Browse Source

订单信息维护

klzhangweiya 1 month ago
parent
commit
9d736adeb5
66 changed files with 4929 additions and 258 deletions
  1. 10 1
      SERVER/ChickenFarmV3/.script/sql/new/data.sql
  2. 37 4
      SERVER/ChickenFarmV3/.script/sql/new/sysmenu.sql
  3. 1 0
      SERVER/ChickenFarmV3/vb-common/vb-common-core/src/main/java/cn/vber/common/core/constant/CacheNames.java
  4. 7 0
      SERVER/ChickenFarmV3/vb-common/vb-common-core/src/main/java/cn/vber/common/core/service/OrderItemService.java
  5. 1 0
      SERVER/ChickenFarmV3/vb-common/vb-common-translation/src/main/java/cn/vber/common/translation/constant/TransConstant.java
  6. 24 0
      SERVER/ChickenFarmV3/vb-common/vb-common-translation/src/main/java/cn/vber/common/translation/core/impl/OrderItemTranslationImpl.java
  7. 2 1
      SERVER/ChickenFarmV3/vb-common/vb-common-translation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  8. 52 0
      SERVER/ChickenFarmV3/vb-modules/vb-base/src/main/java/cn/vber/base/enums/OrderItemStatusEnum.java
  9. 5 1
      SERVER/ChickenFarmV3/vb-modules/vb-base/src/main/java/cn/vber/base/enums/OrderStatusEnum.java
  10. 103 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/controller/FeedbackController.java
  11. 32 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/controller/OrderController.java
  12. 7 5
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/controller/OrderItemController.java
  13. 103 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/controller/OrderSendController.java
  14. 103 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/controller/PayRecordController.java
  15. 103 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/controller/StatementBillController.java
  16. 59 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/Feedback.java
  17. 34 30
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/Order.java
  18. 74 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/OrderSend.java
  19. 60 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/PayRecord.java
  20. 80 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/StatementBill.java
  21. 57 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/bo/FeedbackBo.java
  22. 33 31
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/bo/OrderBo.java
  23. 74 67
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/bo/OrderItemBo.java
  24. 75 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/bo/OrderSendBo.java
  25. 58 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/bo/PayRecordBo.java
  26. 80 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/bo/StatementBillBo.java
  27. 64 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/vo/FeedbackVo.java
  28. 88 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/vo/OrderSendVo.java
  29. 8 2
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/vo/OrderVo.java
  30. 65 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/vo/PayRecordVo.java
  31. 98 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/vo/StatementBillVo.java
  32. 17 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/mapper/FeedbackMapper.java
  33. 6 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/mapper/OrderItemMapper.java
  34. 17 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/mapper/OrderSendMapper.java
  35. 17 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/mapper/PayRecordMapper.java
  36. 17 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/mapper/StatementBillMapper.java
  37. 49 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/IFeedbackService.java
  38. 49 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/IOrderSendService.java
  39. 9 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/IOrderService.java
  40. 49 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/IPayRecordService.java
  41. 49 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/IStatementBillService.java
  42. 112 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/impl/FeedbackServiceImpl.java
  43. 81 14
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/impl/OrderItemServiceImpl.java
  44. 140 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/impl/OrderSendServiceImpl.java
  45. 61 21
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/impl/OrderServiceImpl.java
  46. 112 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/impl/PayRecordServiceImpl.java
  47. 116 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/impl/StatementBillServiceImpl.java
  48. 7 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/resources/mapper/erp/FeedbackMapper.xml
  49. 7 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/resources/mapper/erp/OrderSendMapper.xml
  50. 7 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/resources/mapper/erp/PayRecordMapper.xml
  51. 7 0
      SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/resources/mapper/erp/StatementBillMapper.xml
  52. 67 0
      UI/VB.VUE/src/api/erp/_feedback.ts
  53. 28 0
      UI/VB.VUE/src/api/erp/_order.ts
  54. 8 0
      UI/VB.VUE/src/api/erp/_orderItem.ts
  55. 67 0
      UI/VB.VUE/src/api/erp/_orderSend.ts
  56. 67 0
      UI/VB.VUE/src/api/erp/_payRecord.ts
  57. 67 0
      UI/VB.VUE/src/api/erp/_statementBill.ts
  58. 13 1
      UI/VB.VUE/src/api/erp/index.ts
  59. 8 8
      UI/VB.VUE/src/components/modal-select/ExpectedProductionSelect.vue
  60. 5 1
      UI/VB.VUE/src/components/modal-select/ModalSelect.vue
  61. 129 0
      UI/VB.VUE/src/components/modal-select/OrderSelect.vue
  62. 251 0
      UI/VB.VUE/src/views/erp/sale/order/components/VbFeedbackModal.vue
  63. 249 0
      UI/VB.VUE/src/views/erp/sale/order/components/VbPayRecordModal.vue
  64. 676 71
      UI/VB.VUE/src/views/erp/sale/order/index.vue
  65. 388 0
      UI/VB.VUE/src/views/erp/sale/orderSend/index.vue
  66. 380 0
      UI/VB.VUE/src/views/erp/sale/statementBill/index.vue

+ 10 - 1
SERVER/ChickenFarmV3/.script/sql/new/data.sql

