Преглед изворни кода

✨ feat(feie-printer-module-mt): 新增多租户飞鹅打印机模块路由

- 新增主路由文件 `feie.mt.routes.ts`,集成所有打印机和打印任务路由
- 新增打印机管理路由【创建、删除、详情、列表、状态、设置默认、更新】
- 新增打印任务管理路由【创建、列表】
- 新增配置工具 `feie-config.util.ts`,支持从数据库动态获取租户配置
- 更新路由索引文件,导出新的多租户路由
- 重构集成测试,使用新的测试数据工厂和路由结构
- 新增越权访问防护测试、边界条件测试和管理员权限测试
- 备份原有测试文件,确保测试覆盖率和数据隔离性
yourname пре 1 месец
родитељ
комит
9873fe8a66

+ 29 - 0
packages/feie-printer-module-mt/src/routes/feie.mt.routes.ts

@@ -0,0 +1,29 @@
+import { OpenAPIHono } from '@hono/zod-openapi';
+import printerListRoute from './printers/list.mt';
+import printerCreateRoute from './printers/create.mt';
+import printerDetailRoute from './printers/detail.mt';
+import printerUpdateRoute from './printers/update.mt';
+import printerDeleteRoute from './printers/delete.mt';
+import printerStatusRoute from './printers/status.mt';
+import printerSetDefaultRoute from './printers/set-default.mt';
+import printTaskCreateRoute from './tasks/create.mt';
+import printTaskListRoute from './tasks/list.mt';
+
+// 飞鹅打印模块主路由 - 多租户版本
+export const FeieMtRoutes = new OpenAPIHono()
+  .route('/printers', printerListRoute)
+  .route('/printers', printerCreateRoute)
+  .route('/printers', printerDetailRoute)
+  .route('/printers', printerUpdateRoute)
+  .route('/printers', printerDeleteRoute)
+  .route('/printers', printerStatusRoute)
+  .route('/printers', printerSetDefaultRoute)
+  .route('/tasks', printTaskCreateRoute)
+  .route('/tasks', printTaskListRoute);
+
+// 导出路由配置,用于集成到主应用
+export const feieMtRoutesExport = {
+  '/api/v1/feie': FeieMtRoutes
+};
+
+export default FeieMtRoutes;

+ 1 - 0
packages/feie-printer-module-mt/src/routes/index.ts

@@ -1,2 +1,3 @@
 export { default as createFeieRoutes } from './feie.routes';
+export { default as FeieMtRoutes, feieMtRoutesExport } from './feie.mt.routes';
 export { default } from './feie.routes';

+ 96 - 0
packages/feie-printer-module-mt/src/routes/printers/create.mt.ts

