Quellcode durchsuchen

✨ feat(orders-module): 实现订单模块独立包

- 创建独立的 @d8d/orders-module 包
- 迁移订单实体:Order, OrderGoods, OrderRefund
- 迁移订单服务:OrderService, OrderGoodsService, OrderRefundService
- 实现管理员路由:orders, order-items, refunds
- 实现用户路由:orders, order-items, refunds
- 实现专门的订单创建路由
- 配置完整的数据权限和认证中间件

🤖 Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname vor 1 Monat
Ursprung
Commit
421ca11dbd
27 geänderte Dateien mit 1825 neuen und 0 gelöschten Zeilen
  1. 89 0
      packages/orders-module/package.json
  2. 3 0
      packages/orders-module/src/entities/index.ts
  3. 82 0
      packages/orders-module/src/entities/order-goods.entity.ts
  4. 40 0
      packages/orders-module/src/entities/order-refund.entity.ts
  5. 139 0
      packages/orders-module/src/entities/order.entity.ts
  6. 5 0
      packages/orders-module/src/index.ts
  7. 24 0
      packages/orders-module/src/routes/admin/order-items.ts
  8. 24 0
      packages/orders-module/src/routes/admin/orders.ts
  9. 24 0
      packages/orders-module/src/routes/admin/refunds.ts
  10. 61 0
      packages/orders-module/src/routes/create-order.ts
  11. 10 0
      packages/orders-module/src/routes/index.ts
  12. 26 0
      packages/orders-module/src/routes/user/order-items.ts
  13. 26 0
      packages/orders-module/src/routes/user/orders.ts
  14. 26 0
      packages/orders-module/src/routes/user/refunds.ts
  15. 66 0
      packages/orders-module/src/schemas/create-order.schema.ts
  16. 4 0
      packages/orders-module/src/schemas/index.ts
  17. 246 0
      packages/orders-module/src/schemas/order-goods.schema.ts
  18. 128 0
      packages/orders-module/src/schemas/order-refund.schema.ts
  19. 497 0
      packages/orders-module/src/schemas/order.schema.ts
  20. 3 0
      packages/orders-module/src/services/index.ts
  21. 9 0
      packages/orders-module/src/services/order-goods.service.ts
  22. 9 0
      packages/orders-module/src/services/order-refund.service.ts
  23. 180 0
      packages/orders-module/src/services/order.service.ts
  24. 1 0
      packages/orders-module/src/types/index.ts
  25. 66 0
      packages/orders-module/src/types/order.types.ts
  26. 16 0
      packages/orders-module/tsconfig.json
  27. 21 0
      packages/orders-module/vitest.config.ts

+ 89 - 0
packages/orders-module/package.json

@@ -0,0 +1,89 @@
+{
+  "name": "@d8d/orders-module",
+  "version": "1.0.0",
+  "description": "订单管理模块 - 提供订单、订单商品和退款的完整CRUD功能,包括订单创建、状态管理、库存更新等业务逻辑",
+  "type": "module",
+  "main": "src/index.ts",
+  "types": "src/index.ts",
+  "exports": {
+    ".": {
+      "types": "./src/index.ts",
+      "import": "./src/index.ts",
+      "require": "./src/index.ts"
+    },
+    "./services": {
+      "types": "./src/services/index.ts",
+      "import": "./src/services/index.ts",
+      "require": "./src/services/index.ts"
+    },
+    "./schemas": {
+      "types": "./src/schemas/index.ts",
+      "import": "./src/schemas/index.ts",
+      "require": "./src/schemas/index.ts"
+    },
+    "./routes": {
+      "types": "./src/routes/index.ts",
+      "import": "./src/routes/index.ts",
+      "require": "./src/routes/index.ts"
+    },
+    "./entities": {
+      "types": "./src/entities/index.ts",
+      "import": "./src/entities/index.ts",
+      "require": "./src/entities/index.ts"
+    },
+    "./types": {
+      "types": "./src/types/index.ts",
+      "import": "./src/types/index.ts",
+      "require": "./src/types/index.ts"
+    }
+  },
+  "files": [
+    "src"
+  ],
+  "scripts": {
+    "build": "tsc",
+    "dev": "tsc --watch",
+    "test": "vitest run",
+    "test:watch": "vitest",
+    "test:coverage": "vitest run --coverage",
+    "test:integration": "vitest run tests/integration",
+    "lint": "eslint src --ext .ts,.tsx",
+    "typecheck": "tsc --noEmit"
+  },
+  "dependencies": {
+    "@d8d/shared-types": "workspace:*",
+    "@d8d/shared-utils": "workspace:*",
+    "@d8d/shared-crud": "workspace:*",
+    "@d8d/auth-module": "workspace:*",
+    "@d8d/user-module": "workspace:*",
+    "@d8d/goods-module": "workspace:*",
+    "@d8d/delivery-address-module": "workspace:*",
+    "@d8d/merchant-module": "workspace:*",
+    "@d8d/supplier-module": "workspace:*",
+    "@hono/zod-openapi": "^1.0.2",
+    "typeorm": "^0.3.20",
+    "zod": "^4.1.12"
+  },
+  "devDependencies": {
+    "@types/node": "^22.10.2",
+    "typescript": "^5.8.3",
+    "vitest": "^3.2.4",
+    "@d8d/shared-test-util": "workspace:*",
+    "@typescript-eslint/eslint-plugin": "^8.18.1",
+    "@typescript-eslint/parser": "^8.18.1",
+    "eslint": "^9.17.0"
+  },
+  "peerDependencies": {
+    "hono": "^4.8.5"
+  },
+  "keywords": [
+    "orders",
+    "order-management",
+    "e-commerce",
+    "crud",
+    "api",
+    "management"
+  ],
+  "author": "D8D Team",
+  "license": "MIT"
+}

+ 3 - 0
packages/orders-module/src/entities/index.ts

@@ -0,0 +1,3 @@
+export { Order } from './order.entity';
+export { OrderGoods } from './order-goods.entity';
+export { OrderRefund } from './order-refund.entity';

+ 82 - 0
packages/orders-module/src/entities/order-goods.entity.ts

