Browse Source

fix: 前后端分页格式对齐,所有列表接口统一返回PageResponse

- 50个Controller分页接口统一返回PageResponse{items,totalElements,page,size}
- InventoryController lock/unlock/increment从@RequestParam改为@RequestBody
- 新增InventoryOperationRequest DTO
- 6个Service新增getPage()分页方法
- 前端API lock/unlock/increment发送JSON body
- 清理旧文档

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Jax Docker 3 weeks ago
parent
commit
ac952c9887
62 changed files with 332 additions and 1675 deletions
  1. 0 260
      ALIGNMENT_COMPLETE.md
  2. 0 320
      ENUM_FIX_COMPLETE.md
  3. 0 160
      ENUM_FIX_GUIDE.md
  4. 0 267
      FRONTEND_BACKEND_ALIGNMENT_CHECK.md
  5. 0 342
      PAGINATION_FIX_COMPLETE.md
  6. 5 2
      backend/src/main/java/com/oms/controller/AiChannelController.java
  7. 5 2
      backend/src/main/java/com/oms/controller/AutoReplyRuleController.java
  8. 5 2
      backend/src/main/java/com/oms/controller/ChannelController.java
  9. 5 2
      backend/src/main/java/com/oms/controller/ChannelMappingController.java
  10. 7 2
      backend/src/main/java/com/oms/controller/ChatLogController.java
  11. 5 2
      backend/src/main/java/com/oms/controller/ChatMessageController.java
  12. 5 2
      backend/src/main/java/com/oms/controller/ChatSessionController.java
  13. 5 2
      backend/src/main/java/com/oms/controller/CouponController.java
  14. 5 2
      backend/src/main/java/com/oms/controller/FinancePaymentController.java
  15. 5 2
      backend/src/main/java/com/oms/controller/FinanceRefundController.java
  16. 12 20
      backend/src/main/java/com/oms/controller/InventoryController.java
  17. 8 2
      backend/src/main/java/com/oms/controller/InventoryLogController.java
  18. 5 2
      backend/src/main/java/com/oms/controller/InventoryTurnoverController.java
  19. 5 2
      backend/src/main/java/com/oms/controller/InvoiceController.java
  20. 4 2
      backend/src/main/java/com/oms/controller/IqcController.java
  21. 5 2
      backend/src/main/java/com/oms/controller/KnowledgeBaseController.java
  22. 5 2
      backend/src/main/java/com/oms/controller/KnowledgeCategoryController.java
  23. 5 2
      backend/src/main/java/com/oms/controller/LogisticsProviderController.java
  24. 5 2
      backend/src/main/java/com/oms/controller/PriceWatchController.java
  25. 7 2
      backend/src/main/java/com/oms/controller/PricingRuleController.java
  26. 5 2
      backend/src/main/java/com/oms/controller/ProductCategoryController.java
  27. 5 2
      backend/src/main/java/com/oms/controller/ProductSkuController.java
  28. 5 2
      backend/src/main/java/com/oms/controller/PromotionController.java
  29. 5 2
      backend/src/main/java/com/oms/controller/PurchaseOrderController.java
  30. 7 2
      backend/src/main/java/com/oms/controller/PurchaseRequestController.java
  31. 7 2
      backend/src/main/java/com/oms/controller/ReplenishmentPlanController.java
  32. 7 2
      backend/src/main/java/com/oms/controller/ReportController.java
  33. 8 2
      backend/src/main/java/com/oms/controller/ReportDataController.java
  34. 5 2
      backend/src/main/java/com/oms/controller/ReturnPackageController.java
  35. 7 2
      backend/src/main/java/com/oms/controller/SatisfactionController.java
  36. 5 2
      backend/src/main/java/com/oms/controller/ServicePerformanceController.java
  37. 5 2
      backend/src/main/java/com/oms/controller/ShippingOrderController.java
  38. 5 2
      backend/src/main/java/com/oms/controller/ShippingTemplateController.java
  39. 5 2
      backend/src/main/java/com/oms/controller/SupplierController.java
  40. 5 2
      backend/src/main/java/com/oms/controller/SupplierPerformanceController.java
  41. 5 2
      backend/src/main/java/com/oms/controller/SupplierSettlementController.java
  42. 7 2
      backend/src/main/java/com/oms/controller/SupplyCapabilityController.java
  43. 4 2
      backend/src/main/java/com/oms/controller/SysApiKeyController.java
  44. 5 2
      backend/src/main/java/com/oms/controller/SysApprovalFlowController.java
  45. 5 2
      backend/src/main/java/com/oms/controller/SysDepartmentController.java
  46. 5 2
      backend/src/main/java/com/oms/controller/SysEmployeeController.java
  47. 5 2
      backend/src/main/java/com/oms/controller/SysMessageTemplateController.java
  48. 4 2
      backend/src/main/java/com/oms/controller/SysNotificationController.java
  49. 4 2
      backend/src/main/java/com/oms/controller/SysOperationLogController.java
  50. 4 2
      backend/src/main/java/com/oms/controller/SysRoleController.java
  51. 4 2
      backend/src/main/java/com/oms/controller/SysUserController.java
  52. 7 2
      backend/src/main/java/com/oms/controller/TicketController.java
  53. 5 2
      backend/src/main/java/com/oms/controller/WarehouseController.java
  54. 12 0
      backend/src/main/java/com/oms/dto/InventoryOperationRequest.java
  55. 9 0
      backend/src/main/java/com/oms/service/ChatLogService.java
  56. 9 0
      backend/src/main/java/com/oms/service/PricingRuleService.java
  57. 8 0
      backend/src/main/java/com/oms/service/ReportDataService.java
  58. 9 0
      backend/src/main/java/com/oms/service/ReportService.java
  59. 8 0
      backend/src/main/java/com/oms/service/SatisfactionService.java
  60. 9 0
      backend/src/main/java/com/oms/service/TicketService.java
  61. 0 207
      design-system.md
  62. 5 5
      frontend/src/api/services.ts

+ 0 - 260
ALIGNMENT_COMPLETE.md

@@ -1,260 +0,0 @@
-# 前后端对齐完成报告
-
-## 完成时间
-2026-04-21
-
----
-
-## ✅ 已完成的修复
-
-### 1. 核心类型对齐
-
-#### ID字段类型统一
-```typescript
-// ✅ 修复: 统一使用 number 类型
-export interface OrderItem {
-  id: number;  // 从 string 改为 number
-  channelId?: number;
-  warehouseId?: number;
-  carrierId?: number;
-  handlerId?: number;
-  parentId?: number;
-}
-
-export interface ProductItem {
-  id: number;  // 从 string 改为 number
-}
-```
-
-#### 字段命名统一
-```typescript
-// ✅ 修复: 使用完整字段名
-carrierName?: string;  // 替代 carrier
-handlerName?: string;  // 替代 handler
-warehouseName?: string; // 替代 warehouse
-channelName?: string;   // 替代 channel
-```
-
-#### 添加缺失字段
-```typescript
-// ✅ 订单模块添加:
-channelId?: number;
-warehouseId?: number;
-refundStatus?: string;
-utmSource?: string;
-utmMedium?: string;
-// ... 其他营销归因字段
-
-// ✅ 商品模块添加:
-categoryId: string;  // 使用categoryId而非category
-category?: string;   // 计算字段
-subtitle?: string;
-inventory?: number;
-priceRange?: string;
-```
-
-### 2. 后端DTO增强
-
-#### OrderListDTO.java
-```java
-// ✅ 添加字段:
-private String channelName;      // 渠道名称
-private String refundStatus;      // 退款状态
-private Long warehouseId;         // 仓库ID
-private String warehouseName;     // 仓库名称
-private String carrierName;       // 物流商名称
-private String handlerName;       // 处理人名称
-private String amount;            // 兼容字段
-```
-
-#### ProductDTO.java
-```java
-// ✅ 添加计算字段:
-private String category;          // 分类名称
-private Integer inventory;        // 库存
-private String priceRange;        // 价格区间
-
-// ✅ 添加JSON转换字段:
-private List<String> tagsList;
-private List<Object> specsList;
-private List<Object> imagesList;
-private List<Object> videosList;
-private List<Object> translationsList;
-```
-
-### 3. API路径对齐
-
-| 模块 | 功能 | 后端路径 | 前端调用 | 状态 |
-|------|------|---------|---------|------|
-| 订单 | 列表查询 | GET /api/order/orders | api.getOrders() | ✅ |
-| 订单 | 详情查询 | GET /api/order/orders/{id} | api.getOrder() | ✅ |
-| 订单 | 创建 | POST /api/order/orders | api.createOrder() | ✅ |
-| 订单 | 更新 | PUT /api/order/orders/{id} | api.updateOrder() | ✅ |
-| 订单 | 删除 | DELETE /api/order/orders/{id} | api.deleteOrder() | ✅ |
-| 商品 | 列表查询 | GET /api/product/products | api.getProducts() | ✅ |
-| 商品 | 详情查询 | GET /api/product/products/{id} | api.getProduct() | ✅ |
-| 商品 | 创建 | POST /api/product/products | api.createProduct() | ✅ |
-| 商品 | 更新 | PUT /api/product/products/{id} | api.updateProduct() | ✅ |
-| 商品 | 删除 | DELETE /api/product/products/{id} | api.deleteProduct() | ✅ |
-
-### 4. 分页架构对齐
-
-```typescript
-// ✅ 前端: 正确使用后端分页
-const loadData = async () => {
-  const res = await api.getOrders(page.value, pageSize.value, {
-    keyword: searchKeyword.value || undefined,
-    orderStatus: filters.value.orderStatus || undefined,
-    shippingStatus: filters.value.shippingStatus || undefined,
-    paymentStatus: filters.value.paymentStatus || undefined
-  });
-  items.value = res.items || [];
-  totalElements.value = res.totalElements || 0;
-};
-
-// ✅ 后端: DTO模式简化参数
-@GetMapping
-public PageResponse<OrderListDTO> getOrders(
-    @RequestParam(defaultValue = "1") int page,
-    @RequestParam(defaultValue = "20") int size,
-    @ModelAttribute OrderFilterDTO filters) {
-    // 后端处理筛选和分页
-}
-```
-
----
-
-## ⚠️ 剩余问题(需进一步处理)
-
-### 1. JSON字段序列化(P1优先级)
-
-**问题描述:**
-后端存储为JSON字符串的字段,前端期望是对象数组
-
-**影响字段:**
-```java
-// 后端: String (JSON字符串)
-private String tags;
-private String specs;
-private String images;
-private String videos;
-private String translations;
-
-// 前端期望: 对象数组
-tags?: string[];
-specs?: SpecItem[];
-images?: MediaItem[];
-videos?: MediaItem[];
-translations?: TranslationItem[];
-```
-
-**解决方案:**
-需要在后端Converter中处理JSON序列化/反序列化
-
-### 2. 类型转换问题
-
-**问题描述:**
-前端某些地方仍然期望string类型的ID
-
-**影响位置:**
-- OrderDetailView.vue 584行: 类型不匹配
-- OrderAfterSaleView.vue 359行: 类型不匹配
-
-**解决方案:**
-修改前端组件,使用正确的number类型
-
-### 3. 可选字段处理
-
-**问题描述:**
-某些字段在后端是必需的,前端标记为可选
-
-**示例:**
-```typescript
-receiverName: string;  // 前端必需
-itemCount: number;    // 前端必需
-items: OrderProductItem[];  // 前端必需
-```
-
----
-
-## 📊 对齐完成度
-
-| 模块 | 字段对齐 | 类型对齐 | API对齐 | 总体 |
-|------|---------|---------|---------|------|
-| 订单模块 | 95% | 90% | 100% | 95% |
-| 商品模块 | 90% | 85% | 100% | 92% |
-| **总体** | **93%** | **88%** | **100%** | **93%** |
-
----
-
-## 🎯 验证清单
-
-- ✅ 后端编译成功
-- ✅ 前端类型定义更新
-- ⚠️ 前端构建有小问题(非阻塞性)
-- ✅ API路径完全对齐
-- ✅ 分页架构正确
-- ✅ 枚举值完全对齐
-- ✅ DTO模式应用
-
----
-
-## 📝 下一步工作
-
-### 短期(本次会话)
-1. 修复前端剩余的类型转换问题
-2. 验证订单列表和商品列表功能正常
-
-### 中期(后续优化)
-1. 实现JSON字段序列化Converter
-2. 添加计算字段的业务逻辑
-3. 完善错误处理
-
-### 长期(架构优化)
-1. 考虑使用GraphQL简化前后端对接
-2. 实现OpenAPI规范文档
-3. 添加前端类型生成工具
-
----
-
-## 🔑 关键改进点
-
-### 1. 采用DTO模式
-```java
-// ❌ 之前: 8个参数
-public PageResponse<OrderListDTO> getOrders(
-    int page, int size, String keyword,
-    String orderStatus, String shippingStatus,
-    String paymentStatus, Long channelId,
-    Long warehouseId)
-
-// ✅ 现在: 3个参数
-public PageResponse<OrderListDTO> getOrders(
-    int page, int size,
-    @ModelAttribute OrderFilterDTO filters)
-```
-
-### 2. 类型安全
-```typescript
-// ✅ 统一使用number类型
-id: number;  // 而非 string
-channelId?: number;  // 类型一致
-
-// ✅ 字段命名语义化
-carrierName?: string;  // 而非 carrier
-handlerName?: string;  // 而非 handler
-```
-
-### 3. 向后兼容
-```typescript
-// ✅ 保留兼容字段
-channel?: string;      // 兼容旧代码
-channelName?: string;  // 新字段
-```
-
----
-
-**报告生成时间**: 2026-04-21
-**总体完成度**: 93%
-**核心功能状态**: ✅ 可用
-**建议**: 可以进入测试阶段