@@ -253,10 +253,19 @@ INSERT INTO `sys_dict_type` VALUES (640, '000000', '客户销售绑定状态', '
 INSERT INTO `sys_dict_data` VALUES (641, '000000', 1, '绑定', '1', 'customer_sale_bind_status', NULL, 'success', 'Y', 100, 1, '2025-07-21 09:53:31', 1, '2025-07-21 09:53:31', NULL);
 INSERT INTO `sys_dict_data` VALUES (642, '000000', 2, '已解绑', '2', 'customer_sale_bind_status', NULL, 'primary', 'Y', 100, 1, '2025-07-21 09:53:31', 1, '2025-07-21 09:53:31', NULL);
 
-INSERT INTO `sys_dict_type` VALUES (650, '000000', '订单状态', 'order_status', 100, 1, '2025-07-21 09:53:04', 1, '2025-07-21 09:53:04', '客户销售绑定状态:( 1:绑定 2:已解绑)');
+INSERT INTO `sys_dict_type` VALUES (650, '000000', '订单状态', 'order_status', 100, 1, '2025-07-21 09:53:04', 1, '2025-07-21 09:53:04', '订单状态:( 1:待审核 2:已审核 3:结清 4:退订中 5:已退订)');
 INSERT INTO `sys_dict_data` VALUES (651, '000000', 1, '待审核', '1', 'order_status', NULL, 'info', 'Y', 100, 1, '2025-07-21 09:53:31', 1, '2025-07-21 09:53:31', NULL);
 INSERT INTO `sys_dict_data` VALUES (652, '000000', 2, '已审核', '2', 'order_status', NULL, 'success', 'Y', 100, 1, '2025-07-21 09:53:31', 1, '2025-07-21 09:53:31', NULL);
 INSERT INTO `sys_dict_data` VALUES (653, '000000', 3, '已结清', '3', 'order_status', NULL, 'primary', 'Y', 100, 1, '2025-07-21 09:53:31', 1, '2025-07-21 09:53:31', NULL);
+INSERT INTO `sys_dict_data` VALUES (654, '000000', 4, '退订中', '4', 'order_status', NULL, 'warning', 'Y', 100, 1, '2025-07-21 09:53:31', 1, '2025-07-21 09:53:31', NULL);
+INSERT INTO `sys_dict_data` VALUES (655, '000000', 5, '已退订', '5', 'order_status', NULL, 'info', 'Y', 100, 1, '2025-07-21 09:53:31', 1, '2025-07-21 09:53:31', NULL);
+
+INSERT INTO `sys_dict_type` VALUES (660, '000000', '订单明细状态', 'order_item_status', 100, 1, '2025-07-21 09:53:04', 1, '2025-07-21 09:53:04', '订单明细状态:( 1:待审核 2:已审核 3:已发货 4:退订中 5:已退订)');
+INSERT INTO `sys_dict_data` VALUES (661, '000000', 1, '待审核', '1', 'order_item_status', NULL, 'info', 'Y', 100, 1, '2025-07-21 09:53:31', 1, '2025-07-21 09:53:31', NULL);
+INSERT INTO `sys_dict_data` VALUES (662, '000000', 2, '已审核', '2', 'order_item_status', NULL, 'success', 'Y', 100, 1, '2025-07-21 09:53:31', 1, '2025-07-21 09:53:31', NULL);
+INSERT INTO `sys_dict_data` VALUES (663, '000000', 3, '已发货', '3', 'order_item_status', NULL, 'primary', 'Y', 100, 1, '2025-07-21 09:53:31', 1, '2025-07-21 09:53:31', NULL);
+INSERT INTO `sys_dict_data` VALUES (664, '000000', 4, '退订中', '4', 'order_item_status', NULL, 'warning', 'Y', 100, 1, '2025-07-21 09:53:31', 1, '2025-07-21 09:53:31', NULL);
+INSERT INTO `sys_dict_data` VALUES (665, '000000', 5, '已退订', '5', 'order_item_status', NULL, 'info', 'Y', 100, 1, '2025-07-21 09:53:31', 1, '2025-07-21 09:53:31', NULL);
 
 
 

+ 37 - 4
SERVER/ChickenFarmV3/.script/sql/new/sysmenu.sql

@@ -488,7 +488,40 @@ INSERT INTO `sys_menu` VALUES (2444, '删除产能', 615, 3, '#', NULL, '', 1, 0
 INSERT INTO `sys_menu` VALUES (616, '订单管理', 43, 0, 'order', 'erp/sale/order/index', '', 1, 0, 'C', '0', '0', 'erp:order', '#', NULL, NULL, 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
 INSERT INTO `sys_menu` VALUES (2451, '查询订单', 616, 0, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:order:query', 'eye', '', '', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
 INSERT INTO `sys_menu` VALUES (2452, '新增订单', 616, 1, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:order:add', 'plus-square', 'btn btn-light-primary', 'handleCreate', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
-INSERT INTO `sys_menu` VALUES (2453, '修改订单', 616, 2, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:order:edit', 'pencil-square', 'btn btn-light-success', 'handleUpdate@1', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
-INSERT INTO `sys_menu` VALUES (2454, '删除订单', 616, 3, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:order:remove', 'dash-square', 'btn btn-light-danger', 'handleDelete@0', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
-INSERT INTO `sys_menu` VALUES (2455, '结清订单', 616, 4, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:order:complete', 'pencil-square', 'btn btn-light-danger', 'handleUpdate@1', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
-
+INSERT INTO `sys_menu` VALUES (2453, '修改订单', 616, 2, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:order:edit', 'pencil-square', 'btn btn-light-success', 'handleUpdate@1', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2454, '删除订单', 616, 3, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:order:remove', 'dash-square', 'btn btn-light-danger', 'handleDelete@0', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2455, '结清订单', 616, 4, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:order:complete', 'pencil-square', 'btn btn-light-danger', 'handleUpdate@1', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2456, '审核订单', 616, 5, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:order:audit', 'pencil-square', 'btn btn-light-danger', 'handleUpdate@1', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2457, '取消订单', 616, 6, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:order:cancel', 'pencil-square', 'btn btn-light-danger', 'handleUpdate@1', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2458, '审核取消订单', 616, 7, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:order:auditCancel', 'pencil-square', 'btn btn-light-danger', 'handleUpdate@1', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+
+INSERT INTO `sys_menu` VALUES (617, '订单明细管理', 43, 0, 'orderItem', 'erp/sale/orderItem/index', '', 1, 0, 'C', '1', '0', 'erp:orderItem', '#', NULL, NULL, 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2461, '查询订单明细', 617, 0, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:orderItem:query', 'eye', '', '', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2462, '新增订单明细', 617, 1, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:orderItem:add', 'plus-square', 'btn btn-light-primary', 'handleCreate', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2463, '修改订单明细', 617, 2, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:orderItem:edit', 'pencil-square', 'btn btn-light-success', 'handleUpdate@1', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2464, '删除订单明细', 617, 3, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:orderItem:remove', 'dash-square', 'btn btn-light-danger', 'handleDelete@0', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2465, '订单发货', 617, 4, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:orderItem:remove', 'dash-square', 'btn btn-light-danger', 'handleUpdate@1', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+
+INSERT INTO `sys_menu` VALUES (618, '订单发货管理', 43, 0, 'orderSend', 'erp/sale/orderSend/index', '', 1, 0, 'C', '0', '0', 'erp:orderSend', '#', NULL, NULL, 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2471, '查询发货', 618, 0, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:orderSend:query', 'eye', '', '', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2472, '新增发货', 618, 1, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:orderSend:add', 'plus-square', 'btn btn-light-primary', 'handleCreate', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2473, '修改发货', 618, 2, '#', NULL, '', 1, 0, 'F', '1', '1', 'erp:orderSend:edit', 'pencil-square', 'btn btn-light-success', 'handleUpdate@1', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2474, '删除发货', 618, 3, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:orderSend:remove', 'dash-square', 'btn btn-light-danger', 'handleDelete@0', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+
+INSERT INTO `sys_menu` VALUES (619, '订单回访管理', 43, 0, 'feedback', 'erp/sale/feedback/index', '', 1, 0, 'C', '1', '0', 'erp:feedback', '#', NULL, NULL, 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2481, '查询回访', 619, 0, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:feedback:query', 'eye', '', '', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2482, '新增回访', 619, 1, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:feedback:add', 'plus-square', 'btn btn-light-primary', 'handleCreate', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2483, '修改回访', 619, 2, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:feedback:edit', 'pencil-square', 'btn btn-light-success', 'handleUpdate@1', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2484, '删除回访', 619, 3, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:feedback:remove', 'dash-square', 'btn btn-light-danger', 'handleDelete@0', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+
+INSERT INTO `sys_menu` VALUES (620, '订单收款记录', 43, 0, 'payRecord', 'erp/sale/payRecord/index', '', 1, 0, 'C', '1', '0', 'erp:payRecord', '#', NULL, NULL, 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2491, '查询收款记录', 620, 0, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:payRecord:query', 'eye', '', '', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2492, '新增收款记录', 620, 1, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:payRecord:add', 'plus-square', 'btn btn-light-primary', 'handleCreate', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2493, '修改收款记录', 620, 2, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:payRecord:edit', 'pencil-square', 'btn btn-light-success', 'handleUpdate@1', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2494, '删除收款记录', 620, 3, '#', NULL, '', 1, 0, 'F', '1', '0', 'erp:payRecord:remove', 'dash-square', 'btn btn-light-danger', 'handleDelete@0', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+
+INSERT INTO `sys_menu` VALUES (621, '订单收款记录', 43, 0, 'statementBill', 'erp/sale/statementBill/index', '', 1, 0, 'C', '0', '0', 'erp:statementBill', '#', NULL, NULL, 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2501, '查询收款记录', 621, 0, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:statementBill:query', 'eye', '', '', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2502, '新增收款记录', 621, 1, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:statementBill:add', 'plus-square', 'btn btn-light-primary', 'handleCreate', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2503, '修改收款记录', 621, 2, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:statementBill:edit', 'pencil-square', 'btn btn-light-success', 'handleUpdate@1', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');
+INSERT INTO `sys_menu` VALUES (2504, '删除收款记录', 621, 3, '#', NULL, '', 1, 0, 'F', '0', '0', 'erp:statementBill:remove', 'dash-square', 'btn btn-light-danger', 'handleDelete@0', 100, 1, '2025-10-15 15:02:26', NULL, '2025-10-15 15:02:26', '');

+ 1 - 0
SERVER/ChickenFarmV3/vb-common/vb-common-core/src/main/java/cn/vber/common/core/constant/CacheNames.java

@@ -121,6 +121,7 @@ public interface CacheNames {
     String CUSTOMER_ID_TO_NUM = "customer_id_to_num";
     String CUSTOMER_ID_TO_NAME = "customer_id_to_name";
     String ORDER_ID_TO_NUM = "order_id_to_num";
+    String ORDER_ITEM_ID_TO_ORDER_NUM = "order_item_id_to_order_num";
 
 
 }

+ 7 - 0
SERVER/ChickenFarmV3/vb-common/vb-common-core/src/main/java/cn/vber/common/core/service/OrderItemService.java

@@ -0,0 +1,7 @@
+package cn.vber.common.core.service;
+
+public interface OrderItemService {
+
+    public String getOrderNum(Long itemId);
+
+}

+ 1 - 0
SERVER/ChickenFarmV3/vb-common/vb-common-translation/src/main/java/cn/vber/common/translation/constant/TransConstant.java

@@ -62,5 +62,6 @@ public interface TransConstant {
     String SUPPLIER_ID_TO_INFO = "supplier_id_to_info";
     String CUSTOMER_ID_TO_INFO = "customer_id_to_info";
     String ORDER_ID_TO_INFO = "order_id_to_info";
+    String ORDER_ITEM_ID_TO_INFO = "order_item_id_to_info";
 
 }

+ 24 - 0
SERVER/ChickenFarmV3/vb-common/vb-common-translation/src/main/java/cn/vber/common/translation/core/impl/OrderItemTranslationImpl.java

@@ -0,0 +1,24 @@
+package cn.vber.common.translation.core.impl;
+
+import cn.vber.common.core.service.OrderItemService;
+import cn.vber.common.core.service.OrderService;
+import cn.vber.common.translation.annotation.TranslationType;
+import cn.vber.common.translation.constant.TransConstant;
+import cn.vber.common.translation.core.TranslationInterface;
+import lombok.AllArgsConstructor;
+
+@AllArgsConstructor
+@TranslationType(type = TransConstant.ORDER_ITEM_ID_TO_INFO)
+public class OrderItemTranslationImpl implements TranslationInterface<String> {
+    private final OrderItemService orderItemService;
+
+    @Override
+    public String translation(Object key, String other) {
+        if (key instanceof Long id) {
+            return switch (other) {
+                default -> orderItemService.getOrderNum(id);
+            };
+        }
+        return null;
+    }
+}

+ 2 - 1
SERVER/ChickenFarmV3/vb-common/vb-common-translation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -25,4 +25,5 @@ cn.vber.common.translation.core.impl.SupplierTranslationImpl
 cn.vber.common.translation.core.impl.StoreUserTranslationImpl
 cn.vber.common.translation.core.impl.ProjectTranslationImpl
 cn.vber.common.translation.core.impl.OrderTranslationImpl
-cn.vber.common.translation.core.impl.CustomerTranslationImpl
+cn.vber.common.translation.core.impl.CustomerTranslationImpl
+cn.vber.common.translation.core.impl.OrderItemTranslationImpl

+ 52 - 0
SERVER/ChickenFarmV3/vb-modules/vb-base/src/main/java/cn/vber/base/enums/OrderItemStatusEnum.java

@@ -0,0 +1,52 @@
+package cn.vber.base.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum OrderItemStatusEnum {
+    /**
+     * 新建状态
+     */
+    WAIT_AUDIT(1, "待审核"),
+    /**
+     * 通过状态
+     */
+    PASSED(2, "通过"),
+    /**
+     * 已结清
+     */
+    SENDED(3, "已发货"),
+
+    canceling(4, "退订中"),
+
+    canceled(5, "已退订"),;
+    private final Integer code;
+    private final String description;
+    /**
+     * 根据code获取枚举对象
+     *
+     * @param code 状态码
+     * @return 对应的枚举对象,未找到返回null
+     */
+    public static OrderItemStatusEnum fromCode(Integer code) {
+        if (code == null) {
+            return null;
+        }
+        for (OrderItemStatusEnum status : OrderItemStatusEnum.values()) {
+            if (status.getCode().equals(code)) {
+                return status;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return "OrderItemStatusEnum{" +
+                "code=" + code +
+                ", description='" + description + '\'' +
+                '}';
+    }
+}

+ 5 - 1
SERVER/ChickenFarmV3/vb-modules/vb-base/src/main/java/cn/vber/base/enums/OrderStatusEnum.java

@@ -17,7 +17,11 @@ public enum OrderStatusEnum {
     /**
      * 已结清
      */
-    COMPLETED(3, "已结清");
+    COMPLETED(3, "已结清"),
+
+    canceling(4, "退订中"),
+
+    canceled(5, "已退订"),;
     private final Integer code;
     private final String description;
     /**

+ 103 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/controller/FeedbackController.java

@@ -0,0 +1,103 @@
+package cn.vber.erp.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import cn.vber.common.idempotent.annotation.RepeatSubmit;
+import cn.vber.common.log.annotation.Log;
+import cn.vber.common.web.core.BaseController;
+import cn.vber.common.mybatis.core.page.PageQuery;
+import cn.vber.common.core.domain.R;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import cn.vber.common.log.enums.BusinessType;
+import cn.vber.common.excel.utils.ExcelUtil;
+import cn.vber.erp.domain.vo.FeedbackVo;
+import cn.vber.erp.domain.bo.FeedbackBo;
+import cn.vber.erp.service.IFeedbackService;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 客户反馈记录
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/erp/feedback")
+public class FeedbackController extends BaseController {
+
+    private final IFeedbackService feedbackService;
+
+/**
+ * 查询客户反馈记录列表
+ */
+@SaCheckPermission("erp:feedback")
+@GetMapping("/list")
+    public TableDataInfo<FeedbackVo> list(FeedbackBo bo, PageQuery pageQuery) {
+        return feedbackService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出客户反馈记录列表
+     */
+    @SaCheckPermission("erp:feedback:export")
+    @Log(title = "客户反馈记录", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(FeedbackBo bo, HttpServletResponse response) {
+        List<FeedbackVo> list = feedbackService.queryList(bo);
+        ExcelUtil.exportExcel(list, "客户反馈记录", FeedbackVo.class, response);
+    }
+
+    /**
+     * 获取客户反馈记录详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("erp:feedback:query")
+    @GetMapping("/{id}")
+    public R<FeedbackVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
+        return R.ok(feedbackService.queryById(id));
+    }
+
+    /**
+     * 新增客户反馈记录
+     */
+    @SaCheckPermission("erp:feedback:add")
+    @Log(title = "客户反馈记录", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody FeedbackBo bo) {
+        return toAjax(feedbackService.insertByBo(bo));
+    }
+
+    /**
+     * 修改客户反馈记录
+     */
+    @SaCheckPermission("erp:feedback:edit")
+    @Log(title = "客户反馈记录", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody FeedbackBo bo) {
+        return toAjax(feedbackService.updateByBo(bo));
+    }
+
+    /**
+     * 删除客户反馈记录
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("erp:feedback:remove")
+    @Log(title = "客户反馈记录", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
+        return toAjax(feedbackService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 32 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/controller/OrderController.java

@@ -105,4 +105,36 @@ public class OrderController extends BaseController {
     public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
         return toAjax(orderService.deleteWithValidByIds(List.of(ids), true));
     }
+
+    @SaCheckPermission("erp:order:audit")
+    @Log(title = "订单审核管理", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping("/audit/{id}")
+    public R<Void> audit(@NotNull(message = "主键不能为空") @PathVariable Long id) {
+        return toAjax(orderService.auditOrder(id));
+    }
+
+    @SaCheckPermission("erp:order:complete")
+    @Log(title = "订单结清管理", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping("/complete/{id}")
+    public R<Void> complete(@NotNull(message = "主键不能为空") @PathVariable Long id) {
+        return toAjax(orderService.finishOrder(id));
+    }
+
+    @SaCheckPermission("erp:order:cancel")
+    @Log(title = "订单取消管理", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping("/cancel/{id}")
+    public R<Void> cancel(@NotNull(message = "主键不能为空") @PathVariable Long id) {
+        return toAjax(orderService.cancelOrder(id));
+    }
+
+    @SaCheckPermission("erp:order:auditCancel")
+    @Log(title = "订单取消审核管理", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping("/auditCancel/{id}")
+    public R<Void> auditCancel(@NotNull(message = "主键不能为空") @PathVariable Long id) {
+        return toAjax(orderService.auditCancelOrder(id));
+    }
 }

+ 7 - 5
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/controller/OrderItemController.java

@@ -36,15 +36,17 @@ public class OrderItemController extends BaseController {
 
     private final IOrderItemService orderItemService;
 
-/**
- * 查询订单明细列表
- */
-@SaCheckPermission("erp:orderItem")
-@GetMapping("/list")
+    /**
+     * 查询订单明细列表
+     */
+    @SaCheckPermission("erp:orderItem")
+    @GetMapping("/list")
     public TableDataInfo<OrderItemVo> list(OrderItemBo bo, PageQuery pageQuery) {
         return orderItemService.queryPageList(bo, pageQuery);
     }
 
+
+
     /**
      * 导出订单明细列表
      */

+ 103 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/controller/OrderSendController.java

@@ -0,0 +1,103 @@
+package cn.vber.erp.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import cn.vber.common.idempotent.annotation.RepeatSubmit;
+import cn.vber.common.log.annotation.Log;
+import cn.vber.common.web.core.BaseController;
+import cn.vber.common.mybatis.core.page.PageQuery;
+import cn.vber.common.core.domain.R;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import cn.vber.common.log.enums.BusinessType;
+import cn.vber.common.excel.utils.ExcelUtil;
+import cn.vber.erp.domain.vo.OrderSendVo;
+import cn.vber.erp.domain.bo.OrderSendBo;
+import cn.vber.erp.service.IOrderSendService;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 发货记录
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/erp/orderSend")
+public class OrderSendController extends BaseController {
+
+    private final IOrderSendService orderSendService;
+
+/**
+ * 查询发货记录列表
+ */
+@SaCheckPermission("erp:orderSend")
+@GetMapping("/list")
+    public TableDataInfo<OrderSendVo> list(OrderSendBo bo, PageQuery pageQuery) {
+        return orderSendService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出发货记录列表
+     */
+    @SaCheckPermission("erp:orderSend:export")
+    @Log(title = "发货记录", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(OrderSendBo bo, HttpServletResponse response) {
+        List<OrderSendVo> list = orderSendService.queryList(bo);
+        ExcelUtil.exportExcel(list, "发货记录", OrderSendVo.class, response);
+    }
+
+    /**
+     * 获取发货记录详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("erp:orderSend:query")
+    @GetMapping("/{id}")
+    public R<OrderSendVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
+        return R.ok(orderSendService.queryById(id));
+    }
+
+    /**
+     * 新增发货记录
+     */
+    @SaCheckPermission("erp:orderSend:add")
+    @Log(title = "发货记录", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody OrderSendBo bo) {
+        return toAjax(orderSendService.insertByBo(bo));
+    }
+
+    /**
+     * 修改发货记录
+     */
+    @SaCheckPermission("erp:orderSend:edit")
+    @Log(title = "发货记录", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody OrderSendBo bo) {
+        return toAjax(orderSendService.updateByBo(bo));
+    }
+
+    /**
+     * 删除发货记录
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("erp:orderSend:remove")
+    @Log(title = "发货记录", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
+        return toAjax(orderSendService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 103 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/controller/PayRecordController.java

@@ -0,0 +1,103 @@
+package cn.vber.erp.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import cn.vber.common.idempotent.annotation.RepeatSubmit;
+import cn.vber.common.log.annotation.Log;
+import cn.vber.common.web.core.BaseController;
+import cn.vber.common.mybatis.core.page.PageQuery;
+import cn.vber.common.core.domain.R;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import cn.vber.common.log.enums.BusinessType;
+import cn.vber.common.excel.utils.ExcelUtil;
+import cn.vber.erp.domain.vo.PayRecordVo;
+import cn.vber.erp.domain.bo.PayRecordBo;
+import cn.vber.erp.service.IPayRecordService;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 订单付款记录
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/erp/payRecord")
+public class PayRecordController extends BaseController {
+
+    private final IPayRecordService payRecordService;
+
+/**
+ * 查询订单付款记录列表
+ */
+@SaCheckPermission("erp:payRecord")
+@GetMapping("/list")
+    public TableDataInfo<PayRecordVo> list(PayRecordBo bo, PageQuery pageQuery) {
+        return payRecordService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出订单付款记录列表
+     */
+    @SaCheckPermission("erp:payRecord:export")
+    @Log(title = "订单付款记录", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(PayRecordBo bo, HttpServletResponse response) {
+        List<PayRecordVo> list = payRecordService.queryList(bo);
+        ExcelUtil.exportExcel(list, "订单付款记录", PayRecordVo.class, response);
+    }
+
+    /**
+     * 获取订单付款记录详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("erp:payRecord:query")
+    @GetMapping("/{id}")
+    public R<PayRecordVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
+        return R.ok(payRecordService.queryById(id));
+    }
+
+    /**
+     * 新增订单付款记录
+     */
+    @SaCheckPermission("erp:payRecord:add")
+    @Log(title = "订单付款记录", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody PayRecordBo bo) {
+        return toAjax(payRecordService.insertByBo(bo));
+    }
+
+    /**
+     * 修改订单付款记录
+     */
+    @SaCheckPermission("erp:payRecord:edit")
+    @Log(title = "订单付款记录", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody PayRecordBo bo) {
+        return toAjax(payRecordService.updateByBo(bo));
+    }
+
+    /**
+     * 删除订单付款记录
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("erp:payRecord:remove")
+    @Log(title = "订单付款记录", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
+        return toAjax(payRecordService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 103 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/controller/StatementBillController.java

@@ -0,0 +1,103 @@
+package cn.vber.erp.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import cn.vber.common.idempotent.annotation.RepeatSubmit;
+import cn.vber.common.log.annotation.Log;
+import cn.vber.common.web.core.BaseController;
+import cn.vber.common.mybatis.core.page.PageQuery;
+import cn.vber.common.core.domain.R;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import cn.vber.common.log.enums.BusinessType;
+import cn.vber.common.excel.utils.ExcelUtil;
+import cn.vber.erp.domain.vo.StatementBillVo;
+import cn.vber.erp.domain.bo.StatementBillBo;
+import cn.vber.erp.service.IStatementBillService;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 对账单信息
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/erp/statementBill")
+public class StatementBillController extends BaseController {
+
+    private final IStatementBillService statementBillService;
+
+/**
+ * 查询对账单信息列表
+ */
+@SaCheckPermission("erp:statementBill")
+@GetMapping("/list")
+    public TableDataInfo<StatementBillVo> list(StatementBillBo bo, PageQuery pageQuery) {
+        return statementBillService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出对账单信息列表
+     */
+    @SaCheckPermission("erp:statementBill:export")
+    @Log(title = "对账单信息", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(StatementBillBo bo, HttpServletResponse response) {
+        List<StatementBillVo> list = statementBillService.queryList(bo);
+        ExcelUtil.exportExcel(list, "对账单信息", StatementBillVo.class, response);
+    }
+
+    /**
+     * 获取对账单信息详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("erp:statementBill:query")
+    @GetMapping("/{id}")
+    public R<StatementBillVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
+        return R.ok(statementBillService.queryById(id));
+    }
+
+    /**
+     * 新增对账单信息
+     */
+    @SaCheckPermission("erp:statementBill:add")
+    @Log(title = "对账单信息", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody StatementBillBo bo) {
+        return toAjax(statementBillService.insertByBo(bo));
+    }
+
+    /**
+     * 修改对账单信息
+     */
+    @SaCheckPermission("erp:statementBill:edit")
+    @Log(title = "对账单信息", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody StatementBillBo bo) {
+        return toAjax(statementBillService.updateByBo(bo));
+    }
+
+    /**
+     * 删除对账单信息
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("erp:statementBill:remove")
+    @Log(title = "对账单信息", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
+        return toAjax(statementBillService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 59 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/Feedback.java

@@ -0,0 +1,59 @@
+package cn.vber.erp.domain;
+
+    import cn.vber.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+    import java.util.Date;
+    import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 客户反馈记录对象 erp_feedback
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+        @Data
+        @EqualsAndHashCode(callSuper = true)
+        @TableName("erp_feedback")
+        public class Feedback extends BaseEntity {
+
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+                /**
+                 * 
+                 */
+            @TableId(value = "id")
+        private Long id;
+
+                /**
+                 * 
+                 */
+        private Long orderId;
+
+                /**
+                 * 回访内容
+                 */
+        private String feedback;
+
+                /**
+                 * 回访时间
+                 */
+        private Date recordDate;
+
+                /**
+                 * 备注
+                 */
+        private String remark;
+
+                /**
+                 * 删除标志(0:未删除, 1:已删除)
+                 */
+            @TableLogic
+        private String delFlag;
+
+
+        }

+ 34 - 30
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/Order.java

@@ -15,50 +15,54 @@ import java.io.Serial;
  * @author IwbY
  * @date 2025-10-29
  */
-        @Data
-        @EqualsAndHashCode(callSuper = true)
-        @TableName("erp_order")
-        public class Order extends BaseEntity {
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("erp_order")
+public class Order extends BaseEntity {
 
         @Serial
         private static final long serialVersionUID = 1L;
 
-                /**
-                 * 
-                 */
-            @TableId(value = "id")
+        /**
+         *
+         */
+        @TableId(value = "id")
         private Long id;
 
-                /**
-                 * 订单编号
-                 */
+        /**
+         * 订单编号
+         */
         private String orderNum;
 
-                /**
-                 * 客户
-                 */
+        /**
+         * 客户
+         */
         private Long customerId;
 
-                /**
-                 * 交付日期
-                 */
+        /**
+         * 交付日期
+         */
         private Date deliveryDate;
+        private Double price;
+        /**
+         * 状态
+         */
+        private Integer status;
 
-                /**
-                 * 状态
-                 */
-        private Long status;
-
-                /**
-                 * 备注
-                 */
+        /**
+         * 备注
+         */
         private String remark;
 
-                /**
-                 * 删除标志(0:未删除, 1:已删除)
-                 */
-            @TableLogic
+        /**
+         * 删除标志(0:未删除, 1:已删除)
+         */
+        @TableLogic
         private String delFlag;
 
+        private Date auditDate;
+
+        private Date cancelDate;
 
-        }
+        private Date cancelAuditDate;
+}

+ 74 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/OrderSend.java

@@ -0,0 +1,74 @@
+package cn.vber.erp.domain;
+
+    import cn.vber.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+    import java.util.Date;
+    import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 发货记录对象 erp_order_send
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+        @Data
+        @EqualsAndHashCode(callSuper = true)
+        @TableName("erp_order_send")
+        public class OrderSend extends BaseEntity {
+
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+                /**
+                 * 
+                 */
+            @TableId(value = "id")
+        private Long id;
+
+                /**
+                 * 订单明细
+                 */
+        private Long orderItemId;
+
+                /**
+                 * 发货数量
+                 */
+        private Double sendQuantity;
+
+                /**
+                 * 发货时间
+                 */
+        private Date sendDate;
+
+                /**
+                 * 车牌号
+                 */
+        private String carNum;
+
+                /**
+                 * 实际交付日期
+                 */
+        private Date deliveryDate;
+
+                /**
+                 * 签收照片
+                 */
+        private String signedPhoto;
+
+                /**
+                 * 备注
+                 */
+        private String remark;
+
+                /**
+                 * 删除标志(0:未删除, 1:已删除)
+                 */
+            @TableLogic
+        private String delFlag;
+
+
+        }

+ 60 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/PayRecord.java

@@ -0,0 +1,60 @@
+package cn.vber.erp.domain;
+
+    import cn.vber.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+    import java.math.BigDecimal;
+    import java.util.Date;
+    import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 订单付款记录对象 erp_pay_record
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+        @Data
+        @EqualsAndHashCode(callSuper = true)
+        @TableName("erp_pay_record")
+        public class PayRecord extends BaseEntity {
+
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+                /**
+                 * 
+                 */
+            @TableId(value = "id")
+        private Long id;
+
+                /**
+                 * 
+                 */
+        private Long orderId;
+
+                /**
+                 * 
+                 */
+        private BigDecimal price;
+
+                /**
+                 * 
+                 */
+        private Date payDate;
+
+                /**
+                 * 备注
+                 */
+        private String remark;
+
+                /**
+                 * 删除标志(0:未删除, 1:已删除)
+                 */
+            @TableLogic
+        private String delFlag;
+
+
+        }

+ 80 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/StatementBill.java

@@ -0,0 +1,80 @@
+package cn.vber.erp.domain;
+
+    import cn.vber.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+    import java.math.BigDecimal;
+    import java.util.Date;
+    import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 对账单信息对象 erp_statement_bill
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+        @Data
+        @EqualsAndHashCode(callSuper = true)
+        @TableName("erp_statement_bill")
+        public class StatementBill extends BaseEntity {
+
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+                /**
+                 * 
+                 */
+            @TableId(value = "id")
+        private Long id;
+
+                /**
+                 * 
+                 */
+        private Long orderId;
+
+                /**
+                 * 应收
+                 */
+        private BigDecimal price;
+
+                /**
+                 * 实收
+                 */
+        private BigDecimal actualPrice;
+
+                /**
+                 * 是否开票
+                 */
+        private Integer billStatus;
+
+                /**
+                 * 开票日期
+                 */
+        private Date billDate;
+
+                /**
+                 * 发票金额
+                 */
+        private BigDecimal billPrice;
+
+                /**
+                 * 发票pdf文件
+                 */
+        private String billFile;
+
+                /**
+                 * 备注
+                 */
+        private String remark;
+
+                /**
+                 * 删除标志(0:未删除, 1:已删除)
+                 */
+            @TableLogic
+        private String delFlag;
+
+
+        }

+ 57 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/bo/FeedbackBo.java

@@ -0,0 +1,57 @@
+package cn.vber.erp.domain.bo;
+
+import cn.vber.erp.domain.Feedback;
+import cn.vber.common.mybatis.core.domain.BaseEntity;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 客户反馈记录业务对象 erp_feedback
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = Feedback.class,reverseConvertGenerate =false)
+
+public class FeedbackBo extends BaseEntity {
+
+            /**
+             * 
+             */
+                @NotNull(message = "不能为空", groups = { EditGroup.class })
+        private Long id;
+
+            /**
+             * 
+             */
+                @NotNull(message = "不能为空", groups = { AddGroup.class, EditGroup.class })
+        private Long orderId;
+
+            /**
+             * 回访内容
+             */
+                @NotBlank(message = "回访内容不能为空", groups = { AddGroup.class, EditGroup.class })
+        private String feedback;
+
+            /**
+             * 回访时间
+             */
+                @NotNull(message = "回访时间不能为空", groups = { AddGroup.class, EditGroup.class })
+            @JsonFormat(pattern = "yyyy-MM-dd")
+        private Date recordDate;
+
+            /**
+             * 备注
+             */
+        private String remark;
+
+
+}

+ 33 - 31
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/bo/OrderBo.java

@@ -25,44 +25,46 @@ import com.fasterxml.jackson.annotation.JsonFormat;
 
 public class OrderBo extends BaseEntity {
 
-            /**
-             * 
-             */
-                @NotNull(message = "不能为空", groups = { EditGroup.class })
-        private Long id;
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = {EditGroup.class})
+    private Long id;
 
-            /**
-             * 订单编号
-             */
-                @NotBlank(message = "订单编号不能为空", groups = { AddGroup.class, EditGroup.class })
-        private String orderNum;
+    /**
+     * 订单编号
+     */
+    @NotBlank(message = "订单编号不能为空", groups = {AddGroup.class, EditGroup.class})
+    private String orderNum;
 
-            /**
-             * 客户
-             */
-                @NotNull(message = "客户不能为空", groups = { AddGroup.class, EditGroup.class })
-        private Long customerId;
+    /**
+     * 客户
+     */
+    @NotNull(message = "客户不能为空", groups = {AddGroup.class, EditGroup.class})
+    private Long customerId;
 
-            /**
-             * 交付日期
-             */
-                @NotNull(message = "交付日期不能为空", groups = { AddGroup.class, EditGroup.class })
-            @JsonFormat(pattern = "yyyy-MM-dd")
-        private Date deliveryDate;
+    /**
+     * 交付日期
+     */
+    @NotNull(message = "交付日期不能为空", groups = {AddGroup.class, EditGroup.class})
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date deliveryDate;
 
-            /**
-             * 状态
-             */
-                @NotNull(message = "状态不能为空", groups = { AddGroup.class, EditGroup.class })
-        private Long status;
+    private Double price;
 
-            /**
-             * 备注
-             */
-        private String remark;
+    /**
+     * 状态
+     */
+    @NotNull(message = "状态不能为空", groups = {AddGroup.class, EditGroup.class})
+    private Integer status;
 
+    /**
+     * 备注
+     */
+    private String remark;
 
-        private List<OrderItemBo> orderItemList;
+
+    private List<OrderItemBo> orderItemList;
 
 
 }

+ 74 - 67
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/bo/OrderItemBo.java

@@ -23,73 +23,80 @@ import com.fasterxml.jackson.annotation.JsonFormat;
 
 public class OrderItemBo extends BaseEntity {
 
-            /**
-             * 
-             */
-                @NotNull(message = "不能为空", groups = { EditGroup.class })
-        private Long id;
-
-            /**
-             * 
-             */
-                @NotNull(message = "不能为空", groups = { AddGroup.class, EditGroup.class })
-        private Long orderId;
-
-            /**
-             * 预期产能
-             */
-                @NotNull(message = "预期产能不能为空", groups = { AddGroup.class, EditGroup.class })
-        private Long expectedProductionId;
-
-            /**
-             * 冗余字段
-             */
-        private String variety;
-
-            /**
-             * 订单数量
-             */
-                @NotNull(message = "订单数量不能为空", groups = { AddGroup.class, EditGroup.class })
-        private Long quantity;
-
-            /**
-             * 发货日期
-             */
-            @JsonFormat(pattern = "yyyy-MM-dd")
-        private Date sendDate;
-
-            /**
-             * 实际发货量
-             */
-                @NotNull(message = "实际发货量不能为空", groups = { AddGroup.class, EditGroup.class })
-        private Long sendQuantity;
-
-            /**
-             * 实际交付日期
-             */
-            @JsonFormat(pattern = "yyyy-MM-dd")
-        private Date deliveryDate;
-
-            /**
-             * 车牌号
-             */
-        private String carNum;
-
-            /**
-             * 签收照片
-             */
-        private String signedPhoto;
-
-            /**
-             * 状态
-             */
-                @NotNull(message = "状态不能为空", groups = { AddGroup.class, EditGroup.class })
-        private Integer status;
-
-            /**
-             * 备注
-             */
-        private String remark;
+    public OrderItemBo(){
+
+    }
+    public OrderItemBo(Long orderId){
+        this.orderId = orderId;
+    }
+
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = {EditGroup.class})
+    private Long id;
+
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = {AddGroup.class, EditGroup.class})
+    private Long orderId;
+
+    /**
+     * 预期产能
+     */
+    @NotNull(message = "预期产能不能为空", groups = {AddGroup.class, EditGroup.class})
+    private Long expectedProductionId;
+
+    /**
+     * 冗余字段
+     */
+    private String variety;
+
+    /**
+     * 订单数量
+     */
+    @NotNull(message = "订单数量不能为空", groups = {AddGroup.class, EditGroup.class})
+    private Long quantity;
+
+    /**
+     * 发货日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date sendDate;
+
+    /**
+     * 实际发货量
+     */
+    @NotNull(message = "实际发货量不能为空", groups = {AddGroup.class, EditGroup.class})
+    private Long sendQuantity;
+
+    /**
+     * 实际交付日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date deliveryDate;
+
+    /**
+     * 车牌号
+     */
+    private String carNum;
+
+    /**
+     * 签收照片
+     */
+    private String signedPhoto;
+
+    /**
+     * 状态
+     */
+    @NotNull(message = "状态不能为空", groups = {AddGroup.class, EditGroup.class})
+    private Integer status;
+
+    /**
+     * 备注
+     */
+    private String remark;
 
 
 }

+ 75 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/bo/OrderSendBo.java

@@ -0,0 +1,75 @@
+package cn.vber.erp.domain.bo;
+
+import cn.vber.erp.domain.OrderSend;
+import cn.vber.common.mybatis.core.domain.BaseEntity;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 发货记录业务对象 erp_order_send
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = OrderSend.class,reverseConvertGenerate =false)
+
+public class OrderSendBo extends BaseEntity {
+
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = {EditGroup.class})
+    private Long id;
+
+    private String orderNum;
+
+    /**
+     * 订单明细
+     */
+    @NotNull(message = "订单明细不能为空", groups = {AddGroup.class, EditGroup.class})
+    private Long orderItemId;
+
+    /**
+     * 发货数量
+     */
+    @NotNull(message = "发货数量不能为空", groups = {AddGroup.class, EditGroup.class})
+    private Double sendQuantity;
+
+    /**
+     * 发货时间
+     */
+    @NotNull(message = "发货时间不能为空", groups = {AddGroup.class, EditGroup.class})
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date sendDate;
+
+    /**
+     * 车牌号
+     */
+    private String carNum;
+
+    /**
+     * 实际交付日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date deliveryDate;
+
+    /**
+     * 签收照片
+     */
+    private String signedPhoto;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 58 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/bo/PayRecordBo.java

@@ -0,0 +1,58 @@
+package cn.vber.erp.domain.bo;
+
+import cn.vber.erp.domain.PayRecord;
+import cn.vber.common.mybatis.core.domain.BaseEntity;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 订单付款记录业务对象 erp_pay_record
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = PayRecord.class,reverseConvertGenerate =false)
+
+public class PayRecordBo extends BaseEntity {
+
+            /**
+             * 
+             */
+                @NotNull(message = "不能为空", groups = { EditGroup.class })
+        private Long id;
+
+            /**
+             * 
+             */
+                @NotNull(message = "不能为空", groups = { AddGroup.class, EditGroup.class })
+        private Long orderId;
+
+            /**
+             * 
+             */
+                @NotNull(message = "不能为空", groups = { AddGroup.class, EditGroup.class })
+        private BigDecimal price;
+
+            /**
+             * 
+             */
+                @NotNull(message = "不能为空", groups = { AddGroup.class, EditGroup.class })
+            @JsonFormat(pattern = "yyyy-MM-dd")
+        private Date payDate;
+
+            /**
+             * 备注
+             */
+        private String remark;
+
+
+}

+ 80 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/bo/StatementBillBo.java

@@ -0,0 +1,80 @@
+package cn.vber.erp.domain.bo;
+
+import cn.vber.erp.domain.StatementBill;
+import cn.vber.common.mybatis.core.domain.BaseEntity;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 对账单信息业务对象 erp_statement_bill
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = StatementBill.class,reverseConvertGenerate =false)
+
+public class StatementBillBo extends BaseEntity {
+
+            /**
+             * 
+             */
+                @NotNull(message = "不能为空", groups = { EditGroup.class })
+        private Long id;
+
+            /**
+             * 
+             */
+                @NotNull(message = "不能为空", groups = { AddGroup.class, EditGroup.class })
+        private Long orderId;
+
+            /**
+             * 应收
+             */
+                @NotNull(message = "应收不能为空", groups = { AddGroup.class, EditGroup.class })
+        private BigDecimal price;
+
+            /**
+             * 实收
+             */
+                @NotNull(message = "实收不能为空", groups = { AddGroup.class, EditGroup.class })
+        private BigDecimal actualPrice;
+
+            /**
+             * 是否开票
+             */
+                @NotNull(message = "是否开票不能为空", groups = { AddGroup.class, EditGroup.class })
+        private Integer billStatus;
+
+            /**
+             * 开票日期
+             */
+            @JsonFormat(pattern = "yyyy-MM-dd")
+        private Date billDate;
+
+            /**
+             * 发票金额
+             */
+                @NotNull(message = "发票金额不能为空", groups = { AddGroup.class, EditGroup.class })
+        private BigDecimal billPrice;
+
+            /**
+             * 发票pdf文件
+             */
+        private String billFile;
+
+            /**
+             * 备注
+             */
+        private String remark;
+
+
+}

+ 64 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/vo/FeedbackVo.java

@@ -0,0 +1,64 @@
+package cn.vber.erp.domain.vo;
+
+    import java.util.Date;
+    import com.fasterxml.jackson.annotation.JsonFormat;
+import cn.vber.erp.domain.Feedback;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import cn.vber.common.excel.annotation.ExcelDictFormat;
+import cn.vber.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 客户反馈记录视图对象 erp_feedback
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = Feedback.class)
+
+public class FeedbackVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+            /**
+             * 
+             */
+            @ExcelProperty(value = "")
+        private Long id;
+
+            /**
+             * 
+             */
+            @ExcelProperty(value = "")
+        private Long orderId;
+
+            /**
+             * 回访内容
+             */
+            @ExcelProperty(value = "回访内容")
+        private String feedback;
+
+            /**
+             * 回访时间
+             */
+            @ExcelProperty(value = "回访时间")
+        private Date recordDate;
+
+            /**
+             * 备注
+             */
+            @ExcelProperty(value = "备注")
+        private String remark;
+
+
+}

+ 88 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/vo/OrderSendVo.java

@@ -0,0 +1,88 @@
+package cn.vber.erp.domain.vo;
+
+    import java.util.Date;
+
+    import cn.vber.common.translation.annotation.Translation;
+    import cn.vber.common.translation.constant.TransConstant;
+    import com.fasterxml.jackson.annotation.JsonFormat;
+import cn.vber.erp.domain.OrderSend;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import cn.vber.common.excel.annotation.ExcelDictFormat;
+import cn.vber.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 发货记录视图对象 erp_order_send
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = OrderSend.class)
+
+public class OrderSendVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private Long id;
+
+    @Translation(type = TransConstant.ORDER_ITEM_ID_TO_INFO, mapper = "orderItemId", other = "orderNum")
+    private String orderNum;
+
+    /**
+     * 订单明细
+     */
+    @ExcelProperty(value = "订单明细")
+    private Long orderItemId;
+
+    /**
+     * 发货数量
+     */
+    @ExcelProperty(value = "发货数量")
+    private Double sendQuantity;
+
+    /**
+     * 发货时间
+     */
+    @ExcelProperty(value = "发货时间")
+    private Date sendDate;
+
+    /**
+     * 车牌号
+     */
+    @ExcelProperty(value = "车牌号")
+    private String carNum;
+
+    /**
+     * 实际交付日期
+     */
+    @ExcelProperty(value = "实际交付日期")
+    private Date deliveryDate;
+
+    /**
+     * 签收照片
+     */
+    @ExcelProperty(value = "签收照片")
+    private String signedPhoto;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}

+ 8 - 2
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/vo/OrderVo.java

@@ -60,13 +60,13 @@ public class OrderVo implements Serializable {
      */
     @ExcelProperty(value = "交付日期")
     private Date deliveryDate;
-
+    private Double price;
     /**
      * 状态
      */
     @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
     @ExcelDictFormat(dictType = "order_status")
-    private Long status;
+    private Integer status;
 
     /**
      * 备注
@@ -74,6 +74,12 @@ public class OrderVo implements Serializable {
     @ExcelProperty(value = "备注")
     private String remark;
 
+    private Date auditDate;
+
+    private Date cancelDate;
+
+    private Date cancelAuditDate;
+
 
     private List<OrderItemVo> orderItemList;
 

+ 65 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/vo/PayRecordVo.java

@@ -0,0 +1,65 @@
+package cn.vber.erp.domain.vo;
+
+    import java.math.BigDecimal;
+    import java.util.Date;
+    import com.fasterxml.jackson.annotation.JsonFormat;
+import cn.vber.erp.domain.PayRecord;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import cn.vber.common.excel.annotation.ExcelDictFormat;
+import cn.vber.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 订单付款记录视图对象 erp_pay_record
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = PayRecord.class)
+
+public class PayRecordVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+            /**
+             * 
+             */
+            @ExcelProperty(value = "")
+        private Long id;
+
+            /**
+             * 
+             */
+            @ExcelProperty(value = "")
+        private Long orderId;
+
+            /**
+             * 
+             */
+            @ExcelProperty(value = "")
+        private BigDecimal price;
+
+            /**
+             * 
+             */
+            @ExcelProperty(value = "")
+        private Date payDate;
+
+            /**
+             * 备注
+             */
+            @ExcelProperty(value = "备注")
+        private String remark;
+
+
+}

+ 98 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/domain/vo/StatementBillVo.java

@@ -0,0 +1,98 @@
+package cn.vber.erp.domain.vo;
+
+    import java.math.BigDecimal;
+    import java.util.Date;
+
+    import cn.vber.common.translation.annotation.Translation;
+    import cn.vber.common.translation.constant.TransConstant;
+    import com.fasterxml.jackson.annotation.JsonFormat;
+import cn.vber.erp.domain.StatementBill;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import cn.vber.common.excel.annotation.ExcelDictFormat;
+import cn.vber.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 对账单信息视图对象 erp_statement_bill
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = StatementBill.class)
+
+public class StatementBillVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+            /**
+             * 
+             */
+            @ExcelProperty(value = "")
+        private Long id;
+
+            /**
+             * 
+             */
+            @ExcelProperty(value = "")
+        private Long orderId;
+
+            /**
+             * 订单编号
+             */
+            @Translation(type = TransConstant.ORDER_ID_TO_INFO, mapper = "orderId", other = "orderNum")
+            private String orderNum;
+
+            /**
+             * 应收
+             */
+            @ExcelProperty(value = "应收")
+        private BigDecimal price;
+
+            /**
+             * 实收
+             */
+            @ExcelProperty(value = "实收")
+        private BigDecimal actualPrice;
+
+            /**
+             * 是否开票
+             */
+            @ExcelProperty(value = "是否开票")
+        private Integer billStatus;
+
+            /**
+             * 开票日期
+             */
+            @ExcelProperty(value = "开票日期")
+        private Date billDate;
+
+            /**
+             * 发票金额
+             */
+            @ExcelProperty(value = "发票金额")
+        private BigDecimal billPrice;
+
+            /**
+             * 发票pdf文件
+             */
+            @ExcelProperty(value = "发票pdf文件")
+        private String billFile;
+
+            /**
+             * 备注
+             */
+            @ExcelProperty(value = "备注")
+        private String remark;
+
+
+}

+ 17 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/mapper/FeedbackMapper.java

@@ -0,0 +1,17 @@
+package cn.vber.erp.mapper;
+
+import cn.vber.common.mybatis.core.mapper.BaseMapperPlus;
+import cn.vber.erp.domain.Feedback;
+import cn.vber.erp.domain.vo.FeedbackVo;
+import org.springframework.stereotype.Repository;
+
+/**
+ * 客户反馈记录Mapper接口
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Repository
+public interface FeedbackMapper extends BaseMapperPlus<Feedback, FeedbackVo> {
+
+}

+ 6 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/mapper/OrderItemMapper.java

@@ -3,8 +3,12 @@ package cn.vber.erp.mapper;
 import cn.vber.common.mybatis.core.mapper.BaseMapperPlus;
 import cn.vber.erp.domain.OrderItem;
 import cn.vber.erp.domain.vo.OrderItemVo;
+import org.apache.ibatis.annotations.Select;
 import org.springframework.stereotype.Repository;
 
+import java.io.Serial;
+import java.util.List;
+
 /**
  * 订单明细Mapper接口
  *
@@ -14,4 +18,6 @@ import org.springframework.stereotype.Repository;
 @Repository
 public interface OrderItemMapper extends BaseMapperPlus<OrderItem, OrderItemVo> {
 
+    @Select("select i.id from erp_order_item as i join erp_order as  h on i.order_id = h.id where h.order_num like CONCAT('%', #{orderNum}, '%')")
+    List<Long> selectOrderItemIdsByOrderNum(String orderNum);
 }

+ 17 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/mapper/OrderSendMapper.java

@@ -0,0 +1,17 @@
+package cn.vber.erp.mapper;
+
+import cn.vber.common.mybatis.core.mapper.BaseMapperPlus;
+import cn.vber.erp.domain.OrderSend;
+import cn.vber.erp.domain.vo.OrderSendVo;
+import org.springframework.stereotype.Repository;
+
+/**
+ * 发货记录Mapper接口
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Repository
+public interface OrderSendMapper extends BaseMapperPlus<OrderSend, OrderSendVo> {
+
+}

+ 17 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/mapper/PayRecordMapper.java

@@ -0,0 +1,17 @@
+package cn.vber.erp.mapper;
+
+import cn.vber.common.mybatis.core.mapper.BaseMapperPlus;
+import cn.vber.erp.domain.PayRecord;
+import cn.vber.erp.domain.vo.PayRecordVo;
+import org.springframework.stereotype.Repository;
+
+/**
+ * 订单付款记录Mapper接口
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Repository
+public interface PayRecordMapper extends BaseMapperPlus<PayRecord, PayRecordVo> {
+
+}

+ 17 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/mapper/StatementBillMapper.java

@@ -0,0 +1,17 @@
+package cn.vber.erp.mapper;
+
+import cn.vber.common.mybatis.core.mapper.BaseMapperPlus;
+import cn.vber.erp.domain.StatementBill;
+import cn.vber.erp.domain.vo.StatementBillVo;
+import org.springframework.stereotype.Repository;
+
+/**
+ * 对账单信息Mapper接口
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@Repository
+public interface StatementBillMapper extends BaseMapperPlus<StatementBill, StatementBillVo> {
+
+}

+ 49 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/IFeedbackService.java

@@ -0,0 +1,49 @@
+package cn.vber.erp.service;
+
+import cn.vber.erp.domain.Feedback;
+import cn.vber.erp.domain.vo.FeedbackVo;
+import cn.vber.erp.domain.bo.FeedbackBo;
+    import cn.vber.common.mybatis.core.page.TableDataInfo;
+    import cn.vber.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 客户反馈记录Service接口
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+public interface IFeedbackService {
+
+    /**
+     * 查询客户反馈记录
+     */
+        FeedbackVo queryById(Long id);
+
+        /**
+         * 查询客户反馈记录列表
+         */
+        TableDataInfo<FeedbackVo> queryPageList(FeedbackBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询客户反馈记录列表
+     */
+    List<FeedbackVo> queryList(FeedbackBo bo);
+
+    /**
+     * 新增客户反馈记录
+     */
+    Boolean insertByBo(FeedbackBo bo);
+
+    /**
+     * 修改客户反馈记录
+     */
+    Boolean updateByBo(FeedbackBo bo);
+
+    /**
+     * 校验并批量删除客户反馈记录信息
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 49 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/IOrderSendService.java

@@ -0,0 +1,49 @@
+package cn.vber.erp.service;
+
+import cn.vber.erp.domain.OrderSend;
+import cn.vber.erp.domain.vo.OrderSendVo;
+import cn.vber.erp.domain.bo.OrderSendBo;
+    import cn.vber.common.mybatis.core.page.TableDataInfo;
+    import cn.vber.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 发货记录Service接口
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+public interface IOrderSendService {
+
+    /**
+     * 查询发货记录
+     */
+        OrderSendVo queryById(Long id);
+
+        /**
+         * 查询发货记录列表
+         */
+        TableDataInfo<OrderSendVo> queryPageList(OrderSendBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询发货记录列表
+     */
+    List<OrderSendVo> queryList(OrderSendBo bo);
+
+    /**
+     * 新增发货记录
+     */
+    Boolean insertByBo(OrderSendBo bo);
+
+    /**
+     * 修改发货记录
+     */
+    Boolean updateByBo(OrderSendBo bo);
+
+    /**
+     * 校验并批量删除发货记录信息
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 9 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/IOrderService.java

@@ -46,4 +46,13 @@ public interface IOrderService {
      * 校验并批量删除订单管理信息
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    Boolean auditOrder(Long id);
+
+    Boolean finishOrder(Long id);
+
+    Boolean cancelOrder(Long id);
+
+    Boolean auditCancelOrder(Long id);
+
 }

+ 49 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/IPayRecordService.java

@@ -0,0 +1,49 @@
+package cn.vber.erp.service;
+
+import cn.vber.erp.domain.PayRecord;
+import cn.vber.erp.domain.vo.PayRecordVo;
+import cn.vber.erp.domain.bo.PayRecordBo;
+    import cn.vber.common.mybatis.core.page.TableDataInfo;
+    import cn.vber.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 订单付款记录Service接口
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+public interface IPayRecordService {
+
+    /**
+     * 查询订单付款记录
+     */
+        PayRecordVo queryById(Long id);
+
+        /**
+         * 查询订单付款记录列表
+         */
+        TableDataInfo<PayRecordVo> queryPageList(PayRecordBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询订单付款记录列表
+     */
+    List<PayRecordVo> queryList(PayRecordBo bo);
+
+    /**
+     * 新增订单付款记录
+     */
+    Boolean insertByBo(PayRecordBo bo);
+
+    /**
+     * 修改订单付款记录
+     */
+    Boolean updateByBo(PayRecordBo bo);
+
+    /**
+     * 校验并批量删除订单付款记录信息
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 49 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/IStatementBillService.java

@@ -0,0 +1,49 @@
+package cn.vber.erp.service;
+
+import cn.vber.erp.domain.StatementBill;
+import cn.vber.erp.domain.vo.StatementBillVo;
+import cn.vber.erp.domain.bo.StatementBillBo;
+    import cn.vber.common.mybatis.core.page.TableDataInfo;
+    import cn.vber.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 对账单信息Service接口
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+public interface IStatementBillService {
+
+    /**
+     * 查询对账单信息
+     */
+        StatementBillVo queryById(Long id);
+
+        /**
+         * 查询对账单信息列表
+         */
+        TableDataInfo<StatementBillVo> queryPageList(StatementBillBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询对账单信息列表
+     */
+    List<StatementBillVo> queryList(StatementBillBo bo);
+
+    /**
+     * 新增对账单信息
+     */
+    Boolean insertByBo(StatementBillBo bo);
+
+    /**
+     * 修改对账单信息
+     */
+    Boolean updateByBo(StatementBillBo bo);
+
+    /**
+     * 校验并批量删除对账单信息信息
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 112 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/impl/FeedbackServiceImpl.java

@@ -0,0 +1,112 @@
+package cn.vber.erp.service.impl;
+
+import cn.vber.common.core.utils.MapstructUtils;
+import cn.vber.common.core.utils.StringUtils;
+    import cn.vber.common.mybatis.core.page.TableDataInfo;
+    import cn.vber.common.mybatis.core.page.PageQuery;
+    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import cn.vber.erp.domain.bo.FeedbackBo;
+import cn.vber.erp.domain.vo.FeedbackVo;
+import cn.vber.erp.domain.Feedback;
+import cn.vber.erp.mapper.FeedbackMapper;
+import cn.vber.erp.service.IFeedbackService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 客户反馈记录Service业务层处理
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@RequiredArgsConstructor
+@Service
+public class FeedbackServiceImpl implements IFeedbackService {
+
+    private final FeedbackMapper baseMapper;
+
+    /**
+     * 查询客户反馈记录
+     */
+    @Override
+    public FeedbackVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+
+        /**
+         * 查询客户反馈记录列表
+         */
+        @Override
+        public TableDataInfo<FeedbackVo> queryPageList(FeedbackBo bo, PageQuery pageQuery) {
+            LambdaQueryWrapper<Feedback> lqw = buildQueryWrapper(bo);
+            Page<FeedbackVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+            return TableDataInfo.build(result);
+        }
+
+    /**
+     * 查询客户反馈记录列表
+     */
+    @Override
+    public List<FeedbackVo> queryList(FeedbackBo bo) {
+        LambdaQueryWrapper<Feedback> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<Feedback> buildQueryWrapper(FeedbackBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<Feedback> lqw = Wrappers.lambdaQuery();
+                    lqw.eq(bo.getOrderId() != null, Feedback::getOrderId, bo.getOrderId());
+                    lqw.eq(StringUtils.isNotBlank(bo.getFeedback()), Feedback::getFeedback, bo.getFeedback());
+                    lqw.between(StringUtils.isNotEmpty(params.get("beginRecordDate")) && StringUtils.isNotEmpty(params.get("endRecordDate")),
+                        Feedback::getRecordDate , params.get("beginRecordDate"), params.get("endRecordDate"));
+        return lqw;
+    }
+
+    /**
+     * 新增客户反馈记录
+     */
+    @Override
+    public Boolean insertByBo(FeedbackBo bo) {
+        Feedback add = MapstructUtils.convert(bo, Feedback. class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改客户反馈记录
+     */
+    @Override
+    public Boolean updateByBo(FeedbackBo bo) {
+        Feedback update = MapstructUtils.convert(bo, Feedback. class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(Feedback entity) {
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 批量删除客户反馈记录
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 81 - 14
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/impl/OrderItemServiceImpl.java

@@ -1,23 +1,37 @@
 package cn.vber.erp.service.impl;
 
+import cn.vber.base.enums.OrderStatusEnum;
+import cn.vber.common.core.constant.CacheNames;
+import cn.vber.common.core.exception.ServiceException;
+import cn.vber.common.core.service.OrderItemService;
 import cn.vber.common.core.utils.MapstructUtils;
 import cn.vber.common.core.utils.StringUtils;
     import cn.vber.common.mybatis.core.page.TableDataInfo;
     import cn.vber.common.mybatis.core.page.PageQuery;
-    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import cn.vber.erp.domain.ExpectedProduction;
+import cn.vber.erp.domain.Order;
+import cn.vber.erp.domain.vo.ExpectedProductionVo;
+import cn.vber.erp.mapper.ExpectedProductionMapper;
+import cn.vber.erp.mapper.OrderMapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 import cn.vber.erp.domain.bo.OrderItemBo;
 import cn.vber.erp.domain.vo.OrderItemVo;
 import cn.vber.erp.domain.OrderItem;
 import cn.vber.erp.mapper.OrderItemMapper;
 import cn.vber.erp.service.IOrderItemService;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Collection;
+import java.util.Objects;
 
 /**
  * 订单明细Service业务层处理
@@ -27,9 +41,11 @@ import java.util.Collection;
  */
 @RequiredArgsConstructor
 @Service
-public class OrderItemServiceImpl implements IOrderItemService {
+public class OrderItemServiceImpl implements IOrderItemService, OrderItemService {
 
     private final OrderItemMapper baseMapper;
+    private final OrderMapper orderMapper;
+    private final ExpectedProductionMapper expectedProductionMapper;
 
     /**
      * 查询订单明细
@@ -61,17 +77,17 @@ public class OrderItemServiceImpl implements IOrderItemService {
     private LambdaQueryWrapper<OrderItem> buildQueryWrapper(OrderItemBo bo) {
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<OrderItem> lqw = Wrappers.lambdaQuery();
-                    lqw.eq(bo.getOrderId() != null, OrderItem::getOrderId, bo.getOrderId());
-                    lqw.eq(bo.getExpectedProductionId() != null, OrderItem::getExpectedProductionId, bo.getExpectedProductionId());
-                    lqw.eq(StringUtils.isNotBlank(bo.getVariety()), OrderItem::getVariety, bo.getVariety());
-                    lqw.eq(bo.getQuantity() != null, OrderItem::getQuantity, bo.getQuantity());
-                    lqw.between(StringUtils.isNotEmpty(params.get("beginSendDate")) && StringUtils.isNotEmpty(params.get("endSendDate")),
-                        OrderItem::getSendDate , params.get("beginSendDate"), params.get("endSendDate"));
-                    lqw.eq(bo.getSendQuantity() != null, OrderItem::getSendQuantity, bo.getSendQuantity());
-                    lqw.between(StringUtils.isNotEmpty(params.get("beginDeliveryDate")) && StringUtils.isNotEmpty(params.get("endDeliveryDate")),
-                        OrderItem::getDeliveryDate , params.get("beginDeliveryDate"), params.get("endDeliveryDate"));
-                    lqw.eq(StringUtils.isNotBlank(bo.getCarNum()), OrderItem::getCarNum, bo.getCarNum());
-                    lqw.eq(StringUtils.isNotBlank(bo.getSignedPhoto()), OrderItem::getSignedPhoto, bo.getSignedPhoto());
+        lqw.eq(bo.getOrderId() != null, OrderItem::getOrderId, bo.getOrderId());
+        lqw.eq(bo.getExpectedProductionId() != null, OrderItem::getExpectedProductionId, bo.getExpectedProductionId());
+        lqw.eq(StringUtils.isNotBlank(bo.getVariety()), OrderItem::getVariety, bo.getVariety());
+        lqw.eq(bo.getQuantity() != null, OrderItem::getQuantity, bo.getQuantity());
+        lqw.between(StringUtils.isNotEmpty(params.get("beginSendDate")) && StringUtils.isNotEmpty(params.get("endSendDate")),
+                OrderItem::getSendDate, params.get("beginSendDate"), params.get("endSendDate"));
+        lqw.eq(bo.getSendQuantity() != null, OrderItem::getSendQuantity, bo.getSendQuantity());
+        lqw.between(StringUtils.isNotEmpty(params.get("beginDeliveryDate")) && StringUtils.isNotEmpty(params.get("endDeliveryDate")),
+                OrderItem::getDeliveryDate, params.get("beginDeliveryDate"), params.get("endDeliveryDate"));
+        lqw.eq(StringUtils.isNotBlank(bo.getCarNum()), OrderItem::getCarNum, bo.getCarNum());
+        lqw.eq(StringUtils.isNotBlank(bo.getSignedPhoto()), OrderItem::getSignedPhoto, bo.getSignedPhoto());
         return lqw;
     }
 
@@ -79,6 +95,7 @@ public class OrderItemServiceImpl implements IOrderItemService {
      * 新增订单明细
      */
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public Boolean insertByBo(OrderItemBo bo) {
         OrderItem add = MapstructUtils.convert(bo, OrderItem. class);
         validEntityBeforeSave(add);
@@ -86,6 +103,8 @@ public class OrderItemServiceImpl implements IOrderItemService {
         if (flag) {
             bo.setId(add.getId());
         }
+        // 更新预期产能占用数量
+        expectedProductionMapper.update(new LambdaUpdateWrapper<>(ExpectedProduction.class).eq(ExpectedProduction::getId, add.getExpectedProductionId()).set(ExpectedProduction::getOccupiedQuantity,   add.getQuantity()));
         return flag;
     }
 
@@ -93,9 +112,13 @@ public class OrderItemServiceImpl implements IOrderItemService {
      * 修改订单明细
      */
     @Override
+    @Transactional(rollbackFor = Exception.class)
+    @CacheEvict(cacheNames = CacheNames.ORDER_ITEM_ID_TO_ORDER_NUM, key = "#bo.id")
     public Boolean updateByBo(OrderItemBo bo) {
         OrderItem update = MapstructUtils.convert(bo, OrderItem. class);
         validEntityBeforeSave(update);
+        // 变更预期产能占用数量
+        expectedProductionMapper.update(new LambdaUpdateWrapper<>(ExpectedProduction.class).eq(ExpectedProduction::getId, update.getExpectedProductionId()).set(ExpectedProduction::getOccupiedQuantity,  update.getQuantity()));
         return baseMapper.updateById(update) > 0;
     }
 
@@ -103,7 +126,32 @@ public class OrderItemServiceImpl implements IOrderItemService {
      * 保存前的数据校验
      */
     private void validEntityBeforeSave(OrderItem entity) {
-        //TODO 做一些数据校验,如唯一约束
+        //todo 检查订单状态 只能新增 和 修改待审核的订单
+        Long id = entity.getId();
+        Long orderId = entity.getOrderId();
+        Order order = orderMapper.selectById(orderId);
+        if (!Objects.equals(order.getStatus(), OrderStatusEnum.WAIT_AUDIT.getCode())) {
+            throw new ServiceException("已经审核的订单不能再次新增或编辑明细!");
+        }
+        //todo 检查选中的预期产能占用数量是否大于0 如果大于0 不能被使用 ,如果是修改的情况下,是被自己占用的可以使用
+        Long expectedProductionId = entity.getExpectedProductionId();
+        if (expectedProductionId != null) {
+            ExpectedProductionVo expectedProductionVo = expectedProductionMapper.selectVoById(expectedProductionId);
+            if (expectedProductionVo.getOccupiedQuantity() > 0) {
+                // 判断是否是修改的,如果之前占用的产能就是当前订单明细的,则可以 使用
+                if (id != null) {
+                    OrderItem orderItem = baseMapper.selectById(id);
+                    //如果不是当前订单明细的预期产能,则不能使用
+                    if (!Objects.equals(orderItem.getExpectedProductionId(), expectedProductionId)) {
+                        throw new ServiceException("该预期产能已被使用,不能被使用!");
+                    }
+                }else{
+                    // 添加的时候,检查预期产能是否被使用
+                    throw new ServiceException("该预期产能已被使用,不能被使用!");
+                }
+
+            }
+        }
     }
 
     /**
@@ -113,7 +161,26 @@ public class OrderItemServiceImpl implements IOrderItemService {
     public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
         if (isValid) {
             //TODO 做一些业务上的校验,判断是否需要校验
+            //todo 检查订单状态 订单状态只能是待审核
+            List<OrderItemVo> orderItemVos = baseMapper.selectVoList(new LambdaQueryWrapper<OrderItem>().in(OrderItem::getId, ids));
+            for (OrderItemVo orderItemVo : orderItemVos) {
+                Long orderId = orderItemVo.getOrderId();
+                Order order = orderMapper.selectById(orderId);
+                if (!Objects.equals(order.getStatus(), OrderStatusEnum.WAIT_AUDIT.getCode())) {
+                    throw new ServiceException("非待审核的订单不能删除!");
+                }
+            }
         }
         return baseMapper.deleteByIds(ids) > 0;
     }
+
+    @Override
+    @Cacheable(cacheNames = CacheNames.ORDER_ITEM_ID_TO_ORDER_NUM, key = "#itemId")
+    public String getOrderNum(Long itemId) {
+        OrderItem orderItem = baseMapper.selectById(itemId);
+        if (orderItem != null) {
+            return orderMapper.selectById(orderItem.getOrderId()).getOrderNum();
+        }
+        return "";
+    }
 }

+ 140 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/impl/OrderSendServiceImpl.java

@@ -0,0 +1,140 @@
+package cn.vber.erp.service.impl;
+
+import cn.vber.base.enums.OrderItemStatusEnum;
+import cn.vber.common.core.exception.ServiceException;
+import cn.vber.common.core.utils.MapstructUtils;
+import cn.vber.common.core.utils.StringUtils;
+    import cn.vber.common.mybatis.core.page.TableDataInfo;
+    import cn.vber.common.mybatis.core.page.PageQuery;
+import cn.vber.erp.domain.Order;
+import cn.vber.erp.domain.OrderItem;
+import cn.vber.erp.mapper.OrderItemMapper;
+import cn.vber.erp.mapper.OrderMapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import cn.vber.erp.domain.bo.OrderSendBo;
+import cn.vber.erp.domain.vo.OrderSendVo;
+import cn.vber.erp.domain.OrderSend;
+import cn.vber.erp.mapper.OrderSendMapper;
+import cn.vber.erp.service.IOrderSendService;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 发货记录Service业务层处理
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@RequiredArgsConstructor
+@Service
+public class OrderSendServiceImpl implements IOrderSendService {
+
+    private final OrderSendMapper baseMapper;
+    private final OrderItemMapper orderItemMapper;
+    private final OrderMapper orderMapper;
+
+    /**
+     * 查询发货记录
+     */
+    @Override
+    public OrderSendVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 查询发货记录列表
+     */
+    @Override
+    public TableDataInfo<OrderSendVo> queryPageList(OrderSendBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<OrderSend> lqw = buildQueryWrapper(bo);
+        Page<OrderSendVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询发货记录列表
+     */
+    @Override
+    public List<OrderSendVo> queryList(OrderSendBo bo) {
+        LambdaQueryWrapper<OrderSend> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<OrderSend> buildQueryWrapper(OrderSendBo bo) {
+        Map<String, Object> params = bo.getParams();
+
+        LambdaQueryWrapper<OrderSend> lqw = Wrappers.lambdaQuery();
+                    lqw.eq(bo.getOrderItemId() != null, OrderSend::getOrderItemId, bo.getOrderItemId());
+                    lqw.eq(bo.getSendQuantity() != null, OrderSend::getSendQuantity, bo.getSendQuantity());
+                    lqw.between(StringUtils.isNotEmpty(params.get("beginSendDate")) && StringUtils.isNotEmpty(params.get("endSendDate")),
+                        OrderSend::getSendDate , params.get("beginSendDate"), params.get("endSendDate"));
+                    lqw.eq(StringUtils.isNotBlank(bo.getCarNum()), OrderSend::getCarNum, bo.getCarNum());
+                    lqw.between(StringUtils.isNotEmpty(params.get("beginDeliveryDate")) && StringUtils.isNotEmpty(params.get("endDeliveryDate")),
+                        OrderSend::getDeliveryDate , params.get("beginDeliveryDate"), params.get("endDeliveryDate"));
+                    lqw.eq(StringUtils.isNotBlank(bo.getSignedPhoto()), OrderSend::getSignedPhoto, bo.getSignedPhoto());
+        if (bo.getOrderNum()!=null && !bo.getOrderNum().isEmpty()){
+            List<Long> itemIds = orderItemMapper.selectOrderItemIdsByOrderNum(bo.getOrderNum());
+            lqw.in(OrderSend::getOrderItemId, itemIds);
+        }
+        return lqw;
+    }
+
+    /**
+     * 新增发货记录
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean insertByBo(OrderSendBo bo) {
+        OrderSend add = MapstructUtils.convert(bo, OrderSend. class);
+        validEntityBeforeSave(add);
+        //修改订单明细发货数量
+        OrderItem orderItem = orderItemMapper.selectOne(new LambdaQueryWrapper<>(OrderItem.class).eq(OrderItem::getId, add.getOrderItemId()));
+        // 可发货数量
+        var canSendQuantity = orderItem.getQuantity()- orderItem.getSendQuantity();
+        if (canSendQuantity < add.getSendQuantity()) {
+            throw new ServiceException("可发货数量不足,最多可发货"+canSendQuantity);
+        }
+        orderItemMapper.update(new LambdaUpdateWrapper<>(OrderItem.class).eq(OrderItem::getId, add.getOrderItemId()).set(OrderItem::getStatus, OrderItemStatusEnum.SENDED.getCode()).set(OrderItem::getSendQuantity, orderItem.getSendQuantity() + add.getSendQuantity()));
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改发货记录
+     */
+    @Override
+    public Boolean updateByBo(OrderSendBo bo) {
+        OrderSend update = MapstructUtils.convert(bo, OrderSend. class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(OrderSend entity) {
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 批量删除发货记录
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 61 - 21
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/impl/OrderServiceImpl.java

@@ -1,5 +1,7 @@
 package cn.vber.erp.service.impl;
 
+import cn.vber.base.enums.OrderItemStatusEnum;
+import cn.vber.base.enums.OrderStatusEnum;
 import cn.vber.common.core.constant.CacheNames;
 import cn.vber.common.core.exception.ServiceException;
 import cn.vber.common.core.service.OrderService;
@@ -7,13 +9,12 @@ import cn.vber.common.core.utils.MapstructUtils;
 import cn.vber.common.core.utils.StringUtils;
     import cn.vber.common.mybatis.core.page.TableDataInfo;
     import cn.vber.common.mybatis.core.page.PageQuery;
-import cn.vber.erp.domain.ExpectedProduction;
-import cn.vber.erp.domain.ItemInfo;
-import cn.vber.erp.domain.OrderItem;
+import cn.vber.erp.domain.*;
 import cn.vber.erp.domain.bo.OrderItemBo;
 import cn.vber.erp.domain.vo.OrderItemVo;
 import cn.vber.erp.mapper.ExpectedProductionMapper;
 import cn.vber.erp.mapper.OrderItemMapper;
+import cn.vber.erp.mapper.StatementBillMapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -24,11 +25,11 @@ import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 import cn.vber.erp.domain.bo.OrderBo;
 import cn.vber.erp.domain.vo.OrderVo;
-import cn.vber.erp.domain.Order;
 import cn.vber.erp.mapper.OrderMapper;
 import cn.vber.erp.service.IOrderService;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.List;
@@ -49,7 +50,7 @@ public class OrderServiceImpl implements IOrderService, OrderService {
     private final OrderMapper baseMapper;
     private final OrderItemMapper orderItemMapper;
     private final ExpectedProductionMapper expectedProductionMapper;
-
+    private final StatementBillMapper statementBillMapper;
     /**
      * 查询订单管理
      */
@@ -103,22 +104,22 @@ public class OrderServiceImpl implements IOrderService, OrderService {
         if (flag) {
             bo.setId(add.getId());
         }
-        if (flag && bo.getOrderItemList() != null && !bo.getOrderItemList().isEmpty()) {
-            for (OrderItemBo orderItem : bo.getOrderItemList()) {
-                orderItem.setOrderId(add.getId());
-                OrderItem addItem = MapstructUtils.convert(orderItem, OrderItem. class);
-                if(addItem == null){
-                    continue;
-                }
-                //新增订单明细
-                boolean flagItem = orderItemMapper.insert(addItem) > 0;
-                if (flagItem ){
-                    //更新预计生产计划占用数量
-                    expectedProductionMapper.update(new LambdaUpdateWrapper<>(ExpectedProduction.class).eq(ExpectedProduction::getId, orderItem.getExpectedProductionId()).set(ExpectedProduction::getOccupiedQuantity, addItem.getQuantity()));
-                }
-            }
-
-        }
+//        if (flag && bo.getOrderItemList() != null && !bo.getOrderItemList().isEmpty()) {
+//            for (OrderItemBo orderItem : bo.getOrderItemList()) {
+//                orderItem.setOrderId(add.getId());
+//                OrderItem addItem = MapstructUtils.convert(orderItem, OrderItem. class);
+//                if(addItem == null){
+//                    continue;
+//                }
+//                //新增订单明细
+//                boolean flagItem = orderItemMapper.insert(addItem) > 0;
+//                if (flagItem ){
+//                    //更新预计生产计划占用数量
+//                    expectedProductionMapper.update(new LambdaUpdateWrapper<>(ExpectedProduction.class).eq(ExpectedProduction::getId, orderItem.getExpectedProductionId()).set(ExpectedProduction::getOccupiedQuantity, addItem.getQuantity()));
+//                }
+//            }
+//
+//        }
         return flag;
     }
 
@@ -163,6 +164,45 @@ public class OrderServiceImpl implements IOrderService, OrderService {
         }
     }
 
+    /**
+     *  审核订单
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean auditOrder(Long id) {
+        orderItemMapper.update(new LambdaUpdateWrapper<>(OrderItem.class).eq(OrderItem::getOrderId, id).set(OrderItem::getStatus,  OrderItemStatusEnum.PASSED.getCode()));
+        //生成结算单
+        StatementBill statementBill = new StatementBill();
+        statementBill.setOrderId(id);
+        statementBill.setPrice(BigDecimal.ZERO);
+        statementBill.setActualPrice(BigDecimal.ZERO);
+        statementBill.setBillStatus(0);
+        statementBillMapper.insert(statementBill);
+        return baseMapper.update(new LambdaUpdateWrapper<>(Order.class).eq(Order::getId, id).set(Order::getStatus,  OrderStatusEnum.PASSED.getCode())) > 0;
+    }
+
+    /**
+     * 结清订单
+     */
+    @Override
+    public Boolean finishOrder(Long id) {
+        return baseMapper.update(new LambdaUpdateWrapper<>(Order.class).eq(Order::getId, id).set(Order::getStatus,  OrderStatusEnum.COMPLETED.getCode())) > 0;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean cancelOrder(Long id) {
+        orderItemMapper.update(new LambdaUpdateWrapper<>(OrderItem.class).eq(OrderItem::getOrderId, id).set(OrderItem::getStatus,  OrderItemStatusEnum.canceling.getCode()));
+        return baseMapper.update(new LambdaUpdateWrapper<>(Order.class).eq(Order::getId, id).set(Order::getStatus,  OrderStatusEnum.canceling.getCode())) > 0;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean auditCancelOrder(Long id) {
+        orderItemMapper.update(new LambdaUpdateWrapper<>(OrderItem.class).eq(OrderItem::getOrderId, id).set(OrderItem::getStatus,  OrderItemStatusEnum.canceled.getCode()));
+        return baseMapper.update(new LambdaUpdateWrapper<>(Order.class).eq(Order::getId, id).set(Order::getStatus,  OrderStatusEnum.canceled.getCode())) > 0;
+    }
+
     /**
      * 批量删除订单管理
      */

+ 112 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/impl/PayRecordServiceImpl.java

@@ -0,0 +1,112 @@
+package cn.vber.erp.service.impl;
+
+import cn.vber.common.core.utils.MapstructUtils;
+import cn.vber.common.core.utils.StringUtils;
+    import cn.vber.common.mybatis.core.page.TableDataInfo;
+    import cn.vber.common.mybatis.core.page.PageQuery;
+    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import cn.vber.erp.domain.bo.PayRecordBo;
+import cn.vber.erp.domain.vo.PayRecordVo;
+import cn.vber.erp.domain.PayRecord;
+import cn.vber.erp.mapper.PayRecordMapper;
+import cn.vber.erp.service.IPayRecordService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 订单付款记录Service业务层处理
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@RequiredArgsConstructor
+@Service
+public class PayRecordServiceImpl implements IPayRecordService {
+
+    private final PayRecordMapper baseMapper;
+
+    /**
+     * 查询订单付款记录
+     */
+    @Override
+    public PayRecordVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+
+        /**
+         * 查询订单付款记录列表
+         */
+        @Override
+        public TableDataInfo<PayRecordVo> queryPageList(PayRecordBo bo, PageQuery pageQuery) {
+            LambdaQueryWrapper<PayRecord> lqw = buildQueryWrapper(bo);
+            Page<PayRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+            return TableDataInfo.build(result);
+        }
+
+    /**
+     * 查询订单付款记录列表
+     */
+    @Override
+    public List<PayRecordVo> queryList(PayRecordBo bo) {
+        LambdaQueryWrapper<PayRecord> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<PayRecord> buildQueryWrapper(PayRecordBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<PayRecord> lqw = Wrappers.lambdaQuery();
+                    lqw.eq(bo.getOrderId() != null, PayRecord::getOrderId, bo.getOrderId());
+                    lqw.eq(bo.getPrice() != null, PayRecord::getPrice, bo.getPrice());
+                    lqw.between(StringUtils.isNotEmpty(params.get("beginPayDate")) && StringUtils.isNotEmpty(params.get("endPayDate")),
+                        PayRecord::getPayDate , params.get("beginPayDate"), params.get("endPayDate"));
+        return lqw;
+    }
+
+    /**
+     * 新增订单付款记录
+     */
+    @Override
+    public Boolean insertByBo(PayRecordBo bo) {
+        PayRecord add = MapstructUtils.convert(bo, PayRecord. class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改订单付款记录
+     */
+    @Override
+    public Boolean updateByBo(PayRecordBo bo) {
+        PayRecord update = MapstructUtils.convert(bo, PayRecord. class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(PayRecord entity) {
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 批量删除订单付款记录
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 116 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/java/cn/vber/erp/service/impl/StatementBillServiceImpl.java

@@ -0,0 +1,116 @@
+package cn.vber.erp.service.impl;
+
+import cn.vber.common.core.utils.MapstructUtils;
+import cn.vber.common.core.utils.StringUtils;
+    import cn.vber.common.mybatis.core.page.TableDataInfo;
+    import cn.vber.common.mybatis.core.page.PageQuery;
+    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import cn.vber.erp.domain.bo.StatementBillBo;
+import cn.vber.erp.domain.vo.StatementBillVo;
+import cn.vber.erp.domain.StatementBill;
+import cn.vber.erp.mapper.StatementBillMapper;
+import cn.vber.erp.service.IStatementBillService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 对账单信息Service业务层处理
+ *
+ * @author IwbY
+ * @date 2025-10-30
+ */
+@RequiredArgsConstructor
+@Service
+public class StatementBillServiceImpl implements IStatementBillService {
+
+    private final StatementBillMapper baseMapper;
+
+    /**
+     * 查询对账单信息
+     */
+    @Override
+    public StatementBillVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+
+        /**
+         * 查询对账单信息列表
+         */
+        @Override
+        public TableDataInfo<StatementBillVo> queryPageList(StatementBillBo bo, PageQuery pageQuery) {
+            LambdaQueryWrapper<StatementBill> lqw = buildQueryWrapper(bo);
+            Page<StatementBillVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+            return TableDataInfo.build(result);
+        }
+
+    /**
+     * 查询对账单信息列表
+     */
+    @Override
+    public List<StatementBillVo> queryList(StatementBillBo bo) {
+        LambdaQueryWrapper<StatementBill> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<StatementBill> buildQueryWrapper(StatementBillBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<StatementBill> lqw = Wrappers.lambdaQuery();
+                    lqw.eq(bo.getOrderId() != null, StatementBill::getOrderId, bo.getOrderId());
+                    lqw.eq(bo.getPrice() != null, StatementBill::getPrice, bo.getPrice());
+                    lqw.eq(bo.getActualPrice() != null, StatementBill::getActualPrice, bo.getActualPrice());
+                    lqw.eq(bo.getBillStatus() != null, StatementBill::getBillStatus, bo.getBillStatus());
+                    lqw.between(StringUtils.isNotEmpty(params.get("beginBillDate")) && StringUtils.isNotEmpty(params.get("endBillDate")),
+                        StatementBill::getBillDate , params.get("beginBillDate"), params.get("endBillDate"));
+                    lqw.eq(bo.getBillPrice() != null, StatementBill::getBillPrice, bo.getBillPrice());
+                    lqw.eq(StringUtils.isNotBlank(bo.getBillFile()), StatementBill::getBillFile, bo.getBillFile());
+        return lqw;
+    }
+
+    /**
+     * 新增对账单信息
+     */
+    @Override
+    public Boolean insertByBo(StatementBillBo bo) {
+        StatementBill add = MapstructUtils.convert(bo, StatementBill. class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改对账单信息
+     */
+    @Override
+    public Boolean updateByBo(StatementBillBo bo) {
+        StatementBill update = MapstructUtils.convert(bo, StatementBill. class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(StatementBill entity) {
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 批量删除对账单信息
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 7 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/resources/mapper/erp/FeedbackMapper.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.vber.erp.mapper.FeedbackMapper">
+
+</mapper>

+ 7 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/resources/mapper/erp/OrderSendMapper.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.vber.erp.mapper.OrderSendMapper">
+
+</mapper>

+ 7 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/resources/mapper/erp/PayRecordMapper.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.vber.erp.mapper.PayRecordMapper">
+
+</mapper>

+ 7 - 0
SERVER/ChickenFarmV3/vb-modules/vb-erp/src/main/resources/mapper/erp/StatementBillMapper.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.vber.erp.mapper.StatementBillMapper">
+
+</mapper>

+ 67 - 0
UI/VB.VUE/src/api/erp/_feedback.ts

@@ -0,0 +1,67 @@
+import Rs from "@/core/services/RequestService"
+
+class feedbackApi {
+	tableUrl = "/erp/feedback/list"
+	exportUrl = "/erp/feedback/export"
+
+	// 查询客户反馈记录列表
+	list = (query: any) => {
+		return Rs.get({
+			url: "/erp/feedback/list",
+			params: query,
+			loading: false
+		})
+	}
+
+	// 查询客户反馈记录详细
+	get = (id: string) => {
+		return Rs.get({
+			url: "/erp/feedback/" + id,
+			loading: false
+		})
+	}
+
+	// 新增或修改客户反馈记录
+	addOrUpdate = (data: any) => {
+		return new Promise((resolve) => {
+			if (data.id) {
+				this.update(data).then((res: any) => {
+					message.msgSuccess("修改成功")
+					resolve(res)
+				})
+			} else {
+				this.add(data).then((res: any) => {
+					message.msgSuccess("新增成功")
+					resolve(res)
+				})
+			}
+		})
+	}
+
+	// 新增客户反馈记录
+	add = (data: any) => {
+		return Rs.post({
+			url: "/erp/feedback",
+			data: data,
+			successAlert: false
+		})
+	}
+
+	// 修改客户反馈记录
+	update = (data: any) => {
+		return Rs.put({
+			url: "/erp/feedback",
+			data: data,
+			successAlert: false
+		})
+	}
+
+	// 删除客户反馈记录
+	del = (id: string | string[]) => {
+		return Rs.del({
+			url: "/erp/feedback/" + id
+		})
+	}
+}
+
+export default feedbackApi

+ 28 - 0
UI/VB.VUE/src/api/erp/_order.ts

@@ -69,6 +69,34 @@ class orderApi {
 			url: "/erp/order/" + id
 		})
 	}
+
+	// 审核订单
+	audit = (id: number) => {
+		return Rs.put({
+			url: "/erp/order/audit/" + id
+		})
+	}
+
+	// 结清订单
+	complete = (id: number) => {
+		return Rs.put({
+			url: "/erp/order/complete/" + id
+		})
+	}
+
+	// 退订订单
+	cancel = (id: number) => {
+		return Rs.put({
+			url: "/erp/order/cancel/" + id
+		})
+	}
+
+	// 审核退订订单
+	auditCancel = (id: number) => {
+		return Rs.put({
+			url: "/erp/order/auditCancel/" + id
+		})
+	}
 }
 
 export default orderApi

+ 8 - 0
UI/VB.VUE/src/api/erp/_orderItem.ts

@@ -13,6 +13,14 @@ class orderItemApi {
 		})
 	}
 
+	// // 查询订单明细列表
+	// listByOrderId = (orderId: string) => {
+	// 	return Rs.get({
+	// 		url: "/erp/orderItem/listByOrderId/" + orderId,
+	// 		loading: false
+	// 	})
+	// }
+
 	// 查询订单明细详细
 	get = (id: string) => {
 		return Rs.get({

+ 67 - 0
UI/VB.VUE/src/api/erp/_orderSend.ts

@@ -0,0 +1,67 @@
+import Rs from "@/core/services/RequestService"
+
+class orderSendApi {
+	tableUrl = "/erp/orderSend/list"
+	exportUrl = "/erp/orderSend/export"
+
+	// 查询发货记录列表
+	list = (query: any) => {
+		return Rs.get({
+			url: "/erp/orderSend/list",
+			params: query,
+			loading: false
+		})
+	}
+
+	// 查询发货记录详细
+	get = (id: string) => {
+		return Rs.get({
+			url: "/erp/orderSend/" + id,
+			loading: false
+		})
+	}
+
+	// 新增或修改发货记录
+	addOrUpdate = (data: any) => {
+		return new Promise((resolve) => {
+			if (data.id) {
+				this.update(data).then((res: any) => {
+					message.msgSuccess("修改成功")
+					resolve(res)
+				})
+			} else {
+				this.add(data).then((res: any) => {
+					message.msgSuccess("新增成功")
+					resolve(res)
+				})
+			}
+		})
+	}
+
+	// 新增发货记录
+	add = (data: any) => {
+		return Rs.post({
+			url: "/erp/orderSend",
+			data: data,
+			successAlert: false
+		})
+	}
+
+	// 修改发货记录
+	update = (data: any) => {
+		return Rs.put({
+			url: "/erp/orderSend",
+			data: data,
+			successAlert: false
+		})
+	}
+
+	// 删除发货记录
+	del = (id: string | string[]) => {
+		return Rs.del({
+			url: "/erp/orderSend/" + id
+		})
+	}
+}
+
+export default orderSendApi

+ 67 - 0
UI/VB.VUE/src/api/erp/_payRecord.ts

@@ -0,0 +1,67 @@
+import Rs from "@/core/services/RequestService"
+
+class payRecordApi {
+	tableUrl = "/erp/payRecord/list"
+	exportUrl = "/erp/payRecord/export"
+
+	// 查询订单付款记录列表
+	list = (query: any) => {
+		return Rs.get({
+			url: "/erp/payRecord/list",
+			params: query,
+			loading: false
+		})
+	}
+
+	// 查询订单付款记录详细
+	get = (id: string) => {
+		return Rs.get({
+			url: "/erp/payRecord/" + id,
+			loading: false
+		})
+	}
+
+	// 新增或修改订单付款记录
+	addOrUpdate = (data: any) => {
+		return new Promise((resolve) => {
+			if (data.id) {
+				this.update(data).then((res: any) => {
+					message.msgSuccess("修改成功")
+					resolve(res)
+				})
+			} else {
+				this.add(data).then((res: any) => {
+					message.msgSuccess("新增成功")
+					resolve(res)
+				})
+			}
+		})
+	}
+
+	// 新增订单付款记录
+	add = (data: any) => {
+		return Rs.post({
+			url: "/erp/payRecord",
+			data: data,
+			successAlert: false
+		})
+	}
+
+	// 修改订单付款记录
+	update = (data: any) => {
+		return Rs.put({
+			url: "/erp/payRecord",
+			data: data,
+			successAlert: false
+		})
+	}
+
+	// 删除订单付款记录
+	del = (id: string | string[]) => {
+		return Rs.del({
+			url: "/erp/payRecord/" + id
+		})
+	}
+}
+
+export default payRecordApi

+ 67 - 0
UI/VB.VUE/src/api/erp/_statementBill.ts

@@ -0,0 +1,67 @@
+import Rs from "@/core/services/RequestService"
+
+class statementBillApi {
+	tableUrl = "/erp/statementBill/list"
+	exportUrl = "/erp/statementBill/export"
+
+	// 查询对账单信息列表
+	list = (query: any) => {
+		return Rs.get({
+			url: "/erp/statementBill/list",
+			params: query,
+			loading: false
+		})
+	}
+
+	// 查询对账单信息详细
+	get = (id: string) => {
+		return Rs.get({
+			url: "/erp/statementBill/" + id,
+			loading: false
+		})
+	}
+
+	// 新增或修改对账单信息
+	addOrUpdate = (data: any) => {
+		return new Promise((resolve) => {
+			if (data.id) {
+				this.update(data).then((res: any) => {
+					message.msgSuccess("修改成功")
+					resolve(res)
+				})
+			} else {
+				this.add(data).then((res: any) => {
+					message.msgSuccess("新增成功")
+					resolve(res)
+				})
+			}
+		})
+	}
+
+	// 新增对账单信息
+	add = (data: any) => {
+		return Rs.post({
+			url: "/erp/statementBill",
+			data: data,
+			successAlert: false
+		})
+	}
+
+	// 修改对账单信息
+	update = (data: any) => {
+		return Rs.put({
+			url: "/erp/statementBill",
+			data: data,
+			successAlert: false
+		})
+	}
+
+	// 删除对账单信息
+	del = (id: string | string[]) => {
+		return Rs.del({
+			url: "/erp/statementBill/" + id
+		})
+	}
+}
+
+export default statementBillApi

+ 13 - 1
UI/VB.VUE/src/api/erp/index.ts

@@ -14,6 +14,10 @@ import Product from "./_product"
 import ExpectedProduction from "./_expectedProduction"
 import Order from "./_order"
 import OrderItem from "./_orderItem"
+import Feedback from "./_feedback"
+import PayRecord from "./_payRecord"
+import StatementBill from "./_statementBill"
+import orderSend from "./_orderSend"
 
 export interface IErpApi {
 	supplierApi: Supplier
@@ -32,6 +36,10 @@ export interface IErpApi {
 	expectedProductionApi: ExpectedProduction
 	orderApi: Order
 	orderItemApi: OrderItem
+	feedbackApi: Feedback
+	payRecordApi: PayRecord
+	statementBillApi: StatementBill
+	orderSendApi: orderSend
 }
 
 export const apis: IErpApi = {
@@ -50,7 +58,11 @@ export const apis: IErpApi = {
 	productsApi: new Product(),
 	expectedProductionApi: new ExpectedProduction(),
 	orderApi: new Order(),
-	orderItemApi: new OrderItem()
+	orderItemApi: new OrderItem(),
+	feedbackApi: new Feedback(),
+	payRecordApi: new PayRecord(),
+	statementBillApi: new StatementBill(),
+	orderSendApi: new orderSend()
 }
 
 export default apis

+ 8 - 8
UI/VB.VUE/src/components/modal-select/ExpectedProductionSelect.vue

@@ -56,12 +56,7 @@ const tableOpts = reactive({
 	queryParams: {
 		variety: undefined,
 		planDate: undefined,
-		dateRangePlanDate: undefined,
-		dataRange: [
-			{
-				field: "PlanDate"
-			}
-		]
+		dateRangePlanDate: undefined
 	},
 	searchFormItems:
 		props.searchFormItems ||
@@ -117,6 +112,10 @@ function open() {
 function close() {
 	selectRef.value.close()
 }
+function handleQuery(query?: any) {
+	addDateRange(query, query.dateRangePlanDate, "PlanDate")
+	return query
+}
 
 defineExpose({
 	open,
@@ -127,13 +126,14 @@ defineExpose({
 	<ModalSelect
 		ref="selectRef"
 		:table-opts="tableOpts"
-		modalTitle="选择客户"
+		modalTitle="选择预期产能"
 		v-model="selectIds"
 		:modal-config="modalConfig"
 		:multiple="multiple"
 		:show-tag="showTag"
 		:tag-id="'id'"
-		:tag-name="'customerNum'"
+		:query-custom-fun="handleQuery"
+		:tag-name="'variety'"
 		:convert-data-fun="convertRowDataFun"
 		:save-auto-close="saveAutoClose"
 		@update:modelValue="emits('update:modelValue', $event)"

+ 5 - 1
UI/VB.VUE/src/components/modal-select/ModalSelect.vue

@@ -20,6 +20,7 @@ const props = withDefaults(
 		modalConfig?: any
 		multiple?: boolean
 		saveAutoClose?: boolean
+		queryCustomFun?: (v: any) => any
 	}>(),
 	{
 		showTag: false,
@@ -56,8 +57,11 @@ const { queryParams } = toRefs(tableOpts)
 /** 搜索按钮操作 */
 function handleQuery(query?: any) {
 	query = query || tableRef.value?.getQueryParams() || queryParams.value
-	addDateRange(query, query.dateRange)
+	if (props.queryCustomFun) {
+		query = props.queryCustomFun(query)
+	}
 	tableRef.value?.query(query)
+	//addDateRange(query, query.dateRange)
 	initSelectData()
 }
 

+ 129 - 0
UI/VB.VUE/src/components/modal-select/OrderSelect.vue

@@ -0,0 +1,129 @@
+<script setup lang="ts">
+import apis from "@a"
+import dayjs from "dayjs"
+
+const props = withDefaults(
+	defineProps<{
+		modelValue?: any[] | any
+		modalConfig?: any
+		multiple?: boolean
+		showTag?: boolean
+		optionSelectFun?: (v: any) => any // 自定义选项数据转换
+		convertDataFun?: (v: any) => any
+		searchFormItems?: any[]
+		saveAutoClose?: boolean
+	}>(),
+	{
+		showTag: true,
+		multiple: false,
+		saveAutoClose: true
+	}
+)
+const emits = defineEmits<{
+	(e: "update:modelValue", v: any[]): void
+	(e: "confirm", v: any[]): void
+}>()
+const selectRef = ref()
+
+const selectIds = ref(props.modelValue)
+
+// 定义基础列
+const baseColumns = [
+	{ field: "id", name: "ID", width: 100, isSort: true, visible: false, tooltip: true },
+	{
+		field: "orderNum",
+		name: "订单编号",
+		visible: true,
+		isSort: false,
+		width: "120",
+		tooltip: true
+	},
+	{
+		field: "orderNum",
+		name: "订单编号",
+		visible: true,
+		isSort: false,
+		width: "120",
+		tooltip: true
+	},
+	{
+		field: "customerName",
+		name: "客户",
+		visible: true,
+		isSort: false,
+		width: "180",
+		tooltip: true
+	},
+	{ field: "price", name: "价格", visible: true, isSort: false, width: 145 },
+	{ field: "deliveryDate", name: "交付日期", visible: true, isSort: false, width: 145 },
+	{ field: "status", name: "状态", visible: true, isSort: false, width: 100 },
+	{ field: "remark", name: "备注", visible: false, isSort: false, tooltip: true }
+] as any[]
+
+const tableOpts = reactive({
+	columns: baseColumns,
+	queryParams: {
+		customerNum: undefined,
+		customerName: undefined
+	},
+	searchFormItems:
+		props.searchFormItems ||
+		([
+			{
+				field: "orderNum",
+				label: "订单编号",
+				class: "w-100",
+				required: false,
+				placeholder: "请输入订单编号",
+				listeners: {
+					keyup: (e: KeyboardEvent) => {
+						if (e.code == "Enter") {
+							selectRef.value.handleQuery()
+						}
+					}
+				},
+				span: 6
+			}
+		] as any),
+	customBtns: [],
+	tableListFun: apis.erp.orderApi.list
+})
+const convertRowDataFun = (row: any) => {
+	return props.convertDataFun ? props.convertDataFun(row) : row
+}
+function open() {
+	selectRef.value.open()
+}
+function close() {
+	selectRef.value.close()
+}
+
+defineExpose({
+	open,
+	close
+})
+</script>
+<template>
+	<ModalSelect
+		ref="selectRef"
+		:table-opts="tableOpts"
+		modalTitle="选择订单"
+		v-model="selectIds"
+		:modal-config="modalConfig"
+		:multiple="multiple"
+		:show-tag="showTag"
+		:tag-id="'id'"
+		:tag-name="'orderNum'"
+		:convert-data-fun="convertRowDataFun"
+		:save-auto-close="saveAutoClose"
+		@update:modelValue="emits('update:modelValue', $event)"
+		@confirm="emits('confirm', $event)">
+		<template #status="{ row }">
+			<DictTag type="order_status" :value-is-number="1" :value="row.status"></DictTag>
+		</template>
+
+		<template #deliveryDate="{ row }">
+			{{ row.deliveryDate ? dayjs(row.deliveryDate).format("YYYY-MM-DD") : "-" }}
+		</template>
+	</ModalSelect>
+</template>

+ 251 - 0
UI/VB.VUE/src/views/erp/sale/order/components/VbFeedbackModal.vue

@@ -0,0 +1,251 @@
+<template>
+	<div>
+		<VbModal
+			v-model:modal="modalRef"
+			title="客户回访记录"
+			:form-data="form"
+			:form-items="formItems"
+			:label-width="labelWidth"
+			append-to-body
+			@confirm="submitForm">
+			<template #title>
+				<div class="fs-4">客户回访记录 - {{ orderNum }} - {{ customerName }}</div>
+			</template>
+			<template #feedback_form>
+				<div style="text-align: right; margin-bottom: 15px">
+					<el-input
+						v-model="form.feedback"
+						style="width: 560px"
+						:rows="2"
+						type="textarea"
+						placeholder="请输入回访内容" />
+					<el-button type="primary" style="margin-left: 10px" @click="submitForm">添加</el-button>
+				</div>
+			</template>
+			<template #footer>
+				<div style="height: 380px" class="table-height">
+					<VbDataTable
+						ref="tableRef"
+						keyField="id"
+						:columns="columns"
+						:remote-fun="tableListFun"
+						:show-toolbar="false"
+						:get-entity-fun="getEntityFun"
+						:delete-entity-fun="deleteEntityFun"
+						:export-url="exportUrl"
+						:export-name="exportName"
+						:handle-perm="permission"
+						:handle-btns="handleBtns"
+						:handle-funs="handleFuns"
+						:custom-btns="customBtns"
+						v-model:query-params="queryParams"
+						:noPage="true"
+						:check-multiple="true">
+						<template #recordDate="{ row }">
+							<template v-if="row.recordDate">
+								{{ dayjs(row.recordDate).format("YYYY-MM-DD") }}
+							</template>
+							<template v-else>-</template>
+						</template>
+						<template #actions="{ row }">
+							<vb-tooltip content="删除" placement="top">
+								<el-button
+									link
+									type="primary"
+									@click="handleDelete([row])"
+									v-hasPermission="'erp:feedback:remove'">
+									<template #icon>
+										<VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
+									</template>
+								</el-button>
+							</vb-tooltip>
+						</template>
+					</VbDataTable>
+				</div>
+			</template>
+		</VbModal>
+	</div>
+</template>
+
+<script setup lang="ts">
+import { ref } from "vue"
+import dayjs from "dayjs"
+import apis from "@a"
+
+const modalRef = ref()
+const tableRef = ref()
+const orderNum = ref<string>("")
+const customerName = ref<string>("")
+const orderId = ref<number>(0)
+const props = defineProps({
+	orderId: {
+		type: Number,
+		default: undefined
+	}
+})
+
+const emit = defineEmits(["success"])
+
+// 表单相关
+const form = ref({
+	id: undefined,
+	orderId: undefined,
+	feedback: undefined,
+	recordDate: undefined
+})
+
+const formItems = [
+	{
+		field: "recordDate",
+		label: "回访日期",
+		class: "w-100",
+		required: true,
+		component: "D",
+		props: {
+			placeholder: "请选择回访日期",
+			type: "date",
+			valueFormat: "YYYY-MM-DD"
+		}
+	},
+	{
+		field: "feedback",
+		label: "回访内容",
+		class: "w-100",
+		required: true,
+		placeholder: "请输入回访内容",
+		component: "slot",
+		props: {
+			type: "textarea",
+			placeholder: "请输入回访内容"
+		}
+	}
+] as any
+
+const labelWidth = "80px"
+
+// 表格相关
+const columns = [
+	{ field: "id", name: "ID", width: 100, isSort: true, visible: false, tooltip: true },
+	{
+		field: "feedback",
+		name: "回访内容",
+		visible: true,
+		isSort: false,
+		width: "auto",
+		tooltip: true
+	},
+	{
+		field: "recordDate",
+		name: "回访日期",
+		visible: true,
+		isSort: false,
+		width: "auto",
+		tooltip: true
+	},
+	{ field: "actions", name: `操作`, width: 100 }
+]
+
+const queryParams = ref({
+	orderId: undefined
+})
+
+const permission = "erp:feedback"
+const handleBtns = []
+const customBtns = []
+
+const handleFuns = {
+	handleCreate: () => {
+		handleCreate()
+	},
+	handleUpdate: () => {
+		const row = tableRef.value.getSelected()
+		handleUpdate(row)
+	},
+	handleDelete: () => {
+		const rows = tableRef.value.getSelecteds()
+		handleDelete(rows)
+	}
+}
+
+const tableListFun = apis.erp.feedbackApi.list
+const getEntityFun = apis.erp.feedbackApi.get
+const deleteEntityFun = apis.erp.feedbackApi.del
+const exportUrl = apis.erp.feedbackApi.exportUrl
+const exportName = "Feedback"
+
+// 方法
+function show(row: any) {
+	orderId.value = row.id || props.orderId
+	orderNum.value = row.orderNum || ""
+	customerName.value = row.customerName || ""
+	form.value.orderId = row.id || props.orderId
+	queryParams.value.orderId = row.id || props.orderId
+	modalRef.value.show()
+	console.log("show", queryParams.value)
+	// 加载表格数据
+	nextTick(() => {
+		tableRef.value?.query(queryParams.value)
+	})
+}
+
+function handleCreate() {
+	form.value = {
+		id: undefined,
+		orderId: orderId.value || props.orderId,
+		feedback: undefined,
+		recordDate: undefined
+	}
+}
+
+function handleUpdate(row) {
+	form.value = { ...row }
+}
+
+function handleDelete(rows) {
+	if (rows.length === 0) {
+		message.msgError("请先选择要删除的记录")
+		return
+	}
+
+	message.confirm("确定要删除选中的记录吗?", "确定").then(() => {
+		const ids = rows.map((item) => item.id)
+		apis.erp.feedbackApi.del(ids).then(() => {
+			message.msgSuccess("删除成功")
+			tableRef.value?.query(queryParams.value)
+			emit("success")
+		})
+	})
+}
+
+function submitForm() {
+	if (!form.value.feedback) {
+		message.msgError("请输入回访内容")
+		return
+	}
+
+	if (!form.value.recordDate) {
+		message.msgError("请选择回访日期")
+		return
+	}
+
+	apis.erp.feedbackApi.addOrUpdate(form.value).then(() => {
+		message.msgSuccess("保存成功")
+		tableRef.value?.query(queryParams.value)
+		emit("success")
+		handleCreate() // 重置表单
+	})
+}
+
+// 暴露方法
+defineExpose({
+	show
+})
+</script>
+
+<style scoped>
+.table-height {
+	margin-top: 0;
+	height: 380px;
+	overflow-y: scroll;
+}
+</style>

+ 249 - 0
UI/VB.VUE/src/views/erp/sale/order/components/VbPayRecordModal.vue

@@ -0,0 +1,249 @@
+<template>
+	<div>
+		<VbModal
+			v-model:modal="modalRef"
+			title="付款记录"
+			:form-data="form"
+			:form-items="formItems"
+			:label-width="labelWidth"
+			append-to-body
+			@confirm="submitForm">
+			<template #title>
+				<div class="fs-4">付款记录 - {{ orderNum }} - {{ customerName }}</div>
+			</template>
+			<template #price_form>
+				<div style="text-align: right; margin-bottom: 15px">
+					<el-input
+						v-model="form.price"
+						style="width: 200px"
+						type="number"
+						placeholder="请输入付款金额" />
+					<el-date-picker
+						v-model="form.payDate"
+						style="width: 200px; margin-left: 10px"
+						type="date"
+						value-format="YYYY-MM-DD"
+						placeholder="请选择付款日期" />
+					<el-button type="primary" style="margin-left: 10px" @click="submitForm">添加</el-button>
+				</div>
+			</template>
+			<template #footer>
+				<div style="height: 380px" class="table-height">
+					<VbDataTable
+						ref="tableRef"
+						keyField="id"
+						:columns="columns"
+						:remote-fun="tableListFun"
+						:show-toolbar="false"
+						:get-entity-fun="getEntityFun"
+						:delete-entity-fun="deleteEntityFun"
+						:export-url="exportUrl"
+						:export-name="exportName"
+						:handle-perm="permission"
+						:handle-btns="handleBtns"
+						:handle-funs="handleFuns"
+						:custom-btns="customBtns"
+						v-model:query-params="queryParams"
+						:noPage="true"
+						:check-multiple="true">
+						<template #payDate="{ row }">
+							<template v-if="row.payDate">
+								{{ dayjs(row.payDate).format("YYYY-MM-DD") }}
+							</template>
+							<template v-else>-</template>
+						</template>
+						<template #actions="{ row }">
+							<vb-tooltip content="删除" placement="top">
+								<el-button
+									link
+									type="primary"
+									@click="handleDelete([row])"
+									v-hasPermission="'erp:payRecord:remove'">
+									<template #icon>
+										<VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
+									</template>
+								</el-button>
+							</vb-tooltip>
+						</template>
+					</VbDataTable>
+				</div>
+			</template>
+		</VbModal>
+	</div>
+</template>
+
+<script setup lang="ts">
+import { ref, nextTick } from "vue"
+import dayjs from "dayjs"
+import apis from "@a"
+import message from "@@/utils/message"
+
+const modalRef = ref()
+const orderNum = ref("")
+const customerName = ref("")
+const tableRef = ref()
+const orderId = ref<number>(0)
+const props = defineProps({
+	orderId: {
+		type: Number,
+		default: undefined
+	}
+})
+
+const emit = defineEmits(["success"])
+
+// 表单相关
+const form = ref({
+	id: undefined,
+	orderId: undefined,
+	price: undefined,
+	payDate: undefined
+})
+
+const formItems = [
+	// {
+	// 	field: "payDate",
+	// 	label: "付款日期",
+	// 	class: "w-100",
+	// 	required: true,
+	// 	component: "D",
+	// 	props: {
+	// 		placeholder: "请选择付款日期",
+	// 		type: "date",
+	// 		valueFormat: "YYYY-MM-DD"
+	// 	}
+	// },
+	{
+		field: "price",
+		label: "付款信息",
+		class: "w-100",
+		required: true,
+		placeholder: "请输入付款金额",
+		component: "slot",
+		props: {
+			type: "number",
+			placeholder: "请输入付款金额"
+		}
+	}
+] as any
+
+const labelWidth = "80px"
+
+// 表格相关
+const columns = [
+	{ field: "id", name: "ID", width: 100, isSort: true, visible: false, tooltip: true },
+	{
+		field: "price",
+		name: "付款金额",
+		visible: true,
+		isSort: false,
+		width: "auto",
+		tooltip: true
+	},
+	{
+		field: "payDate",
+		name: "付款日期",
+		visible: true,
+		isSort: false,
+		width: "auto",
+		tooltip: true
+	},
+	{ field: "actions", name: `操作`, width: 100 }
+]
+
+const queryParams = ref({
+	orderId: undefined
+})
+
+const permission = "erp:payRecord"
+const handleBtns = []
+const customBtns = []
+
+const handleFuns = {
+	handleCreate,
+	handleUpdate,
+	handleDelete
+}
+
+const tableListFun = apis.erp.payRecordApi.list
+const getEntityFun = apis.erp.payRecordApi.get
+const deleteEntityFun = apis.erp.payRecordApi.del
+const exportUrl = apis.erp.payRecordApi.exportUrl
+const exportName = "PayRecord"
+
+// 方法
+function show(row: any) {
+	orderId.value = row.id || props.orderId
+	orderNum.value = row.orderNum
+	customerName.value = row.customerName
+	form.value.orderId = row.id || props.orderId
+	queryParams.value.orderId = row.id || props.orderId
+	modalRef.value.show()
+	console.log("show", row)
+	// 加载表格数据
+	nextTick(() => {
+		tableRef.value?.query(queryParams.value)
+	})
+}
+
+function handleCreate() {
+	form.value = {
+		id: undefined,
+		orderId: orderId.value || props.orderId,
+		price: undefined,
+		payDate: undefined
+	}
+}
+
+function handleUpdate(row) {
+	form.value = { ...row }
+}
+
+function handleDelete(rows) {
+	if (rows.length === 0) {
+		message.msgError("请先选择要删除的记录")
+		return
+	}
+
+	message.confirm("确定要删除选中的记录吗?", "确定").then(() => {
+		const ids = rows.map((item) => item.id)
+		apis.erp.payRecordApi.del(ids).then(() => {
+			message.msgSuccess("删除成功")
+			tableRef.value?.query(queryParams.value)
+			emit("success")
+		})
+	})
+}
+
+function submitForm() {
+	if (!form.value.price) {
+		message.msgError("请输入付款金额")
+		return
+	}
+
+	if (!form.value.payDate) {
+		message.msgError("请选择付款日期")
+		return
+	}
+
+	apis.erp.payRecordApi.addOrUpdate(form.value).then(() => {
+		message.msgSuccess("保存成功")
+		tableRef.value?.query(queryParams.value)
+		emit("success")
+		handleCreate() // 重置表单
+	})
+}
+
+// 暴露方法
+defineExpose({
+	show
+})
+</script>
+
+<style scoped>
+.table-height {
+	margin-top: 0;
+	height: 380px;
+	overflow-y: scroll;
+}
+</style>

+ 676 - 71
UI/VB.VUE/src/views/erp/sale/order/index.vue

@@ -1,12 +1,20 @@
 <script setup lang="ts" name="Order">
 import apis from "@a"
 import dayjs from "dayjs"
+import message from "@@/utils/message"
 import CustomerSelect from "@/components/modal-select/CustomerSelect.vue"
 import ExpectedProductionSelect from "@/components/modal-select/ExpectedProductionSelect.vue"
+import VbFeedbackModal from "./components/VbFeedbackModal.vue"
+import VbPayRecordModal from "./components/VbPayRecordModal.vue"
 import { customerOptions } from "@/views/erp/_common"
-
+const isEdit = ref(false)
 const tableRef = ref()
+const tableItemRef = ref()
 const modalRef = ref()
+const modalItemRef = ref()
+const modalSendRef = ref()
+const modalFeedbackRef = ref()
+const modalPayRecordRef = ref()
 const customerModalRef = ref()
 const expectedProductionModalRef = ref()
 const customerOption = ref([])
@@ -23,7 +31,7 @@ const opts = reactive({
 			name: "订单编号",
 			visible: true,
 			isSort: false,
-			width: "auto",
+			width: "120",
 			tooltip: true
 		},
 		{
@@ -31,12 +39,13 @@ const opts = reactive({
 			name: "客户",
 			visible: true,
 			isSort: false,
-			width: "auto",
+			width: "180",
 			tooltip: true
 		},
+		{ field: "price", name: "价格", visible: true, isSort: false, width: 145 },
 		{ field: "deliveryDate", name: "交付日期", visible: true, isSort: false, width: 145 },
 		{ field: "status", name: "状态", visible: true, isSort: false, width: 100 },
-		{ field: "remark", name: "备注", visible: true, isSort: false, tooltip: true },
+		{ field: "remark", name: "备注", visible: false, isSort: false, tooltip: true },
 		{ field: "actions", name: `操作`, width: 150 }
 	] as any[],
 	queryParams: {
@@ -156,7 +165,8 @@ const opts = reactive({
 			component: "I",
 			disabled: true,
 			//component: "slot"
-			appendClickFunc: handleShowCustomerModal
+			appendClickFunc: handleShowCustomerModal,
+			appendDisabled: () => isEdit.value
 		},
 		{
 			field: "deliveryDate",
@@ -170,6 +180,17 @@ const opts = reactive({
 				valueFormat: "YYYY-MM-DD"
 			}
 		},
+		{
+			field: "price",
+			label: "价格",
+			class: "w-100",
+			required: true,
+			component: "I",
+			props: {
+				placeholder: "请输入价格",
+				type: "number"
+			}
+		},
 		// {
 		// 	field: "status",
 		// 	label: "状态",
@@ -183,12 +204,16 @@ const opts = reactive({
 		// 	}
 		// },
 		{
-			field: "orderItemList",
-			label: "订单明细",
+			field: "remark",
+			label: "备注",
 			class: "w-100",
 			required: false,
-			placeholder: "请输入订单商品列表",
-			component: "slot"
+			placeholder: "请输入备注",
+			component: "I",
+			props: {
+				type: "textarea",
+				placeholder: "请输入备注"
+			}
 		}
 	] as any,
 	resetForm: () => {
@@ -202,9 +227,196 @@ const opts = reactive({
 		customerNum: undefined,
 		customerName: undefined,
 		deliveryDate: undefined,
+		price: undefined,
 		status: 1,
-		remark: undefined,
-		orderItemList: []
+		remark: undefined
+	}
+})
+const orderSelectId = ref()
+const orderSelectNum = ref()
+//const orderSelectStatus = ref()
+const itemOpts = reactive({
+	columns: [
+		{ field: "id", name: "详情ID", width: 100, isSort: true, visible: false, tooltip: true },
+		{
+			field: "variety",
+			name: "品系",
+			visible: true,
+			isSort: false,
+			width: "auto",
+			tooltip: true
+		},
+		{
+			field: "quantity",
+			name: "订单数量",
+			visible: true,
+			isSort: false,
+			width: "auto",
+			tooltip: true
+		},
+		// {
+		// 	field: "sendDate",
+		// 	name: "发货日期",
+		// 	visible: true,
+		// 	isSort: false,
+		// 	width: "auto",
+		// 	tooltip: true
+		// },
+		{
+			field: "sendQuantity",
+			name: "发货数量",
+			visible: true,
+			isSort: false,
+			width: "auto",
+			tooltip: true
+		},
+		// {
+		// 	field: "deliveryDate",
+		// 	name: "交付日期",
+		// 	visible: true,
+		// 	isSort: false,
+		// 	width: "auto",
+		// 	tooltip: true
+		// },
+		// { field: "carNum", name: "车牌号", visible: true, isSort: false, tooltip: true },
+		// { field: "signedPhoto", name: "签收照片", visible: true, isSort: false, tooltip: true },
+		{ field: "status", name: "状态", visible: true, isSort: false, tooltip: true },
+		{ field: "actions", name: `操作`, width: 150 }
+	] as any[],
+	itemQueryParams: {
+		orderId: undefined
+	},
+	permission: "erp:orderItem",
+	handleBtns: [],
+	handleFuns: {
+		handleCreate: () => {
+			handleItemCreate()
+		},
+		handleUpdate: () => {
+			const row = tableItemRef.value.getSelected()
+			handleItemUpdate(row)
+		},
+		handleDelete: () => {
+			const rows = tableItemRef.value.getSelecteds()
+			handleItemDelete(rows)
+		}
+	},
+	customBtns: [],
+	tableListFun: apis.erp.orderItemApi.list,
+	getEntityFun: apis.erp.orderItemApi.get,
+	deleteEntityFun: apis.erp.orderItemApi.del,
+	exportUrl: apis.erp.orderItemApi.exportUrl,
+	exportName: "OrderItem",
+	modalTitle: "订单商品详情",
+	formItems: [
+		{
+			field: "orderNum",
+			label: "订单编号",
+			disabled: true,
+			class: "w-100",
+			required: true,
+			placeholder: "请输入订单编号",
+			component: "I"
+		},
+		{
+			field: "variety",
+			label: "品系",
+			class: "w-100",
+			required: true,
+			placeholder: "请输入品系",
+			component: "I",
+			disabled: true,
+			appendClickFunc: handleShowExpectedProductionModal
+		},
+		{
+			field: "quantity",
+			label: "订单数量",
+			class: "w-100",
+			required: true,
+			component: "I",
+			props: {
+				type: "number",
+				min: 0
+			}
+		}
+		// {
+		// 	field: "sendDate",
+		// 	label: "发货日期",
+		// 	class: "w-100",
+		// 	required: false,
+		// 	component: "D",
+		// 	props: {
+		// 		placeholder: "请选择发货日期",
+		// 		type: "date",
+		// 		valueFormat: "YYYY-MM-DD"
+		// 	}
+		// },
+		// {
+		// 	field: "sendQuantity",
+		// 	label: "发货数量",
+		// 	class: "w-100",
+		// 	required: false,
+		// 	component: "I",
+		// 	props: {
+		// 		type: "number",
+		// 		min: 0
+		// 	}
+		// },
+		// {
+		// 	field: "deliveryDate",
+		// 	label: "交付日期",
+		// 	class: "w-100",
+		// 	required: false,
+		// 	component: "D",
+		// 	props: {
+		// 		placeholder: "请选择交付日期",
+		// 		type: "date",
+		// 		valueFormat: "YYYY-MM-DD"
+		// 	}
+		// },
+		// {
+		// 	field: "carNum",
+		// 	label: "车牌号",
+		// 	class: "w-100",
+		// 	required: false,
+		// 	placeholder: "请输入车牌号",
+		// 	component: "I"
+		// },
+		// {
+		// 	field: "signedPhoto",
+		// 	label: "签收照片",
+		// 	class: "w-100",
+		// 	required: false,
+		// 	placeholder: "请上传签收照片",
+		// 	component: "VbUpload",
+		// 	props: {
+		// 		uploadUrl: "resource/oss/upload/erp"
+		// 	}
+		// }
+	] as any,
+	resetForm: () => {
+		// console.log("resetForm", orderItemSelectId.value, detailEmptyFormData.value)
+		if (orderSelectId.value || orderSelectId.value !== 0) {
+			itemEmptyFormData.value.orderId = orderSelectId.value
+		}
+		itemForm.value = itemEmptyFormData.value
+	},
+	labelWidth: "80px",
+	itemEmptyFormData: {
+		id: undefined,
+		orderId: undefined,
+		orderNum: undefined,
+		expected_production_id: undefined,
+		productionQuantity: undefined,
+		variety: undefined,
+		quantity: 0,
+		sendDate: undefined,
+		sendQuantity: 0,
+		deliveryDate: undefined,
+		carNum: undefined,
+		signedPhoto: undefined,
+		status: 1,
+		remark: undefined
 	}
 })
 const { queryParams, emptyFormData } = toRefs(opts)
@@ -232,6 +444,7 @@ function resetQuery(query?: any) {
 }
 
 function handleCreate() {
+	isEdit.value = false
 	apis.erp.orderApi.getOrderNum().then((res: any) => {
 		form.value.orderNum = res.msg
 	})
@@ -240,6 +453,7 @@ function handleCreate() {
 
 /** 修改按钮操作 */
 function handleUpdate(row: any) {
+	isEdit.value = true
 	tableRef.value.defaultHandleFuns.handleUpdate("", row)
 }
 
@@ -255,6 +469,75 @@ function submitForm() {
 	})
 }
 
+function handleAudit(rows: any[]) {
+	if (rows.length > 1) {
+		message.msgError("只能选择一条数据")
+		return
+	}
+	console.log("handleAudit", rows)
+	message.confirm("确定要审核吗?", "确定").then(() => {
+		apis.erp.orderApi.audit(rows[0].id).then(() => {
+			handleQuery()
+		})
+	})
+}
+
+/** 结清按钮操作 */
+function handleComplete(rows: any[]) {
+	if (rows.length > 1) {
+		message.msgError("只能选择一条数据")
+		return
+	}
+	message.confirm("确定要结清吗?", "确定").then(() => {
+		apis.erp.orderApi.complete(rows[0].id).then(() => {
+			handleQuery()
+		})
+	})
+}
+
+function handleCancel(rows: any[]) {
+	if (rows.length > 1) {
+		message.msgError("只能选择一条数据")
+		return
+	}
+	message.confirm("确定要退订吗?", "确定").then(() => {
+		apis.erp.orderApi.cancel(rows[0].id).then(() => {
+			handleQuery()
+		})
+	})
+}
+
+function handleAuditCancel(rows: any[]) {
+	if (rows.length > 1) {
+		message.msgError("只能选择一条数据")
+		return
+	}
+	message.confirm("确定要审核退订记录吗?", "确定").then(() => {
+		apis.erp.orderApi.auditCancel(rows[0].id).then(() => {
+			handleQuery()
+		})
+	})
+}
+
+function handlePayRecord() {
+	const rows = tableRef.value.getSelecteds()
+	if (rows.length !== 1) {
+		message.msgError("请选择一条记录")
+		return
+	}
+	// 显示付款记录模态框
+	modalPayRecordRef.value.show(rows[0])
+}
+
+function handleFeedback(rows: any[]) {
+	if (rows.length > 1) {
+		message.msgError("只能选择一条数据")
+		return
+	}
+	// 调用回访记录模态框组件的show方法
+	modalFeedbackRef.value.show(rows[0])
+}
+
 function handleShowCustomerModal() {
 	customerModalRef.value.open()
 }
@@ -267,76 +550,379 @@ function handleConfirmCustomerModal(rows: any[]) {
 	}
 }
 
+function handleCheckBoxChange(isChecked: boolean, row: any) {
+	orderSelectId.value = isChecked ? row.id : 0
+	orderSelectNum.value = isChecked ? row.orderNum : ""
+	//orderSelectStatus.value = isChecked ? row.status : undefined
+	itemQueryParams.value.orderId = isChecked ? row.id : undefined
+	itemForm.value.orderId = isChecked ? row.id : undefined
+
+	handleItemQuery(itemQueryParams.value)
+}
+function handleQuerySuccess() {
+	const data = tableRef.value.getFirstRowData()
+	tableRef.value.setSelected(data, true)
+}
+
+const { itemQueryParams, itemEmptyFormData } = toRefs(itemOpts)
+const itemForm = ref<any>(itemEmptyFormData.value)
+
+function handleItemCreate() {
+	itemForm.value = itemEmptyFormData.value
+	tableItemRef.value.defaultHandleFuns.handleCreate()
+	nextTick(() => {
+		itemForm.value.orderId = orderSelectId.value
+		itemForm.value.orderNum = orderSelectNum.value
+	})
+}
+
+function handleItemUpdate(row: any) {
+	tableItemRef.value.defaultHandleFuns.handleUpdate("", row)
+}
+
+function handleItemDelete(rows: any) {
+	tableItemRef.value.defaultHandleFuns.handleDelete("", rows)
+}
+function handleItemQuery(query?: any) {
+	query = query || tableItemRef.value?.getQueryParams() || itemQueryParams.value
+	tableItemRef.value?.query(query)
+}
+
+const sendOpts = {
+	modalTitle: "订单发货",
+	formItems: [
+		{
+			field: "sendDate",
+			label: "发货日期",
+			class: "w-100",
+			required: true,
+			component: "D",
+			props: {
+				placeholder: "请选择发货日期",
+				type: "date",
+				valueFormat: "YYYY-MM-DD"
+			}
+		},
+		{
+			field: "sendQuantity",
+			label: "发货数量",
+			class: "w-100",
+			required: true,
+			component: "I",
+			props: {
+				type: "number",
+				min: 0
+			}
+		},
+		{
+			field: "deliveryDate",
+			label: "交付日期",
+			class: "w-100",
+			required: false,
+			component: "D",
+			props: {
+				placeholder: "请选择交付日期",
+				type: "date",
+				valueFormat: "YYYY-MM-DD"
+			}
+		},
+		{
+			field: "carNum",
+			label: "车牌号",
+			class: "w-100",
+			required: false,
+			placeholder: "请输入车牌号",
+			component: "I"
+		},
+		{
+			field: "signedPhoto",
+			label: "签收照片",
+			class: "w-100",
+			required: false,
+			placeholder: "请上传签收照片",
+			component: "VbUpload",
+			props: {
+				uploadUrl: "resource/oss/upload/erp"
+			}
+		}
+	] as any,
+	resetForm: () => {
+		// console.log("resetForm", orderItemSelectId.value, detailEmptyFormData.value)
+		if (orderSelectId.value || orderSelectId.value !== 0) {
+			itemEmptyFormData.value.orderId = orderSelectId.value
+		}
+		itemForm.value = itemEmptyFormData.value
+	},
+	labelWidth: "80px",
+	sendEmptyFormData: {
+		id: undefined,
+		orderItemId: undefined,
+		orderQuantity: 0,
+		sendDate: undefined,
+		sendQuantity: 0,
+		deliveryDate: undefined,
+		carNum: undefined,
+		signedPhoto: undefined,
+		status: 0,
+		remark: undefined
+	}
+}
+
+const sendForm = ref<any>(sendOpts.sendEmptyFormData)
+
+function handleItemSend(row: any) {
+	//itemForm.value = row
+	//todo 新增发货记录 弹出一个发货编辑的模态窗
+	sendForm.value.orderItemId = row.id
+	sendForm.value.orderQuantity = row.quantity
+	modalSendRef.value.show()
+}
+
+/** 提交按钮 */
+function submitItemForm() {
+	if (!itemForm.value || !itemForm.value.orderId) {
+		message.msgError("请先选择一条订单记录创建详情")
+		return
+	}
+	if (Number(itemForm.value.sendQuantity) > Number(itemForm.value.quantity)) {
+		message.msgError("发货数量不能大于订单数量")
+		return
+	}
+	apis.erp.orderItemApi.addOrUpdate(itemForm.value).then(() => {
+		handleItemQuery()
+	})
+}
 function handleShowExpectedProductionModal() {
 	expectedProductionModalRef.value.open()
 }
 
 function handleConfirmExpectedProductionModal(rows: any[]) {
-	// if (rows.length > 0) {
-	// 	form.value.expectedProductionId = rows[0].id
-	// 	form.value.variety = rows[0].variety
-	// 	form.value.planDate = rows[0].planDate
-	// 	form.value.productionQuantity = rows[0].productionQuantity
-	// }
+	if (rows.length > 0) {
+		itemForm.value.expectedProductionId = rows[0].id
+		itemForm.value.variety = rows[0].variety
+		itemForm.value.productionQuantity = rows[0].productionQuantity
+	}
+}
+
+function submitSendForm() {
+	if (!sendForm.value || !sendForm.value.orderItemId) {
+		message.msgError("请先选择一条订单记录创建发货记录")
+		return
+	}
+	if (Number(sendForm.value.sendQuantity) > Number(sendForm.value.orderQuantity)) {
+		message.msgError("发货数量不能大于订单数量")
+		return
+	}
+	message.confirm("确定要发货吗?", "确定").then(() => {
+		apis.erp.orderSendApi.addOrUpdate(sendForm.value).then(() => {
+			handleItemQuery()
+		})
+	})
 }
 </script>
 <template>
 	<div class="app-container">
-		<VbDataTable
-			ref="tableRef"
-			keyField="id"
-			:columns="opts.columns"
-			:handle-perm="opts.permission"
-			:handle-btns="opts.handleBtns"
-			:handle-funs="opts.handleFuns"
-			:search-form-items="opts.searchFormItems"
-			:custom-btns="opts.customBtns"
-			:remote-fun="opts.tableListFun"
-			:get-entity-fun="opts.getEntityFun"
-			:delete-entity-fun="opts.deleteEntityFun"
-			:export-url="opts.exportUrl"
-			:export-name="opts.exportName"
-			:modal="modalRef"
-			:reset-form-fun="opts.resetForm"
-			v-model:form-data="form"
-			v-model:query-params="queryParams"
-			:check-multiple="true"
-			:reset-search-form-fun="resetQuery"
-			:custom-search-fun="handleQuery">
-			<template #deliveryDate="{ row }">
-				<template v-if="row.deliveryDate">
-					{{ dayjs(row.deliveryDate).format("YYYY-MM-DD") }}
-				</template>
-				<template v-else>-</template>
-			</template>
-			<template #status="{ row }">
-				<DictTag type="order_status" :value-is-number="1" :value="row.status"></DictTag>
-			</template>
-			<template #actions="{ row }">
-				<vb-tooltip content="修改" placement="top">
-					<el-button
-						link
-						type="primary"
-						@click="handleUpdate(row)"
-						v-hasPermission="'erp:order:edit'">
-						<template #icon>
-							<VbIcon icon-name="notepad-edit" icon-type="duotone" class="fs-3"></VbIcon>
-						</template>
-					</el-button>
-				</vb-tooltip>
-				<vb-tooltip content="删除" placement="top">
-					<el-button
-						link
-						type="primary"
-						@click="handleDelete([row])"
-						v-hasPermission="'erp:order:remove'">
-						<template #icon>
-							<VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
+		<div class="d-flex flex-column">
+			<div class="h-400px" style="border-bottom: 4px solid #ddd">
+				<VbDataTable
+					ref="tableRef"
+					keyField="id"
+					:columns="opts.columns"
+					:handle-perm="opts.permission"
+					:handle-btns="opts.handleBtns"
+					:handle-funs="opts.handleFuns"
+					:search-form-items="opts.searchFormItems"
+					:custom-btns="opts.customBtns"
+					:remote-fun="opts.tableListFun"
+					:get-entity-fun="opts.getEntityFun"
+					:delete-entity-fun="opts.deleteEntityFun"
+					:export-url="opts.exportUrl"
+					:export-name="opts.exportName"
+					:modal="modalRef"
+					:reset-form-fun="opts.resetForm"
+					v-model:form-data="form"
+					v-model:query-params="queryParams"
+					:check-multiple="false"
+					:has-checkbox="true"
+					:reset-search-form-fun="resetQuery"
+					:custom-search-fun="handleQuery"
+					@checkbox-change="handleCheckBoxChange"
+					@query-success="handleQuerySuccess">
+					<template #deliveryDate="{ row }">
+						<template v-if="row.deliveryDate">
+							{{ dayjs(row.deliveryDate).format("YYYY-MM-DD") }}
 						</template>
-					</el-button>
-				</vb-tooltip>
-			</template>
-		</VbDataTable>
+						<template v-else>-</template>
+					</template>
+					<template #status="{ row }">
+						<DictTag type="order_status" :value-is-number="1" :value="row.status"></DictTag>
+					</template>
+					<template #actions="{ row }">
+						<vb-tooltip content="修改" placement="top" v-if="row.status === 1">
+							<el-button
+								link
+								type="primary"
+								@click="handleUpdate(row)"
+								v-hasPermission="'erp:order:edit'">
+								<template #icon>
+									<VbIcon icon-name="notepad-edit" icon-type="duotone" class="fs-3"></VbIcon>
+								</template>
+							</el-button>
+						</vb-tooltip>
+						<vb-tooltip content="退订" placement="top" v-if="row.status === 1">
+							<el-button
+								link
+								type="primary"
+								@click="handleCancel([row])"
+								v-hasPermission="'erp:order:cancel'">
+								<template #icon>
+									<VbIcon
+										icon-name="abstract-11"
+										icon-type="duotone"
+										class="fs-3 text-danger"></VbIcon>
+								</template>
+							</el-button>
+						</vb-tooltip>
+						<vb-tooltip content="审核" placement="top" v-if="row.status === 1">
+							<el-button
+								link
+								type="primary"
+								@click="handleAudit([row])"
+								v-hasPermission="'erp:order:audit'">
+								<template #icon>
+									<VbIcon
+										icon-name="security-user"
+										icon-type="duotone"
+										class="fs-3 text-warning"></VbIcon>
+								</template>
+							</el-button>
+						</vb-tooltip>
+						<vb-tooltip content="退订审核" placement="top" v-if="row.status === 4">
+							<el-button
+								link
+								type="primary"
+								@click="handleAuditCancel([row])"
+								v-hasPermission="'erp:order:auditCancel'">
+								<template #icon>
+									<VbIcon
+										icon-name="key-square"
+										icon-type="duotone"
+										class="fs-3 text-warning"></VbIcon>
+								</template>
+							</el-button>
+						</vb-tooltip>
+						<vb-tooltip content="售后回访记录" placement="top">
+							<el-button
+								link
+								type="primary"
+								@click="handleFeedback([row])"
+								v-hasPermission="'erp:feedback:add'">
+								<template #icon>
+									<VbIcon
+										icon-name="abstract-14"
+										icon-type="duotone"
+										class="fs-3 text-primary"></VbIcon>
+								</template>
+							</el-button>
+						</vb-tooltip>
+						<vb-tooltip content="付款记录" placement="top">
+							<el-button
+								link
+								type="primary"
+								@click="handlePayRecord()"
+								v-hasPermission="'erp:payRecord:add'">
+								<template #icon>
+									<VbIcon icon-name="paypal" icon-type="duotone" class="fs-3 text-danger"></VbIcon>
+								</template>
+							</el-button>
+						</vb-tooltip>
+						<vb-tooltip content="结清" placement="top" v-if="row.status === 2">
+							<el-button
+								link
+								type="primary"
+								@click="handleComplete([row])"
+								v-hasPermission="'erp:order:complete'">
+								<template #icon>
+									<VbIcon icon-name="check" icon-type="duotone" class="fs-3 text-success"></VbIcon>
+								</template>
+							</el-button>
+						</vb-tooltip>
+					</template>
+				</VbDataTable>
+			</div>
+			<div class="mt-1 h-200px">
+				<VbDataTable
+					ref="tableItemRef"
+					keyField="id"
+					tableBoxHeight="380px"
+					:showRightToolbar="false"
+					:showSearchBar="false"
+					:columns="itemOpts.columns"
+					:handle-perm="itemOpts.permission"
+					:handle-btns="itemOpts.handleBtns"
+					:handle-funs="itemOpts.handleFuns"
+					:custom-btns="itemOpts.customBtns"
+					:remote-fun="itemOpts.tableListFun"
+					:get-entity-fun="itemOpts.getEntityFun"
+					:delete-entity-fun="itemOpts.deleteEntityFun"
+					:export-url="itemOpts.exportUrl"
+					:export-name="itemOpts.exportName"
+					:modal="modalItemRef"
+					:reset-form-fun="itemOpts.resetForm"
+					v-model:form-data="itemForm"
+					v-model:query-params="itemQueryParams"
+					:noPage="true"
+					:check-multiple="true">
+					<!-- @form-edit="handleItemEdit" -->
+					<template #status="{ row }">
+						<DictTag type="order_item_status" :value-is-number="true" :value="row.status"></DictTag>
+					</template>
+					<!-- <template #signedPhoto="{ row }">
+						<VbImagePreview
+							v-if="row.signedPhoto"
+							:src="row.signedPhoto"
+							:image-style="{ margin: `6px 5px -10px 5px`, padding: 0 }"></VbImagePreview>
+						<template v-else>-</template>
+					</template> -->
+					<template #actions="{ row }">
+						<vb-tooltip content="修改" placement="top" v-if="row.status === 1">
+							<el-button
+								link
+								type="primary"
+								@click="handleItemUpdate(row)"
+								v-hasPermission="'erp:orderItem:edit'">
+								<template #icon>
+									<VbIcon icon-name="notepad-edit" icon-type="duotone" class="fs-3"></VbIcon>
+								</template>
+							</el-button>
+						</vb-tooltip>
+						<vb-tooltip content="发货" placement="top" v-if="row.status === 2 || row.status === 3">
+							<el-button
+								link
+								type="primary"
+								@click="handleItemSend(row)"
+								v-hasPermission="'erp:orderItem:send'">
+								<template #icon>
+									<VbIcon icon-name="send" icon-type="solid" class="fs-3 text-success"></VbIcon>
+								</template>
+							</el-button>
+						</vb-tooltip>
+						<vb-tooltip content="删除" placement="top" v-if="row.status === 1">
+							<el-button
+								link
+								type="primary"
+								@click="handleItemDelete([row])"
+								v-hasPermission="'erp:orderItem:remove'">
+								<template #icon>
+									<VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
+								</template>
+							</el-button>
+						</vb-tooltip>
+					</template>
+				</VbDataTable>
+			</div>
+		</div>
+
 		<VbModal
 			v-model:modal="modalRef"
 			:title="opts.modalTitle"
@@ -349,6 +935,25 @@ function handleConfirmExpectedProductionModal(rows: any[]) {
 				<div></div>
 			</template>
 		</VbModal>
+		<VbModal
+			v-model:modal="modalItemRef"
+			:title="itemOpts.modalTitle"
+			:form-data="itemForm"
+			:form-items="itemOpts.formItems"
+			:label-width="itemOpts.labelWidth"
+			append-to-body
+			@confirm="submitItemForm"></VbModal>
+
+		<VbModal
+			v-model:modal="modalSendRef"
+			:title="sendOpts.modalTitle"
+			:form-data="sendForm"
+			:form-items="sendOpts.formItems"
+			:label-width="sendOpts.labelWidth"
+			append-to-body
+			@confirm="submitSendForm"></VbModal>
+		<VbFeedbackModal ref="modalFeedbackRef"></VbFeedbackModal>
+		<VbPayRecordModal ref="modalPayRecordRef"></VbPayRecordModal>
 		<CustomerSelect
 			ref="customerModalRef"
 			:multiple="false"

+ 388 - 0
UI/VB.VUE/src/views/erp/sale/orderSend/index.vue

@@ -0,0 +1,388 @@
+<script setup lang="ts" name="OrderSend">
+import apis from "@a"
+import dayjs from "dayjs"
+
+const tableRef = ref()
+const modalRef = ref()
+const opts = reactive({
+	columns: [
+		{ field: "id", name: "", width: 100, isSort: true, visible: false, tooltip: true },
+		{
+			field: "orderNum",
+			name: "订单编号",
+			visible: true,
+			isSort: false,
+			width: "auto",
+			tooltip: true
+		},
+		{
+			field: "sendQuantity",
+			name: "发货数量",
+			visible: true,
+			isSort: false,
+			width: "auto",
+			tooltip: true
+		},
+		{ field: "sendDate", name: "发货时间", visible: true, isSort: false, width: 145 },
+		{ field: "carNum", name: "车牌号", visible: true, isSort: false, width: "auto", tooltip: true },
+		{ field: "deliveryDate", name: "实际交付日期", visible: true, isSort: false, width: 145 },
+		{
+			field: "signedPhoto",
+			name: "签收照片",
+			visible: true,
+			isSort: false,
+			width: "auto",
+			tooltip: true
+		},
+		{ field: "remark", name: "备注", visible: true, isSort: false, tooltip: true },
+		{ field: "actions", name: `操作`, width: 150 }
+	] as any[],
+	queryParams: {
+		orderNum: undefined,
+		orderItemId: undefined,
+		sendQuantity: undefined,
+		dateRangeSendDate: undefined,
+		carNum: undefined,
+		dateRangeDeliveryDate: undefined,
+		signedPhoto: undefined
+	},
+	searchFormItems: [
+		{
+			field: "orderNum",
+			label: "订单编号",
+			class: "w-100",
+			required: false,
+			placeholder: "请输入订单编号",
+			component: "I",
+			listeners: {
+				keyup: (e: KeyboardEvent) => {
+					if (e.code == "Enter") {
+						handleQuery()
+					}
+				}
+			}
+		},
+		// {
+		// 	field: "sendQuantity",
+		// 	label: "发货数量",
+		// 	class: "w-100",
+		// 	required: false,
+		// 	placeholder: "请输入发货数量",
+		// 	component: "I",
+		// 	listeners: {
+		// 		keyup: (e: KeyboardEvent) => {
+		// 			if (e.code == "Enter") {
+		// 				handleQuery()
+		// 			}
+		// 		}
+		// 	}
+		// },
+		{
+			field: "dateRangeSendDate",
+			label: "发货时间",
+			class: "w-100",
+			required: false,
+			component: "D",
+			placeholder: "请选择发货时间",
+			props: {
+				type: "daterange",
+				valueFormat: "YYYY-MM-DD",
+				rangeSeparator: "-",
+				startPlaceholder: "开始日期",
+				endPlaceholder: "结束日期"
+			},
+			listeners: {
+				change: (v: any) => {
+					queryParams.value.dateRangeSendDate = v
+					handleQuery()
+				}
+			},
+			span: 5
+		},
+		// {
+		// 	field: "carNum",
+		// 	label: "车牌号",
+		// 	class: "w-100",
+		// 	required: false,
+		// 	placeholder: "请输入车牌号",
+		// 	component: "I",
+		// 	listeners: {
+		// 		keyup: (e: KeyboardEvent) => {
+		// 			if (e.code == "Enter") {
+		// 				handleQuery()
+		// 			}
+		// 		}
+		// 	}
+		// },
+		{
+			field: "dateRangeDeliveryDate",
+			label: "实际交付日期",
+			class: "w-100",
+			required: false,
+			component: "D",
+			placeholder: "请选择实际交付日期",
+			props: {
+				type: "daterange",
+				valueFormat: "YYYY-MM-DD",
+				rangeSeparator: "-",
+				startPlaceholder: "开始日期",
+				endPlaceholder: "结束日期"
+			},
+			listeners: {
+				change: (v: any) => {
+					queryParams.value.dateRangeDeliveryDate = v
+					handleQuery()
+				}
+			},
+			span: 5
+		}
+		// {
+		// 	field: "signedPhoto",
+		// 	label: "签收照片",
+		// 	class: "w-100",
+		// 	required: false,
+		// 	placeholder: "请输入签收照片",
+		// 	component: "I",
+		// 	listeners: {
+		// 		keyup: (e: KeyboardEvent) => {
+		// 			if (e.code == "Enter") {
+		// 				handleQuery()
+		// 			}
+		// 		}
+		// 	}
+		// }
+	] as any,
+	permission: "erp:orderSend",
+	handleBtns: [],
+	handleFuns: {
+		handleCreate,
+		handleUpdate: () => {
+			const row = tableRef.value.getSelected()
+			handleUpdate(row)
+		},
+		handleDelete: () => {
+			const rows = tableRef.value.getSelecteds()
+			handleDelete(rows)
+		}
+	},
+	customBtns: [],
+	tableListFun: apis.erp.orderSendApi.list,
+	getEntityFun: apis.erp.orderSendApi.get,
+	deleteEntityFun: apis.erp.orderSendApi.del,
+	exportUrl: apis.erp.orderSendApi.exportUrl,
+	exportName: "OrderSend",
+	modalTitle: "发货记录",
+	formItems: [
+		{
+			field: "orderNum",
+			label: "订单编号",
+			class: "w-100",
+			required: true,
+			disabled: true,
+			placeholder: "请输入订单编号",
+			component: "I"
+		},
+		{
+			field: "sendQuantity",
+			label: "发货数量",
+			class: "w-100",
+			required: true,
+			placeholder: "请输入发货数量",
+			component: "I"
+		},
+		{
+			field: "sendDate",
+			label: "发货时间",
+			class: "w-100",
+			required: true,
+			component: "D",
+			props: {
+				placeholder: "请选择发货时间",
+				type: "date",
+				valueFormat: "YYYY-MM-DD"
+			}
+		},
+		{
+			field: "carNum",
+			label: "车牌号",
+			class: "w-100",
+			required: false,
+			placeholder: "请输入车牌号",
+			component: "I"
+		},
+		{
+			field: "deliveryDate",
+			label: "实际交付日期",
+			class: "w-100",
+			required: false,
+			component: "D",
+			props: {
+				placeholder: "请选择实际交付日期",
+				type: "date",
+				valueFormat: "YYYY-MM-DD"
+			}
+		},
+		{
+			field: "signedPhoto",
+			label: "签收照片",
+			class: "w-100",
+			required: false,
+			placeholder: "请输入签收照片",
+			component: "VbUpload",
+			props: {
+				uploadUrl: "resource/oss/upload/erp"
+			}
+		},
+		{
+			field: "remark",
+			label: "备注",
+			class: "w-100",
+			required: false,
+			placeholder: "请输入备注",
+			component: "I",
+			props: {
+				type: "textarea",
+				rows: 5
+			}
+		}
+	] as any,
+	resetForm: () => {
+		form.value = emptyFormData.value
+	},
+	labelWidth: "80px",
+	emptyFormData: {
+		id: undefined,
+		orderItemId: undefined,
+		sendQuantity: undefined,
+		sendDate: undefined,
+		carNum: undefined,
+		deliveryDate: undefined,
+		signedPhoto: undefined,
+		remark: undefined
+	}
+})
+const { queryParams, emptyFormData } = toRefs(opts)
+const form = ref<any>(emptyFormData.value)
+
+/** 搜索按钮操作 */
+function handleQuery(query?: any) {
+	query = query || tableRef.value?.getQueryParams() || queryParams.value
+	addDateRange(query, query.dateRangeSendDate, "SendDate")
+	addDateRange(query, query.dateRangeDeliveryDate, "DeliveryDate")
+	addDateRange(query, query.dateRangeCreateTime)
+	addDateRange(query, query.dateRangeUpdateTime, "UpdateTime")
+	tableRef.value?.query(query)
+}
+
+/** 重置按钮操作 */
+function resetQuery(query?: any) {
+	query = query || tableRef.value?.getQueryParams() || queryParams.value
+	query.dateRangeSendDate = [] as any
+	addDateRange(query, query.dateRangeSendDate, "SendDate")
+	query.dateRangeDeliveryDate = [] as any
+	addDateRange(query, query.dateRangeDeliveryDate, "DeliveryDate")
+	query.dateRangeCreateTime = [] as any
+	addDateRange(query, query.dateRangeCreateTime)
+	query.dateRangeUpdateTime = [] as any
+	addDateRange(query, query.dateRangeUpdateTime, "UpdateTime")
+	//
+}
+
+function handleCreate() {
+	tableRef.value.defaultHandleFuns.handleCreate()
+}
+
+/** 修改按钮操作 */
+function handleUpdate(row: any) {
+	tableRef.value.defaultHandleFuns.handleUpdate("", row)
+}
+
+/** 删除按钮操作 */
+function handleDelete(rows: any[]) {
+	tableRef.value.defaultHandleFuns.handleDelete("", rows)
+}
+
+/** 提交按钮 */
+function submitForm() {
+	apis.erp.orderSendApi.addOrUpdate(form.value).then(() => {
+		handleQuery()
+	})
+}
+</script>
+<template>
+	<div class="app-container">
+		<VbDataTable
+			ref="tableRef"
+			keyField="id"
+			:columns="opts.columns"
+			:handle-perm="opts.permission"
+			:handle-btns="opts.handleBtns"
+			:handle-funs="opts.handleFuns"
+			:search-form-items="opts.searchFormItems"
+			:custom-btns="opts.customBtns"
+			:remote-fun="opts.tableListFun"
+			:get-entity-fun="opts.getEntityFun"
+			:delete-entity-fun="opts.deleteEntityFun"
+			:export-url="opts.exportUrl"
+			:export-name="opts.exportName"
+			:modal="modalRef"
+			:reset-form-fun="opts.resetForm"
+			v-model:form-data="form"
+			v-model:query-params="queryParams"
+			:check-multiple="true"
+			:reset-search-form-fun="resetQuery"
+			:custom-search-fun="handleQuery">
+			<template #sendDate="{ row }">
+				<template v-if="row.sendDate">
+					{{ dayjs(row.sendDate).format("YYYY-MM-DD") }}
+				</template>
+				<template v-else>-</template>
+			</template>
+			<template #signedPhoto="{ row }">
+				<VbImagePreview
+					v-if="row.signedPhoto"
+					:src="row.signedPhoto"
+					:image-style="{ margin: `6px 5px -10px 5px`, padding: 0 }"></VbImagePreview>
+				<template v-else>-</template>
+			</template>
+			<template #deliveryDate="{ row }">
+				<template v-if="row.deliveryDate">
+					{{ dayjs(row.deliveryDate).format("YYYY-MM-DD") }}
+				</template>
+				<template v-else>-</template>
+			</template>
+			<template #actions="{ row }">
+				<vb-tooltip content="修改" placement="top">
+					<el-button
+						link
+						type="primary"
+						@click="handleUpdate(row)"
+						v-hasPermission="'erp:orderSend:edit'">
+						<template #icon>
+							<VbIcon icon-name="notepad-edit" icon-type="duotone" class="fs-3"></VbIcon>
+						</template>
+					</el-button>
+				</vb-tooltip>
+				<vb-tooltip content="删除" placement="top">
+					<el-button
+						link
+						type="primary"
+						@click="handleDelete([row])"
+						v-hasPermission="'erp:orderSend:remove'">
+						<template #icon>
+							<VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
+						</template>
+					</el-button>
+				</vb-tooltip>
+			</template>
+		</VbDataTable>
+		<VbModal
+			v-model:modal="modalRef"
+			:title="opts.modalTitle"
+			:form-data="form"
+			:form-items="opts.formItems"
+			:label-width="opts.labelWidth"
+			append-to-body
+			@confirm="submitForm"></VbModal>
+	</div>
+</template>

+ 380 - 0
UI/VB.VUE/src/views/erp/sale/statementBill/index.vue

@@ -0,0 +1,380 @@
+<script setup lang="ts" name="StatementBill">
+import apis from "@a"
+import dayjs from "dayjs"
+import OrderSelect from "@@@/modal-select/OrderSelect.vue"
+const billStatusOptions = computed(() => {
+	return [
+		//{ label: "请选择", value: "" },
+		{ label: "已开票", value: "1" },
+		{ label: "未开票", value: "0" }
+	]
+})
+const isEdit = ref(false)
+const tableRef = ref()
+const modalRef = ref()
+const orderModalRef = ref()
+const opts = reactive({
+	columns: [
+		{ field: "id", name: "", width: 100, isSort: true, visible: false, tooltip: true },
+		{
+			field: "orderNum",
+			name: "订单号",
+			visible: true,
+			isSort: false,
+			width: "auto",
+			tooltip: true
+		},
+		{
+			field: "price",
+			name: "应收金额",
+			visible: true,
+			isSort: false,
+			width: "auto",
+			tooltip: true
+		},
+		{
+			field: "actualPrice",
+			name: "实收金额",
+			visible: true,
+			isSort: false,
+			width: "auto",
+			tooltip: true
+		},
+		{
+			field: "billStatus",
+			name: "是否开票",
+			visible: true,
+			isSort: false,
+			width: "auto",
+			tooltip: true
+		},
+		{ field: "billDate", name: "开票日期", visible: true, isSort: false, width: 145 },
+		{
+			field: "billPrice",
+			name: "发票金额",
+			visible: true,
+			isSort: false,
+			width: "auto",
+			tooltip: true
+		},
+		{
+			field: "billFile",
+			name: "发票pdf文件",
+			visible: true,
+			isSort: false,
+			width: "auto",
+			tooltip: true
+		},
+		{ field: "remark", name: "备注", visible: true, isSort: false, tooltip: true },
+		{ field: "actions", name: `操作`, width: 150 }
+	] as any[],
+	queryParams: {
+		orderId: undefined,
+		price: undefined,
+		actualPrice: undefined,
+		billStatus: undefined,
+		dateRangeBillDate: undefined,
+		billPrice: undefined,
+		billFile: undefined
+	},
+	searchFormItems: [
+		{
+			field: "orderNum",
+			label: "订单号",
+			class: "w-100",
+			required: false,
+			placeholder: "请输入订单号",
+			component: "I",
+			listeners: {
+				keyup: (e: KeyboardEvent) => {
+					if (e.code == "Enter") {
+						handleQuery()
+					}
+				}
+			}
+		},
+		{
+			field: "billStatus",
+			label: "是否开票",
+			class: "w-100",
+			required: false,
+			component: "VS",
+			placeholder: "请选择是否开票",
+			data: () => billStatusOptions.value,
+			props: {
+				valueIsNumber: 1,
+				type: "select"
+			},
+			listeners: {
+				change: () => {
+					handleQuery()
+				}
+			}
+		},
+		{
+			field: "dateRangeBillDate",
+			label: "开票日期",
+			class: "w-100",
+			required: false,
+			component: "D",
+			placeholder: "请选择开票日期",
+			props: {
+				type: "daterange",
+				valueFormat: "YYYY-MM-DD",
+				rangeSeparator: "-",
+				startPlaceholder: "开始日期",
+				endPlaceholder: "结束日期"
+			},
+			listeners: {
+				change: (v: any) => {
+					queryParams.value.dateRangeBillDate = v
+					handleQuery()
+				}
+			},
+			span: 5
+		}
+	] as any,
+	permission: "erp:statementBill",
+	handleBtns: [],
+	handleFuns: {
+		handleCreate,
+		handleUpdate: () => {
+			const row = tableRef.value.getSelected()
+			handleUpdate(row)
+		},
+		handleDelete: () => {
+			const rows = tableRef.value.getSelecteds()
+			handleDelete(rows)
+		}
+	},
+	customBtns: [],
+	tableListFun: apis.erp.statementBillApi.list,
+	getEntityFun: apis.erp.statementBillApi.get,
+	deleteEntityFun: apis.erp.statementBillApi.del,
+	exportUrl: apis.erp.statementBillApi.exportUrl,
+	exportName: "StatementBill",
+	modalTitle: "对账单信息",
+	formItems: [
+		{
+			field: "orderNum",
+			label: "订单编号",
+			class: "w-100",
+			required: true,
+			placeholder: "请输入",
+			component: "I",
+			disabled: true,
+			appendClickFunc: handleShowOrderModal,
+			appendDisabled: () => isEdit.value
+		},
+		{
+			field: "price",
+			label: "应收",
+			class: "w-100",
+			required: true,
+			placeholder: "请输入应收",
+			component: "I"
+		},
+		{
+			field: "actualPrice",
+			label: "实收",
+			class: "w-100",
+			required: true,
+			placeholder: "请输入实收",
+			component: "I"
+		},
+		{
+			field: "billStatus",
+			label: "是否开票",
+			class: "w-100",
+			required: true,
+			component: "VS",
+			data: () => billStatusOptions.value,
+			props: {
+				type: "radio",
+				valueIsNumber: 1
+			}
+		},
+		{
+			field: "billDate",
+			label: "开票日期",
+			class: "w-100",
+			required: false,
+			component: "D",
+			props: {
+				placeholder: "请选择开票日期",
+				type: "date",
+				valueFormat: "YYYY-MM-DD"
+			}
+		},
+		{
+			field: "billPrice",
+			label: "发票金额",
+			class: "w-100",
+			required: true,
+			placeholder: "请输入发票金额",
+			component: "I"
+		},
+		{
+			field: "billFile",
+			label: "发票pdf文件",
+			class: "w-100",
+			required: false,
+			component: "VbUpload",
+			props: {
+				uploadUrl: "resource/oss/upload/erp"
+			}
+		},
+		{
+			field: "remark",
+			label: "备注",
+			class: "w-100",
+			required: false,
+			placeholder: "请输入备注",
+			component: "I",
+			props: {
+				type: "textarea",
+				rows: 5
+			}
+		}
+	] as any,
+	resetForm: () => {
+		form.value = emptyFormData.value
+	},
+	labelWidth: "80px",
+	emptyFormData: {
+		id: undefined,
+		orderId: undefined,
+		orderNum: undefined,
+		price: undefined,
+		actualPrice: undefined,
+		billStatus: 0,
+		billDate: undefined,
+		billPrice: undefined,
+		billFile: undefined,
+		remark: undefined
+	}
+})
+const { queryParams, emptyFormData } = toRefs(opts)
+const form = ref<any>(emptyFormData.value)
+
+/** 搜索按钮操作 */
+function handleQuery(query?: any) {
+	query = query || tableRef.value?.getQueryParams() || queryParams.value
+	addDateRange(query, query.dateRangeBillDate, "BillDate")
+	addDateRange(query, query.dateRangeCreateTime)
+	addDateRange(query, query.dateRangeUpdateTime, "UpdateTime")
+	tableRef.value?.query(query)
+}
+
+/** 重置按钮操作 */
+function resetQuery(query?: any) {
+	query = query || tableRef.value?.getQueryParams() || queryParams.value
+	query.dateRangeBillDate = [] as any
+	addDateRange(query, query.dateRangeBillDate, "BillDate")
+	query.dateRangeCreateTime = [] as any
+	addDateRange(query, query.dateRangeCreateTime)
+	query.dateRangeUpdateTime = [] as any
+	addDateRange(query, query.dateRangeUpdateTime, "UpdateTime")
+	//
+}
+function handleShowOrderModal() {
+	orderModalRef.value.open()
+}
+function handleConfirmOrderModal(rows: any[]) {
+	if (rows.length > 0) {
+		form.value.orderId = rows[0].id
+		form.value.orderNum = rows[0].orderNum
+	}
+}
+function handleCreate() {
+	tableRef.value.defaultHandleFuns.handleCreate()
+}
+
+/** 修改按钮操作 */
+function handleUpdate(row: any) {
+	tableRef.value.defaultHandleFuns.handleUpdate("", row)
+}
+
+/** 删除按钮操作 */
+function handleDelete(rows: any[]) {
+	tableRef.value.defaultHandleFuns.handleDelete("", rows)
+}
+
+/** 提交按钮 */
+function submitForm() {
+	apis.erp.statementBillApi.addOrUpdate(form.value).then(() => {
+		handleQuery()
+	})
+}
+</script>
+<template>
+	<div class="app-container">
+		<VbDataTable
+			ref="tableRef"
+			keyField="id"
+			:columns="opts.columns"
+			:handle-perm="opts.permission"
+			:handle-btns="opts.handleBtns"
+			:handle-funs="opts.handleFuns"
+			:search-form-items="opts.searchFormItems"
+			:custom-btns="opts.customBtns"
+			:remote-fun="opts.tableListFun"
+			:get-entity-fun="opts.getEntityFun"
+			:delete-entity-fun="opts.deleteEntityFun"
+			:export-url="opts.exportUrl"
+			:export-name="opts.exportName"
+			:modal="modalRef"
+			:reset-form-fun="opts.resetForm"
+			v-model:form-data="form"
+			v-model:query-params="queryParams"
+			:check-multiple="true"
+			:reset-search-form-fun="resetQuery"
+			:custom-search-fun="handleQuery">
+			<template #billStatus="{ row }">
+				<VbTag :data="billStatusOptions" :value-is-number="1" :value="row.billStatus"></VbTag>
+			</template>
+			<template #billDate="{ row }">
+				<template v-if="row.billDate">
+					{{ dayjs(row.billDate).format("YYYY-MM-DD") }}
+				</template>
+				<template v-else>-</template>
+			</template>
+			<template #actions="{ row }">
+				<vb-tooltip content="修改" placement="top">
+					<el-button
+						link
+						type="primary"
+						@click="handleUpdate(row)"
+						v-hasPermission="'erp:statementBill:edit'">
+						<template #icon>
+							<VbIcon icon-name="notepad-edit" icon-type="duotone" class="fs-3"></VbIcon>
+						</template>
+					</el-button>
+				</vb-tooltip>
+				<vb-tooltip content="删除" placement="top">
+					<el-button
+						link
+						type="primary"
+						@click="handleDelete([row])"
+						v-hasPermission="'erp:statementBill:remove'">
+						<template #icon>
+							<VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
+						</template>
+					</el-button>
+				</vb-tooltip>
+			</template>
+		</VbDataTable>
+		<VbModal
+			v-model:modal="modalRef"
+			:title="opts.modalTitle"
+			:form-data="form"
+			:form-items="opts.formItems"
+			:label-width="opts.labelWidth"
+			append-to-body
+			@confirm="submitForm"></VbModal>
+		<OrderSelect
+			ref="orderModalRef"
+			:multiple="false"
+			@confirm="handleConfirmOrderModal"></OrderSelect>
+	</div>
+</template>