@@ -0,0 +1,82 @@
+import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne, JoinColumn } from 'typeorm';
+import { Order } from './order.entity';
+import { Goods } from '@d8d/goods-module';
+import { Supplier } from '@d8d/supplier-module';
+import { File } from '@d8d/file-module';
+
+@Entity('orders_goods')
+export class OrderGoods {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'order_id', type: 'int', unsigned: true, comment: '订单表id' })
+  orderId!: number;
+
+  @Column({ name: 'order_no', type: 'varchar', length: 50, nullable: true, comment: '订单号' })
+  orderNo!: string | null;
+
+  @Column({ name: 'goods_id', type: 'int', unsigned: true, comment: '商品id' })
+  goodsId!: number;
+
+  @Column({ name: 'goods_name', type: 'varchar', length: 255, nullable: true, comment: '商品名称' })
+  goodsName!: string | null;
+
+  @Column({ name: 'goods_type', type: 'int', default: 1, comment: '1实物产品2虚拟订单' })
+  goodsType!: number;
+
+  @Column({ name: 'supplier_id', type: 'int', unsigned: true, nullable: true, comment: '供货商id' })
+  supplierId!: number | null;
+
+  @Column({ name: 'cost_price', type: 'decimal', precision: 10, scale: 2, default: 0.00, comment: '成本价' })
+  costPrice!: number;
+
+  @Column({ name: 'price', type: 'decimal', precision: 10, scale: 2, default: 0.00, comment: '售价' })
+  price!: number;
+
+  @Column({ name: 'num', type: 'int', default: 0, comment: '数量' })
+  num!: number;
+
+  @Column({ name: 'freight_amount', type: 'decimal', precision: 10, scale: 2, default: 0.00, comment: '运费' })
+  freightAmount!: number;
+
+  @Column({ name: 'state', type: 'int', default: 0, comment: '状态(0未发货、1已发货)' })
+  state!: number;
+
+  @Column({ name: 'express_name', type: 'varchar', length: 255, nullable: true, comment: '快递名称' })
+  expressName!: string | null;
+
+  @Column({ name: 'express_no', type: 'int', nullable: true, comment: '单号' })
+  expressNo!: number | null;
+
+  @CreateDateColumn({ name: 'created_at', type: 'timestamp' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at', type: 'timestamp' })
+  updatedAt!: Date;
+
+  @Column({ name: 'created_by', type: 'int', unsigned: true, nullable: true, comment: '创建人ID' })
+  createdBy!: number | null;
+
+  @Column({ name: 'updated_by', type: 'int', unsigned: true, nullable: true, comment: '更新人ID' })
+  updatedBy!: number | null;
+
+  @Column({ name: 'image_file_id', type: 'int', unsigned: true, nullable: true, comment: '商品图片文件ID' })
+  imageFileId!: number | null;
+
+  // 关联关系
+  @ManyToOne(() => Order)
+  @JoinColumn({ name: 'order_id', referencedColumnName: 'id' })
+  order!: Order;
+
+  @ManyToOne(() => Goods)
+  @JoinColumn({ name: 'goods_id', referencedColumnName: 'id' })
+  goods!: Goods;
+
+  @ManyToOne(() => Supplier)
+  @JoinColumn({ name: 'supplier_id', referencedColumnName: 'id' })
+  supplier!: Supplier;
+
+  @ManyToOne(() => File, { nullable: true })
+  @JoinColumn({ name: 'image_file_id', referencedColumnName: 'id' })
+  imageFile!: File | null;
+}

+ 40 - 0
packages/orders-module/src/entities/order-refund.entity.ts

@@ -0,0 +1,40 @@
+import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne, JoinColumn } from 'typeorm';
+import { Order } from './order.entity';
+
+@Entity('orders_refund')
+export class OrderRefund {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'order_no', type: 'varchar', length: 32, nullable: true, comment: '订单号' })
+  orderNo!: string | null;
+
+  @Column({ name: 'refund_order_no', type: 'varchar', length: 32, nullable: true, comment: '退款订单号' })
+  refundOrderNo!: string | null;
+
+  @Column({ name: 'refund_amount', type: 'decimal', precision: 10, scale: 2, nullable: true, comment: '退款金额' })
+  refundAmount!: number | null;
+
+  @Column({ name: 'state', type: 'int', default: 0, comment: '0未退款1退款中2退款成功3退款失败' })
+  state!: number;
+
+  @Column({ name: 'remark', type: 'varchar', length: 255, nullable: true, comment: '备注' })
+  remark!: string | null;
+
+  @Column({ name: 'created_by', type: 'int', unsigned: true, nullable: true, comment: '创建人ID' })
+  createdBy!: number | null;
+
+  @Column({ name: 'updated_by', type: 'int', unsigned: true, nullable: true, comment: '更新人ID' })
+  updatedBy!: number | null;
+
+  @CreateDateColumn({ name: 'created_at', type: 'timestamp' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at', type: 'timestamp' })
+  updatedAt!: Date;
+
+  // 关联关系
+  @ManyToOne(() => Order)
+  @JoinColumn({ name: 'order_no', referencedColumnName: 'orderNo' })
+  order!: Order;
+}

+ 139 - 0
packages/orders-module/src/entities/order.entity.ts

@@ -0,0 +1,139 @@
+import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne, JoinColumn } from 'typeorm';
+import { User } from '@d8d/user-module';
+import { Merchant } from '@d8d/merchant-module';
+import { Supplier } from '@d8d/supplier-module';
+import { DeliveryAddress } from '@d8d/delivery-address-module';
+
+@Entity('orders')
+export class Order {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'order_no', type: 'varchar', length: 50, unique: true, comment: '订单号' })
+  orderNo!: string;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true, comment: '用户ID' })
+  userId!: number;
+
+  @Column({ name: 'auth_code', type: 'varchar', length: 32, nullable: true, comment: '付款码' })
+  authCode!: string | null;
+
+  @Column({ name: 'card_no', type: 'varchar', length: 32, nullable: true, comment: '卡号' })
+  cardNo!: string | null;
+
+  @Column({ name: 'sjt_card_no', type: 'varchar', length: 32, nullable: true, comment: '盛京通卡号' })
+  sjtCardNo!: string | null;
+
+  @Column({ name: 'amount', type: 'decimal', precision: 10, scale: 2, default: 0.00, comment: '订单金额' })
+  amount!: number;
+
+  @Column({ name: 'cost_amount', type: 'decimal', precision: 10, scale: 2, default: 0.00, comment: '成本金额' })
+  costAmount!: number;
+
+  @Column({ name: 'freight_amount', type: 'decimal', precision: 10, scale: 2, default: 0.00, comment: '运费' })
+  freightAmount!: number;
+
+  @Column({ name: 'discount_amount', type: 'decimal', precision: 10, scale: 2, default: 0.00, comment: '优惠金额' })
+  discountAmount!: number;
+
+  @Column({ name: 'pay_amount', type: 'decimal', precision: 10, scale: 2, default: 0.00, comment: '实际支付金额' })
+  payAmount!: number;
+
+  @Column({ name: 'device_no', type: 'varchar', length: 255, nullable: true, comment: '设备编号' })
+  deviceNo!: string | null;
+
+  @Column({ name: 'description', type: 'varchar', length: 255, nullable: true, comment: '订单描述' })
+  description!: string | null;
+
+  @Column({ name: 'goods_detail', type: 'varchar', length: 2000, nullable: true, comment: '订单详情 json' })
+  goodsDetail!: string | null;
+
+  @Column({ name: 'goods_tag', type: 'varchar', length: 255, nullable: true, comment: '订单优惠标记' })
+  goodsTag!: string | null;
+
+  @Column({ name: 'address', type: 'varchar', length: 255, nullable: true, comment: '地址' })
+  address!: string | null;
+
+  @Column({ name: 'order_type', type: 'int', default: 1, comment: '订单类型 1实物订单 2虚拟订单' })
+  orderType!: number;
+
+  @Column({ name: 'pay_type', type: 'int', default: 0, comment: '支付类型1积分2礼券' })
+  payType!: number;
+
+  @Column({ name: 'pay_state', type: 'int', default: 0, comment: '0未支付1支付中2支付成功3已退款4支付失败5订单关闭' })
+  payState!: number;
+
+  @Column({ name: 'state', type: 'int', default: 0, comment: '订单状态0未发货1已发货2收货成功3已退货' })
+  state!: number;
+
+  @Column({ name: 'user_phone', type: 'varchar', length: 50, nullable: true, comment: '用户手机号' })
+  userPhone!: string | null;
+
+  @Column({ name: 'merchant_id', type: 'int', unsigned: true, default: 0, comment: '商户id' })
+  merchantId!: number;
+
+  @Column({ name: 'merchant_no', type: 'int', unsigned: true, nullable: true, comment: '商户号' })
+  merchantNo!: number | null;
+
+  @Column({ name: 'supplier_id', type: 'int', unsigned: true, default: 0, comment: '供货商id' })
+  supplierId!: number;
+
+  @Column({ name: 'address_id', type: 'int', unsigned: true, default: 0, comment: '地址id' })
+  addressId!: number;
+
+  @Column({ name: 'receiver_mobile', type: 'varchar', length: 255, nullable: true, comment: '收货人手机号' })
+  receiverMobile!: string | null;
+
+  @Column({ name: 'recevier_name', type: 'varchar', length: 255, nullable: true, comment: '收货人姓名' })
+  recevierName!: string | null;
+
+  @Column({ name: 'recevier_province', type: 'bigint', default: 0, comment: '收货人所在省' })
+  recevierProvince!: number;
+
+  @Column({ name: 'recevier_city', type: 'bigint', default: 0, comment: '收货人所在市' })
+  recevierCity!: number;
+
+  @Column({ name: 'recevier_district', type: 'bigint', default: 0, comment: '收货人所在区' })
+  recevierDistrict!: number;
+
+  @Column({ name: 'recevier_town', type: 'bigint', default: 0, comment: '收货人所在街道' })
+  recevierTown!: number;
+
+  @Column({ name: 'refund_time', type: 'timestamp', nullable: true, comment: '退款时间' })
+  refundTime!: Date | null;
+
+  @Column({ name: 'close_time', type: 'timestamp', nullable: true, comment: '订单关闭时间' })
+  closeTime!: Date | null;
+
+  @Column({ name: 'remark', type: 'varchar', length: 255, nullable: true, comment: '管理员备注信息' })
+  remark!: string | null;
+
+  @Column({ name: 'created_by', type: 'int', unsigned: true, nullable: true, comment: '创建人ID' })
+  createdBy!: number | null;
+
+  @Column({ name: 'updated_by', type: 'int', unsigned: true, nullable: true, comment: '更新人ID' })
+  updatedBy!: number | null;
+
+  @CreateDateColumn({ name: 'created_at', type: 'timestamp' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at', type: 'timestamp' })
+  updatedAt!: Date;
+
+  // 关联关系
+  @ManyToOne(() => User)
+  @JoinColumn({ name: 'user_id', referencedColumnName: 'id' })
+  user!: User;
+
+  @ManyToOne(() => Merchant)
+  @JoinColumn({ name: 'merchant_id', referencedColumnName: 'id' })
+  merchant!: Merchant;
+
+  @ManyToOne(() => Supplier)
+  @JoinColumn({ name: 'supplier_id', referencedColumnName: 'id' })
+  supplier!: Supplier;
+
+  @ManyToOne(() => DeliveryAddress)
+  @JoinColumn({ name: 'address_id', referencedColumnName: 'id' })
+  deliveryAddress!: DeliveryAddress;
+}

+ 5 - 0
packages/orders-module/src/index.ts

@@ -0,0 +1,5 @@
+export * from './entities';
+export * from './services';
+export * from './schemas';
+export * from './routes';
+export * from './types';

+ 24 - 0
packages/orders-module/src/routes/admin/order-items.ts

@@ -0,0 +1,24 @@
+import { createCrudRoutes } from '@d8d/shared-crud';
+import { OpenAPIHono } from '@hono/zod-openapi';
+import { OrderGoods } from '../../entities/order-goods.entity';
+import { OrderGoodsSchema, CreateOrderGoodsDto, UpdateOrderGoodsDto } from '../../schemas/order-goods.schema';
+import { authMiddleware } from '@d8d/auth-module';
+
+// 管理员订单商品路由 - 无数据权限限制,完整CRUD功能
+const adminOrderItemsRoutes = createCrudRoutes({
+  entity: OrderGoods,
+  createSchema: CreateOrderGoodsDto,
+  updateSchema: UpdateOrderGoodsDto,
+  getSchema: OrderGoodsSchema,
+  listSchema: OrderGoodsSchema,
+  searchFields: ['orderNo', 'goodsName'],
+  relations: ['order', 'goods', 'supplier', 'imageFile'],
+  middleware: [authMiddleware],
+  userTracking: {
+    createdByField: 'createdBy',
+    updatedByField: 'updatedBy'
+  }
+  // 管理员路由不设置dataPermission,可以访问所有数据
+});
+
+export default adminOrderItemsRoutes;

+ 24 - 0
packages/orders-module/src/routes/admin/orders.ts

@@ -0,0 +1,24 @@
+import { createCrudRoutes } from '@d8d/shared-crud';
+import { OpenAPIHono } from '@hono/zod-openapi';
+import { Order } from '../../entities/order.entity';
+import { OrderSchema, CreateOrderDto, UpdateOrderDto } from '../../schemas/order.schema';
+import { authMiddleware } from '@d8d/auth-module';
+
+// 管理员订单路由 - 无数据权限限制,完整CRUD功能
+const adminOrderRoutes = createCrudRoutes({
+  entity: Order,
+  createSchema: CreateOrderDto,
+  updateSchema: UpdateOrderDto,
+  getSchema: OrderSchema,
+  listSchema: OrderSchema,
+  searchFields: ['orderNo', 'userPhone', 'recevierName'],
+  relations: ['user', 'merchant', 'supplier', 'deliveryAddress'],
+  middleware: [authMiddleware],
+  userTracking: {
+    createdByField: 'createdBy',
+    updatedByField: 'updatedBy'
+  }
+  // 管理员路由不设置dataPermission,可以访问所有数据
+});
+
+export default adminOrderRoutes;

+ 24 - 0
packages/orders-module/src/routes/admin/refunds.ts

@@ -0,0 +1,24 @@
+import { createCrudRoutes } from '@d8d/shared-crud';
+import { OpenAPIHono } from '@hono/zod-openapi';
+import { OrderRefund } from '../../entities/order-refund.entity';
+import { OrderRefundSchema, CreateOrderRefundDto, UpdateOrderRefundDto } from '../../schemas/order-refund.schema';
+import { authMiddleware } from '@d8d/auth-module';
+
+// 管理员退款路由 - 无数据权限限制,完整CRUD功能
+const adminRefundsRoutes = createCrudRoutes({
+  entity: OrderRefund,
+  createSchema: CreateOrderRefundDto,
+  updateSchema: UpdateOrderRefundDto,
+  getSchema: OrderRefundSchema,
+  listSchema: OrderRefundSchema,
+  searchFields: ['orderNo', 'refundOrderNo'],
+  relations: ['order'],
+  middleware: [authMiddleware],
+  userTracking: {
+    createdByField: 'createdBy',
+    updatedByField: 'updatedBy'
+  }
+  // 管理员路由不设置dataPermission,可以访问所有数据
+});
+
+export default adminRefundsRoutes;

+ 61 - 0
packages/orders-module/src/routes/create-order.ts

@@ -0,0 +1,61 @@
+import { OpenAPIHono } from '@hono/zod-openapi';
+import { authMiddleware } from '@d8d/auth-module';
+import { OrderService } from '../services';
+import { CreateOrderRequestSchema, CreateOrderResponseSchema } from '../schemas/create-order.schema';
+
+const createOrderRoutes = new OpenAPIHono();
+
+// 应用认证中间件
+createOrderRoutes.use('*', authMiddleware);
+
+// 创建订单路由
+createOrderRoutes.openapi(
+  {
+    method: 'post',
+    path: '/',
+    request: {
+      body: {
+        content: {
+          'application/json': {
+            schema: CreateOrderRequestSchema
+          }
+        }
+      }
+    },
+    responses: {
+      200: {
+        description: '订单创建成功',
+        content: {
+          'application/json': {
+            schema: CreateOrderResponseSchema
+          }
+        }
+      },
+      400: {
+        description: '请求参数错误'
+      },
+      500: {
+        description: '服务器内部错误'
+      }
+    }
+  },
+  async (c) => {
+    const data = c.req.valid('json');
+    const userId = c.get('user').id;
+
+    try {
+      const orderService = new OrderService(c.get('dataSource'));
+      const result = await orderService.createOrder(data, userId);
+
+      return c.json(result, 200);
+    } catch (error) {
+      console.error('创建订单失败:', error);
+      return c.json(
+        { error: error instanceof Error ? error.message : '创建订单失败' },
+        500
+      );
+    }
+  }
+);
+
+export default createOrderRoutes;

+ 10 - 0
packages/orders-module/src/routes/index.ts

@@ -0,0 +1,10 @@
+// 导出所有路由
+export { default as adminOrderRoutes } from './admin/orders';
+export { default as adminOrderItemsRoutes } from './admin/order-items';
+export { default as adminRefundsRoutes } from './admin/refunds';
+
+export { default as userOrderRoutes } from './user/orders';
+export { default as userOrderItemsRoutes } from './user/order-items';
+export { default as userRefundsRoutes } from './user/refunds';
+
+export { default as createOrderRoutes } from './create-order';

+ 26 - 0
packages/orders-module/src/routes/user/order-items.ts

@@ -0,0 +1,26 @@
+import { createCrudRoutes } from '@d8d/shared-crud';
+import { OrderGoods } from '../../entities/order-goods.entity';
+import { OrderGoodsSchema, CreateOrderGoodsDto, UpdateOrderGoodsDto } from '../../schemas/order-goods.schema';
+import { authMiddleware } from '@d8d/auth-module';
+
+// 用户订单商品路由 - 通过订单关联限制数据权限
+const userOrderItemsRoutes = createCrudRoutes({
+  entity: OrderGoods,
+  createSchema: CreateOrderGoodsDto,
+  updateSchema: UpdateOrderGoodsDto,
+  getSchema: OrderGoodsSchema,
+  listSchema: OrderGoodsSchema,
+  searchFields: ['orderNo', 'goodsName'],
+  relations: ['order', 'goods', 'supplier', 'imageFile'],
+  middleware: [authMiddleware],
+  userTracking: {
+    createdByField: 'createdBy',
+    updatedByField: 'updatedBy'
+  },
+  dataPermission: {
+    field: 'order.userId',
+    userField: 'id'
+  }
+});
+
+export default userOrderItemsRoutes;

+ 26 - 0
packages/orders-module/src/routes/user/orders.ts

@@ -0,0 +1,26 @@
+import { createCrudRoutes } from '@d8d/shared-crud';
+import { Order } from '../../entities/order.entity';
+import { OrderSchema, CreateOrderDto, UpdateOrderDto } from '../../schemas/order.schema';
+import { authMiddleware } from '@d8d/auth-module';
+
+// 用户订单路由 - 有数据权限限制,只能访问自己的订单
+const userOrderRoutes = createCrudRoutes({
+  entity: Order,
+  createSchema: CreateOrderDto,
+  updateSchema: UpdateOrderDto,
+  getSchema: OrderSchema,
+  listSchema: OrderSchema,
+  searchFields: ['orderNo', 'userPhone', 'recevierName'],
+  relations: ['user', 'merchant', 'supplier', 'deliveryAddress'],
+  middleware: [authMiddleware],
+  userTracking: {
+    createdByField: 'createdBy',
+    updatedByField: 'updatedBy'
+  },
+  dataPermission: {
+    field: 'userId',
+    userField: 'id'
+  }
+});
+
+export default userOrderRoutes;

+ 26 - 0
packages/orders-module/src/routes/user/refunds.ts

@@ -0,0 +1,26 @@
+import { createCrudRoutes } from '@d8d/shared-crud';
+import { OrderRefund } from '../../entities/order-refund.entity';
+import { OrderRefundSchema, CreateOrderRefundDto, UpdateOrderRefundDto } from '../../schemas/order-refund.schema';
+import { authMiddleware } from '@d8d/auth-module';
+
+// 用户退款路由 - 通过订单关联限制数据权限
+const userRefundsRoutes = createCrudRoutes({
+  entity: OrderRefund,
+  createSchema: CreateOrderRefundDto,
+  updateSchema: UpdateOrderRefundDto,
+  getSchema: OrderRefundSchema,
+  listSchema: OrderRefundSchema,
+  searchFields: ['orderNo', 'refundOrderNo'],
+  relations: ['order'],
+  middleware: [authMiddleware],
+  userTracking: {
+    createdByField: 'createdBy',
+    updatedByField: 'updatedBy'
+  },
+  dataPermission: {
+    field: 'order.userId',
+    userField: 'id'
+  }
+});
+
+export default userRefundsRoutes;

+ 66 - 0
packages/orders-module/src/schemas/create-order.schema.ts

@@ -0,0 +1,66 @@
+import { z } from '@hono/zod-openapi';
+
+// 订单商品项DTO
+export const OrderItemDto = z.object({
+  id: z.number().int().positive('商品ID必须是正整数').openapi({
+    description: '商品ID',
+    example: 1
+  }),
+  num: z.number().int().min(1, '购买数量必须大于0').openapi({
+    description: '购买数量',
+    example: 2
+  })
+});
+
+// 创建订单请求DTO
+export const CreateOrderRequestDto = z.object({
+  addressId: z.number().int().positive('收货地址ID必须是正整数').optional().openapi({
+    description: '收货地址ID',
+    example: 1
+  }),
+  productOwn: z.string().min(1, '商品所属方不能为空').max(50, '商品所属方最多50个字符').openapi({
+    description: '商品所属方(如:自营、第三方等)',
+    example: '自营'
+  }),
+  consumeFrom: z.string().min(1, '消费来源不能为空').max(50, '消费来源最多50个字符').openapi({
+    description: '消费来源(如:积分兑换、礼券兑换等)',
+    example: '积分兑换'
+  }),
+  products: z.array(OrderItemDto).min(1, '商品列表不能为空').openapi({
+    description: '商品列表',
+    example: [{ id: 1, num: 2 }, { id: 3, num: 1 }]
+  })
+});
+
+// 创建订单响应DTO
+export const CreateOrderResponseDto = z.object({
+  success: z.boolean().openapi({
+    description: '是否成功',
+    example: true
+  }),
+  orderId: z.number().int().positive().openapi({
+    description: '订单ID',
+    example: 1001
+  }),
+  orderNo: z.string().openapi({
+    description: '订单号',
+    example: 'ORD20240101123456'
+  }),
+  amount: z.number().openapi({
+    description: '订单总金额',
+    example: 199.98
+  }),
+  payAmount: z.number().openapi({
+    description: '实际支付金额',
+    example: 199.98
+  }),
+  message: z.string().openapi({
+    description: '提示信息',
+    example: '订单创建成功'
+  })
+});
+
+// 导出类型
+export type CreateOrderRequest = z.infer<typeof CreateOrderRequestDto>;
+export type CreateOrderResponse = z.infer<typeof CreateOrderResponseDto>;
+export type OrderItem = z.infer<typeof OrderItemDto>;

+ 4 - 0
packages/orders-module/src/schemas/index.ts

@@ -0,0 +1,4 @@
+export * from './order.schema';
+export * from './order-goods.schema';
+export * from './order-refund.schema';
+export * from './create-order.schema';

+ 246 - 0
packages/orders-module/src/schemas/order-goods.schema.ts

@@ -0,0 +1,246 @@
+import { z } from '@hono/zod-openapi';
+
+// 订单商品状态枚举
+export const OrderGoodsStatus = {
+  UN_SHIPPED: 0, // 未发货
+  SHIPPED: 1, // 已发货
+} as const;
+
+// 商品类型枚举
+export const GoodsType = {
+  PHYSICAL: 1, // 实物产品
+  VIRTUAL: 2, // 虚拟订单
+} as const;
+
+// 订单商品基础Schema
+export const OrderGoodsSchema = z.object({
+  id: z.number().int().positive().openapi({
+    description: '订单商品ID',
+    example: 1
+  }),
+  orderId: z.number().int().positive().openapi({
+    description: '订单ID',
+    example: 1
+  }),
+  orderNo: z.string().max(50, '订单号最多50个字符').nullable().optional().openapi({
+    description: '订单号',
+    example: 'ORD20240101123456'
+  }),
+  goodsId: z.number().int().positive().openapi({
+    description: '商品ID',
+    example: 1
+  }),
+  goodsName: z.string().max(255, '商品名称最多255个字符').nullable().optional().openapi({
+    description: '商品名称',
+    example: '苹果手机'
+  }),
+  goodsType: z.coerce.number().int().min(1, '商品类型最小为1').max(2, '商品类型最大为2').default(1).openapi({
+    description: '1实物产品2虚拟订单',
+    example: 1
+  }),
+  supplierId: z.coerce.number().int().positive().default(0).openapi({
+    description: '供货商ID',
+    example: 1
+  }),
+  costPrice: z.coerce.number().min(0, '成本价不能小于0').max(999999.99, '成本价不能超过999999.99').default(0).openapi({
+    description: '成本价',
+    example: 50.00
+  }),
+  price: z.coerce.number().min(0, '售价不能小于0').max(999999.99, '售价不能超过999999.99').default(0).openapi({
+    description: '售价',
+    example: 99.99
+  }),
+  num: z.coerce.number().int().min(0, '数量不能小于0').max(99999, '数量不能超过99999').default(0).openapi({
+    description: '数量',
+    example: 2
+  }),
+  freightAmount: z.coerce.number().min(0, '运费不能小于0').max(999999.99, '运费不能超过999999.99').default(0).optional().openapi({
+    description: '运费',
+    example: 10.00
+  }),
+  state: z.coerce.number().int().min(0, '状态最小为0').max(1, '状态最大为1').default(0).openapi({
+    description: '状态(0未发货、1已发货)',
+    example: 0
+  }),
+  expressName: z.string().max(255, '快递名称最多255个字符').nullable().optional().openapi({
+    description: '快递名称',
+    example: '顺丰快递'
+  }),
+  expressNo: z.coerce.number().int().positive().nullable().optional().openapi({
+    description: '快递单号',
+    example: 1234567890
+  }),
+  createdBy: z.number().int().positive().nullable().optional().openapi({
+    description: '创建人ID',
+    example: 1
+  }),
+  updatedBy: z.number().int().positive().nullable().optional().openapi({
+    description: '更新人ID',
+    example: 1
+  }),
+  createdAt: z.coerce.date().openapi({
+    description: '创建时间',
+    example: '2024-01-01T12:00:00Z'
+  }),
+  updatedAt: z.coerce.date().openapi({
+    description: '更新时间',
+    example: '2024-01-01T12:00:00Z'
+  }),
+  imageFileId: z.number().int().positive().nullable().openapi({
+    example: 1,
+    description: '商品图片文件ID'
+  }),
+  imageFile: z.object({
+    id: z.number().int().positive().openapi({ description: '文件ID' }),
+    name: z.string().max(255).openapi({ description: '文件名', example: 'goods.jpg' }),
+    fullUrl: z.string().openapi({ description: '文件完整URL', example: 'https://example.com/goods.jpg' }),
+    type: z.string().nullable().openapi({ description: '文件类型', example: 'image/jpeg' }),
+    size: z.number().nullable().openapi({ description: '文件大小(字节)', example: 102400 })
+  }).nullable().optional().openapi({
+    description: '商品图片文件信息'
+  }),
+  // 关联实体
+  order: z.object({
+    id: z.number().int().positive().openapi({ description: '订单ID' }),
+    orderNo: z.string().openapi({ description: '订单号', example: 'ORD20240101123456' })
+  }).nullable().optional().openapi({
+    description: '订单信息'
+  }),
+  goods: z.object({
+    id: z.number().int().positive().openapi({ description: '商品ID' }),
+    name: z.string().openapi({ description: '商品名称', example: '苹果手机' }),
+    image: z.string().nullable().openapi({ description: '商品图片', example: 'https://example.com/goods.jpg' })
+  }).nullable().optional().openapi({
+    description: '商品信息'
+  }),
+  supplier: z.object({
+    id: z.number().int().positive().openapi({ description: '供货商ID' }),
+    name: z.string().openapi({ description: '供货商名称', example: '供货商A' })
+  }).nullable().optional().openapi({
+    description: '供货商信息'
+  })
+});
+
+// 创建订单商品DTO
+export const CreateOrderGoodsDto = z.object({
+  orderId: z.number().int().positive('订单ID必须是正整数').openapi({
+    description: '订单ID',
+    example: 1
+  }),
+  orderNo: z.string().max(50, '订单号最多50个字符').nullable().optional().openapi({
+    description: '订单号',
+    example: 'ORD20240101123456'
+  }),
+  goodsId: z.number().int().positive('商品ID必须是正整数').openapi({
+    description: '商品ID',
+    example: 1
+  }),
+  goodsName: z.string().max(255, '商品名称最多255个字符').nullable().optional().openapi({
+    description: '商品名称',
+    example: '苹果手机'
+  }),
+  goodsType: z.coerce.number().int().min(1, '商品类型最小为1').max(2, '商品类型最大为2').default(1).optional().openapi({
+    description: '1实物产品2虚拟订单',
+    example: 1
+  }),
+  supplierId: z.coerce.number().int().positive().default(0).optional().openapi({
+    description: '供货商ID',
+    example: 1
+  }),
+  costPrice: z.coerce.number().min(0, '成本价不能小于0').max(999999.99, '成本价不能超过999999.99').default(0).optional().openapi({
+    description: '成本价',
+    example: 50.00
+  }),
+  price: z.coerce.number().min(0, '售价不能小于0').max(999999.99, '售价不能超过999999.99').default(0).optional().openapi({
+    description: '售价',
+    example: 99.99
+  }),
+  num: z.coerce.number().int().min(0, '数量不能小于0').max(99999, '数量不能超过99999').default(0).optional().openapi({
+    description: '数量',
+    example: 2
+  }),
+  freightAmount: z.coerce.number().min(0, '运费不能小于0').max(999999.99, '运费不能超过999999.99').default(0).optional().openapi({
+    description: '运费',
+    example: 10.00
+  }),
+  state: z.coerce.number().int().min(0, '状态最小为0').max(1, '状态最大为1').default(0).optional().openapi({
+    description: '状态(0未发货、1已发货)',
+    example: 0
+  }),
+  expressName: z.string().max(255, '快递名称最多255个字符').nullable().optional().openapi({
+    description: '快递名称',
+    example: '顺丰快递'
+  }),
+  expressNo: z.coerce.number().int().positive().nullable().optional().openapi({
+    description: '快递单号',
+    example: 1234567890
+  }),
+  imageFileId: z.number().int().positive().nullable().optional().openapi({
+    description: '商品图片文件ID',
+    example: 1
+  })
+});
+
+// 更新订单商品DTO
+export const UpdateOrderGoodsDto = z.object({
+  orderId: z.number().int().positive('订单ID必须是正整数').optional().openapi({
+    description: '订单ID',
+    example: 1
+  }),
+  orderNo: z.string().max(50, '订单号最多50个字符').nullable().optional().openapi({
+    description: '订单号',
+    example: 'ORD20240101123456'
+  }),
+  goodsId: z.number().int().positive('商品ID必须是正整数').optional().openapi({
+    description: '商品ID',
+    example: 1
+  }),
+  goodsName: z.string().max(255, '商品名称最多255个字符').nullable().optional().openapi({
+    description: '商品名称',
+    example: '苹果手机'
+  }),
+  goodsType: z.coerce.number().int().min(1, '商品类型最小为1').max(2, '商品类型最大为2').optional().openapi({
+    description: '1实物产品2虚拟订单',
+    example: 1
+  }),
+  supplierId: z.coerce.number().int().positive().optional().openapi({
+    description: '供货商ID',
+    example: 1
+  }),
+  costPrice: z.coerce.number().min(0, '成本价不能小于0').max(999999.99, '成本价不能超过999999.99').optional().openapi({
+    description: '成本价',
+    example: 50.00
+  }),
+  price: z.coerce.number().min(0, '售价不能小于0').max(999999.99, '售价不能超过999999.99').optional().openapi({
+    description: '售价',
+    example: 99.99
+  }),
+  num: z.coerce.number().int().min(0, '数量不能小于0').max(99999, '数量不能超过99999').optional().openapi({
+    description: '数量',
+    example: 2
+  }),
+  freightAmount: z.coerce.number().min(0, '运费不能小于0').max(999999.99, '运费不能超过999999.99').optional().openapi({
+    description: '运费',
+    example: 10.00
+  }),
+  state: z.coerce.number().int().min(0, '状态最小为0').max(1, '状态最大为1').optional().openapi({
+    description: '状态(0未发货、1已发货)',
+    example: 0
+  }),
+  expressName: z.string().max(255, '快递名称最多255个字符').nullable().optional().openapi({
+    description: '快递名称',
+    example: '顺丰快递'
+  }),
+  expressNo: z.coerce.number().int().positive().nullable().optional().openapi({
+    description: '快递单号',
+    example: 1234567890
+  }),
+  imageFileId: z.number().int().positive().nullable().optional().openapi({
+    description: '商品图片文件ID',
+    example: 1
+  })
+});
+
+// 订单商品状态类型
+export type OrderGoodsStatusType = typeof OrderGoodsStatus[keyof typeof OrderGoodsStatus];
+export type GoodsTypeType = typeof GoodsType[keyof typeof GoodsType];

+ 128 - 0
packages/orders-module/src/schemas/order-refund.schema.ts

@@ -0,0 +1,128 @@
+import { z } from '@hono/zod-openapi';
+
+// 退款状态枚举
+export const RefundStatus = {
+  PENDING: 0, // 未退款
+  PROCESSING: 1, // 退款中
+  SUCCESS: 2, // 退款成功
+  FAILED: 3, // 退款失败
+} as const;
+
+// 订单退款基础Schema
+export const OrderRefundSchema = z.object({
+  id: z.number().int().positive().openapi({
+    description: '退款记录ID',
+    example: 1
+  }),
+  orderNo: z.string().max(32, '订单号最多32个字符').nullable().optional().openapi({
+    description: '订单号',
+    example: 'ORD20240101123456'
+  }),
+  refundOrderNo: z.string().max(32, '退款订单号最多32个字符').nullable().optional().openapi({
+    description: '退款订单号',
+    example: 'REF20240101123456'
+  }),
+  refundAmount: z.coerce.number().min(0, '退款金额不能小于0').max(999999.99, '退款金额不能超过999999.99').nullable().optional().openapi({
+    description: '退款金额',
+    example: 99.99
+  }),
+  state: z.coerce.number().int().min(0, '状态最小为0').max(3, '状态最大为3').default(0).openapi({
+    description: '0未退款1退款中2退款成功3退款失败',
+    example: 0
+  }),
+  remark: z.string().max(255, '备注最多255个字符').nullable().optional().openapi({
+    description: '备注',
+    example: '用户申请退款'
+  }),
+  createdBy: z.number().int().positive().nullable().optional().openapi({
+    description: '创建人ID',
+    example: 1
+  }),
+  updatedBy: z.number().int().positive().nullable().optional().openapi({
+    description: '更新人ID',
+    example: 1
+  }),
+  createdAt: z.coerce.date().openapi({
+    description: '创建时间',
+    example: '2024-01-01T12:00:00Z'
+  }),
+  updatedAt: z.coerce.date().openapi({
+    description: '更新时间',
+    example: '2024-01-01T12:00:00Z'
+  }),
+  // 关联实体
+  order: z.object({
+    id: z.number().int().positive().openapi({ description: '订单ID' }),
+    orderNo: z.string().openapi({ description: '订单号', example: 'ORD20240101123456' }),
+    amount: z.number().openapi({ description: '订单金额', example: 99.99 })
+  }).nullable().optional().openapi({
+    description: '订单信息'
+  })
+});
+
+// 创建订单退款DTO
+export const CreateOrderRefundDto = z.object({
+  orderNo: z.string().max(32, '订单号最多32个字符').nullable().optional().openapi({
+    description: '订单号',
+    example: 'ORD20240101123456'
+  }),
+  refundOrderNo: z.string().max(32, '退款订单号最多32个字符').nullable().optional().openapi({
+    description: '退款订单号',
+    example: 'REF20240101123456'
+  }),
+  refundAmount: z.coerce.number().min(0, '退款金额不能小于0').max(999999.99, '退款金额不能超过999999.99').nullable().optional().openapi({
+    description: '退款金额',
+    example: 99.99
+  }),
+  state: z.coerce.number().int().min(0, '状态最小为0').max(3, '状态最大为3').default(0).optional().openapi({
+    description: '0未退款1退款中2退款成功3退款失败',
+    example: 0
+  }),
+  remark: z.string().max(255, '备注最多255个字符').nullable().optional().openapi({
+    description: '备注',
+    example: '用户申请退款'
+  })
+});
+
+// 更新订单退款DTO
+export const UpdateOrderRefundDto = z.object({
+  orderNo: z.string().max(32, '订单号最多32个字符').nullable().optional().openapi({
+    description: '订单号',
+    example: 'ORD20240101123456'
+  }),
+  refundOrderNo: z.string().max(32, '退款订单号最多32个字符').nullable().optional().openapi({
+    description: '退款订单号',
+    example: 'REF20240101123456'
+  }),
+  refundAmount: z.coerce.number().min(0, '退款金额不能小于0').max(999999.99, '退款金额不能超过999999.99').nullable().optional().openapi({
+    description: '退款金额',
+    example: 99.99
+  }),
+  state: z.coerce.number().int().min(0, '状态最小为0').max(3, '状态最大为3').optional().openapi({
+    description: '0未退款1退款中2退款成功3退款失败',
+    example: 2
+  }),
+  remark: z.string().max(255, '备注最多255个字符').nullable().optional().openapi({
+    description: '备注',
+    example: '退款已完成'
+  })
+});
+
+// 订单退款列表响应
+export const OrderRefundListResponse = z.object({
+  data: z.array(OrderRefundSchema),
+  pagination: z.object({
+    total: z.number().openapi({
+      example: 100,
+      description: '总记录数'
+    }),
+    current: z.number().openapi({
+      example: 1,
+      description: '当前页码'
+    }),
+    pageSize: z.number().openapi({
+      example: 10,
+      description: '每页数量'
+    })
+  })
+});

+ 497 - 0
packages/orders-module/src/schemas/order.schema.ts

@@ -0,0 +1,497 @@
+import { z } from '@hono/zod-openapi';
+
+// 订单状态枚举
+export const OrderStatus = {
+  PENDING: 0, // 未发货
+  SHIPPED: 1, // 已发货
+  RECEIVED: 2, // 收货成功
+  RETURNED: 3, // 已退货
+} as const;
+
+// 支付状态枚举
+export const PayStatus = {
+  UNPAID: 0, // 未支付
+  PAYING: 1, // 支付中
+  SUCCESS: 2, // 支付成功
+  REFUNDED: 3, // 已退款
+  FAILED: 4, // 支付失败
+  CLOSED: 5, // 订单关闭
+} as const;
+
+// 订单类型枚举
+export const OrderType = {
+  PHYSICAL: 1, // 实物订单
+  VIRTUAL: 2, // 虚拟订单
+} as const;
+
+// 支付类型枚举
+export const PayType = {
+  POINTS: 1, // 积分
+  COUPON: 2, // 礼券
+} as const;
+
+// 订单基础Schema
+export const OrderSchema = z.object({
+  id: z.number().int().positive().openapi({
+    description: '订单ID',
+    example: 1
+  }),
+  orderNo: z.string().min(1, '订单号不能为空').max(50, '订单号最多50个字符').openapi({
+    description: '订单号',
+    example: 'ORD20240101123456'
+  }),
+  userId: z.number().int().positive().openapi({
+    description: '用户ID',
+    example: 1
+  }),
+  authCode: z.string().max(32, '付款码最多32个字符').nullable().optional().openapi({
+    description: '付款码',
+    example: '12345678901234567890123456789012'
+  }),
+  cardNo: z.string().max(32, '卡号最多32个字符').nullable().optional().openapi({
+    description: '卡号',
+    example: '6222********1234'
+  }),
+  sjtCardNo: z.string().max(32, '盛京通卡号最多32个字符').nullable().optional().openapi({
+    description: '盛京通卡号',
+    example: 'SJT1234567890'
+  }),
+  amount: z.coerce.number().min(0, '订单金额不能小于0').max(999999.99, '订单金额不能超过999999.99').openapi({
+    description: '订单金额',
+    example: 99.99
+  }),
+  costAmount: z.coerce.number().min(0, '成本金额不能小于0').max(999999.99, '成本金额不能超过999999.99').default(0).openapi({
+    description: '成本金额',
+    example: 50.00
+  }),
+  freightAmount: z.coerce.number().min(0, '运费不能小于0').max(999999.99, '运费不能超过999999.99').default(0).openapi({
+    description: '运费',
+    example: 10.00
+  }),
+  discountAmount: z.coerce.number().min(0, '优惠金额不能小于0').max(999999.99, '优惠金额不能超过999999.99').default(0).openapi({
+    description: '优惠金额',
+    example: 5.00
+  }),
+  payAmount: z.coerce.number().min(0, '实际支付金额不能小于0').max(999999.99, '实际支付金额不能超过999999.99').default(0).openapi({
+    description: '实际支付金额',
+    example: 94.99
+  }),
+  deviceNo: z.string().max(255, '设备编号最多255个字符').nullable().optional().openapi({
+    description: '设备编号',
+    example: 'DEV001234'
+  }),
+  description: z.string().max(255, '订单描述最多255个字符').nullable().optional().openapi({
+    description: '订单描述',
+    example: '购买商品'
+  }),
+  goodsDetail: z.string().max(2000, '订单详情最多2000个字符').nullable().optional().openapi({
+    description: '订单详情(json格式)',
+    example: '[{"goodsId":1,"name":"商品1","price":99.99,"num":1}]'
+  }),
+  goodsTag: z.string().max(255, '订单优惠标记最多255个字符').nullable().optional().openapi({
+    description: '订单优惠标记',
+    example: '满100减5'
+  }),
+  address: z.string().max(255, '地址最多255个字符').nullable().optional().openapi({
+    description: '地址',
+    example: '北京市朝阳区xxx路xxx号'
+  }),
+  orderType: z.coerce.number().int().min(1, '订单类型最小为1').max(2, '订单类型最大为2').default(1).openapi({
+    description: '订单类型 1实物订单 2虚拟订单',
+    example: 1
+  }),
+  payType: z.coerce.number().int().min(0, '支付类型最小为0').max(2, '支付类型最大为2').default(0).openapi({
+    description: '支付类型1积分2礼券',
+    example: 1
+  }),
+  payState: z.coerce.number().int().min(0, '支付状态最小为0').max(5, '支付状态最大为5').default(0).openapi({
+    description: '支付状态 0未支付1支付中2支付成功3已退款4支付失败5订单关闭',
+    example: 2
+  }),
+  state: z.coerce.number().int().min(0, '订单状态最小为0').max(3, '订单状态最大为3').default(0).openapi({
+    description: '订单状态 0未发货1已发货2收货成功3已退货',
+    example: 0
+  }),
+  userPhone: z.string().max(50, '用户手机号最多50个字符').nullable().optional().openapi({
+    description: '用户手机号',
+    example: '13800138000'
+  }),
+  merchantId: z.coerce.number().int().positive().default(0).openapi({
+    description: '商户id',
+    example: 1
+  }),
+  merchantNo: z.coerce.number().int().positive().nullable().optional().openapi({
+    description: '商户号',
+    example: 1001
+  }),
+  supplierId: z.coerce.number().int().positive().default(0).openapi({
+    description: '供货商id',
+    example: 1
+  }),
+  addressId: z.coerce.number().int().positive().default(0).openapi({
+    description: '地址id',
+    example: 1
+  }),
+  receiverMobile: z.string().max(255, '收货人手机号最多255个字符').nullable().optional().openapi({
+    description: '收货人手机号',
+    example: '13800138000'
+  }),
+  recevierName: z.string().max(255, '收货人姓名最多255个字符').nullable().optional().openapi({
+    description: '收货人姓名',
+    example: '张三'
+  }),
+  recevierProvince: z.coerce.number().int().positive().default(0).openapi({
+    description: '收货人所在省',
+    example: 110000
+  }),
+  recevierCity: z.coerce.number().int().positive().default(0).openapi({
+    description: '收货人所在市',
+    example: 110100
+  }),
+  recevierDistrict: z.coerce.number().int().positive().default(0).openapi({
+    description: '收货人所在区',
+    example: 110105
+  }),
+  recevierTown: z.coerce.number().int().positive().default(0).openapi({
+    description: '收货人所在街道',
+    example: 110105001
+  }),
+  refundTime: z.coerce.date().nullable().optional().openapi({
+    description: '退款时间',
+    example: '2024-01-01T12:00:00Z'
+  }),
+  closeTime: z.coerce.date().nullable().optional().openapi({
+    description: '订单关闭时间',
+    example: '2024-01-01T12:00:00Z'
+  }),
+  remark: z.string().max(255, '管理员备注信息最多255个字符').nullable().optional().openapi({
+    description: '管理员备注信息',
+    example: '请尽快发货'
+  }),
+  createdBy: z.number().int().positive().nullable().optional().openapi({
+    description: '创建人ID',
+    example: 1
+  }),
+  updatedBy: z.number().int().positive().nullable().optional().openapi({
+    description: '更新人ID',
+    example: 1
+  }),
+  createdAt: z.coerce.date().openapi({
+    description: '创建时间',
+    example: '2024-01-01T12:00:00Z'
+  }),
+  updatedAt: z.coerce.date().openapi({
+    description: '更新时间',
+    example: '2024-01-01T12:00:00Z'
+  }),
+  // 关联实体
+  user: z.object({
+    id: z.number().int().positive().openapi({ description: '用户ID' }),
+    username: z.string().openapi({ description: '用户名', example: 'user123' }),
+    phone: z.string().nullable().openapi({ description: '手机号', example: '13800138000' })
+  }).nullable().optional().openapi({
+    description: '用户信息'
+  }),
+  merchant: z.object({
+    id: z.number().int().positive().openapi({ description: '商户ID' }),
+    name: z.string().openapi({ description: '商户名称', example: '商户A' })
+  }).nullable().optional().openapi({
+    description: '商户信息'
+  }),
+  supplier: z.object({
+    id: z.number().int().positive().openapi({ description: '供货商ID' }),
+    name: z.string().openapi({ description: '供货商名称', example: '供货商A' })
+  }).nullable().optional().openapi({
+    description: '供货商信息'
+  }),
+  deliveryAddress: z.object({
+    id: z.number().int().positive().openapi({ description: '地址ID' }),
+    name: z.string().openapi({ description: '收货人姓名', example: '张三' }),
+    phone: z.string().openapi({ description: '收货人电话', example: '13800138000' }),
+    address: z.string().openapi({ description: '详细地址', example: '北京市朝阳区xxx路xxx号' })
+  }).nullable().optional().openapi({
+    description: '收货地址信息'
+  })
+});
+
+// 创建订单DTO
+export const CreateOrderDto = z.object({
+  orderNo: z.string().min(1, '订单号不能为空').max(50, '订单号最多50个字符').openapi({
+    description: '订单号',
+    example: 'ORD20240101123456'
+  }),
+  userId: z.number().int().positive('用户ID必须是正整数').openapi({
+    description: '用户ID',
+    example: 1
+  }),
+  authCode: z.string().max(32, '付款码最多32个字符').nullable().optional().openapi({
+    description: '付款码',
+    example: '12345678901234567890123456789012'
+  }),
+  cardNo: z.string().max(32, '卡号最多32个字符').nullable().optional().openapi({
+    description: '卡号',
+    example: '6222********1234'
+  }),
+  sjtCardNo: z.string().max(32, '盛京通卡号最多32个字符').nullable().optional().openapi({
+    description: '盛京通卡号',
+    example: 'SJT1234567890'
+  }),
+  amount: z.coerce.number().min(0, '订单金额不能小于0').max(999999.99, '订单金额不能超过999999.99').openapi({
+    description: '订单金额',
+    example: 99.99
+  }),
+  costAmount: z.coerce.number().min(0, '成本金额不能小于0').max(999999.99, '成本金额不能超过999999.99').default(0).optional().openapi({
+    description: '成本金额',
+    example: 50.00
+  }),
+  freightAmount: z.coerce.number().min(0, '运费不能小于0').max(999999.99, '运费不能超过999999.99').default(0).optional().openapi({
+    description: '运费',
+    example: 10.00
+  }),
+  discountAmount: z.coerce.number().min(0, '优惠金额不能小于0').max(999999.99, '优惠金额不能超过999999.99').default(0).optional().openapi({
+    description: '优惠金额',
+    example: 5.00
+  }),
+  payAmount: z.coerce.number().min(0, '实际支付金额不能小于0').max(999999.99, '实际支付金额不能超过999999.99').default(0).optional().openapi({
+    description: '实际支付金额',
+    example: 94.99
+  }),
+  deviceNo: z.string().max(255, '设备编号最多255个字符').nullable().optional().openapi({
+    description: '设备编号',
+    example: 'DEV001234'
+  }),
+  description: z.string().max(255, '订单描述最多255个字符').nullable().optional().openapi({
+    description: '订单描述',
+    example: '购买商品'
+  }),
+  goodsDetail: z.string().max(2000, '订单详情最多2000个字符').nullable().optional().openapi({
+    description: '订单详情(json格式)',
+    example: '[{"goodsId":1,"name":"商品1","price":99.99,"num":1}]'
+  }),
+  goodsTag: z.string().max(255, '订单优惠标记最多255个字符').nullable().optional().openapi({
+    description: '订单优惠标记',
+    example: '满100减5'
+  }),
+  address: z.string().max(255, '地址最多255个字符').nullable().optional().openapi({
+    description: '地址',
+    example: '北京市朝阳区xxx路xxx号'
+  }),
+  orderType: z.coerce.number().int().min(1, '订单类型最小为1').max(2, '订单类型最大为2').default(1).openapi({
+    description: '订单类型 1实物订单 2虚拟订单',
+    example: 1
+  }),
+  payType: z.coerce.number().int().min(0, '支付类型最小为0').max(2, '支付类型最大为2').default(0).openapi({
+    description: '支付类型1积分2礼券',
+    example: 1
+  }),
+  payState: z.coerce.number().int().min(0, '支付状态最小为0').max(5, '支付状态最大为5').default(0).openapi({
+    description: '支付状态 0未支付1支付中2支付成功3已退款4支付失败5订单关闭',
+    example: 2
+  }),
+  state: z.coerce.number().int().min(0, '订单状态最小为0').max(3, '订单状态最大为3').default(0).openapi({
+    description: '订单状态 0未发货1已发货2收货成功3已退货',
+    example: 0
+  }),
+  userPhone: z.string().max(50, '用户手机号最多50个字符').nullable().optional().openapi({
+    description: '用户手机号',
+    example: '13800138000'
+  }),
+  merchantId: z.coerce.number().int().positive().default(0).openapi({
+    description: '商户id',
+    example: 1
+  }),
+  merchantNo: z.coerce.number().int().positive().nullable().optional().openapi({
+    description: '商户号',
+    example: 1001
+  }),
+  supplierId: z.coerce.number().int().positive().default(0).openapi({
+    description: '供货商id',
+    example: 1
+  }),
+  addressId: z.coerce.number().int().positive().default(0).openapi({
+    description: '地址id',
+    example: 1
+  }),
+  receiverMobile: z.string().max(255, '收货人手机号最多255个字符').nullable().optional().openapi({
+    description: '收货人手机号',
+    example: '13800138000'
+  }),
+  recevierName: z.string().max(255, '收货人姓名最多255个字符').nullable().optional().openapi({
+    description: '收货人姓名',
+    example: '张三'
+  }),
+  recevierProvince: z.coerce.number().int().positive().default(0).openapi({
+    description: '收货人所在省',
+    example: 110000
+  }),
+  recevierCity: z.coerce.number().int().positive().default(0).openapi({
+    description: '收货人所在市',
+    example: 110100
+  }),
+  recevierDistrict: z.coerce.number().int().positive().default(0).openapi({
+    description: '收货人所在区',
+    example: 110105
+  }),
+  recevierTown: z.coerce.number().int().positive().default(0).openapi({
+    description: '收货人所在街道',
+    example: 110105001
+  }),
+  refundTime: z.coerce.date().nullable().optional().openapi({
+    description: '退款时间',
+    example: '2024-01-01T12:00:00Z'
+  }),
+  closeTime: z.coerce.date().nullable().optional().openapi({
+    description: '订单关闭时间',
+    example: '2024-01-01T12:00:00Z'
+  }),
+  remark: z.string().max(255, '管理员备注信息最多255个字符').nullable().optional().openapi({
+    description: '管理员备注信息',
+    example: '请尽快发货'
+  })
+});
+
+// 更新订单DTO
+export const UpdateOrderDto = z.object({
+  orderNo: z.string().min(1, '订单号不能为空').max(50, '订单号最多50个字符').optional().openapi({
+    description: '订单号',
+    example: 'ORD20240101123456'
+  }),
+  userId: z.number().int().positive('用户ID必须是正整数').optional().openapi({
+    description: '用户ID',
+    example: 1
+  }),
+  authCode: z.string().max(32, '付款码最多32个字符').nullable().optional().openapi({
+    description: '付款码',
+    example: '12345678901234567890123456789012'
+  }),
+  cardNo: z.string().max(32, '卡号最多32个字符').nullable().optional().openapi({
+    description: '卡号',
+    example: '6222********1234'
+  }),
+  sjtCardNo: z.string().max(32, '盛京通卡号最多32个字符').nullable().optional().openapi({
+    description: '盛京通卡号',
+    example: 'SJT1234567890'
+  }),
+  amount: z.coerce.number().min(0, '订单金额不能小于0').max(999999.99, '订单金额不能超过999999.99').optional().openapi({
+    description: '订单金额',
+    example: 99.99
+  }),
+  costAmount: z.coerce.number().min(0, '成本金额不能小于0').max(999999.99, '成本金额不能超过999999.99').optional().openapi({
+    description: '成本金额',
+    example: 50.00
+  }),
+  freightAmount: z.coerce.number().min(0, '运费不能小于0').max(999999.99, '运费不能超过999999.99').optional().openapi({
+    description: '运费',
+    example: 10.00
+  }),
+  discountAmount: z.coerce.number().min(0, '优惠金额不能小于0').max(999999.99, '优惠金额不能超过999999.99').optional().openapi({
+    description: '优惠金额',
+    example: 5.00
+  }),
+  payAmount: z.coerce.number().min(0, '实际支付金额不能小于0').max(999999.99, '实际支付金额不能超过999999.99').optional().openapi({
+    description: '实际支付金额',
+    example: 94.99
+  }),
+  deviceNo: z.string().max(255, '设备编号最多255个字符').nullable().optional().openapi({
+    description: '设备编号',
+    example: 'DEV001234'
+  }),
+  description: z.string().max(255, '订单描述最多255个字符').nullable().optional().openapi({
+    description: '订单描述',
+    example: '购买商品'
+  }),
+  goodsDetail: z.string().max(2000, '订单详情最多2000个字符').nullable().optional().openapi({
+    description: '订单详情(json格式)',
+    example: '[{"goodsId":1,"name":"商品1","price":99.99,"num":1}]'
+  }),
+  goodsTag: z.string().max(255, '订单优惠标记最多255个字符').nullable().optional().openapi({
+    description: '订单优惠标记',
+    example: '满100减5'
+  }),
+  address: z.string().max(255, '地址最多255个字符').nullable().optional().openapi({
+    description: '地址',
+    example: '北京市朝阳区xxx路xxx号'
+  }),
+  orderType: z.coerce.number().int().min(1, '订单类型最小为1').max(2, '订单类型最大为2').optional().openapi({
+    description: '订单类型 1实物订单 2虚拟订单',
+    example: 1
+  }),
+  payType: z.coerce.number().int().min(0, '支付类型最小为0').max(2, '支付类型最大为2').optional().openapi({
+    description: '支付类型1积分2礼券',
+    example: 1
+  }),
+  payState: z.coerce.number().int().min(0, '支付状态最小为0').max(5, '支付状态最大为5').optional().openapi({
+    description: '支付状态 0未支付1支付中2支付成功3已退款4支付失败5订单关闭',
+    example: 2
+  }),
+  state: z.coerce.number().int().min(0, '订单状态最小为0').max(3, '订单状态最大为3').optional().openapi({
+    description: '订单状态 0未发货1已发货2收货成功3已退货',
+    example: 0
+  }),
+  userPhone: z.string().max(50, '用户手机号最多50个字符').nullable().optional().openapi({
+    description: '用户手机号',
+    example: '13800138000'
+  }),
+  merchantId: z.coerce.number().int().positive().optional().openapi({
+    description: '商户id',
+    example: 1
+  }),
+  merchantNo: z.coerce.number().int().positive().nullable().optional().openapi({
+    description: '商户号',
+    example: 1001
+  }),
+  supplierId: z.coerce.number().int().positive().optional().openapi({
+    description: '供货商id',
+    example: 1
+  }),
+  addressId: z.coerce.number().int().positive().optional().openapi({
+    description: '地址id',
+    example: 1
+  }),
+  receiverMobile: z.string().max(255, '收货人手机号最多255个字符').nullable().optional().openapi({
+    description: '收货人手机号',
+    example: '13800138000'
+  }),
+  recevierName: z.string().max(255, '收货人姓名最多255个字符').nullable().optional().openapi({
+    description: '收货人姓名',
+    example: '张三'
+  }),
+  recevierProvince: z.coerce.number().int().positive().optional().openapi({
+    description: '收货人所在省',
+    example: 110000
+  }),
+  recevierCity: z.coerce.number().int().positive().optional().openapi({
+    description: '收货人所在市',
+    example: 110100
+  }),
+  recevierDistrict: z.coerce.number().int().positive().optional().openapi({
+    description: '收货人所在区',
+    example: 110105
+  }),
+  recevierTown: z.coerce.number().int().positive().optional().openapi({
+    description: '收货人所在街道',
+    example: 110105001
+  }),
+  refundTime: z.coerce.date().nullable().optional().openapi({
+    description: '退款时间',
+    example: '2024-01-01T12:00:00Z'
+  }),
+  closeTime: z.coerce.date().nullable().optional().openapi({
+    description: '订单关闭时间',
+    example: '2024-01-01T12:00:00Z'
+  }),
+  remark: z.string().max(255, '管理员备注信息最多255个字符').nullable().optional().openapi({
+    description: '管理员备注信息',
+    example: '请尽快发货'
+  })
+});
+
+// 订单列表响应Schema
+export const OrderListResponse = z.object({
+  data: z.array(OrderSchema),
+  pagination: z.object({
+    total: z.number().openapi({ example: 100, description: '总记录数' }),
+    current: z.number().openapi({ example: 1, description: '当前页码' }),
+    pageSize: z.number().openapi({ example: 10, description: '每页数量' })
+  })
+});

+ 3 - 0
packages/orders-module/src/services/index.ts

@@ -0,0 +1,3 @@
+export { OrderService } from './order.service';
+export { OrderGoodsService } from './order-goods.service';
+export { OrderRefundService } from './order-refund.service';

+ 9 - 0
packages/orders-module/src/services/order-goods.service.ts

@@ -0,0 +1,9 @@
+import { GenericCrudService } from '@d8d/shared-crud';
+import { DataSource } from 'typeorm';
+import { OrderGoods } from '../entities/order-goods.entity';
+
+export class OrderGoodsService extends GenericCrudService<OrderGoods> {
+  constructor(dataSource: DataSource) {
+    super(dataSource, OrderGoods);
+  }
+}

+ 9 - 0
packages/orders-module/src/services/order-refund.service.ts

@@ -0,0 +1,9 @@
+import { GenericCrudService } from '@d8d/shared-crud';
+import { DataSource } from 'typeorm';
+import { OrderRefund } from '../entities/order-refund.entity';
+
+export class OrderRefundService extends GenericCrudService<OrderRefund> {
+  constructor(dataSource: DataSource) {
+    super(dataSource, OrderRefund);
+  }
+}

+ 180 - 0
packages/orders-module/src/services/order.service.ts

@@ -0,0 +1,180 @@
+import { GenericCrudService } from '@d8d/shared-crud';
+import { DataSource, Repository } from 'typeorm';
+import { Order } from '../entities/order.entity';
+import { OrderGoods } from '../entities/order-goods.entity';
+import { Goods } from '@d8d/goods-module';
+import { DeliveryAddress } from '@d8d/delivery-address-module';
+import type { CreateOrderRequest } from '../schemas/create-order.schema';
+
+export class OrderService extends GenericCrudService<Order> {
+  private orderGoodsRepository: Repository<OrderGoods>;
+  private goodsRepository: Repository<Goods>;
+  private deliveryAddressRepository: Repository<DeliveryAddress>;
+
+  constructor(dataSource: DataSource) {
+    super(dataSource, Order);
+    this.orderGoodsRepository = dataSource.getRepository(OrderGoods);
+    this.goodsRepository = dataSource.getRepository(Goods);
+    this.deliveryAddressRepository = dataSource.getRepository(DeliveryAddress);
+  }
+
+  /**
+   * 创建订单
+   * @param data 创建订单请求数据
+   * @param userId 用户ID
+   * @returns 创建的订单信息
+   */
+  async createOrder(data: CreateOrderRequest, userId: number): Promise<{
+    orderId: number;
+    orderNo: string;
+    amount: number;
+    payAmount: number;
+  }> {
+    const queryRunner = this.dataSource.createQueryRunner();
+    await queryRunner.connect();
+    await queryRunner.startTransaction();
+
+    try {
+      const { addressId, productOwn, consumeFrom, products } = data;
+
+      // 验证商品信息并计算总价
+      let totalAmount = 0;
+      let totalCostAmount = 0;
+      const goodsInfo = [];
+
+      for (const item of products) {
+        const goods = await this.goodsRepository.findOne({
+          where: { id: item.id }
+        });
+
+        if (!goods) {
+          throw new Error(`商品ID ${item.id} 不存在`);
+        }
+
+        if (goods.stock < item.num) {
+          throw new Error(`商品 ${goods.name} 库存不足`);
+        }
+
+        const itemAmount = goods.price * item.num;
+        const itemCostAmount = goods.costPrice * item.num;
+
+        totalAmount += itemAmount;
+        totalCostAmount += itemCostAmount;
+
+        goodsInfo.push({
+          goods,
+          quantity: item.num,
+          amount: itemAmount,
+          costAmount: itemCostAmount
+        });
+      }
+
+      // 获取收货地址信息
+      let deliveryAddress = null;
+      if (addressId) {
+        deliveryAddress = await this.deliveryAddressRepository.findOne({
+          where: { id: addressId, userId }
+        });
+
+        if (!deliveryAddress) {
+          throw new Error('收货地址不存在');
+        }
+      }
+
+      // 生成订单号
+      const orderNo = this.generateOrderNo();
+
+      // 创建订单
+      const order = this.repository.create({
+        orderNo,
+        userId,
+        amount: totalAmount,
+        costAmount: totalCostAmount,
+        payAmount: totalAmount, // 这里可以根据优惠规则计算实际支付金额
+        orderType: 1, // 实物订单
+        payType: consumeFrom === '积分兑换' ? 1 : 2, // 根据消费来源设置支付类型
+        payState: 0, // 未支付
+        state: 0, // 未发货
+        addressId: addressId || 0,
+        merchantId: goodsInfo[0]?.goods.merchantId || 0,
+        supplierId: goodsInfo[0]?.goods.supplierId || 0,
+        createdBy: userId,
+        updatedBy: userId,
+        // 设置收货地址信息(如果提供)
+        ...(deliveryAddress && {
+          receiverMobile: deliveryAddress.phone,
+          recevierName: deliveryAddress.name,
+          recevierProvince: deliveryAddress.receiverProvince,
+          recevierCity: deliveryAddress.receiverCity,
+          recevierDistrict: deliveryAddress.receiverDistrict,
+          recevierTown: deliveryAddress.receiverTown,
+          address: deliveryAddress.address
+        })
+      });
+
+      const savedOrder = await queryRunner.manager.save(order);
+
+      // 创建订单商品明细
+      const orderGoodsList = goodsInfo.map(info => ({
+        orderId: savedOrder.id,
+        orderNo,
+        goodsId: info.goods.id,
+        goodsName: info.goods.name,
+        imageFileId: info.goods.imageFileId,
+        goodsType: info.goods.goodsType,
+        supplierId: info.goods.supplierId,
+        costPrice: info.goods.costPrice,
+        price: info.goods.price,
+        num: info.quantity,
+        freightAmount: 0,
+        state: 0,
+        createdBy: userId,
+        updatedBy: userId,
+        expressName: null,
+        expressNo: null
+      }));
+
+      await queryRunner.manager.save(OrderGoods, orderGoodsList);
+
+      // 更新商品库存
+      for (const item of goodsInfo) {
+        await queryRunner.manager.update(Goods, item.goods.id, {
+          stock: () => `stock - ${item.quantity}`,
+          salesNum: () => `sales_num + ${item.quantity}`
+        });
+      }
+
+      await queryRunner.commitTransaction();
+
+      return {
+        orderId: savedOrder.id,
+        orderNo: savedOrder.orderNo,
+        amount: savedOrder.amount,
+        payAmount: savedOrder.payAmount
+      };
+
+    } catch (error) {
+      await queryRunner.rollbackTransaction();
+      throw error;
+    } finally {
+      await queryRunner.release();
+    }
+  }
+
+  /**
+   * 生成订单号
+   * 格式:年月日时分秒 + 6位随机数
+   */
+  private generateOrderNo(): string {
+    const now = new Date();
+    const year = now.getFullYear();
+    const month = String(now.getMonth() + 1).padStart(2, '0');
+    const day = String(now.getDate()).padStart(2, '0');
+    const hour = String(now.getHours()).padStart(2, '0');
+    const minute = String(now.getMinutes()).padStart(2, '0');
+    const second = String(now.getSeconds()).padStart(2, '0');
+    const random = String(Math.floor(Math.random() * 1000000)).padStart(6, '0');
+
+    return `ORD${year}${month}${day}${hour}${minute}${second}${random}`;
+  }
+}

+ 1 - 0
packages/orders-module/src/types/index.ts

@@ -0,0 +1 @@
+export * from './order.types';

+ 66 - 0
packages/orders-module/src/types/order.types.ts

@@ -0,0 +1,66 @@
+import { OrderStatus, PayStatus, OrderType, PayType } from '../schemas/order.schema';
+import { OrderGoodsStatus, GoodsType } from '../schemas/order-goods.schema';
+import { RefundStatus } from '../schemas/order-refund.schema';
+
+// 订单状态类型
+export type OrderStatusType = typeof OrderStatus[keyof typeof OrderStatus];
+export type PayStatusType = typeof PayStatus[keyof typeof PayStatus];
+export type OrderTypeType = typeof OrderType[keyof typeof OrderType];
+export type PayTypeType = typeof PayType[keyof typeof PayType];
+
+// 订单商品状态类型
+export type OrderGoodsStatusType = typeof OrderGoodsStatus[keyof typeof OrderGoodsStatus];
+export type GoodsTypeType = typeof GoodsType[keyof typeof GoodsType];
+
+// 退款状态类型
+export type RefundStatusType = typeof RefundStatus[keyof typeof RefundStatus];
+
+// 订单相关类型
+export interface OrderQueryParams {
+  page?: number;
+  pageSize?: number;
+  userId?: number;
+  orderNo?: string;
+  state?: OrderStatusType;
+  payState?: PayStatusType;
+  startDate?: string;
+  endDate?: string;
+}
+
+// 订单统计类型
+export interface OrderStats {
+  totalOrders: number;
+  totalAmount: number;
+  pendingOrders: number;
+  completedOrders: number;
+  refundOrders: number;
+}
+
+// 订单创建结果类型
+export interface OrderCreateResult {
+  success: boolean;
+  orderId: number;
+  orderNo: string;
+  amount: number;
+  payAmount: number;
+  message: string;
+}
+
+// 订单商品信息类型
+export interface OrderGoodsInfo {
+  goodsId: number;
+  goodsName: string;
+  price: number;
+  num: number;
+  totalAmount: number;
+}
+
+// 订单详情类型
+export interface OrderDetail {
+  order: any; // Order 实体类型
+  orderGoods: any[]; // OrderGoods 实体类型数组
+  user?: any; // User 实体类型
+  merchant?: any; // Merchant 实体类型
+  supplier?: any; // Supplier 实体类型
+  deliveryAddress?: any; // DeliveryAddress 实体类型
+}

+ 16 - 0
packages/orders-module/tsconfig.json

@@ -0,0 +1,16 @@
+{
+  "extends": "../../tsconfig.json",
+  "compilerOptions": {
+    "composite": true,
+    "rootDir": ".",
+    "outDir": "dist"
+  },
+  "include": [
+    "src/**/*",
+    "tests/**/*"
+  ],
+  "exclude": [
+    "node_modules",
+    "dist"
+  ]
+}

+ 21 - 0
packages/orders-module/vitest.config.ts

@@ -0,0 +1,21 @@
+import { defineConfig } from 'vitest/config';
+
+export default defineConfig({
+  test: {
+    globals: true,
+    environment: 'node',
+    include: ['tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
+    coverage: {
+      provider: 'v8',
+      reporter: ['text', 'json', 'html'],
+      exclude: [
+        'tests/**',
+        '**/*.d.ts',
+        '**/*.config.*',
+        '**/dist/**'
+      ]
+    },
+    // 关闭并行测试以避免数据库连接冲突
+    fileParallelism: false
+  }
+});