+ 0 - 320
ENUM_FIX_COMPLETE.md

@@ -1,320 +0,0 @@
-# 电商OMS 枚举值修复完成报告
-
-## 📊 修复统计
-
-- **总页面数**: 70+ 个 Vue 页面
-- **已修复页面**: 51 个页面
-- **移除隔行换色**: 51 个文件(批量移除 `stripe` 属性)
-- **枚举映射函数**: 50+ 个
-- **新增枚举定义**: 60+ 组
-
----
-
-## ✅ 已完成的修复
-
-### 1. 核心业务模块 (8个页面)
-- ✅ **订单列表** (`OrderListView.vue`) - 订单状态、发货状态、支付状态、优先级
-- ✅ **售后订单** (`OrderAfterSaleView.vue`) - 审核状态、退款状态、售后类型
-- ✅ **订单详情** (`OrderDetailView.vue`) - 订单状态、买家等级、发货状态
-- ✅ **产品列表** (`ProductListView.vue`) - 产品状态
-- ✅ **产品映射** (`ProductMappingView.vue`) - 映射状态、校验状态
-- ✅ **产品定价** (`ProductPricingView.vue`) - 定价规则状态
-
-### 2. 供应商管理模块 (4个页面)
-- ✅ **供应商列表** (`SupplierListView.vue`) - 合作状态
-- ✅ **供应商绩效** (`SupplierPerformanceView.vue`) - 绩效状态
-- ✅ **供应能力** (`SupplyCapabilityView.vue`) - 能力状态
-- ✅ **采购订单** (`PurchaseOrderView.vue`) - 采购订单状态
-
-### 3. 采购管理模块 (3个页面)
-- ✅ **采购申请** (`PurchaseRequestView.vue`) - 紧急程度、申请状态
-- ✅ **IQC质检** (`IQCView.vue`) - 质检结果
-- ✅ **补货计划** (`ReplenishmentPlanView.vue`) - 补货状态
-
-### 4. 物流管理模块 (2个页面)
-- ✅ **物流商管理** (`LogisticsProviderView.vue`) - 物流商状态
-- ✅ **运费模板** (`ShippingTemplateView.vue`) - 模板状态
-
-### 5. 财务管理模块 (2个页面)
-- ✅ **支付管理** (`PaymentView.vue`) - 对账状态
-- ✅ **退款管理** (`RefundView.vue`) - 退款状态
-- ✅ **发票管理** (`InvoiceView.vue`) - 发票状态、类型
-- ✅ **供应商结算** (`SupplierSettlementView.vue`) - 结算状态
-
-### 6. 营销管理模块 (2个页面)
-- ✅ **营销活动** (`PromotionView.vue`) - 活动状态
-- ✅ **优惠券** (`CouponView.vue`) - 优惠券状态、类型
-- ✅ **价格监控** (`PriceWatchView.vue`) - 价格警报状态
-
-### 7. 仓库管理模块 (3个页面)
-- ✅ **仓库管理** (`WarehouseView.vue`) - 仓库状态
-- ✅ **退货包裹** (`ReturnPackageView.vue`) - 退货状态
-- ✅ **库存日志** (`InventoryLogView.vue`) - 变动类型
-
-### 8. 库存管理模块 (2个页面)
-- ✅ **库存概览** (`InventoryOverviewView.vue`) - 库存预警状态
-- ✅ **发货工作** (`ShippingWorkView.vue`) - 发货状态、退货状态
-
-### 9. CRM客户关系模块 (5个页面)
-- ✅ **工单系统** (`TicketView.vue`) - 优先级、工单状态
-- ✅ **聊天记录** (`ChatLogView.vue`) - 聊天状态、处理方式
-- ✅ **知识库** (`KnowledgeBaseView.vue`) - 知识库状态
-- ✅ **满意度** (`SatisfactionView.vue`) - 处理状态
-- ✅ **渠道配置** (`ChannelConfigView.vue`) - 渠道状态、优先级
-
-### 10. 系统管理模块 (6个页面)
-- ✅ **员工管理** (`EmployeeView.vue`) - 员工状态、角色
-- ✅ **部门管理** (`DepartmentView.vue`) - 部门状态
-- ✅ **消息模板** (`MessageTemplateView.vue`) - 模板状态、类型
-- ✅ **通知管理** (`NotificationView.vue`) - 通知状态、类型
-- ✅ **审批流程** (`ApprovalFlowView.vue`) - 流程状态、类型
-- ✅ **API密钥** (`ApiKeyView.vue`) - 密钥状态
-- ✅ **操作日志** (`OperationLogView.vue`) - 操作结果状态
-- ✅ **角色权限** (`RolePermissionView.vue`) - 角色状态
-
-### 11. 报表分析模块 (6个页面)
-- ✅ **营销报表** (`MarketingReportView.vue`) - 活动类型、状态
-- ✅ **库存周转** (`InventoryTurnoverView.vue`) - 周转状态、建议
-- ✅ **物流报表** (`LogisticsReportView.vue`) - 配送状态
-- ✅ **采购报表** (`ProcurementReportView.vue`) - 质检状态
-- ✅ **客户分析** (`CustomerAnalysisView.vue`) - VIP等级
-- ✅ **报表仪表板** (`ReportDashboardView.vue`) - 预警级别
-
----
-
-## 🎨 枚举映射系统
-
-### 枚举类别 (18大类)
-
-| 类别 | 枚举数量 | 函数前缀 |
-|------|----------|----------|
-| 订单状态 | 8组 | `getOrderStatus`, `getShippingStatus`, `getPaymentStatus` |
-| 售后状态 | 3组 | `getAuditStatus`, `getRefundStatus`, `getAfterSaleType` |
-| 产品状态 | 4组 | `getProductStatus`, `getMappingStatus`, `getValidateStatus` |
-| 供应商 | 4组 | `getSupplierStatus`, `getPerformanceStatus`, `getCapabilityStatus` |
-| 采购 | 3组 | `getPurchaseOrderStatus`, `getPurchaseRequestStatus`, `getIQCResult` |
-| 物流 | 2组 | `getLogisticsStatus` |
-| 财务 | 4组 | `getInvoiceStatus`, `getSettlementStatus`, `getReconcileStatus` |
-| 营销 | 4组 | `getCouponStatus`, `getPromotionStatus`, `getPriceAlertStatus` |
-| 仓库 | 2组 | `getWarehouseStatus`, `getReturnPackageStatus` |
-| 库存 | 3组 | `getWarningStatus`, `getInventoryChangeType`, `getShippingWorkStatus` |
-| CRM | 6组 | `getChatStatus`, `getKnowledgeStatus`, `getChannelPriority` |
-| 系统管理 | 10组 | `getEmployeeStatus`, `getDepartmentStatus`, `getMessageTemplateStatus` |
-| 报表 | 9组 | `getMarketingActivityType`, `getInventoryTurnoverStatus` |
-
----
-
-## 📁 修改的文件
-
-### 核心文件
-- ✅ `frontend/src/utils/enumMappings.ts` - 新增 1031 行,50+ 枚举函数
-- ✅ `frontend/src/styles/global.scss` - 优化配色方案
-- ✅ `frontend/src/layout/AppLayout.vue` - 布局交互优化
-
-### 累计修复
-- ✅ **51 个页面** 移除了 `stripe` 隔行换色
-- ✅ **45+ 个页面** 修复了枚举值显示
-
----
-
-## 🎯 主要改进
-
-### 1. 视觉优化
-- ❌ 移除所有隔行换色,视觉更清爽
-- ✅ 统一使用纯白背景 + 边框分隔
-- ✅ 优化配色方案,提升对比度和可读性
-
-### 2. 交互优化
-- ⚡ 所有交互元素添加平滑过渡动画 (150ms)
-- ✅ 按钮、输入框、卡片悬停效果优化
-- ✅ 菜单激活状态添加视觉指示条
-
-### 3. 代码优化
-- 📦 枚举映射集中管理,消除重复代码
-- 🔧 统一使用 `getXXX(value).label` 和 `.type`
-- 🎨 支持50+ 种状态类型的中文映射
-
-### 4. 可维护性
-- ✅ 新增状态只需修改 `enumMappings.ts`
-- ✅ 自动支持中英文双语
-- ✅ 类型安全的颜色映射
-
----
-
-## 🔧 使用示例
-
-```vue
-<script setup>
-import { getOrderStatus, getShippingStatus } from '@/utils/enumMappings';
-
-const statusConfig = (s: string) => getOrderStatus(s);
-</script>
-
-<template>
-  <el-table-column prop="status" label="状态">
-    <template #default="{ row }">
-      <el-tag :type="statusConfig(row.status).type" size="small">
-        {{ statusConfig(row.status).label }}
-      </el-tag>
-    </template>
-  </el-table-column>
-</template>
-```
-
----
-
-## ✨ 验证清单
-
-- [x] 所有表格不再有隔行换色
-- [x] 所有状态显示中文(不再显示英文枚举值)
-- [x] Tag 颜色符合语义(成功=绿,警告=橙,危险=红)
-- [x] 交互元素有 hover 效果
-- [x] 按钮点击有反馈
-- [x] 输入框聚焦有高亮
-- [x] 支持 `prefers-reduced-motion`
-
----
-
-## 📊 技术栈
-
-- **框架**: Vue 3 + TypeScript
-- **UI库**: Element Plus
-- **状态管理**: Pinia
-- **路由**: Vue Router
-- **构建**: Vite
-
----
-
-## 🔥 CRITICAL FIX: 后端枚举值对齐
-
-### 问题描述
-初始版本中前端枚举映射使用小写键值(如 `created`, `paid`),但后端 Java 枚举返回大写值(如 `CREATED`, `PAID`),导致映射失败,前端显示原始英文枚举值而非中文。
-
-### 后端枚举定义(Java标准 - 大写)
-
-**OrderStatus.java:**
-```java
-public enum OrderStatus {
-    CREATED,      // 待支付
-    PAID,         // 已支付
-    ALLOCATED,    // 已分配
-    SHIPPED,      // 已发货
-    DELIVERED,    // 已签收
-    COMPLETED,    // 已完成
-    CANCELLED     // 已取消
-}
-```
-
-**ShippingStatus.java:**
-```java
-public enum ShippingStatus {
-    UNSHIPPED,    // 未发货
-    PROCESSING,   // 处理中
-    SHIPPED,      // 已发货
-    IN_TRANSIT,   // 运输中
-    DELIVERED     // 已签收
-}
-```
-
-**PaymentStatus.java:**
-```java
-public enum PaymentStatus {
-    UNPAID,       // 待支付
-    PENDING,      // 待支付
-    PAID          // 已支付
-}
-```
-
-### 修复内容
-
-✅ **ORDER_STATUS** - 移除小写键值,使用大写键值匹配后端
-✅ **SHIPPING_STATUS** - 更新为大写键值,添加 `IN_TRANSIT`
-✅ **PAYMENT_STATUS** - 更新为大写键值(UNPAID, PENDING, PAID)
-
-### 修复后的映射
-
-```typescript
-// 订单状态 - 匹配后端 OrderStatus.java
-export const ORDER_STATUS: Record<string, { label: string; type: string }> = {
-  CREATED: { label: '待支付', type: 'info' },
-  PAID: { label: '已支付', type: '' },
-  ALLOCATED: { label: '已分配', type: 'warning' },
-  SHIPPED: { label: '已发货', type: 'success' },
-  DELIVERED: { label: '已签收', type: 'success' },
-  COMPLETED: { label: '已完成', type: 'success' },
-  CANCELLED: { label: '已取消', type: 'danger' },
-};
-
-// 发货状态 - 匹配后端 ShippingStatus.java
-export const SHIPPING_STATUS: Record<string, { label: string; type: string }> = {
-  UNSHIPPED: { label: '未发货', type: 'info' },
-  PROCESSING: { label: '处理中', type: 'warning' },
-  SHIPPED: { label: '已发货', type: 'primary' },
-  IN_TRANSIT: { label: '运输中', type: 'primary' },
-  DELIVERED: { label: '已签收', type: 'success' },
-};
-
-// 支付状态 - 匹配后端 PaymentStatus.java
-export const PAYMENT_STATUS: Record<string, { label: string; type: string }> = {
-  UNPAID: { label: '待支付', type: 'warning' },
-  PENDING: { label: '待支付', type: 'warning' },
-  PAID: { label: '已支付', type: 'success' },
-};
-```
-
----
-
-## 📝 注意事项
-
-1. **新增状态**: 在 `enumMappings.ts` 中添加新枚举定义
-2. **修改状态**: 只需更新枚举映射,无需修改各组件
-3. **颜色类型**: 使用 `success`/`warning`/`danger`/`info`/`primary`/`''`
-4. **兼容性**: 支持中英文双语,自动回退到原值
-5. **后端对齐**: 新增枚举必须使用大写键值(Java标准),与后端枚举名称完全一致
-
----
-
-**修复完成时间**: 2026-04-21
-**修复范围**: 51 个页面,70+ 枚举类型
-**代码质量**: 消除重复代码,提升可维护性
-**后端对齐**: ✅ 核心枚举已与Java后端完全对齐
-
----
-
-## 🔍 额外检查和修复
-
-### 2026-04-21 持续检查修复
-
-#### 1. TicketView.vue 错误修复
-**问题**: 工单类型使用了错误的映射函数 `statusConfig`,应该使用 `typeTag`
-```vue
-<!-- ❌ 修复前 -->
-<el-tag :type="statusConfig(detailItem.type).type">{{ detailItem.type }}</el-tag>
-
-<!-- ✅ 修复后 -->
-<el-tag :type="typeTag(detailItem.type)">{{ detailItem.type }}</el-tag>
-```
-
-#### 2. OrderDetailView.vue 默认值修复
-**问题**: 发货状态默认值使用了小写 `'unshipped'`
-```vue
-<!-- ❌ 修复前 -->
-{{ getShippingStatus(order.shippingStatus || 'unshipped').label }}
-
-<!-- ✅ 修复后 -->
-{{ getShippingStatus(order.shippingStatus || 'UNSHIPPED').label }}
-```
-
-#### 3. 全面检查枚举映射使用情况
-✅ 检查了所有使用 `getXXXStatus()`, `getXXXLevel()`, `getXXXPriority()` 函数的地方
-✅ 确认 70+ 处枚举映射都正确使用了大写键值
-✅ 验证了所有状态标签都正确显示中文而非英文枚举值
-
-### 后端枚举定义验证
-后端 Java 枚举(标准大写格式):
-- `OrderStatus`: CREATED, PAID, ALLOCATED, SHIPPED, DELIVERED, COMPLETED, CANCELLED
-- `ShippingStatus`: UNSHIPPED, PROCESSING, SHIPPED, IN_TRANSIT, DELIVERED
-- `PaymentStatus`: UNPAID, PENDING, PAID
-
-### 前端枚举映射(已对齐)
-所有前端枚举映射已更新为使用大写键值,完全匹配后端 Java 枚举名称。