@@ -0,0 +1,96 @@
+import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
+import { z } from 'zod';
+import { AppDataSource } from '@d8d/shared-utils';
+import { authMiddleware } from '@d8d/auth-module-mt';
+import { AuthContext } from '@d8d/shared-types';
+import { PrinterService } from '../../services/printer.service';
+import { getFeieApiConfig } from '../utils/feie-config.util';
+
+// 打印机创建请求Schema
+const PrinterCreateRequestSchema = z.object({
+  printerSn: z.string().min(1, '打印机SN不能为空'),
+  printerKey: z.string().min(1, '打印机密钥不能为空'),
+  printerName: z.string().optional(),
+  printerType: z.enum(['RECEIPT', 'LABEL']).default('RECEIPT'),
+  isDefault: z.boolean().default(false)
+});
+
+// 打印机创建响应Schema
+const PrinterCreateResponseSchema = z.object({
+  success: z.boolean(),
+  data: z.object({
+    id: z.number(),
+    tenantId: z.number(),
+    printerSn: z.string(),
+    printerName: z.string().nullable(),
+    printerKey: z.string(),
+    printerType: z.enum(['RECEIPT', 'LABEL']),
+    printerStatus: z.enum(['ONLINE', 'OFFLINE', 'ERROR']),
+    isDefault: z.number(),
+    createdAt: z.string(),
+    updatedAt: z.string()
+  })
+});
+
+// 打印机创建路由定义
+const printerCreateRoute = createRoute({
+  method: 'post',
+  path: '/',
+  middleware: [authMiddleware],
+  request: {
+    body: {
+      content: {
+        'application/json': { schema: PrinterCreateRequestSchema }
+      }
+    }
+  },
+  responses: {
+    200: {
+      description: '打印机添加成功',
+      content: { 'application/json': { schema: PrinterCreateResponseSchema } }
+    },
+    400: {
+      description: '参数错误或配置错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    401: {
+      description: '未授权',
+      content: { 'application/json': { schema: z.object({ message: z.string() }) } }
+    },
+    500: {
+      description: '服务器错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    }
+  }
+});
+
+const app = new OpenAPIHono<AuthContext>()
+  .openapi(printerCreateRoute, async (c) => {
+    const user = c.get('user');
+    const tenantId = user?.tenantId || 1;
+
+    try {
+      const body = c.req.valid('json');
+
+      // 获取飞鹅API配置
+      const feieConfig = await getFeieApiConfig(tenantId, AppDataSource);
+      if (!feieConfig) {
+        return c.json({ success: false, message: '飞鹅API配置未找到或配置不完整' }, 400);
+      }
+
+      // 创建带配置的服务实例
+      const printerService = new PrinterService(AppDataSource, feieConfig);
+      const printer = await printerService.addPrinter(tenantId, body);
+
+      return c.json({
+        success: true,
+        data: printer
+      });
+    } catch (error) {
+      console.error(`[租户${tenantId}] 添加打印机失败:`, error);
+      const errorMessage = error instanceof Error ? error.message : '添加打印机失败';
+      return c.json({ success: false, message: errorMessage }, 500);
+    }
+  });
+
+export default app;

+ 80 - 0
packages/feie-printer-module-mt/src/routes/printers/delete.mt.ts

@@ -0,0 +1,80 @@
+import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
+import { z } from 'zod';
+import { AppDataSource } from '@d8d/shared-utils';
+import { authMiddleware } from '@d8d/auth-module-mt';
+import { AuthContext } from '@d8d/shared-types';
+import { PrinterService } from '../../services/printer.service';
+import { getFeieApiConfig } from '../utils/feie-config.util';
+
+// 打印机删除路由参数Schema
+const PrinterDeleteParamsSchema = z.object({
+  printerSn: z.string()
+});
+
+// 打印机删除响应Schema
+const PrinterDeleteResponseSchema = z.object({
+  success: z.boolean(),
+  message: z.string()
+});
+
+// 打印机删除路由定义
+const printerDeleteRoute = createRoute({
+  method: 'delete',
+  path: '/:printerSn',
+  middleware: [authMiddleware],
+  request: {
+    params: PrinterDeleteParamsSchema
+  },
+  responses: {
+    200: {
+      description: '打印机删除成功',
+      content: { 'application/json': { schema: PrinterDeleteResponseSchema } }
+    },
+    400: {
+      description: '配置错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    401: {
+      description: '未授权',
+      content: { 'application/json': { schema: z.object({ message: z.string() }) } }
+    },
+    404: {
+      description: '打印机不存在',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    500: {
+      description: '服务器错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    }
+  }
+});
+
+const app = new OpenAPIHono<AuthContext>()
+  .openapi(printerDeleteRoute, async (c) => {
+    const user = c.get('user');
+    const tenantId = user?.tenantId || 1;
+    const { printerSn } = c.req.valid('param');
+
+    try {
+      // 获取飞鹅API配置
+      const feieConfig = await getFeieApiConfig(tenantId, AppDataSource);
+      if (!feieConfig) {
+        return c.json({ success: false, message: '飞鹅API配置未找到或配置不完整' }, 400);
+      }
+
+      // 创建带配置的服务实例
+      const printerService = new PrinterService(AppDataSource, feieConfig);
+      await printerService.deletePrinter(tenantId, printerSn);
+
+      return c.json({
+        success: true,
+        message: '打印机删除成功'
+      });
+    } catch (error) {
+      console.error(`[租户${tenantId}] 删除打印机失败,打印机SN: ${printerSn}:`, error);
+      const errorMessage = error instanceof Error ? error.message : '删除打印机失败';
+      return c.json({ success: false, message: errorMessage }, 500);
+    }
+  });
+
+export default app;

+ 91 - 0
packages/feie-printer-module-mt/src/routes/printers/detail.mt.ts

@@ -0,0 +1,91 @@
+import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
+import { z } from 'zod';
+import { AppDataSource } from '@d8d/shared-utils';
+import { authMiddleware } from '@d8d/auth-module-mt';
+import { AuthContext } from '@d8d/shared-types';
+import { PrinterService } from '../../services/printer.service';
+import { getFeieApiConfig } from '../utils/feie-config.util';
+
+// 打印机详情路由参数Schema
+const PrinterDetailParamsSchema = z.object({
+  printerSn: z.string()
+});
+
+// 打印机详情响应Schema
+const PrinterDetailResponseSchema = z.object({
+  success: z.boolean(),
+  data: z.object({
+    id: z.number(),
+    tenantId: z.number(),
+    printerSn: z.string(),
+    printerName: z.string().nullable(),
+    printerKey: z.string(),
+    printerType: z.enum(['RECEIPT', 'LABEL']),
+    printerStatus: z.enum(['ONLINE', 'OFFLINE', 'ERROR']),
+    isDefault: z.number(),
+    createdAt: z.string(),
+    updatedAt: z.string()
+  })
+});
+
+// 打印机详情路由定义
+const printerDetailRoute = createRoute({
+  method: 'get',
+  path: '/:printerSn',
+  middleware: [authMiddleware],
+  request: {
+    params: PrinterDetailParamsSchema
+  },
+  responses: {
+    200: {
+      description: '打印机详情获取成功',
+      content: { 'application/json': { schema: PrinterDetailResponseSchema } }
+    },
+    400: {
+      description: '配置错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    401: {
+      description: '未授权',
+      content: { 'application/json': { schema: z.object({ message: z.string() }) } }
+    },
+    404: {
+      description: '打印机不存在',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    500: {
+      description: '服务器错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    }
+  }
+});
+
+const app = new OpenAPIHono<AuthContext>()
+  .openapi(printerDetailRoute, async (c) => {
+    const user = c.get('user');
+    const tenantId = user?.tenantId || 1;
+    const { printerSn } = c.req.valid('param');
+
+    // 获取飞鹅API配置
+    const feieConfig = await getFeieApiConfig(tenantId, AppDataSource);
+    if (!feieConfig) {
+      return c.json({ success: false, message: '飞鹅API配置未找到或配置不完整' }, 400);
+    }
+
+    // 创建带配置的服务实例
+    const printerService = new PrinterService(AppDataSource, feieConfig);
+    const printer = await printerService.repository.findOne({
+      where: { tenantId, printerSn } as any
+    });
+
+    if (!printer) {
+      return c.json({ success: false, message: '打印机不存在' }, 404);
+    }
+
+    return c.json({
+      success: true,
+      data: printer
+    });
+  });
+
+export default app;

+ 134 - 0
packages/feie-printer-module-mt/src/routes/printers/list.mt.ts

@@ -0,0 +1,134 @@
+import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
+import { z } from 'zod';
+import { AppDataSource } from '@d8d/shared-utils';
+import { authMiddleware } from '@d8d/auth-module-mt';
+import { AuthContext } from '@d8d/shared-types';
+import { PrinterService } from '../../services/printer.service';
+import { getFeieApiConfig } from '../utils/feie-config.util';
+
+// 打印机列表查询参数Schema
+const PrinterListQuerySchema = z.object({
+  page: z.string().optional().transform(val => val ? parseInt(val, 10) : 1),
+  pageSize: z.string().optional().transform(val => val ? parseInt(val, 10) : 10),
+  search: z.string().optional(),
+  status: z.enum(['ONLINE', 'OFFLINE', 'ERROR', 'ALL']).optional().default('ALL'),
+  printerType: z.enum(['RECEIPT', 'LABEL', 'ALL']).optional().default('ALL'),
+  isDefault: z.enum(['true', 'false']).optional().transform(val => val === 'true')
+});
+
+// 打印机列表响应Schema
+const PrinterListResponseSchema = z.object({
+  success: z.boolean(),
+  data: z.object({
+    data: z.array(z.object({
+      id: z.number(),
+      tenantId: z.number(),
+      printerSn: z.string(),
+      printerName: z.string().nullable(),
+      printerKey: z.string(),
+      printerType: z.enum(['RECEIPT', 'LABEL']),
+      printerStatus: z.enum(['ONLINE', 'OFFLINE', 'ERROR']),
+      isDefault: z.number(),
+      createdAt: z.string(),
+      updatedAt: z.string()
+    })),
+    total: z.number(),
+    page: z.number(),
+    pageSize: z.number()
+  })
+});
+
+// 打印机列表路由定义
+const printerListRoute = createRoute({
+  method: 'get',
+  path: '/',
+  middleware: [authMiddleware],
+  request: {
+    query: PrinterListQuerySchema
+  },
+  responses: {
+    200: {
+      description: '打印机列表获取成功',
+      content: { 'application/json': { schema: PrinterListResponseSchema } }
+    },
+    400: {
+      description: '配置错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    401: {
+      description: '未授权',
+      content: { 'application/json': { schema: z.object({ message: z.string() }) } }
+    },
+    500: {
+      description: '服务器错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    }
+  }
+});
+
+const app = new OpenAPIHono<AuthContext>()
+  .openapi(printerListRoute, async (c) => {
+    const user = c.get('user');
+    const tenantId = user?.tenantId || 1;
+
+    // 获取查询参数
+    const query = c.req.valid('query');
+    const { page, pageSize, search, status, printerType, isDefault } = query;
+
+    // 获取飞鹅API配置
+    const feieConfig = await getFeieApiConfig(tenantId, AppDataSource);
+    if (!feieConfig) {
+      console.error(`租户 ${tenantId} 的飞鹅API配置未找到或配置不完整`);
+      return c.json({ success: false, message: '飞鹅API配置未找到或配置不完整' }, 400);
+    }
+
+    // 创建带配置的服务实例
+    const printerService = new PrinterService(AppDataSource, feieConfig);
+    const printers = await printerService.getPrinters(tenantId);
+
+    // 应用筛选逻辑
+    let filteredPrinters = printers;
+
+    // 搜索筛选
+    if (search) {
+      filteredPrinters = filteredPrinters.filter(p =>
+        (p.printerName && p.printerName.includes(search)) ||
+        p.printerSn.includes(search)
+      );
+    }
+
+    // 状态筛选
+    if (status && status !== 'ALL') {
+      filteredPrinters = filteredPrinters.filter(p => p.printerStatus === status);
+    }
+
+    // 类型筛选
+    if (printerType && printerType !== 'ALL') {
+      filteredPrinters = filteredPrinters.filter(p => p.printerType === printerType);
+    }
+
+    // 默认打印机筛选
+    if (isDefault) {
+      filteredPrinters = filteredPrinters.filter(p => p.isDefault === 1);
+    }
+
+    // 分页逻辑
+    const total = filteredPrinters.length;
+    const startIndex = (page - 1) * pageSize;
+    const endIndex = Math.min(startIndex + pageSize, total);
+    const paginatedPrinters = filteredPrinters.slice(startIndex, endIndex);
+
+    console.debug(`返回打印机列表,总数: ${total}, 分页: ${page}/${Math.ceil(total/pageSize)}, 数量: ${paginatedPrinters.length}`);
+
+    return c.json({
+      success: true,
+      data: {
+        data: paginatedPrinters,
+        total,
+        page,
+        pageSize
+      }
+    });
+  });
+
+export default app;

+ 91 - 0
packages/feie-printer-module-mt/src/routes/printers/set-default.mt.ts

@@ -0,0 +1,91 @@
+import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
+import { z } from 'zod';
+import { AppDataSource } from '@d8d/shared-utils';
+import { authMiddleware } from '@d8d/auth-module-mt';
+import { AuthContext } from '@d8d/shared-types';
+import { PrinterService } from '../../services/printer.service';
+import { getFeieApiConfig } from '../utils/feie-config.util';
+
+// 设置默认打印机路由参数Schema
+const SetDefaultPrinterParamsSchema = z.object({
+  printerSn: z.string()
+});
+
+// 设置默认打印机响应Schema
+const SetDefaultPrinterResponseSchema = z.object({
+  success: z.boolean(),
+  data: z.object({
+    id: z.number(),
+    tenantId: z.number(),
+    printerSn: z.string(),
+    printerName: z.string().nullable(),
+    printerKey: z.string(),
+    printerType: z.enum(['RECEIPT', 'LABEL']),
+    printerStatus: z.enum(['ONLINE', 'OFFLINE', 'ERROR']),
+    isDefault: z.number(),
+    createdAt: z.string(),
+    updatedAt: z.string()
+  })
+});
+
+// 设置默认打印机路由定义
+const setDefaultPrinterRoute = createRoute({
+  method: 'post',
+  path: '/:printerSn/set-default',
+  middleware: [authMiddleware],
+  request: {
+    params: SetDefaultPrinterParamsSchema
+  },
+  responses: {
+    200: {
+      description: '设置默认打印机成功',
+      content: { 'application/json': { schema: SetDefaultPrinterResponseSchema } }
+    },
+    400: {
+      description: '配置错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    401: {
+      description: '未授权',
+      content: { 'application/json': { schema: z.object({ message: z.string() }) } }
+    },
+    404: {
+      description: '打印机不存在',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    500: {
+      description: '服务器错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    }
+  }
+});
+
+const app = new OpenAPIHono<AuthContext>()
+  .openapi(setDefaultPrinterRoute, async (c) => {
+    const user = c.get('user');
+    const tenantId = user?.tenantId || 1;
+    const { printerSn } = c.req.valid('param');
+
+    try {
+      // 获取飞鹅API配置
+      const feieConfig = await getFeieApiConfig(tenantId, AppDataSource);
+      if (!feieConfig) {
+        return c.json({ success: false, message: '飞鹅API配置未找到或配置不完整' }, 400);
+      }
+
+      // 创建带配置的服务实例
+      const printerService = new PrinterService(AppDataSource, feieConfig);
+      const printer = await printerService.setDefaultPrinter(tenantId, printerSn);
+
+      return c.json({
+        success: true,
+        data: printer
+      });
+    } catch (error) {
+      console.error(`[租户${tenantId}] 设置默认打印机失败,打印机SN: ${printerSn}:`, error);
+      const errorMessage = error instanceof Error ? error.message : '设置默认打印机失败';
+      return c.json({ success: false, message: errorMessage }, 500);
+    }
+  });
+
+export default app;

+ 89 - 0
packages/feie-printer-module-mt/src/routes/printers/status.mt.ts

@@ -0,0 +1,89 @@
+import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
+import { z } from 'zod';
+import { AppDataSource } from '@d8d/shared-utils';
+import { authMiddleware } from '@d8d/auth-module-mt';
+import { AuthContext } from '@d8d/shared-types';
+import { PrinterService } from '../../services/printer.service';
+import { getFeieApiConfig } from '../utils/feie-config.util';
+
+// 打印机状态查询路由参数Schema
+const PrinterStatusParamsSchema = z.object({
+  printerSn: z.string()
+});
+
+// 打印机状态响应Schema
+const PrinterStatusResponseSchema = z.object({
+  success: z.boolean(),
+  data: z.object({
+    printerSn: z.string(),
+    printerName: z.string().nullable(),
+    printerStatus: z.enum(['ONLINE', 'OFFLINE', 'ERROR']),
+    paperStatus: z.enum(['NORMAL', 'LOW', 'EMPTY']).optional(),
+    temperature: z.number().optional(),
+    printCount: z.number().optional(),
+    lastPrintTime: z.string().optional(),
+    lastCheckTime: z.string()
+  })
+});
+
+// 打印机状态查询路由定义
+const printerStatusRoute = createRoute({
+  method: 'get',
+  path: '/:printerSn/status',
+  middleware: [authMiddleware],
+  request: {
+    params: PrinterStatusParamsSchema
+  },
+  responses: {
+    200: {
+      description: '打印机状态获取成功',
+      content: { 'application/json': { schema: PrinterStatusResponseSchema } }
+    },
+    400: {
+      description: '配置错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    401: {
+      description: '未授权',
+      content: { 'application/json': { schema: z.object({ message: z.string() }) } }
+    },
+    404: {
+      description: '打印机不存在',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    500: {
+      description: '服务器错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    }
+  }
+});
+
+const app = new OpenAPIHono<AuthContext>()
+  .openapi(printerStatusRoute, async (c) => {
+    const user = c.get('user');
+    const tenantId = user?.tenantId || 1;
+    const { printerSn } = c.req.valid('param');
+
+    try {
+      // 获取飞鹅API配置
+      const feieConfig = await getFeieApiConfig(tenantId, AppDataSource);
+      if (!feieConfig) {
+        return c.json({ success: false, message: '飞鹅API配置未找到或配置不完整' }, 400);
+      }
+
+      // 创建带配置的服务实例
+      const printerService = new PrinterService(AppDataSource, feieConfig);
+      const status = await printerService.getPrinterStatus(tenantId, printerSn);
+
+      return c.json({
+        success: true,
+        data: status
+      });
+    } catch (error) {
+      console.error(`[租户${tenantId}] 查询打印机状态失败,打印机SN: ${printerSn}:`, error);
+      const errorMessage = error instanceof Error ? error.message : '查询打印机状态失败';
+      return c.json({ success: false, message: errorMessage }, 500);
+    }
+  });
+
+export default app;

+ 106 - 0
packages/feie-printer-module-mt/src/routes/printers/update.mt.ts

@@ -0,0 +1,106 @@
+import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
+import { z } from 'zod';
+import { AppDataSource } from '@d8d/shared-utils';
+import { authMiddleware } from '@d8d/auth-module-mt';
+import { AuthContext } from '@d8d/shared-types';
+import { PrinterService } from '../../services/printer.service';
+import { getFeieApiConfig } from '../utils/feie-config.util';
+
+// 打印机更新请求Schema
+const PrinterUpdateRequestSchema = z.object({
+  printerName: z.string().optional(),
+  printerKey: z.string().optional(),
+  printerType: z.enum(['RECEIPT', 'LABEL']).optional(),
+  isDefault: z.boolean().optional()
+});
+
+// 打印机更新路由参数Schema
+const PrinterUpdateParamsSchema = z.object({
+  printerSn: z.string()
+});
+
+// 打印机更新响应Schema
+const PrinterUpdateResponseSchema = z.object({
+  success: z.boolean(),
+  data: z.object({
+    id: z.number(),
+    tenantId: z.number(),
+    printerSn: z.string(),
+    printerName: z.string().nullable(),
+    printerKey: z.string(),
+    printerType: z.enum(['RECEIPT', 'LABEL']),
+    printerStatus: z.enum(['ONLINE', 'OFFLINE', 'ERROR']),
+    isDefault: z.number(),
+    createdAt: z.string(),
+    updatedAt: z.string()
+  })
+});
+
+// 打印机更新路由定义
+const printerUpdateRoute = createRoute({
+  method: 'put',
+  path: '/:printerSn',
+  middleware: [authMiddleware],
+  request: {
+    params: PrinterUpdateParamsSchema,
+    body: {
+      content: {
+        'application/json': { schema: PrinterUpdateRequestSchema }
+      }
+    }
+  },
+  responses: {
+    200: {
+      description: '打印机更新成功',
+      content: { 'application/json': { schema: PrinterUpdateResponseSchema } }
+    },
+    400: {
+      description: '参数错误或配置错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    401: {
+      description: '未授权',
+      content: { 'application/json': { schema: z.object({ message: z.string() }) } }
+    },
+    404: {
+      description: '打印机不存在',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    500: {
+      description: '服务器错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    }
+  }
+});
+
+const app = new OpenAPIHono<AuthContext>()
+  .openapi(printerUpdateRoute, async (c) => {
+    const user = c.get('user');
+    const tenantId = user?.tenantId || 1;
+    const { printerSn } = c.req.valid('param');
+
+    try {
+      const body = c.req.valid('json');
+
+      // 获取飞鹅API配置
+      const feieConfig = await getFeieApiConfig(tenantId, AppDataSource);
+      if (!feieConfig) {
+        return c.json({ success: false, message: '飞鹅API配置未找到或配置不完整' }, 400);
+      }
+
+      // 创建带配置的服务实例
+      const printerService = new PrinterService(AppDataSource, feieConfig);
+      const printer = await printerService.updatePrinter(tenantId, printerSn, body);
+
+      return c.json({
+        success: true,
+        data: printer
+      });
+    } catch (error) {
+      console.error(`[租户${tenantId}] 更新打印机失败,打印机SN: ${printerSn}:`, error);
+      const errorMessage = error instanceof Error ? error.message : '更新打印机失败';
+      return c.json({ success: false, message: errorMessage }, 500);
+    }
+  });
+
+export default app;

+ 99 - 0
packages/feie-printer-module-mt/src/routes/tasks/create.mt.ts

@@ -0,0 +1,99 @@
+import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
+import { z } from 'zod';
+import { AppDataSource } from '@d8d/shared-utils';
+import { authMiddleware } from '@d8d/auth-module-mt';
+import { AuthContext } from '@d8d/shared-types';
+import { PrintTaskService } from '../../services/print-task.service';
+import { getFeieApiConfig } from '../utils/feie-config.util';
+
+// 打印任务创建请求Schema
+const PrintTaskCreateRequestSchema = z.object({
+  printerSn: z.string().min(1, '打印机SN不能为空'),
+  orderId: z.number().optional(),
+  printType: z.enum(['RECEIPT', 'LABEL']).default('RECEIPT'),
+  content: z.string().min(1, '打印内容不能为空'),
+  copies: z.number().min(1).max(10).default(1),
+  priority: z.enum(['HIGH', 'NORMAL', 'LOW']).default('NORMAL')
+});
+
+// 打印任务创建响应Schema
+const PrintTaskCreateResponseSchema = z.object({
+  success: z.boolean(),
+  data: z.object({
+    taskId: z.string(),
+    tenantId: z.number(),
+    printerSn: z.string(),
+    orderId: z.number().nullable(),
+    printType: z.enum(['RECEIPT', 'LABEL']),
+    content: z.string(),
+    copies: z.number(),
+    priority: z.enum(['HIGH', 'NORMAL', 'LOW']),
+    printStatus: z.enum(['PENDING', 'PROCESSING', 'SUCCESS', 'FAILED', 'CANCELLED']),
+    errorMessage: z.string().nullable(),
+    createdAt: z.string(),
+    updatedAt: z.string()
+  })
+});
+
+// 打印任务创建路由定义
+const printTaskCreateRoute = createRoute({
+  method: 'post',
+  path: '/',
+  middleware: [authMiddleware],
+  request: {
+    body: {
+      content: {
+        'application/json': { schema: PrintTaskCreateRequestSchema }
+      }
+    }
+  },
+  responses: {
+    200: {
+      description: '打印任务创建成功',
+      content: { 'application/json': { schema: PrintTaskCreateResponseSchema } }
+    },
+    400: {
+      description: '参数错误或配置错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    401: {
+      description: '未授权',
+      content: { 'application/json': { schema: z.object({ message: z.string() }) } }
+    },
+    500: {
+      description: '服务器错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    }
+  }
+});
+
+const app = new OpenAPIHono<AuthContext>()
+  .openapi(printTaskCreateRoute, async (c) => {
+    const user = c.get('user');
+    const tenantId = user?.tenantId || 1;
+
+    try {
+      const body = c.req.valid('json');
+
+      // 获取飞鹅API配置
+      const feieConfig = await getFeieApiConfig(tenantId, AppDataSource);
+      if (!feieConfig) {
+        return c.json({ success: false, message: '飞鹅API配置未找到或配置不完整' }, 400);
+      }
+
+      // 创建带配置的打印任务服务实例
+      const printTaskService = new PrintTaskService(AppDataSource, feieConfig);
+      const task = await printTaskService.createPrintTask(tenantId, body);
+
+      return c.json({
+        success: true,
+        data: task
+      });
+    } catch (error) {
+      console.error(`[租户${tenantId}] 创建打印任务失败:`, error);
+      const errorMessage = error instanceof Error ? error.message : '创建打印任务失败';
+      return c.json({ success: false, message: errorMessage }, 500);
+    }
+  });
+
+export default app;

+ 119 - 0
packages/feie-printer-module-mt/src/routes/tasks/list.mt.ts

@@ -0,0 +1,119 @@
+import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
+import { z } from 'zod';
+import { AppDataSource } from '@d8d/shared-utils';
+import { authMiddleware } from '@d8d/auth-module-mt';
+import { AuthContext } from '@d8d/shared-types';
+import { PrintTaskService } from '../../services/print-task.service';
+import { getFeieApiConfig } from '../utils/feie-config.util';
+
+// 打印任务列表查询参数Schema
+const PrintTaskListQuerySchema = z.object({
+  page: z.string().optional().transform(val => val ? parseInt(val, 10) : 1),
+  pageSize: z.string().optional().transform(val => val ? parseInt(val, 10) : 20),
+  orderId: z.string().optional().transform(val => val ? parseInt(val, 10) : undefined),
+  printerSn: z.string().optional(),
+  printType: z.enum(['RECEIPT', 'LABEL', 'ALL']).optional().default('ALL'),
+  status: z.enum(['PENDING', 'PROCESSING', 'SUCCESS', 'FAILED', 'CANCELLED', 'ALL']).optional().default('ALL'),
+  startDate: z.string().optional().transform(val => val ? new Date(val) : undefined),
+  endDate: z.string().optional().transform(val => val ? new Date(val) : undefined),
+  search: z.string().optional()
+});
+
+// 打印任务列表响应Schema
+const PrintTaskListResponseSchema = z.object({
+  success: z.boolean(),
+  data: z.object({
+    data: z.array(z.object({
+      taskId: z.string(),
+      tenantId: z.number(),
+      printerSn: z.string(),
+      orderId: z.number().nullable(),
+      printType: z.enum(['RECEIPT', 'LABEL']),
+      content: z.string(),
+      copies: z.number(),
+      priority: z.enum(['HIGH', 'NORMAL', 'LOW']),
+      printStatus: z.enum(['PENDING', 'PROCESSING', 'SUCCESS', 'FAILED', 'CANCELLED']),
+      errorMessage: z.string().nullable(),
+      createdAt: z.string(),
+      updatedAt: z.string()
+    })),
+    total: z.number(),
+    page: z.number(),
+    pageSize: z.number()
+  })
+});
+
+// 打印任务列表路由定义
+const printTaskListRoute = createRoute({
+  method: 'get',
+  path: '/',
+  middleware: [authMiddleware],
+  request: {
+    query: PrintTaskListQuerySchema
+  },
+  responses: {
+    200: {
+      description: '打印任务列表获取成功',
+      content: { 'application/json': { schema: PrintTaskListResponseSchema } }
+    },
+    400: {
+      description: '配置错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    },
+    401: {
+      description: '未授权',
+      content: { 'application/json': { schema: z.object({ message: z.string() }) } }
+    },
+    500: {
+      description: '服务器错误',
+      content: { 'application/json': { schema: z.object({ success: z.boolean(), message: z.string() }) } }
+    }
+  }
+});
+
+const app = new OpenAPIHono<AuthContext>()
+  .openapi(printTaskListRoute, async (c) => {
+    const user = c.get('user');
+    const tenantId = user?.tenantId || 1;
+
+    try {
+      const query = c.req.valid('query');
+      const filters = {
+        orderId: query.orderId,
+        printerSn: query.printerSn,
+        printType: query.printType !== 'ALL' ? query.printType : undefined,
+        printStatus: query.status !== 'ALL' ? query.status : undefined,
+        startDate: query.startDate,
+        endDate: query.endDate,
+        search: query.search
+      };
+      const page = query.page;
+      const limit = query.pageSize;
+
+      // 获取飞鹅API配置
+      const feieConfig = await getFeieApiConfig(tenantId, AppDataSource);
+      if (!feieConfig) {
+        return c.json({ success: false, message: '飞鹅API配置未找到或配置不完整' }, 400);
+      }
+
+      // 创建带配置的打印任务服务实例
+      const printTaskService = new PrintTaskService(AppDataSource, feieConfig);
+      const result = await printTaskService.getPrintTasks(tenantId, filters, page, limit);
+
+      return c.json({
+        success: true,
+        data: {
+          data: result.tasks,
+          total: result.total,
+          page,
+          pageSize: limit
+        }
+      });
+    } catch (error) {
+      console.error(`[租户${tenantId}] 获取打印任务列表失败:`, error);
+      const errorMessage = error instanceof Error ? error.message : '获取打印任务列表失败';
+      return c.json({ success: false, message: errorMessage }, 500);
+    }
+  });
+
+export default app;

+ 65 - 0
packages/feie-printer-module-mt/src/routes/utils/feie-config.util.ts

@@ -0,0 +1,65 @@
+import { DataSource, In } from 'typeorm';
+import { FeieApiConfig } from '../../types/feie.types';
+
+/**
+ * 获取飞鹅API配置
+ */
+export async function getFeieApiConfig(tenantId: number, dataSource: DataSource): Promise<FeieApiConfig | null> {
+  try {
+    console.debug(`开始获取租户 ${tenantId} 的飞鹅API配置`);
+
+    // 从 system_config_mt 表获取飞鹅API配置
+    const configKeys = [
+      'feie.api.user',      // 飞鹅API用户
+      'feie.api.ukey',      // 飞鹅API密钥
+      'feie.api.base_url',  // 飞鹅API基础URL
+      'feie.api.timeout',   // API超时时间
+      'feie.api.max_retries' // 最大重试次数
+    ];
+
+    // 直接查询数据库
+    const configRepository = dataSource.getRepository('system_config_mt');
+    console.debug(`查询数据库,租户ID: ${tenantId}, 配置键: ${configKeys.join(', ')}`);
+
+    const configs = await configRepository.find({
+      where: {
+        tenantId,
+        configKey: In(configKeys)
+      }
+    });
+
+    console.debug(`找到 ${configs.length} 条配置记录`);
+
+    // 转换为键值对
+    const configMap: Record<string, string> = {};
+    configs.forEach((config: any) => {
+      configMap[config.configKey] = config.configValue;
+      console.debug(`配置键: ${config.configKey}, 值: ${config.configValue}`);
+    });
+
+    // 检查必要的配置项
+    const user = configMap['feie.api.user'];
+    const ukey = configMap['feie.api.ukey'];
+
+    if (!user || !ukey) {
+      console.warn(`[租户${tenantId}] 飞鹅API配置不完整,缺少user或ukey`);
+      console.debug(`当前配置映射:`, JSON.stringify(configMap, null, 2));
+      return null;
+    }
+
+    // 返回配置结构
+    const feieConfig = {
+      user,
+      ukey,
+      baseUrl: configMap['feie.api.base_url'] || 'https://api.feieyun.cn/Api/Open/',
+      timeout: parseInt(configMap['feie.api.timeout'] || '10000', 10),
+      maxRetries: parseInt(configMap['feie.api.max_retries'] || '3', 10)
+    };
+
+    console.debug(`租户 ${tenantId} 的飞鹅API配置获取成功:`, JSON.stringify(feieConfig, null, 2));
+    return feieConfig;
+  } catch (error) {
+    console.warn(`[租户${tenantId}] 获取飞鹅API配置失败:`, error);
+    return null;
+  }
+}

+ 198 - 34
packages/feie-printer-module-mt/tests/integration/feie-api.integration.test.ts

@@ -1,12 +1,11 @@
 import { describe, it, expect, beforeEach } from 'vitest';
 import { testClient } from 'hono/testing';
 import { IntegrationTestDatabase, setupIntegrationDatabaseHooksWithEntities } from '@d8d/shared-test-util';
-import { JWTUtil } from '@d8d/shared-utils';
 import { UserEntityMt, RoleMt } from '@d8d/user-module-mt';
 import { FileMt } from '@d8d/file-module-mt';
-import createFeieRoutes from '../../src/routes/feie.routes';
+import { FeieMtRoutes } from '../../src/routes';
 import { FeiePrinterMt, FeiePrintTaskMt, FeieConfigMt } from '../../src/entities';
-import { FeieTestFactory } from '../factories/feie-test-factory';
+import { FeieTestDataFactory } from '../utils/test-data-factory';
 
 // 设置集成测试钩子
 setupIntegrationDatabaseHooksWithEntities([
@@ -14,9 +13,9 @@ setupIntegrationDatabaseHooksWithEntities([
 ])
 
 describe('飞鹅打印多租户API集成测试', () => {
-  let client: ReturnType<typeof testClient<ReturnType<typeof createFeieRoutes>>>;
-  let testFactory: FeieTestFactory;
+  let client: ReturnType<typeof testClient<typeof FeieMtRoutes>>;
   let userToken: string;
+  let adminToken: string;
   let otherUserToken: string;
   let otherTenantUserToken: string;
   let testUser: UserEntityMt;
@@ -28,33 +27,33 @@ describe('飞鹅打印多租户API集成测试', () => {
     const dataSource = await IntegrationTestDatabase.getDataSource();
 
     // 创建测试客户端
-    client = testClient(createFeieRoutes(dataSource));
-
-    // 创建测试工厂
-    testFactory = new FeieTestFactory(dataSource);
+    client = testClient(FeieMtRoutes);
 
     // 创建测试用户
-    testUser = await testFactory.createTestUser(1);
-    otherUser = await testFactory.createTestUser(1);
-    otherTenantUser = await testFactory.createTestUser(2);
+    testUser = await FeieTestDataFactory.createTestUser(dataSource, 1);
+    otherUser = await FeieTestDataFactory.createTestUser(dataSource, 1);
+    otherTenantUser = await FeieTestDataFactory.createTestUser(dataSource, 2);
 
     // 生成JWT令牌
-    userToken = JWTUtil.generateToken({ id: testUser.id, username: testUser.username, tenantId: 1 });
-    otherUserToken = JWTUtil.generateToken({ id: otherUser.id, username: otherUser.username, tenantId: 1 });
-    otherTenantUserToken = JWTUtil.generateToken({ id: otherTenantUser.id, username: otherTenantUser.username, tenantId: 2 });
+    userToken = FeieTestDataFactory.generateUserToken(testUser);
+    adminToken = FeieTestDataFactory.generateAdminToken(1);
+    otherUserToken = FeieTestDataFactory.generateUserToken(otherUser);
+    otherTenantUserToken = FeieTestDataFactory.generateUserToken(otherTenantUser);
 
     // 创建飞鹅API配置
-    await testFactory.createFullFeieConfig(1);
-    await testFactory.createFullFeieConfig(2);
+    await FeieTestDataFactory.createFullFeieConfig(dataSource, 1);
+    await FeieTestDataFactory.createFullFeieConfig(dataSource, 2);
   });
 
   describe('租户数据隔离验证', () => {
     it('应该只能访问自己租户的打印机', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
       // 创建租户1的打印机
-      const tenant1Printer = await testFactory.createTestPrinter(1);
+      const tenant1Printer = await FeieTestDataFactory.createTestPrinter(dataSource, 1);
 
       // 创建租户2的打印机
-      const tenant2Printer = await testFactory.createTestPrinter(2);
+      const tenant2Printer = await FeieTestDataFactory.createTestPrinter(dataSource, 2);
 
       // 使用租户1的用户查询打印机列表
       const response = await client.printers.$get({
@@ -78,8 +77,10 @@ describe('飞鹅打印多租户API集成测试', () => {
     });
 
     it('不应该访问其他租户的打印机详情', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
       // 创建租户2的打印机
-      const otherTenantPrinter = await testFactory.createTestPrinter(2);
+      const otherTenantPrinter = await FeieTestDataFactory.createTestPrinter(dataSource, 2);
 
       // 使用租户1的用户尝试访问租户2的打印机
       const response = await client['printers/:printerSn'].$get({
@@ -95,8 +96,10 @@ describe('飞鹅打印多租户API集成测试', () => {
     });
 
     it('应该正确过滤跨租户打印机访问', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
       // 创建租户1的打印机
-      const tenant1Printer = await testFactory.createTestPrinter(1);
+      const tenant1Printer = await FeieTestDataFactory.createTestPrinter(dataSource, 1);
 
       // 使用租户2的用户尝试访问租户1的打印机
       const response = await client['printers/:printerSn'].$get({
@@ -114,9 +117,11 @@ describe('飞鹅打印多租户API集成测试', () => {
 
   describe('打印机管理功能验证', () => {
     it('应该能够查询打印机列表', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
       // 创建测试打印机
-      const printer1 = await testFactory.createTestPrinter(1, { printerName: '打印机1' });
-      const printer2 = await testFactory.createTestPrinter(1, { printerName: '打印机2' });
+      const printer1 = await FeieTestDataFactory.createTestPrinter(dataSource, 1, { printerName: '打印机1' });
+      const printer2 = await FeieTestDataFactory.createTestPrinter(dataSource, 1, { printerName: '打印机2' });
 
       // 查询打印机列表
       const response = await client.printers.$get({
@@ -138,9 +143,11 @@ describe('飞鹅打印多租户API集成测试', () => {
     });
 
     it('应该能够根据名称搜索打印机', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
       // 创建测试打印机
-      const printer1 = await testFactory.createTestPrinter(1, { printerName: '测试打印机A' });
-      const printer2 = await testFactory.createTestPrinter(1, { printerName: '其他打印机' });
+      const printer1 = await FeieTestDataFactory.createTestPrinter(dataSource, 1, { printerName: '测试打印机A' });
+      const printer2 = await FeieTestDataFactory.createTestPrinter(dataSource, 1, { printerName: '其他打印机' });
 
       // 搜索打印机
       const response = await client.printers.$get({
@@ -162,9 +169,11 @@ describe('飞鹅打印多租户API集成测试', () => {
     });
 
     it('应该能够设置默认打印机', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
       // 创建两个打印机
-      const printer1 = await testFactory.createTestPrinter(1, { printerName: '打印机1', isDefault: 1 });
-      const printer2 = await testFactory.createTestPrinter(1, { printerName: '打印机2', isDefault: 0 });
+      const printer1 = await FeieTestDataFactory.createTestPrinter(dataSource, 1, { printerName: '打印机1', isDefault: 1 });
+      const printer2 = await FeieTestDataFactory.createTestPrinter(dataSource, 1, { printerName: '打印机2', isDefault: 0 });
 
       // 设置打印机2为默认
       const response = await client['printers/:printerSn/set-default'].$post({
@@ -184,7 +193,6 @@ describe('飞鹅打印多租户API集成测试', () => {
       }
 
       // 验证打印机1不再是默认
-      const dataSource = await IntegrationTestDatabase.getDataSource();
       const updatedPrinter1 = await dataSource.getRepository(FeiePrinterMt).findOne({
         where: { tenantId: 1, printerSn: printer1.printerSn }
       });
@@ -196,8 +204,9 @@ describe('飞鹅打印多租户API集成测试', () => {
     let testPrinter: FeiePrinterMt;
 
     beforeEach(async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
       // 创建测试打印机
-      testPrinter = await testFactory.createTestPrinter(1);
+      testPrinter = await FeieTestDataFactory.createTestPrinter(dataSource, 1);
     });
 
     it.skip('应该能够创建打印任务 - 需要实际飞鹅API连接', async () => {
@@ -233,9 +242,11 @@ describe('飞鹅打印多租户API集成测试', () => {
     });
 
     it('应该能够查询打印任务列表', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
       // 创建测试打印任务
-      const task1 = await testFactory.createTestPrintTask(1, testPrinter.printerSn);
-      const task2 = await testFactory.createTestPrintTask(1, testPrinter.printerSn);
+      const task1 = await FeieTestDataFactory.createTestPrintTask(dataSource, 1, testPrinter.printerSn);
+      const task2 = await FeieTestDataFactory.createTestPrintTask(dataSource, 1, testPrinter.printerSn);
 
       // 查询打印任务列表
       const response = await client.tasks.$get({
@@ -257,12 +268,14 @@ describe('飞鹅打印多租户API集成测试', () => {
     });
 
     it('应该能够根据打印机筛选打印任务', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
       // 创建另一个打印机
-      const otherPrinter = await testFactory.createTestPrinter(1);
+      const otherPrinter = await FeieTestDataFactory.createTestPrinter(dataSource, 1);
 
       // 创建测试打印任务
-      const task1 = await testFactory.createTestPrintTask(1, testPrinter.printerSn);
-      const task2 = await testFactory.createTestPrintTask(1, otherPrinter.printerSn);
+      const task1 = await FeieTestDataFactory.createTestPrintTask(dataSource, 1, testPrinter.printerSn);
+      const task2 = await FeieTestDataFactory.createTestPrintTask(dataSource, 1, otherPrinter.printerSn);
 
       // 根据打印机筛选
       const response = await client.tasks.$get({
@@ -497,4 +510,155 @@ describe('飞鹅打印多租户API集成测试', () => {
       }
     });
   });
+
+  // 新增:越权访问防护测试
+  describe('越权访问防护验证', () => {
+    it('应该拒绝访问其他用户的打印机详情', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
+      // 为otherUser创建打印机
+      const otherUserPrinter = await FeieTestDataFactory.createTestPrinter(dataSource, 1);
+
+      // testUser尝试访问otherUser的打印机
+      const response = await client['printers/:printerSn'].$get({
+        param: { printerSn: otherUserPrinter.printerSn }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}` // testUser的token
+        }
+      });
+
+      // 应该返回404,因为打印机查询包含租户ID过滤
+      expect(response.status).toBe(404);
+    });
+
+    it('应该拒绝跨租户访问打印机详情', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
+      // 为otherTenantUser创建打印机(租户2)
+      const otherTenantPrinter = await FeieTestDataFactory.createTestPrinter(dataSource, 2);
+
+      // testUser(租户1)尝试访问otherTenantUser(租户2)的打印机
+      const response = await client['printers/:printerSn'].$get({
+        param: { printerSn: otherTenantPrinter.printerSn }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}` // 租户1的用户
+        }
+      });
+
+      // 应该返回404,因为租户ID不匹配
+      expect(response.status).toBe(404);
+    });
+  });
+
+  // 新增:边界条件测试
+  describe('边界条件测试', () => {
+    it('应该处理打印机名称为空的情况', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
+      // 创建打印机名称为空的打印机
+      const printer = await FeieTestDataFactory.createTestPrinter(dataSource, 1, { printerName: '' });
+
+      // 查询打印机列表
+      const response = await client.printers.$get({
+        query: {}
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+        expect(data.success).toBe(true);
+        // 应该能正常返回,即使打印机名称为空
+        expect(data.data.data).toHaveLength(1);
+      }
+    });
+
+    it('应该处理打印机状态无效的情况', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
+      // 创建状态为无效的打印机
+      const printer = await FeieTestDataFactory.createTestPrinter(dataSource, 1, { printerStatus: 'INVALID_STATUS' });
+
+      // 查询打印机列表
+      const response = await client.printers.$get({
+        query: {}
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+        expect(data.success).toBe(true);
+        // 应该能正常返回,即使状态无效
+        expect(data.data.data).toHaveLength(1);
+        expect(data.data.data[0].printerStatus).toBe('INVALID_STATUS');
+      }
+    });
+  });
+
+  // 新增:管理员权限测试
+  describe('管理员权限验证', () => {
+    it('管理员应该能够访问所有打印机', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
+      // 创建多个打印机
+      const printer1 = await FeieTestDataFactory.createTestPrinter(dataSource, 1, { printerName: '管理员打印机1' });
+      const printer2 = await FeieTestDataFactory.createTestPrinter(dataSource, 1, { printerName: '管理员打印机2' });
+
+      // 管理员查询打印机列表
+      const response = await client.printers.$get({
+        query: {}
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+        expect(data.success).toBe(true);
+        // 管理员应该能看到所有打印机
+        expect(data.data.data).toHaveLength(2);
+      }
+    });
+
+    it('管理员应该能够更新打印机配置', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+
+      // 创建打印机
+      const printer = await FeieTestDataFactory.createTestPrinter(dataSource, 1);
+
+      // 管理员更新打印机
+      const updateData = {
+        printerName: '管理员更新后的打印机',
+        printerType: '80mm'
+      };
+
+      const response = await client['printers/:printerSn'].$put({
+        param: { printerSn: printer.printerSn },
+        json: updateData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+        expect(data.success).toBe(true);
+        expect(data.data.printerName).toBe('管理员更新后的打印机');
+        expect(data.data.printerType).toBe('80mm');
+      }
+    });
+  });
 });

+ 500 - 0
packages/feie-printer-module-mt/tests/integration/feie-api.integration.test.ts.backup

@@ -0,0 +1,500 @@
+import { describe, it, expect, beforeEach } from 'vitest';
+import { testClient } from 'hono/testing';
+import { IntegrationTestDatabase, setupIntegrationDatabaseHooksWithEntities } from '@d8d/shared-test-util';
+import { JWTUtil } from '@d8d/shared-utils';
+import { UserEntityMt, RoleMt } from '@d8d/user-module-mt';
+import { FileMt } from '@d8d/file-module-mt';
+import { createFeieMtRoutes } from '../../src/routes/feie.mt.routes';
+import { FeiePrinterMt, FeiePrintTaskMt, FeieConfigMt } from '../../src/entities';
+import { FeieTestFactory } from '../factories/feie-test-factory';
+
+// 设置集成测试钩子
+setupIntegrationDatabaseHooksWithEntities([
+  UserEntityMt, RoleMt, FileMt, FeiePrinterMt, FeiePrintTaskMt, FeieConfigMt
+])
+
+describe('飞鹅打印多租户API集成测试', () => {
+  let client: ReturnType<typeof testClient<ReturnType<typeof createFeieMtRoutes>>>;
+  let testFactory: FeieTestFactory;
+  let userToken: string;
+  let otherUserToken: string;
+  let otherTenantUserToken: string;
+  let testUser: UserEntityMt;
+  let otherUser: UserEntityMt;
+  let otherTenantUser: UserEntityMt;
+
+  beforeEach(async () => {
+    // 获取数据源
+    const dataSource = await IntegrationTestDatabase.getDataSource();
+
+    // 创建测试客户端
+    client = testClient(createFeieMtRoutes(dataSource));
+
+    // 创建测试工厂
+    testFactory = new FeieTestFactory(dataSource);
+
+    // 创建测试用户
+    testUser = await testFactory.createTestUser(1);
+    otherUser = await testFactory.createTestUser(1);
+    otherTenantUser = await testFactory.createTestUser(2);
+
+    // 生成JWT令牌
+    userToken = JWTUtil.generateToken({ id: testUser.id, username: testUser.username, tenantId: 1 });
+    otherUserToken = JWTUtil.generateToken({ id: otherUser.id, username: otherUser.username, tenantId: 1 });
+    otherTenantUserToken = JWTUtil.generateToken({ id: otherTenantUser.id, username: otherTenantUser.username, tenantId: 2 });
+
+    // 创建飞鹅API配置
+    await testFactory.createFullFeieConfig(1);
+    await testFactory.createFullFeieConfig(2);
+  });
+
+  describe('租户数据隔离验证', () => {
+    it('应该只能访问自己租户的打印机', async () => {
+      // 创建租户1的打印机
+      const tenant1Printer = await testFactory.createTestPrinter(1);
+
+      // 创建租户2的打印机
+      const tenant2Printer = await testFactory.createTestPrinter(2);
+
+      // 使用租户1的用户查询打印机列表
+      const response = await client.printers.$get({
+        query: {}
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+
+        // 应该只返回租户1的打印机
+        expect(data.success).toBe(true);
+        expect(data.data.data).toHaveLength(1);
+        expect(data.data.data[0].tenantId).toBe(1);
+        expect(data.data.data[0].printerSn).toBe(tenant1Printer.printerSn);
+      }
+    });
+
+    it('不应该访问其他租户的打印机详情', async () => {
+      // 创建租户2的打印机
+      const otherTenantPrinter = await testFactory.createTestPrinter(2);
+
+      // 使用租户1的用户尝试访问租户2的打印机
+      const response = await client['printers/:printerSn'].$get({
+        param: { printerSn: otherTenantPrinter.printerSn }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      // 应该返回404,因为打印机不在当前租户
+      expect(response.status).toBe(404);
+    });
+
+    it('应该正确过滤跨租户打印机访问', async () => {
+      // 创建租户1的打印机
+      const tenant1Printer = await testFactory.createTestPrinter(1);
+
+      // 使用租户2的用户尝试访问租户1的打印机
+      const response = await client['printers/:printerSn'].$get({
+        param: { printerSn: tenant1Printer.printerSn }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${otherTenantUserToken}`
+        }
+      });
+
+      // 应该返回404,因为打印机不在当前租户
+      expect(response.status).toBe(404);
+    });
+  });
+
+  describe('打印机管理功能验证', () => {
+    it('应该能够查询打印机列表', async () => {
+      // 创建测试打印机
+      const printer1 = await testFactory.createTestPrinter(1, { printerName: '打印机1' });
+      const printer2 = await testFactory.createTestPrinter(1, { printerName: '打印机2' });
+
+      // 查询打印机列表
+      const response = await client.printers.$get({
+        query: {}
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+
+        expect(data.success).toBe(true);
+        expect(data.data.data).toHaveLength(2);
+        expect(data.data.total).toBe(2);
+      }
+    });
+
+    it('应该能够根据名称搜索打印机', async () => {
+      // 创建测试打印机
+      const printer1 = await testFactory.createTestPrinter(1, { printerName: '测试打印机A' });
+      const printer2 = await testFactory.createTestPrinter(1, { printerName: '其他打印机' });
+
+      // 搜索打印机
+      const response = await client.printers.$get({
+        query: { search: '测试' }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+
+        expect(data.success).toBe(true);
+        expect(data.data.data).toHaveLength(1);
+        expect(data.data.data[0].printerName).toBe('测试打印机A');
+      }
+    });
+
+    it('应该能够设置默认打印机', async () => {
+      // 创建两个打印机
+      const printer1 = await testFactory.createTestPrinter(1, { printerName: '打印机1', isDefault: 1 });
+      const printer2 = await testFactory.createTestPrinter(1, { printerName: '打印机2', isDefault: 0 });
+
+      // 设置打印机2为默认
+      const response = await client['printers/:printerSn/set-default'].$post({
+        param: { printerSn: printer2.printerSn }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+
+        expect(data.success).toBe(true);
+        expect(data.data.isDefault).toBe(1);
+      }
+
+      // 验证打印机1不再是默认
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const updatedPrinter1 = await dataSource.getRepository(FeiePrinterMt).findOne({
+        where: { tenantId: 1, printerSn: printer1.printerSn }
+      });
+      expect(updatedPrinter1?.isDefault).toBe(0);
+    });
+  });
+
+  describe('打印任务管理功能验证', () => {
+    let testPrinter: FeiePrinterMt;
+
+    beforeEach(async () => {
+      // 创建测试打印机
+      testPrinter = await testFactory.createTestPrinter(1);
+    });
+
+    it.skip('应该能够创建打印任务 - 需要实际飞鹅API连接', async () => {
+      const taskData = {
+        printerSn: testPrinter.printerSn,
+        content: '<CB>测试打印内容</CB><BR>',
+        printType: 'RECEIPT',
+        delaySeconds: 0
+      };
+
+      const response = await client.tasks.$post({
+        json: taskData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      console.debug('创建打印任务响应状态码:', response.status);
+      if (response.status !== 200) {
+        const errorResult = await response.json();
+        console.debug('创建打印任务错误响应:', errorResult);
+      }
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+
+        expect(data.success).toBe(true);
+        expect(data.data.taskId).toBeDefined();
+        expect(data.data.printerSn).toBe(testPrinter.printerSn);
+        expect(data.data.printType).toBe('RECEIPT');
+      }
+    });
+
+    it('应该能够查询打印任务列表', async () => {
+      // 创建测试打印任务
+      const task1 = await testFactory.createTestPrintTask(1, testPrinter.printerSn);
+      const task2 = await testFactory.createTestPrintTask(1, testPrinter.printerSn);
+
+      // 查询打印任务列表
+      const response = await client.tasks.$get({
+        query: {}
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+
+        expect(data.success).toBe(true);
+        expect(data.data.data).toHaveLength(2);
+        expect(data.data.total).toBe(2);
+      }
+    });
+
+    it('应该能够根据打印机筛选打印任务', async () => {
+      // 创建另一个打印机
+      const otherPrinter = await testFactory.createTestPrinter(1);
+
+      // 创建测试打印任务
+      const task1 = await testFactory.createTestPrintTask(1, testPrinter.printerSn);
+      const task2 = await testFactory.createTestPrintTask(1, otherPrinter.printerSn);
+
+      // 根据打印机筛选
+      const response = await client.tasks.$get({
+        query: { printerSn: testPrinter.printerSn }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+
+        expect(data.success).toBe(true);
+        expect(data.data.data).toHaveLength(1);
+        expect(data.data.data[0].printerSn).toBe(testPrinter.printerSn);
+      }
+    });
+  });
+
+  describe('错误处理验证', () => {
+    it('应该在打印机不存在时创建打印任务失败', async () => {
+      const taskData = {
+        printerSn: 'NONEXISTENT_PRINTER',
+        content: '测试内容',
+        printType: 'RECEIPT'
+      };
+
+      const response = await client.tasks.$post({
+        json: taskData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      // 应该返回错误
+      expect(response.status).toBe(500);
+      if (response.status === 500) {
+        const data = await response.json();
+        expect(data.success).toBe(false);
+        expect(data.message).toContain('打印机不存在');
+      }
+    });
+
+    it('应该在打印任务不存在时查询状态失败', async () => {
+      const response = await client['tasks/:taskId/status'].$get({
+        param: { taskId: 'NONEXISTENT_TASK' }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      // 应该返回500(服务层抛出错误)
+      expect(response.status).toBe(500);
+      if (response.status === 500) {
+        const data = await response.json();
+        expect(data.success).toBe(false);
+        expect(data.message).toBe('打印任务不存在');
+      }
+    });
+
+    it('应该在缺少飞鹅API配置时返回错误', async () => {
+      // 清理配置
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      await dataSource.getRepository(FeieConfigMt).delete({ tenantId: 1 });
+
+      // 尝试查询打印机列表
+      const response = await client.printers.$get({
+        query: {}
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      // 应该返回400,因为缺少配置
+      expect(response.status).toBe(400);
+      if (response.status === 400) {
+        const data = await response.json();
+        expect(data.success).toBe(false);
+        expect(data.message).toBe('飞鹅API配置未找到或配置不完整');
+      }
+    });
+  });
+
+  describe('调度器管理功能验证', () => {
+    it.skip('应该能够获取调度器状态 - 需要实际飞鹅API连接', async () => {
+      const response = await client['scheduler/status'].$get({}, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+
+        expect(data.success).toBe(true);
+        expect(data.data).toBeDefined();
+        expect(data.data.isRunning).toBeDefined();
+        expect(data.data.lastRunTime).toBeDefined();
+      }
+    });
+
+    it.skip('应该能够启动和停止调度器 - 需要实际飞鹅API连接', async () => {
+      // 启动调度器
+      const startResponse = await client['scheduler/start'].$post({}, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(startResponse.status).toBe(200);
+      if (startResponse.status === 200) {
+        const data = await startResponse.json();
+        expect(data.success).toBe(true);
+        expect(data.message).toBe('调度器已启动');
+      }
+
+      // 停止调度器
+      const stopResponse = await client['scheduler/stop'].$post({}, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(stopResponse.status).toBe(200);
+      if (stopResponse.status === 200) {
+        const data = await stopResponse.json();
+        expect(data.success).toBe(true);
+        expect(data.message).toBe('调度器已停止');
+      }
+    });
+
+    it.skip('应该能够进行调度器健康检查 - 需要实际飞鹅API连接', async () => {
+      const response = await client['scheduler/health'].$get({}, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+
+        expect(data.success).toBe(true);
+        expect(data.data).toBeDefined();
+        expect(data.data.healthy).toBeDefined();
+        expect(data.data.message).toBeDefined();
+      }
+    });
+  });
+
+  describe('配置管理功能验证', () => {
+    it('应该能够获取打印配置', async () => {
+      const response = await client.config.$get({}, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+
+        expect(data.success).toBe(true);
+        expect(data.data.data).toBeDefined();
+        expect(Array.isArray(data.data.data)).toBe(true);
+
+        // 应该包含飞鹅API配置
+        const feieConfigs = data.data.data.filter((config: any) =>
+          config.configKey.startsWith('feie.api.')
+        );
+        expect(feieConfigs.length).toBeGreaterThan(0);
+      }
+    });
+
+    it('应该能够更新打印配置', async () => {
+      const updateData = {
+        configValue: 'new_test_user'
+      };
+
+      const response = await client['config/:configKey'].$put({
+        param: { configKey: 'feie.api.user' },
+        json: updateData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      if (response.status === 200) {
+        const data = await response.json();
+
+        expect(data.success).toBe(true);
+        expect(data.data.configKey).toBe('feie.api.user');
+        expect(data.data.configValue).toBe('new_test_user');
+      }
+
+      // 验证配置已更新
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const updatedConfig = await dataSource.getRepository(FeieConfigMt).findOne({
+        where: { tenantId: 1, configKey: 'feie.api.user' }
+      });
+      expect(updatedConfig?.configValue).toBe('new_test_user');
+    });
+
+    it('应该在配置值为空时返回错误', async () => {
+      const updateData = {
+        configValue: ''
+      };
+
+      const response = await client['config/:configKey'].$put({
+        param: { configKey: 'feie.api.user' },
+        json: updateData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      // 应该返回400
+      expect(response.status).toBe(400);
+      if (response.status === 400) {
+        const data = await response.json();
+        expect(data.success).toBe(false);
+        expect(data.message).toBe('配置值不能为空');
+      }
+    });
+  });
+});

+ 192 - 0
packages/feie-printer-module-mt/tests/utils/test-data-factory.ts

@@ -0,0 +1,192 @@
+import { DataSource } from 'typeorm';
+import { UserEntityMt } from '@d8d/user-module-mt';
+import { JWTUtil } from '@d8d/shared-utils';
+import { FeiePrinterMt, FeiePrintTaskMt, FeieConfigMt } from '../../src/entities';
+
+/**
+ * 飞鹅打印模块测试数据工厂类
+ */
+export class FeieTestDataFactory {
+  /**
+   * 创建测试用户数据
+   */
+  static createUserData(overrides: Partial<UserEntityMt> = {}): Partial<UserEntityMt> {
+    const timestamp = Math.floor(Math.random() * 100000);
+    return {
+      username: `test_user_${timestamp}`,
+      password: 'test_password',
+      nickname: '测试用户',
+      registrationSource: 'web',
+      isDisabled: 0,
+      ...overrides
+    };
+  }
+
+  /**
+   * 在数据库中创建测试用户
+   */
+  static async createTestUser(dataSource: DataSource, tenantId: number, overrides: Partial<UserEntityMt> = {}): Promise<UserEntityMt> {
+    const userData = this.createUserData({ tenantId, ...overrides });
+    const userRepository = dataSource.getRepository(UserEntityMt);
+    const user = userRepository.create(userData);
+    return await userRepository.save(user);
+  }
+
+  /**
+   * 创建测试打印机
+   */
+  static async createTestPrinter(dataSource: DataSource, tenantId: number, overrides: Partial<FeiePrinterMt> = {}): Promise<FeiePrinterMt> {
+    const printerRepository = dataSource.getRepository(FeiePrinterMt);
+    const timestamp = Math.floor(Math.random() * 100000);
+
+    const printer = printerRepository.create({
+      tenantId,
+      printerSn: `TEST_SN_${timestamp}`,
+      printerKey: `TEST_KEY_${timestamp}`,
+      printerName: '测试打印机',
+      printerType: '58mm',
+      printerStatus: 'ACTIVE',
+      isDefault: 0,
+      ...overrides
+    });
+
+    return await printerRepository.save(printer);
+  }
+
+  /**
+   * 创建测试打印任务
+   */
+  static async createTestPrintTask(dataSource: DataSource, tenantId: number, printerSn: string, overrides: Partial<FeiePrintTaskMt> = {}): Promise<FeiePrintTaskMt> {
+    const taskRepository = dataSource.getRepository(FeiePrintTaskMt);
+    const timestamp = Date.now();
+
+    const task = taskRepository.create({
+      tenantId,
+      taskId: `TASK_${timestamp}`,
+      printerSn,
+      content: '<CB>测试打印内容</CB><BR>',
+      printType: 'RECEIPT',
+      printStatus: 'PENDING',
+      retryCount: 0,
+      ...overrides
+    });
+
+    return await taskRepository.save(task);
+  }
+
+  /**
+   * 创建测试飞鹅配置
+   */
+  static async createTestFeieConfig(dataSource: DataSource, tenantId: number, overrides: Partial<FeieConfigMt> = {}): Promise<FeieConfigMt> {
+    const configRepository = dataSource.getRepository(FeieConfigMt);
+
+    const config = configRepository.create({
+      tenantId,
+      configKey: 'feie.api.user',
+      configValue: 'test_user',
+      configType: 'STRING',
+      description: '飞鹅API用户',
+      ...overrides
+    });
+
+    return await configRepository.save(config);
+  }
+
+  /**
+   * 创建完整的飞鹅API配置
+   */
+  static async createFullFeieConfig(dataSource: DataSource, tenantId: number): Promise<void> {
+    const configRepository = dataSource.getRepository(FeieConfigMt);
+
+    const configs = [
+      {
+        tenantId,
+        configKey: 'feie.api.user',
+        configValue: 'test_user',
+        configType: 'STRING',
+        description: '飞鹅API用户'
+      },
+      {
+        tenantId,
+        configKey: 'feie.api.ukey',
+        configValue: 'test_ukey',
+        configType: 'STRING',
+        description: '飞鹅API密钥'
+      },
+      {
+        tenantId,
+        configKey: 'feie.api.base_url',
+        configValue: 'https://api.feieyun.cn/Api/Open/',
+        configType: 'STRING',
+        description: '飞鹅API基础URL'
+      },
+      {
+        tenantId,
+        configKey: 'feie.api.timeout',
+        configValue: '10000',
+        configType: 'NUMBER',
+        description: 'API超时时间'
+      },
+      {
+        tenantId,
+        configKey: 'feie.api.max_retries',
+        configValue: '3',
+        configType: 'NUMBER',
+        description: '最大重试次数'
+      }
+    ];
+
+    for (const config of configs) {
+      await configRepository.save(configRepository.create(config));
+    }
+  }
+
+  /**
+   * 创建完整的测试环境数据
+   */
+  static async createCompleteTestData(dataSource: DataSource, tenantId: number = 1): Promise<{
+    user: UserEntityMt;
+    printer: FeiePrinterMt;
+    task: FeiePrintTaskMt;
+  }> {
+    // 创建用户
+    const user = await this.createTestUser(dataSource, tenantId);
+
+    // 创建打印机
+    const printer = await this.createTestPrinter(dataSource, tenantId);
+
+    // 创建打印任务
+    const task = await this.createTestPrintTask(dataSource, tenantId, printer.printerSn);
+
+    // 创建配置
+    await this.createFullFeieConfig(dataSource, tenantId);
+
+    return {
+      user,
+      printer,
+      task
+    };
+  }
+
+  /**
+   * 为测试用户生成JWT token
+   */
+  static generateUserToken(user: UserEntityMt): string {
+    return JWTUtil.generateToken({
+      id: user.id,
+      username: user.username,
+      tenantId: user.tenantId
+    });
+  }
+
+  /**
+   * 为管理员生成JWT token
+   */
+  static generateAdminToken(tenantId: number): string {
+    return JWTUtil.generateToken({
+      id: 1,
+      username: 'admin',
+      tenantId
+    });
+  }
+}