Przeglądaj źródła

订单相关,客户相关等模块

hurx 5 miesięcy temu
rodzic
commit
5d3044a3dd
69 zmienionych plików z 13446 dodań i 136 usunięć
  1. 74 0
      src/api/company/comCurrency/index.ts
  2. 105 0
      src/api/company/comCurrency/types.ts
  3. 63 0
      src/api/company/logisticsCompany/index.ts
  4. 116 0
      src/api/company/logisticsCompany/types.ts
  5. 74 0
      src/api/company/revenueExpense/index.ts
  6. 135 0
      src/api/company/revenueExpense/types.ts
  7. 75 0
      src/api/company/warehouse/index.ts
  8. 380 0
      src/api/company/warehouse/types.ts
  9. 1 1
      src/api/customer/customerFile/customerDept/index.ts
  10. 2 2
      src/api/customer/customerFile/customerDept/types.ts
  11. 3 3
      src/api/customer/customerFile/salesInfo/types.ts
  12. 63 0
      src/api/order/deliverProduct/index.ts
  13. 135 0
      src/api/order/deliverProduct/types.ts
  14. 63 0
      src/api/order/orderDeliver/index.ts
  15. 243 0
      src/api/order/orderDeliver/types.ts
  16. 102 0
      src/api/order/orderMain/index.ts
  17. 752 0
      src/api/order/orderMain/types.ts
  18. 63 0
      src/api/order/orderProduct/index.ts
  19. 425 0
      src/api/order/orderProduct/types.ts
  20. 63 0
      src/api/order/orderReturn/index.ts
  21. 566 0
      src/api/order/orderReturn/types.ts
  22. 63 0
      src/api/order/orderReturnItem/index.ts
  23. 170 0
      src/api/order/orderReturnItem/types.ts
  24. 75 0
      src/api/order/returnReason/index.ts
  25. 110 0
      src/api/order/returnReason/types.ts
  26. 63 0
      src/api/order/revenueDetail/index.ts
  27. 215 0
      src/api/order/revenueDetail/types.ts
  28. 75 0
      src/api/order/revenueHeader/index.ts
  29. 247 0
      src/api/order/revenueHeader/types.ts
  30. 63 0
      src/api/product/afterSales/index.ts
  31. 65 0
      src/api/product/afterSales/types.ts
  32. 63 0
      src/api/product/attributes/index.ts
  33. 160 0
      src/api/product/attributes/types.ts
  34. 156 0
      src/api/product/base/index.ts
  35. 674 0
      src/api/product/base/types.ts
  36. 63 0
      src/api/product/brand/index.ts
  37. 309 0
      src/api/product/brand/types.ts
  38. 74 0
      src/api/product/category/index.ts
  39. 392 0
      src/api/product/category/types.ts
  40. 63 0
      src/api/product/ensure/index.ts
  41. 65 0
      src/api/product/ensure/types.ts
  42. 63 0
      src/api/product/unit/index.ts
  43. 95 0
      src/api/product/unit/types.ts
  44. 8 0
      src/api/system/dept/index.ts
  45. 6 54
      src/api/system/dept/types.ts
  46. 55 20
      src/views/customer/customerFile/customerInfo/add.vue
  47. 3 0
      src/views/customer/customerFile/customerInfo/index.vue
  48. 83 30
      src/views/customer/customerFile/customerInfo/overview/baseInfo.vue
  49. 21 26
      src/views/customer/customerFile/customerInfo/overview/orgStructure.vue
  50. 202 0
      src/views/order/expense/index.vue
  51. 181 0
      src/views/order/orderAssignment/assignmentDialog.vue
  52. 337 0
      src/views/order/orderAssignment/index.vue
  53. 328 0
      src/views/order/orderAssignment/splitAssignDialog.vue
  54. 369 0
      src/views/order/orderDeliver/index.vue
  55. 130 0
      src/views/order/orderInquiry/index.vue
  56. 168 0
      src/views/order/orderMain/components/addressDialog.vue
  57. 102 0
      src/views/order/orderMain/components/chooseAddress.vue
  58. 225 0
      src/views/order/orderMain/components/chooseProduct.vue
  59. 149 0
      src/views/order/orderMain/components/selectProductDetail.vue
  60. 987 0
      src/views/order/orderMain/index.vue
  61. 283 0
      src/views/order/orderReturn/index.vue
  62. 265 0
      src/views/order/orderReturn/returnDetail.vue
  63. 135 0
      src/views/order/orderService/index.vue
  64. 290 0
      src/views/order/orderService/serviceDetail.vue
  65. 571 0
      src/views/order/revenueHeader/add.vue
  66. 291 0
      src/views/order/revenueHeader/index.vue
  67. 388 0
      src/views/order/saleOrder/deliverDialog.vue
  68. 539 0
      src/views/order/saleOrder/index.vue
  69. 504 0
      src/views/order/saleOrder/sendDetail.vue

+ 74 - 0
src/api/company/comCurrency/index.ts

@@ -0,0 +1,74 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { ComCurrencyVO, ComCurrencyForm, ComCurrencyQuery } from '@/api/company/comCurrency/types';
+
+/**
+ * 查询交易币别配置列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listComCurrency = (query?: ComCurrencyQuery): AxiosPromise<ComCurrencyVO[]> => {
+  return request({
+    url: '/system/comCurrency/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询交易币别配置详细
+ * @param id
+ */
+export const getComCurrency = (id: string | number): AxiosPromise<ComCurrencyVO> => {
+  return request({
+    url: '/system/comCurrency/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增交易币别配置
+ * @param data
+ */
+export const addComCurrency = (data: ComCurrencyForm) => {
+  return request({
+    url: '/system/comCurrency',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改交易币别配置
+ * @param data
+ */
+export const updateComCurrency = (data: ComCurrencyForm) => {
+  return request({
+    url: '/system/comCurrency',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除交易币别配置
+ * @param id
+ */
+export const delComCurrency = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/system/comCurrency/' + id,
+    method: 'delete'
+  });
+};
+export function changeStatus(id: string | number, isShow: string) {
+  const data = {
+    id,
+    isShow
+  };
+  return request({
+    url: '/system/comCurrency/changeStatus',
+    method: 'put',
+    data: data
+  });
+}

+ 105 - 0
src/api/company/comCurrency/types.ts

@@ -0,0 +1,105 @@
+export interface ComCurrencyVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 货币编码
+   */
+  currencyCode: string;
+
+  /**
+   * 货币名称
+   */
+  currencyName: string;
+
+  /**
+   * 是否显示(0-显示,1-不显示)
+   */
+  isShow: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface ComCurrencyForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 货币编码
+   */
+  currencyCode?: string;
+
+  /**
+   * 货币名称
+   */
+  currencyName?: string;
+
+  /**
+   * 是否显示(0-显示,1-不显示)
+   */
+  isShow?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface ComCurrencyQuery extends PageQuery {
+  /**
+   * 货币编码
+   */
+  currencyCode?: string;
+
+  /**
+   * 货币名称
+   */
+  currencyName?: string;
+
+  /**
+   * 是否显示(0-显示,1-不显示)
+   */
+  isShow?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 63 - 0
src/api/company/logisticsCompany/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { LogisticsCompanyVO, LogisticsCompanyForm, LogisticsCompanyQuery } from '@/api/company/logisticsCompany/types';
+
+/**
+ * 查询物流公司列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listLogisticsCompany = (query?: LogisticsCompanyQuery): AxiosPromise<LogisticsCompanyVO[]> => {
+  return request({
+    url: '/system/logisticsCompany/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询物流公司详细
+ * @param id
+ */
+export const getLogisticsCompany = (id: string | number): AxiosPromise<LogisticsCompanyVO> => {
+  return request({
+    url: '/system/logisticsCompany/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增物流公司
+ * @param data
+ */
+export const addLogisticsCompany = (data: LogisticsCompanyForm) => {
+  return request({
+    url: '/system/logisticsCompany',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改物流公司
+ * @param data
+ */
+export const updateLogisticsCompany = (data: LogisticsCompanyForm) => {
+  return request({
+    url: '/system/logisticsCompany',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除物流公司
+ * @param id
+ */
+export const delLogisticsCompany = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/system/logisticsCompany/' + id,
+    method: 'delete'
+  });
+};

+ 116 - 0
src/api/company/logisticsCompany/types.ts

@@ -0,0 +1,116 @@
+export interface LogisticsCompanyVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 物流公司编码
+   */
+  logisticsCode: string;
+
+  /**
+   * 物流公司名称
+   */
+  logisticsName: string;
+
+  /**
+   * 物流公司描述
+   */
+  logisticsDescription: string;
+
+  /**
+   * 是否显示
+   */
+  isShow: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+
+}
+
+export interface LogisticsCompanyForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 物流公司编码
+   */
+  logisticsCode?: string;
+
+  /**
+   * 物流公司名称
+   */
+  logisticsName?: string;
+
+  /**
+   * 物流公司描述
+   */
+  logisticsDescription?: string;
+
+  /**
+   * 是否显示
+   */
+  isShow?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+
+}
+
+export interface LogisticsCompanyQuery extends PageQuery {
+
+  /**
+   * 物流公司编码
+   */
+  logisticsCode?: string;
+
+  /**
+   * 物流公司名称
+   */
+  logisticsName?: string;
+
+  /**
+   * 物流公司描述
+   */
+  logisticsDescription?: string;
+
+  /**
+   * 是否显示
+   */
+  isShow?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+    /**
+     * 日期范围参数
+     */
+    params?: any;
+}
+
+
+

+ 74 - 0
src/api/company/revenueExpense/index.ts

@@ -0,0 +1,74 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { RevenueExpenseVO, RevenueExpenseForm, RevenueExpenseQuery } from '@/api/company/revenueExpense/types';
+
+/**
+ * 查询收入费用设定列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listRevenueExpense = (query?: RevenueExpenseQuery): AxiosPromise<RevenueExpenseVO[]> => {
+  return request({
+    url: '/system/revenueExpense/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询收入费用设定详细
+ * @param id
+ */
+export const getRevenueExpense = (id: string | number): AxiosPromise<RevenueExpenseVO> => {
+  return request({
+    url: '/system/revenueExpense/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增收入费用设定
+ * @param data
+ */
+export const addRevenueExpense = (data: RevenueExpenseForm) => {
+  return request({
+    url: '/system/revenueExpense',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改收入费用设定
+ * @param data
+ */
+export const updateRevenueExpense = (data: RevenueExpenseForm) => {
+  return request({
+    url: '/system/revenueExpense',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除收入费用设定
+ * @param id
+ */
+export const delRevenueExpense = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/system/revenueExpense/' + id,
+    method: 'delete'
+  });
+};
+export function changeStatus(id: string | number, isShow: string) {
+  const data = {
+    id,
+    isShow
+  };
+  return request({
+    url: '/system/revenueExpense/changeStatus',
+    method: 'put',
+    data: data
+  });
+}

+ 135 - 0
src/api/company/revenueExpense/types.ts

@@ -0,0 +1,135 @@
+export interface RevenueExpenseVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 编码
+   */
+  revenueCode: string;
+
+  /**
+   * 费用名称
+   */
+  revenueName: string;
+
+  /**
+   * 费用类(0 是  1否)
+   */
+  expenseFlag: string;
+
+  /**
+   * 收入类(0 是  1否)
+   */
+  revenueFlag: string;
+
+  /**
+   * 是否显示(0-显示,1-不显示)
+   */
+  isShow: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface RevenueExpenseForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 编码
+   */
+  revenueCode?: string;
+
+  /**
+   * 费用名称
+   */
+  revenueName?: string;
+
+  /**
+   * 费用类(0 是  1否)
+   */
+  expenseFlag?: string;
+
+  /**
+   * 收入类(0 是  1否)
+   */
+  revenueFlag?: string;
+
+  /**
+   * 是否显示(0-显示,1-不显示)
+   */
+  isShow?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface RevenueExpenseQuery extends PageQuery {
+  /**
+   * 编码
+   */
+  revenueCode?: string;
+
+  /**
+   * 费用名称
+   */
+  revenueName?: string;
+
+  /**
+   * 费用类(0 是  1否)
+   */
+  expenseFlag?: string;
+
+  /**
+   * 收入类(0 是  1否)
+   */
+  revenueFlag?: string;
+
+  /**
+   * 是否显示(0-显示,1-不显示)
+   */
+  isShow?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 75 - 0
src/api/company/warehouse/index.ts

@@ -0,0 +1,75 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { WarehouseVO, WarehouseForm, WarehouseQuery } from '@/api/company/warehouse/types';
+
+/**
+ * 查询仓库信息列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listWarehouse = (query?: WarehouseQuery): AxiosPromise<WarehouseVO[]> => {
+  return request({
+    url: '/system/warehouse/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询仓库信息详细
+ * @param id
+ */
+export const getWarehouse = (id: string | number): AxiosPromise<WarehouseVO> => {
+  return request({
+    url: '/system/warehouse/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增仓库信息
+ * @param data
+ */
+export const addWarehouse = (data: WarehouseForm) => {
+  return request({
+    url: '/system/warehouse',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改仓库信息
+ * @param data
+ */
+export const updateWarehouse = (data: WarehouseForm) => {
+  return request({
+    url: '/system/warehouse',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除仓库信息
+ * @param id
+ */
+export const delWarehouse = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/system/warehouse/' + id,
+    method: 'delete'
+  });
+};
+
+export function changeStatus(id: string | number, isShow: string) {
+  const data = {
+    id,
+    isShow
+  };
+  return request({
+    url: '/system/warehouse/changeStatus',
+    method: 'put',
+    data: data
+  });
+}

+ 380 - 0
src/api/company/warehouse/types.ts

@@ -0,0 +1,380 @@
+export interface WarehouseVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 仓库编码
+   */
+  warehouseCode: string;
+
+  /**
+   * 仓库名称
+   */
+  warehouseName: string;
+
+  /**
+   * 库存状态
+   */
+  stkStu: string;
+
+  /**
+   * 所属公司
+   */
+  companyId: string | number;
+
+  /**
+   * 省份
+   */
+  province: string;
+
+  /**
+   * 城市
+   */
+  city: string;
+
+  /**
+   * 区/县
+   */
+  district: string;
+
+  /**
+   * 省市区
+   */
+  provinceCityDistrict: string;
+
+  /**
+   * 仓库类型
+   */
+  warehouseType: string;
+
+  /**
+   * 仓库功能
+   */
+  warehouseFunction: string;
+
+  /**
+   * 是否支持发货
+   */
+  isShip: string;
+
+  /**
+   * 是否支持退货
+   */
+  isReturn: string;
+
+  /**
+   * 是否默认仓库
+   */
+  isDefault: string;
+
+  /**
+   * 是否前台展示
+   */
+  isShow: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource: string;
+
+  /**
+   * 联系人姓名
+   */
+  contacts: string;
+
+  /**
+   * 手机号
+   */
+  mobile: string;
+
+  /**
+   * 固定电话
+   */
+  phone: string;
+
+  /**
+   * 详细地址
+   */
+  address: string;
+
+  /**
+   * 邮政编码
+   */
+  zipCode: string;
+
+  /**
+   * 最大配送时效(天)
+   */
+  maxLeadTime: number;
+
+  /**
+   * 最小配送时效(天)
+   */
+  minLeadTime: number;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface WarehouseForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 仓库编码
+   */
+  warehouseCode?: string;
+
+  /**
+   * 仓库名称
+   */
+  warehouseName?: string;
+
+  /**
+   * 库存状态
+   */
+  stkStu?: string;
+
+  /**
+   * 所属公司
+   */
+  companyId?: string | number;
+
+  /**
+   * 省份
+   */
+  province?: string;
+
+  /**
+   * 城市
+   */
+  city?: string;
+
+  /**
+   * 区/县
+   */
+  district?: string;
+
+  /**
+   * 省市区
+   */
+  provinceCityDistrict?: string;
+
+  /**
+   * 仓库类型
+   */
+  warehouseType?: string;
+
+  /**
+   * 仓库功能
+   */
+  warehouseFunction?: string;
+
+  /**
+   * 是否支持发货
+   */
+  isShip?: string;
+
+  /**
+   * 是否支持退货
+   */
+  isReturn?: string;
+
+  /**
+   * 是否默认仓库
+   */
+  isDefault?: string;
+
+  /**
+   * 是否前台展示
+   */
+  isShow?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 联系人姓名
+   */
+  contacts?: string;
+
+  /**
+   * 手机号
+   */
+  mobile?: string;
+
+  /**
+   * 固定电话
+   */
+  phone?: string;
+
+  /**
+   * 详细地址
+   */
+  address?: string;
+
+  /**
+   * 邮政编码
+   */
+  zipCode?: string;
+
+  /**
+   * 最大配送时效(天)
+   */
+  maxLeadTime?: number;
+
+  /**
+   * 最小配送时效(天)
+   */
+  minLeadTime?: number;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface WarehouseQuery extends PageQuery {
+  /**
+   * 仓库编码
+   */
+  warehouseCode?: string;
+
+  /**
+   * 仓库名称
+   */
+  warehouseName?: string;
+
+  /**
+   * 库存状态
+   */
+  stkStu?: string;
+
+  /**
+   * 所属公司
+   */
+  companyId?: string | number;
+
+  /**
+   * 省份
+   */
+  province?: string;
+
+  /**
+   * 城市
+   */
+  city?: string;
+
+  /**
+   * 区/县
+   */
+  district?: string;
+
+  /**
+   * 省市区
+   */
+  provinceCityDistrict?: string;
+
+  /**
+   * 仓库类型
+   */
+  warehouseType?: string;
+
+  /**
+   * 仓库功能
+   */
+  warehouseFunction?: string;
+
+  /**
+   * 是否支持发货
+   */
+  isShip?: string;
+
+  /**
+   * 是否支持退货
+   */
+  isReturn?: string;
+
+  /**
+   * 是否默认仓库
+   */
+  isDefault?: string;
+
+  /**
+   * 是否前台展示
+   */
+  isShow?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 联系人姓名
+   */
+  contacts?: string;
+
+  /**
+   * 手机号
+   */
+  mobile?: string;
+
+  /**
+   * 固定电话
+   */
+  phone?: string;
+
+  /**
+   * 详细地址
+   */
+  address?: string;
+
+  /**
+   * 邮政编码
+   */
+  zipCode?: string;
+
+  /**
+   * 最大配送时效(天)
+   */
+  maxLeadTime?: number;
+
+  /**
+   * 最小配送时效(天)
+   */
+  minLeadTime?: number;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 1 - 1
src/api/customer/customerFile/customerDept/index.ts

@@ -10,7 +10,7 @@ import { CustomerDeptVO, CustomerDeptForm, CustomerDeptQuery } from '@/api/custo
 
 export const listCustomerDept = (query?: CustomerDeptQuery): AxiosPromise<CustomerDeptVO[]> => {
   return request({
-    url: '/customer/customerDept/list',
+    url: '/customer/customerDept/tree',
     method: 'get',
     params: query
   });

+ 2 - 2
src/api/customer/customerFile/customerDept/types.ts

@@ -2,7 +2,7 @@ export interface CustomerDeptVO {
   /**
    * ID
    */
-  id: string | number;
+  deptId: string | number;
 
   /**
    * 部门编号
@@ -114,7 +114,7 @@ export interface CustomerDeptForm extends BaseEntity {
   /**
    * ID
    */
-  id?: string | number;
+  deptId?: string | number;
 
   /**
    * 部门编号

+ 3 - 3
src/api/customer/customerFile/salesInfo/types.ts

@@ -47,7 +47,7 @@ export interface SalesInfoVO {
   /**
    * 信用管理方式
    */
-  creditManagement: string;
+  creditManagementId: number | string;
 
   /**
    * 信用支付密码
@@ -139,7 +139,7 @@ export interface SalesInfoForm extends BaseEntity {
   /**
    * 信用管理方式
    */
-  creditManagement?: string;
+  creditManagementId?: number | string;
 
   /**
    * 信用支付密码
@@ -226,7 +226,7 @@ export interface SalesInfoQuery extends PageQuery {
   /**
    * 信用管理方式
    */
-  creditManagement?: string;
+  creditManagementId?: number | string;
 
   /**
    * 信用支付密码

+ 63 - 0
src/api/order/deliverProduct/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { DeliverProductVO, DeliverProductForm, DeliverProductQuery } from '@/api/order/deliverProduct/types';
+
+/**
+ * 查询订单发货商品明细列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listDeliverProduct = (query?: DeliverProductQuery): AxiosPromise<DeliverProductVO[]> => {
+  return request({
+    url: '/order/deliverProduct/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询订单发货商品明细详细
+ * @param id
+ */
+export const getDeliverProduct = (id: string | number): AxiosPromise<DeliverProductVO> => {
+  return request({
+    url: '/order/deliverProduct/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增订单发货商品明细
+ * @param data
+ */
+export const addDeliverProduct = (data: DeliverProductForm) => {
+  return request({
+    url: '/order/deliverProduct',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改订单发货商品明细
+ * @param data
+ */
+export const updateDeliverProduct = (data: DeliverProductForm) => {
+  return request({
+    url: '/order/deliverProduct',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除订单发货商品明细
+ * @param id
+ */
+export const delDeliverProduct = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/order/deliverProduct/' + id,
+    method: 'delete'
+  });
+};

+ 135 - 0
src/api/order/deliverProduct/types.ts

@@ -0,0 +1,135 @@
+export interface DeliverProductVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 发货单
+   */
+  deliverId: string | number;
+
+  /**
+   * 商品编号
+   */
+  productId: string | number;
+
+  productNo: string;
+
+  /**
+   * 商品名称
+   */
+  productName: string;
+
+  /**
+   * 商品单位
+   */
+  productUnitId: string | number;
+
+  /**
+   * 商品单位
+   */
+  productUnit: string;
+
+  /**
+   * 本次发货数量
+   */
+  deliverNum: number;
+
+  dataSource: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface DeliverProductForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 发货单
+   */
+  deliverId?: string | number;
+
+  /**
+   * 商品编号
+   */
+  productId?: string | number;
+
+  productNo?: string;
+
+  /**
+   * 商品名称
+   */
+  productName?: string;
+
+  /**
+   * 商品单位
+   */
+  productUnitId?: string | number;
+
+  /**
+   * 商品单位
+   */
+  productUnit?: string;
+
+  /**
+   * 本次发货数量
+   */
+  deliverNum?: number;
+
+  dataSource?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface DeliverProductQuery extends PageQuery {
+  /**
+   * 发货单
+   */
+  deliverId?: string | number;
+
+  /**
+   * 商品编号
+   */
+  productId?: string | number;
+
+  /**
+   * 商品名称
+   */
+  productName?: string;
+
+  /**
+   * 商品单位
+   */
+  productUnitId?: string | number;
+
+  /**
+   * 商品单位
+   */
+  productUnit?: string;
+
+  /**
+   * 本次发货数量
+   */
+  deliverNum?: number;
+
+  dataSource?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 63 - 0
src/api/order/orderDeliver/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { OrderDeliverVO, OrderDeliverForm, OrderDeliverQuery } from '@/api/order/orderDeliver/types';
+
+/**
+ * 查询订单发货主列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listOrderDeliver = (query?: OrderDeliverQuery): AxiosPromise<OrderDeliverVO[]> => {
+  return request({
+    url: '/order/orderDeliver/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询订单发货主详细
+ * @param id
+ */
+export const getOrderDeliver = (id: string | number): AxiosPromise<OrderDeliverVO> => {
+  return request({
+    url: '/order/orderDeliver/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增订单发货主
+ * @param data
+ */
+export const addOrderDeliver = (data: OrderDeliverForm) => {
+  return request({
+    url: '/order/orderDeliver',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改订单发货主
+ * @param data
+ */
+export const updateOrderDeliver = (data: OrderDeliverForm) => {
+  return request({
+    url: '/order/orderDeliver',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除订单发货主
+ * @param id
+ */
+export const delOrderDeliver = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/order/orderDeliver/' + id,
+    method: 'delete'
+  });
+};

+ 243 - 0
src/api/order/orderDeliver/types.ts

@@ -0,0 +1,243 @@
+export interface OrderDeliverVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 订单id
+   */
+  orderId: string | number;
+
+  /**
+   * 订单编号
+   */
+  orderCode: string;
+
+  /**
+   * 物流包裹号
+   */
+  logisticPackNo: string;
+
+  /**
+   * 发货方式
+   */
+  deliverMethod: string;
+
+  /**
+   * 送货人姓名
+   */
+  deliverMan: string;
+
+  /**
+   * 送货人联系电话
+   */
+  phone: string;
+
+  /**
+   * 物流状态
+   */
+  logisticsStatus: string;
+
+  /**
+   * 发货备注
+   */
+  deliverRemark: string;
+
+  /**
+   * 装箱/验货备注
+   */
+  checklistRemark: string;
+
+  /**
+   * 承运物流公司
+   */
+  logisticsCompany: number;
+
+  /**
+   * 物流单号
+   */
+  logisticNo: string;
+
+  /**
+   * 包裹状态
+   */
+  logisticPackStatus: string;
+
+  /**
+   * 收货人电话
+   */
+  consigneePhone: string;
+
+  dataSource: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+
+  deliverProductList: any[];
+}
+
+export interface OrderDeliverForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 订单id
+   */
+  orderId?: string | number;
+
+  /**
+   * 订单编号
+   */
+  orderCode?: string;
+
+  /**
+   * 物流包裹号
+   */
+  logisticPackNo?: string;
+
+  /**
+   * 发货方式
+   */
+  deliverMethod?: string;
+
+  /**
+   * 送货人姓名
+   */
+  deliverMan?: string;
+
+  /**
+   * 送货人联系电话
+   */
+  phone?: string;
+
+  /**
+   * 物流状态
+   */
+  logisticsStatus?: string;
+
+  /**
+   * 发货备注
+   */
+  deliverRemark?: string;
+
+  /**
+   * 装箱/验货备注
+   */
+  checklistRemark?: string;
+
+  /**
+   * 承运物流公司
+   */
+  logisticsCompany?: number;
+
+  /**
+   * 物流单号
+   */
+  logisticNo?: string;
+
+  /**
+   * 包裹状态
+   */
+  logisticPackStatus?: string;
+
+  /**
+   * 收货人电话
+   */
+  consigneePhone?: string;
+
+  dataSource?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+
+  /**
+   * 订单商品明细列表
+   */
+  orderDeliverProducts?: any[];
+}
+
+export interface OrderDeliverQuery extends PageQuery {
+  /**
+   * 订单id
+   */
+  orderId?: string | number;
+
+  /**
+   * 订单编号
+   */
+  orderCode?: string;
+
+  /**
+   * 物流包裹号
+   */
+  logisticPackNo?: string;
+
+  /**
+   * 发货方式
+   */
+  deliverMethod?: string;
+
+  /**
+   * 送货人姓名
+   */
+  deliverMan?: string;
+
+  /**
+   * 送货人联系电话
+   */
+  phone?: string;
+
+  /**
+   * 物流状态
+   */
+  logisticsStatus?: string;
+
+  /**
+   * 发货备注
+   */
+  deliverRemark?: string;
+
+  /**
+   * 装箱/验货备注
+   */
+  checklistRemark?: string;
+
+  /**
+   * 承运物流公司
+   */
+  logisticsCompany?: number;
+
+  /**
+   * 物流单号
+   */
+  logisticNo?: string;
+
+  /**
+   * 包裹状态
+   */
+  logisticPackStatus?: string;
+
+  /**
+   * 收货人电话
+   */
+  consigneePhone?: string;
+
+  dataSource?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 102 - 0
src/api/order/orderMain/index.ts

@@ -0,0 +1,102 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { OrderMainVO, OrderMainForm, OrderMainQuery } from '@/api/order/orderMain/types';
+
+/**
+ * 查询订单主信息列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listOrderMain = (query?: OrderMainQuery): AxiosPromise<OrderMainVO[]> => {
+  return request({
+    url: '/order/orderMain/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询分配订单信息列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listOrderAssignment = (query?: OrderMainQuery): AxiosPromise<OrderMainVO[]> => {
+  return request({
+    url: '/order/orderMain/assignmentList',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询订单主信息详细
+ * @param id
+ */
+export const getOrderMain = (id: string | number): AxiosPromise<OrderMainVO> => {
+  return request({
+    url: '/order/orderMain/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增订单主信息
+ * @param data
+ */
+export const addOrderMain = (data: OrderMainForm) => {
+  return request({
+    url: '/order/orderMain',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改订单主信息
+ * @param data
+ */
+export const updateOrderMain = (data: OrderMainForm) => {
+  return request({
+    url: '/order/orderMain',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除订单主信息
+ * @param id
+ */
+export const delOrderMain = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/order/orderMain/' + id,
+    method: 'delete'
+  });
+};
+
+/**
+ * 查询数量
+ * @param query
+ * @returns {*}
+ */
+
+export const queryOrderStatusStats = () => {
+  return request({
+    url: '/order/orderMain/queryOrderStatusStats',
+    method: 'get'
+  });
+};
+
+export function changeCheckStatus(id: string | number, checkStatus: string) {
+  const data = {
+    id,
+    checkStatus
+  };
+  return request({
+    url: '/order/orderMain/checkStatus',
+    method: 'put',
+    data: data
+  });
+}

+ 752 - 0
src/api/order/orderMain/types.ts

@@ -0,0 +1,752 @@
+export interface OrderMainVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 订单编号
+   */
+  orderNo: string;
+
+  /**
+   * 发货单号
+   */
+  shipmentNo: string;
+
+  /**
+   * 子订单编号
+   */
+  subOrderNo: string;
+
+  /**
+   * 所属公司
+   */
+  companyId: string | number;
+
+  /**
+   * 客户ID(关联客户主表)
+   */
+  customerId: string | number;
+
+  /**
+   * 客户编号
+   */
+  customerCode: string;
+
+  /**
+   * 用户ID(关联用户表)
+   */
+  userId: string | number;
+
+  /**
+   * 收货地址ID
+   */
+  shippingAddressId: string | number;
+
+  /**
+   * 采购事由
+   */
+  purchaseReason: string;
+
+  /**
+   * 发票类型
+   */
+  invoiceType: string;
+
+  /**
+   * 支付方式
+   */
+  payType: string;
+
+  /**
+   * 发货仓库
+   */
+  warehouseId: string | number;
+
+  /**
+   * 信用额度(元)
+   */
+  creditLimit: number;
+
+  /**
+   * 预计送达时间
+   */
+  expectedDeliveryTime: string;
+
+  /**
+   * 业务员姓名/工号
+   */
+  businessStaff: string;
+
+  /**
+   * 客服人员
+   */
+  customerService: string;
+
+  /**
+   * 业务部门
+   */
+  businessDept: string;
+
+  /**
+   * 用户所属部门
+   */
+  userDept: string;
+
+  /**
+   * 商品总数量
+   */
+  productQuantity: number;
+
+  /**
+   * 运费(元)
+   */
+  shippingFee: number;
+
+  /**
+   * 订单总金额(元)
+   */
+  totalAmount: number;
+
+  /**
+   * 应付金额(元)
+   */
+  payableAmount: number;
+
+  /**
+   * 支付状态
+   */
+  paymentStatus: string;
+
+  /**
+   * 订单来源
+   */
+  orderSource: string;
+
+  /**
+   * 订单状态
+   */
+  orderStatus: string;
+
+  /**
+   * 下单时间
+   */
+  orderTime: string;
+
+  /**
+   * 确认时间
+   */
+  confirmTime: string;
+
+  /**
+   * 发货时间
+   */
+  shippingTime: string;
+
+  /**
+   * 收货时间
+   */
+  receivingTime: string;
+
+  /**
+   * 已发货数量
+   */
+  shippedQuantity: number;
+
+  /**
+   * 未发货数量
+   */
+  unshippedQuantity: number;
+
+  /**
+   * 包裹数量
+   */
+  packageCount: number;
+
+  /**
+   * 签收数量
+   */
+  signedQuantity: number;
+
+  /**
+   * 已完成售后数量
+   */
+  afterSaleCompleted: number;
+
+  /**
+   * 申请售后数量
+   */
+  afterSalePending: number;
+
+  /**
+   * 配送时效描述
+   */
+  deliveryDesc: string;
+
+  /**
+   * 推送状态
+   */
+  pushStatus: string;
+
+  /**
+   * 订单附件文件路径
+   */
+  attachmentPath: string;
+
+  /**
+   * 配送类型
+   */
+  deliveryType: string;
+
+  /**
+   * 创建类别
+   */
+  orderCategory: string;
+
+  /**
+   * 商品编码
+   */
+  productCode: string;
+
+  /**
+   * 取消或异常原因
+   */
+  cancelReason: string;
+
+  /**
+   * 费用类型
+   */
+  expenseType: string;
+
+  /**
+   * 用户编号
+   */
+  userNo: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status: string;
+
+  platformCode: string;
+
+  dataSource: string;
+
+  isSplitChild: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+
+  checkStatus: string;
+
+  assignmentStatus: string;
+
+  orderProductList: any[];
+
+  deliverProductList: any[];
+}
+
+export interface OrderMainForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 订单编号
+   */
+  orderNo?: string;
+
+  /**
+   * 发货单号
+   */
+  shipmentNo?: string;
+
+  /**
+   * 子订单编号
+   */
+  subOrderNo?: string;
+
+  /**
+   * 所属公司
+   */
+  companyId?: string | number;
+
+  /**
+   * 客户ID(关联客户主表)
+   */
+  customerId?: string | number;
+
+  /**
+   * 客户编号
+   */
+  customerCode: string;
+
+  /**
+   * 用户ID(关联用户表)
+   */
+  userId?: string | number;
+
+  /**
+   * 收货地址ID
+   */
+  shippingAddressId?: string | number;
+
+  /**
+   * 采购事由
+   */
+  purchaseReason?: string;
+
+  /**
+   * 发票类型
+   */
+  invoiceType?: string;
+
+  /**
+   * 支付方式
+   */
+  payType?: string;
+
+  /**
+   * 发货仓库
+   */
+  warehouseId?: string | number;
+
+  /**
+   * 信用额度(元)
+   */
+  creditLimit?: number;
+
+  /**
+   * 预计送达时间
+   */
+  expectedDeliveryTime?: string;
+
+  /**
+   * 业务员姓名/工号
+   */
+  businessStaff?: string;
+
+  /**
+   * 客服人员
+   */
+  customerService?: string;
+
+  /**
+   * 业务部门
+   */
+  businessDept?: string;
+
+  /**
+   * 用户所属部门
+   */
+  userDept?: string;
+
+  /**
+   * 商品总数量
+   */
+  productQuantity?: number;
+
+  /**
+   * 运费(元)
+   */
+  shippingFee?: number;
+
+  /**
+   * 订单总金额(元)
+   */
+  totalAmount?: number;
+
+  /**
+   * 应付金额(元)
+   */
+  payableAmount?: number;
+
+  /**
+   * 支付状态
+   */
+  paymentStatus?: string;
+
+  /**
+   * 订单来源
+   */
+  orderSource?: string;
+
+  /**
+   * 订单状态
+   */
+  orderStatus?: string;
+
+  /**
+   * 下单时间
+   */
+  orderTime?: string;
+
+  /**
+   * 确认时间
+   */
+  confirmTime?: string;
+
+  /**
+   * 发货时间
+   */
+  shippingTime?: string;
+
+  /**
+   * 收货时间
+   */
+  receivingTime?: string;
+
+  /**
+   * 已发货数量
+   */
+  shippedQuantity?: number;
+
+  /**
+   * 未发货数量
+   */
+  unshippedQuantity?: number;
+
+  /**
+   * 包裹数量
+   */
+  packageCount?: number;
+
+  /**
+   * 签收数量
+   */
+  signedQuantity?: number;
+
+  /**
+   * 已完成售后数量
+   */
+  afterSaleCompleted?: number;
+
+  /**
+   * 申请售后数量
+   */
+  afterSalePending?: number;
+
+  /**
+   * 配送时效描述
+   */
+  deliveryDesc?: string;
+
+  /**
+   * 推送状态
+   */
+  pushStatus?: string;
+
+  /**
+   * 订单附件文件路径
+   */
+  attachmentPath?: string;
+
+  /**
+   * 配送类型
+   */
+  deliveryType?: string;
+
+  /**
+   * 创建类别
+   */
+  orderCategory?: string;
+
+  /**
+   * 商品编码
+   */
+  productCode?: string;
+
+  /**
+   * 取消或异常原因
+   */
+  cancelReason?: string;
+
+  /**
+   * 费用类型
+   */
+  expenseType?: string;
+
+  /**
+   * 用户编号
+   */
+  userNo?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  isSplitChild: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+
+  dataSource?: string;
+
+  checkStatus?: string;
+
+  assignmentStatus?: string;
+
+  /**
+   * 订单商品明细列表
+   */
+  orderProductBos?: any[];
+
+  customerSalesInfoVo: any;
+}
+
+export interface OrderMainQuery extends PageQuery {
+  /**
+   * 订单编号
+   */
+  orderNo?: string;
+
+  /**
+   * 发货单号
+   */
+  shipmentNo?: string;
+
+  /**
+   * 子订单编号
+   */
+  subOrderNo?: string;
+
+  /**
+   * 所属公司
+   */
+  companyId?: string | number;
+
+  /**
+   * 客户ID(关联客户主表)
+   */
+  customerId?: string | number;
+
+  /**
+   * 用户ID(关联用户表)
+   */
+  userId?: string | number;
+
+  /**
+   * 收货地址ID
+   */
+  shippingAddressId?: string | number;
+
+  /**
+   * 采购事由
+   */
+  purchaseReason?: string;
+
+  /**
+   * 发票类型
+   */
+  invoiceType?: string;
+
+  /**
+   * 支付方式
+   */
+  payType?: string;
+
+  /**
+   * 发货仓库
+   */
+  warehouseId?: string | number;
+
+  /**
+   * 信用额度(元)
+   */
+  creditLimit?: number;
+
+  /**
+   * 预计送达时间
+   */
+  expectedDeliveryTime?: string;
+
+  /**
+   * 业务员姓名/工号
+   */
+  businessStaff?: string;
+
+  /**
+   * 客服人员
+   */
+  customerService?: string;
+
+  /**
+   * 业务部门
+   */
+  businessDept?: string;
+
+  /**
+   * 用户所属部门
+   */
+  userDept?: string;
+
+  /**
+   * 商品总数量
+   */
+  productQuantity?: number;
+
+  /**
+   * 运费(元)
+   */
+  shippingFee?: number;
+
+  /**
+   * 订单总金额(元)
+   */
+  totalAmount?: number;
+
+  /**
+   * 应付金额(元)
+   */
+  payableAmount?: number;
+
+  /**
+   * 支付状态
+   */
+  paymentStatus?: string;
+
+  /**
+   * 订单来源
+   */
+  orderSource?: string;
+
+  customerName?: string;
+
+  /**
+   * 订单状态
+   */
+  orderStatus?: string;
+
+  orderStatuses?: string;
+
+  /**
+   * 下单时间
+   */
+  orderTime?: string;
+
+  /**
+   * 确认时间
+   */
+  confirmTime?: string;
+
+  /**
+   * 发货时间
+   */
+  shippingTime?: string;
+
+  /**
+   * 收货时间
+   */
+  receivingTime?: string;
+
+  /**
+   * 已发货数量
+   */
+  shippedQuantity?: number;
+
+  /**
+   * 未发货数量
+   */
+  unshippedQuantity?: number;
+
+  /**
+   * 包裹数量
+   */
+  packageCount?: number;
+
+  /**
+   * 签收数量
+   */
+  signedQuantity?: number;
+
+  /**
+   * 已完成售后数量
+   */
+  afterSaleCompleted?: number;
+
+  /**
+   * 申请售后数量
+   */
+  afterSalePending?: number;
+
+  /**
+   * 配送时效描述
+   */
+  deliveryDesc?: string;
+
+  /**
+   * 推送状态
+   */
+  pushStatus?: string;
+
+  /**
+   * 订单附件文件路径
+   */
+  attachmentPath?: string;
+
+  /**
+   * 配送类型
+   */
+  deliveryType?: string;
+
+  /**
+   * 创建类别
+   */
+  orderCategory?: string;
+
+  /**
+   * 商品编码
+   */
+  productCode?: string;
+
+  /**
+   * 取消或异常原因
+   */
+  cancelReason?: string;
+
+  /**
+   * 费用类型
+   */
+  expenseType?: string;
+
+  /**
+   * 客户编号
+   */
+
+  customerCode?: string;
+
+  /**
+   * 用户编号
+   */
+  userNo?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  dataSource?: string;
+
+  isSplitChild?: string;
+
+  checkStatus?: string;
+
+  assignmentStatus?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 63 - 0
src/api/order/orderProduct/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { OrderProductVO, OrderProductForm, OrderProductQuery } from '@/api/order/orderProduct/types';
+
+/**
+ * 查询订单商品明细列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listOrderProduct = (query?: OrderProductQuery): AxiosPromise<OrderProductVO[]> => {
+  return request({
+    url: '/order/orderProduct/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询订单商品明细详细
+ * @param id
+ */
+export const getOrderProduct = (id: string | number): AxiosPromise<OrderProductVO> => {
+  return request({
+    url: '/order/orderProduct/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增订单商品明细
+ * @param data
+ */
+export const addOrderProduct = (data: OrderProductForm) => {
+  return request({
+    url: '/order/orderProduct',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改订单商品明细
+ * @param data
+ */
+export const updateOrderProduct = (data: OrderProductForm) => {
+  return request({
+    url: '/order/orderProduct',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除订单商品明细
+ * @param id
+ */
+export const delOrderProduct = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/order/orderProduct/' + id,
+    method: 'delete'
+  });
+};

+ 425 - 0
src/api/order/orderProduct/types.ts

@@ -0,0 +1,425 @@
+export interface OrderProductVO {
+  /**
+   * 订单商品明细ID
+   */
+  id: string | number;
+
+  /**
+   * 订单ID
+   */
+  orderId: string | number;
+
+  /**
+   * 订单编号
+   */
+  orderNo: string;
+
+  /**
+   * 发货单编号
+   */
+  shipmentNo: string;
+
+  /**
+   * 产品ID
+   */
+  productId: string | number;
+
+  /**
+   * 产品编号(业务编码)
+   */
+  productNo: string;
+
+  /**
+   * 产品名称
+   */
+  productName: string;
+
+  /**
+   * 产品单位
+   */
+  productUnit: string;
+
+  /**
+   * 产品图片URL
+   */
+  productImage: string;
+
+  /**
+   * 产品图片URLUrl
+   */
+  productImageUrl: string;
+  /**
+   * 平台价格(元)
+   */
+  platformPrice: number;
+
+  /**
+   * 税率
+   */
+  taxRate: number;
+
+  /**
+   * 平台价格价
+   */
+  marketPrice: number;
+
+  /**
+   * 会员价格
+   */
+  memberPrice: number;
+
+  /**
+   * 采购价格
+   */
+  purchasingPrice: number;
+
+  /**
+   * 最高采购价
+   */
+  maxPurchasePrice: number;
+
+  /**
+   * 最小起订量
+   */
+  minOrderQuantity: number;
+
+  /**
+   * 订单单价(元)
+   */
+  orderPrice: number;
+
+  /**
+   * 订购数量
+   */
+  orderQuantity: number;
+
+  /**
+   * 行小计金额(元)
+   */
+  subtotal: number;
+
+  /**
+   * 最低销售价(元)
+   */
+  minSellingPrice: number;
+
+  /**
+   * 已签收数量
+   */
+  signedQuantity: number;
+
+  /**
+   * 已发货数量
+   */
+  quantitySent: number;
+
+  /**
+   * 未发货数量
+   */
+  unsentQuantity: number;
+
+  /**
+   * 是否申请售后
+   */
+  isAfterSale: string;
+
+  /**
+   * 售后申请数量
+   */
+  afterSaleQuantity: number;
+
+  /**
+   * 退款金额(元)
+   */
+  returnAmount: number;
+
+  /**
+   * 预计送达时间
+   */
+  preDeliveryDate: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status: string;
+
+  dataSource: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface OrderProductForm extends BaseEntity {
+  /**
+   * 订单商品明细ID
+   */
+  id?: string | number;
+
+  /**
+   * 订单ID
+   */
+  orderId?: string | number;
+
+  /**
+   * 订单编号
+   */
+  orderNo?: string;
+
+  /**
+   * 发货单编号
+   */
+  shipmentNo?: string;
+
+  /**
+   * 产品ID
+   */
+  productId?: string | number;
+
+  /**
+   * 产品编号(业务编码)
+   */
+  productNo?: string;
+
+  /**
+   * 产品名称
+   */
+  productName?: string;
+
+  /**
+   * 产品单位
+   */
+  productUnit?: string;
+
+  /**
+   * 产品图片URL
+   */
+  productImage?: string;
+
+  /**
+   * 平台价格(元)
+   */
+  platformPrice?: number;
+
+  /**
+   * 税率
+   */
+  taxRate?: number;
+
+  /**
+   * 平台价格价
+   */
+  marketPrice?: number;
+
+  /**
+   * 会员价格
+   */
+  memberPrice?: number;
+
+  /**
+   * 采购价格
+   */
+  purchasingPrice?: number;
+
+  /**
+   * 最高采购价
+   */
+  maxPurchasePrice?: number;
+
+  /**
+   * 最小起订量
+   */
+  minOrderQuantity?: number;
+
+  /**
+   * 订单单价(元)
+   */
+  orderPrice?: number;
+
+  /**
+   * 订购数量
+   */
+  orderQuantity?: number;
+
+  /**
+   * 行小计金额(元)
+   */
+  subtotal?: number;
+
+  /**
+   * 最低销售价(元)
+   */
+  minSellingPrice?: number;
+
+  /**
+   * 已签收数量
+   */
+  signedQuantity?: number;
+
+  /**
+   * 已发货数量
+   */
+  quantitySent?: number;
+
+  /**
+   * 未发货数量
+   */
+  unsentQuantity?: number;
+
+  /**
+   * 是否申请售后
+   */
+  isAfterSale?: string;
+
+  /**
+   * 售后申请数量
+   */
+  afterSaleQuantity?: number;
+
+  /**
+   * 退款金额(元)
+   */
+  returnAmount?: number;
+
+  /**
+   * 预计送达时间
+   */
+  preDeliveryDate?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  dataSource?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface OrderProductQuery extends PageQuery {
+  /**
+   * 订单ID
+   */
+  orderId?: string | number;
+
+  /**
+   * 订单编号
+   */
+  orderNo?: string;
+
+  /**
+   * 发货单编号
+   */
+  shipmentNo?: string;
+
+  /**
+   * 产品ID
+   */
+  productId?: string | number;
+
+  /**
+   * 产品编号(业务编码)
+   */
+  productNo?: string;
+
+  /**
+   * 产品名称
+   */
+  productName?: string;
+
+  /**
+   * 产品单位
+   */
+  productUnit?: string;
+
+  /**
+   * 产品图片URL
+   */
+  productImage?: string;
+
+  /**
+   * 平台价格(元)
+   */
+  platformPrice?: number;
+
+  /**
+   * 最小起订量
+   */
+  minOrderQuantity?: number;
+
+  /**
+   * 订单单价(元)
+   */
+  orderPrice?: number;
+
+  /**
+   * 订购数量
+   */
+  orderQuantity?: number;
+
+  /**
+   * 行小计金额(元)
+   */
+  subtotal?: number;
+
+  /**
+   * 最低销售价(元)
+   */
+  minSellingPrice?: number;
+
+  /**
+   * 已签收数量
+   */
+  signedQuantity?: number;
+
+  /**
+   * 已发货数量
+   */
+  quantitySent?: number;
+
+  /**
+   * 未发货数量
+   */
+  unsentQuantity?: number;
+
+  /**
+   * 是否申请售后
+   */
+  isAfterSale?: string;
+
+  /**
+   * 售后申请数量
+   */
+  afterSaleQuantity?: number;
+
+  /**
+   * 退款金额(元)
+   */
+  returnAmount?: number;
+
+  /**
+   * 预计送达时间
+   */
+  preDeliveryDate?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  dataSource?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 63 - 0
src/api/order/orderReturn/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { OrderReturnVO, OrderReturnForm, OrderReturnQuery } from '@/api/order/orderReturn/types';
+
+/**
+ * 查询退货主列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listOrderReturn = (query?: OrderReturnQuery): AxiosPromise<OrderReturnVO[]> => {
+  return request({
+    url: '/order/orderReturn/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询退货主详细
+ * @param id
+ */
+export const getOrderReturn = (id: string | number): AxiosPromise<OrderReturnVO> => {
+  return request({
+    url: '/order/orderReturn/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增退货主
+ * @param data
+ */
+export const addOrderReturn = (data: OrderReturnForm) => {
+  return request({
+    url: '/order/orderReturn',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改退货主
+ * @param data
+ */
+export const updateOrderReturn = (data: OrderReturnForm) => {
+  return request({
+    url: '/order/orderReturn',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除退货主
+ * @param id
+ */
+export const delOrderReturn = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/order/orderReturn/' + id,
+    method: 'delete'
+  });
+};

+ 566 - 0
src/api/order/orderReturn/types.ts

@@ -0,0 +1,566 @@
+export interface OrderReturnVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 原订单id
+   */
+  orderId: string | number;
+
+  /**
+   * 原订单编号
+   */
+  orderNo: string;
+
+  /**
+   * 售后服务类型(如:退货、换货、仅退款等)
+   */
+  serviceType: string;
+
+  /**
+   * 退货申请时间
+   */
+  returnTime: string;
+
+  /**
+   * 退货单号
+   */
+  returnNo: string;
+
+  /**
+   * 客户编号
+   */
+  customerId: string | number;
+
+  /**
+   * 客户编号
+   */
+  customerNo: string;
+
+  /**
+   * 客户姓名
+   */
+  customerName: string;
+
+  /**
+   * 售后金额
+   */
+  afterSaleAmount: number;
+
+  /**
+   * 退货订单状态
+   */
+  returnStatus: string;
+
+  /**
+   * 退货商品总数量
+   */
+  returnProductNum: number;
+
+  /**
+   * 处理完成时间
+   */
+  processingTime: string;
+
+  /**
+   * 退货原因id
+   */
+  returnReasonId: string | number;
+
+  /**
+   * 退货原因
+   */
+  returnReason: string;
+
+  /**
+   * 问题描述
+   */
+  problemDescription: string;
+
+  /**
+   * 凭证图片URL
+   */
+  voucherPhoto: string;
+
+  /**
+   * 运费金额
+   */
+  shippingFee: number;
+
+  /**
+   * 是否承担运费
+   */
+  isShippingFee: string;
+
+  /**
+   * 原订单总金额
+   */
+  orderAmount: number;
+
+  /**
+   * 实际退款金额
+   */
+  returnAmount: number;
+
+  /**
+   * 售后备注
+   */
+  afterSalesRemarks: string;
+
+  /**
+   * 退货方式(如:上门取件、自行寄回)
+   */
+  returnMethod: string;
+
+  /**
+   * 取件人姓名
+   */
+  chargebackName: string;
+
+  /**
+   * 取件联系电话
+   */
+  chargebackPhone: string;
+
+  /**
+   * 预约取件时间
+   */
+  chargebackPickupTime: string;
+
+  /**
+   * 取件省
+   */
+  chargebackProvincial: string;
+
+  /**
+   * 取件市
+   */
+  chargebackCity: string;
+
+  /**
+   * 取件区/县
+   */
+  chargebackCounty: string;
+
+  /**
+   * 取件区/县
+   */
+  provincialCityCounty: string;
+
+  /**
+   * 取件详细地址
+   */
+  chargebackAddress: string;
+
+  /**
+   * 推送状态(如:0-未推送, 1-已推送)
+   */
+  pushStatus: string;
+
+  /**
+   * 物流公司id
+   */
+  logisticsId: string | number;
+
+  /**
+   * 物流公司名称
+   */
+  logisticsName: string;
+
+  /**
+   * 物流单号
+   */
+  logisticsNo: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status: string;
+
+  createTime: string;
+
+  orderReturnItemList: any[];
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface OrderReturnForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 原订单id
+   */
+  orderId?: string | number;
+
+  /**
+   * 原订单编号
+   */
+  orderNo?: string;
+
+  /**
+   * 售后服务类型(如:退货、换货、仅退款等)
+   */
+  serviceType?: string;
+
+  /**
+   * 退货申请时间
+   */
+  returnTime?: string;
+
+  /**
+   * 退货单号
+   */
+  returnNo?: string;
+
+  /**
+   * 客户编号
+   */
+  customerId?: string | number;
+
+  /**
+   * 客户编号
+   */
+  customerNo?: string;
+
+  /**
+   * 客户姓名
+   */
+  customerName?: string;
+
+  /**
+   * 售后金额
+   */
+  afterSaleAmount?: number;
+
+  /**
+   * 退货订单状态
+   */
+  returnStatus?: string;
+
+  /**
+   * 退货商品总数量
+   */
+  returnProductNum?: number;
+
+  /**
+   * 处理完成时间
+   */
+  processingTime?: string;
+
+  /**
+   * 退货原因id
+   */
+  returnReasonId?: string | number;
+
+  /**
+   * 退货原因
+   */
+  returnReason?: string;
+
+  /**
+   * 问题描述
+   */
+  problemDescription?: string;
+
+  /**
+   * 凭证图片URL
+   */
+  voucherPhoto?: string;
+
+  /**
+   * 运费金额
+   */
+  shippingFee?: number;
+
+  /**
+   * 是否承担运费
+   */
+  isShippingFee?: string;
+
+  /**
+   * 原订单总金额
+   */
+  orderAmount?: number;
+
+  /**
+   * 实际退款金额
+   */
+  returnAmount?: number;
+
+  /**
+   * 售后备注
+   */
+  afterSalesRemarks?: string;
+
+  /**
+   * 退货方式(如:上门取件、自行寄回)
+   */
+  returnMethod?: string;
+
+  /**
+   * 取件人姓名
+   */
+  chargebackName?: string;
+
+  /**
+   * 取件联系电话
+   */
+  chargebackPhone?: string;
+
+  /**
+   * 预约取件时间
+   */
+  chargebackPickupTime?: string;
+
+  /**
+   * 取件省
+   */
+  chargebackProvincial?: string;
+
+  /**
+   * 取件市
+   */
+  chargebackCity?: string;
+
+  /**
+   * 取件区/县
+   */
+  chargebackCounty?: string;
+
+  /**
+   * 取件区/县
+   */
+  provincialCityCounty?: string;
+
+  /**
+   * 取件详细地址
+   */
+  chargebackAddress?: string;
+
+  /**
+   * 推送状态(如:0-未推送, 1-已推送)
+   */
+  pushStatus?: string;
+
+  /**
+   * 物流公司id
+   */
+  logisticsId?: string | number;
+
+  /**
+   * 物流公司名称
+   */
+  logisticsName?: string;
+
+  /**
+   * 物流单号
+   */
+  logisticsNo?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+
+  orderReturnItemList?: any[];
+}
+
+export interface OrderReturnQuery extends PageQuery {
+  /**
+   * 原订单id
+   */
+  orderId?: string | number;
+
+  /**
+   * 原订单编号
+   */
+  orderNo?: string;
+
+  /**
+   * 售后服务类型(如:退货、换货、仅退款等)
+   */
+  serviceType?: string;
+
+  /**
+   * 退货申请时间
+   */
+  returnTime?: string;
+
+  /**
+   * 退货单号
+   */
+  returnNo?: string;
+
+  /**
+   * 客户编号
+   */
+  customerId?: string | number;
+
+  /**
+   * 客户编号
+   */
+  customerNo?: string;
+
+  /**
+   * 客户姓名
+   */
+  customerName?: string;
+
+  /**
+   * 售后金额
+   */
+  afterSaleAmount?: number;
+
+  /**
+   * 退货订单状态
+   */
+  returnStatus?: string;
+
+  /**
+   * 退货商品总数量
+   */
+  returnProductNum?: number;
+
+  /**
+   * 处理完成时间
+   */
+  processingTime?: string;
+
+  /**
+   * 退货原因id
+   */
+  returnReasonId?: string | number;
+
+  /**
+   * 退货原因
+   */
+  returnReason?: string;
+
+  /**
+   * 问题描述
+   */
+  problemDescription?: string;
+
+  /**
+   * 凭证图片URL
+   */
+  voucherPhoto?: string;
+
+  /**
+   * 运费金额
+   */
+  shippingFee?: number;
+
+  /**
+   * 是否承担运费
+   */
+  isShippingFee?: string;
+
+  /**
+   * 原订单总金额
+   */
+  orderAmount?: number;
+
+  /**
+   * 实际退款金额
+   */
+  returnAmount?: number;
+
+  /**
+   * 售后备注
+   */
+  afterSalesRemarks?: string;
+
+  /**
+   * 退货方式(如:上门取件、自行寄回)
+   */
+  returnMethod?: string;
+
+  /**
+   * 取件人姓名
+   */
+  chargebackName?: string;
+
+  /**
+   * 取件联系电话
+   */
+  chargebackPhone?: string;
+
+  /**
+   * 预约取件时间
+   */
+  chargebackPickupTime?: string;
+
+  /**
+   * 取件省
+   */
+  chargebackProvincial?: string;
+
+  /**
+   * 取件市
+   */
+  chargebackCity?: string;
+
+  /**
+   * 取件区/县
+   */
+  chargebackCounty?: string;
+
+  /**
+   * 取件区/县
+   */
+  provincialCityCounty?: string;
+
+  /**
+   * 取件详细地址
+   */
+  chargebackAddress?: string;
+
+  /**
+   * 推送状态(如:0-未推送, 1-已推送)
+   */
+  pushStatus?: string;
+
+  /**
+   * 物流公司id
+   */
+  logisticsId?: string | number;
+
+  /**
+   * 物流公司名称
+   */
+  logisticsName?: string;
+
+  /**
+   * 物流单号
+   */
+  logisticsNo?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 63 - 0
src/api/order/orderReturnItem/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { OrderReturnItemVO, OrderReturnItemForm, OrderReturnItemQuery } from '@/api/order/orderReturnItem/types';
+
+/**
+ * 查询退货商品明细列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listOrderReturnItem = (query?: OrderReturnItemQuery): AxiosPromise<OrderReturnItemVO[]> => {
+  return request({
+    url: '/order/orderReturnItem/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询退货商品明细详细
+ * @param id
+ */
+export const getOrderReturnItem = (id: string | number): AxiosPromise<OrderReturnItemVO> => {
+  return request({
+    url: '/order/orderReturnItem/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增退货商品明细
+ * @param data
+ */
+export const addOrderReturnItem = (data: OrderReturnItemForm) => {
+  return request({
+    url: '/order/orderReturnItem',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改退货商品明细
+ * @param data
+ */
+export const updateOrderReturnItem = (data: OrderReturnItemForm) => {
+  return request({
+    url: '/order/orderReturnItem',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除退货商品明细
+ * @param id
+ */
+export const delOrderReturnItem = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/order/orderReturnItem/' + id,
+    method: 'delete'
+  });
+};

+ 170 - 0
src/api/order/orderReturnItem/types.ts

@@ -0,0 +1,170 @@
+export interface OrderReturnItemVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 关联的退货单ID
+   */
+  returnId: string | number;
+
+  /**
+   * 原订单明细ID
+   */
+  orderProductId: string | number;
+
+  /**
+   * 商品SKU编码
+   */
+  productSku: string;
+
+  /**
+   * 商品名称
+   */
+  productName: string;
+
+  /**
+   * 本次退货数量
+   */
+  returnQuantity: number;
+
+  /**
+   * 商品单价
+   */
+  unitPrice: number;
+
+  /**
+   * 该项退货总金额
+   */
+  totalAmount: number;
+
+  /**
+   * 该商品的具体退货原因
+   */
+  reasonDetail: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface OrderReturnItemForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 关联的退货单ID
+   */
+  returnId?: string | number;
+
+  /**
+   * 原订单明细ID
+   */
+  orderProductId?: string | number;
+
+  /**
+   * 商品SKU编码
+   */
+  productSku?: string;
+
+  /**
+   * 商品名称
+   */
+  productName?: string;
+
+  /**
+   * 本次退货数量
+   */
+  returnQuantity?: number;
+
+  /**
+   * 商品单价
+   */
+  unitPrice?: number;
+
+  /**
+   * 该项退货总金额
+   */
+  totalAmount?: number;
+
+  /**
+   * 该商品的具体退货原因
+   */
+  reasonDetail?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface OrderReturnItemQuery extends PageQuery {
+  /**
+   * 关联的退货单ID
+   */
+  returnId?: string | number;
+
+  /**
+   * 原订单明细ID
+   */
+  orderProductId?: string | number;
+
+  /**
+   * 商品SKU编码
+   */
+  productSku?: string;
+
+  /**
+   * 商品名称
+   */
+  productName?: string;
+
+  /**
+   * 本次退货数量
+   */
+  returnQuantity?: number;
+
+  /**
+   * 商品单价
+   */
+  unitPrice?: number;
+
+  /**
+   * 该项退货总金额
+   */
+  totalAmount?: number;
+
+  /**
+   * 该商品的具体退货原因
+   */
+  reasonDetail?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 75 - 0
src/api/order/returnReason/index.ts

@@ -0,0 +1,75 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { ReturnReasonVO, ReturnReasonForm, ReturnReasonQuery } from '@/api/order/returnReason/types';
+
+/**
+ * 查询退货原因列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listReturnReason = (query?: ReturnReasonQuery): AxiosPromise<ReturnReasonVO[]> => {
+  return request({
+    url: '/system/returnReason/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询退货原因详细
+ * @param id
+ */
+export const getReturnReason = (id: string | number): AxiosPromise<ReturnReasonVO> => {
+  return request({
+    url: '/system/returnReason/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增退货原因
+ * @param data
+ */
+export const addReturnReason = (data: ReturnReasonForm) => {
+  return request({
+    url: '/system/returnReason',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改退货原因
+ * @param data
+ */
+export const updateReturnReason = (data: ReturnReasonForm) => {
+  return request({
+    url: '/system/returnReason',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除退货原因
+ * @param id
+ */
+export const delReturnReason = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/system/returnReason/' + id,
+    method: 'delete'
+  });
+};
+
+export function changeStatus(id: string | number, isShow: string) {
+  const data = {
+    id,
+    isShow
+  };
+  return request({
+    url: '/system/returnReason/changeStatus',
+    method: 'put',
+    data: data
+  });
+}

+ 110 - 0
src/api/order/returnReason/types.ts

@@ -0,0 +1,110 @@
+export interface ReturnReasonVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 退货原因编号
+   */
+  returnReasonCode: string;
+
+  /**
+   * 退货原因
+   */
+  returnReasonName: string;
+
+  /**
+   * 是否显示
+   */
+  isShow: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface ReturnReasonForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 退货原因编号
+   */
+  returnReasonCode?: string;
+
+  /**
+   * 退货原因
+   */
+  returnReasonName?: string;
+
+  /**
+   * 是否显示
+   */
+  isShow?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface ReturnReasonQuery extends PageQuery {
+  /**
+   * 退货原因编号
+   */
+  returnReasonCode?: string;
+
+  /**
+   * 退货原因
+   */
+  returnReasonName?: string;
+
+  /**
+   * 是否显示
+   */
+  isShow?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 63 - 0
src/api/order/revenueDetail/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { RevenueDetailVO, RevenueDetailForm, RevenueDetailQuery } from '@/api/order/revenueDetail/types';
+
+/**
+ * 查询收入单明细列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listRevenueDetail = (query?: RevenueDetailQuery): AxiosPromise<RevenueDetailVO[]> => {
+  return request({
+    url: '/order/revenueDetail/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询收入单明细详细
+ * @param id
+ */
+export const getRevenueDetail = (id: string | number): AxiosPromise<RevenueDetailVO> => {
+  return request({
+    url: '/order/revenueDetail/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增收入单明细
+ * @param data
+ */
+export const addRevenueDetail = (data: RevenueDetailForm) => {
+  return request({
+    url: '/order/revenueDetail',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改收入单明细
+ * @param data
+ */
+export const updateRevenueDetail = (data: RevenueDetailForm) => {
+  return request({
+    url: '/order/revenueDetail',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除收入单明细
+ * @param id
+ */
+export const delRevenueDetail = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/order/revenueDetail/' + id,
+    method: 'delete'
+  });
+};

+ 215 - 0
src/api/order/revenueDetail/types.ts

@@ -0,0 +1,215 @@
+export interface RevenueDetailVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 关联的收入单id
+   */
+  orderRevenueId: string | number;
+
+  /**
+   * 收入类型ID
+   */
+  revenueId: string | number;
+
+  /**
+   * 收入明细编号
+   */
+  revenueCode: string;
+
+  /**
+   * 税率编码
+   */
+  taxRateCode: string;
+
+  /**
+   * 总金额
+   */
+  totalAmount: number;
+
+  /**
+   * 单价
+   */
+  unitPrice: number;
+
+  /**
+   * 数量
+   */
+  quantity: number;
+
+  /**
+   * 平台分账金额
+   */
+  platformAmount: number;
+
+  /**
+   * 平台单价
+   */
+  platformPrice: number;
+
+  /**
+   * 订单类型
+   */
+  orderType: string;
+
+  /**
+   * 明细附件文件路径
+   */
+  revFile: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface RevenueDetailForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 关联的收入单id
+   */
+  orderRevenueId?: string | number;
+
+  /**
+   * 收入类型ID
+   */
+  revenueId?: string | number;
+
+  /**
+   * 收入明细编号
+   */
+  revenueCode?: string;
+
+  /**
+   * 税率编码
+   */
+  taxRateCode?: string;
+
+  /**
+   * 总金额
+   */
+  totalAmount?: number;
+
+  /**
+   * 单价
+   */
+  unitPrice?: number;
+
+  /**
+   * 数量
+   */
+  quantity?: number;
+
+  /**
+   * 平台分账金额
+   */
+  platformAmount?: number;
+
+  /**
+   * 平台单价
+   */
+  platformPrice?: number;
+
+  /**
+   * 订单类型
+   */
+  orderType?: string;
+
+  /**
+   * 明细附件文件路径
+   */
+  revFile?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface RevenueDetailQuery extends PageQuery {
+  /**
+   * 关联的收入单id
+   */
+  orderRevenueId?: string | number;
+
+  /**
+   * 收入类型ID
+   */
+  revenueId?: string | number;
+
+  /**
+   * 收入明细编号
+   */
+  revenueCode?: string;
+
+  /**
+   * 税率编码
+   */
+  taxRateCode?: string;
+
+  /**
+   * 总金额
+   */
+  totalAmount?: number;
+
+  /**
+   * 单价
+   */
+  unitPrice?: number;
+
+  /**
+   * 数量
+   */
+  quantity?: number;
+
+  /**
+   * 平台分账金额
+   */
+  platformAmount?: number;
+
+  /**
+   * 平台单价
+   */
+  platformPrice?: number;
+
+  /**
+   * 订单类型
+   */
+  orderType?: string;
+
+  /**
+   * 明细附件文件路径
+   */
+  revFile?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 75 - 0
src/api/order/revenueHeader/index.ts

@@ -0,0 +1,75 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { RevenueHeaderVO, RevenueHeaderForm, RevenueHeaderQuery } from '@/api/order/revenueHeader/types';
+
+/**
+ * 查询收入单主列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listRevenueHeader = (query?: RevenueHeaderQuery): AxiosPromise<RevenueHeaderVO[]> => {
+  return request({
+    url: '/order/revenueHeader/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询收入单主详细
+ * @param id
+ */
+export const getRevenueHeader = (id: string | number): AxiosPromise<RevenueHeaderVO> => {
+  return request({
+    url: '/order/revenueHeader/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增收入单主
+ * @param data
+ */
+export const addRevenueHeader = (data: RevenueHeaderForm) => {
+  return request({
+    url: '/order/revenueHeader',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改收入单主
+ * @param data
+ */
+export const updateRevenueHeader = (data: RevenueHeaderForm) => {
+  return request({
+    url: '/order/revenueHeader',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除收入单主
+ * @param id
+ */
+export const delRevenueHeader = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/order/revenueHeader/' + id,
+    method: 'delete'
+  });
+};
+
+export function changeStatus(id: string | number, status: string) {
+  const data = {
+    id,
+    status
+  };
+  return request({
+    url: '/order/revenueHeader/changeStatus',
+    method: 'put',
+    data: data
+  });
+}

+ 247 - 0
src/api/order/revenueHeader/types.ts

@@ -0,0 +1,247 @@
+export interface RevenueHeaderVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 收入大类
+   */
+  revenueType: string;
+
+  /**
+   * 收入单号
+   */
+  orderRevenueCode: string;
+
+  /**
+   * 关联的主订单号
+   */
+  incomeOrderCode: string;
+
+  /**
+   * 其他收入子类型
+   */
+  otherRevenueType: string;
+
+  /**
+   * 客户id
+   */
+  customerId: string | number;
+
+  /**
+   * 客户名称
+   */
+  customerName: string;
+
+  /**
+   * 供应商id
+   */
+  supplierId: string | number;
+
+  /**
+   * 是否含税
+   */
+  isPrwTax: string;
+
+  /**
+   * 币种
+   */
+  currencyId: string | number;
+
+  /**
+   * 推送状态
+   */
+  pushStatus: string;
+
+  /**
+   * 附件文件路径或URL
+   */
+  orderFile: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+
+  orderRevenueDetailList: any[];
+}
+
+export interface RevenueHeaderForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 收入大类
+   */
+  revenueType?: string;
+
+  /**
+   * 收入单号
+   */
+  orderRevenueCode?: string;
+
+  /**
+   * 关联的主订单号
+   */
+  incomeOrderCode?: string;
+
+  /**
+   * 其他收入子类型
+   */
+  otherRevenueType?: string;
+
+  /**
+   * 客户id
+   */
+  customerId?: string | number;
+
+  /**
+   * 客户名称
+   */
+  customerName?: string;
+
+  /**
+   * 供应商id
+   */
+  supplierId?: string | number;
+
+  /**
+   * 是否含税
+   */
+  isPrwTax?: string;
+
+  /**
+   * 币种
+   */
+  currencyId?: string | number;
+
+  /**
+   * 推送状态
+   */
+  pushStatus?: string;
+
+  /**
+   * 附件文件路径或URL
+   */
+  orderFile?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+
+  companyId?: string | number;
+
+  companyName?: string;
+
+  dataSource?: string;
+
+  businessStaff?: string;
+
+  businessDept?: string;
+
+  customerService?: string;
+
+  customerCode?: string;
+
+  supplierName?: string;
+
+  orderRevenueDetails?: any[];
+}
+
+export interface RevenueHeaderQuery extends PageQuery {
+  /**
+   * 收入大类
+   */
+  revenueType?: string;
+
+  /**
+   * 收入单号
+   */
+  orderRevenueCode?: string;
+
+  /**
+   * 关联的主订单号
+   */
+  incomeOrderCode?: string;
+
+  /**
+   * 其他收入子类型
+   */
+  otherRevenueType?: string;
+
+  /**
+   * 客户id
+   */
+  customerId?: string | number;
+
+  /**
+   * 客户名称
+   */
+  customerName?: string;
+
+  /**
+   * 供应商id
+   */
+  supplierId?: string | number;
+
+  /**
+   * 是否含税
+   */
+  isPrwTax?: string;
+
+  /**
+   * 币种
+   */
+  currencyId?: string | number;
+
+  /**
+   * 推送状态
+   */
+  pushStatus?: string;
+
+  /**
+   * 附件文件路径或URL
+   */
+  orderFile?: string;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  searchValue?: string;
+
+  createTime?: string;
+
+  businessStaff?: string;
+
+  businessDept?: string;
+
+  customerService?: string;
+
+  customerCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 63 - 0
src/api/product/afterSales/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { AfterSalesVO, AfterSalesForm, AfterSalesQuery } from '@/api/product/afterSales/types';
+
+/**
+ * 查询产品售后服务项列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listAfterSales = (query?: AfterSalesQuery): AxiosPromise<AfterSalesVO[]> => {
+  return request({
+    url: '/product/afterSales/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询产品售后服务项详细
+ * @param id
+ */
+export const getAfterSales = (id: string | number): AxiosPromise<AfterSalesVO> => {
+  return request({
+    url: '/product/afterSales/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增产品售后服务项
+ * @param data
+ */
+export const addAfterSales = (data: AfterSalesForm) => {
+  return request({
+    url: '/product/afterSales',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改产品售后服务项
+ * @param data
+ */
+export const updateAfterSales = (data: AfterSalesForm) => {
+  return request({
+    url: '/product/afterSales',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除产品售后服务项
+ * @param id
+ */
+export const delAfterSales = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/product/afterSales/' + id,
+    method: 'delete'
+  });
+};

+ 65 - 0
src/api/product/afterSales/types.ts

@@ -0,0 +1,65 @@
+export interface AfterSalesVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 售后服务项目(如:保修、退换货、技术支持等)
+   */
+  afterSalesItems: string;
+
+  /**
+   * 数据来源(如:系统录入、接口同步等)
+   */
+  dataSource: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface AfterSalesForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 售后服务项目(如:保修、退换货、技术支持等)
+   */
+  afterSalesItems?: string;
+
+  /**
+   * 数据来源(如:系统录入、接口同步等)
+   */
+  dataSource?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface AfterSalesQuery extends PageQuery {
+  /**
+   * 售后服务项目(如:保修、退换货、技术支持等)
+   */
+  afterSalesItems?: string;
+
+  /**
+   * 数据来源(如:系统录入、接口同步等)
+   */
+  dataSource?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 63 - 0
src/api/product/attributes/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { AttributesVO, AttributesForm, AttributesQuery } from '@/api/product/attributes/types';
+
+/**
+ * 查询产品属性定义(用于动态属性配置)列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listAttributes = (query?: AttributesQuery): AxiosPromise<AttributesVO[]> => {
+  return request({
+    url: '/product/attributes/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询产品属性定义(用于动态属性配置)详细
+ * @param id
+ */
+export const getAttributes = (id: string | number): AxiosPromise<AttributesVO> => {
+  return request({
+    url: '/product/attributes/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增产品属性定义(用于动态属性配置)
+ * @param data
+ */
+export const addAttributes = (data: AttributesForm) => {
+  return request({
+    url: '/product/attributes',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改产品属性定义(用于动态属性配置)
+ * @param data
+ */
+export const updateAttributes = (data: AttributesForm) => {
+  return request({
+    url: '/product/attributes',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除产品属性定义(用于动态属性配置)
+ * @param id
+ */
+export const delAttributes = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/product/attributes/' + id,
+    method: 'delete'
+  });
+};

+ 160 - 0
src/api/product/attributes/types.ts

@@ -0,0 +1,160 @@
+export interface AttributesVO {
+  /**
+   * 主键,自增ID
+   */
+  id: string | number;
+
+  /**
+   * 关联的产品分类id
+   */
+  categoryId: string | number;
+
+  /**
+   * 产品分类名称
+   */
+  categoryName?: string;
+
+  /**
+   * 属性编码(用于系统识别)
+   */
+  productAttributesCode: string;
+
+  /**
+   * 属性显示名称
+   */
+  productAttributesName: string;
+
+  /**
+   * 是否可选:0=单选属性,1=唯一属性,2=复选属性
+   */
+  isOptional: string;
+
+  /**
+   * 属性录入方式(1=手工录入,2=从列表中选择)
+   */
+  entryMethod: string;
+
+  /**
+   * 是否用于商品筛选:1=是,0=否
+   */
+  isFilter: string;
+
+  /**
+   * 预定义属性值列表(逗号分隔或JSON)
+   */
+  attributesList: string;
+
+  /**
+   * 是否必填: 1=是, 0=否
+   */
+  required: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface AttributesForm extends BaseEntity {
+  /**
+   * 主键,自增ID
+   */
+  id?: string | number;
+
+  /**
+   * 关联的产品分类id
+   */
+  categoryId?: string | number;
+
+  /**
+   * 属性编码(用于系统识别)
+   */
+  productAttributesCode?: string;
+
+  /**
+   * 属性显示名称
+   */
+  productAttributesName?: string;
+
+  /**
+   * 是否可选:0=单选属性,1=唯一属性,2=复选属性
+   */
+  isOptional?: string | number;
+
+  /**
+   * 属性录入方式(manual=手工录入,select=从列表中选择)
+   */
+  entryMethod?: string;
+
+  /**
+   * 是否用于商品筛选:1=是,0=否
+   */
+  isFilter?: string | number;
+
+  /**
+   * 预定义属性值列表(逗号分隔或JSON)
+   */
+  attributesList?: string;
+
+  /**
+   * 是否必填: 1=是, 0=否
+   */
+  required?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface AttributesQuery extends PageQuery {
+  /**
+   * 关联的产品分类id
+   */
+  categoryId?: string | number;
+
+  /**
+   * 属性编码(用于系统识别)
+   */
+  productAttributesCode?: string;
+
+  /**
+   * 属性显示名称
+   */
+  productAttributesName?: string;
+
+  /**
+   * 是否可选:0=单选属性,1=唯一属性,2=复选属性
+   */
+  isOptional?: string;
+
+  /**
+   * 属性录入方式(manual=手工录入,select=从列表中选择)
+   */
+  entryMethod?: string;
+
+  /**
+   * 是否用于商品筛选:1=是,0=否
+   */
+  isFilter?: string;
+
+  /**
+   * 预定义属性值列表(逗号分隔或JSON)
+   */
+  attributesList?: string;
+
+  /**
+   * 是否必填: 1=是, 0=否
+   */
+  required?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 156 - 0
src/api/product/base/index.ts

@@ -0,0 +1,156 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { BaseVO, BaseForm, BaseQuery } from '@/api/product/base/types';
+import { CategoryQuery, categoryTreeVO, CategoryVO } from '../category/types';
+import { BrandQuery, BrandVO } from '../brand/types';
+import { AttributesVO } from '../attributes/types';
+import { EnsureQuery, EnsureVO } from '../ensure/types';
+import { AfterSalesQuery, AfterSalesVO } from '../afterSales/types';
+import { UnitQuery, UnitVO } from '../unit/types';
+
+/**
+ * 查询产品基础信息列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listBase = (query?: BaseQuery): AxiosPromise<BaseVO[]> => {
+  return request({
+    url: '/product/base/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询产品基础信息详细
+ * @param id
+ */
+export const getBase = (id: string | number): AxiosPromise<BaseVO> => {
+  return request({
+    url: '/product/base/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增产品基础信息
+ * @param data
+ */
+export const addBase = (data: BaseForm) => {
+  return request({
+    url: '/product/base',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改产品基础信息
+ * @param data
+ */
+export const updateBase = (data: BaseForm) => {
+  return request({
+    url: '/product/base',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除产品基础信息
+ * @param id
+ */
+export const delBase = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/product/base/' + id,
+    method: 'delete'
+  });
+};
+
+/**
+ * 获取产品分类树
+ * @param query
+ * @returns {*}
+ */
+export const categoryTree = (query?: CategoryQuery): AxiosPromise<categoryTreeVO[]> => {
+  return request({
+    url: '/product/base/categoryTree',
+    method: 'get',
+    params: query
+  });
+};
+/**
+ * 查询产品分类信息列表
+ * @param query
+ * @returns {*}
+ */
+export const categoryList = (query?: CategoryQuery): AxiosPromise<CategoryVO[]> => {
+  return request({
+    url: '/product/base/categoryList',
+    method: 'get',
+    params: query
+  });
+};
+/**
+ * 查询产品品牌信息列表
+ * @param query
+ * @returns {*}
+ */
+export const brandList = (query?: BrandQuery): AxiosPromise<BrandVO[]> => {
+  return request({
+    url: '/product/base/brandList',
+    method: 'get',
+    params: query
+  });
+};
+/**
+ * 查询产品分类下的属性列表
+ * @param id
+ * @returns {*}
+ */
+export const categoryAttributeList = (id: string | number): AxiosPromise<AttributesVO[]> => {
+  return request({
+    url: '/product/base/getProductAttributeList/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 查询产品服务保障列表
+ * @param query
+ * @returns {*}
+ */
+export const getServiceList = (query?: EnsureQuery): AxiosPromise<EnsureVO[]> => {
+  return request({
+    url: '/product/base/getServiceList',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 获取售后服务信息列表
+ * @param query
+ * @returns {*}
+ */
+export const getAfterSaleList = (query?: AfterSalesQuery): AxiosPromise<AfterSalesVO[]> => {
+  return request({
+    url: '/product/base/getAfterSalesList',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 获取单位信息列表
+ * @param query
+ * @returns {*}
+ */
+export const getUnitList = (query?: UnitQuery): AxiosPromise<UnitVO[]> => {
+  return request({
+    url: '/product/base/getUnitList',
+    method: 'get',
+    params: query
+  });
+};

+ 674 - 0
src/api/product/base/types.ts

@@ -0,0 +1,674 @@
+export interface BaseVO {
+  /**
+   * 主键,自增ID
+   */
+  id: string | number;
+
+  /**
+   * 产品编号
+   */
+  productNo: string;
+
+  /**
+   * 项目名称
+   */
+  itemName: string;
+
+  /**
+   * 品牌id
+   */
+  brandId: string | number;
+
+  /**
+   * 顶级分类id
+   */
+  topCategoryId: string | number;
+
+  /**
+   * 中级分类id
+   */
+  mediumCategoryId: string | number;
+
+  /**
+   * 底层分类id
+   */
+  bottomCategoryId: string | number;
+
+  /**
+   * 单位id
+   */
+  unitId: string | number;
+
+  /**
+   * 产品图片URL
+   */
+  productImage: string;
+
+  /**
+   * 产品图片URLUrl
+   */
+  productImageUrl: string;
+  /**
+   * 是否自营(1=是,0=否)
+   */
+  isSelf: string;
+
+  /**
+   * 产品审核状态 0=待提交,1=待审核,2=审核通过,3=审核驳回
+   */
+  productReviewStatus: string;
+
+  /**
+   * 首页推荐:1=推荐,0=不推荐
+   */
+  homeRecommended: string;
+
+  /**
+   * 分类推荐:1=推荐,0=不推荐
+   */
+  categoryRecommendation: string;
+
+  /**
+   * 购物车推荐:1=推荐,0=不推荐
+   */
+  cartRecommendation: string;
+
+  /**
+   * 推荐产品顺序
+   */
+  recommendedProductOrder: number;
+
+  /**
+   * 是否热门:1=是,0=否
+   */
+  isPopular: string;
+
+  /**
+   * 是否新品:1=是,0=否
+   */
+  isNew: string;
+
+  /**
+   * 商品状态:1=上架,0=下架等
+   */
+  productStatus: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource: string;
+
+  /**
+   * 市场价
+   */
+  marketPrice: number;
+
+  /**
+   * 会员价格
+   */
+  memberPrice: number;
+
+  /**
+   * 最低销售价格
+   */
+  minSellingPrice: number;
+
+  /**
+   * 采购价格
+   */
+  purchasingPrice: number;
+
+  /**
+   * 暂估毛利率
+   */
+  tempGrossMargin: number;
+
+  /**
+   * 备注
+   */
+  remark: string;
+
+  /**
+   * 主库简介
+   */
+  mainLibraryIntro?: string;
+
+  /**
+   * 售后服务
+   */
+  afterSalesService?: string;
+
+  /**
+   * 服务保障 支持多选,分隔 (存储服务保障ID列表,如: "1,2,3")
+   */
+  serviceGuarantee?: string;
+
+  /**
+   * 安装服务 - 免费安装
+   */
+  freeInstallation?: string;
+
+  /**
+   * 市场价
+   */
+  midRangePrice?: number;
+
+  /**
+   * 平档价
+   */
+  standardPrice?: number;
+
+  /**
+   * 最低售价
+   */
+  certificatePrice?: number;
+
+  /**
+   * 售价验证量
+   */
+  priceVerificationQuantity?: string;
+
+  /**
+   * 采购价
+   */
+  purchasePrice?: number;
+
+  /**
+   * 暂估采购价
+   */
+  estimatedPurchasePrice?: number;
+
+  /**
+   * 产品性质
+   */
+  productNature?: string;
+
+  /**
+   * 采购人员
+   */
+  purchasingPersonnel?: string;
+
+  /**
+   * 旧属性类型
+   */
+  oldAttributeType?: string;
+
+  /**
+   * 录入套数
+   */
+  entrySetCount?: string;
+
+  /**
+   * 商品主图
+   */
+  mainImage?: string;
+
+  /**
+   * 商品详情 - 电脑端
+   */
+  pcDetail?: string;
+
+  /**
+   * 商品详情 - 移动端
+   */
+  mobileDetail?: string;
+
+  /**
+   * 税率
+   */
+  taxRate?: number;
+
+  /**
+   * 币种
+   */
+  currency?: string;
+
+  /**
+   * 最低起订量
+   */
+  minOrderQuantity?: number;
+
+  /**
+   * 商品属性值(JSON字符串)
+   */
+  attributesList?: string;
+}
+
+export interface BaseForm extends BaseEntity {
+  /**
+   * 主键,自增ID
+   */
+  id?: string | number;
+
+  /**
+   * 产品编号
+   */
+  productNo?: string;
+
+  /**
+   * 项目名称
+   */
+  itemName?: string;
+
+  /**
+   * 品牌id
+   */
+  brandId?: string | number;
+
+  /**
+   * 顶级分类id
+   */
+  topCategoryId?: string | number;
+
+  /**
+   * 中级分类id
+   */
+  mediumCategoryId?: string | number;
+
+  /**
+   * 底层分类id
+   */
+  bottomCategoryId?: string | number;
+
+  /**
+   * 单位id
+   */
+  unitId?: string | number;
+
+  /**
+   * 产品图片URL
+   */
+  productImage?: string;
+
+  /**
+   * 是否自营(1=是,0=否)
+   */
+  isSelf?: string;
+
+  /**
+   * 产品审核状态 0=待提交,1=待审核,2=审核通过,3=审核驳回
+   */
+  productReviewStatus?: string;
+
+  /**
+   * 首页推荐:1=推荐,0=不推荐
+   */
+  homeRecommended?: string;
+
+  /**
+   * 分类推荐:1=推荐,0=不推荐
+   */
+  categoryRecommendation?: string;
+
+  /**
+   * 购物车推荐:1=推荐,0=不推荐
+   */
+  cartRecommendation?: string;
+
+  /**
+   * 推荐产品顺序
+   */
+  recommendedProductOrder?: number;
+
+  /**
+   * 是否热门:1=是,0=否
+   */
+  isPopular?: string;
+
+  /**
+   * 是否新品:1=是,0=否
+   */
+  isNew?: string;
+
+  /**
+   * 商品状态:1=上架,0=下架等
+   */
+  productStatus?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+
+  /**
+   * 款号
+   */
+  styleNo?: string;
+
+  /**
+   * A10产品名称
+   */
+  a10ProductName?: string;
+
+  /**
+   * 规格型号
+   */
+  specification?: string;
+
+  /**
+   * UPC(S)条码
+   */
+  upcBarcode?: string;
+
+  /**
+   * 发票名称
+   */
+  invoiceName?: string;
+
+  /**
+   * 发票规格
+   */
+  invoiceSpec?: string;
+
+  /**
+   * 产品品牌
+   */
+  productBrand?: string;
+
+  /**
+   * 段号
+   */
+  sectionNo?: string;
+
+  /**
+   * 包装规格
+   */
+  packagingSpec?: string;
+
+  /**
+   * 采用基准
+   */
+  adoptionStandard?: string;
+
+  /**
+   * 采品性质
+   */
+  purchaseNature?: string;
+
+  /**
+   * 参考链接
+   */
+  referenceLink?: string;
+
+  /**
+   * 商品重量
+   */
+  weight?: string;
+
+  /**
+   * 重量单位
+   */
+  weightUnit?: string;
+
+  /**
+   * 商品体积
+   */
+  volume?: string;
+
+  /**
+   * 体积单位
+   */
+  volumeUnit?: string;
+
+  /**
+   * 主库简介
+   */
+  mainLibraryIntro?: string;
+
+  /**
+   * 售后服务
+   */
+  afterSalesService?: string;
+
+  /**
+   * 服务保障 支持多选,分隔 (存储服务保障ID列表,如: "1,2,3")
+   */
+  serviceGuarantee?: string;
+
+  /**
+   * 安装服务 - 免费安装
+   */
+  freeInstallation?: string;
+
+  /**
+   * 市场价
+   */
+  midRangePrice?: number;
+
+  /**
+   * 平档价
+   */
+  standardPrice?: number;
+
+  /**
+   * 最低售价
+   */
+  certificatePrice?: number;
+
+  /**
+   * 售价验证量
+   */
+  priceVerificationQuantity?: string;
+
+  /**
+   * 采购价
+   */
+  purchasePrice?: number;
+
+  /**
+   * 暂估采购价
+   */
+  estimatedPurchasePrice?: number;
+
+  /**
+   * 产品性质
+   */
+  productNature?: string;
+
+  /**
+   * 采购人员
+   */
+  purchasingPersonnel?: string;
+
+  /**
+   * 旧属性类型
+   */
+  oldAttributeType?: string;
+
+  /**
+   * 录入套数
+   */
+  entrySetCount?: string;
+
+  /**
+   * 商品主图
+   */
+  mainImage?: string;
+
+  /**
+   * 商品详情 - 电脑端
+   */
+  pcDetail?: string;
+
+  /**
+   * 商品详情 - 移动端
+   */
+  mobileDetail?: string;
+
+  /**
+   * 税率
+   */
+  taxRate?: number;
+
+  /**
+   * 币种
+   */
+  currency?: string;
+
+  /**
+   * 最低起订量
+   */
+  minOrderQuantity?: number;
+
+  /**
+   * 是否可定制
+   */
+  customizable?: boolean;
+
+  /**
+   * 定制方式(逗号分隔)
+   */
+  customizedStyle?: string;
+
+  /**
+   * 定制工艺(逗号分隔)
+   */
+  customizedCraft?: string;
+
+  /**
+   * 定制说明
+   */
+  customDescription?: string;
+
+  /**
+   * 定制详情列表(JSON字符串)
+   */
+  customDetailsJson?: string;
+
+  /**
+   * 销售量/销量人气
+   */
+  salesVolume?: number;
+
+  /**
+   * 商品属性值(JSON字符串)
+   */
+  attributesList?: string;
+}
+
+export interface BaseQuery extends PageQuery {
+  /**
+   * 产品编号
+   */
+  productNo?: string;
+
+  /**
+   * 项目名称
+   */
+  itemName?: string;
+
+  /**
+   * 品牌id
+   */
+  brandId?: string | number;
+
+  /**
+   * 顶级分类id
+   */
+  topCategoryId?: string | number;
+
+  /**
+   * 中级分类id
+   */
+  mediumCategoryId?: string | number;
+
+  /**
+   * 底层分类id
+   */
+  bottomCategoryId?: string | number;
+
+  /**
+   * 单位id
+   */
+  unitId?: string | number;
+
+  /**
+   * 产品图片URL
+   */
+  productImage?: string;
+
+  /**
+   * 是否自营(1=是,0=否)
+   */
+  isSelf?: string;
+
+  /**
+   * 产品审核状态 0=待提交,1=待审核,2=审核通过,3=审核驳回
+   */
+  productReviewStatus?: string;
+
+  /**
+   * 首页推荐:1=推荐,0=不推荐
+   */
+  homeRecommended?: string;
+
+  /**
+   * 分类推荐:1=推荐,0=不推荐
+   */
+  categoryRecommendation?: string;
+
+  /**
+   * 购物车推荐:1=推荐,0=不推荐
+   */
+  cartRecommendation?: string;
+
+  /**
+   * 推荐产品顺序
+   */
+  recommendedProductOrder?: number;
+
+  /**
+   * 是否热门:1=是,0=否
+   */
+  isPopular?: string;
+
+  /**
+   * 是否新品:1=是,0=否
+   */
+  isNew?: string;
+
+  /**
+   * 商品状态:1=上架,0=下架等
+   */
+  productStatus?: string | number;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 商品标签
+   */
+  productTag?: string;
+
+  /**
+   * 采购性质
+   */
+  purchaseNature?: string;
+
+  /**
+   * 供应商类型
+   */
+  supplierType?: string;
+
+  /**
+   * 供应商性质
+   */
+  supplierNature?: string;
+
+  /**
+   * 项目组织
+   */
+  projectOrg?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 63 - 0
src/api/product/brand/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { BrandVO, BrandForm, BrandQuery } from '@/api/product/brand/types';
+
+/**
+ * 查询产品品牌信息列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listBrand = (query?: BrandQuery): AxiosPromise<BrandVO[]> => {
+  return request({
+    url: '/product/brand/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询产品品牌信息详细
+ * @param id
+ */
+export const getBrand = (id: string | number): AxiosPromise<BrandVO> => {
+  return request({
+    url: '/product/brand/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增产品品牌信息
+ * @param data
+ */
+export const addBrand = (data: BrandForm) => {
+  return request({
+    url: '/product/brand',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改产品品牌信息
+ * @param data
+ */
+export const updateBrand = (data: BrandForm) => {
+  return request({
+    url: '/product/brand',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除产品品牌信息
+ * @param id
+ */
+export const delBrand = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/product/brand/' + id,
+    method: 'delete'
+  });
+};

+ 309 - 0
src/api/product/brand/types.ts

@@ -0,0 +1,309 @@
+export interface BrandVO {
+  /**
+   * 主键
+   */
+  id: string | number;
+
+  /**
+   * 品牌编号(唯一标识)
+   */
+  brandNo: string;
+
+  /**
+   * 品牌中文名称
+   */
+  brandName: string;
+
+  /**
+   * 品牌首字母缩写(如拼音首字母)
+   */
+  brandInitials: string;
+
+  /**
+   * 品牌英文名称
+   */
+  brandEnglishName: string;
+
+  /**
+   * 推荐值(数值越大越靠前)
+   */
+  recommendValue: number;
+
+  /**
+   * 品牌Logo图片路径或URL
+   */
+  brandLogo: string;
+
+  /**
+   * 品牌标题(用于展示)
+   */
+  brandTitle: string;
+
+  /**
+   * 品牌大图(横幅/封面图)
+   */
+  brandBigImage: string;
+
+  /**
+   * 品牌大图(横幅/封面图)Url
+   */
+  brandBigImageUrl: string;
+  /**
+   * 品牌故事(简介文本)
+   */
+  brandStory: string;
+
+  /**
+   * 是否显示(1=显示,0=隐藏)
+   */
+  isShow: number;
+
+  /**
+   * 品牌注册人
+   */
+  brandRegistrant: string;
+
+  /**
+   * 许可证编号
+   */
+  license: string;
+
+  /**
+   * 注册证书编号
+   */
+  registrationCertificate: string;
+
+  /**
+   * 证书/许可过期时间
+   */
+  expireTime: string;
+
+  /**
+   * 品牌描述(较长文本)
+   */
+  brandDescribe: string;
+
+  /**
+   * 展示位置(如首页、分类页等)
+   */
+  position: string;
+
+  /**
+   * 关注度/收藏数(默认为0)
+   */
+  care: number;
+
+  /**
+   * 数据来源
+   */
+  dataSource: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface BrandForm extends BaseEntity {
+  /**
+   * 主键
+   */
+  id?: string | number;
+
+  /**
+   * 品牌编号(唯一标识)
+   */
+  brandNo?: string;
+
+  /**
+   * 品牌中文名称
+   */
+  brandName?: string;
+
+  /**
+   * 品牌首字母缩写(如拼音首字母)
+   */
+  brandInitials?: string;
+
+  /**
+   * 品牌英文名称
+   */
+  brandEnglishName?: string;
+
+  /**
+   * 推荐值(数值越大越靠前)
+   */
+  recommendValue?: number;
+
+  /**
+   * 品牌Logo图片路径或URL
+   */
+  brandLogo?: string;
+
+  /**
+   * 品牌标题(用于展示)
+   */
+  brandTitle?: string;
+
+  /**
+   * 品牌大图(横幅/封面图)
+   */
+  brandBigImage?: string;
+
+  /**
+   * 品牌故事(简介文本)
+   */
+  brandStory?: string;
+
+  /**
+   * 是否显示(1=显示,0=隐藏)
+   */
+  isShow?: number;
+
+  /**
+   * 品牌注册人
+   */
+  brandRegistrant?: string;
+
+  /**
+   * 许可证编号
+   */
+  license?: string;
+
+  /**
+   * 注册证书编号
+   */
+  registrationCertificate?: string;
+
+  /**
+   * 证书/许可过期时间
+   */
+  expireTime?: string;
+
+  /**
+   * 品牌描述(较长文本)
+   */
+  brandDescribe?: string;
+
+  /**
+   * 展示位置(如首页、分类页等)
+   */
+  position?: string;
+
+  /**
+   * 关注度/收藏数(默认为0)
+   */
+  care?: number;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface BrandQuery extends PageQuery {
+  /**
+   * 品牌编号(唯一标识)
+   */
+  brandNo?: string;
+
+  /**
+   * 品牌中文名称
+   */
+  brandName?: string;
+
+  /**
+   * 品牌首字母缩写(如拼音首字母)
+   */
+  brandInitials?: string;
+
+  /**
+   * 品牌英文名称
+   */
+  brandEnglishName?: string;
+
+  /**
+   * 推荐值(数值越大越靠前)
+   */
+  recommendValue?: number;
+
+  /**
+   * 品牌Logo图片路径或URL
+   */
+  brandLogo?: string;
+
+  /**
+   * 品牌标题(用于展示)
+   */
+  brandTitle?: string;
+
+  /**
+   * 品牌大图(横幅/封面图)
+   */
+  brandBigImage?: string;
+
+  /**
+   * 品牌故事(简介文本)
+   */
+  brandStory?: string;
+
+  /**
+   * 是否显示(1=显示,0=隐藏)
+   */
+  isShow?: number;
+
+  /**
+   * 品牌注册人
+   */
+  brandRegistrant?: string;
+
+  /**
+   * 许可证编号
+   */
+  license?: string;
+
+  /**
+   * 注册证书编号
+   */
+  registrationCertificate?: string;
+
+  /**
+   * 证书/许可过期时间
+   */
+  expireTime?: string;
+
+  /**
+   * 品牌描述(较长文本)
+   */
+  brandDescribe?: string;
+
+  /**
+   * 展示位置(如首页、分类页等)
+   */
+  position?: string;
+
+  /**
+   * 关注度/收藏数(默认为0)
+   */
+  care?: number;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 74 - 0
src/api/product/category/index.ts

@@ -0,0 +1,74 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { CategoryVO, CategoryForm, CategoryQuery } from '@/api/product/category/types';
+
+/**
+ * 查询产品分类列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listCategory = (query?: CategoryQuery): AxiosPromise<CategoryVO[]> => {
+  return request({
+    url: '/product/category/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询产品分类详细
+ * @param id
+ */
+export const getCategory = (id: string | number): AxiosPromise<CategoryVO> => {
+  return request({
+    url: '/product/category/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增产品分类
+ * @param data
+ */
+export const addCategory = (data: CategoryForm) => {
+  return request({
+    url: '/product/category',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改产品分类
+ * @param data
+ */
+export const updateCategory = (data: CategoryForm) => {
+  return request({
+    url: '/product/category',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除产品分类
+ * @param id
+ */
+export const delCategory = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/product/category/' + id,
+    method: 'delete'
+  });
+};
+
+/**
+ * 查询产品分类列表(排除节点)
+ * @param id
+ */
+export const listCategoryExcludeChild = (id: string | number): AxiosPromise<CategoryVO[]> => {
+  return request({
+    url: '/product/category/list/exclude/' + id,
+    method: 'get'
+  });
+};

+ 392 - 0
src/api/product/category/types.ts

@@ -0,0 +1,392 @@
+export interface CategoryVO {
+  /**
+   * 主键
+   */
+  id: string | number;
+
+  /**
+   * 分类编号
+   */
+  categoryNo: string;
+
+  /**
+   * 分类名称
+   */
+  categoryName: string;
+
+  /**
+   * 父级分类ID
+   */
+  parentId: string | number;
+
+  /**
+   * 父级分类名称
+   */
+  parentName?: string;
+
+  /**
+   * 祖籍列表
+   */
+  ancestors: string;
+
+  /**
+   * 分类层级(1=一级,2=二级, 3三级)
+   */
+  classLevel: number;
+
+  /**
+   * 是否显示(1=显示,0=隐藏)
+   */
+  isShow: number;
+
+  /**
+   * 是否在GPS中显示
+   */
+  isShowGps: number;
+
+  /**
+   * 折扣率(可能为JSON或文本)
+   */
+  discountRate: number;
+
+  /**
+   * 拼音码(用于快速检索)
+   */
+  pyCode: string;
+
+  /**
+   * 分类描述
+   */
+  classDescription: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource: string;
+
+  /**
+   * 自定义标签1
+   */
+  oneLable1: string;
+
+  /**
+   * 自定义标签2
+   */
+  oneLable2: string;
+
+  /**
+   * 自定义链接1
+   */
+  oneLink1: string;
+
+  /**
+   * 自定义链接2
+   */
+  oneLink2: string;
+
+  /**
+   * 排序值,默认为0
+   */
+  sort: number;
+
+  /**
+   * 颜色(如CSS颜色值)
+   */
+  color: string;
+
+  /**
+   * 采购编号
+   */
+  purchaseNo: string;
+
+  /**
+   * 采购名称
+   */
+  purchaseName: string;
+
+  /**
+   * 采购负责人编号
+   */
+  purchaseManagerNo: string;
+
+  /**
+   * 采购负责人姓名
+   */
+  purchaseManagerName: string;
+
+  /**
+   * 所属平台(0=Web, 1=小程序)
+   */
+  platform: number;
+
+  /**
+   * 备注
+   */
+  remark: string;
+
+  /**
+   * 子级分类
+   */
+  children?: CategoryVO[];
+}
+
+export interface CategoryForm extends BaseEntity {
+  /**
+   * 主键
+   */
+  id?: string | number;
+
+  /**
+   * 分类编号
+   */
+  categoryNo?: string;
+
+  /**
+   * 分类名称
+   */
+  categoryName?: string;
+
+  /**
+   * 父级分类ID
+   */
+  parentId?: string | number;
+
+  /**
+   * 父级分类名称
+   */
+  parentName?: string;
+
+  /**
+   * 祖籍列表
+   */
+  ancestors?: string;
+
+  /**
+   * 分类层级(1=一级,2=二级, 3三级)
+   */
+  classLevel?: number;
+
+  /**
+   * 是否显示(1=显示,0=隐藏)
+   */
+  isShow?: number;
+
+  /**
+   * 是否在GPS中显示
+   */
+  isShowGps?: number;
+
+  /**
+   * 折扣率(可能为JSON或文本)
+   */
+  discountRate?: number;
+
+  /**
+   * 拼音码(用于快速检索)
+   */
+  pyCode?: string;
+
+  /**
+   * 分类描述
+   */
+  classDescription?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 自定义标签1
+   */
+  oneLable1?: string;
+
+  /**
+   * 自定义标签2
+   */
+  oneLable2?: string;
+
+  /**
+   * 自定义链接1
+   */
+  oneLink1?: string;
+
+  /**
+   * 自定义链接2
+   */
+  oneLink2?: string;
+
+  /**
+   * 排序值,默认为0
+   */
+  sort?: number;
+
+  /**
+   * 颜色(如CSS颜色值)
+   */
+  color?: string;
+
+  /**
+   * 采购编号
+   */
+  purchaseNo?: string;
+
+  /**
+   * 采购名称
+   */
+  purchaseName?: string;
+
+  /**
+   * 采购负责人编号
+   */
+  purchaseManagerNo?: string;
+
+  /**
+   * 采购负责人姓名
+   */
+  purchaseManagerName?: string;
+
+  /**
+   * 所属平台(0=Web, 1=小程序)
+   */
+  platform?: number;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface CategoryQuery extends PageQuery {
+  /**
+   * 分类编号
+   */
+  categoryNo?: string;
+
+  /**
+   * 分类名称
+   */
+  categoryName?: string;
+
+  /**
+   * 父级分类ID
+   */
+  parentId?: string | number;
+
+  /**
+   * 祖籍列表
+   */
+  ancestors?: string;
+
+  /**
+   * 分类层级(1=一级,2=二级, 3三级)
+   */
+  classLevel?: number;
+
+  /**
+   * 是否显示(1=显示,0=隐藏)
+   */
+  isShow?: number;
+
+  /**
+   * 是否在GPS中显示
+   */
+  isShowGps?: number;
+
+  /**
+   * 折扣率(可能为JSON或文本)
+   */
+  discountRate?: number;
+
+  /**
+   * 拼音码(用于快速检索)
+   */
+  pyCode?: string;
+
+  /**
+   * 分类描述
+   */
+  classDescription?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 自定义标签1
+   */
+  oneLable1?: string;
+
+  /**
+   * 自定义标签2
+   */
+  oneLable2?: string;
+
+  /**
+   * 自定义链接1
+   */
+  oneLink1?: string;
+
+  /**
+   * 自定义链接2
+   */
+  oneLink2?: string;
+
+  /**
+   * 排序值,默认为0
+   */
+  sort?: number;
+
+  /**
+   * 颜色(如CSS颜色值)
+   */
+  color?: string;
+
+  /**
+   * 采购编号
+   */
+  purchaseNo?: string;
+
+  /**
+   * 采购名称
+   */
+  purchaseName?: string;
+
+  /**
+   * 采购负责人编号
+   */
+  purchaseManagerNo?: string;
+
+  /**
+   * 采购负责人姓名
+   */
+  purchaseManagerName?: string;
+
+  /**
+   * 所属平台(0=Web, 1=小程序)
+   */
+  platform?: number;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}
+
+/**
+ * 部门类型
+ */
+export interface categoryTreeVO extends BaseEntity {
+  id: number | string;
+  label: string;
+  parentId: number | string;
+  weight: number;
+  children: categoryTreeVO[];
+  isShow: '';
+}

+ 63 - 0
src/api/product/ensure/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { EnsureVO, EnsureForm, EnsureQuery } from '@/api/product/ensure/types';
+
+/**
+ * 查询产品保障项列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listEnsure = (query?: EnsureQuery): AxiosPromise<EnsureVO[]> => {
+  return request({
+    url: '/product/ensure/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询产品保障项详细
+ * @param id
+ */
+export const getEnsure = (id: string | number): AxiosPromise<EnsureVO> => {
+  return request({
+    url: '/product/ensure/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增产品保障项
+ * @param data
+ */
+export const addEnsure = (data: EnsureForm) => {
+  return request({
+    url: '/product/ensure',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改产品保障项
+ * @param data
+ */
+export const updateEnsure = (data: EnsureForm) => {
+  return request({
+    url: '/product/ensure',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除产品保障项
+ * @param id
+ */
+export const delEnsure = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/product/ensure/' + id,
+    method: 'delete'
+  });
+};

+ 65 - 0
src/api/product/ensure/types.ts

@@ -0,0 +1,65 @@
+export interface EnsureVO {
+  /**
+   * 主键ID
+   */
+  id: string | number;
+
+  /**
+   * 保障名称(如:正品保证、售后保障等)
+   */
+  ensureName: string;
+
+  /**
+   * 数据来源(如:系统配置、接口同步等)
+   */
+  dataSource: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface EnsureForm extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id?: string | number;
+
+  /**
+   * 保障名称(如:正品保证、售后保障等)
+   */
+  ensureName?: string;
+
+  /**
+   * 数据来源(如:系统配置、接口同步等)
+   */
+  dataSource?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface EnsureQuery extends PageQuery {
+  /**
+   * 保障名称(如:正品保证、售后保障等)
+   */
+  ensureName?: string;
+
+  /**
+   * 数据来源(如:系统配置、接口同步等)
+   */
+  dataSource?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 63 - 0
src/api/product/unit/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { UnitVO, UnitForm, UnitQuery } from '@/api/product/unit/types';
+
+/**
+ * 查询产品计量单位列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listUnit = (query?: UnitQuery): AxiosPromise<UnitVO[]> => {
+  return request({
+    url: '/product/unit/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询产品计量单位详细
+ * @param id
+ */
+export const getUnit = (id: string | number): AxiosPromise<UnitVO> => {
+  return request({
+    url: '/product/unit/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增产品计量单位
+ * @param data
+ */
+export const addUnit = (data: UnitForm) => {
+  return request({
+    url: '/product/unit',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改产品计量单位
+ * @param data
+ */
+export const updateUnit = (data: UnitForm) => {
+  return request({
+    url: '/product/unit',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除产品计量单位
+ * @param id
+ */
+export const delUnit = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/product/unit/' + id,
+    method: 'delete'
+  });
+};

+ 95 - 0
src/api/product/unit/types.ts

@@ -0,0 +1,95 @@
+export interface UnitVO {
+  /**
+   * 主键,自增ID
+   */
+  id: string | number;
+
+  /**
+   * 单位编号
+   */
+  unitNo: string;
+
+  /**
+   * 单位名称(如:件、箱、千克等)
+   */
+  unitName: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource: string;
+
+  /**
+   * 是否显示:1=是,0=否
+   */
+  isShow: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+}
+
+export interface UnitForm extends BaseEntity {
+  /**
+   * 主键,自增ID
+   */
+  id?: string | number;
+
+  /**
+   * 单位编号
+   */
+  unitNo?: string;
+
+  /**
+   * 单位名称(如:件、箱、千克等)
+   */
+  unitName?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 是否显示:1=是,0=否
+   */
+  isShow?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+}
+
+export interface UnitQuery extends PageQuery {
+  /**
+   * 单位编号
+   */
+  unitNo?: string;
+
+  /**
+   * 单位名称(如:件、箱、千克等)
+   */
+  unitName?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 是否显示:1=是,0=否
+   */
+  isShow?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 8 - 0
src/api/system/dept/index.ts

@@ -63,3 +63,11 @@ export const delDept = (deptId: number | string) => {
     method: 'delete'
   });
 };
+
+// 查询客户部门
+export const listCustomerDept = (customerId: string | number): AxiosPromise<DeptVO[]> => {
+  return request({
+    url: `/system/dept/customerDeptList/${customerId}`, // 拼接 customerId 到路径
+    method: 'get'
+  });
+};

+ 6 - 54
src/api/system/dept/types.ts

@@ -5,7 +5,8 @@ export interface DeptQuery extends PageQuery {
   deptName?: string;
   deptCategory?: string;
   status?: number;
-  customerId?: number | string;
+  isCompanyFlag?: string;
+  companyId?: number | string;
 }
 
 /**
@@ -27,33 +28,8 @@ export interface DeptVO extends BaseEntity {
   delFlag: string;
   ancestors: string;
   menuId: string | number;
-
-  /**
-   * 年度预算
-   */
-  annualBudget: number;
-
-  /**
-   * 已用预算
-   */
-  budgetUsed: number;
-
-  /**
-   * 月采限额
-   */
-  monthlyQuota: number;
-
-  /**
-   * 是否绑定
-   */
-  isBound: string;
-
-  /**
-   * 地址ID
-   */
-  shopAddressId: number | string;
-
-  customerId: number | string;
+  platformCode: string;
+  companyId?: number | string;
 }
 
 /**
@@ -66,7 +42,6 @@ export interface DeptTreeVO extends BaseEntity {
   weight: number;
   children: DeptTreeVO[];
   disabled: boolean;
-  customerId: number | string;
 }
 
 /**
@@ -86,29 +61,6 @@ export interface DeptForm {
   status?: string;
   delFlag?: string;
   ancestors?: string;
-  /**
-   * 年度预算
-   */
-  annualBudget?: number;
-
-  /**
-   * 已用预算
-   */
-  budgetUsed?: number;
-
-  /**
-   * 月采限额
-   */
-  monthlyQuota?: number;
-
-  /**
-   * 是否绑定
-   */
-  isBound?: string;
-
-  /**
-   * 地址ID
-   */
-  shopAddressId?: number | string;
-  customerId?: number | string;
+  platformCode?: string;
+  companyId?: number | string;
 }

+ 55 - 20
src/views/customer/customerFile/customerInfo/add.vue

@@ -320,17 +320,17 @@
           <el-button type="primary" @click="handleSubmit">保存</el-button>
         </div>
       </template>
-      <el-form :model="salesForm" label-width="120px">
+      <el-form ref="salesFormRef" :model="salesForm" :rules="salesRules" label-width="120px">
         <el-row :gutter="20">
           <el-col :span="8">
-            <el-form-item label="业务人员" prop="salesPersonId">
+            <el-form-item label="业务人员" prop="salesPersonId" required>
               <el-select v-model="salesForm.salesPersonId" placeholder="请选择业务人员" class="w-full" filterable @change="handleSalesPersonChange">
                 <el-option v-for="item in comStaffList" :key="item.staffId" :label="`${item.staffCode} , ${item.staffName}`" :value="item.staffId" />
               </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="8">
-            <el-form-item label="客服人员" prop="serviceStaffId">
+            <el-form-item label="客服人员" prop="serviceStaffId" required>
               <el-select v-model="salesForm.serviceStaffId" placeholder="请选择客服人员" class="w-full" filterable>
                 <el-option v-for="item in comStaffList" :key="item.staffId" :label="`${item.staffCode} , ${item.staffName}`" :value="item.staffId" />
               </el-select>
@@ -338,12 +338,7 @@
           </el-col>
           <el-col :span="8">
             <el-form-item label="所属部门" prop="belongingDepartmentId">
-              <el-select v-model="salesForm.belongingDepartmentId" placeholder="请选择所属部门" class="w-full" filterable disabled>
-                <el-option v-for="item in comDeptList" :key="item.id" :label="item.deptName" :value="String(item.id)" />
-              </el-select>
-              <div v-if="salesForm.belongingDepartmentId && !comDeptList.length" style="color: #606266; font-size: 14px; margin-top: 4px">
-                {{ getDeptName(salesForm.belongingDepartmentId) }}
-              </div>
+              <el-input v-model="deptName" placeholder="请选择所属部门" class="w-full" disabled />
             </el-form-item>
           </el-col>
         </el-row>
@@ -409,12 +404,13 @@ import type { EnterpriseScaleVO } from '@/api/customer/customerCategory/enterpri
 import type { IndustryCategoryVO } from '@/api/customer/customerCategory/industryCategory/types';
 import { listComStaff, getComStaff } from '@/api/company/comStaff';
 import { ComStaffVO, ComStaffQuery, ComStaffForm } from '@/api/company/comStaff/types';
-import { listComDept, getComDept } from '@/api/company/comDept';
-import { ComDeptVO } from '@/api/company/comDept/types';
+import { listDept, getDept, listDeptExcludeChild } from '@/api/system/dept';
+import { DeptVO } from '@/api/system/dept/types';
 
 import { listCompany } from '@/api/company/company';
 import { CompanyVO } from '@/api/company/company/types';
 import { Plus, Delete } from '@element-plus/icons-vue';
+import { log } from 'console';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { customer_type, customer_level } = toRefs<any>(proxy?.useDict('customer_type', 'customer_level'));
@@ -423,6 +419,7 @@ const route = useRoute();
 const router = useRouter();
 
 const formRef = ref<any>(null);
+const salesFormRef = ref<any>(null);
 const submitLoading = ref(false);
 
 // 生成客户编号
@@ -440,7 +437,7 @@ const settlementMethodList = ref<SettlementMethodVO[]>([]);
 const customerLevelList = ref<CustomerLevelVO[]>([]);
 const customerTypeList = ref<CustomerTypeVO[]>([]);
 const comStaffList = ref<ComStaffVO[]>([]);
-const comDeptList = ref<ComDeptVO[]>([]);
+const comDeptList = ref<DeptVO[]>([]);
 
 // Logo选择器相关
 const logoSelectorVisible = ref(false);
@@ -648,7 +645,7 @@ const loadComStaffList = async () => {
 // 加载部门列表
 const loadComDeptList = async () => {
   try {
-    const res = await listComDept();
+    const res = await listDept();
     // 处理可能的不同返回结构
     comDeptList.value = res.rows || res.data || [];
   } catch (error) {
@@ -730,6 +727,12 @@ const rules = {
   address: [{ required: true, message: '请输入详细地址', trigger: 'blur' }]
 };
 
+// 销售信息表单验证规则
+const salesRules = {
+  salesPersonId: [{ required: true, message: '请选择业务人员', trigger: 'change' }],
+  serviceStaffId: [{ required: true, message: '请选择客服人员', trigger: 'change' }]
+};
+
 // 获取角色名称
 const getRoleName = (roleId: string | number | undefined) => {
   const roleMap: Record<string, string> = {
@@ -784,17 +787,45 @@ const handleChange = (val: string[]) => {
 const handleSalesPersonChange = (staffId: any) => {
   // 根据选中的业务人员ID,找到对应的部门ID
   const selectedStaff = comStaffList.value.find((staff) => staff.staffId === staffId);
-  if (selectedStaff) {
-    // 确保 deptId 的类型一致
+  if (selectedStaff && selectedStaff.deptId) {
+    // 确保 deptId 的类型一致,watch 会自动触发加载部门名称
     salesForm.belongingDepartmentId = String(selectedStaff.deptId);
   }
 };
 
-// 获取部门名称
-const getDeptName = (deptId: any) => {
-  const dept = comDeptList.value.find(d => String(d.id) === String(deptId));
-  return dept ? dept.deptName : deptId;
-};
+// 部门名称(响应式)
+const deptName = ref('');
+
+// 监听部门ID变化,自动加载部门名称
+watch(
+  () => salesForm.belongingDepartmentId,
+  async (newDeptId) => {
+    if (!newDeptId) {
+      deptName.value = '';
+      return;
+    }
+
+    // 先从列表中查找
+    const dept = comDeptList.value.find((d) => String(d.deptId) === String(newDeptId));
+    if (dept) {
+      deptName.value = dept.deptName;
+      return;
+    }
+
+    // 如果列表中没有,从API获取
+    try {
+      const res = await getDept(newDeptId);
+      if (res.data) {
+        deptName.value = res.data.deptName;
+        comDeptList.value.push(res.data);
+      }
+    } catch (error) {
+      console.error('获取部门信息失败:', error);
+      deptName.value = String(newDeptId);
+    }
+  },
+  { immediate: true }
+);
 
 // 编辑联系人
 const handleEditContact = (row: CustomerContactForm, index: number) => {
@@ -870,7 +901,11 @@ const removeInvoice = (index: number) => {
 // 提交表单
 const handleSubmit = async () => {
   try {
+    // 验证基本信息表单
     await formRef.value?.validate();
+    // 验证销售信息表单
+    await salesFormRef.value?.validate();
+
     submitLoading.value = true;
 
     // 将客户编号赋值到表单

+ 3 - 0
src/views/customer/customerFile/customerInfo/index.vue

@@ -572,4 +572,7 @@ onMounted(() => {
   loadComStaffList();
   loadComDeptList();
 });
+onActivated(() => {
+  getList();
+});
 </script>

+ 83 - 30
src/views/customer/customerFile/customerInfo/overview/baseInfo.vue

@@ -293,17 +293,17 @@
           <el-button type="primary" @click="handleSave">保存</el-button>
         </div>
       </template>
-      <el-form :model="salesForm" label-width="140px">
+      <el-form ref="salesFormRef" :model="salesForm" :rules="salesRules" label-width="140px">
         <el-row :gutter="20">
           <el-col :span="8">
-            <el-form-item label="业务人员" prop="salesPersonId">
+            <el-form-item label="业务人员" prop="salesPersonId" required>
               <el-select v-model="salesForm.salesPersonId" placeholder="请选择业务人员" class="w-full" filterable @change="handleSalesPersonChange">
                 <el-option v-for="item in comStaffList" :key="item.staffId" :label="`${item.staffCode} , ${item.staffName}`" :value="item.staffId" />
               </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="8">
-            <el-form-item label="客服人员" prop="serviceStaffId">
+            <el-form-item label="客服人员" prop="serviceStaffId" required>
               <el-select v-model="salesForm.serviceStaffId" placeholder="请选择客服人员" class="w-full" filterable>
                 <el-option v-for="item in comStaffList" :key="item.staffId" :label="`${item.staffCode} , ${item.staffName}`" :value="item.staffId" />
               </el-select>
@@ -311,20 +311,15 @@
           </el-col>
           <el-col :span="8">
             <el-form-item label="所属部门" prop="belongingDepartmentId">
-              <el-select v-model="salesForm.belongingDepartmentId" placeholder="请选择所属部门" class="w-full" filterable disabled>
-                <el-option v-for="item in comDeptList" :key="item.id" :label="item.deptName" :value="String(item.id)" />
-              </el-select>
-              <div v-if="salesForm.belongingDepartmentId && !comDeptList.length" style="color: #606266; font-size: 14px; margin-top: 4px">
-                {{ getDeptName(salesForm.belongingDepartmentId) }}
-              </div>
+              <el-input v-model="deptName" placeholder="请选择所属部门" class="w-full" disabled />
             </el-form-item>
           </el-col>
         </el-row>
 
         <el-row :gutter="20">
           <el-col :span="8">
-            <el-form-item label="信用等级" prop="creditManagement">
-              <el-select v-model="salesForm.creditManagement" placeholder="请选择信用等级" class="w-full" filterable>
+            <el-form-item label="信用等级" prop="creditManagementId">
+              <el-select v-model="salesForm.creditManagementId" placeholder="请选择信用等级" class="w-full" filterable>
                 <el-option
                   v-for="item in creditLevelList"
                   :key="item.id"
@@ -454,8 +449,8 @@ import { listCompany } from '@/api/company/company';
 import { CompanyVO } from '@/api/company/company/types';
 import { listComStaff } from '@/api/company/comStaff';
 import { ComStaffVO, ComStaffQuery } from '@/api/company/comStaff/types';
-import { listComDept } from '@/api/company/comDept';
-import { ComDeptVO } from '@/api/company/comDept/types';
+import { listDept, getDept } from '@/api/system/dept';
+import { DeptVO } from '@/api/system/dept/types';
 import FileSelector from '@/components/FileSelector/index.vue';
 import { Plus, Delete } from '@element-plus/icons-vue';
 
@@ -471,6 +466,7 @@ const route = useRoute();
 const router = useRouter();
 
 const formRef = ref<any>(null);
+const salesFormRef = ref<any>(null);
 const submitLoading = ref(false);
 const customerId = ref<string | number>('');
 const customerNumber = ref('');
@@ -486,7 +482,7 @@ const creditLevelList = ref<CreditLevelVO[]>([]);
 const customerLevelList = ref<CustomerLevelVO[]>([]);
 const customerTypeList = ref<CustomerTypeVO[]>([]);
 const comStaffList = ref<ComStaffVO[]>([]);
-const comDeptList = ref<ComDeptVO[]>([]);
+const comDeptList = ref<DeptVO[]>([]);
 
 // 企业基本信息(用于显示)
 const customerInfo = reactive<any>({
@@ -561,7 +557,7 @@ const salesForm = reactive<SalesInfoForm>({
   salesPersonId: undefined,
   serviceStaffId: undefined,
   belongingDepartmentId: undefined,
-  creditManagement: undefined,
+  creditManagementId: undefined,
   creditAmount: undefined,
   remainingQuota: undefined,
   orderAudit: undefined,
@@ -600,6 +596,12 @@ const rules = {
   address: [{ required: true, message: '请输入详细地址', trigger: 'blur' }]
 };
 
+// 销售信息表单验证规则
+const salesRules = {
+  salesPersonId: [{ required: true, message: '请选择业务人员', trigger: 'change' }],
+  serviceStaffId: [{ required: true, message: '请选择客服人员', trigger: 'change' }]
+};
+
 // 初始化
 onMounted(async () => {
   // 加载下拉框数据
@@ -730,7 +732,7 @@ const loadComStaffList = async () => {
 // 加载部门列表
 const loadComDeptList = async () => {
   try {
-    const res = await listComDept();
+    const res = await listDept();
     // 处理可能的不同返回结构
     comDeptList.value = res.rows || res.data || [];
   } catch (error) {
@@ -782,6 +784,21 @@ const loadCustomerData = async (id: string) => {
     // 填充销售信息
     if (data.customerSalesInfoVo) {
       Object.assign(salesForm, data.customerSalesInfoVo);
+
+      // 如果有部门ID,且部门不在列表中,从API获取
+      if (salesForm.belongingDepartmentId) {
+        const deptExists = comDeptList.value.find((d) => String(d.deptId) === String(salesForm.belongingDepartmentId));
+        if (!deptExists) {
+          try {
+            const deptRes = await getDept(salesForm.belongingDepartmentId);
+            if (deptRes.data) {
+              comDeptList.value.push(deptRes.data);
+            }
+          } catch (error) {
+            console.error('获取部门信息失败:', error);
+          }
+        }
+      }
     }
 
     // 填充开票信息列表
@@ -823,20 +840,39 @@ const getCustomerLevelName = (id: string | number | undefined) => {
   return map[String(id)] || '-';
 };
 
-const getSalesPersonName = (id: string | number | undefined) => {
-  const map: Record<string, string> = { '1': '张三', '2': '李四', '3': '王五', '4': '赵六' };
-  return map[String(id)] || '-';
-};
+// 部门名称(响应式)
+const deptName = ref('');
 
-const getServiceStaffName = (id: string | number | undefined) => {
-  const map: Record<string, string> = { '1': '客服A', '2': '客服B', '3': '客服C', '4': '客服D' };
-  return map[String(id)] || '-';
-};
+// 监听部门ID变化,自动加载部门名称
+watch(
+  () => salesForm.belongingDepartmentId,
+  async (newDeptId) => {
+    if (!newDeptId) {
+      deptName.value = '';
+      return;
+    }
 
-const getDepartmentName = (id: string | number | undefined) => {
-  const map: Record<string, string> = { '1': '销售部', '2': '市场部', '3': '客服部', '4': '技术部' };
-  return map[String(id)] || '-';
-};
+    // 先从列表中查找
+    const dept = comDeptList.value.find((d) => String(d.deptId) === String(newDeptId));
+    if (dept) {
+      deptName.value = dept.deptName;
+      return;
+    }
+
+    // 如果列表中没有,从API获取
+    try {
+      const res = await getDept(newDeptId);
+      if (res.data) {
+        deptName.value = res.data.deptName;
+        comDeptList.value.push(res.data);
+      }
+    } catch (error) {
+      console.error('获取部门信息失败:', error);
+      deptName.value = String(newDeptId);
+    }
+  },
+  { immediate: true }
+);
 
 // 处理区域选择变化
 const handleChange = (val: string[]) => {
@@ -873,12 +909,25 @@ const handleChange = (val: string[]) => {
 };
 
 // 处理业务人员选择变化
-const handleSalesPersonChange = (staffId: any) => {
+const handleSalesPersonChange = async (staffId: any) => {
   // 根据选中的业务人员ID,找到对应的部门ID
   const selectedStaff = comStaffList.value.find((staff) => staff.staffId === staffId);
-  if (selectedStaff) {
+  if (selectedStaff && selectedStaff.deptId) {
     // 确保 deptId 的类型一致
     salesForm.belongingDepartmentId = String(selectedStaff.deptId);
+
+    // 如果部门不在列表中,从API获取
+    const deptExists = comDeptList.value.find((d) => String(d.deptId) === String(selectedStaff.deptId));
+    if (!deptExists) {
+      try {
+        const res = await getDept(selectedStaff.deptId);
+        if (res.data) {
+          comDeptList.value.push(res.data);
+        }
+      } catch (error) {
+        console.error('获取部门信息失败:', error);
+      }
+    }
   }
 };
 
@@ -991,7 +1040,11 @@ const removeInvoice = (index: number) => {
 // 保存按钮
 const handleSave = async () => {
   try {
+    // 验证基本信息表单
     await formRef.value?.validate();
+    // 验证销售信息表单
+    await salesFormRef.value?.validate();
+
     submitLoading.value = true;
 
     // 组装提交数据

+ 21 - 26
src/views/customer/customerFile/customerInfo/overview/orgStructure.vue

@@ -12,7 +12,7 @@
         </el-row>
       </template>
 
-      <el-table v-loading="loading" :data="customerDeptList" row-key="id" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
+      <el-table v-loading="loading" :data="customerDeptList" row-key="deptId" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
         <el-table-column prop="deptName" label="部门名称" width="200" />
         <el-table-column prop="yearlyBudget" label="年度预算" align="center" />
         <el-table-column prop="monthLimit" label="月采限额" align="center" />
@@ -41,8 +41,8 @@
           <el-tree-select
             v-model="form.parentId"
             :data="customerDeptOptions"
-            :props="{ value: 'id', label: 'deptName', children: 'children' }"
-            value-key="id"
+            :props="{ value: 'deptId', label: 'deptName', children: 'children' }"
+            value-key="deptId"
             placeholder="请选择"
             check-strictly
             :render-after-expand="false"
@@ -61,10 +61,9 @@
         <el-form-item label="已用预算" prop="usedBudget">
           <el-input v-model="form.usedBudget" placeholder="请输入已用预算" />
         </el-form-item>
-        <el-form-item label="状态">
+        <el-form-item label="是否启用">
           <el-radio-group v-model="form.status">
-            <el-radio value="0">启用</el-radio>
-            <el-radio value="1">未启用</el-radio>
+            <el-radio v-for="dict in sys_platform_yes_no" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
           </el-radio-group>
         </el-form-item>
         <el-form-item label="是否绑定">
@@ -90,9 +89,10 @@
 <script setup name="CustomerDept" lang="ts">
 import { listCustomerDept, getCustomerDept, delCustomerDept, addCustomerDept, updateCustomerDept } from '@/api/customer/customerFile/customerDept';
 import { CustomerDeptVO, CustomerDeptQuery, CustomerDeptForm } from '@/api/customer/customerFile/customerDept/types';
+import { delDept } from '@/api/system/dept';
 
 type CustomerDeptOption = {
-  id: number;
+  deptId: number;
   deptName: string;
   children?: CustomerDeptOption[];
 };
@@ -106,7 +106,7 @@ const props = defineProps<{
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
-const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable'));
+const { sys_platform_yes_no } = toRefs<any>(proxy?.useDict('sys_platform_yes_no'));
 
 const customerDeptList = ref<CustomerDeptVO[]>([]);
 const customerDeptOptions = ref<CustomerDeptOption[]>([]);
@@ -125,13 +125,12 @@ const dialog = reactive<DialogOption>({
 });
 
 const initFormData: CustomerDeptForm = {
-  id: undefined,
+  deptId: undefined,
   deptNo: undefined,
   deptName: undefined,
   parentId: undefined,
   ancestors: undefined,
   customerId: undefined,
-  departmentLevel: undefined,
   yearlyBudget: undefined,
   usedBudget: undefined,
   monthLimit: undefined,
@@ -144,7 +143,7 @@ const initFormData: CustomerDeptForm = {
   expenseType: undefined,
   residueYearlyBudget: undefined,
   recharge: undefined,
-  status: undefined,
+  status: '0',
   remark: undefined
 };
 
@@ -155,7 +154,6 @@ const data = reactive<PageData<CustomerDeptForm, CustomerDeptQuery>>({
     parentId: undefined,
     ancestors: undefined,
     customerId: undefined,
-    departmentLevel: undefined,
     yearlyBudget: undefined,
     usedBudget: undefined,
     monthLimit: undefined,
@@ -192,7 +190,7 @@ const getList = async () => {
     const res = await listCustomerDept(queryParams.value);
     // 如果返回的数据是数组,直接使用;否则尝试构建树形结构
     if (Array.isArray(res.data)) {
-      const treeData = proxy?.handleTree<CustomerDeptVO>(res.data, 'id', 'parentId');
+      const treeData = proxy?.handleTree<CustomerDeptVO>(res.data, 'deptId', 'parentId');
       customerDeptList.value = treeData || res.data;
     } else {
       customerDeptList.value = [];
@@ -208,7 +206,7 @@ const getTreeselect = async () => {
     customerId: props.customerId
   };
   const res = await listCustomerDept(query);
-  customerDeptOptions.value = proxy?.handleTree<CustomerDeptOption>(res.data, 'id', 'parentId') || [];
+  customerDeptOptions.value = proxy?.handleTree<CustomerDeptOption>(res.data, 'deptId', 'parentId') || [];
 };
 
 // 取消按钮
@@ -238,12 +236,11 @@ const resetQuery = () => {
 const handleAdd = async (row?: CustomerDeptVO) => {
   reset();
   await getTreeselect();
-  if (row != null && row.id) {
-    form.value.parentId = row.id;
+  if (row != null && row.deptId) {
+    form.value.parentId = row.deptId;
   }
   // 设置客户ID
   form.value.customerId = props.customerId;
-  form.value.status = '0';
   form.value.bindStatus = '1';
   dialog.visible = true;
   dialog.title = '新增部门';
@@ -267,10 +264,10 @@ const toggleExpandAll = (data: CustomerDeptVO[], status: boolean) => {
 const handleUpdate = async (row: CustomerDeptVO) => {
   reset();
   await getTreeselect();
-  const res = await getCustomerDept(row.id);
+  const res = await getCustomerDept(row.deptId);
   Object.assign(form.value, res.data);
   // 修正数据:如果 parentId 等于自己的 id,说明是顶级部门,将 parentId 设为 0
-  if (form.value.parentId === form.value.id) {
+  if (form.value.parentId === form.value.deptId) {
     form.value.parentId = 0;
   }
   dialog.visible = true;
@@ -288,7 +285,7 @@ const submitForm = () => {
           ...form.value,
           customerId: props.customerId
         };
-        if (form.value.id) {
+        if (form.value.deptId) {
           await updateCustomerDept(submitData);
           proxy?.$modal.msgSuccess('修改成功');
         } else {
@@ -306,12 +303,10 @@ const submitForm = () => {
 
 /** 删除按钮操作 */
 const handleDelete = async (row: CustomerDeptVO) => {
-  try {
-    await proxy?.$modal.confirm('是否确认删除名称为"' + row.deptName + '"的部门?');
-    await delCustomerDept(row.id);
-    await getList();
-    proxy?.$modal.msgSuccess('删除成功');
-  } catch {}
+  await proxy?.$modal.confirm('是否确认删除名称为"' + row.deptName + '"的数据项?');
+  await delDept(row.deptId);
+  await getList();
+  proxy?.$modal.msgSuccess('删除成功');
 };
 
 onMounted(() => {

+ 202 - 0
src/views/order/expense/index.vue

@@ -0,0 +1,202 @@
+<template>
+  <div class="p-2">
+    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+      <div v-show="showSearch" class="mb-[10px]">
+        <el-card shadow="hover">
+          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
+            <el-form-item label="单据编号" prop="orderRevenueCode">
+              <el-input v-model="queryParams.orderRevenueCode" placeholder="请输入单据编号" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="单据日期" prop="createTime">
+              <el-date-picker v-model="queryParams.createTime" placeholder="请选择单据日期" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="关键字" prop="searchValue">
+              <el-input v-model="queryParams.searchValue" placeholder="供应商名称/编号" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item>
+              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+            </el-form-item>
+          </el-form>
+        </el-card>
+      </div>
+    </transition>
+
+    <el-card shadow="never">
+      <template #header>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="22"> 费用单信息列表 </el-col>
+        </el-row>
+      </template>
+
+      <el-table v-loading="loading" border :data="revenueHeaderList" @selection-change="handleSelectionChange">
+        <el-table-column label="单据日期" align="center" prop="createTime">
+          <template #default="scope">
+            <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="单据编号" align="center" prop="orderRevenueCode" />
+        <el-table-column label="供应商" align="center" prop="supplierName" />
+        <el-table-column label="产品经理" align="center" prop="" />
+        <el-table-column label="采购员" align="center" prop="" />
+        <el-table-column label="含税金额" align="center" prop="totalAmount">
+          <template #default="scope">
+            <span>{{ Number(scope.row.totalAmount || 0).toFixed(2) }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="备注" align="center" prop="remark" />
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+          <template #default="scope">
+            <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['order:revenueHeader:edit']">编辑</el-button>
+            <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['order:revenueHeader:remove']">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+    </el-card>
+    <!-- 添加或修改收入单主对话框 -->
+  </div>
+</template>
+
+<script setup name="RevenueHeader" lang="ts">
+import { listRevenueHeader, delRevenueHeader } from '@/api/order/revenueHeader';
+import { RevenueHeaderVO, RevenueHeaderQuery, RevenueHeaderForm } from '@/api/order/revenueHeader/types';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { sys_platform_yes_no, check_status, revenue_type } = toRefs<any>(proxy?.useDict('sys_platform_yes_no', 'check_status', 'revenue_type'));
+
+const revenueHeaderList = ref<RevenueHeaderVO[]>([]);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<string | number>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const router = useRouter();
+const queryFormRef = ref<ElFormInstance>();
+const revenueHeaderFormRef = ref<ElFormInstance>();
+
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+
+const initFormData: RevenueHeaderForm = {
+  id: undefined,
+  revenueType: undefined,
+  orderRevenueCode: undefined,
+  incomeOrderCode: undefined,
+  otherRevenueType: undefined,
+  customerId: undefined,
+  supplierId: undefined,
+  isPrwTax: undefined,
+  currencyId: undefined,
+  pushStatus: undefined,
+  orderFile: undefined,
+  status: undefined,
+  remark: undefined
+};
+const data = reactive<PageData<RevenueHeaderForm, RevenueHeaderQuery>>({
+  form: { ...initFormData },
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    revenueType: '1',
+    orderRevenueCode: undefined,
+    incomeOrderCode: undefined,
+    otherRevenueType: undefined,
+    customerId: undefined,
+    supplierId: undefined,
+    isPrwTax: undefined,
+    currencyId: undefined,
+    pushStatus: undefined,
+    orderFile: undefined,
+    status: undefined,
+    platformCode: undefined,
+    params: {}
+  },
+  rules: {}
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+/** 查询收入单主列表 */
+const getList = async () => {
+  loading.value = true;
+  const res = await listRevenueHeader(queryParams.value);
+  revenueHeaderList.value = res.rows;
+  total.value = res.total;
+  loading.value = false;
+};
+
+/** 取消按钮 */
+const cancel = () => {
+  reset();
+  dialog.visible = false;
+};
+
+/** 表单重置 */
+const reset = () => {
+  form.value = { ...initFormData };
+  revenueHeaderFormRef.value?.resetFields();
+};
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.value.pageNum = 1;
+  getList();
+};
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value?.resetFields();
+  handleQuery();
+};
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection: RevenueHeaderVO[]) => {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+
+/** 修改按钮操作 */
+const handleUpdate = async (row?: RevenueHeaderVO) => {
+  reset();
+  const _id = row?.id || ids.value[0];
+  router.push({
+    path: '/order-center/order-revenue-add',
+    query: { revenueType: row.revenueType, id: _id }
+  });
+};
+
+/** 删除按钮操作 */
+const handleDelete = async (row?: RevenueHeaderVO) => {
+  const _ids = row?.id || ids.value;
+  await proxy?.$modal.confirm('是否确认删除收入单主编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
+  await delRevenueHeader(_ids);
+  proxy?.$modal.msgSuccess('删除成功');
+  await getList();
+};
+
+/** 导出按钮操作 */
+const handleExport = () => {
+  proxy?.download(
+    'order/revenueHeader/export',
+    {
+      ...queryParams.value
+    },
+    `revenueHeader_${new Date().getTime()}.xlsx`
+  );
+};
+
+onMounted(() => {
+  getList();
+});
+
+onActivated(() => {
+  getList();
+});
+</script>

+ 181 - 0
src/views/order/orderAssignment/assignmentDialog.vue

@@ -0,0 +1,181 @@
+<template>
+  <el-drawer v-model="drawer.visible" :title="drawer.title" size="500px" direction="rtl" :before-close="handleClose">
+    <div class="drawer-content">
+      <el-form ref="orderAssignmentFormRef" :model="form" :rules="rules" label-width="120px">
+        <el-form-item label="订单编号" v-if="form.orderNo">
+          <span class="form-value">{{ form.orderNo }}</span>
+        </el-form-item>
+
+        <el-form-item label="订单数量" v-if="orderCount > 1">
+          <span class="form-value">{{ orderCount }} 个订单</span>
+        </el-form-item>
+
+        <el-divider v-if="form.platformCode" />
+
+        <el-form-item label="当前平台" v-if="form.platformCode">
+          <dict-tag :options="sys_platform_code" :value="form.platformCode" />
+        </el-form-item>
+
+        <el-form-item label="分配后平台" prop="platformAfter">
+          <el-select v-model="form.platformAfter" placeholder="请选择平台" style="width: 100%" filterable clearable>
+            <el-option v-for="dict in sys_platform_code" :key="dict.value" :label="dict.label" :value="dict.value" />
+          </el-select>
+        </el-form-item>
+
+        <el-divider content-position="left">分配原因</el-divider>
+
+        <el-form-item label-width="0" prop="remark">
+          <el-input v-model="form.remark" type="textarea" :rows="6" placeholder="请输入分配原因(选填)" maxlength="500" show-word-limit />
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <template #footer>
+      <div class="drawer-footer">
+        <el-button @click="cancel">取 消</el-button>
+        <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
+      </div>
+    </template>
+  </el-drawer>
+</template>
+
+<style scoped lang="scss">
+.drawer-content {
+  padding: 0 20px 20px;
+  height: calc(100% - 60px);
+  overflow-y: auto;
+}
+
+.drawer-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+  padding: 10px 20px;
+  border-top: 1px solid #e4e7ed;
+}
+
+.form-value {
+  font-weight: 500;
+  color: #303133;
+  font-size: 14px;
+}
+
+:deep(.el-divider__text) {
+  font-weight: 600;
+  font-size: 14px;
+}
+
+:deep(.el-form-item__label) {
+  font-weight: 500;
+}
+</style>
+<script setup name="OrderAssignmentDialog" lang="ts">
+import { getOrderAssignment, addOrderAssignment, updateOrderAssignment } from '@/api/order/orderAssignmentLog';
+import { OrderAssignmentForm } from '@/api/order/orderAssignmentLog/types';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { sys_platform_code } = toRefs<any>(proxy?.useDict('sys_platform_code'));
+
+const emit = defineEmits(['success']);
+
+const buttonLoading = ref(false);
+const orderAssignmentFormRef = ref<ElFormInstance>();
+const orderCount = ref(0); // 订单数量
+
+const drawer = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+
+const initFormData: OrderAssignmentForm = {
+  id: undefined,
+  orderId: undefined,
+  orderIds: undefined,
+  orderNo: undefined,
+  platformBefore: undefined,
+  platformAfter: undefined,
+  assignedBy: undefined,
+  assignTime: undefined,
+  assignType: '0',
+  status: undefined,
+  remark: undefined
+};
+
+const data = reactive<PageData<OrderAssignmentForm, any>>({
+  form: { ...initFormData },
+  queryParams: {},
+  rules: {
+    platformAfter: [{ required: true, message: '分配后平台不能为空', trigger: 'blur' }]
+  }
+});
+
+const { form, rules } = toRefs(data);
+
+/** 打开对话框 */
+const open = async (orderIds: Array<string | number>, orderNo?: string, platformCode?: string) => {
+  reset();
+  drawer.visible = true;
+  drawer.title = orderIds.length > 1 ? '批量整单分配' : '整单分配';
+
+  form.value.orderNo = orderNo;
+  form.value.platformCode = platformCode;
+  orderCount.value = orderIds.length;
+
+  // 如果是单个订单,可以查询已有的分配信息
+  if (orderIds.length === 1) {
+    try {
+      form.value.orderIds = orderIds[0] as string;
+    } catch (error) {}
+  } else {
+    // 批量分配
+    form.value.orderIds = orderIds.join(',');
+  }
+};
+
+/** 表单重置 */
+const reset = () => {
+  form.value = { ...initFormData };
+  orderAssignmentFormRef.value?.resetFields();
+};
+
+/** 取消按钮 */
+const cancel = () => {
+  drawer.visible = false;
+  reset();
+};
+
+/** 关闭前的回调 */
+const handleClose = (done: () => void) => {
+  if (buttonLoading.value) {
+    return;
+  }
+  done();
+  reset();
+};
+
+/** 提交按钮 */
+const submitForm = () => {
+  orderAssignmentFormRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      buttonLoading.value = true;
+      try {
+        if (form.value.id) {
+          await updateOrderAssignment(form.value);
+          proxy?.$modal.msgSuccess('修改成功');
+        } else {
+          await addOrderAssignment(form.value);
+          proxy?.$modal.msgSuccess('分配成功');
+        }
+        drawer.visible = false;
+        emit('success');
+      } finally {
+        buttonLoading.value = false;
+      }
+    }
+  });
+};
+
+defineExpose({
+  open
+});
+</script>

+ 337 - 0
src/views/order/orderAssignment/index.vue

@@ -0,0 +1,337 @@
+<template>
+  <div class="p-2">
+    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+      <div v-show="showSearch" class="mb-[10px]">
+        <el-card shadow="hover">
+          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
+            <el-form-item label="订单编号" prop="orderNo">
+              <el-input v-model="queryParams.orderNo" placeholder="请输入订单编号" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="客户编号" prop="customerCode">
+              <el-input v-model="queryParams.customerCode" placeholder="请输入客户编号" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="客户名称" prop="customerName">
+              <el-input v-model="queryParams.customerName" placeholder="请输入客户名称" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="订单来源" prop="orderSource">
+              <el-select v-model="queryParams.orderSource" placeholder="请选择订单来源" clearable>
+                <el-option v-for="dict in order_source" :key="dict.value" :label="dict.label" :value="dict.value" />
+              </el-select>
+            </el-form-item>
+            <!-- <el-form-item label="订单状态" prop="orderStatus">
+              <el-select v-model="queryParams.orderStatus" placeholder="请选择订单状态" clearable>
+                <el-option v-for="dict in order_status" :key="dict.value" :label="dict.label" :value="dict.value" />
+              </el-select>
+            </el-form-item> -->
+
+            <el-form-item label="提交时间" prop="dateRange">
+              <el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" />
+            </el-form-item>
+
+            <el-form-item>
+              <el-button type="primary" icon="Search" @click="handleQuery()">搜索</el-button>
+              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+            </el-form-item>
+          </el-form>
+        </el-card>
+      </div>
+    </transition>
+
+    <el-card shadow="never">
+      <template #header>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="18"> 订单分配列表 </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" :disabled="!ids.length" plain @click="handleAssignment(null)">批量整单分配</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" :disabled="!ids.length" plain>关闭订单</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" :disabled="!ids.length" plain>删除订单</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" :disabled="!ids.length" plain>导出订单</el-button>
+          </el-col>
+        </el-row>
+      </template>
+
+      <el-table v-loading="loading" border :data="orderMainList" @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="订单时间" align="center" prop="orderTime" />
+        <el-table-column label="订单编号" align="center" prop="orderNo" />
+        <el-table-column label="客户编号" align="center" prop="customerCode" />
+        <el-table-column label="订单总金额" align="center" prop="totalAmount" />
+        <el-table-column label="支付方式" align="center" prop="payType">
+          <template #default="scope">
+            <dict-tag :options="pay_method" :value="scope.row.payType" />
+          </template>
+        </el-table-column>
+        <el-table-column label="业务员" align="center" prop="businessStaff" />
+        <el-table-column label="客服" align="center" prop="customerService" />
+        <el-table-column label="归属部门" align="center" prop="businessDept" />
+        <el-table-column label="订单来源" align="center" prop="orderSource">
+          <template #default="scope">
+            <dict-tag :options="order_source" :value="scope.row.orderSource" />
+          </template>
+        </el-table-column>
+        <el-table-column label="分配状态" align="center" prop="assignmentStatus">
+          <template #default="scope">
+            <dict-tag :options="order_assignment_status" :value="scope.row.assignmentStatus" />
+          </template>
+        </el-table-column>
+        <el-table-column label="当前平台" align="center" prop="platformCode">
+          <template #default="scope">
+            <dict-tag :options="sys_platform_code" :value="scope.row.platformCode" />
+          </template>
+        </el-table-column>
+
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="180">
+          <template #default="scope">
+            <el-button link type="primary" @click="handleReview(scope.row)">查看</el-button>
+            <el-button
+              link
+              type="primary"
+              v-if="scope.row.checkStatus == '1' && scope.row.assignmentStatus == '0'"
+              @click="handleAssignment(scope.row)"
+              >订单分配</el-button
+            >
+            <el-button
+              link
+              type="primary"
+              v-if="scope.row.checkStatus == '1' && scope.row.assignmentStatus == '1'"
+              @click="handleAssignment(scope.row)"
+              >重新分配</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+    </el-card>
+
+    <!-- 订单分配对话框 -->
+    <assignment-dialog ref="assignmentDialogRef" @success="getList" />
+    <!-- 拆单分配对话框 -->
+    <split-assign-dialog ref="splitAssignDialogRef" @success="getList" />
+  </div>
+</template>
+
+<script setup name="OrderAssignment" lang="ts">
+import { listOrderAssignment, getOrderMain, delOrderMain } from '@/api/order/orderMain';
+import { OrderMainVO, OrderMainQuery, OrderMainForm } from '@/api/order/orderMain/types';
+import AssignmentDialog from './assignmentDialog.vue';
+import SplitAssignDialog from './splitAssignDialog.vue';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { order_assignment_status, order_check_status, pay_method, order_source, sys_platform_code } = toRefs<any>(
+  proxy?.useDict('order_assignment_status', 'order_check_status', 'pay_method', 'order_source', 'sys_platform_code')
+);
+
+const orderMainList = ref<OrderMainVO[]>([]);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<string | number>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const router = useRouter();
+const queryFormRef = ref<ElFormInstance>();
+const orderMainFormRef = ref<ElFormInstance>();
+const assignmentDialogRef = ref<InstanceType<typeof AssignmentDialog>>();
+const splitAssignDialogRef = ref<InstanceType<typeof SplitAssignDialog>>();
+
+const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+
+const initFormData: OrderMainForm = {
+  id: undefined,
+  orderNo: undefined,
+  shipmentNo: undefined,
+  subOrderNo: undefined,
+  companyId: undefined,
+  customerId: undefined,
+  customerCode: undefined,
+  userId: undefined,
+  shippingAddressId: undefined,
+  purchaseReason: undefined,
+  invoiceType: undefined,
+  payType: undefined,
+  warehouseId: undefined,
+  creditLimit: undefined,
+  expectedDeliveryTime: undefined,
+  businessStaff: undefined,
+  customerService: undefined,
+  businessDept: undefined,
+  userDept: undefined,
+  productQuantity: undefined,
+  shippingFee: undefined,
+  totalAmount: undefined,
+  payableAmount: undefined,
+  paymentStatus: undefined,
+  orderSource: undefined,
+  orderStatus: undefined,
+  orderTime: undefined,
+  confirmTime: undefined,
+  shippingTime: undefined,
+  receivingTime: undefined,
+  shippedQuantity: undefined,
+  unshippedQuantity: undefined,
+  packageCount: undefined,
+  signedQuantity: undefined,
+  afterSaleCompleted: undefined,
+  afterSalePending: undefined,
+  deliveryDesc: undefined,
+  pushStatus: undefined,
+  attachmentPath: undefined,
+  deliveryType: undefined,
+  orderCategory: undefined,
+  productCode: undefined,
+  cancelReason: undefined,
+  expenseType: undefined,
+  userNo: undefined,
+  status: undefined,
+  remark: undefined,
+  isSplitChild: undefined,
+  orderProductBos: [],
+  customerSalesInfoVo: {}
+};
+const data = reactive<PageData<OrderMainForm, OrderMainQuery>>({
+  form: { ...initFormData },
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    checkStatus: '1',
+    orderNo: undefined,
+    shipmentNo: undefined,
+    subOrderNo: undefined,
+    companyId: undefined,
+    customerCode: undefined,
+    customerId: undefined,
+    userId: undefined,
+    payType: undefined,
+    warehouseId: undefined,
+    expectedDeliveryTime: undefined,
+    businessStaff: undefined,
+    customerService: undefined,
+    businessDept: undefined,
+    productQuantity: undefined,
+    totalAmount: undefined,
+    payableAmount: undefined,
+    paymentStatus: undefined,
+    orderSource: undefined,
+    orderStatus: undefined,
+    orderTime: undefined,
+    confirmTime: undefined,
+    status: undefined,
+    isSplitChild: '1',
+    params: {}
+  },
+  rules: {}
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+/** 查询订单主信息列表 */
+const getList = async () => {
+  loading.value = true;
+  const res = await listOrderAssignment(proxy?.addDateRange(queryParams.value, dateRange.value));
+  orderMainList.value = res.rows;
+  total.value = res.total;
+  loading.value = false;
+};
+
+/** 取消按钮 */
+const cancel = () => {
+  reset();
+  dialog.visible = false;
+};
+
+/** 表单重置 */
+const reset = () => {
+  form.value = { ...initFormData };
+  orderMainFormRef.value?.resetFields();
+};
+
+/** 搜索按钮操作 */
+const handleQuery = (orderStatus?: string) => {
+  if (orderStatus) {
+    queryParams.value.orderStatus = orderStatus;
+  } else {
+    queryParams.value.orderStatus = undefined;
+  }
+  queryParams.value.pageNum = 1;
+  getList();
+};
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  dateRange.value = ['', ''];
+  queryFormRef.value?.resetFields();
+  handleQuery();
+};
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection: OrderMainVO[]) => {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+
+const handleReview = (row?: OrderMainVO) => {
+  router.push({
+    path: '/order-manage/order-sendDetail',
+    query: { id: row.id }
+  });
+};
+
+/** 订单分配按钮操作 */
+const handleAssignment = async (row?: OrderMainVO | null) => {
+  let orderIds: Array<string | number>;
+
+  if (row) {
+    // 单个订单分配 - 直接打开统一的分配抽屉
+    splitAssignDialogRef.value?.open(row.id);
+  } else {
+    // 批量分配 - 只支持整单分配
+    if (!ids.value || ids.value.length === 0) {
+      proxy?.$modal.msgWarning('请选择要分配的订单');
+      return;
+    }
+    orderIds = ids.value;
+    assignmentDialogRef.value?.open(orderIds, undefined, undefined);
+  }
+};
+
+/** 删除按钮操作 */
+const handleDelete = async (row?: OrderMainVO) => {
+  const _ids = row?.id || ids.value;
+  await proxy?.$modal.confirm('是否确认删除订单主信息编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
+  await delOrderMain(_ids);
+  proxy?.$modal.msgSuccess('删除成功');
+  await getList();
+};
+
+/** 导出按钮操作 */
+const handleExport = () => {
+  proxy?.download(
+    'order/orderMain/export',
+    {
+      ...queryParams.value
+    },
+    `orderMain_${new Date().getTime()}.xlsx`
+  );
+};
+
+onMounted(() => {
+  getList();
+});
+
+onActivated(() => {
+  getList();
+});
+</script>

+ 328 - 0
src/views/order/orderAssignment/splitAssignDialog.vue

@@ -0,0 +1,328 @@
+<template>
+  <el-drawer v-model="drawer.visible" :title="drawer.title" size="70%" direction="rtl" :before-close="handleClose">
+    <div class="drawer-content">
+      <!-- 分配方式选择 -->
+      <div class="assign-type-selector">
+        <el-radio-group v-model="assignType" @change="handleAssignTypeChange">
+          <el-radio-button value="whole">整单分配</el-radio-button>
+          <el-radio-button value="split">拆单分配</el-radio-button>
+        </el-radio-group>
+      </div>
+
+      <el-divider />
+
+      <!-- 整单分配表单 -->
+      <div v-show="assignType === 'whole'" class="whole-assign-form">
+        <el-form ref="wholeAssignFormRef" :model="wholeForm" :rules="wholeRules" label-width="120px">
+          <el-form-item label="订单编号" v-if="orderInfo.orderNo">
+            <span class="form-value">{{ orderInfo.orderNo }}</span>
+          </el-form-item>
+
+          <el-form-item label="当前平台" v-if="orderInfo.platformCode">
+            <dict-tag :options="sys_platform_code" :value="orderInfo.platformCode" />
+          </el-form-item>
+
+          <el-form-item label="分配后平台" prop="platformAfter">
+            <el-select v-model="wholeForm.platformAfter" placeholder="请选择平台" style="width: 100%" filterable clearable>
+              <el-option v-for="dict in sys_platform_code" :key="dict.value" :label="dict.label" :value="dict.value" />
+            </el-select>
+          </el-form-item>
+
+          <el-divider content-position="left">分配原因</el-divider>
+
+          <el-form-item label-width="0" prop="remark">
+            <el-input v-model="wholeForm.remark" type="textarea" :rows="6" placeholder="请输入分配原因(选填)" maxlength="500" show-word-limit />
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <!-- 拆单分配表单 -->
+      <div v-show="assignType === 'split'" class="split-assign-form">
+        <el-form ref="splitAssignFormRef" :model="form" label-width="100px">
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="订单编号">
+                <span class="form-value">{{ orderInfo.orderNo }}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="当前平台">
+                <dict-tag :options="sys_platform_code" :value="orderInfo.platformCode" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-divider content-position="left">商品列表</el-divider>
+
+          <el-form-item label-width="0">
+            <el-table :data="form.productList" border style="width: 100%" max-height="500">
+              <el-table-column type="index" label="序号" width="60" align="center" />
+              <el-table-column label="商品图片" width="100" align="center">
+                <template #default="scope">
+                  <el-image
+                    v-if="scope.row.productImage"
+                    :src="scope.row.productImage"
+                    style="width: 60px; height: 60px"
+                    fit="cover"
+                    :preview-src-list="[scope.row.productImage]"
+                  />
+                  <span v-else style="color: #999">暂无图片</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="商品编号" prop="productNo" width="140" align="center" />
+              <el-table-column label="商品名称" prop="productName" show-overflow-tooltip />
+              <el-table-column label="数量" prop="orderQuantity" width="100" align="center" />
+              <el-table-column label="单价" prop="orderPrice" width="120" align="center">
+                <template #default="scope">
+                  <span>¥{{ scope.row.orderPrice }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="小计" width="120" align="center">
+                <template #default="scope">
+                  <span>¥{{ (scope.row.orderPrice * scope.row.orderQuantity).toFixed(2) }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="分配平台" align="center" fixed="right">
+                <template #default="scope">
+                  <el-select v-model="scope.row.targetPlatform" placeholder="请选择平台" style="width: 100%">
+                    <el-option v-for="dict in sys_platform_code" :key="dict.value" :label="dict.label" :value="dict.value" />
+                  </el-select>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-form-item>
+
+          <el-divider content-position="left">分配原因</el-divider>
+
+          <el-form-item label-width="0" prop="remark">
+            <el-input v-model="form.remark" type="textarea" :rows="4" placeholder="请输入分配原因(选填)" maxlength="500" show-word-limit />
+          </el-form-item>
+        </el-form>
+      </div>
+    </div>
+
+    <template #footer>
+      <div class="drawer-footer">
+        <el-button @click="cancel">取 消</el-button>
+        <el-button v-if="assignType === 'whole'" :loading="buttonLoading" type="primary" @click="submitWholeForm">确 定</el-button>
+        <el-button v-else :loading="buttonLoading" type="primary" @click="submitSplitForm">确 定</el-button>
+      </div>
+    </template>
+  </el-drawer>
+</template>
+
+<style scoped lang="scss">
+.drawer-content {
+  padding: 0 20px 20px;
+  height: calc(100% - 60px);
+  overflow-y: auto;
+}
+
+.assign-type-selector {
+  display: flex;
+  justify-content: center;
+  padding: 10px 0;
+
+  :deep(.el-radio-button__inner) {
+    padding: 12px 30px;
+    font-size: 14px;
+  }
+}
+
+.drawer-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+  padding: 10px 20px;
+  border-top: 1px solid #e4e7ed;
+}
+
+.form-value {
+  font-weight: 500;
+  color: #303133;
+}
+
+:deep(.el-divider__text) {
+  font-weight: 600;
+  font-size: 14px;
+}
+</style>
+
+<script setup name="SplitAssignDialog" lang="ts">
+import { getOrderMain } from '@/api/order/orderMain';
+import { addOrderSplitAssign, addOrderAssignment } from '@/api/order/orderAssignmentLog';
+import { OrderSplitAssignForm, OrderProductAssignRule, OrderAssignmentForm } from '@/api/order/orderAssignmentLog/types';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { sys_platform_code } = toRefs<any>(proxy?.useDict('sys_platform_code'));
+
+const emit = defineEmits(['success']);
+
+const buttonLoading = ref(false);
+const splitAssignFormRef = ref<ElFormInstance>();
+const wholeAssignFormRef = ref<ElFormInstance>();
+
+// 分配类型:whole-整单分配,split-拆单分配
+const assignType = ref<'whole' | 'split'>('whole');
+
+const drawer = reactive<DialogOption>({
+  visible: false,
+  title: '订单分配'
+});
+
+const orderInfo = ref<any>({
+  orderNo: '',
+  id: undefined,
+  platformCode: ''
+});
+
+// 拆单分配表单
+const form = reactive({
+  productList: [] as any[],
+  remark: ''
+});
+
+// 整单分配表单
+const wholeForm = reactive({
+  platformAfter: '',
+  remark: ''
+});
+
+const wholeRules = {
+  platformAfter: [{ required: true, message: '分配后平台不能为空', trigger: 'blur' }]
+};
+
+/** 打开对话框 */
+const open = async (orderId: string | number) => {
+  reset();
+  drawer.visible = true;
+  assignType.value = 'whole'; // 默认显示整单分配
+
+  try {
+    // 获取订单详情
+    const res = await getOrderMain(orderId);
+    orderInfo.value = {
+      orderNo: res.data.orderNo,
+      id: res.data.id,
+      platformCode: res.data.platformCode
+    };
+
+    // 加载订单商品列表(用于拆单分配)
+    if (res.data.orderProductList && res.data.orderProductList.length > 0) {
+      form.productList = res.data.orderProductList.map((item: any) => ({
+        ...item,
+        itemId: item.id, // 商品行ID
+        targetPlatform: '' // 初始化分配平台为空
+      }));
+    }
+  } catch (error) {
+    proxy?.$modal.msgError('获取订单信息失败');
+    drawer.visible = false;
+  }
+};
+
+/** 分配类型切换 */
+const handleAssignTypeChange = (value: 'whole' | 'split') => {
+  // 切换时可以做一些清理工作
+  if (value === 'split' && form.productList.length === 0) {
+    proxy?.$modal.msgWarning('该订单没有商品信息,无法进行拆单分配');
+    assignType.value = 'whole';
+  }
+};
+
+/** 表单重置 */
+const reset = () => {
+  form.productList = [];
+  form.remark = '';
+  wholeForm.platformAfter = '';
+  wholeForm.remark = '';
+  assignType.value = 'whole';
+  orderInfo.value = {
+    orderNo: '',
+    id: undefined,
+    platformCode: ''
+  };
+  splitAssignFormRef.value?.resetFields();
+  wholeAssignFormRef.value?.resetFields();
+};
+
+/** 取消按钮 */
+const cancel = () => {
+  drawer.visible = false;
+  reset();
+};
+
+/** 关闭前的回调 */
+const handleClose = (done: () => void) => {
+  if (buttonLoading.value) {
+    return;
+  }
+  done();
+  reset();
+};
+
+/** 提交整单分配 */
+const submitWholeForm = async () => {
+  wholeAssignFormRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      buttonLoading.value = true;
+      try {
+        const submitData: OrderAssignmentForm = {
+          orderIds: orderInfo.value.id,
+          platformAfter: wholeForm.platformAfter,
+          assignType: '0', // 整单分配
+          remark: wholeForm.remark
+        };
+
+        await addOrderAssignment(submitData);
+        proxy?.$modal.msgSuccess('整单分配成功');
+        drawer.visible = false;
+        emit('success');
+      } catch (error) {
+        proxy?.$modal.msgError('整单分配失败');
+      } finally {
+        buttonLoading.value = false;
+      }
+    }
+  });
+};
+
+/** 提交拆单分配 */
+const submitSplitForm = async () => {
+  // 验证每个商品都选择了平台
+  const unassignedProducts = form.productList.filter((item) => !item.targetPlatform);
+  if (unassignedProducts.length > 0) {
+    proxy?.$modal.msgWarning('请为所有商品选择分配平台');
+    return;
+  }
+
+  buttonLoading.value = true;
+  try {
+    // 组装数据结构
+    const submitData: OrderSplitAssignForm = {
+      orderId: orderInfo.value.id,
+      itemRules: form.productList.map(
+        (product): OrderProductAssignRule => ({
+          itemId: product.itemId,
+          targetPlatform: product.targetPlatform
+        })
+      ),
+      remark: form.remark
+    };
+
+    // 调用拆单分配接口
+    await addOrderSplitAssign(submitData);
+    proxy?.$modal.msgSuccess('拆单分配成功');
+    drawer.visible = false;
+    emit('success');
+  } catch (error) {
+    proxy?.$modal.msgError('拆单分配失败');
+  } finally {
+    buttonLoading.value = false;
+  }
+};
+
+defineExpose({
+  open
+});
+</script>

+ 369 - 0
src/views/order/orderDeliver/index.vue

@@ -0,0 +1,369 @@
+<template>
+  <div class="p-2">
+    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+      <div v-show="showSearch" class="mb-[10px]">
+        <el-card shadow="hover">
+          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
+            <el-form-item label="订单编号" prop="orderNo">
+              <el-input v-model="queryParams.orderNo" placeholder="请输入订单编号" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="客户编号" prop="customerCode">
+              <el-input v-model="queryParams.customerCode" placeholder="请输入客户编号" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="客户名称" prop="customerName">
+              <el-input v-model="queryParams.customerName" placeholder="请输入客户名称" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="订单来源" prop="orderSource">
+              <el-select v-model="queryParams.orderSource" placeholder="请选择订单来源" clearable>
+                <el-option v-for="dict in order_source" :key="dict.value" :label="dict.label" :value="dict.value" />
+              </el-select>
+            </el-form-item>
+            <!-- <el-form-item label="订单状态" prop="orderStatus">
+              <el-select v-model="queryParams.orderStatus" placeholder="请选择订单状态" clearable>
+                <el-option v-for="dict in order_status" :key="dict.value" :label="dict.label" :value="dict.value" />
+              </el-select>
+            </el-form-item> -->
+            <el-form-item label="业务员" prop="">
+              <el-select v-model="queryParams.orderStatus" placeholder="请选择业务员" clearable> </el-select>
+            </el-form-item>
+            <el-form-item label="部门" prop="">
+              <el-select v-model="queryParams.orderStatus" placeholder="请选择部门" clearable> </el-select>
+            </el-form-item>
+            <el-form-item label="提交时间" prop="createTime">
+              <el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" />
+            </el-form-item>
+            <el-form-item>
+              <el-button type="primary" icon="Search" @click="handleQuery()">搜索</el-button>
+              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+            </el-form-item>
+          </el-form>
+        </el-card>
+      </div>
+    </transition>
+
+    <el-card shadow="never">
+      <template #header>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="19"> 发货单信息列表 </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" plain>关闭订单</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" plain>删除订单</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" plain>导出订单</el-button>
+          </el-col>
+        </el-row>
+      </template>
+
+      <el-table v-loading="loading" border :data="orderMainList" @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="发货单编号" align="center" prop="deliverCode" />
+        <el-table-column label="订单编号" align="center" prop="orderNo" />
+        <el-table-column label="客户名称" align="center" prop="customerName" />
+        <el-table-column label="发货时间" align="center" prop="deliverTime" />
+        <el-table-column label="签收时间" align="center" prop="deliverTime" />
+        <el-table-column label="发货方式" align="center" prop="deliverMethod">
+          <template #default="scope">
+            <dict-tag :options="deliver_method" :value="scope.row.deliverMethod" />
+          </template>
+        </el-table-column>
+        <el-table-column label="包裹状态" align="center" prop="orderStatus">
+          <template #default="scope">
+            <dict-tag :options="order_status" :value="scope.row.orderStatus" />
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+          <template #default="scope">
+            <el-button link type="primary" @click="handleDeliver(scope.row)">发货</el-button>
+            <el-button link type="primary" @click="handleReview(scope.row)">查看发货信息</el-button>
+            <el-button link type="primary">取消订单</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+    </el-card>
+
+    <!-- 发货对话框 -->
+    <DeliverDialog v-model="showDeliverDialog" :order-id="currentOrderId" :order-no="currentOrderNo" @success="handleDeliverSuccess" />
+  </div>
+</template>
+
+<script setup name="OrderMain" lang="ts">
+import { listOrderMain, getOrderMain, delOrderMain, addOrderMain, updateOrderMain, queryOrderStatusStats } from '@/api/order/orderMain';
+import { OrderMainVO, OrderMainQuery, OrderMainForm } from '@/api/order/orderMain/types';
+import DeliverDialog from '../saleOrder/deliverDialog.vue';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { order_status, fee_type, pay_method, order_source, deliver_method } = toRefs<any>(
+  proxy?.useDict('order_status', 'fee_type', 'pay_method', 'order_source', 'deliver_method')
+);
+
+const orderMainList = ref<OrderMainVO[]>([]);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<string | number>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const router = useRouter();
+const queryFormRef = ref<ElFormInstance>();
+const orderMainFormRef = ref<ElFormInstance>();
+const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
+
+// 发货对话框
+const showDeliverDialog = ref(false);
+const currentOrderId = ref<string | number>();
+const currentOrderNo = ref<string>();
+
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+
+const orderStatusStats = ref({
+  pendingPaymentCount: 0, // 待支付
+  pendingShipmentCount: 0, // 待发货
+  shippedCount: 0, // 已发货(发货完成)
+  completedCount: 0, // 已完成
+  closedCount: 0, // 已关闭
+  totalCount: 0 // 全部订单
+});
+
+const initFormData: OrderMainForm = {
+  id: undefined,
+  orderNo: undefined,
+  isSplitChild: undefined,
+  shipmentNo: undefined,
+  subOrderNo: undefined,
+  companyId: undefined,
+  customerId: undefined,
+  customerCode: undefined,
+  userId: undefined,
+  shippingAddressId: undefined,
+  purchaseReason: undefined,
+  invoiceType: undefined,
+  payType: undefined,
+  warehouseId: undefined,
+  creditLimit: undefined,
+  expectedDeliveryTime: undefined,
+  businessStaff: undefined,
+  customerService: undefined,
+  businessDept: undefined,
+  userDept: undefined,
+  productQuantity: undefined,
+  shippingFee: undefined,
+  totalAmount: undefined,
+  payableAmount: undefined,
+  paymentStatus: undefined,
+  orderSource: undefined,
+  orderStatus: undefined,
+  orderTime: undefined,
+  confirmTime: undefined,
+  shippingTime: undefined,
+  receivingTime: undefined,
+  shippedQuantity: undefined,
+  unshippedQuantity: undefined,
+  packageCount: undefined,
+  signedQuantity: undefined,
+  afterSaleCompleted: undefined,
+  afterSalePending: undefined,
+  deliveryDesc: undefined,
+  pushStatus: undefined,
+  attachmentPath: undefined,
+  deliveryType: undefined,
+  orderCategory: undefined,
+  productCode: undefined,
+  cancelReason: undefined,
+  expenseType: undefined,
+  userNo: undefined,
+  status: undefined,
+  remark: undefined,
+  orderProductBos: [],
+  customerSalesInfoVo: {}
+};
+const data = reactive<PageData<OrderMainForm, OrderMainQuery>>({
+  form: { ...initFormData },
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    orderNo: undefined,
+    shipmentNo: undefined,
+    subOrderNo: undefined,
+    companyId: undefined,
+    customerCode: undefined,
+    customerId: undefined,
+    userId: undefined,
+    purchaseReason: undefined,
+    invoiceType: undefined,
+    payType: undefined,
+    warehouseId: undefined,
+    creditLimit: undefined,
+    expectedDeliveryTime: undefined,
+    businessStaff: undefined,
+    customerService: undefined,
+    businessDept: undefined,
+    userDept: undefined,
+    paymentStatus: undefined,
+    orderSource: undefined,
+    orderStatus: undefined,
+    orderStatuses: '2,3',
+    orderTime: undefined,
+    confirmTime: undefined,
+    shippingTime: undefined,
+    receivingTime: undefined,
+    deliveryType: undefined,
+    orderCategory: undefined,
+    productCode: undefined,
+    expenseType: undefined,
+    status: undefined,
+    platformCode: undefined,
+    params: {}
+  },
+  rules: {
+    customerId: [{ required: true, message: '客户ID不能为空', trigger: 'blur' }],
+    payType: [{ required: true, message: '支付方式不能为空', trigger: 'change' }],
+    warehouseId: [{ required: true, message: '发货仓库不能为空', trigger: 'change' }],
+    expectedDeliveryTime: [{ required: true, message: '预计送达时间不能为空', trigger: 'blur' }],
+    shippingFee: [{ required: true, message: '运费不能为空', trigger: 'blur' }],
+    confirmTime: [{ required: true, message: '确认时间不能为空', trigger: 'blur' }],
+    shippingTime: [{ required: true, message: '发货时间不能为空', trigger: 'blur' }],
+    receivingTime: [{ required: true, message: '收货时间不能为空', trigger: 'blur' }],
+    cancelReason: [{ required: true, message: '取消或异常原因不能为空', trigger: 'blur' }],
+    expenseType: [{ required: true, message: '费用类型不能为空', trigger: 'change' }]
+  }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+/** 查询订单主信息列表 */
+const getList = async () => {
+  loading.value = true;
+  const res = await listOrderMain(proxy?.addDateRange(queryParams.value, dateRange.value));
+  orderMainList.value = res.rows;
+  total.value = res.total;
+  loading.value = false;
+  queryOrderStatusStatsMethod();
+};
+
+const queryOrderStatusStatsMethod = async () => {
+  const res = await queryOrderStatusStats();
+  orderStatusStats.value = res as any;
+};
+
+/** 取消按钮 */
+const cancel = () => {
+  reset();
+  dialog.visible = false;
+};
+
+/** 表单重置 */
+const reset = () => {
+  form.value = { ...initFormData };
+  orderMainFormRef.value?.resetFields();
+};
+
+/** 搜索按钮操作 */
+const handleQuery = (orderStatus?: string) => {
+  if (orderStatus) {
+    queryParams.value.orderStatus = orderStatus;
+  } else {
+    queryParams.value.orderStatus = undefined;
+  }
+  queryParams.value.pageNum = 1;
+  getList();
+};
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  dateRange.value = ['', ''];
+  queryFormRef.value?.resetFields();
+  handleQuery();
+};
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection: OrderMainVO[]) => {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+
+const handleReview = (row?: OrderMainVO) => {
+  router.push({
+    path: '/order-manage/order-sendDetail',
+    query: { id: row.id }
+  });
+};
+
+/** 发货按钮操作 */
+const handleDeliver = (row?: OrderMainVO) => {
+  if (!row?.id) {
+    proxy?.$modal.msgWarning('订单ID不能为空');
+    return;
+  }
+  currentOrderId.value = row.id;
+  currentOrderNo.value = row.orderNo;
+  showDeliverDialog.value = true;
+};
+
+/** 发货成功回调 */
+const handleDeliverSuccess = () => {};
+
+/** 修改按钮操作 */
+const handleUpdate = async (row?: OrderMainVO) => {
+  reset();
+  const _id = row?.id || ids.value[0];
+  const res = await getOrderMain(_id);
+  Object.assign(form.value, res.data);
+  dialog.visible = true;
+  dialog.title = '修改订单主信息';
+};
+
+/** 提交按钮 */
+const submitForm = () => {
+  orderMainFormRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      buttonLoading.value = true;
+      if (form.value.id) {
+        await updateOrderMain(form.value).finally(() => (buttonLoading.value = false));
+      } else {
+        await addOrderMain(form.value).finally(() => (buttonLoading.value = false));
+      }
+      proxy?.$modal.msgSuccess('操作成功');
+      dialog.visible = false;
+      await getList();
+    }
+  });
+};
+
+/** 删除按钮操作 */
+const handleDelete = async (row?: OrderMainVO) => {
+  const _ids = row?.id || ids.value;
+  await proxy?.$modal.confirm('是否确认删除订单主信息编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
+  await delOrderMain(_ids);
+  proxy?.$modal.msgSuccess('删除成功');
+  await getList();
+};
+
+/** 导出按钮操作 */
+const handleExport = () => {
+  proxy?.download(
+    'order/orderMain/export',
+    {
+      ...queryParams.value
+    },
+    `orderMain_${new Date().getTime()}.xlsx`
+  );
+};
+
+onMounted(() => {
+  getList();
+});
+
+onActivated(() => {
+  getList();
+});
+</script>

+ 130 - 0
src/views/order/orderInquiry/index.vue

@@ -0,0 +1,130 @@
+<template>
+  <div class="p-2">
+    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+      <div v-show="showSearch" class="mb-[10px]">
+        <el-card shadow="hover">
+          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
+            <el-form-item label="订单编号" prop="">
+              <el-input placeholder="请输入订单编号" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="状态">
+              <el-select placeholder="请选择状态" clearable>
+                <!-- <el-option v-for="dict in order_status" :key="dict.value" :label="dict.label" :value="dict.value" /> -->
+              </el-select>
+            </el-form-item>
+            <el-form-item label="提报部门" prop="">
+              <el-select placeholder="请选择提报部门" clearable>
+                <!-- <el-option v-for="dict in order_status" :key="dict.value" :label="dict.label" :value="dict.value" /> -->
+              </el-select>
+            </el-form-item>
+            <el-form-item label="提交时间" prop="orderTime">
+              <el-date-picker type="daterange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" />
+            </el-form-item>
+            <el-form-item>
+              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+            </el-form-item>
+          </el-form>
+        </el-card>
+      </div>
+    </transition>
+
+    <el-card shadow="never">
+      <template #header>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="22"> 询价单管理信息列表 </el-col>
+        </el-row>
+      </template>
+
+      <el-table v-loading="loading" border :data="orderInquiryList" @selection-change="handleSelectionChange">
+        <el-table-column label="订单编号" align="center" prop="" />
+        <el-table-column label="类型" align="center" prop="" />
+        <el-table-column label="公司名称" align="center" prop="" />
+        <el-table-column label="公司名称" align="center" prop="" />
+        <el-table-column label="提交时间" align="center" prop="createTime">
+          <template #default="scope">
+            <span>{{ parseTime(scope.row.createTime) }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="需求报价时间" align="center">
+          <!-- <template #default="scope">
+             <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
+          </template> -->
+        </el-table-column>
+        <el-table-column label="报价时间" align="center">
+          <!-- <template #default="scope">
+             <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
+          </template> -->
+        </el-table-column>
+        <el-table-column label="报价负责人" align="center" prop="supplierName" />
+        <el-table-column label="订单状态" align="center" prop="" />
+
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+          <!-- <template #default="scope">
+            <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['order:orderInquiry:edit']">编辑</el-button>
+          </template> -->
+        </el-table-column>
+      </el-table>
+
+      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+    </el-card>
+  </div>
+</template>
+
+<script setup name="OrderInquiry" lang="ts">
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { sys_platform_yes_no, check_status, revenue_type } = toRefs<any>(proxy?.useDict('sys_platform_yes_no', 'check_status', 'revenue_type'));
+
+const orderInquiryList = ref<[]>([]);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<string | number>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const router = useRouter();
+const queryFormRef = ref<ElFormInstance>();
+const queryParams = reactive<any>({
+  pageNum: 1,
+  pageSize: 10
+});
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+
+/** 表单重置 */
+const reset = () => {};
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.value.pageNum = 1;
+  getList();
+};
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value?.resetFields();
+  handleQuery();
+};
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection: any[]) => {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+const getList = () => {
+  loading.value = true;
+  setTimeout(() => {
+    loading.value = false;
+  }, 1000);
+};
+
+onMounted(() => {
+  getList();
+});
+
+onActivated(() => {});
+</script>

+ 168 - 0
src/views/order/orderMain/components/addressDialog.vue

@@ -0,0 +1,168 @@
+<template>
+  <el-dialog v-model="dialogVisible" title="添加收货地址" width="650px" @close="handleClose">
+    <el-form ref="formRef" :model="form" :rules="rules" label-width="110px">
+      <el-form-item label="收货人" prop="consignee">
+        <el-input v-model="form.consignee" placeholder="请输入收货人姓名" />
+      </el-form-item>
+      <el-form-item label="部门名称" prop="deptName">
+        <el-input v-model="form.deptName" placeholder="请输入部门名称" />
+      </el-form-item>
+      <el-form-item label="手机号码" prop="phone">
+        <el-input v-model="form.phone" placeholder="请输入联系电话" />
+      </el-form-item>
+      <el-form-item label="邮政编码" prop="postal">
+        <el-input v-model="form.postal" placeholder="请输入邮政编码" />
+      </el-form-item>
+      <el-form-item label="详细地址" prop="provincialCityCountry">
+        <el-cascader v-model="codeArr" :options="regionData" placeholder="请选择" @change="handleRegionChange" style="width: 100%" />
+      </el-form-item>
+      <el-form-item prop="address">
+        <el-input v-model="form.address" type="textarea" placeholder="请输入详细地址" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button :loading="submitLoading" type="primary" @click="handleSubmit">确 定</el-button>
+        <el-button @click="handleClose">取 消</el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { ref, watch, getCurrentInstance } from 'vue';
+import { addShippingAddress } from '@/api/customer/customerFile/shippingAddress';
+import { ShippingAddressForm } from '@/api/customer/customerFile/shippingAddress/types';
+import { regionData } from 'element-china-area-data';
+import type { FormInstance, FormRules } from 'element-plus';
+
+interface Props {
+  modelValue: boolean;
+  customerId?: string | number;
+}
+
+interface Emits {
+  (e: 'update:modelValue', value: boolean): void;
+  (e: 'success'): void;
+}
+
+const props = defineProps<Props>();
+const emit = defineEmits<Emits>();
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+
+const dialogVisible = ref(false);
+const formRef = ref<FormInstance>();
+const submitLoading = ref(false);
+const codeArr = ref<string[]>([]);
+
+const initForm: ShippingAddressForm = {
+  customerId: undefined,
+  consignee: undefined,
+  deptName: undefined,
+  phone: undefined,
+  address: undefined,
+  postal: undefined,
+  provincialNo: undefined,
+  cityNo: undefined,
+  countryNo: undefined,
+  provincialCityCountry: undefined
+};
+
+const form = ref<ShippingAddressForm>({ ...initForm });
+
+const rules: FormRules = {
+  consignee: [{ required: true, message: '收货人姓名不能为空', trigger: 'blur' }],
+  provincialCityCountry: [{ required: true, message: '详细地址不能为空', trigger: 'blur' }]
+};
+
+// 监听 modelValue 变化
+watch(
+  () => props.modelValue,
+  (val) => {
+    dialogVisible.value = val;
+    if (val) {
+      form.value.customerId = props.customerId;
+    }
+  },
+  { immediate: true }
+);
+
+// 监听 dialogVisible 变化,同步到父组件
+watch(dialogVisible, (val) => {
+  emit('update:modelValue', val);
+});
+
+// 处理区域选择变化
+const handleRegionChange = (val: string[]) => {
+  if (!val || val.length === 0) {
+    form.value.provincialNo = undefined;
+    form.value.cityNo = undefined;
+    form.value.countryNo = undefined;
+    form.value.provincialCityCountry = undefined;
+    return;
+  }
+
+  // 保存编码
+  form.value.provincialNo = val[0];
+  form.value.cityNo = val[1];
+  form.value.countryNo = val[2];
+
+  // 根据编码获取名称
+  const names: string[] = [];
+  if (val[0]) {
+    const province = regionData.find((item: any) => item.value === val[0]);
+    if (province) {
+      names.push(province.label);
+
+      if (val[1] && province.children) {
+        const city = province.children.find((item: any) => item.value === val[1]);
+        if (city) {
+          names.push(city.label);
+
+          if (val[2] && city.children) {
+            const county = city.children.find((item: any) => item.value === val[2]);
+            if (county) {
+              names.push(county.label);
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // 将省市区名称用斜杠连接
+  form.value.provincialCityCountry = names.join('/');
+};
+
+// 关闭对话框
+const handleClose = () => {
+  emit('update:modelValue', false);
+  resetForm();
+};
+
+// 重置表单
+const resetForm = () => {
+  formRef.value?.resetFields();
+  form.value = { ...initForm };
+  codeArr.value = [];
+};
+
+// 提交表单
+const handleSubmit = async () => {
+  if (!formRef.value) return;
+
+  try {
+    const valid = await formRef.value.validate();
+    if (!valid) return;
+
+    submitLoading.value = true;
+    await addShippingAddress(form.value);
+    emit('success');
+    handleClose();
+  } catch (error) {
+    console.error('添加收货地址失败:', error);
+  } finally {
+    submitLoading.value = false;
+  }
+};
+</script>

+ 102 - 0
src/views/order/orderMain/components/chooseAddress.vue

@@ -0,0 +1,102 @@
+<template>
+  <el-dialog v-model="visible" title="选择地址" width="800px" @close="handleClose">
+    <el-table :data="addressList" border style="width: 100%" highlight-current-row @current-change="handleCurrentChange">
+      <el-table-column label="选择" width="80" align="center">
+        <template #default="scope">
+          <el-radio v-model="selectedAddressId" :value="scope.row.id">
+            <span></span>
+          </el-radio>
+        </template>
+      </el-table-column>
+      <el-table-column prop="consignee" label="收货人" width="120" />
+      <el-table-column prop="phone" label="手机号" width="150" />
+      <el-table-column prop="address" label="地址" show-overflow-tooltip>
+        <template #default="scope"> {{ scope.row.provincialCityCountry }} {{ scope.row.address }} </template>
+      </el-table-column>
+    </el-table>
+
+    <div v-if="addressList.length === 0" class="empty-data">暂无数据</div>
+
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="handleClose">取消</el-button>
+        <el-button type="primary" @click="handleConfirm">确定</el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { ref, watch } from 'vue';
+import { listShippingAddress } from '@/api/customer/customerFile/shippingAddress';
+import { ShippingAddressVO, ShippingAddressQuery } from '@/api/customer/customerFile/shippingAddress/types';
+
+interface Props {
+  modelValue: boolean;
+  customerId?: string | number;
+  addressList?: ShippingAddressVO[];
+}
+
+interface Emits {
+  (e: 'update:modelValue', value: boolean): void;
+  (e: 'confirm', address: ShippingAddressVO): void;
+}
+
+const props = defineProps<Props>();
+const emit = defineEmits<Emits>();
+
+const visible = ref(false);
+const selectedAddressId = ref<string | number>('');
+const selectedAddress = ref<ShippingAddressVO | null>(null);
+
+// 监听 modelValue 变化,同步到 visible
+watch(
+  () => props.modelValue,
+  (newVal) => {
+    visible.value = newVal;
+  },
+  { immediate: true }
+);
+
+// 监听 visible 变化,同步到 modelValue
+watch(visible, (newVal) => {
+  emit('update:modelValue', newVal);
+});
+
+// 选中行变化
+const handleCurrentChange = (row: ShippingAddressVO | null) => {
+  if (row) {
+    selectedAddressId.value = row.id;
+    selectedAddress.value = row;
+  }
+};
+
+// 关闭对话框
+const handleClose = () => {
+  emit('update:modelValue', false);
+  selectedAddressId.value = '';
+  selectedAddress.value = null;
+};
+
+// 确认选择
+const handleConfirm = () => {
+  if (!selectedAddress.value) {
+    return;
+  }
+  emit('confirm', selectedAddress.value);
+  handleClose();
+};
+</script>
+
+<style scoped lang="scss">
+.empty-data {
+  text-align: center;
+  padding: 40px 0;
+  color: #909399;
+  font-size: 14px;
+}
+
+:deep(.el-radio__label) {
+  display: none;
+}
+</style>

+ 225 - 0
src/views/order/orderMain/components/chooseProduct.vue

@@ -0,0 +1,225 @@
+<template>
+  <el-dialog
+    :model-value="modelValue"
+    title="添加商品"
+    width="1200px"
+    @update:model-value="handleDialogChange"
+    @open="handleOpen"
+    @close="handleClose"
+  >
+    <!-- 搜索条件 -->
+    <el-form :model="queryParams" :inline="true" label-width="80px">
+      <el-form-item label="商品编号">
+        <el-input v-model="queryParams.productNo" placeholder="请输入商品编号" clearable style="width: 200px" />
+      </el-form-item>
+      <el-form-item label="商品名称">
+        <el-input v-model="queryParams.itemName" placeholder="请输入商品名称" clearable style="width: 200px" />
+      </el-form-item>
+      <el-form-item label="商品品牌">
+        <el-select v-model="queryParams.brandId" placeholder="请选择品牌" clearable style="width: 200px">
+          <el-option v-for="brand in brandOptions" :key="brand.id" :label="brand.brandName" :value="brand.id" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="商品分类">
+        <el-tree-select
+          v-model="queryParams.bottomCategoryId"
+          :data="categoryList"
+          :props="{ value: 'id', label: 'label', children: 'children' } as any"
+          value-key="id"
+          placeholder="请选择商品分类"
+          clearable
+          check-strictly
+        />
+      </el-form-item>
+      <el-form-item label="商品状态">
+        <el-select v-model="queryParams.productStatus" placeholder="请选择" clearable style="width: 200px">
+          <el-option label="上架" value="0" />
+          <el-option label="下架" value="1" />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="handleQuery">查询</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 商品列表 -->
+    <el-table :data="productList" border style="width: 100%" max-height="400px" v-loading="loading">
+      <el-table-column prop="productNo" label="商品编号" width="120" />
+      <el-table-column label="商品图片" width="100">
+        <template #default="scope">
+          <el-image v-if="scope.row.productImage" :src="scope.row.productImage" style="width: 60px; height: 60px" fit="cover" />
+          <span v-else>暂无图片</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="商品信息" min-width="200">
+        <template #default="scope">
+          <div>{{ scope.row.itemName }}</div>
+          <div>品牌: {{ scope.row.brandName }}</div>
+        </template>
+      </el-table-column>
+      <el-table-column label="税率" width="100">
+        <template #default="scope"> 增值税{{ formatTaxRate(scope.row.taxRate) }}% </template>
+      </el-table-column>
+      <el-table-column prop="unitName" label="单位" width="80" />
+      <el-table-column prop="minSellingPrice" label="最低售价" width="100" />
+      <el-table-column prop="minOrderQuantity" label="起订量" width="100" />
+      <el-table-column prop="memberPrice" label="含税单价" width="100" />
+      <el-table-column prop="productStatus" label="商品状态" width="100">
+        <template #default="scope">
+          <el-tag v-if="scope.row.productStatus === '0'" type="success">上架</el-tag>
+          <el-tag v-else type="danger">下架</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" width="100" fixed="right">
+        <template #default="scope">
+          <el-button link type="primary" @click="handleAddProduct(scope.row)">加入</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 分页 -->
+    <el-pagination
+      v-model:current-page="queryParams.pageNum"
+      v-model:page-size="queryParams.pageSize"
+      :page-sizes="[10, 20, 30, 50]"
+      :total="total"
+      layout="prev, next"
+      @current-change="handleCurrentChange"
+      class="mt-4"
+    />
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted } from 'vue';
+import { listBase, brandList, categoryTree } from '@/api/product/base';
+import { BaseVO, BaseQuery } from '@/api/product/base/types';
+import { BrandVO } from '@/api/product/brand/types';
+import { categoryTreeVO } from '@/api/product/category/types';
+
+interface Props {
+  modelValue: boolean;
+}
+
+interface Emits {
+  (e: 'update:modelValue', value: boolean): void;
+  (e: 'confirm', product: BaseVO): void;
+}
+
+const props = defineProps<Props>();
+const emit = defineEmits<Emits>();
+
+const loading = ref(false);
+const productList = ref<BaseVO[]>([]);
+const brandOptions = ref<BrandVO[]>([]);
+const categoryList = ref<categoryTreeVO[]>([]);
+const total = ref(0);
+
+const queryParams = ref<BaseQuery>({
+  pageNum: 1,
+  pageSize: 10,
+  productNo: undefined,
+  itemName: undefined,
+  brandId: undefined,
+  topCategoryId: undefined
+});
+
+// 对话框状态变化
+const handleDialogChange = (val: boolean) => {
+  emit('update:modelValue', val);
+};
+
+// 格式化税率
+const formatTaxRate = (taxRate: number | string | undefined): string => {
+  if (taxRate === undefined || taxRate === null) {
+    return '0';
+  }
+  return Number(taxRate).toFixed(0);
+};
+
+// 对话框打开时触发
+const handleOpen = () => {
+  loadProductList();
+};
+
+// 对话框关闭时触发
+const handleClose = () => {
+  // 可以在这里重置数据
+};
+
+// 加载商品列表
+const loadProductList = async () => {
+  if (loading.value) return;
+
+  loading.value = true;
+  try {
+    const res = await listBase(queryParams.value);
+    productList.value = res.rows || [];
+    total.value = res.total || 0;
+  } catch (error) {
+    console.error('加载商品列表失败:', error);
+    productList.value = [];
+    total.value = 0;
+  } finally {
+    loading.value = false;
+  }
+};
+
+// 加载品牌列表
+const loadBrandList = async () => {
+  try {
+    const res = await brandList();
+    brandOptions.value = res.data || [];
+  } catch (error) {
+    console.error('加载品牌列表失败:', error);
+    brandOptions.value = [];
+  }
+};
+
+// 加载分类树
+const loadCategoryTree = async () => {
+  try {
+    const res = await categoryTree();
+    categoryList.value = res.data || [];
+  } catch (error) {
+    console.error('加载分类树失败:', error);
+    categoryList.value = [];
+  }
+};
+
+// 查询
+const handleQuery = () => {
+  queryParams.value.pageNum = 1;
+  loadProductList();
+};
+
+// 分页大小变化
+const handleSizeChange = () => {
+  queryParams.value.pageNum = 1;
+  loadProductList();
+};
+
+// 页码变化
+const handleCurrentChange = () => {
+  loadProductList();
+};
+
+// 添加商品
+const handleAddProduct = (product: BaseVO) => {
+  emit('confirm', product);
+  // 关闭对话框
+  emit('update:modelValue', false);
+};
+
+// 初始化
+onMounted(() => {
+  // loadBrandList(); // 暂时注释掉
+  loadCategoryTree();
+});
+</script>
+
+<style scoped lang="scss">
+.mt-4 {
+  margin-top: 16px;
+}
+</style>

+ 149 - 0
src/views/order/orderMain/components/selectProductDetail.vue

@@ -0,0 +1,149 @@
+<template>
+  <el-dialog v-model="visible" title="查询商品明细" width="800px" :before-close="handleClose">
+    <div class="product-detail">
+      <!-- SKU价格 -->
+      <div class="section">
+        <div class="section-title">SKU价格</div>
+        <el-row :gutter="20" class="price-row">
+          <el-col :span="8">
+            <div class="price-item">
+              <span class="label">市场价</span>
+              <span class="value">{{ productDetail.marketPrice || '0.00' }}</span>
+            </div>
+          </el-col>
+          <el-col :span="8">
+            <div class="price-item">
+              <span class="label">平台售价</span>
+              <span class="value">{{ productDetail.platformPrice || '0.00' }}</span>
+            </div>
+          </el-col>
+          <el-col :span="8">
+            <div class="price-item">
+              <span class="label">协议价</span>
+              <span class="value">{{ productDetail.agreementPrice || '0.00' }}</span>
+            </div>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20" class="price-row">
+          <el-col :span="8">
+            <div class="price-item">
+              <span class="label">最低售价</span>
+              <span class="value">{{ productDetail.minSellingPrice || '0.00' }}</span>
+            </div>
+          </el-col>
+        </el-row>
+      </div>
+
+      <!-- 库存信息 -->
+      <div class="section">
+        <div class="section-title">库存信息</div>
+        <el-row :gutter="20" class="stock-row">
+          <el-col :span="12">
+            <div class="stock-item">
+              <span class="label">总库存量</span>
+              <span class="value">{{ productDetail.totalStock || '0' }}</span>
+            </div>
+          </el-col>
+          <el-col :span="12">
+            <div class="stock-item">
+              <span class="label">当期仓库存量</span>
+              <span class="value">{{ productDetail.currentWarehouseStock || '0' }}</span>
+            </div>
+          </el-col>
+        </el-row>
+      </div>
+    </div>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { ref, watch } from 'vue';
+
+interface ProductDetail {
+  marketPrice?: number | string;
+  platformPrice?: number | string;
+  agreementPrice?: number | string;
+  minSellingPrice?: number | string;
+  totalStock?: number | string;
+  currentWarehouseStock?: number | string;
+}
+
+const props = defineProps({
+  modelValue: {
+    type: Boolean,
+    default: false
+  },
+  productData: {
+    type: Object as () => ProductDetail,
+    default: () => ({})
+  }
+});
+
+const emit = defineEmits(['update:modelValue']);
+
+const visible = ref(false);
+const productDetail = ref<ProductDetail>({});
+
+watch(
+  () => props.modelValue,
+  (val) => {
+    visible.value = val;
+    if (val) {
+      productDetail.value = { ...props.productData };
+    }
+  }
+);
+
+watch(visible, (val) => {
+  emit('update:modelValue', val);
+});
+
+const handleClose = () => {
+  visible.value = false;
+};
+</script>
+
+<style scoped lang="scss">
+.product-detail {
+  padding: 10px 0;
+
+  .section {
+    margin-bottom: 30px;
+
+    .section-title {
+      font-size: 16px;
+      font-weight: bold;
+      color: #303133;
+      margin-bottom: 20px;
+      padding-bottom: 10px;
+      border-bottom: 1px solid #e4e7ed;
+    }
+
+    .price-row,
+    .stock-row {
+      margin-bottom: 15px;
+    }
+
+    .price-item,
+    .stock-item {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 12px 16px;
+      background-color: #f5f7fa;
+      border-radius: 4px;
+
+      .label {
+        font-size: 14px;
+        color: #606266;
+      }
+
+      .value {
+        font-size: 14px;
+        color: #303133;
+        font-weight: 500;
+      }
+    }
+  }
+}
+</style>

+ 987 - 0
src/views/order/orderMain/index.vue

@@ -0,0 +1,987 @@
+<template>
+  <div class="p-2">
+    <!-- 订单流程 -->
+    <el-card shadow="never" class="mb-2">
+      <div class="order-steps">
+        <span class="step-title">A10订单流程</span>
+      </div>
+    </el-card>
+
+    <!-- 订单基本信息 -->
+    <el-card shadow="never" class="mb-2">
+      <template #header>
+        <div class="card-header">
+          <span>订单基本信息</span>
+          <span> 订单日期:<el-date-picker v-model="form.orderTime" type="date" value-format="YYYY-MM-DD" /></span>
+        </div>
+      </template>
+
+      <el-form ref="orderMainFormRef" :model="form" :rules="rules" label-width="100px">
+        <el-row :gutter="20">
+          <!-- 第一行 -->
+          <el-col :span="8">
+            <el-form-item label="归属公司" prop="companyId">
+              <el-select v-model="form.companyId" placeholder="请选择" style="width: 100%" filterable>
+                <el-option v-for="company in companyList" :key="company.id" :label="company.companyName" :value="company.id" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="客户名称" prop="customerId">
+              <el-select
+                v-model="form.customerId"
+                placeholder="请选择客户"
+                style="width: 100%"
+                filterable
+                :disabled="!form.companyId"
+                :loading="customerLoading"
+                @change="handleCustomerChange"
+              >
+                <el-option v-for="customer in customerList" :key="customer.id" :label="customer.customerName" :value="customer.id" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <!-- 第二行 -->
+          <el-col :span="8"> </el-col>
+          <el-col :span="8">
+            <el-form-item label="信用额度" prop="creditLimit">
+              <el-input v-model="form.creditLimit" placeholder="0" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="剩余额度">
+              <el-input value="0" disabled />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <!-- 第三行 -->
+          <el-col :span="8">
+            <el-form-item label="业务人员" prop="businessStaff">
+              <el-input v-model="form.businessStaff" placeholder="请选择" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="客服人员" prop="customerService">
+              <el-input v-model="form.customerService" placeholder="请选择" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="业务部门" prop="businessDept">
+              <el-input v-model="form.businessDept" placeholder="请选择" disabled />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <!-- 第四行 -->
+          <el-col :span="8">
+            <el-form-item label="发票类型" prop="invoiceType">
+              <el-select v-model="form.invoiceType" placeholder="请选择" style="width: 100%" disabled>
+                <el-option label="普通发票" value="1" />
+                <el-option label="增值税发票" value="2" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="支付方式" prop="payType">
+              <el-select v-model="form.payType" placeholder="请选择" style="width: 100%">
+                <el-option v-for="dict in pay_method" :key="dict.value" :label="dict.label" :value="dict.value" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="预收货日" prop="expectedDeliveryTime">
+              <el-date-picker
+                v-model="form.expectedDeliveryTime"
+                type="date"
+                placeholder="请选择"
+                value-format="YYYY-MM-DD"
+                style="width: 100%"
+                :disabled-date="disabledDeliveryDate"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <!-- 第五行 -->
+          <el-col :span="8">
+            <el-form-item label="发货仓库" prop="warehouseId">
+              <el-select v-model="form.warehouseId" placeholder="请选择" style="width: 100%" filterable>
+                <el-option
+                  v-for="warehouse in warehouseList"
+                  :key="warehouse.id"
+                  :label="`${warehouse.warehouseCode},${warehouse.warehouseName}`"
+                  :value="warehouse.id"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="费用类型" prop="expenseType">
+              <el-select v-model="form.expenseType" placeholder="请选择" style="width: 100%">
+                <el-option v-for="dict in fee_type" :key="dict.value" :label="dict.label" :value="dict.value" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="下单部门" prop="userDept">
+              <el-tree-select
+                v-model="form.userDept"
+                :data="customerDeptList"
+                :props="{ value: 'deptId', label: 'deptName', children: 'children' } as any"
+                value-key="deptId"
+                placeholder="选择下单部门"
+                check-strictly
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <!-- 第六行 -->
+          <el-col :span="24">
+            <el-form-item label="采购事由" prop="purchaseReason">
+              <el-input v-model="form.purchaseReason" placeholder="请输入采购事由" type="textarea" :rows="2" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <!-- 第七行 -->
+          <el-col :span="24">
+            <el-form-item label="订单备注" prop="remark">
+              <el-input v-model="form.remark" placeholder="请输入订单备注" type="textarea" :rows="2" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <!-- 第八行 -->
+          <el-col :span="24">
+            <el-form-item label="附件" prop="attachmentPath">
+              <el-upload class="upload-demo" action="#" :auto-upload="false">
+                <el-button type="primary" plain>上传附件</el-button>
+              </el-upload>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+    </el-card>
+
+    <!-- 收货地址 -->
+    <el-card shadow="never" class="mb-2">
+      <template #header>
+        <div class="card-header">
+          <span>收货地址</span>
+          <div>
+            <el-button type="primary" plain @click="chooseAddress">选择收货地址</el-button>
+            <el-button type="primary" plain @click="addAddress">添加收货地址</el-button>
+          </div>
+        </div>
+      </template>
+
+      <el-form :model="form" label-width="100px">
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="收货人姓名">
+              <el-input v-model="addressDisplay.receiverName" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="手机号码">
+              <el-input v-model="addressDisplay.receiverPhone" disabled />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="详细地址">
+              <el-input v-model="addressDisplay.receiverProvince" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item>
+              <el-input v-model="addressDisplay.addressDetail" disabled />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+    </el-card>
+
+    <!-- 商品明细 -->
+    <el-card shadow="never" class="mb-2">
+      <template #header>
+        <div class="card-header">
+          <span>商品明细</span>
+          <div>
+            <el-button type="primary" plain @click="handleAddProduct">添加商品</el-button>
+            <el-button type="primary" plain>导入</el-button>
+          </div>
+        </div>
+      </template>
+      <el-table :data="productList" border style="width: 100%">
+        <el-table-column prop="productCode" label="产品编码" width="130" align="center" />
+        <el-table-column label="商品图片" align="center">
+          <template #default="scope">
+            <el-image v-if="scope.row.productImage" :src="scope.row.productImage" style="width: 60px; height: 60px" fit="cover" />
+            <span v-else>暂无图片</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="商品信息">
+          <template #default="scope">
+            <div>{{ scope.row.productName }}</div>
+            <div>品牌: {{ scope.row.brandName }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="taxRate" label="税率" align="center">
+          <template #default="scope"> 增值税{{ scope.row.taxRate }}% </template>
+        </el-table-column>
+        <el-table-column prop="unitName" label="单位" align="center" />
+        <el-table-column prop="certificatePrice" label="最低售价" align="center" />
+        <el-table-column prop="minOrderQuantity" label="起订量" align="center" />
+        <el-table-column prop="unitPrice" label="含税单价" align="center">
+          <template #default="scope">
+            <el-input-number
+              v-model="scope.row.unitPrice"
+              :min="scope.row.certificatePrice"
+              :precision="2"
+              :controls="false"
+              @blur="handleUnitPriceChange(scope.$index)"
+            />
+          </template>
+        </el-table-column>
+        <el-table-column prop="quantity" label="数量" align="center">
+          <template #default="scope">
+            <el-input-number
+              v-model="scope.row.quantity"
+              :min="scope.row.minOrderQuantity || 1"
+              :precision="0"
+              :controls="false"
+              @change="handleQuantityChange(scope.$index)"
+            />
+          </template>
+        </el-table-column>
+        <el-table-column prop="amount" label="小计" align="center" />
+        <el-table-column label="操作" align="center">
+          <template #default="scope">
+            <el-button link type="danger" size="small" @click="handleDeleteProduct(scope.$index)">删除</el-button>
+            <el-button link type="primary" size="small" @click="handleSelect(scope.$index)">查询</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <div class="mt-2 text-right">
+        <span>商品数:{{ totalQuantity }} 合计金额:¥ {{ totalAmount.toFixed(2) }}</span>
+      </div>
+    </el-card>
+
+    <!-- 信息汇总 -->
+    <el-card shadow="never" class="mb-2">
+      <template #header>
+        <div class="card-header">
+          <span>信息汇总</span>
+        </div>
+      </template>
+
+      <el-table :data="summaryData" border style="width: 100%">
+        <el-table-column prop="quantity" label="商品数量" align="center" />
+        <el-table-column prop="shippingFee" label="运费" align="center" />
+        <el-table-column prop="totalAmount" label="订单总金额" align="center" />
+        <el-table-column prop="payableAmount" label="应付款金额" align="center" />
+      </el-table>
+    </el-card>
+
+    <!-- 底部按钮 -->
+    <div class="text-center mt-4">
+      <!-- <el-button @click="cancel">取消</el-button> -->
+      <el-button type="primary" :loading="buttonLoading" @click="submitForm">确定</el-button>
+    </div>
+
+    <!-- 选择地址对话框 -->
+    <ChooseAddress v-model="showAddressDialog" :customer-id="form.customerId" :address-list="addressList" @confirm="handleAddressConfirm" />
+
+    <!-- 添加地址对话框 -->
+    <AddAddress v-model="showAddAddressDialog" :customer-id="form.customerId" @success="handleAddAddressSuccess" />
+
+    <!-- 选择商品对话框 -->
+    <ChooseProduct v-model="showProductDialog" @confirm="handleProductConfirm" />
+
+    <!-- 查询商品明细对话框 -->
+    <SelectProductDetail v-model="showProductDetailDialog" :product-data="currentProductDetail" />
+  </div>
+</template>
+
+<script setup name="OrderMain" lang="ts">
+import { listOrderMain, getOrderMain, delOrderMain, addOrderMain, updateOrderMain } from '@/api/order/orderMain';
+import { OrderMainVO, OrderMainQuery, OrderMainForm } from '@/api/order/orderMain/types';
+import { listCompany } from '@/api/company/company';
+import { listCustomerDept } from '@/api/system/dept';
+import { CompanyVO } from '@/api/company/company/types';
+import { listWarehouse, getWarehouse } from '@/api/company/warehouse';
+import { WarehouseVO, WarehouseQuery } from '@/api/company/warehouse/types';
+import { listCustomerInfo, getCustomerInfo } from '@/api/customer/customerFile/customerInfo';
+import { CustomerInfoVO, CustomerInfoQuery, CustomerInfoForm } from '@/api/customer/customerFile/customerInfo/types';
+import { listShippingAddress } from '@/api/customer/customerFile/shippingAddress';
+import { ShippingAddressVO, ShippingAddressQuery } from '@/api/customer/customerFile/shippingAddress/types';
+import ChooseAddress from './components/chooseAddress.vue';
+import AddAddress from './components/addressDialog.vue';
+import ChooseProduct from './components/chooseProduct.vue';
+import SelectProductDetail from './components/selectProductDetail.vue';
+import { BaseVO } from '@/api/product/base/types';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { order_status, fee_type, pay_method } = toRefs<any>(proxy?.useDict('order_status', 'fee_type', 'pay_method'));
+import { regionData } from 'element-china-area-data';
+const buttonLoading = ref(false);
+const loading = ref(true);
+const ids = ref<Array<string | number>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const router = useRouter();
+const queryFormRef = ref<ElFormInstance>();
+const orderMainFormRef = ref<ElFormInstance>();
+
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+
+interface DeptOptionsType {
+  deptId: number | string;
+  deptName: string;
+  children: DeptOptionsType[];
+}
+
+// 商品列表数据
+const productList = ref([]);
+
+// 地址选择对话框
+const showAddressDialog = ref(false);
+
+// 添加地址对话框
+const showAddAddressDialog = ref(false);
+
+// 选择商品对话框
+const showProductDialog = ref(false);
+
+// 查询商品明细对话框
+const showProductDetailDialog = ref(false);
+const currentProductDetail = ref({});
+
+// 计算商品总数(所有商品的数量之和)
+const totalQuantity = computed(() => {
+  return productList.value.reduce((sum, item) => {
+    return sum + (Number(item.quantity) || 0);
+  }, 0);
+});
+
+// 计算商品总金额(所有商品的小计之和)
+const totalAmount = computed(() => {
+  return productList.value.reduce((sum, item) => {
+    return sum + (Number(item.amount) || 0);
+  }, 0);
+});
+
+// 计算应付款金额(订单总金额 + 运费)
+const payableAmount = computed(() => {
+  const shipping = Number(form.value.shippingFee) || 0;
+  return totalAmount.value + shipping;
+});
+
+// 汇总数据(用于表格显示)
+const summaryData = computed(() => {
+  return [
+    {
+      quantity: totalQuantity.value,
+      shippingFee: `¥${(Number(form.value.shippingFee) || 0).toFixed(2)}`,
+      totalAmount: `¥${totalAmount.value.toFixed(2)}`,
+      payableAmount: `¥${payableAmount.value.toFixed(2)}`
+    }
+  ];
+});
+
+// 公司列表
+const companyList = ref<CompanyVO[]>([]);
+
+// 仓库列表
+const warehouseList = ref<WarehouseVO[]>([]);
+
+// 客户列表
+const customerList = ref<CustomerInfoVO[]>([]);
+const customerLoading = ref(false);
+
+// 客户部门列表
+const customerDeptList = ref<DeptOptionsType[]>([]);
+
+const addressList = ref<ShippingAddressVO[]>([]);
+
+// 收货地址显示信息(仅用于显示,不提交)
+const addressDisplay = ref({
+  receiverName: '',
+  receiverPhone: '',
+  receiverProvince: '',
+  addressDetail: ''
+});
+
+// 禁用预收货日期的函数(只能选择订单日期之后的日期)
+const disabledDeliveryDate = (time: Date) => {
+  if (!form.value.orderTime) {
+    // 如果没有选择订单日期,禁用今天之前的日期
+    return time.getTime() < Date.now() - 8.64e7;
+  }
+  // 将订单日期转换为时间戳进行比较
+  const orderDate = new Date(form.value.orderTime);
+  orderDate.setHours(0, 0, 0, 0);
+  const compareTime = time.getTime();
+  const orderTime = orderDate.getTime();
+  // 禁用订单日期及之前的日期
+  return compareTime <= orderTime;
+};
+
+const initFormData: OrderMainForm = {
+  id: undefined,
+  orderNo: undefined,
+  shipmentNo: undefined,
+  subOrderNo: undefined,
+  companyId: undefined,
+  customerId: undefined,
+  customerCode: undefined,
+  userId: undefined,
+  shippingAddressId: undefined,
+  purchaseReason: undefined,
+  invoiceType: undefined,
+  payType: '0',
+  warehouseId: undefined,
+  creditLimit: undefined,
+  expectedDeliveryTime: undefined,
+  businessStaff: undefined,
+  customerService: undefined,
+  businessDept: undefined,
+  userDept: undefined,
+  productQuantity: undefined,
+  shippingFee: undefined,
+  totalAmount: undefined,
+  payableAmount: undefined,
+  paymentStatus: undefined,
+  orderSource: '1',
+  orderStatus: undefined,
+  orderTime: new Date().toISOString().split('T')[0], // 默认今天,格式:YYYY-MM-DD
+  confirmTime: undefined,
+  shippingTime: undefined,
+  receivingTime: undefined,
+  shippedQuantity: undefined,
+  unshippedQuantity: undefined,
+  packageCount: undefined,
+  signedQuantity: undefined,
+  afterSaleCompleted: undefined,
+  afterSalePending: undefined,
+  deliveryDesc: undefined,
+  pushStatus: undefined,
+  attachmentPath: undefined,
+  deliveryType: undefined,
+  orderCategory: undefined,
+  productCode: undefined,
+  cancelReason: undefined,
+  expenseType: undefined,
+  userNo: undefined,
+  status: undefined,
+  remark: undefined,
+  isSplitChild: '1',
+  customerSalesInfoVo: {
+    salesPerson: '',
+    serviceStaff: '',
+    belongingDepartment: ''
+  }
+};
+const data = reactive<PageData<OrderMainForm, OrderMainQuery>>({
+  form: { ...initFormData },
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    orderNo: undefined,
+    shipmentNo: undefined,
+    subOrderNo: undefined,
+    companyId: undefined,
+    customerId: undefined,
+    customerCode: undefined,
+    userId: undefined,
+    shippingAddressId: undefined,
+
+    params: {}
+  },
+  rules: {
+    companyId: [{ required: true, message: '归属公司不能为空', trigger: 'blur' }],
+    customerId: [{ required: true, message: '客户名称不能为空', trigger: 'blur' }],
+    payType: [{ required: true, message: '支付方式不能为空', trigger: 'change' }],
+    warehouseId: [{ required: true, message: '发货仓库不能为空', trigger: 'change' }],
+    expectedDeliveryTime: [{ required: true, message: '预计送达时间不能为空', trigger: 'blur' }],
+    shippingFee: [{ required: true, message: '运费不能为空', trigger: 'blur' }],
+    confirmTime: [{ required: true, message: '确认时间不能为空', trigger: 'blur' }],
+    shippingTime: [{ required: true, message: '发货时间不能为空', trigger: 'blur' }],
+    expenseType: [{ required: true, message: '费用类型不能为空', trigger: 'change' }],
+    purchaseReason: [{ required: true, message: '采购事由不能为空', trigger: 'change' }]
+  }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+// 监听公司变化,加载该公司的客户列表
+watch(
+  () => form.value.companyId,
+  (newVal, oldVal) => {
+    if (newVal !== oldVal) {
+      // 清空客户选择和相关信息
+      form.value.customerId = undefined;
+      form.value.customerCode = undefined;
+      customerList.value = [];
+      customerDeptList.value = [];
+      form.value.creditLimit = undefined;
+      form.value.shippingAddressId = undefined;
+      form.value.userDept = undefined;
+      form.value.businessStaff = undefined;
+      form.value.customerService = undefined;
+      form.value.businessDept = undefined;
+      // 清空收货地址显示信息
+      addressDisplay.value = {
+        receiverName: '',
+        receiverPhone: '',
+        addressDetail: ''
+      } as any;
+
+      // 如果选择了公司,加载该公司的客户列表
+      if (newVal) {
+        loadCustomerListByCompany(newVal);
+      }
+    }
+  }
+);
+
+/** 取消按钮 */
+const cancel = () => {
+  reset();
+  dialog.visible = false;
+};
+
+/** 表单重置 */
+const reset = () => {
+  form.value = { ...initFormData };
+  orderMainFormRef.value?.resetFields();
+};
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.value.pageNum = 1;
+};
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value?.resetFields();
+  handleQuery();
+};
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection: OrderMainVO[]) => {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+
+/** 新增按钮操作 */
+const handleAdd = () => {
+  reset();
+  dialog.visible = true;
+  dialog.title = '添加订单主信息';
+};
+
+/** 修改按钮操作 */
+const handleUpdate = async (row?: OrderMainVO) => {
+  reset();
+  const _id = row?.id || ids.value[0];
+  const res = await getOrderMain(_id);
+  Object.assign(form.value, res.data);
+  dialog.visible = true;
+  dialog.title = '修改订单主信息';
+};
+
+/** 提交按钮 */
+const submitForm = () => {
+  orderMainFormRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      // 验证是否有商品
+      if (!productList.value || productList.value.length === 0) {
+        proxy?.$modal.msgWarning('请至少添加一个商品');
+        return;
+      }
+
+      buttonLoading.value = true;
+
+      try {
+        // 组装订单商品明细数据
+        const orderProductList = productList.value.map((product) => ({
+          productId: product.id,
+          productNo: product.productCode, // 产品编号
+          productName: product.productName, // 产品名称
+          productUnit: product.unitName, // 产品单位
+          productImage: product.productImage, // 产品图片
+          platformPrice: product.price, // 平台价格(单价)
+          marketPrice: product.marketPrice,
+          minOrderQuantity: product.minOrderQuantity, // 最小起订量
+          orderPrice: product.unitPrice, // 订单单价(含税单价)
+          orderQuantity: product.quantity, // 订购数量
+          subtotal: product.amount, // 行小计金额
+          taxRate: product.taxRate,
+          minSellingPrice: product.certificatePrice, // 最低销售价
+          preDeliveryDate: form.value.expectedDeliveryTime, // 预计送达时间
+          status: '0' // 状态(0正常)
+        }));
+
+        if (form.value.payType == '0') {
+          //如果选项信用支付  则订单状态为待发货
+          form.value.orderStatus = '2';
+        }
+
+        // 组装提交数据
+        const submitData = {
+          ...form.value,
+          productQuantity: totalQuantity.value, // 商品总数量
+          totalAmount: totalAmount.value, // 订单总金额
+          payableAmount: payableAmount.value, // 应付金额
+          shippingFee: Number(form.value.shippingFee) || 0, // 运费
+          orderProductBos: orderProductList // 订单商品明细列表
+        };
+
+        if (form.value.id) {
+          await updateOrderMain(submitData);
+        } else {
+          await addOrderMain(submitData);
+        }
+
+        proxy?.$modal.msgSuccess('操作成功');
+        // 可以在这里添加跳转逻辑,比如返回列表页
+        router.push('/order-manage/order-list');
+      } catch (error) {
+        console.error('提交订单失败:', error);
+        proxy?.$modal.msgError('提交订单失败,请检查数据后重试');
+      } finally {
+        buttonLoading.value = false;
+      }
+    }
+  });
+};
+
+/** 删除按钮操作 */
+const handleDelete = async (row?: OrderMainVO) => {
+  const _ids = row?.id || ids.value;
+  await proxy?.$modal.confirm('是否确认删除订单主信息编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
+  await delOrderMain(_ids);
+  proxy?.$modal.msgSuccess('删除成功');
+};
+
+/** 导出按钮操作 */
+const handleExport = () => {
+  proxy?.download(
+    'order/orderMain/export',
+    {
+      ...queryParams.value
+    },
+    `orderMain_${new Date().getTime()}.xlsx`
+  );
+};
+
+/** 选择收货地址 */
+const chooseAddress = () => {
+  if (!form.value.customerId) {
+    proxy?.$modal.msgWarning('请先选择客户');
+    return;
+  }
+  showAddressDialog.value = true;
+};
+
+/** 添加收货地址 */
+const addAddress = () => {
+  if (!form.value.customerId) {
+    proxy?.$modal.msgWarning('请先选择客户');
+    return;
+  }
+  showAddAddressDialog.value = true;
+};
+
+/** 添加地址成功回调 */
+const handleAddAddressSuccess = () => {
+  // 获取客户收货地址列表
+  loadAddressList(form.value.customerId);
+  proxy?.$modal.msgSuccess('添加地址成功');
+};
+
+/** 打开添加商品对话框 */
+const handleAddProduct = () => {
+  showProductDialog.value = true;
+};
+
+/** 确认选择商品 */
+const handleProductConfirm = (product: any) => {
+  // 将商品添加到商品列表,按照新的字段映射
+  const newProduct = {
+    id: product.id,
+    productCode: product.productNo, // 产品编码
+    productImage: product.productImage, // 商品图片
+    productName: product.itemName, // 产品信息
+    taxRate: product.taxRate || 0, // 税率
+    marketPrice: product.marketPrice || 0,
+    unitName: product.unitName, // 单位
+    price: product.standardPrice || 0, // 单价(使用平档价)
+    certificatePrice: product.minSellingPrice || 0, // 最低售价
+    minOrderQuantity: product.minOrderQuantity || 1, // 起订量
+    unitPrice: product.memberPrice || 0, // 含税单价(默认使用最低售价)
+    quantity: product.minOrderQuantity || 1, // 数量(默认使用起订量)
+    amount: ((product.memberPrice || 0) * (product.minOrderQuantity || 1)).toFixed(2) // 小计 = 含税单价 × 数量
+  };
+  productList.value.push(newProduct);
+  proxy?.$modal.msgSuccess('添加商品成功');
+};
+
+/** 删除商品 */
+const handleDeleteProduct = (index: number) => {
+  productList.value.splice(index, 1);
+  proxy?.$modal.msgSuccess('删除成功');
+};
+
+/** 查询商品明细 */
+const handleSelect = (index: number) => {
+  if (form.value.warehouseId === undefined) {
+    proxy?.$modal.msgWarning('请先选择仓库');
+    return;
+  }
+  const product = productList.value[index];
+  if (product) {
+    // 组装商品明细数据
+    currentProductDetail.value = {
+      marketPrice: product.marketPrice || 0, // 市场价(使用平档价)
+      platformPrice: product.unitPrice || 0, // 平台售价(使用含税单价)
+      agreementPrice: 0, // 协议价(暂无数据)
+      minSellingPrice: product.certificatePrice || 0, // 最低售价
+      totalStock: 0, // 总库存量(需要从后端获取)
+      currentWarehouseStock: 0 // 当期仓库存量(需要从后端获取)
+    };
+    showProductDetailDialog.value = true;
+  }
+};
+
+/** 含税单价变化时验证最低售价 */
+const handleUnitPriceChange = (index: number) => {
+  const product = productList.value[index];
+  if (product) {
+    // 如果含税单价小于最低售价,自动设置为最低售价
+    if (Number(product.unitPrice) < Number(product.certificatePrice)) {
+      product.unitPrice = product.certificatePrice;
+    }
+    // 重新计算小计:小计 = 数量 × 含税单价
+    product.amount = (Number(product.quantity) * Number(product.unitPrice)).toFixed(2);
+  }
+};
+
+/** 数量变化时重新计算金额 */
+const handleQuantityChange = (index: number) => {
+  const product = productList.value[index];
+  if (product) {
+    // 小计 = 数量 × 含税单价
+    product.amount = (Number(product.quantity) * Number(product.unitPrice)).toFixed(2);
+  }
+};
+
+/** 确认选择地址 */
+const handleAddressConfirm = (address: ShippingAddressVO) => {
+  form.value.shippingAddressId = address.id;
+  // 更新地址显示信息
+  addressDisplay.value = {
+    receiverName: address.consignee,
+    receiverPhone: address.phone,
+    receiverProvince: address.provincialCityCountry,
+    addressDetail: address.address
+  };
+};
+
+/** 获取公司列表 */
+const getCompanyList = async () => {
+  try {
+    const res = await listCompany({
+      isShow: '0',
+      pageNum: 1,
+      pageSize: 1000
+    });
+    companyList.value = res.rows || [];
+  } catch (error) {
+    console.error('获取公司列表失败:', error);
+    companyList.value = [];
+  }
+};
+
+/** 获取仓库列表 */
+const getWarehouseList = async () => {
+  try {
+    const res = await listWarehouse({
+      isShow: '0',
+      pageNum: 1,
+      pageSize: 1000
+    });
+    warehouseList.value = res.rows || [];
+  } catch (error) {
+    console.error('获取仓库列表失败:', error);
+    warehouseList.value = [];
+  }
+};
+
+/** 根据公司ID加载客户列表 */
+const loadCustomerListByCompany = async (companyId: string | number) => {
+  customerLoading.value = true;
+  try {
+    const params: CustomerInfoQuery = {
+      belongCompanyId: companyId,
+      pageNum: 1,
+      pageSize: 1000 // 加载所有客户
+    };
+    const res = await listCustomerInfo(params);
+    customerList.value = res.rows || [];
+  } catch (error) {
+    console.error('加载客户列表失败:', error);
+    customerList.value = [];
+  } finally {
+    customerLoading.value = false;
+  }
+};
+
+/** 客户变化时获取客户详情 */
+const handleCustomerChange = async (customerId: string | number) => {
+  if (!customerId) {
+    // 清空客户相关信息
+    form.value.creditLimit = undefined;
+    form.value.shippingAddressId = undefined;
+    form.value.userDept = undefined;
+    form.value.businessStaff = undefined;
+    form.value.customerService = undefined;
+    form.value.businessDept = undefined;
+    customerDeptList.value = [];
+    // 清空收货地址显示信息
+    addressDisplay.value = {
+      receiverName: '',
+      receiverPhone: '',
+      addressDetail: ''
+    } as any;
+    return;
+  }
+
+  try {
+    // 获取客户详情
+    const res = await getCustomerInfo(customerId);
+    const customerInfo = res.data;
+    form.value.customerCode = customerInfo.customerNo;
+    // 填充客户相关信息
+    if (customerInfo.customerSalesInfoVo) {
+      const salesInfo = customerInfo.customerSalesInfoVo as any;
+      form.value.creditLimit = salesInfo.remainingQuota || salesInfo.creditAmount;
+      // 填充业务人员、客服人员、业务部门
+      form.value.businessStaff = salesInfo.salesPerson;
+      form.value.customerService = salesInfo.serviceStaff;
+      form.value.businessDept = salesInfo.belongingDepartment;
+    }
+
+    // 获取客户部门列表
+    await getCustomerDeptList(customerId);
+
+    // 获取客户收货地址列表
+    await loadAddressList(customerId);
+  } catch (error) {
+    console.error('获取客户详情失败:', error);
+  }
+};
+
+/** 获取客户部门列表 */
+const getCustomerDeptList = async (customerId: string | number) => {
+  try {
+    const res = await listCustomerDept(customerId);
+    const data = proxy?.handleTree<DeptOptionsType>(res.data, 'deptId');
+    customerDeptList.value = data;
+  } catch (error) {
+    console.error('获取客户部门列表失败:', error);
+    customerDeptList.value = [];
+  }
+};
+
+// 加载地址列表
+const loadAddressList = async (customerId: string | number) => {
+  if (!customerId) {
+    addressList.value = [];
+    return;
+  }
+  try {
+    const queryParams: any = {
+      customerId: customerId
+    };
+    const res = await listShippingAddress(queryParams);
+    addressList.value = res.rows || [];
+    console.log(addressList.value);
+  } catch (error) {
+    console.error('加载地址列表失败:', error);
+    addressList.value = [];
+  }
+};
+
+onMounted(() => {
+  getCompanyList();
+  getWarehouseList();
+});
+</script>
+
+<style scoped lang="scss">
+.order-steps {
+  padding: 10px 0;
+
+  .step-title {
+    font-size: 16px;
+    font-weight: bold;
+    color: #303133;
+  }
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  font-weight: bold;
+}
+
+.mb-2 {
+  margin-bottom: 16px;
+}
+
+.mt-2 {
+  margin-top: 16px;
+}
+
+.mt-4 {
+  margin-top: 32px;
+}
+
+.text-right {
+  text-align: right;
+}
+
+.text-center {
+  text-align: center;
+}
+
+:deep(.el-form-item__label) {
+  font-weight: normal;
+}
+
+:deep(.el-card__header) {
+  padding: 12px 20px;
+  background-color: #f5f7fa;
+}
+</style>

+ 283 - 0
src/views/order/orderReturn/index.vue

@@ -0,0 +1,283 @@
+<template>
+  <div class="p-2">
+    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+      <div v-show="showSearch" class="mb-[10px]">
+        <el-card shadow="hover">
+          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
+            <el-form-item label="退货原因" prop="returnReasonId">
+              <el-select v-model="queryParams.returnReasonId" placeholder="请选择退货原因" clearable>
+                <el-option v-for="reason in returnReasonList" :key="reason.id" :label="reason.returnReasonName" :value="reason.id" />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="订单状态" prop="returnStatus">
+              <el-select v-model="queryParams.returnStatus" placeholder="请选择订单状态" clearable>
+                <el-option v-for="dict in return_order_status" :key="dict.value" :label="dict.label" :value="dict.value" />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="提交时间" prop="dateRange">
+              <el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" />
+            </el-form-item>
+            <el-form-item>
+              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+            </el-form-item>
+          </el-form>
+        </el-card>
+      </div>
+    </transition>
+
+    <el-card shadow="never">
+      <template #header>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="19"> 退货单信息列表 </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" plain>关闭订单</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" plain>删除订单</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" plain>导出订单</el-button>
+          </el-col>
+        </el-row>
+      </template>
+
+      <el-table v-loading="loading" border :data="orderReturnList" @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="订单时间" align="center" prop="createTime" width="180">
+          <template #default="scope">
+            <span>{{ scope.row.createTime }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="售后单号" align="center" prop="returnNo" />
+        <el-table-column label="售后类型" align="center" prop="serviceType">
+          <template #default="scope">
+            <dict-tag :options="return_type" :value="scope.row.serviceType" />
+          </template>
+        </el-table-column>
+        <el-table-column label="客户编号" align="center" prop="customerNo" />
+        <el-table-column label="客户姓名" align="center" prop="customerName" />
+        <el-table-column label="售后金额" align="center" prop="afterSaleAmount" />
+        <el-table-column label="订单状态" align="center" prop="returnStatus">
+          <template #default="scope">
+            <dict-tag :options="return_order_status" :value="scope.row.returnStatus" />
+          </template>
+        </el-table-column>
+        <el-table-column label="退货原因" align="center" prop="returnReason" />
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+          <template #default="scope">
+            <el-button link type="primary" icon="Edit" @click="handleReview(scope.row)" v-hasPermi="['order:orderReturn:edit']"
+              >查看退货信息</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+    </el-card>
+  </div>
+</template>
+
+<script setup name="OrderReturn" lang="ts">
+import { listOrderReturn, getOrderReturn, delOrderReturn, addOrderReturn, updateOrderReturn } from '@/api/order/orderReturn';
+import { OrderReturnVO, OrderReturnQuery, OrderReturnForm } from '@/api/order/orderReturn/types';
+import { listReturnReason } from '@/api/order/returnReason';
+import { ReturnReasonVO } from '@/api/order/returnReason/types';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { return_order_status, return_type } = toRefs<any>(proxy?.useDict('return_order_status', 'return_type'));
+
+const orderReturnList = ref<OrderReturnVO[]>([]);
+const returnReasonList = ref<ReturnReasonVO[]>([]);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<string | number>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
+
+const queryFormRef = ref<ElFormInstance>();
+const orderReturnFormRef = ref<ElFormInstance>();
+const router = useRouter();
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+
+const initFormData: OrderReturnForm = {
+  id: undefined,
+  orderId: undefined,
+  orderNo: undefined,
+  serviceType: undefined,
+  returnTime: undefined,
+  returnNo: undefined,
+  customerId: undefined,
+  customerNo: undefined,
+  customerName: undefined,
+  afterSaleAmount: undefined,
+  returnStatus: undefined,
+  returnProductNum: undefined,
+  processingTime: undefined,
+  returnReasonId: undefined,
+  returnReason: undefined,
+  problemDescription: undefined,
+  voucherPhoto: undefined,
+  shippingFee: undefined,
+  isShippingFee: undefined,
+  orderAmount: undefined,
+  returnAmount: undefined,
+  afterSalesRemarks: undefined,
+  returnMethod: undefined,
+  chargebackName: undefined,
+  chargebackPhone: undefined,
+  chargebackPickupTime: undefined,
+  chargebackProvincial: undefined,
+  chargebackCity: undefined,
+  chargebackCounty: undefined,
+  provincialCityCounty: undefined,
+  chargebackAddress: undefined,
+  pushStatus: undefined,
+  logisticsId: undefined,
+  logisticsName: undefined,
+  logisticsNo: undefined,
+  status: undefined,
+  remark: undefined
+};
+const data = reactive<PageData<OrderReturnForm, OrderReturnQuery>>({
+  form: { ...initFormData },
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    orderId: undefined,
+    orderNo: undefined,
+    serviceType: undefined,
+    returnNo: undefined,
+    customerId: undefined,
+    customerNo: undefined,
+    customerName: undefined,
+    returnStatus: undefined,
+    processingTime: undefined,
+    returnReasonId: undefined,
+    returnReason: undefined,
+    pushStatus: undefined,
+    status: undefined,
+    params: {}
+  },
+  rules: {}
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+/** 查询退货主列表 */
+const getList = async () => {
+  loading.value = true;
+  const res = await listOrderReturn(proxy?.addDateRange(queryParams.value, dateRange.value));
+  orderReturnList.value = res.rows;
+  total.value = res.total;
+  loading.value = false;
+};
+
+/** 取消按钮 */
+const cancel = () => {
+  reset();
+  dialog.visible = false;
+};
+
+/** 表单重置 */
+const reset = () => {
+  form.value = { ...initFormData };
+  orderReturnFormRef.value?.resetFields();
+};
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.value.pageNum = 1;
+  getList();
+};
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  dateRange.value = ['', ''];
+  queryFormRef.value?.resetFields();
+  handleQuery();
+};
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection: OrderReturnVO[]) => {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+
+/** 新增按钮操作 */
+const handleAdd = () => {
+  reset();
+  dialog.visible = true;
+  dialog.title = '添加退货主';
+};
+
+const handleReview = (row?: OrderReturnVO) => {
+  router.push({
+    path: '/order-manage/return-detail',
+    query: { id: row.id }
+  });
+};
+
+/** 提交按钮 */
+const submitForm = () => {
+  orderReturnFormRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      buttonLoading.value = true;
+      if (form.value.id) {
+        await updateOrderReturn(form.value).finally(() => (buttonLoading.value = false));
+      } else {
+        await addOrderReturn(form.value).finally(() => (buttonLoading.value = false));
+      }
+      proxy?.$modal.msgSuccess('操作成功');
+      dialog.visible = false;
+      await getList();
+    }
+  });
+};
+
+/** 删除按钮操作 */
+const handleDelete = async (row?: OrderReturnVO) => {
+  const _ids = row?.id || ids.value;
+  await proxy?.$modal.confirm('是否确认删除退货主编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
+  await delOrderReturn(_ids);
+  proxy?.$modal.msgSuccess('删除成功');
+  await getList();
+};
+
+/** 导出按钮操作 */
+const handleExport = () => {
+  proxy?.download(
+    'order/orderReturn/export',
+    {
+      ...queryParams.value
+    },
+    `orderReturn_${new Date().getTime()}.xlsx`
+  );
+};
+
+// 加载退货原因列表
+const loadReturnReasonList = async () => {
+  try {
+    const res = await listReturnReason({
+      pageNum: 1,
+      pageSize: 1000
+    });
+    returnReasonList.value = res.rows || [];
+  } catch (error) {
+    console.error('加载退货原因列表失败:', error);
+    returnReasonList.value = [];
+  }
+};
+
+onMounted(() => {
+  getList();
+  loadReturnReasonList();
+});
+</script>

+ 265 - 0
src/views/order/orderReturn/returnDetail.vue

@@ -0,0 +1,265 @@
+<template>
+  <div class="app-container">
+    <el-card shadow="never" class="mb-2">
+      <!-- 订单信息 -->
+      <el-descriptions title="订单信息" :column="2" border class="custom-descriptions">
+        <!-- 第一行 -->
+        <el-descriptions-item label="申请时间">{{ orderDetail.createTime }}</el-descriptions-item>
+        <el-descriptions-item label="申请单号">{{ orderDetail.returnNo }}</el-descriptions-item>
+
+        <!-- 第二行 -->
+        <el-descriptions-item label="订单编号">{{ orderDetail.orderNo }}</el-descriptions-item>
+        <el-descriptions-item label="订单状态">
+          <dict-tag :options="return_order_status" :value="orderDetail.returnStatus" />
+        </el-descriptions-item>
+
+        <!-- 第三行 -->
+        <el-descriptions-item label="退货金额">{{ orderDetail.afterSaleAmount }}</el-descriptions-item>
+        <el-descriptions-item label="售后完成时间">{{ orderDetail.processingTime }}</el-descriptions-item>
+
+        <!-- 第四行 -->
+        <el-descriptions-item label="售后处理方式"> <dict-tag :options="return_type" :value="orderDetail.serviceType" /></el-descriptions-item>
+        <el-descriptions-item label="退货原因">{{ orderDetail.returnReason }}</el-descriptions-item>
+
+        <!-- 以下每项独占一行(span=2) -->
+        <el-descriptions-item label="问题描述" :span="2">
+          {{ orderDetail.problemDescription || '无' }}
+        </el-descriptions-item>
+
+        <el-descriptions-item label="售后备注" :span="2">
+          {{ orderDetail.remark || '无' }}
+        </el-descriptions-item>
+
+        <el-descriptions-item label="凭证照片" :span="2">
+          <div v-if="orderDetail.voucherPhoto && orderDetail.voucherPhoto.length > 0">
+            <el-image
+              v-for="(url, index) in orderDetail.voucherPhoto"
+              :key="index"
+              :src="url"
+              :preview-src-list="orderDetail.voucherPhoto.split(',')"
+              style="width: 80px; height: 80px; margin-right: 8px; object-fit: cover"
+              fit="cover"
+              :initial-index="index"
+            />
+          </div>
+          <span v-else>无</span>
+        </el-descriptions-item>
+      </el-descriptions>
+    </el-card>
+
+    <!-- 商品明细 -->
+    <el-card shadow="never" class="mb-2">
+      <template #header>
+        <span>商品明细</span>
+      </template>
+      <el-table :data="productList" border style="width: 100%">
+        <el-table-column prop="productNo" label="商品编号" />
+        <el-table-column label="商品图片" width="100">
+          <template #default="scope">
+            <el-image v-if="scope.row.productImage" :src="scope.row.productImage" style="width: 60px; height: 60px" fit="cover" />
+            <span v-else>暂无图片</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="productName" label="商品名称" min-width="150" />
+        <el-table-column prop="productUnit" label="产品类别" />
+        <el-table-column prop="productUnit" label="单位" />
+        <el-table-column prop="unitPrice" label="单价" />
+        <el-table-column prop="returnQuantity" label="退货数量" />
+        <el-table-column prop="totalAmount" label="金额" />
+      </el-table>
+    </el-card>
+    <div class="mt-2 text-right" style="margin-right: 20px">
+      <span
+        >商品数:{{ totalQuantity }}, 合计金额<span style="color: #f56c6c">{{ totalAmount }}</span></span
+      >
+    </div>
+    <!-- 信息汇总 -->
+    <el-card shadow="never" class="mb-2">
+      <template #header>
+        <div class="card-header">
+          <span>信息汇总</span>
+        </div>
+      </template>
+
+      <el-table :data="summaryData" border style="width: 100%">
+        <el-table-column prop="" label="签收数量" align="center" />
+        <el-table-column prop="" label="已售后数量" align="center" />
+        <el-table-column prop="" label="售后数量" align="center" />
+        <el-table-column prop="" label="退回运费" align="center" />
+        <el-table-column prop="" label="订单总金额" align="center" />
+        <el-table-column prop="" label="退货总金额" align="center" />
+      </el-table>
+    </el-card>
+
+    <!-- 底部按钮 -->
+    <div class="text-center mt-4">
+      <el-button @click="goBack">返回</el-button>
+    </div>
+  </div>
+</template>
+
+<script setup name="ReturnDetail" lang="ts">
+import { ref, computed, onMounted } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
+import { getOrderReturn } from '@/api/order/orderReturn';
+import { OrderReturnVO } from '@/api/order/orderReturn/types';
+import { OrderReturnItemVO } from '@/api/order/orderReturnItem/types';
+import { getCustomerInfo } from '@/api/customer/customerFile/customerInfo';
+import { CustomerInfoVO } from '@/api/customer/customerFile/customerInfo/types';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { return_order_status, return_type, fee_type, pay_method } = toRefs<any>(
+  proxy?.useDict('return_order_status', 'return_type', 'fee_type', 'pay_method')
+);
+const route = useRoute();
+const router = useRouter();
+
+// 订单详情
+const orderDetail = ref<OrderReturnVO>({} as OrderReturnVO);
+
+// 客户信息
+const customerInfo = ref<CustomerInfoVO>({} as CustomerInfoVO);
+
+// 商品明细列表
+const productList = ref<OrderReturnItemVO[]>([]);
+
+// 计算商品总数(所有商品的采购数量之和)
+const totalQuantity = computed(() => {
+  return productList.value.reduce((sum, item) => {
+    return sum + (Number(item.returnQuantity) || 0);
+  }, 0);
+});
+
+// 获取订单详情
+const getOrderDetail = async () => {
+  const orderId = route.query.id || route.params.id;
+  if (!orderId) {
+    proxy?.$modal.msgError('订单ID不能为空');
+    return;
+  }
+
+  try {
+    const res = await getOrderReturn(orderId as any);
+    orderDetail.value = res.data;
+
+    // 获取商品明细
+    if (orderDetail.value.orderReturnItemList) {
+      productList.value = orderDetail.value.orderReturnItemList;
+    } else if (orderDetail.value.id) {
+      await getProductList(orderDetail.value);
+    }
+
+    // 获取客户信息
+    if (orderDetail.value.customerId) {
+      await getCustomerDetail(orderDetail.value.customerId);
+    }
+  } catch (error) {
+    console.error('获取订单详情失败:', error);
+    proxy?.$modal.msgError('获取订单详情失败');
+  }
+};
+
+// 获取商品明细列表
+const getProductList = async (orderDetail: OrderReturnVO) => {
+  try {
+    productList.value = orderDetail.orderReturnItemList || [];
+  } catch (error) {
+    console.error('获取商品明细失败:', error);
+  }
+};
+
+// 计算商品总金额(所有商品的小计之和)
+const totalAmount = computed(() => {
+  return productList.value.reduce((sum, item) => {
+    return sum + (Number(item.totalAmount) || 0);
+  }, 0);
+});
+
+// 计算应付款金额(订单总金额 + 运费)
+const payableAmount = computed(() => {
+  const shipping = Number(orderDetail.value.shippingFee) || 0;
+  return totalAmount.value + shipping;
+});
+// 汇总数据(用于表格显示)
+const summaryData = computed(() => {
+  return [
+    {
+      quantity: totalQuantity.value,
+      shippingFee: `¥${(Number(orderDetail.value.shippingFee) || 0).toFixed(2)}`,
+      totalAmount: `¥${totalAmount.value.toFixed(2)}`,
+      payableAmount: `¥${payableAmount.value.toFixed(2)}`
+    }
+  ];
+});
+
+// 获取客户详情
+const getCustomerDetail = async (customerId: string | number) => {
+  try {
+    const res = await getCustomerInfo(customerId);
+    customerInfo.value = res.data;
+  } catch (error) {
+    console.error('获取客户信息失败:', error);
+  }
+};
+
+// 字典label工具
+function getDictLabel(dictList: any[], value: string) {
+  if (!dictList || !Array.isArray(dictList)) return value || '--';
+  const found = dictList.find((item) => item.value === value);
+  return found ? found.label : value || '--';
+}
+
+// 返回
+const goBack = () => {
+  router.back();
+};
+
+// 打印
+const handlePrint = () => {
+  window.print();
+};
+
+onMounted(() => {
+  getOrderDetail();
+});
+</script>
+
+<style scoped lang="scss">
+.mb-2 {
+  margin-bottom: 16px;
+}
+
+.mt-4 {
+  margin-top: 32px;
+}
+
+.text-center {
+  text-align: center;
+}
+
+.detail-item {
+  padding: 8px 0;
+  line-height: 1.8;
+
+  .label {
+    color: #909399;
+    margin-right: 8px;
+  }
+}
+
+:deep(.custom-descriptions .el-descriptions__label) {
+  width: 160px;
+  /* 可选:强制不换行 */
+  white-space: nowrap;
+}
+:deep(.custom-descriptions .el-descriptions__content) {
+  /* 内容区域自动占剩余空间 */
+  flex: 1;
+}
+
+@media print {
+  .el-button {
+    display: none;
+  }
+}
+</style>

+ 135 - 0
src/views/order/orderService/index.vue

@@ -0,0 +1,135 @@
+<template>
+  <div class="p-2">
+    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+      <div v-show="showSearch" class="mb-[10px]">
+        <el-card shadow="hover">
+          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
+            <el-form-item label="客户名称" prop="">
+              <el-input placeholder="请输入客户名称" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="单号">
+              <el-input placeholder="请输入单号" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="收货人">
+              <el-input placeholder="请输入收货人" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="申请时间" prop="createTime">
+              <el-date-picker type="date" />
+            </el-form-item>
+            <el-form-item>
+              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+            </el-form-item>
+          </el-form>
+        </el-card>
+      </div>
+    </transition>
+
+    <el-card shadow="never">
+      <template #header>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="22"> 服务工单信息列表 </el-col>
+        </el-row>
+      </template>
+
+      <el-table v-loading="loading" border :data="orderServiceList" @selection-change="handleSelectionChange">
+        <el-table-column label="订单时间" align="center" prop="createTime">
+          <template #default="scope">
+            <span>{{ parseTime(scope.row.createTime) }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="订单编号" align="center" prop="" />
+        <el-table-column label="维保项目" align="center" prop="" />
+        <el-table-column label="客户编号" align="center" prop="" />
+        <el-table-column label="客户名称" align="center" prop="" />
+        <el-table-column label="业务员" align="center" prop="" />
+        <el-table-column label="客服" align="center" prop="" />
+        <el-table-column label="归属部门" align="center" prop="" />
+        <el-table-column label="技术工程师" align="center" prop="" />
+        <el-table-column label="预约时间" align="center" prop="" />
+        <el-table-column label="完成时间" align="center" prop="">
+          <!-- <template #default="scope">
+            <span>{{ parseTime(scope.row.createTime),'{y}-{m}-{d}') }}</span>
+          </template> -->
+        </el-table-column>
+        <el-table-column label="订单状态" align="center" prop="" />
+
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+          <template #default="scope">
+            <el-button link type="primary" @click="handleReview(scope.row)" v-hasPermi="['order:orderService:edit']">查看</el-button>
+            <el-button link type="primary" @click="handleFinish(scope.row)" v-hasPermi="['order:orderService:edit']">完成</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+    </el-card>
+  </div>
+</template>
+
+<script setup name="OrderService" lang="ts">
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { sys_platform_yes_no, check_status, revenue_type } = toRefs<any>(proxy?.useDict('sys_platform_yes_no', 'check_status', 'revenue_type'));
+
+const orderServiceList = ref<[]>([]);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<string | number>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const router = useRouter();
+const queryFormRef = ref<ElFormInstance>();
+const queryParams = reactive<any>({
+  pageNum: 1,
+  pageSize: 10
+});
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+
+/** 表单重置 */
+const reset = (row?: any) => {};
+
+const handleReview = (row?: any) => {
+  router.push({
+    path: '/order-manage/service-detail',
+    query: { id: row.id }
+  });
+};
+
+const handleFinish = (row?: any) => {};
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.value.pageNum = 1;
+  getList();
+};
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value?.resetFields();
+  handleQuery();
+};
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection: any[]) => {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+const getList = () => {
+  loading.value = true;
+  setTimeout(() => {
+    loading.value = false;
+  }, 1000);
+};
+
+onMounted(() => {
+  getList();
+});
+
+onActivated(() => {});
+</script>

+ 290 - 0
src/views/order/orderService/serviceDetail.vue

@@ -0,0 +1,290 @@
+<template>
+  <div class="p-4">
+    <!-- 顶部返回按钮 -->
+    <div class="mb-4">
+      <el-button @click="handleBack">
+        <el-icon><ArrowLeft /></el-icon>
+        返回
+      </el-button>
+      <span class="ml-4 text-lg font-medium">华南上单</span>
+    </div>
+
+    <el-row :gutter="20">
+      <!-- 左侧:工单信息 -->
+      <el-col :span="16">
+        <!-- 工单信息 -->
+        <el-card shadow="never" class="mb-4">
+          <template #header>
+            <span class="font-medium">工单信息</span>
+          </template>
+
+          <!-- 基础信息 -->
+          <div class="mb-4">
+            <div class="text-sm text-gray-500 mb-2">基础信息</div>
+            <el-row :gutter="20">
+              <el-col :span="8">
+                <div class="info-item">
+                  <span class="label">工单编号:</span>
+                  <span class="value">{{ orderInfo.orderNo }}</span>
+                </div>
+              </el-col>
+              <el-col :span="8">
+                <div class="info-item">
+                  <span class="label">客户名称:</span>
+                  <span class="value">{{ orderInfo.customerName }}</span>
+                </div>
+              </el-col>
+              <el-col :span="8">
+                <div class="info-item">
+                  <span class="label">联系人:</span>
+                  <span class="value">{{ orderInfo.contactPerson }}</span>
+                </div>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20" class="mt-2">
+              <el-col :span="8">
+                <div class="info-item">
+                  <span class="label">联系电话:</span>
+                  <span class="value">{{ orderInfo.contactPhone }}</span>
+                </div>
+              </el-col>
+            </el-row>
+          </div>
+
+          <!-- 派单信息 -->
+          <div class="mb-4">
+            <div class="text-sm text-gray-500 mb-2">派单信息</div>
+            <el-row :gutter="20">
+              <el-col :span="8">
+                <div class="info-item">
+                  <span class="label">派单人员:</span>
+                  <span class="value">{{ orderInfo.assignPerson }}</span>
+                </div>
+              </el-col>
+              <el-col :span="8">
+                <div class="info-item">
+                  <span class="label">联系方式:</span>
+                  <span class="value">{{ orderInfo.assignPhone }}</span>
+                </div>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20" class="mt-2">
+              <el-col :span="8">
+                <div class="info-item">
+                  <span class="label">工单时间:</span>
+                  <span class="value">{{ orderInfo.orderTime }}</span>
+                </div>
+              </el-col>
+              <el-col :span="8">
+                <div class="info-item">
+                  <span class="label">重点:</span>
+                  <span class="value">{{ orderInfo.priority }}</span>
+                </div>
+              </el-col>
+            </el-row>
+          </div>
+
+          <!-- 完成信息 -->
+          <div>
+            <div class="text-sm text-gray-500 mb-2">完成信息</div>
+            <el-row :gutter="20">
+              <el-col :span="8">
+                <div class="info-item">
+                  <span class="label">完成时间:</span>
+                  <span class="value">{{ orderInfo.completeTime }}</span>
+                </div>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20" class="mt-2">
+              <el-col :span="16">
+                <div class="info-item">
+                  <span class="label">完成地址:</span>
+                  <span class="value">{{ orderInfo.completeAddress }}</span>
+                </div>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20" class="mt-2">
+              <el-col :span="16">
+                <div class="info-item">
+                  <span class="label">完成状态:</span>
+                  <span class="value">{{ orderInfo.completeStatus }}</span>
+                </div>
+              </el-col>
+            </el-row>
+          </div>
+        </el-card>
+
+        <!-- 接单/派工 -->
+        <el-card shadow="never">
+          <template #header>
+            <span class="font-medium">接单 / 派工</span>
+          </template>
+
+          <el-form :model="dispatchForm" label-width="100px">
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item label="技术人员" prop="technicianId">
+                  <el-input v-model="dispatchForm.technician" placeholder="请输入" />
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="联系方式" prop="technicianPhone">
+                  <el-input v-model="dispatchForm.technicianPhone" placeholder="请输入" />
+                </el-form-item>
+              </el-col>
+            </el-row>
+
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item label="预约时间" prop="appointmentTime">
+                  <el-date-picker
+                    v-model="dispatchForm.appointmentTime"
+                    type="datetime"
+                    placeholder="请选择"
+                    class="w-full"
+                    value-format="YYYY-MM-DD HH:mm:ss"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
+
+            <el-row :gutter="20">
+              <el-col :span="24">
+                <el-form-item label="现场地址" prop="siteAddress">
+                  <el-input v-model="dispatchForm.siteAddress" placeholder="请输入现场地址" />
+                </el-form-item>
+              </el-col>
+            </el-row>
+
+            <el-row :gutter="20">
+              <el-col :span="24">
+                <el-form-item label="上传附件" prop="attachments">
+                  <el-upload class="upload-demo" action="#" :auto-upload="false" :file-list="fileList">
+                    <el-button type="primary">点击上传</el-button>
+                  </el-upload>
+                </el-form-item>
+              </el-col>
+            </el-row>
+
+            <el-row :gutter="20">
+              <el-col :span="24">
+                <el-form-item label="预期解决" prop="expectedSolution">
+                  <el-input v-model="dispatchForm.expectedSolution" type="textarea" :rows="4" placeholder="请输入预期解决方案" />
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </el-form>
+        </el-card>
+      </el-col>
+
+      <!-- 右侧:操作进度时间线 -->
+      <el-col :span="8">
+        <el-card shadow="never">
+          <template #header>
+            <span class="font-medium">操作 / 进度</span>
+          </template>
+
+          <el-timeline>
+            <el-timeline-item v-for="(item, index) in timeline" :key="index" :timestamp="item.timestamp" placement="top">
+              <div class="timeline-content">
+                <div class="font-medium">{{ item.title }}</div>
+                <div class="text-sm text-gray-500 mt-1">{{ item.description }}</div>
+              </div>
+            </el-timeline-item>
+          </el-timeline>
+        </el-card>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts" name="ServiceDetail">
+import { ArrowLeft } from '@element-plus/icons-vue';
+
+const route = useRoute();
+const router = useRouter();
+
+// 工单信息
+const orderInfo = reactive({
+  orderNo: 'HL',
+  customerName: '华南上单',
+  contactPerson: '张三',
+  contactPhone: '13800138000',
+  assignPerson: '中联',
+  assignPhone: '1',
+  orderTime: '2022-11-17 09:00:00',
+  priority: '1',
+  completeTime: '2022-11-17 09:00:00',
+  completeAddress: '广东省深圳市',
+  completeStatus: '已完成'
+});
+
+// 派工表单
+const dispatchForm = reactive({
+  technician: '',
+  technicianPhone: '',
+  appointmentTime: '',
+  siteAddress: '',
+  expectedSolution: ''
+});
+
+// 文件列表
+const fileList = ref([]);
+
+// 时间线数据
+const timeline = ref([
+  {
+    timestamp: '2022-11-17 09:00:00',
+    title: '工单创建',
+    description: '工单已创建'
+  },
+  {
+    timestamp: '2022-11-17 10:00:00',
+    title: '已派单',
+    description: '已分配给技术人员'
+  },
+  {
+    timestamp: '2022-11-17 14:00:00',
+    title: '进行中',
+    description: '技术人员正在处理'
+  }
+]);
+
+// 返回
+const handleBack = () => {
+  router.back();
+};
+</script>
+
+<style scoped lang="scss">
+.info-item {
+  display: flex;
+  align-items: center;
+  margin-bottom: 8px;
+
+  .label {
+    color: #606266;
+    font-size: 14px;
+    white-space: nowrap;
+  }
+
+  .value {
+    color: #303133;
+    font-size: 14px;
+    margin-left: 4px;
+  }
+}
+
+.timeline-content {
+  padding: 8px 0;
+}
+
+:deep(.el-card__header) {
+  padding: 16px 20px;
+  border-bottom: 1px solid #ebeef5;
+}
+
+:deep(.el-card__body) {
+  padding: 20px;
+}
+</style>

+ 571 - 0
src/views/order/revenueHeader/add.vue

@@ -0,0 +1,571 @@
+<template>
+  <div class="p-2">
+    <!-- 页面标题 -->
+    <el-card shadow="never" class="mb-2">
+      <div class="flex justify-between items-center">
+        <div class="flex items-center">
+          <el-button link @click="handleBack" class="mr-2">
+            <el-icon class="mr-1"><ArrowLeft /></el-icon>
+            返回
+          </el-button>
+          <span class="text-lg font-bold">{{ pageTitle }}</span>
+        </div>
+        <el-button type="primary" @click="submitForm" :loading="buttonLoading">保存</el-button>
+      </div>
+    </el-card>
+
+    <!-- 基本信息 -->
+    <el-card shadow="never" class="mb-2">
+      <el-form ref="revenueHeaderFormRef" :model="form" :rules="rules" label-width="120px">
+        <el-row :gutter="20" v-if="form.revenueType == '0'">
+          <el-col :span="8">
+            <el-form-item label="客户编号:" prop="customerCode">
+              <el-select
+                v-model="form.customerCode"
+                placeholder="请输入客户编号"
+                style="width: 100%"
+                filterable
+                remote
+                :remote-method="handleSearchCustomer"
+                :loading="customerSearchLoading"
+                @change="handleCustomerChange"
+                clearable
+              >
+                <el-option
+                  v-for="customer in filteredCustomerList"
+                  :key="customer.id"
+                  :label="`${customer.customerNo} - ${customer.customerName}`"
+                  :value="customer.customerNo"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="收入单类型:" prop="revenueType">
+              <el-select v-model="form.revenueType" placeholder="请选择" style="width: 100%" disabled>
+                <el-option v-for="dict in revenue_type" :key="dict.value" :label="dict.label" :value="dict.value" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="所属公司:" prop="companyName">
+              <el-input v-model="form.companyName" disabled />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20" v-if="form.revenueType == '1'">
+          <el-col :span="8">
+            <el-form-item label="收入单类型:" prop="revenueType">
+              <el-select v-model="form.revenueType" placeholder="请选择" style="width: 100%" disabled>
+                <el-option v-for="dict in revenue_type" :key="dict.value" :label="dict.label" :value="dict.value" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="所属公司:" prop="companyName">
+              <el-input v-model="form.companyName" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="供应商:" prop="supplierName">
+              <el-select
+                v-model="form.supplierName"
+                placeholder="请输入供应商名称"
+                style="width: 100%"
+                filterable
+                remote
+                :remote-method="handleSearchCustomer"
+                :loading="customerSearchLoading"
+                @change="handleCustomerChange"
+                clearable
+              >
+                <el-option
+                  v-for="customer in filteredCustomerList"
+                  :key="customer.id"
+                  :label="`${customer.customerNo} - ${customer.customerName}`"
+                  :value="customer.customerNo"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="业务部门:" prop="businessDept">
+              <el-input v-model="form.businessDept" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="客服人员:" prop="customerService">
+              <el-input v-model="form.customerService" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="业务员:" prop="businessStaff">
+              <el-input v-model="form.businessStaff" disabled />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="是否含税:" prop="isPrwTax">
+              <el-radio-group v-model="form.isPrwTax">
+                <el-radio v-for="dict in sys_platform_yes_no" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="交易币别:" prop="currencyId">
+              <el-select v-model="form.currencyId" placeholder="请选择" style="width: 100%" clearable>
+                <el-option v-for="currency in currencyList" :key="currency.id" :label="currency.currencyName" :value="currency.id" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="16">
+            <el-form-item label="备注:" prop="remark">
+              <el-input v-model="form.remark" type="textarea" :min="3" placeholder="请输入备注" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+    </el-card>
+
+    <!-- 其他信息 -->
+    <el-card shadow="never">
+      <template #header>
+        <div class="flex justify-between items-center">
+          <span>其他信息:</span>
+          <el-button type="primary" plain @click="handleAddDetail">新增</el-button>
+        </div>
+        <div style="margin-left: 60px">
+          <span>总计:{{ totalAmount.toFixed(2) }}</span>
+        </div>
+      </template>
+
+      <el-table :data="detailList" border style="width: 100%">
+        <el-table-column label="费用类型" min-width="150" align="center">
+          <template #default="scope">
+            <el-select v-model="scope.row.revenueId" placeholder="请选择" style="width: 100%">
+              <el-option v-for="item in feeTypeList" :key="item.id" :label="`${item.revenueCode},${item.revenueName}`" :value="item.id" />
+            </el-select>
+          </template>
+        </el-table-column>
+        <el-table-column label="数量" min-width="120" align="center">
+          <template #default="scope">
+            <el-input-number
+              v-model="scope.row.quantity"
+              :precision="0"
+              :controls="false"
+              style="width: 100%"
+              placeholder="请输入"
+              @change="handleQuantityOrPriceChange(scope.$index)"
+            />
+          </template>
+        </el-table-column>
+        <el-table-column label="单价" min-width="120" align="center">
+          <template #default="scope">
+            <el-input-number
+              v-model="scope.row.unitPrice"
+              :precision="2"
+              :controls="false"
+              style="width: 100%"
+              placeholder="请输入"
+              @change="handleQuantityOrPriceChange(scope.$index)"
+            />
+          </template>
+        </el-table-column>
+        <el-table-column label="总金额" min-width="120" align="center">
+          <template #default="scope">
+            <el-input-number
+              v-model="scope.row.totalAmount"
+              :precision="2"
+              :controls="false"
+              style="width: 100%"
+              placeholder="请输入"
+              @change="calculateTotal"
+            />
+          </template>
+        </el-table-column>
+        <el-table-column label="备注" min-width="150" align="center">
+          <template #default="scope">
+            <el-input v-model="scope.row.remark" placeholder="请输入" />
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="80" fixed="right" align="center">
+          <template #default="scope">
+            <el-button link type="danger" @click="handleDeleteDetail(scope.$index)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-card>
+  </div>
+</template>
+<script setup lang="ts">
+import { useRouter } from 'vue-router';
+import { listRevenueHeader, getRevenueHeader, addRevenueHeader, updateRevenueHeader } from '@/api/order/revenueHeader';
+import { RevenueHeaderVO, RevenueHeaderQuery, RevenueHeaderForm } from '@/api/order/revenueHeader/types';
+import { listCustomerInfo, getCustomerInfo } from '@/api/customer/customerFile/customerInfo';
+import { CustomerInfoVO } from '@/api/customer/customerFile/customerInfo/types';
+import { listRevenueExpense } from '@/api/company/revenueExpense';
+import { RevenueExpenseVO } from '@/api/company/revenueExpense/types';
+import { listComCurrency } from '@/api/company/comCurrency';
+import { ComCurrencyVO } from '@/api/company/comCurrency/types';
+import { getCompany } from '@/api/company/company';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { sys_platform_yes_no, check_status, revenue_type } = toRefs<any>(proxy?.useDict('sys_platform_yes_no', 'check_status', 'revenue_type'));
+const router = useRouter();
+const route = useRoute();
+
+const revenueHeaderFormRef = ref();
+const buttonLoading = ref(false);
+const customerList = ref<CustomerInfoVO[]>([]);
+const filteredCustomerList = ref<CustomerInfoVO[]>([]);
+const customerSearchLoading = ref(false);
+const feeTypeList = ref<RevenueExpenseVO[]>([]);
+const currencyList = ref<ComCurrencyVO[]>([]);
+
+// 防抖定时器
+let searchTimer: NodeJS.Timeout | null = null;
+const detailList = ref<any[]>([]);
+
+// 计算总金额
+const totalAmount = computed(() => {
+  return detailList.value.reduce((sum, item) => {
+    const amount = Number(item.totalAmount) || 0;
+    return sum + amount;
+  }, 0);
+});
+
+// 表单初始数据
+const initFormData: RevenueHeaderForm = {
+  id: undefined,
+  revenueType: '收入申请',
+  orderRevenueCode: undefined,
+  incomeOrderCode: undefined,
+  otherRevenueType: undefined,
+  customerId: undefined,
+  customerCode: undefined,
+  supplierId: undefined,
+  isPrwTax: '0',
+  currencyId: undefined,
+  pushStatus: undefined,
+  orderFile: undefined,
+  status: undefined,
+  remark: undefined,
+  companyId: undefined,
+  businessDept: undefined,
+  customerService: undefined,
+  businessStaff: undefined,
+  createTime: new Date().toISOString().split('T')[0],
+  orderRevenueDetails: []
+};
+
+const data = reactive<PageData<RevenueHeaderForm, RevenueHeaderQuery>>({
+  form: { ...initFormData },
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    revenueType: undefined,
+    orderRevenueCode: undefined,
+    incomeOrderCode: undefined,
+    otherRevenueType: undefined,
+    customerId: undefined,
+    supplierId: undefined,
+    isPrwTax: undefined,
+    currencyId: undefined,
+    pushStatus: undefined,
+    orderFile: undefined,
+    status: undefined,
+    platformCode: undefined,
+    params: {}
+  },
+  rules: {
+    revenueType: [{ required: true, message: '收入单类型不能为空', trigger: 'change' }],
+    customerCode: [{ required: true, message: '客户编号不能为空', trigger: 'blur' }],
+    companyId: [{ required: true, message: '所属公司不能为空', trigger: 'change' }],
+    currencyId: [{ required: true, message: '交易币别不能为空', trigger: 'change' }],
+    isPrwTax: [{ required: true, message: '是否含税不能为空', trigger: 'change' }]
+  }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+// 防抖搜索客户
+const handleSearchCustomer = (query: string) => {
+  if (searchTimer) {
+    clearTimeout(searchTimer);
+  }
+
+  if (!query) {
+    filteredCustomerList.value = [];
+    return;
+  }
+
+  customerSearchLoading.value = true;
+
+  searchTimer = setTimeout(async () => {
+    try {
+      const res = await listCustomerInfo({
+        customerNo: query,
+        pageNum: 1,
+        pageSize: 10
+      });
+      filteredCustomerList.value = res.rows || [];
+    } catch (error) {
+      console.error('搜索客户失败:', error);
+      filteredCustomerList.value = [];
+    } finally {
+      customerSearchLoading.value = false;
+    }
+  }, 500);
+};
+
+// 客户选择变化
+const handleCustomerChange = async (customerNo: string) => {
+  if (!customerNo) {
+    // 清空相关字段
+    form.value.customerId = undefined;
+    form.value.customerName = '';
+    form.value.companyName = '';
+    form.value.businessDept = '';
+    form.value.customerService = '';
+    form.value.businessStaff = '';
+    return;
+  }
+
+  try {
+    // 从筛选列表中找到选中的客户
+    const selectedCustomer = filteredCustomerList.value.find((c) => c.customerNo === customerNo);
+    if (!selectedCustomer) return;
+
+    // 获取客户详细信息
+    const res = await getCustomerInfo(selectedCustomer.id);
+    const customerInfo = res.data;
+
+    // 填充客户信息
+    form.value.customerId = customerInfo.id;
+    form.value.customerName = customerInfo.customerName;
+
+    // 从客户销售信息中获取业务信息
+    if (customerInfo.customerSalesInfoVo) {
+      const salesInfo = customerInfo.customerSalesInfoVo as any;
+      form.value.businessStaff = salesInfo.businessStaffName || '';
+      form.value.customerService = salesInfo.customerServiceName || '';
+      form.value.businessDept = salesInfo.businessDeptName || '';
+    }
+
+    // 获取所属公司信息
+    if (customerInfo.belongCompanyId) {
+      try {
+        const companyRes = await getCompany(customerInfo.belongCompanyId);
+        form.value.companyName = companyRes.data.companyName || '';
+        form.value.companyId = customerInfo.belongCompanyId;
+      } catch (error) {
+        console.error('获取公司信息失败:', error);
+      }
+    }
+  } catch (error) {
+    console.error('获取客户信息失败:', error);
+    ElMessage.error('获取客户信息失败');
+  }
+};
+
+// 加载费用类型列表
+const loadFeeTypeList = async () => {
+  try {
+    // 根据revenueType决定查询条件
+    const queryParams: any = {
+      isShow: '0',
+      pageNum: 1,
+      pageSize: 1000
+    };
+
+    if (form.value.revenueType === '0') {
+      // 收入申请:查询收入类
+      queryParams.revenueFlag = '0';
+    } else if (form.value.revenueType === '1') {
+      // 费用申请:查询费用类
+      queryParams.expenseFlag = '0';
+    }
+
+    const res = await listRevenueExpense(queryParams);
+    feeTypeList.value = res.rows || [];
+  } catch (error) {
+    console.error('加载费用类型列表失败:', error);
+    feeTypeList.value = [];
+  }
+};
+
+// 加载币种列表
+const loadCurrencyList = async () => {
+  try {
+    const res = await listComCurrency({
+      isShow: '0',
+      pageNum: 1,
+      pageSize: 1000
+    });
+    currencyList.value = res.rows || [];
+  } catch (error) {
+    console.error('加载币种列表失败:', error);
+    currencyList.value = [];
+  }
+};
+
+// 新增明细行
+const handleAddDetail = () => {
+  detailList.value.push({
+    revenueId: undefined,
+    quantity: 0,
+    unitPrice: 0,
+    totalAmount: 0,
+    remark: ''
+  });
+};
+
+// 数量或单价变化时自动计算总金额
+const handleQuantityOrPriceChange = (index: number) => {
+  const detail = detailList.value[index];
+  if (detail) {
+    const quantity = Number(detail.quantity) || 0;
+    const unitPrice = Number(detail.unitPrice) || 0;
+    detail.totalAmount = quantity * unitPrice;
+  }
+};
+
+// 删除明细行
+const handleDeleteDetail = (index: number) => {
+  detailList.value.splice(index, 1);
+};
+
+// 计算总金额(手动触发)
+const calculateTotal = () => {
+  // 触发计算属性重新计算
+};
+
+// 提交表单
+const submitForm = async () => {
+  try {
+    await revenueHeaderFormRef.value?.validate();
+
+    // 验证是否有明细数据
+    if (!detailList.value || detailList.value.length === 0) {
+      ElMessage.warning('请至少添加一条其他信息');
+      return;
+    }
+
+    buttonLoading.value = true;
+
+    // 组装明细数据到 orderRevenueDetails
+    form.value.orderRevenueDetails = detailList.value.map((detail) => ({
+      revenueId: detail.revenueId,
+      quantity: detail.quantity,
+      unitPrice: detail.unitPrice,
+      totalAmount: detail.totalAmount,
+      remark: detail.remark
+    }));
+
+    // 调用保存接口
+    if (form.value.id) {
+      await updateRevenueHeader(form.value);
+    } else {
+      await addRevenueHeader(form.value);
+    }
+
+    ElMessage.success('保存成功');
+    // 跳转回列表页
+    router.push('/order-manage/order-revenue');
+  } catch (error) {
+    console.error('保存失败:', error);
+    if (error !== false) {
+      ElMessage.error('保存失败,请检查数据后重试');
+    }
+  } finally {
+    buttonLoading.value = false;
+  }
+};
+
+// 返回按钮
+const handleBack = () => {
+  router.back();
+};
+
+// 取消
+const cancel = () => {
+  router.back();
+};
+
+// 页面标题
+const pageTitle = computed(() => {
+  const isEdit = !!route.query.id;
+  if (isEdit) {
+    return form.value.revenueType === '1' ? '编辑费用申请单' : '编辑收入申请单';
+  }
+  return form.value.revenueType === '1' ? '新增费用申请单' : '新增收入申请单';
+});
+
+// 加载订单详情
+const loadOrderDetail = async (id: string | number) => {
+  try {
+    const res = await getRevenueHeader(id);
+    const data = res.data;
+
+    // 填充表单数据
+    Object.assign(form.value, data);
+
+    // 填充明细列表
+    if (data.orderRevenueDetailList && data.orderRevenueDetailList.length > 0) {
+      detailList.value = data.orderRevenueDetailList.map((item: any) => ({
+        revenueId: item.revenueId,
+        quantity: item.quantity || 0,
+        unitPrice: item.unitPrice || 0,
+        totalAmount: item.totalAmount || 0,
+        remark: item.remark || ''
+      }));
+    }
+  } catch (error) {
+    console.error('加载订单详情失败:', error);
+    ElMessage.error('加载订单详情失败');
+  }
+};
+
+// 组件挂载时加载数据
+onMounted(async () => {
+  // 从路由参数获取revenueType和id
+  const revenueType = route.query.revenueType as string;
+  const orderId = route.query.id as string;
+
+  if (revenueType) {
+    form.value.revenueType = revenueType;
+  } else {
+    // 默认为收入申请
+    form.value.revenueType = '0';
+  }
+
+  // 加载基础数据
+  await loadFeeTypeList();
+  await loadCurrencyList();
+
+  // 如果有id,说明是编辑模式,加载订单详情
+  if (orderId) {
+    await loadOrderDetail(orderId);
+  } else {
+    // 新增模式,默认添加一个空行
+    handleAddDetail();
+  }
+});
+</script>
+
+<style scoped lang="scss">
+.mb-2 {
+  margin-bottom: 16px;
+}
+
+.mt-4 {
+  margin-top: 16px;
+}
+</style>

+ 291 - 0
src/views/order/revenueHeader/index.vue

@@ -0,0 +1,291 @@
+<template>
+  <div class="p-2">
+    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+      <div v-show="showSearch" class="mb-[10px]">
+        <el-card shadow="hover">
+          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
+            <el-form-item label="关键字" prop="searchValue">
+              <el-input v-model="queryParams.searchValue" placeholder="客户名称/编号" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="单据日期" prop="createTime">
+              <el-input v-model="queryParams.createTime" placeholder="请选择单据日期" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="单据编号" prop="orderRevenueCode">
+              <el-input v-model="queryParams.orderRevenueCode" placeholder="请输入单据编号" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="业务员" prop="businessStaff">
+              <el-input v-model="queryParams.businessStaff" placeholder="请输入业务员" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="客服" prop="customerService">
+              <el-input v-model="queryParams.customerService" placeholder="请输入客服" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="关联费用" prop="isPrwTax">
+              <el-select v-model="queryParams.isPrwTax" clearable>
+                <el-option v-for="dict in sys_platform_yes_no" :key="dict.value" :label="dict.label" :value="dict.value" />
+              </el-select>
+            </el-form-item>
+            <el-form-item>
+              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+            </el-form-item>
+          </el-form>
+        </el-card>
+      </div>
+    </transition>
+
+    <el-card shadow="never">
+      <template #header>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="22"> 收入申请单信息列表 </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['order:revenueHeader:add']">新增</el-button>
+          </el-col>
+        </el-row>
+      </template>
+
+      <el-table v-loading="loading" border :data="revenueHeaderList" @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="单据日期" align="center" prop="createTime">
+          <template #default="scope">
+            <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="单据编号" align="center" prop="orderRevenueCode" />
+        <el-table-column label="客户名称" align="center" prop="customerName" />
+        <el-table-column label="业务员" align="center" prop="businessStaff" />
+        <el-table-column label="客服" align="center" prop="customerService" />
+        <el-table-column label="备注" align="center" prop="remark" />
+        <el-table-column label="是否关联" align="center" prop="isPrwTax">
+          <template #default="scope">
+            <dict-tag :options="sys_platform_yes_no" :value="scope.row.isPrwTax" />
+          </template>
+        </el-table-column>
+        <el-table-column label="审核状态" align="center" prop="status">
+          <template #default="scope">
+            <dict-tag :options="check_status" :value="scope.row.status" />
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+          <template #default="scope">
+            <el-button
+              link
+              type="primary"
+              icon="Edit"
+              @click="handleAudit(scope.row)"
+              v-if="scope.row.status == '0'"
+              v-hasPermi="['order:revenueHeader:edit']"
+              >审核</el-button
+            >
+            <el-button link type="primary" icon="Edit" @click="handleExpenseApply(scope.row)" v-hasPermi="['order:revenueHeader:edit']"
+              >费用申请</el-button
+            >
+            <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['order:revenueHeader:edit']">编辑</el-button>
+            <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['order:revenueHeader:remove']">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+    </el-card>
+    <!-- 添加或修改收入单主对话框 -->
+  </div>
+</template>
+
+<script setup name="RevenueHeader" lang="ts">
+import {
+  listRevenueHeader,
+  getRevenueHeader,
+  delRevenueHeader,
+  addRevenueHeader,
+  updateRevenueHeader,
+  changeStatus
+} from '@/api/order/revenueHeader';
+import { RevenueHeaderVO, RevenueHeaderQuery, RevenueHeaderForm } from '@/api/order/revenueHeader/types';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { sys_platform_yes_no, check_status, revenue_type } = toRefs<any>(proxy?.useDict('sys_platform_yes_no', 'check_status', 'revenue_type'));
+
+const revenueHeaderList = ref<RevenueHeaderVO[]>([]);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<string | number>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const router = useRouter();
+const queryFormRef = ref<ElFormInstance>();
+const revenueHeaderFormRef = ref<ElFormInstance>();
+
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+
+const initFormData: RevenueHeaderForm = {
+  id: undefined,
+  revenueType: undefined,
+  orderRevenueCode: undefined,
+  incomeOrderCode: undefined,
+  otherRevenueType: undefined,
+  customerId: undefined,
+  supplierId: undefined,
+  isPrwTax: undefined,
+  currencyId: undefined,
+  pushStatus: undefined,
+  orderFile: undefined,
+  status: undefined,
+  remark: undefined
+};
+const data = reactive<PageData<RevenueHeaderForm, RevenueHeaderQuery>>({
+  form: { ...initFormData },
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    revenueType: '0',
+    orderRevenueCode: undefined,
+    incomeOrderCode: undefined,
+    otherRevenueType: undefined,
+    customerId: undefined,
+    supplierId: undefined,
+    isPrwTax: undefined,
+    currencyId: undefined,
+    pushStatus: undefined,
+    orderFile: undefined,
+    status: undefined,
+    platformCode: undefined,
+    params: {}
+  },
+  rules: {
+    customerId: [{ required: true, message: '客户id不能为空', trigger: 'blur' }]
+  }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+/** 查询收入单主列表 */
+const getList = async () => {
+  loading.value = true;
+  const res = await listRevenueHeader(queryParams.value);
+  revenueHeaderList.value = res.rows;
+  total.value = res.total;
+  loading.value = false;
+};
+
+/** 取消按钮 */
+const cancel = () => {
+  reset();
+  dialog.visible = false;
+};
+
+/** 表单重置 */
+const reset = () => {
+  form.value = { ...initFormData };
+  revenueHeaderFormRef.value?.resetFields();
+};
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.value.pageNum = 1;
+  getList();
+};
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value?.resetFields();
+  handleQuery();
+};
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection: RevenueHeaderVO[]) => {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+
+/** 新增按钮操作 */
+const handleAdd = () => {
+  router.push({
+    path: '/order-manage/order-revenue-add',
+    query: { revenueType: '0' } // 收入申请
+  });
+};
+
+/** 费用申请按钮操作 */
+const handleExpenseApply = (row?: RevenueHeaderVO) => {
+  router.push({
+    path: '/order-manage/order-revenue-add',
+    query: { revenueType: '1' } // 费用申请
+  });
+};
+
+/** 修改按钮操作 */
+const handleUpdate = async (row?: RevenueHeaderVO) => {
+  reset();
+  const _id = row?.id || ids.value[0];
+  router.push({
+    path: '/order-manage/order-revenue-add',
+    query: { revenueType: row.revenueType, id: _id }
+  });
+};
+
+/** 审核按钮操作 */
+const handleAudit = async (row: RevenueHeaderVO) => {
+  try {
+    await proxy?.$modal.confirm('是否确认审核该收入单?');
+
+    // 更新状态为已审核
+    await changeStatus(row.id, '1');
+
+    proxy?.$modal.msgSuccess('审核成功');
+    await getList();
+  } catch (error) {
+    console.error('审核失败:', error);
+  }
+};
+
+/** 提交按钮 */
+const submitForm = () => {
+  revenueHeaderFormRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      buttonLoading.value = true;
+      if (form.value.id) {
+        await updateRevenueHeader(form.value).finally(() => (buttonLoading.value = false));
+      } else {
+        await addRevenueHeader(form.value).finally(() => (buttonLoading.value = false));
+      }
+      proxy?.$modal.msgSuccess('操作成功');
+      dialog.visible = false;
+      await getList();
+    }
+  });
+};
+
+/** 删除按钮操作 */
+const handleDelete = async (row?: RevenueHeaderVO) => {
+  const _ids = row?.id || ids.value;
+  await proxy?.$modal.confirm('是否确认删除收入单主编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
+  await delRevenueHeader(_ids);
+  proxy?.$modal.msgSuccess('删除成功');
+  await getList();
+};
+
+/** 导出按钮操作 */
+const handleExport = () => {
+  proxy?.download(
+    'order/revenueHeader/export',
+    {
+      ...queryParams.value
+    },
+    `revenueHeader_${new Date().getTime()}.xlsx`
+  );
+};
+
+onMounted(() => {
+  getList();
+});
+
+onActivated(() => {
+  getList();
+});
+</script>

+ 388 - 0
src/views/order/saleOrder/deliverDialog.vue

@@ -0,0 +1,388 @@
+<template>
+  <el-dialog :model-value="modelValue" title="发货" width="1200px" @update:model-value="handleDialogChange" @open="handleOpen" @close="handleClose">
+    <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="订单编号" prop="orderCode">
+            <el-input v-model="form.orderCode" disabled />
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="12" v-if="form.deliverMethod === '0'">
+          <el-form-item label="送货人" prop="deliverMan">
+            <el-input v-model="form.deliverMan" placeholder="请输入送货人姓名" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12" v-if="form.deliverMethod === '1'">
+          <el-form-item label="物流公司名称" prop="logisticsCompany">
+            <el-select v-model="form.logisticsCompany" placeholder="请选择" style="width: 100%" filterable>
+              <el-option v-for="company in logisticsCompanyList" :key="company.id" :label="company.logisticsName" :value="company.id" />
+            </el-select>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item v-if="form.deliverMethod === '1'" label="物流单号" prop="logisticNo">
+            <el-input v-model="form.logisticNo" placeholder="请输入物流单号" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="发货方式" prop="deliverMethod">
+            <el-radio-group v-model="form.deliverMethod">
+              <el-radio v-for="dict in deliver_method" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12" v-if="form.deliverMethod === '1'">
+          <el-form-item label="收货人手机" prop="consigneePhone">
+            <el-input v-model="form.consigneePhone" placeholder="请输入收货人手机" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12" v-if="form.deliverMethod === '0'">
+          <el-form-item label="手机号码" prop="phone">
+            <el-input v-model="form.phone" placeholder="请输入手机号码" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="24">
+          <el-form-item label="发货备注" prop="deliverRemark">
+            <el-input v-model="form.deliverRemark" type="textarea" :rows="3" placeholder="请输入内容" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+
+    <!-- 商品列表 -->
+    <el-table :data="productList" border style="width: 100%" max-height="600px">
+      <el-table-column prop="productNo" label="产品编号" width="100" />
+      <el-table-column label="产品图片" width="100">
+        <template #default="scope">
+          <el-image v-if="scope.row.productImage" :src="scope.row.productImage" style="width: 60px; height: 60px" fit="cover" />
+          <span v-else>暂无图片</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="productName" label="产品名称" min-width="200" show-overflow-tooltip />
+      <el-table-column prop="categoryName" label="类别" width="120" />
+      <el-table-column prop="productUnit" label="单位" width="80" />
+      <el-table-column prop="orderQuantity" label="商品总数" width="100" />
+      <el-table-column prop="quantitySent" label="已发货数量" width="100" />
+      <el-table-column prop="unsentQuantity" label="未发货数量" width="100" />
+      <el-table-column label="发货数量">
+        <template #default="scope">
+          <el-input-number
+            v-model="scope.row.deliverNum"
+            :min="0"
+            :max="scope.row.unsentQuantity"
+            :precision="0"
+            size="small"
+            :controls="false"
+            style="width: 100%"
+            @change="handleDeliveryQuantityChange(scope.$index)"
+          />
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" width="100" fixed="right" align="center">
+        <template #default="scope">
+          <el-button link type="danger" size="small" @click="handleDeleteProduct(scope.$index)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 分页 -->
+    <el-pagination
+      v-model:current-page="queryParams.pageNum"
+      v-model:page-size="queryParams.pageSize"
+      :total="total"
+      :page-sizes="[20, 50, 100]"
+      layout="total, sizes, prev, pager, next, jumper"
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+      class="mt-4"
+    />
+
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="handleCancel">取消</el-button>
+        <el-button type="primary" :loading="submitLoading" @click="handleSubmit">确认</el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive, computed, onMounted } from 'vue';
+import { getOrderMain } from '@/api/order/orderMain';
+import { OrderMainVO } from '@/api/order/orderMain/types';
+import { listOrderProduct } from '@/api/order/orderProduct';
+import { OrderProductVO } from '@/api/order/orderProduct/types';
+import { listLogisticsCompany } from '@/api/company/logisticsCompany';
+import { LogisticsCompanyVO } from '@/api/company/logisticsCompany/types';
+import { addOrderDeliver } from '@/api/order/orderDeliver';
+import { OrderDeliverVO, OrderDeliverForm } from '@/api/order/orderDeliver/types';
+import { ElMessage } from 'element-plus';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { deliver_method } = toRefs<any>(proxy?.useDict('deliver_method'));
+
+interface Props {
+  modelValue: boolean;
+  orderId?: string | number;
+  orderNo?: string;
+}
+
+interface Emits {
+  (e: 'update:modelValue', value: boolean): void;
+  (e: 'success'): void;
+}
+
+const props = defineProps<Props>();
+const emit = defineEmits<Emits>();
+
+const formRef = ref();
+const submitLoading = ref(false);
+const productList = ref<any[]>([]);
+const total = ref(0);
+
+// 物流公司列表
+const logisticsCompanyList = ref<LogisticsCompanyVO[]>([]);
+
+// 查询参数
+const queryParams = ref({
+  pageNum: 1,
+  pageSize: 20,
+  orderId: undefined as string | number | undefined
+});
+
+// 表单数据
+const form = reactive<OrderDeliverForm>({
+  orderId: undefined,
+  orderCode: '',
+  logisticPackNo: '',
+  deliverMethod: '1',
+  deliverMan: '',
+  phone: '',
+  logisticsStatus: '',
+  deliverRemark: '',
+  checklistRemark: '',
+  logisticsCompany: undefined,
+  logisticNo: '',
+  logisticPackStatus: '',
+  consigneePhone: '',
+  remark: '',
+  orderDeliverProducts: []
+});
+
+// 动态校验规则
+const rules = computed(() => {
+  const baseRules: any = {
+    deliverMethod: [{ required: true, message: '请选择发货方式', trigger: 'change' }]
+  };
+
+  // 第三方物流(deliverMethod === '1')
+  if (form.deliverMethod === '1') {
+    baseRules.logisticsCompany = [{ required: true, message: '请选择物流公司', trigger: 'change' }];
+    baseRules.logisticNo = [{ required: true, message: '请输入物流单号', trigger: 'blur' }];
+    baseRules.consigneePhone = [
+      { required: true, message: '请输入收货人手机', trigger: 'blur' },
+      { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
+    ];
+  }
+
+  // 自有物流(deliverMethod === '0')
+  if (form.deliverMethod === '0') {
+    baseRules.deliverMan = [{ required: true, message: '请输入送货人姓名', trigger: 'blur' }];
+    baseRules.phone = [
+      { required: true, message: '请输入手机号码', trigger: 'blur' },
+      { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
+    ];
+  }
+
+  return baseRules;
+});
+
+// 对话框状态变化
+const handleDialogChange = (val: boolean) => {
+  emit('update:modelValue', val);
+};
+
+// 对话框打开时触发
+const handleOpen = () => {
+  resetForm();
+  if (props.orderId) {
+    form.orderId = props.orderId;
+    form.orderCode = props.orderNo || '';
+    queryParams.value.orderId = props.orderId;
+    loadProductList();
+  }
+};
+
+// 对话框关闭时触发
+const handleClose = () => {
+  resetForm();
+};
+
+// 重置表单
+const resetForm = () => {
+  form.orderId = undefined;
+  form.orderCode = '';
+  form.logisticsCompany = undefined;
+  form.logisticNo = '';
+  form.deliverMethod = '1';
+  form.deliverMan = '';
+  form.phone = '';
+  form.consigneePhone = '';
+  form.deliverRemark = '';
+  productList.value = [];
+  queryParams.value.pageNum = 1;
+  formRef.value?.clearValidate();
+};
+
+// 加载商品列表
+const loadProductList = async () => {
+  try {
+    const res = await getOrderMain(props.orderId);
+    console.log(res.data.orderProductList);
+
+    // 为每个商品添加发货数量字段,默认为未发货数量
+    productList.value = (res.data.orderProductList || []).map((item: OrderProductVO) => ({
+      ...item,
+      deliverNum: 0,
+      productNo: item.productNo,
+      productId: item.productId,
+      productUnitId: item.productUnit
+    }));
+    total.value = res.data.orderProductList.length || 0;
+  } catch (error) {
+    console.error('加载商品列表失败:', error);
+    ElMessage.error('加载商品列表失败');
+    productList.value = [];
+    total.value = 0;
+  }
+};
+
+// 加载物流公司列表
+const loadLogisticsCompanyList = async () => {
+  try {
+    const res = await listLogisticsCompany({
+      isShow: '0',
+      pageNum: 1,
+      pageSize: 1000
+    });
+    logisticsCompanyList.value = res.rows || [];
+  } catch (error) {
+    console.error('加载物流公司列表失败:', error);
+    logisticsCompanyList.value = [];
+  }
+};
+
+// 发货数量变化
+const handleDeliveryQuantityChange = (index: number) => {
+  const product = productList.value[index];
+  if (product) {
+    // 确保发货数量不超过未发货数量
+    if (product.deliverNum > product.unsentQuantity) {
+      product.deliverNum = product.unsentQuantity;
+      ElMessage.warning('发货数量不能大于未发货数量');
+    }
+    // 确保发货数量不小于0
+    if (product.deliverNum < 0) {
+      product.deliverNum = 0;
+    }
+  }
+};
+
+// 删除商品
+const handleDeleteProduct = (index: number) => {
+  productList.value.splice(index, 1);
+};
+
+// 分页大小变化
+const handleSizeChange = () => {
+  queryParams.value.pageNum = 1;
+  loadProductList();
+};
+
+// 页码变化
+const handleCurrentChange = () => {
+  loadProductList();
+};
+
+// 取消
+const handleCancel = () => {
+  emit('update:modelValue', false);
+};
+
+// 提交
+const handleSubmit = async () => {
+  try {
+    // 验证表单
+    await formRef.value?.validate();
+
+    // 验证是否有发货商品
+    const deliveryProducts = productList.value.filter((item) => item.deliverNum > 0);
+    if (deliveryProducts.length === 0) {
+      ElMessage.warning('请至少选择一个商品进行发货');
+      return;
+    }
+
+    submitLoading.value = true;
+
+    // 组装发货数据
+    const deliveryData: OrderDeliverForm = {
+      orderId: form.orderId,
+      orderCode: form.orderCode,
+      logisticsCompany: form.logisticsCompany,
+      logisticNo: form.logisticNo,
+      deliverMethod: form.deliverMethod,
+      deliverMan: form.deliverMan,
+      phone: form.phone,
+      consigneePhone: form.consigneePhone,
+      deliverRemark: form.deliverRemark,
+      orderDeliverProducts: deliveryProducts.map((item) => ({
+        productId: item.productId,
+        productNo: item.productNo,
+        productName: item.productName,
+        productUnitId: item.productUnitId,
+        productUnit: item.productUnit,
+        deliverNum: item.deliverNum
+      }))
+    };
+
+    // 调用发货API
+    await addOrderDeliver(deliveryData);
+
+    ElMessage.success('发货成功');
+    emit('success');
+    emit('update:modelValue', false);
+  } catch (error) {
+    console.error('发货失败:', error);
+    if (error !== false) {
+      // 不是表单验证失败
+      ElMessage.error('发货失败,请重试');
+    }
+  } finally {
+    submitLoading.value = false;
+  }
+};
+
+// 组件挂载时加载物流公司列表
+onMounted(() => {
+  loadLogisticsCompanyList();
+});
+</script>
+
+<style scoped lang="scss">
+.mt-4 {
+  margin-top: 16px;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+</style>

+ 539 - 0
src/views/order/saleOrder/index.vue

@@ -0,0 +1,539 @@
+<template>
+  <div class="p-2">
+    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+      <div v-show="showSearch" class="mb-[10px]">
+        <el-card shadow="hover">
+          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
+            <el-form-item label="订单编号" prop="orderNo">
+              <el-input v-model="queryParams.orderNo" placeholder="请输入订单编号" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="客户编号" prop="customerCode">
+              <el-input v-model="queryParams.customerCode" placeholder="请输入客户编号" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="客户名称" prop="customerName">
+              <el-input v-model="queryParams.customerName" placeholder="请输入客户名称" clearable @keyup.enter="handleQuery" />
+            </el-form-item>
+            <el-form-item label="订单来源" prop="orderSource">
+              <el-select v-model="queryParams.orderSource" placeholder="请选择订单来源" clearable>
+                <el-option v-for="dict in order_source" :key="dict.value" :label="dict.label" :value="dict.value" />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="订单状态" prop="orderStatus">
+              <el-select v-model="queryParams.orderStatus" placeholder="请选择订单状态" clearable>
+                <el-option v-for="dict in order_status" :key="dict.value" :label="dict.label" :value="dict.value" />
+              </el-select>
+            </el-form-item>
+
+            <el-form-item label="提交时间" prop="orderTime">
+              <el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" />
+            </el-form-item>
+
+            <el-form-item>
+              <el-button type="primary" icon="Search" @click="handleQuery()">搜索</el-button>
+              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+            </el-form-item>
+          </el-form>
+        </el-card>
+      </div>
+    </transition>
+
+    <el-card shadow="never">
+      <template #header>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="15"> 销售订单信息列表 </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" plain>关闭订单</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" plain>删除订单</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" plain>导出订单</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button
+              :type="queryParams.orderStatus === undefined ? 'primary' : ''"
+              :plain="queryParams.orderStatus !== undefined"
+              @click="handleQuery()"
+              >全部订单{{ orderStatusStats.totalCount }}</el-button
+            >
+          </el-col>
+          <el-col :span="1.5">
+            <el-button :type="queryParams.orderStatus === '0' ? 'primary' : ''" :plain="queryParams.orderStatus !== '0'" @click="handleQuery('0')"
+              >待付款{{ orderStatusStats.pendingPaymentCount }}</el-button
+            >
+          </el-col>
+          <el-col :span="1.5">
+            <el-button :type="queryParams.orderStatus === '2' ? 'primary' : ''" :plain="queryParams.orderStatus !== '2'" @click="handleQuery('2')"
+              >待发货{{ orderStatusStats.pendingShipmentCount }}</el-button
+            >
+          </el-col>
+          <el-col :span="1.5">
+            <el-button :type="queryParams.orderStatus === '4' ? 'primary' : ''" :plain="queryParams.orderStatus !== '4'" @click="handleQuery('4')"
+              >已发货{{ orderStatusStats.shippedCount }}</el-button
+            >
+          </el-col>
+          <el-col :span="1.5">
+            <el-button :type="queryParams.orderStatus === '5' ? 'primary' : ''" :plain="queryParams.orderStatus !== '5'" @click="handleQuery('5')"
+              >已完成{{ orderStatusStats.completedCount }}</el-button
+            >
+          </el-col>
+          <el-col :span="1.5">
+            <el-button :type="queryParams.orderStatus === '6' ? 'primary' : ''" :plain="queryParams.orderStatus !== '6'" @click="handleQuery('6')"
+              >已关闭{{ orderStatusStats.closedCount }}</el-button
+            >
+          </el-col>
+        </el-row>
+      </template>
+
+      <el-table v-loading="loading" border :data="orderMainList" @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="订单时间" align="center" prop="orderTime" />
+        <el-table-column label="订单编号" align="center" prop="orderNo" />
+        <el-table-column label="客户编号" align="center" prop="customerCode" />
+        <el-table-column label="订单总金额" align="center" prop="totalAmount" />
+        <el-table-column label="支付方式" align="center" prop="payType">
+          <template #default="scope">
+            <dict-tag :options="pay_method" :value="scope.row.payType" />
+          </template>
+        </el-table-column>
+        <el-table-column label="业务员" align="center" prop="businessStaff" />
+        <el-table-column label="客服" align="center" prop="customerService" />
+        <el-table-column label="归属部门" align="center" prop="businessDept" />
+        <el-table-column label="订单来源" align="center" prop="orderSource">
+          <template #default="scope">
+            <dict-tag :options="order_source" :value="scope.row.orderSource" />
+          </template>
+        </el-table-column>
+        <el-table-column label="审核状态" align="center" prop="checkStatus">
+          <template #default="scope">
+            <dict-tag :options="order_check_status" :value="scope.row.checkStatus" />
+          </template>
+        </el-table-column>
+        <el-table-column label="订单状态" align="center" prop="orderStatus">
+          <template #default="scope">
+            <dict-tag :options="order_status" :value="scope.row.orderStatus" />
+          </template>
+        </el-table-column>
+
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+          <template #default="scope">
+            <el-button link type="primary" v-if="scope.row.orderStatus === '0'" @click="handleReview(scope.row)">查看</el-button>
+            <el-button link type="primary" v-if="scope.row.checkStatus === '0'" @click="handleCheck(scope.row)">审核</el-button>
+            <el-button link type="primary" v-if="scope.row.orderStatus === '2' || scope.row.orderStatus === '3'" @click="handleDeliver(scope.row)"
+              >发货</el-button
+            >
+            <el-button
+              link
+              type="primary"
+              v-if="scope.row.orderStatus === '2' || scope.row.orderStatus === '3' || scope.row.orderStatus === '4' || scope.row.orderStatus === '5'"
+              @click="handleReview(scope.row)"
+              >查看订单信息</el-button
+            >
+            <el-button link type="primary" v-if="scope.row.orderStatus === '4' || scope.row.orderStatus === '5'">查看物流</el-button>
+            <el-button
+              link
+              type="primary"
+              v-if="scope.row.orderStatus === '0' || scope.row.orderStatus === '3' || scope.row.orderStatus === '4' || scope.row.orderStatus === '5'"
+              >取消订单</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+    </el-card>
+
+    <!-- 发货对话框 -->
+    <DeliverDialog v-model="showDeliverDialog" :order-id="currentOrderId" :order-no="currentOrderNo" @success="handleDeliverSuccess" />
+  </div>
+</template>
+
+<script setup name="OrderMain" lang="ts">
+import {
+  listOrderMain,
+  getOrderMain,
+  delOrderMain,
+  addOrderMain,
+  updateOrderMain,
+  queryOrderStatusStats,
+  changeCheckStatus
+} from '@/api/order/orderMain';
+import { OrderMainVO, OrderMainQuery, OrderMainForm } from '@/api/order/orderMain/types';
+import DeliverDialog from './deliverDialog.vue';
+import { ElMessageBox } from 'element-plus';
+import { h } from 'vue';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { order_status, order_check_status, pay_method, order_source } = toRefs<any>(
+  proxy?.useDict('order_status', 'order_check_status', 'pay_method', 'order_source')
+);
+
+const orderMainList = ref<OrderMainVO[]>([]);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<string | number>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const router = useRouter();
+const queryFormRef = ref<ElFormInstance>();
+const orderMainFormRef = ref<ElFormInstance>();
+const checkStatusValue = ref('1'); // 审核状态选择值
+
+// 发货对话框
+const showDeliverDialog = ref(false);
+const currentOrderId = ref<string | number>();
+const currentOrderNo = ref<string>();
+const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
+
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+
+const orderStatusStats = ref({
+  pendingPaymentCount: 0, // 待支付
+  pendingShipmentCount: 0, // 待发货
+  shippedCount: 0, // 已发货(发货完成)
+  completedCount: 0, // 已完成
+  closedCount: 0, // 已关闭
+  totalCount: 0 // 全部订单
+});
+
+const initFormData: OrderMainForm = {
+  id: undefined,
+  orderNo: undefined,
+  isSplitChild: undefined,
+  shipmentNo: undefined,
+  subOrderNo: undefined,
+  companyId: undefined,
+  customerId: undefined,
+  customerCode: undefined,
+  userId: undefined,
+  shippingAddressId: undefined,
+  purchaseReason: undefined,
+  invoiceType: undefined,
+  payType: undefined,
+  warehouseId: undefined,
+  creditLimit: undefined,
+  expectedDeliveryTime: undefined,
+  businessStaff: undefined,
+  customerService: undefined,
+  businessDept: undefined,
+  userDept: undefined,
+  productQuantity: undefined,
+  shippingFee: undefined,
+  totalAmount: undefined,
+  payableAmount: undefined,
+  paymentStatus: undefined,
+  orderSource: undefined,
+  orderStatus: undefined,
+  orderTime: undefined,
+  confirmTime: undefined,
+  shippingTime: undefined,
+  receivingTime: undefined,
+  shippedQuantity: undefined,
+  unshippedQuantity: undefined,
+  packageCount: undefined,
+  signedQuantity: undefined,
+  afterSaleCompleted: undefined,
+  afterSalePending: undefined,
+  deliveryDesc: undefined,
+  pushStatus: undefined,
+  attachmentPath: undefined,
+  deliveryType: undefined,
+  orderCategory: undefined,
+  productCode: undefined,
+  cancelReason: undefined,
+  expenseType: undefined,
+  userNo: undefined,
+  status: undefined,
+  remark: undefined,
+  orderProductBos: [],
+  customerSalesInfoVo: {}
+};
+const data = reactive<PageData<OrderMainForm, OrderMainQuery>>({
+  form: { ...initFormData },
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    orderNo: undefined,
+    shipmentNo: undefined,
+    subOrderNo: undefined,
+    companyId: undefined,
+    customerCode: undefined,
+    customerId: undefined,
+    userId: undefined,
+    shippingAddressId: undefined,
+    purchaseReason: undefined,
+    invoiceType: undefined,
+    payType: undefined,
+    warehouseId: undefined,
+    creditLimit: undefined,
+    expectedDeliveryTime: undefined,
+    businessStaff: undefined,
+    customerService: undefined,
+    businessDept: undefined,
+    userDept: undefined,
+    productQuantity: undefined,
+    shippingFee: undefined,
+    totalAmount: undefined,
+    payableAmount: undefined,
+    paymentStatus: undefined,
+    orderSource: undefined,
+    orderStatus: undefined,
+    orderTime: undefined,
+    confirmTime: undefined,
+    shippingTime: undefined,
+    receivingTime: undefined,
+    shippedQuantity: undefined,
+    unshippedQuantity: undefined,
+    packageCount: undefined,
+    signedQuantity: undefined,
+    afterSaleCompleted: undefined,
+    afterSalePending: undefined,
+    deliveryDesc: undefined,
+    pushStatus: undefined,
+    attachmentPath: undefined,
+    deliveryType: undefined,
+    orderCategory: undefined,
+    productCode: undefined,
+    cancelReason: undefined,
+    expenseType: undefined,
+    status: undefined,
+    platformCode: undefined,
+    params: {}
+  },
+  rules: {
+    customerId: [{ required: true, message: '客户ID不能为空', trigger: 'blur' }],
+    payType: [{ required: true, message: '支付方式不能为空', trigger: 'change' }],
+    warehouseId: [{ required: true, message: '发货仓库不能为空', trigger: 'change' }],
+    expectedDeliveryTime: [{ required: true, message: '预计送达时间不能为空', trigger: 'blur' }],
+    shippingFee: [{ required: true, message: '运费不能为空', trigger: 'blur' }],
+    confirmTime: [{ required: true, message: '确认时间不能为空', trigger: 'blur' }],
+    shippingTime: [{ required: true, message: '发货时间不能为空', trigger: 'blur' }],
+    receivingTime: [{ required: true, message: '收货时间不能为空', trigger: 'blur' }],
+    cancelReason: [{ required: true, message: '取消或异常原因不能为空', trigger: 'blur' }],
+    expenseType: [{ required: true, message: '费用类型不能为空', trigger: 'change' }]
+  }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+/** 查询订单主信息列表 */
+const getList = async () => {
+  loading.value = true;
+  const res = await listOrderMain(proxy?.addDateRange(queryParams.value, dateRange.value));
+  orderMainList.value = res.rows;
+  total.value = res.total;
+  loading.value = false;
+  queryOrderStatusStatsMethod();
+};
+
+const queryOrderStatusStatsMethod = async () => {
+  const res = await queryOrderStatusStats();
+  orderStatusStats.value = res as any;
+};
+
+/** 取消按钮 */
+const cancel = () => {
+  reset();
+  dialog.visible = false;
+};
+
+/** 表单重置 */
+const reset = () => {
+  form.value = { ...initFormData };
+  orderMainFormRef.value?.resetFields();
+};
+
+/** 搜索按钮操作 */
+const handleQuery = (orderStatus?: string) => {
+  if (orderStatus) {
+    queryParams.value.orderStatus = orderStatus;
+  } else {
+    queryParams.value.orderStatus = undefined;
+  }
+  queryParams.value.pageNum = 1;
+  getList();
+};
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  dateRange.value = ['', ''];
+  queryFormRef.value?.resetFields();
+  handleQuery();
+};
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection: OrderMainVO[]) => {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+
+const handleReview = (row?: OrderMainVO) => {
+  router.push({
+    path: '/order-manage/order-sendDetail',
+    query: { id: row.id }
+  });
+};
+
+/** 审核按钮操作 */
+const handleCheck = async (row?: OrderMainVO) => {
+  const oldValue = row.checkStatus; // 保存旧值
+
+  // 弹出审核选择对话框
+  try {
+    await ElMessageBox({
+      title: '审核',
+      message: h('div', { style: 'padding: 10px 0' }, [
+        h('p', { style: 'margin-bottom: 15px; font-size: 14px' }, '请选择审核结果:'),
+        h('div', { style: 'display: flex; flex-direction: column; gap: 12px' }, [
+          h(
+            'label',
+            {
+              style: 'display: flex; align-items: center; cursor: pointer; font-size: 14px',
+              onClick: () => {
+                checkStatusValue.value = '1';
+                const radio = document.querySelector('input[name="checkStatus"][value="1"]') as HTMLInputElement;
+                if (radio) radio.checked = true;
+              }
+            },
+            [
+              h('input', {
+                type: 'radio',
+                name: 'checkStatus',
+                value: '1',
+                checked: true,
+                style: 'margin-right: 8px; cursor: pointer',
+                onChange: () => {
+                  checkStatusValue.value = '1';
+                }
+              }),
+              h('span', null, '审核通过')
+            ]
+          ),
+          h(
+            'label',
+            {
+              style: 'display: flex; align-items: center; cursor: pointer; font-size: 14px',
+              onClick: () => {
+                checkStatusValue.value = '2';
+                const radio = document.querySelector('input[name="checkStatus"][value="2"]') as HTMLInputElement;
+                if (radio) radio.checked = true;
+              }
+            },
+            [
+              h('input', {
+                type: 'radio',
+                name: 'checkStatus',
+                value: '2',
+                style: 'margin-right: 8px; cursor: pointer',
+                onChange: () => {
+                  checkStatusValue.value = '2';
+                }
+              }),
+              h('span', null, '驳回')
+            ]
+          )
+        ])
+      ]),
+      showCancelButton: true,
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      beforeClose: (action, instance, done) => {
+        if (action === 'confirm') {
+          done();
+        } else {
+          done();
+        }
+      }
+    });
+
+    // 调用接口,传入用户选择的值
+    await changeCheckStatus(row.id, checkStatusValue.value);
+    getList();
+    proxy?.$modal.msgSuccess('操作成功');
+  } catch (error) {
+    // 用户取消或操作失败
+    if (error !== 'cancel' && error !== 'close') {
+      row.checkStatus = oldValue; // 失败回滚
+      proxy?.$modal.msgError('操作失败,请重试');
+    }
+  }
+};
+
+/** 发货按钮操作 */
+const handleDeliver = (row?: OrderMainVO) => {
+  if (!row?.id) {
+    proxy?.$modal.msgWarning('订单ID不能为空');
+    return;
+  }
+  currentOrderId.value = row.id;
+  currentOrderNo.value = row.orderNo;
+  showDeliverDialog.value = true;
+};
+
+/** 发货成功回调 */
+const handleDeliverSuccess = () => {
+  getList();
+};
+
+/** 修改按钮操作 */
+const handleUpdate = async (row?: OrderMainVO) => {
+  reset();
+  const _id = row?.id || ids.value[0];
+  const res = await getOrderMain(_id);
+  Object.assign(form.value, res.data);
+  dialog.visible = true;
+  dialog.title = '修改订单主信息';
+};
+
+/** 提交按钮 */
+const submitForm = () => {
+  orderMainFormRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      buttonLoading.value = true;
+      if (form.value.id) {
+        await updateOrderMain(form.value).finally(() => (buttonLoading.value = false));
+      } else {
+        await addOrderMain(form.value).finally(() => (buttonLoading.value = false));
+      }
+      proxy?.$modal.msgSuccess('操作成功');
+      dialog.visible = false;
+      await getList();
+    }
+  });
+};
+
+/** 删除按钮操作 */
+const handleDelete = async (row?: OrderMainVO) => {
+  const _ids = row?.id || ids.value;
+  await proxy?.$modal.confirm('是否确认删除订单主信息编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
+  await delOrderMain(_ids);
+  proxy?.$modal.msgSuccess('删除成功');
+  await getList();
+};
+
+/** 导出按钮操作 */
+const handleExport = () => {
+  proxy?.download(
+    'system/orderMain/export',
+    {
+      ...queryParams.value
+    },
+    `orderMain_${new Date().getTime()}.xlsx`
+  );
+};
+
+onMounted(() => {
+  getList();
+});
+
+onActivated(() => {
+  getList();
+});
+</script>

+ 504 - 0
src/views/order/saleOrder/sendDetail.vue

@@ -0,0 +1,504 @@
+<template>
+  <div class="app-container">
+    <el-card shadow="never" class="mb-2">
+      <!-- 订单信息 -->
+      <el-descriptions title="订单信息" :column="2" border class="custom-descriptions">
+        <el-descriptions-item label="订单编号">{{ orderDetail.orderNo }}</el-descriptions-item>
+        <el-descriptions-item label="发货单编号">{{ orderDetail.shipmentNo }}</el-descriptions-item>
+        <el-descriptions-item label="订单总金额">{{ orderDetail.totalAmount }}</el-descriptions-item>
+        <el-descriptions-item label="支付状态">
+          <dict-tag :options="payment_status" :value="orderDetail.paymentStatus" />
+        </el-descriptions-item>
+        <el-descriptions-item label="订单状态">
+          <dict-tag :options="order_status" :value="orderDetail.orderStatus" />
+        </el-descriptions-item>
+        <el-descriptions-item label="下单时间">{{ orderDetail.orderTime }}</el-descriptions-item>
+        <el-descriptions-item label="确认时间">{{ orderDetail.confirmTime }}</el-descriptions-item>
+        <el-descriptions-item label="发货时间">{{ orderDetail.shippingTime }}</el-descriptions-item>
+        <el-descriptions-item label="签收时间">{{ orderDetail.receivingTime }}</el-descriptions-item>
+      </el-descriptions>
+    </el-card>
+
+    <!-- 订单详情信息 -->
+    <el-card shadow="never" class="mb-2">
+      <template #header>
+        <span>订单基本信息</span>
+      </template>
+      <el-row :gutter="20">
+        <el-col :span="8">
+          <div class="detail-item">
+            <span class="label">归属公司:</span>
+            <span>{{ companyInfo.companyCode || '--' }},{{ companyInfo.companyName || '--' }}</span>
+          </div>
+          <div class="detail-item">
+            <span class="label">业务人员:</span>
+            <span>{{ orderDetail.businessStaff }}</span>
+          </div>
+          <div class="detail-item">
+            <span class="label">发票类型:</span>
+            <span>{{ invoiceTypeInfo.invoiceTypeNo || '--' }},{{ invoiceTypeInfo.invoiceTypeName || '--' }}</span>
+          </div>
+          <div class="detail-item">
+            <span class="label">发货仓库:</span>
+            <span>{{ warehouseInfo.warehouseName || '--' }}</span>
+          </div>
+          <div class="detail-item">
+            <span class="label">采购事由:</span>
+            <span>{{ orderDetail.purchaseReason }}</span>
+          </div>
+          <div class="detail-item">
+            <span class="label">订单备注:</span>
+            <span>{{ orderDetail.remark }}</span>
+          </div>
+          <div class="detail-item">
+            <span class="label">附件:</span>
+            <span>{{ orderDetail.attachmentPath || '' }}</span>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="detail-item">
+            <span class="label">客户名称:</span>
+            <span>{{ customerInfo.customerNo || '--' }},{{ customerInfo.customerName || '--' }}</span>
+          </div>
+          <div class="detail-item">
+            <span class="label">客服人员:</span>
+            <span>{{ orderDetail.customerService }}</span>
+          </div>
+          <div class="detail-item">
+            <span class="label">支付方式:</span>
+            <span>{{ getDictLabel(pay_method, orderDetail.payType) }}</span>
+          </div>
+          <div class="detail-item">
+            <span class="label">费用类型:</span>
+            <span>{{ getDictLabel(fee_type, orderDetail.expenseType) }}</span>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="detail-item">
+            <span class="label">所属项目</span>
+            <span>{{ '--' }}</span>
+          </div>
+          <div class="detail-item">
+            <span class="label">业务部门:</span>
+            <span>{{ orderDetail.businessDept }}</span>
+          </div>
+          <div class="detail-item">
+            <span class="label">下单部门:</span>
+            <span>{{ orderDetail.userDept }}</span>
+          </div>
+          <div class="detail-item">
+            <span class="label">订单状态:</span>
+            <span>{{ getDictLabel(order_status, orderDetail.orderStatus) }}</span>
+          </div>
+        </el-col>
+      </el-row>
+    </el-card>
+
+    <!-- 收货信息 -->
+    <el-card shadow="never" class="mb-2">
+      <template #header>
+        <span>收货信息</span>
+      </template>
+      <el-descriptions :column="2" border>
+        <el-descriptions-item label="收货人姓名">{{ shippingAddress.consignee }}</el-descriptions-item>
+        <el-descriptions-item label="联系电话">{{ shippingAddress.phone }}</el-descriptions-item>
+        <el-descriptions-item label="收货地址">{{ shippingAddress.provincialCityCountry }} {{ shippingAddress.address }}</el-descriptions-item>
+      </el-descriptions>
+    </el-card>
+
+    <!-- 商品明细 -->
+    <el-card shadow="never" class="mb-2">
+      <template #header>
+        <span>商品明细</span>
+      </template>
+      <el-table :data="productList" border style="width: 100%">
+        <el-table-column label="产品图片" width="100">
+          <template #default="scope">
+            <el-image v-if="scope.row.productImage" :src="scope.row.productImage" style="width: 60px; height: 60px" fit="cover" />
+            <span v-else>暂无图片</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="productNo" label="商品编号" />
+
+        <el-table-column prop="productName" label="商品信息" min-width="150" />
+        <el-table-column prop="taxRate" label="税率" align="center">
+          <template #default="scope"> 增值税{{ scope.row.taxRate }}% </template>
+        </el-table-column>
+        <el-table-column prop="productUnit" label="单位" />
+        <el-table-column prop="minSellingPrice" label="最低售价" />
+        <el-table-column prop="orderPrice" label="含税单价" />
+        <el-table-column prop="subtotal" label="小计" />
+        <el-table-column prop="orderQuantity" label="采购数量" />
+        <el-table-column prop="quantitySent" label="已发货数量" />
+        <el-table-column prop="unsentQuantity" label="未发货数量" />
+      </el-table>
+    </el-card>
+    <div class="mt-2 text-right">
+      <span
+        >商品数:{{ totalQuantity }}, 其中有<span style="color: #f56c6c">{{ totalQuantitySent }}已经发货</span></span
+      >
+    </div>
+    <!-- 信息汇总 -->
+    <el-card shadow="never" class="mb-2">
+      <template #header>
+        <div class="card-header">
+          <span>信息汇总</span>
+        </div>
+      </template>
+
+      <el-table :data="summaryData" border style="width: 100%">
+        <el-table-column prop="quantity" label="商品数量" align="center" />
+        <el-table-column prop="shippingFee" label="运费" align="center" />
+        <el-table-column prop="totalAmount" label="订单总金额" align="center" />
+        <el-table-column prop="payableAmount" label="应付款金额" align="center" />
+      </el-table>
+    </el-card>
+    <!-- 发货对话框 -->
+    <DeliverDialog v-model="showDeliverDialog" :order-id="currentOrderId" :order-no="currentOrderNo" @success="handleDeliverSuccess" />
+    <!-- 发货信息 -->
+    <el-card shadow="never" class="mb-2" v-show="orderDetail.orderStatus != '0'">
+      <template #header>
+        <div class="card-header">
+          <span>发货信息:共{{ 0 }}个包裹</span>
+          <el-button type="primary" style="float: right" @click="handleAddDeliver(orderDetail)">添加发货信息</el-button>
+        </div>
+      </template>
+      <div v-show="totalQuantitySent > 0">
+        <div style="white-space: nowrap" class="mb-2">
+          <span style="margin-right: 16px">发货单号:--</span>
+          <span style="margin-right: 16px">发货时间:--</span>
+          <span style="margin-right: 16px">发货方式:--</span>
+          <span style="margin-right: 16px">送货人:--</span>
+          <span style="margin-right: 16px">手机:--</span>
+          <span style="margin-right: 16px">物流状态:--</span>
+          <span>发货备注:--</span>
+        </div>
+        <el-table :data="deliverProductList" border style="width: 100%">
+          <el-table-column label="产品编号" prop="productNo" align="center" />
+          <el-table-column label="商品名称" prop="productName" align="center" />
+          <el-table-column label="单位" prop="productUnit" align="center" />
+          <el-table-column label="发货数量" prop="deliverNum" align="center" />
+        </el-table>
+      </div>
+    </el-card>
+
+    <!-- A10备货信息 -->
+    <el-card shadow="never" class="mb-2">
+      <template #header>
+        <div class="card-header">
+          <span>A10备货信息</span>
+        </div>
+      </template>
+
+      <el-table border style="width: 100%">
+        <el-table-column label="副点人员编号" align="center" />
+        <el-table-column label="单据编号" align="center" />
+        <el-table-column label="清货人员编号" align="center" />
+        <el-table-column label="配货人员编号" align="center" />
+        <el-table-column label="快递编号" align="center" />
+        <el-table-column label="快递单号" align="center" />
+        <el-table-column label="付款方式" align="center" />
+        <el-table-column label="库存记录单号" align="center" />
+        <el-table-column label="回签信息" align="center" />
+      </el-table>
+    </el-card>
+
+    <!-- 底部按钮 -->
+    <div class="text-center mt-4">
+      <el-button @click="goBack">返回</el-button>
+    </div>
+  </div>
+</template>
+
+<script setup name="SendDetail" lang="ts">
+import { ref, computed, onMounted } from 'vue';
+import DeliverDialog from './deliverDialog.vue';
+import { useRoute, useRouter } from 'vue-router';
+import { getOrderMain } from '@/api/order/orderMain';
+import { OrderMainVO } from '@/api/order/orderMain/types';
+import { listOrderProduct } from '@/api/order/orderProduct';
+import { OrderProductVO } from '@/api/order/orderProduct/types';
+import { DeliverProductVO } from '@/api/order/deliverProduct/types';
+import { getShippingAddress } from '@/api/customer/customerFile/shippingAddress';
+import { ShippingAddressVO } from '@/api/customer/customerFile/shippingAddress/types';
+import { getWarehouse } from '@/api/company/warehouse';
+import { WarehouseVO } from '@/api/company/warehouse/types';
+import { getCompany } from '@/api/company/company';
+import { CompanyVO } from '@/api/company/company/types';
+import { getCustomerInfo } from '@/api/customer/customerFile/customerInfo';
+import { CustomerInfoVO } from '@/api/customer/customerFile/customerInfo/types';
+import { getInvoiceType } from '@/api/customer/invoiceType';
+import { InvoiceTypeVO } from '@/api/customer/invoiceType/types';
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { order_status, payment_status, fee_type, pay_method } = toRefs<any>(
+  proxy?.useDict('order_status', 'payment_status', 'fee_type', 'pay_method')
+);
+const route = useRoute();
+const router = useRouter();
+
+// 订单详情
+const orderDetail = ref<OrderMainVO>({} as OrderMainVO);
+
+// 仓库信息
+const warehouseInfo = ref<WarehouseVO>({} as WarehouseVO);
+
+// 公司信息
+const companyInfo = ref<CompanyVO>({} as CompanyVO);
+
+// 客户信息
+const customerInfo = ref<CustomerInfoVO>({} as CustomerInfoVO);
+
+// 发票类型信息
+const invoiceTypeInfo = ref<InvoiceTypeVO>({} as InvoiceTypeVO);
+
+// 商品明细列表
+const productList = ref<OrderProductVO[]>([]);
+
+const deliverProductList = ref<DeliverProductVO[]>([]);
+
+// 收货地址信息
+const shippingAddress = ref<ShippingAddressVO>({} as ShippingAddressVO);
+
+// 发货对话框
+const showDeliverDialog = ref(false);
+const currentOrderId = ref<string | number>();
+const currentOrderNo = ref<string>();
+
+/** 发货成功回调 */
+const handleDeliverSuccess = () => {};
+
+// 计算商品总数(所有商品的采购数量之和)
+const totalQuantity = computed(() => {
+  return productList.value.reduce((sum, item) => {
+    return sum + (Number(item.orderQuantity) || 0);
+  }, 0);
+});
+
+// 计算已发货总数(所有商品的已发货数量之和)
+const totalQuantitySent = computed(() => {
+  return productList.value.reduce((sum, item) => {
+    return sum + (Number(item.quantitySent) || 0);
+  }, 0);
+});
+
+// 获取订单详情
+const getOrderDetail = async () => {
+  const orderId = route.query.id || route.params.id;
+  if (!orderId) {
+    proxy?.$modal.msgError('订单ID不能为空');
+    return;
+  }
+
+  try {
+    const res = await getOrderMain(orderId as any);
+    orderDetail.value = res.data;
+
+    // 获取商品明细
+    if (orderDetail.value.orderProductList) {
+      productList.value = orderDetail.value.orderProductList;
+    } else if (orderDetail.value.id) {
+      await getProductList(orderDetail.value);
+    }
+
+    // 获取发货商品明细
+    if (orderDetail.value.deliverProductList) {
+      deliverProductList.value = orderDetail.value.deliverProductList;
+    } else if (orderDetail.value.id) {
+      await getDeliverProductList(orderDetail.value);
+    }
+
+    // 获取收货地址
+    if (orderDetail.value.shippingAddressId) {
+      await getShippingAddressDetail(orderDetail.value.shippingAddressId);
+    }
+
+    // 获取仓库信息
+    if (orderDetail.value.warehouseId) {
+      await getWarehouseDetail(orderDetail.value.warehouseId);
+    }
+
+    // 获取公司信息
+    if (orderDetail.value.companyId) {
+      await getCompanyDetail(orderDetail.value.companyId);
+    }
+
+    // 获取客户信息
+    if (orderDetail.value.customerId) {
+      await getCustomerDetail(orderDetail.value.customerId);
+    }
+
+    // 获取发票类型信息
+    if (orderDetail.value.invoiceType) {
+      await getInvoiceTypeDetail(orderDetail.value.invoiceType);
+    }
+  } catch (error) {
+    console.error('获取订单详情失败:', error);
+    proxy?.$modal.msgError('获取订单详情失败');
+  }
+};
+
+/** 发货按钮操作 */
+const handleAddDeliver = (row?: OrderMainVO) => {
+  if (!row?.id) {
+    proxy?.$modal.msgWarning('订单ID不能为空');
+    return;
+  }
+  currentOrderId.value = row.id;
+  currentOrderNo.value = row.orderNo;
+  showDeliverDialog.value = true;
+};
+
+// 获取商品明细列表
+const getProductList = async (orderDetail: OrderMainVO) => {
+  try {
+    productList.value = orderDetail.orderProductList || [];
+  } catch (error) {
+    console.error('获取商品明细失败:', error);
+  }
+};
+
+// 获取发货商品明细列表
+const getDeliverProductList = async (orderDetail: OrderMainVO) => {
+  try {
+    deliverProductList.value = orderDetail.deliverProductList || [];
+  } catch (error) {
+    console.error('获取发货商品明细失败:', error);
+  }
+};
+
+// 获取收货地址详情
+const getShippingAddressDetail = async (addressId: string | number) => {
+  try {
+    const res = await getShippingAddress(addressId);
+    shippingAddress.value = res.data;
+  } catch (error) {
+    console.error('获取收货地址失败:', error);
+  }
+};
+
+// 计算商品总金额(所有商品的小计之和)
+const totalAmount = computed(() => {
+  return productList.value.reduce((sum, item) => {
+    return sum + (Number(item.subtotal) || 0);
+  }, 0);
+});
+
+// 计算应付款金额(订单总金额 + 运费)
+const payableAmount = computed(() => {
+  const shipping = Number(orderDetail.value.shippingFee) || 0;
+  return totalAmount.value + shipping;
+});
+// 汇总数据(用于表格显示)
+const summaryData = computed(() => {
+  return [
+    {
+      quantity: totalQuantity.value,
+      shippingFee: `¥${(Number(orderDetail.value.shippingFee) || 0).toFixed(2)}`,
+      totalAmount: `¥${totalAmount.value.toFixed(2)}`,
+      payableAmount: `¥${payableAmount.value.toFixed(2)}`
+    }
+  ];
+});
+
+// 获取仓库详情
+const getWarehouseDetail = async (warehouseId: string | number) => {
+  try {
+    const res = await getWarehouse(warehouseId);
+    warehouseInfo.value = res.data;
+  } catch (error) {
+    console.error('获取仓库信息失败:', error);
+  }
+};
+
+// 获取公司详情
+const getCompanyDetail = async (companyId: string | number) => {
+  try {
+    const res = await getCompany(companyId);
+    companyInfo.value = res.data;
+  } catch (error) {
+    console.error('获取公司信息失败:', error);
+  }
+};
+
+// 获取客户详情
+const getCustomerDetail = async (customerId: string | number) => {
+  try {
+    const res = await getCustomerInfo(customerId);
+    customerInfo.value = res.data;
+  } catch (error) {
+    console.error('获取客户信息失败:', error);
+  }
+};
+
+// 获取发票类型详情
+const getInvoiceTypeDetail = async (invoiceTypeId: string | number) => {
+  try {
+    const res = await getInvoiceType(invoiceTypeId);
+    invoiceTypeInfo.value = res.data;
+  } catch (error) {
+    console.error('获取发票类型信息失败:', error);
+  }
+};
+
+// 字典label工具
+function getDictLabel(dictList: any[], value: string) {
+  if (!dictList || !Array.isArray(dictList)) return value || '--';
+  const found = dictList.find((item) => item.value === value);
+  return found ? found.label : value || '--';
+}
+
+// 返回
+const goBack = () => {
+  router.back();
+};
+
+// 打印
+const handlePrint = () => {
+  window.print();
+};
+
+onMounted(() => {
+  getOrderDetail();
+});
+</script>
+
+<style scoped lang="scss">
+.mb-2 {
+  margin-bottom: 16px;
+}
+
+.mt-4 {
+  margin-top: 32px;
+}
+
+.text-center {
+  text-align: center;
+}
+
+.detail-item {
+  padding: 8px 0;
+  line-height: 1.8;
+
+  .label {
+    color: #909399;
+    margin-right: 8px;
+  }
+}
+
+:deep(.custom-descriptions .el-descriptions__label) {
+  width: 160px;
+  /* 可选:强制不换行 */
+  white-space: nowrap;
+}
+:deep(.custom-descriptions .el-descriptions__content) {
+  /* 内容区域自动占剩余空间 */
+  flex: 1;
+}
+
+@media print {
+  .el-button {
+    display: none;
+  }
+}
+</style>