+ 0 - 160
ENUM_FIX_GUIDE.md

@@ -1,160 +0,0 @@
-# 枚举值中文显示修复指南
-
-## 已完成的修复
-
-✅ **订单列表** (`order/OrderListView.vue`)
-✅ **售后订单** (`order/OrderAfterSaleView.vue`)
-✅ **所有页面** - 已移除 `stripe` 隔行换色属性
-
-## 枚举映射工具
-
-已创建通用枚举映射工具:`frontend/src/utils/enumMappings.ts`
-
-### 可用的转换函数
-
-```typescript
-// 订单相关
-getOrderStatus(value)        // 订单状态
-getShippingStatus(value)     // 发货状态
-getPaymentStatus(value)      // 支付状态
-getPriorityLabel(value)      // 优先级
-getExceptionLabel(value)     // 异常标签
-
-// 售后相关
-getAuditStatus(value)        // 审核状态
-getRefundStatus(value)       // 退款状态
-getAfterSaleType(value)      // 售后类型
-
-// 产品相关
-getProductStatus(value)      // 产品状态
-
-// 供应商相关
-getSupplierStatus(value)     // 供应商状态
-```
-
-## 快速修复步骤
-
-### 步骤 1: 在页面中导入工具
-
-```vue
-<script setup lang="ts">
-import { getOrderStatus, getShippingStatus } from '@/utils/enumMappings';
-</script>
-```
-
-### 步骤 2: 添加辅助函数
-
-```vue
-<script setup lang="ts">
-// 方式1: 直接使用
-const statusConfig = (s: string) => getOrderStatus(s);
-
-// 方式2: 解构使用
-const { label: statusLabel, type: statusType } = getOrderStatus(row.status);
-</script>
-```
-
-### 步骤 3: 更新模板
-
-**修改前(直接显示枚举值):**
-```vue
-<el-table-column prop="status" label="状态" width="100">
-  <template #default="{ row }">
-    <el-tag :type="statusType(row.status)" size="small">
-      {{ row.status }}
-    </el-tag>
-  </template>
-</el-table-column>
-```
-
-**修改后(使用枚举映射):**
-```vue
-<el-table-column prop="status" label="状态" width="100">
-  <template #default="{ row }">
-    <el-tag :type="statusConfig(row.status).type" size="small">
-      {{ statusConfig(row.status).label }}
-    </el-tag>
-  </template>
-</el-table-column>
-```
-
-## 需要修复的页面清单
-
-根据搜索结果,以下页面可能包含枚举值显示问题:
-
-### 高优先级(核心业务)
-- [ ] `product/ProductListView.vue` - 产品状态
-- [ ] `finance/PaymentView.vue` - 支付状态
-- [ ] `finance/RefundView.vue` - 退款状态
-- [ ] `warehouse/WarehouseView.vue` - 仓库状态
-- [ ] `marketing/PromotionView.vue` - 活动状态
-
-### 中优先级(管理功能)
-- [ ] `crm/TicketView.vue` - 工单状态/优先级
-- [ ] `crm/ServicePerformanceView.vue` - 服务状态
-- [ ] `supplier/SupplierListView.vue` - 供应商状态
-- [ ] `logistics/LogisticsProviderView.vue` - 物流商状态
-
-### 低优先级(报表和配置)
-- [ ] `report/*` - 各类报表页面
-- [ ] `system/*` - 系统配置页面
-- [ ] `inventory/*` - 库存页面
-
-## 添加新的枚举映射
-
-如果 `enumMappings.ts` 中没有你需要的枚举,按以下格式添加:
-
-```typescript
-// 在 enumMappings.ts 中添加
-export const YOUR_ENUM: Record<string, { label: string; type: string }> = {
-  key1: { label: '中文1', type: 'primary' },
-  key2: { label: '中文2', type: 'success' },
-  key3: { label: '中文3', type: 'warning' },
-  key4: { label: '中文4', type: 'danger' },
-  key5: { label: '中文5', type: 'info' },
-};
-
-// 添加快捷函数
-export function getYourEnum(value: string) {
-  return getEnumWithStyle(YOUR_ENUM, value);
-}
-```
-
-## Tag 类型参考
-
-```typescript
-type: 'primary'    // 蓝色 - 主要信息
-type: 'success'    // 绿色 - 成功/正常
-type: 'warning'    // 橙色 - 警告/处理中
-type: 'danger'     // 红色 - 危险/错误
-type: 'info'       // 灰色 - 信息/禁用
-```
-
-## 常见问题
-
-### Q: 后端返回的是中文,还需要映射吗?
-A: 建议仍然使用枚举映射,这样可以:
-1. 统一样式和类型
-2. 防止后端返回值变化
-3. 便于后期维护
-
-### Q: 如何处理未知枚举值?
-A: `getEnumWithStyle` 函数会自动返回原值和 `info` 类型,不会报错
-
-### Q: 条件判断怎么处理?
-A: 使用中文值进行判断:
-```vue
-<el-button v-if="row.status === '已完成'">查看</el-button>
-```
-
-## 验证修复
-
-修复后请检查:
-1. ✅ 所有状态显示中文
-2. ✅ Tag 颜色符合语义
-3. ✅ 筛选器选项使用中文
-4. ✅ 没有直接显示英文枚举值
-
----
-
-**注意**: 如果遇到问题或需要添加新的枚举映射,请参考 `OrderListView.vue` 和 `OrderAfterSaleView.vue` 的实现示例。

+ 0 - 267
FRONTEND_BACKEND_ALIGNMENT_CHECK.md

@@ -1,267 +0,0 @@
-# 前后端代码对齐检查报告
-
-## 检查时间
-2026-04-21
-
-## 检查范围
-- 订单模块 (Orders)
-- 商品模块 (Products)
-
----
-
-## 一、订单模块对齐分析
-
-### 1.1 字段类型对比
-
-| 字段名 | 后端类型 | 前端类型 | 状态 | 说明 |
-|--------|---------|---------|------|------|
-| id | Long | string | ❌ **不对齐** | 应统一为 number |
-| orderNo | String | string | ✅ | 对齐 |
-| channelOrderNo | String | string | ✅ | 对齐 |
-| channelId | Long | - | ⚠️ | 前端缺少此字段 |
-| channel | - | string | ⚠️ | 后端DTO有,实体无 |
-| orderStatus | String | string | ✅ | 对齐 |
-| shippingStatus | String | string | ✅ | 对齐 |
-| paymentStatus | String | string | ✅ | 对齐 |
-| refundStatus | String | string | ✅ | 对齐 |
-| exceptionTag | String | string | ✅ | 对齐 |
-| priority | String | string | ✅ | 对齐 |
-| buyerId | String | string | ✅ | 对齐 |
-| buyer | String | string | ✅ | 对齐 |
-| buyerEmail | String | string | ✅ | 对齐 |
-| buyerPhone | String | string | ✅ | 对齐 |
-| buyerCountry | String | string | ✅ | 对齐 |
-| buyerLevel | String | string | ✅ | 对齐 |
-| buyerTags | String | string[] | ❌ **不对齐** | String vs Array |
-| buyerOrderCount | Integer | number | ✅ | 对齐 |
-| buyerTotalSpent | BigDecimal | string | ⚠️ | 建议用 string |
-| receiverName | String | string | ✅ | 对齐 |
-| receiverPhone | String | string | ✅ | 对齐 |
-| receiverCountry | String | string | ✅ | 对齐 |
-| receiverState | String | string | ✅ | 对齐 |
-| receiverCity | String | string | ✅ | 对齐 |
-| receiverDistrict | String | string | ✅ | 对齐 |
-| receiverPostalCode | String | string | ✅ | 对齐 |
-| receiverAddress | String | string | ✅ | 对齐 |
-| latitude | BigDecimal | number | ⚠️ | 可接受 |
-| longitude | BigDecimal | number | ⚠️ | 可接受 |
-| orderAmount | BigDecimal | string | ⚠️ | 建议用 string |
-| actualPaid | BigDecimal | string | ⚠️ | 建议用 string |
-| amount | - | string | ❌ **后端缺失** | 前端在用 |
-| warehouseLocation | String | string | ✅ | 对齐 |
-| warehouseId | Long | - | ⚠️ | 前端缺少 |
-| trackingNo | String | string | ✅ | 对齐 |
-| itemCount | Integer | number | ✅ | 对齐 |
-| items | List<OrderItemDTO> | OrderProductItem[] | ⚠️ | 类型名不同 |
-
-### 1.2 字段命名差异
-
-| 后端命名 | 前端命名 | 建议 |
-|---------|---------|------|
-| carrierName | carrier | 前端统一用 carrierName |
-| handlerName | handler | 前端统一用 handlerName |
-| warehouseName | warehouse | 前端统一用 warehouseName |
-| channelName | channel | 前端统一用 channelName |
-
----
-
-## 二、商品模块对齐分析
-
-### 2.1 字段类型对比
-
-| 字段名 | 后端类型 | 前端类型 | 状态 | 说明 |
-|--------|---------|---------|------|------|
-| id | Long | string | ❌ **不对齐** | 应统一为 number |
-| spu | String | string | ✅ | 对齐 |
-| title | String | string | ✅ | 对齐 |
-| subtitle | String | - | ⚠️ | 前端缺少 |
-| categoryId | Long | string | ❌ **不对齐** | Long vs string |
-| category | - | string | ❌ **后端缺失** | 前端在用 |
-| brand | String | string | ✅ | 对齐 |
-| tags | String | string[] | ❌ **不对齐** | String vs Array |
-| description | String | string | ✅ | 对齐 |
-| specs | String | SpecItem[] | ❌ **不对齐** | JSON vs Array |
-| channelStatus | String | string | ✅ | 对齐 |
-| status | String | string | ✅ | 对齐 |
-| owner | String | string | ✅ | 对齐 |
-| skuCount | Integer | number | ✅ | 对齐 |
-| image | String | string | ✅ | 对齐 |
-| images | String | MediaItem[] | ❌ **不对齐** | JSON vs Array |
-| videos | String | MediaItem[] | ❌ **不对齐** | JSON vs Array |
-| translations | String | TranslationItem[] | ❌ **不对齐** | JSON vs Array |
-| inventory | - | number | ❌ **后端缺失** | 前端在用 |
-| priceRange | - | string | ❌ **后端缺失** | 前端在用 |
-
-### 2.2 字段命名差异
-
-| 后端命名 | 前端命名 | 建议 |
-|---------|---------|------|
-| categoryId | category | 前端使用 categoryId,前端也应有分类名称字段 |
-
----
-
-## 三、严重问题汇总
-
-### 3.1 类型不匹配问题
-
-1. **ID字段类型不一致**
-   - 后端: `Long`
-   - 前端: `string`
-   - 影响: 路由参数、API调用
-   - 建议: 前端统一使用 `number` 类型
-
-2. **JSON字段序列化问题**
-   - 后端: `String` (存储JSON字符串)
-   - 前端: `Array` 类型
-   - 影响: tags, specs, images, videos, translations
-   - 需要后端Converter处理序列化/反序列化
-
-3. **金额字段类型**
-   - 后端: `BigDecimal`
-   - 前端: `string`
-   - 建议: 统一使用 `string` 避免精度问题
-
-### 3.2 缺失字段
-
-**订单模块:**
-- 后端有但前端未使用: `channelId`, `warehouseId`, `carrierId`
-- 前端在用但后端无: `amount` (应该是 `actualPaid` 的别名)
-
-**商品模块:**
-- 后端有但前端未使用: `subtitle`, `categoryId`
-- 前端在用但后端无: `category`, `inventory`, `priceRange` (计算字段)
-
-### 3.3 字段命名不一致
-
-```
-后端实体使用驼峰命名: orderNo, buyerId, channelId
-前端类型使用驼峰命名: orderNo, buyerId, channelId
-✅ 命名风格一致,但具体字段名有差异:
-- carrierName vs carrier
-- handlerName vs handler
-- warehouseName vs warehouse
-- channelName vs channel
-```
-
----
-
-## 四、DTO转换器问题
-
-### 4.1 后端Converter检查
-
-需要检查以下Converter是否正确处理字段映射:
-- `OrdersConverter.toListDto()`
-- `OrdersConverter.toDto()`
-- `OrderItemConverter.toDto()`
-- Product相关的Converter
-
-### 4.2 JSON字段序列化
-
-后端存储为JSON字符串的字段,需要Converter处理:
-```java
-// 后端需要Converter处理
-private String tags;           // -> 前端 string[]
-private String specs;          // -> 前端 SpecItem[]
-private String images;         // -> 前端 MediaItem[]
-private String videos;         // -> 前端 MediaItem[]
-private String translations;   // -> 前端 TranslationItem[]
-```
-
----
-
-## 五、API路径对齐
-
-### 5.1 订单API
-
-| 功能 | 后端路径 | 前端调用 | 状态 |
-|------|---------|---------|------|
-| 获取订单列表 | GET /api/order/orders | api.getOrders() | ✅ |
-| 获取订单详情 | GET /api/order/orders/{id} | api.getOrder() | ✅ |
-| 创建订单 | POST /api/order/orders | api.createOrder() | ✅ |
-| 更新订单 | PUT /api/order/orders/{id} | api.updateOrder() | ✅ |
-| 删除订单 | DELETE /api/order/orders/{id} | api.deleteOrder() | ✅ |
-
-### 5.2 商品API
-
-| 功能 | 后端路径 | 前端调用 | 状态 |
-|------|---------|---------|------|
-| 获取商品列表 | GET /api/product/products | api.getProducts() | ✅ |
-| 获取商品详情 | GET /api/product/products/{id} | api.getProduct() | ✅ |
-| 创建商品 | POST /api/product/products | api.createProduct() | ✅ |
-| 更新商品 | PUT /api/product/products/{id} | api.updateProduct() | ✅ |
-| 删除商品 | DELETE /api/product/products/{id} | api.deleteProduct() | ✅ |
-
----
-
-## 六、修复建议优先级
-
-### 🔴 P0 - 必须立即修复
-
-1. **ID字段类型统一**
-   - 前端 OrderItem.id: string → number
-   - 前端 ProductItem.id: string → number
-   - 影响: 路由跳转、API调用
-
-2. **JSON字段序列化**
-   - 后端Converter处理 tags, specs, images, videos, translations
-   - 确保 JSON字符串正确转换为对象数组
-
-### 🟡 P1 - 高优先级
-
-3. **字段补齐**
-   - 前端添加: channelId, warehouseId
-   - 后端DTO添加: 计算字段 (inventory, priceRange)
-
-4. **字段命名统一**
-   - 前端: carrier → carrierName
-   - 前端: handler → handlerName
-   - 前端: warehouse → warehouseName
-   - 前端: channel → channelName
-
-### 🟢 P2 - 中优先级
-
-5. **金额字段规范**
-   - 统一使用 string 类型避免精度问题
-   - 前端显示时格式化
-
-6. **Category字段处理**
-   - 后端DTO增加: categoryName (从categoryId查询)
-   - 前端使用 categoryId 而非 category
-
----
-
-## 七、待修复代码清单
-
-### 后端需要修改:
-
-1. **OrderListDTO.java** - 添加缺失字段
-2. **OrdersConverter.java** - 完善字段映射
-3. **ProductConverter.java** - 处理JSON序列化
-4. **ProductDTO.java** - 添加计算字段
-
-### 前端需要修改:
-
-1. **types/page.ts** - 修改类型定义
-2. **views/order/OrderListView.vue** - 使用正确字段名
-3. **views/product/ProductListView.vue** - 使用正确字段名
-
----
-
-## 八、验证方法
-
-修复后需要验证:
-
-1. ✅ 后端编译通过
-2. ✅ 前端构建通过
-3. ✅ 订单列表正常显示
-4. ✅ 订单详情正常显示
-5. ✅ 商品列表正常显示
-6. ✅ 商品详情正常显示
-7. ✅ 筛选功能正常
-8. ✅ 分页功能正常
-
----
-
-**检查完成时间**: 2026-04-21
-**检查人员**: Claude Code
-**下一步**: 开始修复P0问题

+ 0 - 342
PAGINATION_FIX_COMPLETE.md

@@ -1,342 +0,0 @@
-# 后端分页修复完成报告
-
-## 问题描述
-
-之前的实现存在严重的架构问题:
-- **前端**: 从后端获取分页数据(如20条)→ 客户端筛选这20条 → 对筛选结果进行分页
-- **结果**: 如果后端返回20条但只有5条符合筛选条件,第1页显示5条,第2页为空
-- **根本原因**: 混合使用了后端分页和前端筛选,导致分页失效
-
-## 解决方案
-
-### 架构改进
-
-采用**纯后端分页 + 后端筛选**的架构:
-1. 前端发送筛选参数到后端API
-2. 后端应用筛选条件并返回分页结果
-3. 前端直接显示后端返回的数据,不做任何客户端筛选
-
-### 实现细节
-
-#### 1. 创建筛选DTO(用户建议)
-
-**后端新增DTO类:**
-
-```java
-// OrderFilterDTO.java
-@Data
-public class OrderFilterDTO {
-    private String keyword;
-    private String orderStatus;
-    private String shippingStatus;
-    private String paymentStatus;
-    private Long channelId;
-    private Long warehouseId;
-}
-
-// ProductFilterDTO.java
-@Data
-public class ProductFilterDTO {
-    private String keyword;
-    private String category;
-    private String status;
-    private String brand;
-}
-```
-
-**优点:**
-- ✅ 代码更简洁,可维护性更高
-- ✅ 易于扩展新的筛选条件
-- ✅ 类型安全,编译时检查
-- ✅ 符合Java企业级应用最佳实践
-
-#### 2. 更新后端Controller
-
-**OrdersController.java:**
-```java
-@GetMapping
-public PageResponse<OrderListDTO> getOrders(
-        @RequestParam(defaultValue = "1") int page,
-        @RequestParam(defaultValue = "20") int size,
-        @ModelAttribute OrderFilterDTO filters) {
-    Page<Orders> pageResult = ordersService.getPage(page, size, filters);
-    // ... 返回分页结果
-}
-```
-
-**ProductController.java:**
-```java
-@GetMapping
-public PageResponse<Product> getProducts(
-        @RequestParam(defaultValue = "1") int page,
-        @RequestParam(defaultValue = "20") int size,
-        @ModelAttribute ProductFilterDTO filters) {
-    Page<Product> pageResult = productService.getProducts(page, size, filters);
-    // ... 返回分页结果
-}
-```
-
-#### 3. 更新后端Service
-
-**OrdersService.java:**
-```java
-public Page<Orders> getPage(int page, int size, OrderFilterDTO filters) {
-    LambdaQueryWrapper<Orders> wrapper = new LambdaQueryWrapper<Orders>()
-        .orderByDesc(Orders::getCreatedAt);
-    if (filters.getKeyword() != null && !filters.getKeyword().isEmpty()) {
-        wrapper.and(w -> w.like(Orders::getOrderNo, filters.getKeyword())
-                .or().like(Orders::getChannelOrderNo, filters.getKeyword())
-                .or().like(Orders::getBuyer, filters.getKeyword())
-                .or().like(Orders::getReceiverName, filters.getKeyword()));
-    }
-    if (filters.getOrderStatus() != null && !filters.getOrderStatus().isEmpty())
-        wrapper.eq(Orders::getOrderStatus, filters.getOrderStatus());
-    if (filters.getShippingStatus() != null && !filters.getShippingStatus().isEmpty())
-        wrapper.eq(Orders::getShippingStatus, filters.getShippingStatus());
-    if (filters.getPaymentStatus() != null && !filters.getPaymentStatus().isEmpty())
-        wrapper.eq(Orders::getPaymentStatus, filters.getPaymentStatus());
-    if (filters.getChannelId() != null)
-        wrapper.eq(Orders::getChannelId, filters.getChannelId());
-    if (filters.getWarehouseId() != null)
-        wrapper.eq(Orders::getWarehouseId, filters.getWarehouseId());
-    return mapper.selectPage(new Page<>(page, size), wrapper);
-}
-```
-
-**ProductService.java:**
-```java
-public Page<Product> getProducts(int page, int size, ProductFilterDTO filters) {
-    LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<Product>()
-        .orderByDesc(Product::getCreatedAt);
-    if (filters.getKeyword() != null && !filters.getKeyword().isEmpty())
-        wrapper.and(w -> w.like(Product::getTitle, filters.getKeyword())
-                .or().like(Product::getSpu, filters.getKeyword()));
-    if (filters.getCategory() != null && !filters.getCategory().isEmpty())
-        wrapper.eq(Product::getCategoryId, filters.getCategory());
-    if (filters.getStatus() != null && !filters.getStatus().isEmpty())
-        wrapper.eq(Product::getStatus, filters.getStatus());
-    if (filters.getBrand() != null && !filters.getBrand().isEmpty())
-        wrapper.eq(Product::getBrand, filters.getBrand());
-    return mapper.selectPage(new Page<>(page, size), wrapper);
-}
-```
-
-#### 4. 更新前端API服务
-
-**frontend/src/api/services.ts:**
-
-```typescript
-/* Orders */
-getOrders: (page?: number, size?: number, filters?: {
-  keyword?: string;
-  orderStatus?: string;
-  shippingStatus?: string;
-  paymentStatus?: string;
-  channelId?: number;
-  warehouseId?: number;
-}) => {
-  const params = new URLSearchParams({
-    page: String(page || 1),
-    size: String(size || 20)
-  });
-  if (filters?.keyword) params.append('keyword', filters.keyword);
-  if (filters?.orderStatus) params.append('orderStatus', filters.orderStatus);
-  if (filters?.shippingStatus) params.append('shippingStatus', filters.shippingStatus);
-  if (filters?.paymentStatus) params.append('paymentStatus', filters.paymentStatus);
-  if (filters?.channelId) params.append('channelId', String(filters.channelId));
-  if (filters?.warehouseId) params.append('warehouseId', String(filters.warehouseId));
-  return request<{ items: OrderItem[]; totalElements: number }>(
-    `/api/order/orders?${params.toString()}`
-  );
-},
-
-/* Products */
-getProducts: (page?: number, size?: number, filters?: {
-  keyword?: string;
-  category?: string;
-  status?: string;
-  brand?: string;
-}) => {
-  const params = new URLSearchParams({
-    page: String(page || 1),
-    size: String(size || 20)
-  });
-  if (filters?.keyword) params.append('keyword', filters.keyword);
-  if (filters?.category) params.append('category', filters.category);
-  if (filters?.status) params.append('status', filters.status);
-  if (filters?.brand) params.append('brand', filters.brand);
-  return request<{ items: ProductItem[]; totalElements: number }>(
-    `/api/product/products?${params.toString()}`
-  );
-},
-```
-
-#### 5. 更新前端视图组件
-
-**OrderListView.vue - 移除客户端筛选:**
-```typescript
-// ❌ 删除: 客户端筛选逻辑
-const filteredItems = computed(() => {
-  return items.value.filter(item => {
-    // ... 筛选逻辑
-  });
-});
-
-const paginatedItems = computed(() => {
-  const start = (page.value - 1) * pageSize.value;
-  const end = start + pageSize.value;
-  return filteredItems.value.slice(start, end);
-});
-
-// ✅ 新增: 直接调用后端API并传递筛选参数
-const loadData = async () => {
-  loading.value = true;
-  try {
-    const res = await api.getOrders(page.value, pageSize.value, {
-      keyword: searchKeyword.value || undefined,
-      orderStatus: filters.value.orderStatus || undefined,
-      shippingStatus: filters.value.shippingStatus || undefined,
-      paymentStatus: filters.value.paymentStatus || undefined
-    });
-    items.value = res.items || [];
-    totalElements.value = res.totalElements || 0;
-  } finally {
-    loading.value = false;
-  }
-};
-
-// 监听筛选条件变化,重新加载数据
-watch([searchKeyword, () => filters.value, page, pageSize], () => {
-  loadData();
-}, { deep: true });
-```
-
-**ProductListView.vue - 同样修改:**
-```typescript
-const loadData = async () => {
-  loading.value = true;
-  try {
-    const res = await api.getProducts(page.value, pageSize.value, {
-      keyword: filters.value.keyword || undefined,
-      category: filters.value.category || undefined,
-      status: filters.value.status || undefined,
-      brand: filters.value.brand || undefined
-    });
-    items.value = res.items ?? [];
-    totalElements.value = res.totalElements || 0;
-  } finally {
-    loading.value = false;
-  }
-};
-```
-
-**表格数据绑定修改:**
-```vue
-<!-- ❌ 之前: 使用客户端分页数据 -->
-<el-table :data="paginatedItems" ...>
-
-<!-- ✅ 现在: 直接使用后端返回的数据 -->
-<el-table :data="items" ...>
-
-<!-- ❌ 之前: 使用客户端筛选后的总数 -->
-<el-pagination :total="filteredTotal" ...>
-
-<!-- ✅ 现在: 使用后端返回的总数 -->
-<el-pagination :total="totalElements" ...>
-```
-
-## 修改的文件
-
-### 后端文件
-1. ✅ `backend/src/main/java/com/oms/dto/OrderFilterDTO.java` - 新建
-2. ✅ `backend/src/main/java/com/oms/dto/ProductFilterDTO.java` - 新建
-3. ✅ `backend/src/main/java/com/oms/controller/OrdersController.java` - 使用DTO简化参数
-4. ✅ `backend/src/main/java/com/oms/controller/ProductController.java` - 使用DTO简化参数
-5. ✅ `backend/src/main/java/com/oms/service/OrdersService.java` - 支持DTO筛选
-6. ✅ `backend/src/main/java/com/oms/service/ProductService.java` - 支持DTO筛选
-
-### 前端文件
-1. ✅ `frontend/src/api/services.ts` - API方法支持筛选参数
-2. ✅ `frontend/src/views/order/OrderListView.vue` - 移除客户端筛选,使用后端分页
-3. ✅ `frontend/src/views/product/ProductListView.vue` - 移除客户端筛选,使用后端分页
-
-## 技术优势
-
-### 使用DTO的优势
-1. **代码简洁性**: Controller方法签名从8个参数减少到3个
-2. **可扩展性**: 新增筛选条件只需修改DTO,无需改Controller和Service方法签名
-3. **类型安全**: 编译时检查,减少运行时错误
-4. **可维护性**: 筛选逻辑集中在DTO,便于理解和维护
-
-### 架构优势
-1. **性能优化**:
-   - 只查询需要的数据,减少网络传输
-   - 数据库层面筛选,利用索引提升查询速度
-   - 避免前端处理大量数据
-
-2. **可扩展性**:
-   - 支持海量数据(百万级订单)
-   - 筛选条件可无限扩展
-   - 易于添加缓存层
-
-3. **用户体验**:
-   - 分页准确,不会出现空页
-   - 筛选即时生效
-   - 支持深度分页
-
-## 验证结果
-
-- ✅ 后端编译成功
-- ✅ 前端构建成功
-- ✅ 分页功能正常
-- ✅ 筛选功能正常
-- ✅ 代码质量提升
-
-## 使用示例
-
-### 前端调用示例
-```typescript
-// 订单列表 - 带筛选的分页查询
-const res = await api.getOrders(1, 20, {
-  keyword: 'OMS-',
-  orderStatus: 'PAID',
-  shippingStatus: 'SHIPPED'
-});
-
-// 商品列表 - 带筛选的分页查询
-const res = await api.getProducts(1, 20, {
-  keyword: '行李箱',
-  category: 'Luggage',
-  status: 'LISTED'
-});
-```
-
-### 后端接收示例
-```java
-@GetMapping
-public PageResponse<OrderListDTO> getOrders(
-        @RequestParam(defaultValue = "1") int page,
-        @RequestParam(defaultValue = "20") int size,
-        @ModelAttribute OrderFilterDTO filters) {
-    // Spring自动绑定查询参数到DTO
-    // ?keyword=OMS-&orderStatus=PAID -> filters.setKeyword("OMS-"), filters.setOrderStatus("PAID")
-}
-```
-
-## 总结
-
-这次修复解决了分页架构的根本问题,采用了企业级应用的标准实践:
-
-1. **使用DTO简化参数传递** - 响应用户建议,提升代码质量
-2. **后端筛选 + 后端分页** - 正确的架构模式
-3. **前端零筛选逻辑** - 简化前端代码
-4. **类型安全 + 可扩展** - 符合Java最佳实践
-
-修复完成后,系统可以正确处理海量数据的分页和筛选,用户体验得到显著提升。
-
----
-
-**修复时间**: 2026-04-21
-**修复范围**: 订单列表、商品列表的分页架构
-**代码质量**: 采用DTO模式,符合企业级应用标准
-**用户反馈**: ✅ 接受使用DTO的建议,代码更简洁

+ 5 - 2
backend/src/main/java/com/oms/controller/AiChannelController.java

@@ -6,6 +6,8 @@ import com.oms.service.AiChannelService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class AiChannelController {
     private final AiChannelService aiChannelService;
 
     @GetMapping
-    public List<AiChannel> getAiChannels(
+    public PageResponse<AiChannel> getAiChannels(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return aiChannelService.getPage(page, size).getRecords();
+        Page<AiChannel> pageResult = aiChannelService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/AutoReplyRuleController.java

@@ -6,6 +6,8 @@ import com.oms.service.AutoReplyRuleService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class AutoReplyRuleController {
     private final AutoReplyRuleService autoReplyRuleService;
 
     @GetMapping
-    public List<AutoReplyRule> getAutoReplyRules(
+    public PageResponse<AutoReplyRule> getAutoReplyRules(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return autoReplyRuleService.getPage(page, size).getRecords();
+        Page<AutoReplyRule> pageResult = autoReplyRuleService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/ChannelController.java

@@ -6,6 +6,8 @@ import com.oms.service.ChannelService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -16,10 +18,11 @@ public class ChannelController {
     private final ChannelService channelService;
 
     @GetMapping
-    public List<Channel> getChannels(
+    public PageResponse<Channel> getChannels(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return channelService.getPage(page, size).getRecords();
+        Page<Channel> pageResult = channelService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/{id}")

+ 5 - 2
backend/src/main/java/com/oms/controller/ChannelMappingController.java

@@ -5,6 +5,8 @@ import com.oms.service.ChannelMappingService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class ChannelMappingController {
     private final ChannelMappingService channelMappingService;
 
     @GetMapping
-    public List<ChannelMapping> getMappings(
+    public PageResponse<ChannelMapping> getMappings(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return channelMappingService.getMappings(page, size).getRecords();
+        Page<ChannelMapping> pageResult = channelMappingService.getMappings(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/product/{productId}")

+ 7 - 2
backend/src/main/java/com/oms/controller/ChatLogController.java

@@ -1,6 +1,8 @@
 package com.oms.controller;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.oms.common.ApiResponse;
+import com.oms.dto.PageResponse;
 import com.oms.dto.ChatLogDTO;
 import com.oms.entity.ChatLog;
 import com.oms.service.ChatLogService;
@@ -17,10 +19,13 @@ public class ChatLogController {
     private final ChatLogService chatLogService;
 
     @GetMapping
-    public ApiResponse<List<ChatLog>> getChatLogs(
+    public PageResponse<ChatLog> getChatLogs(
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "20") int size,
             @RequestParam(required = false) String sessionId,
             @RequestParam(required = false) String status) {
-        return ApiResponse.success(chatLogService.listChatLogs(sessionId, status));
+        Page<ChatLog> pageResult = chatLogService.getPage(page, size, sessionId, status);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/{id}")

+ 5 - 2
backend/src/main/java/com/oms/controller/ChatMessageController.java

@@ -6,6 +6,8 @@ import com.oms.service.ChatMessageService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class ChatMessageController {
     private final ChatMessageService chatMessageService;
 
     @GetMapping
-    public List<ChatMessage> getChatMessages(
+    public PageResponse<ChatMessage> getChatMessages(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return chatMessageService.getPage(page, size).getRecords();
+        Page<ChatMessage> pageResult = chatMessageService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/ChatSessionController.java

@@ -6,6 +6,8 @@ import com.oms.service.ChatSessionService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class ChatSessionController {
     private final ChatSessionService chatSessionService;
 
     @GetMapping
-    public List<ChatSession> getChatSessions(
+    public PageResponse<ChatSession> getChatSessions(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return chatSessionService.getPage(page, size).getRecords();
+        Page<ChatSession> pageResult = chatSessionService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/CouponController.java

@@ -6,6 +6,8 @@ import com.oms.service.CouponService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class CouponController {
     private final CouponService couponService;
 
     @GetMapping
-    public List<Coupon> getCoupons(
+    public PageResponse<Coupon> getCoupons(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return couponService.getPage(page, size).getRecords();
+        Page<Coupon> pageResult = couponService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/FinancePaymentController.java

@@ -6,6 +6,8 @@ import com.oms.service.FinancePaymentService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -16,10 +18,11 @@ public class FinancePaymentController {
     private final FinancePaymentService financePaymentService;
 
     @GetMapping
-    public List<FinancePayment> getPayments(
+    public PageResponse<FinancePayment> getPayments(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return financePaymentService.getPage(page, size).getRecords();
+        Page<FinancePayment> pageResult = financePaymentService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/FinanceRefundController.java

@@ -6,6 +6,8 @@ import com.oms.service.FinanceRefundService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -16,10 +18,11 @@ public class FinanceRefundController {
     private final FinanceRefundService financeRefundService;
 
     @GetMapping
-    public List<FinanceRefund> getRefunds(
+    public PageResponse<FinanceRefund> getRefunds(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return financeRefundService.getPage(page, size).getRecords();
+        Page<FinanceRefund> pageResult = financeRefundService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 12 - 20
backend/src/main/java/com/oms/controller/InventoryController.java

@@ -1,11 +1,14 @@
 package com.oms.controller;
 
 import com.oms.dto.InventoryDTO;
+import com.oms.dto.InventoryOperationRequest;
 import com.oms.entity.Inventory;
 import com.oms.service.InventoryService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -16,10 +19,11 @@ public class InventoryController {
     private final InventoryService inventoryService;
 
     @GetMapping
-    public List<Inventory> getInventories(
+    public PageResponse<Inventory> getInventories(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return inventoryService.getPage(page, size).getRecords();
+        Page<Inventory> pageResult = inventoryService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")
@@ -56,30 +60,18 @@ public class InventoryController {
     }
 
     @PostMapping("/{id}/lock")
-    public void lockInventory(
-            @PathVariable Long id,
-            @RequestParam int qty,
-            @RequestParam String operator) {
-        inventoryService.lockInventory(id, qty, operator);
+    public void lockInventory(@PathVariable Long id, @RequestBody InventoryOperationRequest req) {
+        inventoryService.lockInventory(id, req.getQty(), req.getOperator());
     }
 
     @PostMapping("/{id}/unlock")
-    public void unlockInventory(
-            @PathVariable Long id,
-            @RequestParam int qty,
-            @RequestParam String operator) {
-        inventoryService.unlockInventory(id, qty, operator);
+    public void unlockInventory(@PathVariable Long id, @RequestBody InventoryOperationRequest req) {
+        inventoryService.unlockInventory(id, req.getQty(), req.getOperator());
     }
 
     @PostMapping("/{id}/increment")
-    public void incrementInventory(
-            @PathVariable Long id,
-            @RequestParam int qty,
-            @RequestParam String changeType,
-            @RequestParam String operator,
-            @RequestParam(required = false) Long orderId,
-            @RequestParam(required = false) String orderNo) {
-        inventoryService.incrementInventory(id, qty, changeType, operator, orderId, orderNo);
+    public void incrementInventory(@PathVariable Long id, @RequestBody InventoryOperationRequest req) {
+        inventoryService.incrementInventory(id, req.getQty(), req.getChangeType(), req.getOperator(), req.getOrderId(), req.getOrderNo());
     }
 
     @DeleteMapping("/{id}")

+ 8 - 2
backend/src/main/java/com/oms/controller/InventoryLogController.java

@@ -1,5 +1,7 @@
 package com.oms.controller;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import com.oms.entity.InventoryLog;
 import com.oms.service.InventoryLogService;
 import lombok.RequiredArgsConstructor;
@@ -15,8 +17,12 @@ public class InventoryLogController {
     private final InventoryLogService inventoryLogService;
 
     @GetMapping("/{inventoryId}/logs")
-    public List<InventoryLog> getByInventoryId(@PathVariable Long inventoryId) {
-        return inventoryLogService.getAll();
+    public PageResponse<InventoryLog> getByInventoryId(
+            @PathVariable Long inventoryId,
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "20") int size) {
+        Page<InventoryLog> pageResult = inventoryLogService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/log/{id}")

+ 5 - 2
backend/src/main/java/com/oms/controller/InventoryTurnoverController.java

@@ -6,6 +6,8 @@ import com.oms.service.InventoryTurnoverService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class InventoryTurnoverController {
     private final InventoryTurnoverService inventoryTurnoverService;
 
     @GetMapping
-    public List<InventoryTurnover> getInventoryTurnovers(
+    public PageResponse<InventoryTurnover> getInventoryTurnovers(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return inventoryTurnoverService.getPage(page, size).getRecords();
+        Page<InventoryTurnover> pageResult = inventoryTurnoverService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/InvoiceController.java

@@ -6,6 +6,8 @@ import com.oms.service.InvoiceService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -16,10 +18,11 @@ public class InvoiceController {
     private final InvoiceService invoiceService;
 
     @GetMapping
-    public List<Invoice> getInvoices(
+    public PageResponse<Invoice> getInvoices(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return invoiceService.getPage(page, size).getRecords();
+        Page<Invoice> pageResult = invoiceService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 4 - 2
backend/src/main/java/com/oms/controller/IqcController.java

@@ -6,6 +6,8 @@ import com.oms.service.IqcService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.List;
+
 @RestController
 @RequestMapping("/purchase")
 @RequiredArgsConstructor
@@ -14,8 +16,8 @@ public class IqcController {
     private final IqcService iqcService;
 
     @GetMapping("/{arrivalId}/iqc")
-    public IqcDTO getByArrivalId(@PathVariable Long arrivalId) {
-        return iqcService.getDtoById(arrivalId);
+    public List<Iqc> getByArrivalId(@PathVariable Long arrivalId) {
+        return iqcService.getByArrivalId(arrivalId);
     }
 
     @GetMapping("/iqc/{id}")

+ 5 - 2
backend/src/main/java/com/oms/controller/KnowledgeBaseController.java

@@ -6,6 +6,8 @@ import com.oms.service.KnowledgeBaseService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class KnowledgeBaseController {
     private final KnowledgeBaseService knowledgeBaseService;
 
     @GetMapping
-    public List<KnowledgeBase> getKnowledgeBases(
+    public PageResponse<KnowledgeBase> getKnowledgeBases(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return knowledgeBaseService.getPage(page, size).getRecords();
+        Page<KnowledgeBase> pageResult = knowledgeBaseService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/KnowledgeCategoryController.java

@@ -6,6 +6,8 @@ import com.oms.service.KnowledgeCategoryService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class KnowledgeCategoryController {
     private final KnowledgeCategoryService knowledgeCategoryService;
 
     @GetMapping
-    public List<KnowledgeCategory> getKnowledgeCategories(
+    public PageResponse<KnowledgeCategory> getKnowledgeCategories(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return knowledgeCategoryService.getPage(page, size).getRecords();
+        Page<KnowledgeCategory> pageResult = knowledgeCategoryService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/LogisticsProviderController.java

@@ -6,6 +6,8 @@ import com.oms.service.LogisticsProviderService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -16,10 +18,11 @@ public class LogisticsProviderController {
     private final LogisticsProviderService logisticsProviderService;
 
     @GetMapping
-    public List<LogisticsProvider> getProviders(
+    public PageResponse<LogisticsProvider> getProviders(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return logisticsProviderService.getPage(page, size).getRecords();
+        Page<LogisticsProvider> pageResult = logisticsProviderService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/PriceWatchController.java

@@ -6,6 +6,8 @@ import com.oms.service.PriceWatchService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class PriceWatchController {
     private final PriceWatchService priceWatchService;
 
     @GetMapping
-    public List<PriceWatch> getPriceWatches(
+    public PageResponse<PriceWatch> getPriceWatches(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return priceWatchService.getPage(page, size).getRecords();
+        Page<PriceWatch> pageResult = priceWatchService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 7 - 2
backend/src/main/java/com/oms/controller/PricingRuleController.java

@@ -1,6 +1,8 @@
 package com.oms.controller;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.oms.common.ApiResponse;
+import com.oms.dto.PageResponse;
 import com.oms.dto.PricingRuleDTO;
 import com.oms.entity.PricingRule;
 import com.oms.service.PricingRuleService;
@@ -17,10 +19,13 @@ public class PricingRuleController {
     private final PricingRuleService pricingRuleService;
 
     @GetMapping
-    public ApiResponse<List<PricingRule>> getPricingRules(
+    public PageResponse<PricingRule> getPricingRules(
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "20") int size,
             @RequestParam(required = false) String ruleType,
             @RequestParam(required = false) String status) {
-        return ApiResponse.success(pricingRuleService.listRules(ruleType, status));
+        Page<PricingRule> pageResult = pricingRuleService.getPage(page, size, ruleType, status);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/{id}")

+ 5 - 2
backend/src/main/java/com/oms/controller/ProductCategoryController.java

@@ -5,6 +5,8 @@ import com.oms.service.ProductCategoryService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class ProductCategoryController {
     private final ProductCategoryService productCategoryService;
 
     @GetMapping
-    public List<ProductCategory> getCategories(
+    public PageResponse<ProductCategory> getCategories(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return productCategoryService.getCategories(page, size).getRecords();
+        Page<ProductCategory> pageResult = productCategoryService.getCategories(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/tree")

+ 5 - 2
backend/src/main/java/com/oms/controller/ProductSkuController.java

@@ -5,6 +5,8 @@ import com.oms.service.ProductSkuService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class ProductSkuController {
     private final ProductSkuService productSkuService;
 
     @GetMapping
-    public List<ProductSku> getSkus(
+    public PageResponse<ProductSku> getSkus(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return productSkuService.getSkus(page, size).getRecords();
+        Page<ProductSku> pageResult = productSkuService.getSkus(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/product/{productId}")

+ 5 - 2
backend/src/main/java/com/oms/controller/PromotionController.java

@@ -6,6 +6,8 @@ import com.oms.service.PromotionService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class PromotionController {
     private final PromotionService promotionService;
 
     @GetMapping
-    public List<Promotion> getPromotions(
+    public PageResponse<Promotion> getPromotions(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return promotionService.getPage(page, size).getRecords();
+        Page<Promotion> pageResult = promotionService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/PurchaseOrderController.java

@@ -6,6 +6,8 @@ import com.oms.service.PurchaseOrderService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -16,10 +18,11 @@ public class PurchaseOrderController {
     private final PurchaseOrderService purchaseOrderService;
 
     @GetMapping
-    public List<PurchaseOrder> getOrders(
+    public PageResponse<PurchaseOrder> getOrders(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return purchaseOrderService.getPage(page, size).getRecords();
+        Page<PurchaseOrder> pageResult = purchaseOrderService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 7 - 2
backend/src/main/java/com/oms/controller/PurchaseRequestController.java

@@ -1,5 +1,7 @@
 package com.oms.controller;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import com.oms.dto.PurchaseRequestDTO;
 import com.oms.entity.PurchaseRequest;
 import com.oms.service.PurchaseRequestService;
@@ -16,8 +18,11 @@ public class PurchaseRequestController {
     private final PurchaseRequestService purchaseRequestService;
 
     @GetMapping
-    public List<PurchaseRequest> getAll() {
-        return purchaseRequestService.getAll();
+    public PageResponse<PurchaseRequest> getPurchaseRequests(
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "20") int size) {
+        Page<PurchaseRequest> pageResult = purchaseRequestService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/{id}")

+ 7 - 2
backend/src/main/java/com/oms/controller/ReplenishmentPlanController.java

@@ -1,5 +1,7 @@
 package com.oms.controller;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import com.oms.dto.ReplenishmentPlanDTO;
 import com.oms.entity.ReplenishmentPlan;
 import com.oms.service.ReplenishmentPlanService;
@@ -16,8 +18,11 @@ public class ReplenishmentPlanController {
     private final ReplenishmentPlanService replenishmentPlanService;
 
     @GetMapping
-    public List<ReplenishmentPlan> getAll() {
-        return replenishmentPlanService.getAll();
+    public PageResponse<ReplenishmentPlan> getReplenishmentPlans(
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "20") int size) {
+        Page<ReplenishmentPlan> pageResult = replenishmentPlanService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/{id}")

+ 7 - 2
backend/src/main/java/com/oms/controller/ReportController.java

@@ -1,6 +1,8 @@
 package com.oms.controller;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.oms.common.ApiResponse;
+import com.oms.dto.PageResponse;
 import com.oms.dto.ReportDTO;
 import com.oms.entity.Report;
 import com.oms.service.ReportService;
@@ -17,10 +19,13 @@ public class ReportController {
     private final ReportService reportService;
 
     @GetMapping
-    public ApiResponse<List<Report>> getReports(
+    public PageResponse<Report> getReports(
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "20") int size,
             @RequestParam(required = false) String reportType,
             @RequestParam(required = false) String status) {
-        return ApiResponse.success(reportService.listReports(reportType, status));
+        Page<Report> pageResult = reportService.getPage(page, size, reportType, status);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/{id}")

+ 8 - 2
backend/src/main/java/com/oms/controller/ReportDataController.java

@@ -1,6 +1,8 @@
 package com.oms.controller;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.oms.common.ApiResponse;
+import com.oms.dto.PageResponse;
 import com.oms.dto.ReportDataDTO;
 import com.oms.entity.ReportData;
 import com.oms.service.ReportDataService;
@@ -17,8 +19,12 @@ public class ReportDataController {
     private final ReportDataService reportDataService;
 
     @GetMapping
-    public ApiResponse<List<ReportData>> getReportData(@RequestParam Long reportId) {
-        return ApiResponse.success(reportDataService.listByReportId(reportId));
+    public PageResponse<ReportData> getReportData(
+            @RequestParam(required = false) Long reportId,
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "20") int size) {
+        Page<ReportData> pageResult = reportDataService.getPage(page, size, reportId);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/{id}")

+ 5 - 2
backend/src/main/java/com/oms/controller/ReturnPackageController.java

@@ -6,6 +6,8 @@ import com.oms.service.ReturnPackageService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -16,10 +18,11 @@ public class ReturnPackageController {
     private final ReturnPackageService returnPackageService;
 
     @GetMapping
-    public List<ReturnPackage> getReturns(
+    public PageResponse<ReturnPackage> getReturns(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return returnPackageService.getPage(page, size).getRecords();
+        Page<ReturnPackage> pageResult = returnPackageService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 7 - 2
backend/src/main/java/com/oms/controller/SatisfactionController.java

@@ -1,6 +1,8 @@
 package com.oms.controller;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.oms.common.ApiResponse;
+import com.oms.dto.PageResponse;
 import com.oms.dto.SatisfactionDTO;
 import com.oms.entity.Satisfaction;
 import com.oms.service.SatisfactionService;
@@ -17,9 +19,12 @@ public class SatisfactionController {
     private final SatisfactionService satisfactionService;
 
     @GetMapping
-    public ApiResponse<List<Satisfaction>> getSatisfactions(
+    public PageResponse<Satisfaction> getSatisfactions(
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "20") int size,
             @RequestParam(required = false) String rating) {
-        return ApiResponse.success(satisfactionService.listSatisfactions(rating));
+        Page<Satisfaction> pageResult = satisfactionService.getPage(page, size, rating);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/{id}")

+ 5 - 2
backend/src/main/java/com/oms/controller/ServicePerformanceController.java

@@ -6,6 +6,8 @@ import com.oms.service.ServicePerformanceService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class ServicePerformanceController {
     private final ServicePerformanceService servicePerformanceService;
 
     @GetMapping
-    public List<ServicePerformance> getServicePerformances(
+    public PageResponse<ServicePerformance> getServicePerformances(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return servicePerformanceService.getPage(page, size).getRecords();
+        Page<ServicePerformance> pageResult = servicePerformanceService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/ShippingOrderController.java

@@ -6,6 +6,8 @@ import com.oms.service.ShippingOrderService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -16,10 +18,11 @@ public class ShippingOrderController {
     private final ShippingOrderService shippingOrderService;
 
     @GetMapping
-    public List<ShippingOrder> getShippingOrders(
+    public PageResponse<ShippingOrder> getShippingOrders(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return shippingOrderService.getPage(page, size).getRecords();
+        Page<ShippingOrder> pageResult = shippingOrderService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/ShippingTemplateController.java

@@ -6,6 +6,8 @@ import com.oms.service.ShippingTemplateService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -16,10 +18,11 @@ public class ShippingTemplateController {
     private final ShippingTemplateService shippingTemplateService;
 
     @GetMapping
-    public List<ShippingTemplate> getTemplates(
+    public PageResponse<ShippingTemplate> getTemplates(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return shippingTemplateService.getPage(page, size).getRecords();
+        Page<ShippingTemplate> pageResult = shippingTemplateService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/SupplierController.java

@@ -6,6 +6,8 @@ import com.oms.service.SupplierService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -16,10 +18,11 @@ public class SupplierController {
     private final SupplierService supplierService;
 
     @GetMapping
-    public List<Supplier> getSuppliers(
+    public PageResponse<Supplier> getSuppliers(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return supplierService.getPage(page, size).getRecords();
+        Page<Supplier> pageResult = supplierService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/SupplierPerformanceController.java

@@ -6,6 +6,8 @@ import com.oms.service.SupplierPerformanceService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class SupplierPerformanceController {
     private final SupplierPerformanceService supplierPerformanceService;
 
     @GetMapping
-    public List<SupplierPerformance> getSupplierPerformances(
+    public PageResponse<SupplierPerformance> getSupplierPerformances(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return supplierPerformanceService.getPage(page, size).getRecords();
+        Page<SupplierPerformance> pageResult = supplierPerformanceService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/SupplierSettlementController.java

@@ -6,6 +6,8 @@ import com.oms.service.SupplierSettlementService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -16,10 +18,11 @@ public class SupplierSettlementController {
     private final SupplierSettlementService supplierSettlementService;
 
     @GetMapping
-    public List<SupplierSettlement> getSettlements(
+    public PageResponse<SupplierSettlement> getSettlements(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return supplierSettlementService.getPage(page, size).getRecords();
+        Page<SupplierSettlement> pageResult = supplierSettlementService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 7 - 2
backend/src/main/java/com/oms/controller/SupplyCapabilityController.java

@@ -1,6 +1,8 @@
 package com.oms.controller;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.oms.common.ApiResponse;
+import com.oms.dto.PageResponse;
 import com.oms.dto.SupplyCapabilityDTO;
 import com.oms.entity.SupplyCapability;
 import com.oms.service.SupplyCapabilityService;
@@ -27,8 +29,11 @@ public class SupplyCapabilityController {
     }
 
     @GetMapping("/capabilities")
-    public ApiResponse<List<SupplyCapability>> getAll() {
-        return ApiResponse.success(supplyCapabilityService.getAll());
+    public PageResponse<SupplyCapability> getAll(
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "20") int size) {
+        Page<SupplyCapability> pageResult = supplyCapabilityService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/capability/{id}")

+ 4 - 2
backend/src/main/java/com/oms/controller/SysApiKeyController.java

@@ -1,6 +1,7 @@
 package com.oms.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.oms.dto.PageResponse;
 import com.oms.entity.SysApiKey;
 import com.oms.service.SysApiKeyService;
 import lombok.RequiredArgsConstructor;
@@ -14,9 +15,10 @@ public class SysApiKeyController {
     private final SysApiKeyService sysApiKeyService;
 
     @GetMapping
-    public IPage<SysApiKey> list(@RequestParam(defaultValue = "1") long page,
+    public PageResponse<SysApiKey> list(@RequestParam(defaultValue = "1") long page,
                                  @RequestParam(defaultValue = "10") long size) {
-        return sysApiKeyService.getApiKeys(page, size);
+        IPage<SysApiKey> pageResult = sysApiKeyService.getApiKeys(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/{id}")

+ 5 - 2
backend/src/main/java/com/oms/controller/SysApprovalFlowController.java

@@ -6,6 +6,8 @@ import com.oms.service.SysApprovalFlowService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class SysApprovalFlowController {
     private final SysApprovalFlowService sysApprovalFlowService;
 
     @GetMapping
-    public List<SysApprovalFlow> getSysApprovalFlows(
+    public PageResponse<SysApprovalFlow> getSysApprovalFlows(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return sysApprovalFlowService.getPage(page, size).getRecords();
+        Page<SysApprovalFlow> pageResult = sysApprovalFlowService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/SysDepartmentController.java

@@ -5,6 +5,8 @@ import com.oms.service.SysDepartmentService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class SysDepartmentController {
     private final SysDepartmentService sysDepartmentService;
 
     @GetMapping
-    public List<SysDepartment> getDepartments(
+    public PageResponse<SysDepartment> getDepartments(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return sysDepartmentService.getDepartments(page, size).getRecords();
+        Page<SysDepartment> pageResult = sysDepartmentService.getDepartments(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/tree")

+ 5 - 2
backend/src/main/java/com/oms/controller/SysEmployeeController.java

@@ -5,6 +5,8 @@ import com.oms.service.SysEmployeeService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class SysEmployeeController {
     private final SysEmployeeService sysEmployeeService;
 
     @GetMapping
-    public List<SysEmployee> getEmployees(
+    public PageResponse<SysEmployee> getEmployees(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return sysEmployeeService.getEmployees(page, size).getRecords();
+        Page<SysEmployee> pageResult = sysEmployeeService.getEmployees(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 5 - 2
backend/src/main/java/com/oms/controller/SysMessageTemplateController.java

@@ -6,6 +6,8 @@ import com.oms.service.SysMessageTemplateService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -15,10 +17,11 @@ public class SysMessageTemplateController {
     private final SysMessageTemplateService sysMessageTemplateService;
 
     @GetMapping
-    public List<SysMessageTemplate> getSysMessageTemplates(
+    public PageResponse<SysMessageTemplate> getSysMessageTemplates(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return sysMessageTemplateService.getPage(page, size).getRecords();
+        Page<SysMessageTemplate> pageResult = sysMessageTemplateService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 4 - 2
backend/src/main/java/com/oms/controller/SysNotificationController.java

@@ -1,6 +1,7 @@
 package com.oms.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.oms.dto.PageResponse;
 import com.oms.entity.SysNotification;
 import com.oms.service.SysNotificationService;
 import lombok.RequiredArgsConstructor;
@@ -14,10 +15,11 @@ public class SysNotificationController {
     private final SysNotificationService sysNotificationService;
 
     @GetMapping
-    public IPage<SysNotification> list(@RequestParam(defaultValue = "1") long page,
+    public PageResponse<SysNotification> list(@RequestParam(defaultValue = "1") long page,
                                       @RequestParam(defaultValue = "10") long size,
                                       @RequestParam String userId) {
-        return sysNotificationService.getNotifications(page, size, userId);
+        IPage<SysNotification> pageResult = sysNotificationService.getNotifications(page, size, userId);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/{id}")

+ 4 - 2
backend/src/main/java/com/oms/controller/SysOperationLogController.java

@@ -1,6 +1,7 @@
 package com.oms.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.oms.dto.PageResponse;
 import com.oms.entity.SysOperationLog;
 import com.oms.service.SysOperationLogService;
 import lombok.RequiredArgsConstructor;
@@ -14,9 +15,10 @@ public class SysOperationLogController {
     private final SysOperationLogService sysOperationLogService;
 
     @GetMapping
-    public IPage<SysOperationLog> list(@RequestParam(defaultValue = "1") long page,
+    public PageResponse<SysOperationLog> list(@RequestParam(defaultValue = "1") long page,
                                        @RequestParam(defaultValue = "10") long size) {
-        return sysOperationLogService.getLogs(page, size);
+        IPage<SysOperationLog> pageResult = sysOperationLogService.getLogs(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/{id}")

+ 4 - 2
backend/src/main/java/com/oms/controller/SysRoleController.java

@@ -1,6 +1,7 @@
 package com.oms.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.oms.dto.PageResponse;
 import com.oms.entity.SysRole;
 import com.oms.service.SysRoleService;
 import lombok.RequiredArgsConstructor;
@@ -14,9 +15,10 @@ public class SysRoleController {
     private final SysRoleService sysRoleService;
 
     @GetMapping
-    public IPage<SysRole> list(@RequestParam(defaultValue = "1") long page,
+    public PageResponse<SysRole> list(@RequestParam(defaultValue = "1") long page,
                                @RequestParam(defaultValue = "10") long size) {
-        return sysRoleService.getRoles(page, size);
+        IPage<SysRole> pageResult = sysRoleService.getRoles(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/{id}")

+ 4 - 2
backend/src/main/java/com/oms/controller/SysUserController.java

@@ -1,6 +1,7 @@
 package com.oms.controller;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import com.oms.entity.SysUser;
 import com.oms.service.SysUserService;
 import lombok.RequiredArgsConstructor;
@@ -16,10 +17,11 @@ public class SysUserController {
     private final SysUserService sysUserService;
 
     @GetMapping
-    public Page<SysUser> getUsers(
+    public PageResponse<SysUser> getUsers(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return sysUserService.getUsers(page, size);
+        Page<SysUser> pageResult = sysUserService.getUsers(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 7 - 2
backend/src/main/java/com/oms/controller/TicketController.java

@@ -1,6 +1,8 @@
 package com.oms.controller;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.oms.common.ApiResponse;
+import com.oms.dto.PageResponse;
 import com.oms.dto.TicketDTO;
 import com.oms.entity.Ticket;
 import com.oms.service.TicketService;
@@ -18,10 +20,13 @@ public class TicketController {
     private final TicketService ticketService;
 
     @GetMapping
-    public ApiResponse<List<Ticket>> getTickets(
+    public PageResponse<Ticket> getTickets(
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "20") int size,
             @RequestParam(required = false) String status,
             @RequestParam(required = false) String priority) {
-        return ApiResponse.success(ticketService.listTickets(status, priority));
+        Page<Ticket> pageResult = ticketService.getPage(page, size, status, priority);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/{id}")

+ 5 - 2
backend/src/main/java/com/oms/controller/WarehouseController.java

@@ -6,6 +6,8 @@ import com.oms.service.WarehouseService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.oms.dto.PageResponse;
 import java.util.List;
 
 @RestController
@@ -16,10 +18,11 @@ public class WarehouseController {
     private final WarehouseService warehouseService;
 
     @GetMapping
-    public List<Warehouse> getWarehouses(
+    public PageResponse<Warehouse> getWarehouses(
             @RequestParam(defaultValue = "1") int page,
             @RequestParam(defaultValue = "20") int size) {
-        return warehouseService.getPage(page, size).getRecords();
+        Page<Warehouse> pageResult = warehouseService.getPage(page, size);
+        return PageResponse.of(pageResult.getRecords(), pageResult.getTotal(), (int) pageResult.getCurrent(), (int) pageResult.getSize());
     }
 
     @GetMapping("/all")

+ 12 - 0
backend/src/main/java/com/oms/dto/InventoryOperationRequest.java

@@ -0,0 +1,12 @@
+package com.oms.dto;
+
+import lombok.Data;
+
+@Data
+public class InventoryOperationRequest {
+    private int qty;
+    private String operator;
+    private String changeType;
+    private Long orderId;
+    private String orderNo;
+}

+ 9 - 0
backend/src/main/java/com/oms/service/ChatLogService.java

@@ -1,6 +1,7 @@
 package com.oms.service;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.oms.entity.ChatLog;
 import com.oms.mapper.ChatLogMapper;
 import com.oms.dto.ChatLogDTO;
@@ -22,6 +23,14 @@ public class ChatLogService {
         return mapper.selectList(wrapper);
     }
 
+    public Page<ChatLog> getPage(int page, int size, String sessionId, String status) {
+        LambdaQueryWrapper<ChatLog> wrapper = new LambdaQueryWrapper<>();
+        if (sessionId != null) wrapper.eq(ChatLog::getSessionId, sessionId);
+        if (status != null) wrapper.eq(ChatLog::getStatus, status);
+        wrapper.orderByDesc(ChatLog::getCreatedAt);
+        return mapper.selectPage(new Page<>(page, size), wrapper);
+    }
+
     public ChatLog getChatLog(Long id) {
         return mapper.selectById(id);
     }

+ 9 - 0
backend/src/main/java/com/oms/service/PricingRuleService.java

@@ -1,6 +1,7 @@
 package com.oms.service;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.oms.entity.PricingRule;
 import com.oms.mapper.PricingRuleMapper;
 import com.oms.dto.PricingRuleDTO;
@@ -25,6 +26,14 @@ public class PricingRuleService {
         return mapper.selectList(wrapper);
     }
 
+    public Page<PricingRule> getPage(int page, int size, String ruleType, String status) {
+        LambdaQueryWrapper<PricingRule> wrapper = new LambdaQueryWrapper<>();
+        if (ruleType != null) wrapper.eq(PricingRule::getRuleType, ruleType);
+        if (status != null) wrapper.eq(PricingRule::getStatus, status);
+        wrapper.orderByDesc(PricingRule::getCreatedAt);
+        return mapper.selectPage(new Page<>(page, size), wrapper);
+    }
+
     public PricingRule getRule(Long id) {
         return mapper.selectById(id);
     }

+ 8 - 0
backend/src/main/java/com/oms/service/ReportDataService.java

@@ -1,6 +1,7 @@
 package com.oms.service;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.oms.entity.ReportData;
 import com.oms.mapper.ReportDataMapper;
 import com.oms.dto.ReportDataDTO;
@@ -20,6 +21,13 @@ public class ReportDataService {
         return mapper.selectList(wrapper);
     }
 
+    public Page<ReportData> getPage(int page, int size, Long reportId) {
+        LambdaQueryWrapper<ReportData> wrapper = new LambdaQueryWrapper<>();
+        if (reportId != null) wrapper.eq(ReportData::getReportId, reportId);
+        wrapper.orderByDesc(ReportData::getCreatedAt);
+        return mapper.selectPage(new Page<>(page, size), wrapper);
+    }
+
     public ReportData getReportData(Long id) {
         return mapper.selectById(id);
     }

+ 9 - 0
backend/src/main/java/com/oms/service/ReportService.java

@@ -1,6 +1,7 @@
 package com.oms.service;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.oms.entity.*;
 import com.oms.enums.*;
@@ -32,6 +33,14 @@ public class ReportService {
         return mapper.selectList(wrapper);
     }
 
+    public Page<Report> getPage(int page, int size, String reportType, String status) {
+        LambdaQueryWrapper<Report> wrapper = new LambdaQueryWrapper<>();
+        if (reportType != null) wrapper.eq(Report::getReportType, reportType);
+        if (status != null) wrapper.eq(Report::getStatus, status);
+        wrapper.orderByDesc(Report::getCreatedAt);
+        return mapper.selectPage(new Page<>(page, size), wrapper);
+    }
+
     public Report getReport(Long id) { return mapper.selectById(id); }
 
     public Report createReport(ReportDTO dto) {

+ 8 - 0
backend/src/main/java/com/oms/service/SatisfactionService.java

@@ -1,6 +1,7 @@
 package com.oms.service;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.oms.entity.Satisfaction;
 import com.oms.mapper.SatisfactionMapper;
 import com.oms.dto.SatisfactionDTO;
@@ -21,6 +22,13 @@ public class SatisfactionService {
         return mapper.selectList(wrapper);
     }
 
+    public Page<Satisfaction> getPage(int page, int size, String rating) {
+        LambdaQueryWrapper<Satisfaction> wrapper = new LambdaQueryWrapper<>();
+        if (rating != null) wrapper.eq(Satisfaction::getRating, rating);
+        wrapper.orderByDesc(Satisfaction::getCreatedAt);
+        return mapper.selectPage(new Page<>(page, size), wrapper);
+    }
+
     public Satisfaction getSatisfaction(Long id) {
         return mapper.selectById(id);
     }

+ 9 - 0
backend/src/main/java/com/oms/service/TicketService.java

@@ -1,6 +1,7 @@
 package com.oms.service;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.oms.entity.Ticket;
 import com.oms.enums.Priority;
 import com.oms.enums.TicketStatus;
@@ -42,6 +43,14 @@ public class TicketService {
         return mapper.selectList(wrapper);
     }
 
+    public Page<Ticket> getPage(int page, int size, String status, String priority) {
+        LambdaQueryWrapper<Ticket> wrapper = new LambdaQueryWrapper<>();
+        if (status != null) wrapper.eq(Ticket::getStatus, status);
+        if (priority != null) wrapper.eq(Ticket::getPriority, priority);
+        wrapper.orderByDesc(Ticket::getCreatedAt);
+        return mapper.selectPage(new Page<>(page, size), wrapper);
+    }
+
     public Ticket getTicket(Long id) { return mapper.selectById(id); }
 
     @Transactional

+ 0 - 207
design-system.md

@@ -1,207 +0,0 @@
-# CrossBorder OMS 设计系统
-
-## 设计理念
-**专业、高效、数据驱动** - 为跨境电商订单管理系统打造的现代化界面设计
-
----
-
-## 配色方案
-
-### 主色调 (Primary)
-用于主要操作、导航、重要链接
-
-| 变量 | 值 | 用途 |
-|------|-----|------|
-| `--cb-primary` | `#0284C7` | 主色(天空蓝) |
-| `--cb-primary-hover` | `#0369A1` | 悬停状态 |
-| `--cb-primary-soft` | `#E0F2FE` | 浅色背景 |
-| `--cb-primary-strong` | `#0C4A6E` | 深色强调 |
-
-### 辅助色 (Accent)
-用于次要操作、装饰元素、数据高亮
-
-| 变量 | 值 | 用途 |
-|------|-----|------|
-| `--cb-accent` | `#F59E0B` | 强调色(琥珀金) |
-| `--cb-accent-soft` | `#FEF3C7` | 浅色背景 |
-| `--cb-accent-hover` | `#D97706` | 悬停状态 |
-
-### 功能色
-用于状态指示、反馈信息
-
-| 变量 | 值 | 用途 |
-|------|-----|------|
-| `--cb-success` | `#059669` | 成功、完成 |
-| `--cb-success-soft` | `#D1FAE5` | 成功背景 |
-| `--cb-danger` | `#DC2626` | 错误、危险 |
-| `--cb-danger-soft` | `#FEE2E2` | 错误背景 |
-| `--cb-warning` | `#D97706` | 警告 |
-| `--cb-warning-soft` | `#FEF3C7` | 警告背景 |
-| `--cb-info` | `#0284C7` | 信息 |
-| `--cb-info-soft` | `#E0F2FE` | 信息背景 |
-
-### 中性色
-用于背景、边框、文字
-
-| 变量 | 值 | 用途 |
-|------|-----|------|
-| `--cb-bg` | `#F8FAFC` | 页面背景 |
-| `--cb-bg-soft` | `#F1F5F9` | 次级背景 |
-| `--cb-panel` | `#FFFFFF` | 卡片/面板背景 |
-| `--cb-border` | `#E2E8F0` | 边框 |
-| `--cb-text` | `#0F172A` | 主文本(对比度 16.4:1)|
-| `--cb-text-soft` | `#475569` | 次级文本(对比度 7.2:1)|
-| `--cb-text-muted` | `#94A3B8` | 辅助文本(对比度 3.9:1)|
-
-### 阴影系统
-
-| 变量 | 值 | 用途 |
-|------|-----|------|
-| `--cb-shadow` | `0 1px 2px rgba(0,0,0,0.05)` | 轻微阴影 |
-| `--cb-shadow-sm` | `0 1px 3px rgba(0,0,0,0.08)` | 小阴影 |
-| `--cb-shadow-md` | `0 4px 8px rgba(0,0,0,0.08)` | 中等阴影 |
-| `--cb-shadow-lg` | `0 8px 16px rgba(0,0,0,0.10)` | 大阴影 |
-| `--cb-shadow-glow` | `0 0 0 3px rgba(2,132,199,0.15)` | 发光效果 |
-
----
-
-## 字体系统
-
-### 字体族
-```
---cb-font-family: "Inter", "SF Pro Display", "HarmonyOS Sans SC", "PingFang SC", sans-serif
---cb-font-mono: "JetBrains Mono", "Fira Code", "Consolas", monospace
-```
-
-### 字体大小
-
-| 级别 | 大小 | 字重 | 用途 |
-|------|------|------|------|
-| XS | 11px | 500 | 标签、徽章 |
-| SM | 12px | 500 | 辅助信息 |
-| Base | 13px | 400 | 正文、表格 |
-| MD | 14px | 500 | 次级标题 |
-| LG | 16px | 600 | 卡片标题 |
-| XL | 18px | 600 | 页面标题 |
-| 2XL | 24px | 700 | 主标题 |
-| 3XL | 32px | 700 | 特大标题 |
-
-### 行高
-- 正文:1.6
-- 标题:1.3
-- 紧凑:1.4
-
----
-
-## 间距系统
-
-使用 4px 基础单位的倍数:
-
-| 名称 | 值 | 用途 |
-|------|-----|------|
-| --cb-space-1 | 4px | 最小间距 |
-| --cb-space-2 | 8px | 小间距 |
-| --cb-space-3 | 12px | 默认间距 |
-| --cb-space-4 | 16px | 中等间距 |
-| --cb-space-5 | 20px | 大间距 |
-| --cb-space-6 | 24px | 超大间距 |
-| --cb-space-8 | 32px | 章节间距 |
-
----
-
-## 组件规范
-
-### 按钮
-- 高度:36px(默认)、32px(小)、40px(大)
-- 圆角:6px
-- 内边距:0 16px
-- 过渡:150ms ease-out
-
-### 输入框
-- 高度:36px
-- 圆角:6px
-- 边框:1px solid var(--cb-border)
-- 聚焦边框:2px solid var(--cb-primary)
-
-### 卡片
-- 圆角:8px
-- 内边距:20px
-- 边框:1px solid var(--cb-border)
-- 阴影:var(--cb-shadow-sm)
-
-### 表格
-- 行高:44px
-- 边框:1px solid var(--cb-border)
-- 斑马纹:var(--cb-bg-soft)
-- 悬停:var(--cb-primary-soft)
-
-### 导航菜单
-- 项高度:40px(一级)、38px(二级)
-- 内边距:0 12px
-- 圆角:6px
-- 悬停背景:var(--cb-primary-soft)
-
----
-
-## 动画规范
-
-### 缓动函数
-```css
---cb-ease-out: cubic-bezier(0.33, 1, 0.68, 1)
---cb-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1)
-```
-
-### 持续时间
-- 微交互:150ms
-- 标准过渡:200ms
-- 复杂动画:300ms
-- 页面切换:400ms
-
----
-
-## 响应式断点
-
-| 断点 | 宽度 | 设备 |
-|------|------|------|
-| SM | 640px | 手机横屏 |
-| MD | 768px | 平板 |
-| LG | 1024px | 小笔记本 |
-| XL | 1280px | 桌面 |
-| 2XL | 1536px | 大屏 |
-
----
-
-## 最佳实践
-
-### 1. 可访问性
-- 所有交互元素必须有 `:hover` 和 `:focus` 状态
-- 颜色对比度至少 4.5:1
-- 使用语义化 HTML
-- 为图标按钮提供 aria-label
-
-### 2. 性能
-- 使用 `transform` 和 `opacity` 做动画
-- 避免频繁的 DOM 操作
-- 图片使用懒加载
-- 大列表使用虚拟滚动
-
-### 3. 一致性
-- 相同功能使用相同颜色
-- 保持统一的间距和圆角
-- 使用固定的 z-index 层级
-- 保持动画效果一致
-
----
-
-## 暗色模式支持
-
-预留暗色模式变量,使用 `prefers-color-scheme` 检测:
-
-```css
-@media (prefers-color-scheme: dark) {
-  --cb-bg: #0F172A;
-  --cb-panel: #1E293B;
-  --cb-text: #F1F5F9;
-  /* ... 更多变量 */
-}
-```

+ 5 - 5
frontend/src/api/services.ts

@@ -244,11 +244,11 @@ export const api = {
     request<InventoryItem>(`/api/inventory/inventories/${id}`, { method: 'PUT', body: JSON.stringify(data) }),
   deleteInventory: (id: number) =>
     request<void>(`/api/inventory/inventories/${id}`, { method: 'DELETE' }),
-  lockInventory: (id: number) =>
-    request<void>(`/api/inventory/inventories/${id}/lock`, { method: 'POST' }),
-  unlockInventory: (id: number) =>
-    request<void>(`/api/inventory/inventories/${id}/unlock`, { method: 'POST' }),
-  incrementInventory: (id: number, data: any) =>
+  lockInventory: (id: number, data: { qty: number; operator: string }) =>
+    request<void>(`/api/inventory/inventories/${id}/lock`, { method: 'POST', body: JSON.stringify(data) }),
+  unlockInventory: (id: number, data: { qty: number; operator: string }) =>
+    request<void>(`/api/inventory/inventories/${id}/unlock`, { method: 'POST', body: JSON.stringify(data) }),
+  incrementInventory: (id: number, data: { qty: number; changeType: string; operator: string; orderId?: number; orderNo?: string }) =>
     request<void>(`/api/inventory/inventories/${id}/increment`, { method: 'POST', body: JSON.stringify(data) }),
 
   /* Inventory Logs */