From 4d629b54ee8411b4c6a68deef6491d732b5e12c9 Mon Sep 17 00:00:00 2001
From: boyang <1920788179@qq.com>
Date: Thu, 15 Aug 2024 22:47:07 +0800
Subject: [PATCH] 应收款与应付款前后端联调完成

---
 src/api/project/approve.ts                            |   2 +-
 src/api/project/invoice.ts                            |  88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 src/api/project/order.ts                              |  10 ++++++++++
 src/api/sys/config.ts                                 |   6 ++++++
 src/components/Modal/src/hooks/useModal.ts            |   2 +-
 src/router/routes/modules/project/approve.ts          |   3 ++-
 src/views/project/approve/ReceivePanel.vue            | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/views/project/approve/index.vue                   |   8 ++++++++
 src/views/project/config/CreateModal.vue              |  11 +++++++++--
 src/views/project/config/DrawerEdit.vue               |   2 +-
 src/views/project/config/EmailPanel.vue               |   2 +-
 src/views/project/config/TablePanel.vue               |   2 +-
 src/views/project/config/data.tsx                     |  16 +++++++++++++++-
 src/views/project/config/index.vue                    |   9 ++++++++-
 src/views/project/finance/pay/CheckDetail.vue         | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/views/project/finance/pay/CheckSum.vue            | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/views/project/finance/pay/FinanceEdit.vue         |  45 +++++++++++++++++++++++++++------------------
 src/views/project/finance/pay/InvoiceUpload.vue       |  50 ++++++++++++++++++++++++++++++++------------------
 src/views/project/finance/pay/TrackEdit.vue           |  58 ++++++++++++++++++++++++++++++++++++++++++----------------
 src/views/project/finance/pay/index.vue               | 332 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
 src/views/project/finance/pay/pay.data.tsx            |  88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
 src/views/project/finance/receive/FinanceEdit.vue     |  13 ++++++++-----
 src/views/project/finance/receive/InvoiceAnalysis.vue | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------
 src/views/project/finance/receive/InvoiceDetail.vue   |  46 +++++++++++++++++++++++++++++++++++++++++-----
 src/views/project/finance/receive/TrackEdit.vue       |  24 ++++++++++++++++--------
 src/views/project/finance/receive/index.vue           | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 src/views/project/finance/receive/receive.data.tsx    |  72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 src/views/project/finance/receive/type.d.ts           |   9 +++++++++
 src/views/project/order/ExportModal.vue               |   1 -
 src/views/project/order/FormDetail/index.vue          |  32 +++++++++++++++++++++++---------
 src/views/project/order/InvoiceCreate.vue             |  11 ++++++-----
 src/views/project/order/PassCalculate.vue             |  33 ++++++++++++++-------------------
 src/views/project/order/ProductInvoice.vue            |  14 ++++++++++----
 src/views/project/order/ProductText.vue               |  35 +++++++++++++++++++++--------------
 src/views/project/order/TrackHistory.vue              |  33 ++++++++++++++++++++++++++++-----
 src/views/project/order/index.vue                     | 314 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------------------------------------------------------
 src/views/project/order/tableData.tsx                 | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
 vite.config.ts                                        |   3 +++
 38 files changed, 1939 insertions(+), 322 deletions(-)
 create mode 100644 src/views/project/approve/ReceivePanel.vue
 create mode 100644 src/views/project/finance/pay/CheckDetail.vue
 create mode 100644 src/views/project/finance/pay/CheckSum.vue
 create mode 100644 src/views/project/finance/receive/type.d.ts

diff --git a/src/api/project/approve.ts b/src/api/project/approve.ts
index ec5d6b7..854688a 100644
--- a/src/api/project/approve.ts
+++ b/src/api/project/approve.ts
@@ -30,7 +30,7 @@ export const getWaitListApi = async (params: DemoParams) => {
   res.records = res.records.map((item) => {
     return item;
   });
-
+  console.log(res.records, 5656565656);
   return new Promise((resolve) => {
     resolve({ items: res.records, total: res.total });
   });
diff --git a/src/api/project/invoice.ts b/src/api/project/invoice.ts
index 5b11834..2a006ff 100644
--- a/src/api/project/invoice.ts
+++ b/src/api/project/invoice.ts
@@ -11,9 +11,21 @@ enum Api {
   UPDATE_AMOUNT = '/order/erp/invoice_bill/update_amount_info', //更新其他金额信息
   INVOICE_DELETE = '/order/erp/invoice_bill/delete_by_id', //删除数据
   COMMIT = '/order/erp/invoice_bill/commit_apply', //提交审核
+
+  PRODUCT_CREATE = '/order/erp/check_bill/create', //创建生产科应付单据
+  PAYED_DATE = '/order/erp/check_bill/get_payed_date', //获取生产科应回款日期
+  UPDATE_DEDUCT_INFO = '/order/erp/check_bill/update_deduct_info', //更新扣款信息
+  UPDATE_AMOUNT_INFO = '/order/erp/check_bill/update_amount_info', //更新其他金额信息
+  UPDATE_INVOICE_INFO = '/order/erp/check_bill/update_invoice_info', //更新发票信息
+  CHECK_COMMIT = '/order/erp/check_bill/commit_apply', //提交审核
+  CHECK_DELETE = '/order/erp/check_bill/delete_by_id', //删除数据
+  CHECK_BILL = '/order/erp/check_bill/list_by_page', //分页查询列表
+  CHECK_DETAIL = '/order/erp/check_bill/list_base_order_info_by', //基础订单查询
+  CHECK_ANALYSIS = '/order/erp/check_bill/list_analysis_by', //分析列表
+  EXPORT_CHECK_ANALYSIS = '/order/erp/check_bill/export', //导出分析列表
 }
 
-export const getRefundDate = async (params: any) => {
+export const getRefundDate = async (params: any, data?: any) => {
   const res = await defHttp.post<any>({
     url: Api.REFUND_DATE,
     params,
@@ -33,7 +45,6 @@ export const getInvoice = async (params: any) => {
     url: Api.INVOICE,
     params,
   });
-  console.log(res, 5656);
   return res.records;
 };
 export const getBaseInvoice = async (params: any) => {
@@ -55,13 +66,15 @@ export const exportAnalysis = async (params: any) => {
     params,
   });
 };
+
 export const updateDeduct = async (params: any) => {
   return await defHttp.post<any>({
     url: Api.UPDATE_DEDUCT,
     params,
   });
 };
-export const updateAmount = async (params: any, p0?: { id: any; bgUrl: any }) => {
+// export const updateAmount = async (params: any, p0?: { id: any; bgUrl: any }) => {
+export const updateAmount = async (params: any) => {
   return await defHttp.post<any>({
     url: Api.UPDATE_AMOUNT,
     params,
@@ -79,3 +92,72 @@ export const commit = async (params: any) => {
     params,
   });
 };
+
+export const checkCreate = async (params: any) => {
+  return await defHttp.post<any>({
+    url: Api.PRODUCT_CREATE,
+    params,
+  });
+};
+export const payDate = async (params: any) => {
+  return await defHttp.post<any>({
+    url: Api.PAYED_DATE,
+    params,
+  });
+};
+export const updateDeductInfo = async (params: any) => {
+  return await defHttp.post<any>({
+    url: Api.UPDATE_DEDUCT_INFO,
+    params,
+  });
+};
+export const updateAmountInfo = async (params: any) => {
+  return await defHttp.post<any>({
+    url: Api.UPDATE_AMOUNT_INFO,
+    params,
+  });
+};
+export const checkCommit = async (params: any) => {
+  return await defHttp.post<any>({
+    url: Api.CHECK_COMMIT,
+    params,
+  });
+};
+export const checkDelete = async (params: any, id?: string[]) => {
+  return await defHttp.post<any>({
+    url: Api.CHECK_DELETE,
+    params,
+  });
+};
+export const getCheck = async (params: any) => {
+  const res = await defHttp.post<any>({
+    url: Api.CHECK_BILL,
+    params,
+  });
+  console.log(res, '5656check');
+  return res.records;
+};
+export const checkDetail = async (params: any) => {
+  return await defHttp.post<any>({
+    url: Api.CHECK_DETAIL,
+    params,
+  });
+};
+export const checkAnalysis = async (params: any) => {
+  return await defHttp.post<any>({
+    url: Api.CHECK_ANALYSIS,
+    params,
+  });
+};
+export const updateInvoiceInfo = async (params: any) => {
+  return await defHttp.post<any>({
+    url: Api.UPDATE_INVOICE_INFO,
+    params,
+  });
+};
+export const exportCheckAnalysis = async (params: any) => {
+  return await defHttp.post<any>({
+    url: Api.EXPORT_CHECK_ANALYSIS,
+    params,
+  });
+};
diff --git a/src/api/project/order.ts b/src/api/project/order.ts
index de03148..44d170b 100644
--- a/src/api/project/order.ts
+++ b/src/api/project/order.ts
@@ -33,6 +33,7 @@ enum Api {
   ORDER_FIELD_CHECK = '/order/erp/order/check', // 校验内部编号是否重复
 
   TRACK_HISTORY = '/order/erp/opinion/log/query_by_id', //跟单结果记录
+  PASS_CALCULATE = '/order/erp/order/passRate', //一次性通过率
 }
 
 export const formatSearchData = (params) => {
@@ -187,6 +188,7 @@ export const orderExport = async (data: any = {}) => {
       a.download = `${strArr.join('_')} ${date}.xlsx`; // 你可以为文件命名
       document.body.appendChild(a);
       a.click(); // 模拟点击操作来下载文件
+      console.log(a, '5656a');
       URL.revokeObjectURL(downloadUrl); // 释放掉 blob 对象所占用的内存
       document.body.removeChild(a);
 
@@ -305,3 +307,11 @@ export const trackHistory = async (data: any) => {
   });
   return res;
 };
+
+export const passCalculate = async (data: any) => {
+  const res = await defHttp.post<any>({
+    url: Api.PASS_CALCULATE,
+    data: data,
+  });
+  return res;
+};
diff --git a/src/api/sys/config.ts b/src/api/sys/config.ts
index 0696780..4766d4d 100644
--- a/src/api/sys/config.ts
+++ b/src/api/sys/config.ts
@@ -91,6 +91,12 @@ export const getEmailList = async (params: any) => {
     params,
   });
   const resAll = dealRecords(res.records);
+  resAll.sort((a, b) => {
+    if (a.enableFlag === b.enableFlag) {
+      return 0;
+    }
+    return a.enableFlag === 10 ? -1 : 1;
+  });
   return resAll;
 };
 
diff --git a/src/components/Modal/src/hooks/useModal.ts b/src/components/Modal/src/hooks/useModal.ts
index c4cade2..d33f404 100644
--- a/src/components/Modal/src/hooks/useModal.ts
+++ b/src/components/Modal/src/hooks/useModal.ts
@@ -100,7 +100,7 @@ export function useModal(): UseModalReturnType {
   return [register, methods];
 }
 
-export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType => {
+export const useModalInner = (callbackFn?: Fn, p0?: () => Promise<void>): UseModalInnerReturnType => {
   const modalInstanceRef = ref<Nullable<ModalMethods>>(null);
   const currentInstance = getCurrentInstance();
   const uidRef = ref<string>('');
diff --git a/src/router/routes/modules/project/approve.ts b/src/router/routes/modules/project/approve.ts
index 1c7945a..fd2a9f9 100644
--- a/src/router/routes/modules/project/approve.ts
+++ b/src/router/routes/modules/project/approve.ts
@@ -1,6 +1,7 @@
 import type { AppRouteModule } from '/@/router/types';
 
 import { LAYOUT } from '/@/router/constant';
+import { RoleEnum } from '/@/enums/roleEnum';
 
 const order: AppRouteModule = {
   path: '/approve',
@@ -10,7 +11,7 @@ const order: AppRouteModule = {
   meta: {
     hideChildrenInMenu: true,
     orderNo: 3,
-    // icon: 'ion:grid-outline',
+    icon: 'ion:grid-outline',
     title: '审批管理',
   },
   children: [
diff --git a/src/views/project/approve/ReceivePanel.vue b/src/views/project/approve/ReceivePanel.vue
new file mode 100644
index 0000000..8d02d13
--- /dev/null
+++ b/src/views/project/approve/ReceivePanel.vue
@@ -0,0 +1,222 @@
+<template>
+  <BasicTable @register="registerTable" className="p-0">
+    <template #form-custom> custom-slot </template>
+    <template #bodyCell="{ column, record }">
+      <template v-if="column.key === 'picUrl'">
+        <img
+          :width="50"
+          :height="50"
+          :src="record?.orderBaseInfo?.smallPicUrl"
+          @click="handlePreview(record?.orderBaseInfo?.picUrl)"
+        />
+      </template>
+      <template v-if="column.key === 'action'">
+        <TableAction
+          :actions="[
+            {
+              label: '编辑',
+              // icon: 'ic:outline-delete-outline',
+              onClick: handleDetail.bind(null, record),
+            },
+          ]"
+        />
+      </template>
+    </template>
+  </BasicTable>
+  <BasicDrawer
+    :showFooter="!isApproved && role === ROLE.ADMIN"
+    @register="registerDrawer"
+    title="申请信息"
+    okText="通过"
+    @ok="handleTrue"
+  >
+    <BaseInfo :baseInfos="baseInfos" />
+    <h2>收款单信息</h2>
+    <div v-for="field in fieldInfos" :key="field">
+      <span className="w-[140px] inline-block text-right mr-3">{{ field.label }}:</span
+      ><span>{{ field.value }}</span>
+    </div>
+    <template #appendFooter>
+      <a-button @click="handleFalse"> 不通过</a-button>
+    </template>
+  </BasicDrawer>
+  <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" />
+</template>
+<script lang="ts">
+  import MsgModal from './MsgModal.vue';
+  import { computed, defineComponent, ref } from 'vue';
+  import { BasicTable, useTable, TableAction } from '/@/components/Table';
+  import { BasicDrawer, useDrawer } from '/@/components/Drawer';
+
+  import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve';
+  import { FIELDS_BASE_INFO, FIELDS_PROFIT_INFO, FIELDS_REPORT_INFO } from '../order/tableData';
+  import { ROLE } from '../order//type.d';
+  import { useUserStoreWithOut } from '/@/store/modules/user';
+  import BaseInfo from './BaseInfo.vue';
+  import { createImgPreview } from '/@/components/Preview';
+  import { getFormConfig } from './data';
+
+  const userStore = useUserStoreWithOut();
+
+  export default defineComponent({
+    components: {
+      BasicTable,
+      BasicDrawer,
+      TableAction,
+      BaseInfo,
+      MsgModal,
+    },
+    props: {
+      isApproved: { type: Boolean },
+    },
+    setup(props) {
+      // visible 用于msgModal显示隐藏
+      const msgVisible = ref(false);
+      const checkedKeys = ref<Array<string | number>>([]);
+      const currentKey = ref('1');
+      const [registerDrawer, { openDrawer, closeDrawer }] = useDrawer();
+      const fieldInfos = ref({});
+      const baseInfos = ref({});
+      const id = ref('');
+
+      let columns = [
+        {
+          title: '申请人',
+          dataIndex: 'createBy',
+          width: 150,
+        },
+        {
+          title: 'INVOICE编号',
+          dataIndex: 'invoiceNo',
+          width: 150,
+          customRender: (column) => {
+            const { record } = column || {};
+            return record?.fieldInfos?.invoiceBillOrderDO?.invoiceNo;
+          },
+        },
+        // {
+        //   title: '内部编号',
+        //   dataIndex: 'innerNo',
+        //   width: 150,
+        //   customRender: (column) => {
+        //     const { record } = column || {};
+        //     return record?.fieldInfos?.invoiceBillOrderDO?.innerNo;
+        //   },
+        // },
+      ];
+
+      if (props.isApproved) {
+        columns = columns.concat([
+          {
+            title: '状态',
+            dataIndex: 'status',
+            width: 150,
+            customRender: (column) => {
+              const { record } = column || {};
+
+              return record.status === 10 ? '通过' : '拒绝';
+            },
+          },
+          { title: '拒绝原因', dataIndex: 'refuseRemark', width: 250 },
+        ]);
+      }
+
+      const [registerTable, { reload }] = useTable({
+        api: props.isApproved ? getApprovedListApi : getWaitListApi,
+        searchInfo: { type: 30 },
+        // scroll: {
+        //   scrollToFirstRowOnChange: true,
+        // },
+        columns,
+        useSearchForm: true,
+        formConfig: getFormConfig(),
+        rowKey: 'id',
+        actionColumn: {
+          width: 160,
+          title: 'Action',
+          dataIndex: 'action',
+          // slots: { customRender: 'action' },
+        },
+      });
+
+      function onSelect(record, selected) {
+        if (selected) {
+          checkedKeys.value = [...checkedKeys.value, record.id];
+        } else {
+          checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id);
+        }
+      }
+      function onSelectAll(selected, selectedRows, changeRows) {
+        const changeIds = changeRows.map((item) => item.id);
+        if (selected) {
+          checkedKeys.value = [...checkedKeys.value, ...changeIds];
+        } else {
+          checkedKeys.value = checkedKeys.value.filter((id) => {
+            return !changeIds.includes(id);
+          });
+        }
+      }
+      function handleEdit(record, e) {
+        e?.stopPropagation();
+        return false;
+      }
+
+      function handleProfitModal() {}
+
+      async function handleDetail(data) {}
+
+      async function handleTrue() {
+        await approveAuditApi({ status: 10, id: id.value });
+        reload();
+        closeDrawer();
+      }
+
+      async function handleFalse() {
+        msgVisible.value = true;
+        // await approveAuditApi({ status: 20, id: id.value });
+        // reload();
+        // closeDrawer();
+      }
+
+      const role = computed(() => {
+        return userStore.getUserInfo?.roleSmallVO?.code;
+      });
+
+      // 定义MsgModalClose的事件,方便子组件调用
+      const handleMsgModalClose = async (data) => {
+        if (data) {
+          await approveAuditApi({ status: 20, id: id.value, refuseRemark: data });
+          reload();
+          closeDrawer();
+        }
+        msgVisible.value = false;
+      };
+
+      const handlePreview = (url) => {
+        createImgPreview({ imageList: [url], defaultWidth: 500 });
+        return false;
+      };
+
+      return {
+        handleProfitModal,
+        registerTable,
+        checkedKeys,
+        currentKey,
+        onSelect,
+        handleEdit,
+        onSelectAll,
+        handleDetail,
+        registerDrawer,
+        fieldInfos,
+        baseInfos,
+        handleTrue,
+        handleFalse,
+        role,
+        ROLE,
+        msgVisible,
+        handleMsgModalClose,
+        handlePreview,
+      };
+    },
+  });
+</script>
diff --git a/src/views/project/approve/index.vue b/src/views/project/approve/index.vue
index b63cc9c..fead471 100644
--- a/src/views/project/approve/index.vue
+++ b/src/views/project/approve/index.vue
@@ -10,6 +10,9 @@
       <a-tab-pane key="5" tab="项目报告书待审核">
         <ReportPanel />
       </a-tab-pane>
+      <a-tab-pane key="7" tab="应收款待审核">
+        <ReceivePanel />
+      </a-tab-pane>
       <a-tab-pane key="2" tab="字段已审核">
         <FieldPanel isApproved />
       </a-tab-pane>
@@ -19,6 +22,9 @@
       <a-tab-pane key="6" tab="项目报告书已审核">
         <ReportPanel isApproved />
       </a-tab-pane>
+      <a-tab-pane key="8" tab="应收款已审核">
+        <ReceivePanel isApproved />
+      </a-tab-pane>
     </a-tabs>
   </div>
 </template>
@@ -28,6 +34,7 @@
   import ReportPanel from './ReportPanel.vue';
   import ProfitPanel from './ProfitPanel.vue';
   import FieldPanel from './FieldPanel.vue';
+  import ReceivePanel from './ReceivePanel.vue';
   import { useOrderStoreWithOut } from '/@/store/modules/order';
 
   const orderStore = useOrderStoreWithOut();
@@ -39,6 +46,7 @@
       ReportPanel,
       FieldPanel,
       ProfitPanel,
+      ReceivePanel,
     },
     setup() {
       const checkedKeys = ref<Array<string | number>>([]);
diff --git a/src/views/project/config/CreateModal.vue b/src/views/project/config/CreateModal.vue
index 2dca6b8..bc26ba7 100644
--- a/src/views/project/config/CreateModal.vue
+++ b/src/views/project/config/CreateModal.vue
@@ -58,7 +58,7 @@
           {
             field: 'relationValue',
             component: 'InputNumber',
-            label: props.column === 1 ? '利润率' : '包装费用',
+            label: props.column === 1 ? '利润率' : props.column === 5 ? '回款时间' : '包装费用',
             rules: [{ required: true }],
             colProps: {
               span: 24,
@@ -96,7 +96,14 @@
             settingName: '客户编码',
             settingValue: values.settingValue,
             settingType: 1,
-            relationCode: props.column === 1 ? 'profitRate' : 'packetPrice',
+            // relationCode: props.column === 1 ? 'profitRate' : 'packetPrice',
+            relationCode:
+              props.column === 1
+                ? 'profitRate'
+                : props.column === 5
+                ? 'orderHodTime'
+                : 'packetPrice',
+
             relationName: '包装费用',
             relationValue: values.relationValue,
           };
diff --git a/src/views/project/config/DrawerEdit.vue b/src/views/project/config/DrawerEdit.vue
index be8e4b3..373f579 100644
--- a/src/views/project/config/DrawerEdit.vue
+++ b/src/views/project/config/DrawerEdit.vue
@@ -50,7 +50,7 @@
       colProps: {
         span: 23,
       },
-      label: '确认样品确认状态(填写邮箱)',
+      label: '确认样品确认状态(填写邮箱,请用逗号隔开)',
       rules: [{ required: true }],
     },
     {
diff --git a/src/views/project/config/EmailPanel.vue b/src/views/project/config/EmailPanel.vue
index 1e289f3..bb3d906 100644
--- a/src/views/project/config/EmailPanel.vue
+++ b/src/views/project/config/EmailPanel.vue
@@ -1,5 +1,5 @@
 <template>
-  <div class="p-4">
+  <div :style="{ marginLeft: '0px' }">
     <BasicTable @register="registerTable">
       <template #toolbar>
         <!-- <a-button type="primary" class="my-4" @click="handleCreate"> 新增 </a-button> -->
diff --git a/src/views/project/config/TablePanel.vue b/src/views/project/config/TablePanel.vue
index b24667c..c1afa54 100644
--- a/src/views/project/config/TablePanel.vue
+++ b/src/views/project/config/TablePanel.vue
@@ -1,5 +1,5 @@
 <template>
-  <BasicTable @register="registerTable">
+  <BasicTable @register="registerTable" :bordered="true">
     <template #toolbar>
       <a-button v-if="props.column !== 3" type="primary" @click="handleCreateModal">新建</a-button>
     </template>
diff --git a/src/views/project/config/data.tsx b/src/views/project/config/data.tsx
index f6ca632..93f7c5d 100644
--- a/src/views/project/config/data.tsx
+++ b/src/views/project/config/data.tsx
@@ -45,6 +45,20 @@ export const COLUMNS = {
       editRow: true,
     },
   ],
+  5: [
+    {
+      title: '客户编码',
+      dataIndex: 'settingValue',
+      width: 150,
+    },
+    {
+      title: '最后汇款日期',
+      dataIndex: 'relationValue',
+      width: 150,
+      editComponent: 'InputNumber',
+      editRow: true,
+    },
+  ],
 };
 
 export const columns: BasicColumn[] = [
@@ -56,7 +70,7 @@ export const columns: BasicColumn[] = [
   {
     title: '状态',
     dataIndex: 'enableFlag',
-    width: 70,
+    width: 100,
     customRender: (column) => {
       const { record } = column || {};
       return record.enableFlag === 10 ? <Tag color="green">启用</Tag> : <Tag color="red">禁用</Tag>;
diff --git a/src/views/project/config/index.vue b/src/views/project/config/index.vue
index 3b2a57f..babbe0e 100644
--- a/src/views/project/config/index.vue
+++ b/src/views/project/config/index.vue
@@ -1,7 +1,11 @@
 <template>
   <PageWrapper contentBackground>
     <div className="config-page">
-      <Tabs v-model:selectedKey="currentKey" className="ml-2 mb-0">
+      <Tabs
+        v-model:selectedKey="currentKey"
+        className="ml-2 mb-0"
+        :style="{ marginLeft: '30px', marginRight: '5px' }"
+      >
         <Tabs.TabPane key="1" tab="利润率配置">
           <TablePanel :searchInfo="{ relationCode: 'profitRate' }" :column="1" />
         </Tabs.TabPane>
@@ -12,6 +16,9 @@
           <TablePanel :searchInfo="{ settingCode: 'exchangeRate' }" :column="3"
         /></Tabs.TabPane>
         <Tabs.TabPane key="4" tab="邮件发送配置"><EmailPanel /></Tabs.TabPane>
+        <Tabs.TabPane key="5" tab="最后汇款日期">
+          <TablePanel :searchInfo="{ relationCode: 'orderHodTime' }" :column="5" />
+        </Tabs.TabPane>
       </Tabs>
     </div>
   </PageWrapper>
diff --git a/src/views/project/finance/pay/CheckDetail.vue b/src/views/project/finance/pay/CheckDetail.vue
new file mode 100644
index 0000000..1f62300
--- /dev/null
+++ b/src/views/project/finance/pay/CheckDetail.vue
@@ -0,0 +1,120 @@
+<template>
+  <template>
+    <BasicDrawer
+      @register="register"
+      v-bind="$attrs"
+      title="订单信息"
+      width="60%"
+      :isDetail="true"
+      :showDetailBack="false"
+      :destroyOnClose="true"
+    >
+      <div class="p-4">
+        <BasicTable @register="registerTable">
+          <template #bodyCell="{ column, record }">
+            <template v-if="column.key === 'action'"> </template>
+            <template v-if="column.key === 'picUrl'">
+              <img :z-index="100000" :width="50" :height="50" :src="record?.smallPicUrl" />
+            </template>
+          </template>
+        </BasicTable>
+      </div>
+    </BasicDrawer>
+  </template>
+</template>
+<script lang="ts" setup>
+  import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
+  import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue';
+  import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table';
+  import { checkDetail } from '/@/api/project/invoice';
+  import { useDesign } from '@/hooks/web/useDesign';
+
+  // const handlePreview = (url) => {
+  //   createImgPreview({ imageList: [url], defaultWidth: 500 });
+  //   return false;
+  // };
+  const columns: BasicColumn[] = [
+    {
+      title: '客户编码',
+      dataIndex: 'customerCode',
+      width: 100,
+    },
+    {
+      title: '项目号',
+      dataIndex: 'projectNo',
+      width: 100,
+    },
+    {
+      title: '内部编码',
+      dataIndex: 'innerNo',
+      width: 100,
+    },
+    {
+      title: '客户po号',
+      dataIndex: 'customerPo',
+      width: 100,
+    },
+    {
+      title: '客户STYLE',
+      width: 150,
+      dataIndex: 'customerStyle',
+    },
+    {
+      title: 'Model(REFERENCE)',
+      width: 150,
+      dataIndex: 'modeleLo',
+    },
+    {
+      title: '订单图片',
+      width: 150,
+      dataIndex: 'picUrl',
+    },
+    {
+      title: '数量',
+      width: 150,
+      dataIndex: 'orderCount',
+    },
+    {
+      title: '生产科单价¥',
+      width: 150,
+      dataIndex: 'productionDepartmentPrice',
+      customRender: (column) => {
+        const { record } = column || {};
+        return record?.profitAnalysisInfo?.productionDepartmentPrice;
+        // ? `¥ ${record?.profitAnalysisInfo?.productionDepartmentPrice}`
+        // : '';
+      },
+    },
+    {
+      title: '生产科总价¥',
+      width: 150,
+      dataIndex: 'productionDepartmentTotalPrice',
+      customRender: (column) => {
+        const { record } = column || {};
+        return record?.profitAnalysisInfo?.productionDepartmentTotalPrice;
+        // ? `¥ ${record?.profitAnalysisInfo?.productionDepartmentTotalPrice}`
+        // : '';
+      },
+    },
+  ];
+  const checkNo = ref();
+
+  const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
+    // 方式1
+    checkNo.value = data.data.checkNo;
+    console.log(data, '56562vvsdfv');
+    // checkDetail({ checkNo: checkNo.value });
+  });
+  const params = ref({
+    checkNo: checkNo.value,
+  });
+  const [registerTable] = useTable({
+    api: () => {
+      const res = checkDetail({ checkNo: checkNo.value });
+      console.log(res, 56565555);
+      return res;
+    },
+    columns: columns,
+    bordered: true,
+  });
+</script>
diff --git a/src/views/project/finance/pay/CheckSum.vue b/src/views/project/finance/pay/CheckSum.vue
new file mode 100644
index 0000000..50acdf8
--- /dev/null
+++ b/src/views/project/finance/pay/CheckSum.vue
@@ -0,0 +1,146 @@
+<template>
+  <BasicModal
+    v-bind="$attrs"
+    @register="register"
+    title="收款单汇总"
+    width="80%"
+    :isDetail="true"
+    :showDetailBack="false"
+    @ok="handleOk"
+    @visible-change="handleShow"
+  >
+    <div class="p-4">
+      <BasicTable @register="registerTable">
+        <template #bodyCell="{ column, record }">
+          <template v-if="column.key === 'action'"> </template>
+        </template>
+      </BasicTable>
+    </div>
+  </BasicModal>
+</template>
+<script lang="ts" setup>
+  import { BasicModal, useModalInner } from '@/components/Modal';
+  import { computed, ref } from 'vue';
+  import { checkAnalysis, exportCheckAnalysis } from '@/api/project/invoice';
+  import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table';
+  // 处理弹窗的确定按钮点击事件
+  import axios from 'axios';
+
+  const columnsAnalysis: BasicColumn[] = [
+    {
+      title: '生产科名称',
+      dataIndex: 'productionDepartment',
+      width: 50,
+      customRender: (res) => {
+        // console.log(res, 56562);
+        return res.record.exportVOS[0].productionDepartment;
+      },
+    },
+    {
+      title: '生产科总价汇总',
+      dataIndex: 'productionDepartmentTotalPrice',
+      width: 50,
+    },
+    {
+      title: '生产科扣款金额汇总',
+      dataIndex: 'actualReceivableAmount',
+      width: 50,
+    },
+    {
+      title: '生产科实际应付金额',
+      dataIndex: 'calculateActualPayedAmount',
+      width: 50,
+    },
+    {
+      title: '实际付款金额汇总',
+      dataIndex: 'actualPayedAmount',
+      width: 50,
+    },
+    {
+      title: '未付金额',
+      dataIndex: 'unPayedAmount',
+      width: 50,
+    },
+  ];
+  // const ids = ref<number[]>([]);
+  const ids = ref();
+  // const res = ref();
+
+  const [register, { closeModal }] = useModalInner(async (data) => {
+    ids.value = data.data;
+    setTimeout(() => {
+      reload();
+    }, 50);
+  });
+  const [registerTable, { reload }] = useTable({
+    // api: () => invoiceAnalysis({ ids: ids.value }),
+    api: async () => {
+      const res = await checkAnalysis({ ids: ids.value });
+      const arrayRes = ref([]);
+      arrayRes.value.push(res);
+      console.log(res, 56561);
+      return arrayRes.value;
+    },
+    columns: columnsAnalysis,
+    bordered: true,
+  });
+  function handleShow(visible: boolean) {
+    reload();
+  }
+  const searchData = ref({});
+  async function handleOk() {
+    // 构造符合 API 要求的参数
+    // const ids = [23];
+    // const requestData = {
+    //   ids: ids.value,
+    // };
+    const idss = ids.value;
+    // await exportCheckAnalysis({ ids: ids });
+    axios
+      .post(
+        '/basic-api/order/erp/check_bill/export',
+        { ids: idss },
+        {
+          responseType: 'blob', // 设置响应类型为 'blob'
+        },
+      )
+      .then((response) => {
+        // 创建一个 Blob 对象来保存二进制数据
+        const blob = new Blob([response.data], { type: 'application/zip' });
+        const getFormattedDate = (): string => {
+          const date = new Date();
+
+          const year = date.getFullYear();
+          const month = String(date.getMonth() + 1).padStart(2, '0');
+          const day = String(date.getDate()).padStart(2, '0');
+
+          const hours = String(date.getHours()).padStart(2, '0');
+          const minutes = String(date.getMinutes()).padStart(2, '0');
+          const seconds = String(date.getSeconds()).padStart(2, '0');
+
+          return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+        };
+        const date = getFormattedDate();
+        // 创建一个链接元素用于下载
+        const link = document.createElement('a');
+        link.href = window.URL.createObjectURL(blob);
+        link.download = `应付款分析${date}.xlsx`; // 你可以为文件命名
+        document.body.appendChild(link);
+        link.click(); // 自动点击链接,触发下载
+        console.log(link, 5656);
+        document.body.removeChild(link); // 下载完成后移除链接
+      })
+      .catch((error) => {
+        console.error(error);
+      });
+    reload();
+    closeModal();
+  }
+</script>
+<style scoped>
+  .divAll {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+</style>
diff --git a/src/views/project/finance/pay/FinanceEdit.vue b/src/views/project/finance/pay/FinanceEdit.vue
index 6874405..817df63 100644
--- a/src/views/project/finance/pay/FinanceEdit.vue
+++ b/src/views/project/finance/pay/FinanceEdit.vue
@@ -28,11 +28,13 @@
   import { BasicForm, FormSchema, useForm } from '@/components/Form';
   import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue';
   import { getEmailList } from '/@/api/sys/config';
+  import { updateAmountInfo } from '@/api/project/invoice';
 
+  const emit = defineEmits(['success']);
   const schemas: FormSchema[] = [
     {
-      field: 'configSample',
-      component: 'Input',
+      field: 'actualPayedAmount',
+      component: 'InputNumber',
       labelWidth: 250,
       colProps: {
         span: 23,
@@ -40,31 +42,31 @@
       label: '生产科实际应付金额',
     },
     {
-      field: 'configSample',
-      component: 'Input',
+      field: 'actualPayedAmount1',
+      component: 'InputNumber',
       labelWidth: 250,
       colProps: {
         span: 23,
       },
-      label: '实际应收金额1',
+      label: '实际应付金额1',
     },
     {
-      field: 'configSample',
-      component: 'Input',
+      field: 'actualPayedAmount2',
+      component: 'InputNumber',
       labelWidth: 250,
       colProps: {
         span: 23,
       },
-      label: '实际应收金额2',
+      label: '实际应付金额2',
     },
     {
-      field: 'configSample',
-      component: 'Input',
+      field: 'actualPayedAmount3',
+      component: 'InputNumber',
       labelWidth: 250,
       colProps: {
         span: 23,
       },
-      label: '实际应收金额3',
+      label: '实际应付金额3',
     },
   ];
   const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({
@@ -76,23 +78,30 @@
       span: 24,
     },
   });
+
+  const update = ref();
   const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
     // 方式1
-    console.log(data, 56561);
     resetFields();
     setDrawerProps({ confirmLoading: false });
     setFieldsValue({
       ...toRaw(data.data),
     });
+    update.value = data;
+    console.log(data, '5656data');
   });
-  //获取现有的列表
-  async function getData() {
-    const emailAll = await getEmailList({});
-    return emailAll;
-  }
   //完成编辑
   async function handleSubmit() {
     const values = await validate();
-    console.log('5656handleSubmit');
+    const updatedValues = {
+      ...values,
+      id: update.value.data.id,
+    };
+    console.log(updatedValues, 56565);
+    await updateAmountInfo({
+      ...updatedValues,
+    });
+    emit('success');
+    closeDrawer();
   }
 </script>
diff --git a/src/views/project/finance/pay/InvoiceUpload.vue b/src/views/project/finance/pay/InvoiceUpload.vue
index b9c4996..8460940 100644
--- a/src/views/project/finance/pay/InvoiceUpload.vue
+++ b/src/views/project/finance/pay/InvoiceUpload.vue
@@ -4,13 +4,15 @@
     @register="register"
     title="发票上传"
     width="500px"
-    :bodyStyle="{ height: '200px' }"
+    :bodyStyle="{ height: '240px' }"
     @ok="handleOk"
     ><a-upload-dragger
       v-model:fileList="fileList"
       name="file"
+      :beforeUpload="beforeUpload"
+      :max-count="1"
       :multiple="true"
-      action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
+      :action="updateInvoiceUrl"
       @change="handleChange"
       @drop="handleDrop"
     >
@@ -27,31 +29,43 @@
   import type { UploadProps, UploadChangeParam } from 'ant-design-vue';
   import { InboxOutlined } from '@ant-design/icons-vue';
   import { message } from 'ant-design-vue';
+  import { updateInvoiceInfo } from '@/api/project/invoice';
 
-  const handleChange = (info: UploadChangeParam) => {
-    const status = info.file.status;
-    if (status !== 'uploading') {
-      console.log(info.file, info.fileList);
-    }
-    if (status === 'done') {
-      message.success(`${info.file.name} file uploaded successfully.`);
-    } else if (status === 'error') {
-      message.error(`${info.file.name} file upload failed.`);
+  const emit = defineEmits(['success']);
+  const uploadUrl = ref('http://47.104.8.35:18000/api/localStorage/upload_file_oss?name=');
+  const updateInvoiceUrl = ref('http://47.104.8.35:18000/api/localStorage/upload_file_oss?name=');
+  const invoiceUrl = ref();
+  const id = ref();
+
+  const [register, { closeModal }] = useModalInner(async (data) => {
+    // fileList.value = [];
+    fileList.value = [];
+    invoiceUrl.value = data.data.invoiceUrl;
+    id.value = data.data.id;
+  });
+
+  const handleChange = (info) => {
+    if (info.file.status == 'done') {
+      updateInvoiceUrl.value = info.file.response.data.fileUrl;
+      invoiceUrl.value = updateInvoiceUrl.value;
     }
   };
+  function beforeUpload(info) {
+    updateInvoiceUrl.value = uploadUrl.value + info.name;
+  }
   function handleDrop(e: DragEvent) {
     console.log(e);
   }
   const fileList = ref<UploadProps['fileList']>([]);
 
-  const Input1 = ref('');
-  const Input2 = ref('123');
-
-  const [register, { closeModal }] = useModalInner(async (data) => {
-    title.value = data.title;
-  });
-  const title = ref('');
   async function handleOk() {
+    await updateInvoiceInfo({
+      id: id.value,
+      invoiceUrl: invoiceUrl.value,
+    });
+    // await updateDeduct(requestData);
+    fileList.value = [];
+    emit('success');
     closeModal();
   }
 </script>
diff --git a/src/views/project/finance/pay/TrackEdit.vue b/src/views/project/finance/pay/TrackEdit.vue
index d21d769..0840ac7 100644
--- a/src/views/project/finance/pay/TrackEdit.vue
+++ b/src/views/project/finance/pay/TrackEdit.vue
@@ -3,7 +3,7 @@
     <BasicDrawer
       @register="register"
       v-bind="$attrs"
-      title="编辑"
+      title="跟单编辑"
       width="30%"
       :isDetail="true"
       @ok="handleSubmit"
@@ -14,23 +14,22 @@
     >
       <div>
         <div style="font-size: 15px">生产科扣款金额</div>
-        <a-input v-model:value="Input1" placeholder="请输入" auto-size />
+        <a-input v-model:value="input1" placeholder="请输入" auto-size />
         <div style="margin: 16px 0"></div>
         <div style="font-size: 15px">扣款责任部门</div>
-        <a-input v-model:value="Input2" placeholder="请输入" auto-size />
+        <a-input v-model:value="deductDept" placeholder="请输入" auto-size />
         <div style="margin: 16px 0"></div>
         <div>上传扣款单</div
         ><a-space direction="vertical" style="width: 100%" size="large">
           <a-upload
             v-model:file-list="fileList"
+            :beforeUpload="beforeUpload"
             list-type="picture"
             :max-count="1"
-            action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
+            :action="updateDeductUrl"
+            @change="handleChange"
           >
-            <a-button>
-              <!-- <upload-outlined></upload-outlined> -->
-              上传报关单
-            </a-button>
+            <a-button> 上传扣款单 </a-button>
           </a-upload>
         </a-space>
       </div>
@@ -47,22 +46,49 @@
   import { getEmailList } from '/@/api/sys/config';
   import { UploadOutlined } from '@ant-design/icons-vue';
   import type { UploadProps } from 'ant-design-vue';
+  import { updateDeductInfo } from '@/api/project/invoice';
 
+  const emit = defineEmits(['success']);
   const fileList = ref<UploadProps['fileList']>([]);
 
-  const Input1 = ref('');
-  const Input2 = ref('123');
+  const input1 = ref();
+  const deductUrl = ref();
+  const id = ref();
+  const checkNo = ref();
+  const deductDept = ref();
+  const uploadUrl = ref('http://47.104.8.35:18000/api/localStorage/upload_file_oss?name=');
+  const updateDeductUrl = ref('http://47.104.8.35:18000/api/localStorage/upload_file_oss?name=');
 
   const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
-    console.log(data, 56561);
+    id.value = data.data.id;
+    checkNo.value = data.data.checkNo;
+    input1.value = data.data.deductAmount;
+    deductDept.value = data.data.deductDept;
+    deductUrl.value = data.data.deductUrl;
   });
-  //获取现有的列表
-  async function getData() {
-    const emailAll = await getEmailList({});
-    return emailAll;
+
+  function handleChange(info) {
+    if (info.file.status == 'done') {
+      updateDeductUrl.value = info.file.response.data.fileUrl;
+      deductUrl.value = updateDeductUrl.value;
+    }
+  }
+  function beforeUpload(info) {
+    updateDeductUrl.value = uploadUrl.value + info.name;
   }
+
   //完成编辑
   async function handleSubmit() {
-    console.log('5656handleSubmit');
+    await updateDeductInfo({
+      id: id.value,
+      checkNo: checkNo.value,
+      deductAmount: input1.value,
+      deductDept: deductDept.value,
+      deductUrl: deductUrl.value,
+    });
+    // await updateDeduct(requestData);
+    fileList.value = [];
+    emit('success');
+    closeDrawer();
   }
 </script>
diff --git a/src/views/project/finance/pay/index.vue b/src/views/project/finance/pay/index.vue
index 148bbcd..d4a58ff 100644
--- a/src/views/project/finance/pay/index.vue
+++ b/src/views/project/finance/pay/index.vue
@@ -2,10 +2,12 @@
   <div class="p-4">
     <BasicTable @register="registerTable">
       <template #toolbar>
-        <a-button type="primary">导出</a-button>
-        <FinanceEdit @register="registerFinanceEdit" />
-        <TrackEdit @register="registerTrackEdit" />
-        <InvoiceUpload @register="registerInvoiceUpload" />
+        <a-button type="primary" @click="handleCheckSum">应付款汇总</a-button>
+        <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" />
+        <TrackEdit @register="registerTrackEdit" @success="handleSuccess" />
+        <CheckSum @register="registerCheckSum" />
+        <InvoiceUpload @register="registerInvoiceUpload" @success="handleSuccess" />
+        <CheckDetail @register="registerInvoiceDetail" />
       </template>
       <template #bodyCell="{ column, record }">
         <template v-if="column.key === 'action'">
@@ -26,11 +28,15 @@
             ]"
             :dropDownActions="[
               {
-                label: '应付款提交',
-                onClick: handleDelete.bind(null, record),
+                label: '提交审核',
+                onClick: handleCommit.bind(null, record),
               },
               {
                 label: '订单信息',
+                onClick: handleDetail.bind(null, record),
+              },
+              {
+                label: '删除',
                 onClick: handleDelete.bind(null, record),
               },
             ]"
@@ -41,28 +47,38 @@
   </div>
 </template>
 <script lang="ts" setup>
-  import { defineComponent } from 'vue';
+  import { defineComponent, ref } from 'vue';
   import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table';
   import { searchFormSchema, columns } from './pay.data';
-  import { demoListApi } from '/@/api/demo/table';
   import TrackEdit from './TrackEdit.vue';
   import FinanceEdit from './FinanceEdit.vue';
   import InvoiceUpload from './InvoiceUpload.vue';
+  import CheckDetail from './CheckDetail.vue';
+  import CheckSum from './CheckSum.vue';
   import { useDrawer } from '/@/components/Drawer';
   import { useModal } from '/@/components/Modal';
+  import { getCheck, checkDelete, checkCommit, checkDetail } from '@/api/project/invoice';
+  import { useMessage } from '/@/hooks/web/useMessage';
 
+  const [registerCheckSum, { openModal: openCheckSum }] = useModal();
   const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer();
   const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer();
   const [registerInvoiceUpload, { openModal: openInvoiceUpload }] = useModal();
+  const [registerInvoiceDetail, { openDrawer: openCheckDetail }] = useDrawer();
+  const checkedKeys = ref<Array<string | number>>([]);
 
-  const [registerTable] = useTable({
+  const [registerTable, { reload }] = useTable({
     title: '',
-    api: demoListApi,
+    api: getCheck,
     columns: columns,
     bordered: true,
+    clickToRowSelect: false,
     rowKey: 'id',
     rowSelection: {
       type: 'checkbox',
+      selectedRowKeys: checkedKeys,
+      onSelect,
+      onSelectAll,
     },
     formConfig: {
       labelWidth: 120,
@@ -82,28 +98,314 @@
       // slots: { customRender: 'action' },
     },
   });
+  //选择
+  // function onSelect(record, selected) {
+  //   if (selected) {
+  //     checkedKeys.value = [...checkedKeys.value, record.id];
+  //   } else {
+  //     checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id);
+  //   }
+  // }
+  // function onSelectAll(selected, selectedRows, changeRows) {
+  //   const changeIds = changeRows.map((item) => item.id);
+  //   if (selected) {
+  //     checkedKeys.value = [...checkedKeys.value, ...changeIds];
+  //   } else {
+  //     checkedKeys.value = checkedKeys.value.filter((id) => {
+  //       return !changeIds.includes(id);
+  //     });
+  //   }
+  // }
+
+  // type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count]
+
+  // const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref
+
+  // // 选择函数
+  // async function onSelect(record: any, selected: boolean) {
+  //   if (selected) {
+  //     const res = await checkDetail({ checkNo: record.checkNo });
+  //     const customerCode = res[0].customerCode;
+
+  //     const index = selectedCustomCodes.value.findIndex(([code]) => code === customerCode);
+
+  //     if (index !== -1) {
+  //       // 如果存在,增加计数
+  //       selectedCustomCodes.value[index][1] += 1;
+  //     } else {
+  //       // 如果不存在,添加新项 [customerCode, 1]
+  //       selectedCustomCodes.value.push([customerCode, 1]);
+  //     }
+
+  //     checkedKeys.value = [...checkedKeys.value, record.id];
+  //   } else {
+  //     const res = await checkDetail({ checkNo: record.checkNo });
+  //     const customerCode = res[0].customerCode;
+
+  //     const index = selectedCustomCodes.value.findIndex(([code]) => code === customerCode);
+
+  //     if (index !== -1) {
+  //       if (selectedCustomCodes.value[index][1] > 1) {
+  //         // 如果计数大于 1,减少计数
+  //         selectedCustomCodes.value[index][1] -= 1;
+  //       } else {
+  //         // 如果计数为 1,移除该项
+  //         selectedCustomCodes.value.splice(index, 1);
+  //       }
+  //     }
+
+  //     checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id);
+  //   }
+  //   console.log(selectedCustomCodes.value, 56561);
+  //   console.log(checkedKeys.value, 56562);
+  // }
+
+  // async function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) {
+  //   const changeIds = changeRows.map((item) => item.id);
+  //   const changeCustomerCodes = await Promise.all(
+  //     changeRows.map(async (item) => {
+  //       const res = await checkDetail({ checkNo: item.checkNo });
+  //       return res[0].customerCode;
+  //     }),
+  //   );
+
+  //   if (selected) {
+  //     // 添加到 checkedKeys
+  //     checkedKeys.value = [...checkedKeys.value, ...changeIds];
+
+  //     // 处理每个 customerCode
+  //     changeCustomerCodes.forEach((code) => {
+  //       const index = selectedCustomCodes.value.findIndex(
+  //         ([customerCode]) => customerCode === code,
+  //       );
+  //       if (index !== -1) {
+  //         // 如果存在,增加计数
+  //         selectedCustomCodes.value[index][1] += 1;
+  //       } else {
+  //         // 如果不存在,添加新项 [customerCode, 1]
+  //         selectedCustomCodes.value.push([code, 1]);
+  //       }
+  //     });
+  //   } else {
+  //     // 从 checkedKeys 中移除
+  //     checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id));
+
+  //     // 处理每个 customerCode
+  //     changeCustomerCodes.forEach((code) => {
+  //       const index = selectedCustomCodes.value.findIndex(
+  //         ([customerCode]) => customerCode === code,
+  //       );
+  //       if (index !== -1) {
+  //         if (selectedCustomCodes.value[index][1] > 1) {
+  //           // 如果计数大于 1,减少计数
+  //           selectedCustomCodes.value[index][1] -= 1;
+  //         } else {
+  //           // 如果计数为 1,移除该项
+  //           selectedCustomCodes.value.splice(index, 1);
+  //         }
+  //       }
+  //     });
+  //   }
+  //   console.log(selectedCustomCodes.value, 56561);
+  //   console.log(checkedKeys.value, 56562);
+  // }
+
+  type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count]
+  type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count]
+
+  const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref
+  const selectedProductionDepartment = ref<ProductionDepartmentEntry[]>([]); // 创建一个二维数组的 ref
+  // const checkedKeys = ref<string[]>([]); // 选中的键值列表
+
+  // 单选函数
+  async function onSelect(record, selected: boolean) {
+    const res = await checkDetail({ checkNo: record.checkNo });
+
+    const customerCode = res[0].customerCode;
+    const productionDepartment = res[0].productionDepartment;
+
+    const customerCodeIndex = selectedCustomCodes.value.findIndex(
+      ([code]) => code === customerCode,
+    );
+
+    const productionDepartmentIndex = selectedProductionDepartment.value.findIndex(
+      ([department]) => department === productionDepartment,
+    );
+
+    if (selected) {
+      checkedKeys.value = [...checkedKeys.value, record.id];
+
+      // 更新 selectedCustomCodes
+      if (customerCodeIndex !== -1) {
+        selectedCustomCodes.value[customerCodeIndex][1] += 1;
+      } else {
+        selectedCustomCodes.value.push([customerCode, 1]);
+      }
+
+      // 更新 selectedProductionDepartment
+      if (productionDepartmentIndex !== -1) {
+        selectedProductionDepartment.value[productionDepartmentIndex][1] += 1;
+      } else {
+        selectedProductionDepartment.value.push([productionDepartment, 1]);
+      }
+    } else {
+      checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id);
+
+      // 更新 selectedCustomCodes
+      if (customerCodeIndex !== -1) {
+        if (selectedCustomCodes.value[customerCodeIndex][1] > 1) {
+          selectedCustomCodes.value[customerCodeIndex][1] -= 1;
+        } else {
+          selectedCustomCodes.value.splice(customerCodeIndex, 1);
+        }
+      }
+
+      // 更新 selectedProductionDepartment
+      if (productionDepartmentIndex !== -1) {
+        if (selectedProductionDepartment.value[productionDepartmentIndex][1] > 1) {
+          selectedProductionDepartment.value[productionDepartmentIndex][1] -= 1;
+        } else {
+          selectedProductionDepartment.value.splice(productionDepartmentIndex, 1);
+        }
+      }
+    }
+    console.log(checkedKeys.value, 565666666); // 输出当前的 selectedCustomCodes 值
+    console.log(selectedCustomCodes.value, 565666666); // 输出当前的 selectedCustomCodes 值
+    console.log(selectedProductionDepartment.value, 565666666); // 输出当前的 selectedCustomCodes 值
+  }
+
+  // 全选函数
+  async function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) {
+    const changeIds = changeRows.map((item) => item.id);
+    const changeCustomerCodes = await Promise.all(
+      changeRows.map(async (item) => {
+        const res = await checkDetail({ checkNo: item.checkNo });
+        return res[0].customerCode;
+      }),
+    );
+
+    const changeProductionDepartments = await Promise.all(
+      changeRows.map(async (item) => {
+        const res = await checkDetail({ checkNo: item.checkNo });
+        return res[0].productionDepartment;
+      }),
+    );
+
+    if (selected) {
+      checkedKeys.value = [...checkedKeys.value, ...changeIds];
+
+      // 更新 selectedCustomCodes
+      changeCustomerCodes.forEach((code) => {
+        const index = selectedCustomCodes.value.findIndex(
+          ([customerCode]) => customerCode === code,
+        );
+        if (index !== -1) {
+          selectedCustomCodes.value[index][1] += 1;
+        } else {
+          selectedCustomCodes.value.push([code, 1]);
+        }
+      });
+
+      // 更新 selectedProductionDepartment
+      changeProductionDepartments.forEach((department) => {
+        const index = selectedProductionDepartment.value.findIndex(
+          ([prodDepartment]) => prodDepartment === department,
+        );
+        if (index !== -1) {
+          selectedProductionDepartment.value[index][1] += 1;
+        } else {
+          selectedProductionDepartment.value.push([department, 1]);
+        }
+      });
+    } else {
+      checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id));
+
+      // 更新 selectedCustomCodes
+      changeCustomerCodes.forEach((code) => {
+        const index = selectedCustomCodes.value.findIndex(
+          ([customerCode]) => customerCode === code,
+        );
+        if (index !== -1) {
+          if (selectedCustomCodes.value[index][1] > 1) {
+            selectedCustomCodes.value[index][1] -= 1;
+          } else {
+            selectedCustomCodes.value.splice(index, 1);
+          }
+        }
+      });
+
+      // 更新 selectedProductionDepartment
+      changeProductionDepartments.forEach((department) => {
+        const index = selectedProductionDepartment.value.findIndex(
+          ([prodDepartment]) => prodDepartment === department,
+        );
+        if (index !== -1) {
+          if (selectedProductionDepartment.value[index][1] > 1) {
+            selectedProductionDepartment.value[index][1] -= 1;
+          } else {
+            selectedProductionDepartment.value.splice(index, 1);
+          }
+        }
+      });
+    }
+
+    console.log(checkedKeys.value, 565666666); // 输出当前的 selectedCustomCodes 值
+    console.log(selectedCustomCodes.value, 565666666); // 输出当前的 selectedCustomCodes 值
+    console.log(selectedProductionDepartment.value, 565666666); // 输出当前的 selectedCustomCodes 值
+  }
+
   function handleFinanceEdit(record) {
-    console.log('点击了编辑', record);
     openFinanceEdit(true, {
       data: record,
     });
   }
   function handleTrackEdit(record) {
-    console.log('点击了编辑', record);
     openTrackEdit(true, {
       data: record,
     });
   }
   function handleInvoiceUpload(record) {
-    console.log('点击了编辑', record);
     openInvoiceUpload(true, {
       data: record,
     });
   }
   function handleDelete(record) {
-    console.log('点击了编辑', record);
-    openTrackEdit(true, {
+    const id: string[] = Array.isArray(record.id) ? record.id : [record.id];
+    checkDelete({ ids: id });
+    setTimeout(() => {
+      reload();
+    }, 50);
+  }
+  function handleDetail(record) {
+    openCheckDetail(true, {
       data: record,
     });
   }
+  function handleCommit(record) {
+    checkCommit({ id: record.id });
+    setTimeout(() => {
+      reload();
+    }, 50);
+  }
+
+  const { createMessage } = useMessage();
+  const { error } = createMessage;
+  function handleCheckSum(record) {
+    if (checkedKeys.value.length == 0) {
+      error('请选择订单');
+      return;
+    }
+    if (selectedProductionDepartment.value.length > 1) {
+      error('勾选订单的生产科需一致');
+      return;
+    }
+    openCheckSum(true, {
+      data: checkedKeys.value,
+    });
+  }
+  function handleSuccess() {
+    setTimeout(() => {
+      reload();
+    }, 150);
+  }
 </script>
diff --git a/src/views/project/finance/pay/pay.data.tsx b/src/views/project/finance/pay/pay.data.tsx
index 1c50f6a..e768525 100644
--- a/src/views/project/finance/pay/pay.data.tsx
+++ b/src/views/project/finance/pay/pay.data.tsx
@@ -1,89 +1,137 @@
 import { FormSchema } from '/@/components/Form';
 import { BasicColumn } from '/@/components/Table';
 import { icon } from 'ant-design-vue';
-import { FolderAddOutlined } from '@ant-design/icons-vue';
+import { FolderAddOutlined, FilePptOutlined } from '@ant-design/icons-vue';
 import { size } from 'lodash-es';
 
 export const searchFormSchema: FormSchema[] = [
   {
-    field: 'phone',
+    field: 'checkNo',
     label: '生产科对账单号',
     component: 'Input',
     colProps: { span: 8 },
   },
   {
-    field: 'nickName',
-    label: '总经理审核',
+    field: 'productionDepartment',
+    label: '生产科',
     component: 'Input',
     colProps: { span: 8 },
   },
+  {
+    field: 'status',
+    label: '总经理审核',
+    component: 'Select',
+    colProps: { span: 8 },
+    componentProps: {
+      options: [
+        { label: '未提交审核', value: -1 },
+        { label: '待审核', value: 0 },
+        { label: '审核通过', value: 1 },
+        { label: '审核驳回', value: 2 },
+      ],
+    },
+  },
+  {
+    field: 'customerCode',
+    label: '客户编码',
+    component: 'Input',
+    colProps: {
+      span: 8,
+    },
+  },
 ];
 
 export const columns: BasicColumn[] = [
   {
     title: '生产科对账单号',
-    dataIndex: 'no',
+    dataIndex: 'checkNo',
     width: 120,
-    customRender: (column) => {
-      return '5667';
-    },
   },
   {
     title: '生产科应付款日期',
-    dataIndex: 'no',
+    dataIndex: 'payedDate',
     width: 140,
   },
   {
     title: '生产科扣款金额',
-    dataIndex: 'no',
+    dataIndex: 'deductAmount',
     width: 120,
   },
   {
     title: '扣款责任部门',
-    dataIndex: 'no',
+    dataIndex: 'deductDept',
     width: 120,
   },
   {
     title: '上传扣款单',
-    dataIndex: 'no',
+    dataIndex: 'deductUrl',
     width: 120,
+    customRender: (column) => {
+      const deductUrl = column.record.deductUrl;
+      if (deductUrl == undefined) {
+        return;
+      }
+      return <FilePptOutlined style="font-size:25px" onClick={() => window.open(deductUrl)} />;
+    },
   },
   {
     title: '生产科实际应付金额',
-    dataIndex: 'no',
+    dataIndex: 'actualPayedAmount',
     width: 120,
   },
   {
     title: '生产科发票上传',
-    dataIndex: 'no',
+    dataIndex: 'invoiceUrl',
     width: 80,
     customRender: (column) => {
-      return <FolderAddOutlined style="font-size:25px" />;
+      const deductUrl = column.record.invoiceUrl;
+      if (deductUrl == undefined) {
+        return;
+      }
+      return <FilePptOutlined style="font-size:25px" onClick={() => window.open(deductUrl)} />;
     },
   },
   {
     title: '实际付款金额1',
-    dataIndex: 'no',
+    dataIndex: 'actualPayedAmount1',
     width: 120,
   },
   {
     title: '实际付款金额2',
-    dataIndex: 'no',
+    dataIndex: 'actualPayedAmount2',
     width: 120,
   },
   {
     title: '实际付款金额3',
-    dataIndex: 'no',
+    dataIndex: 'actualPayedAmount3',
     width: 120,
   },
   {
     title: '生产科发票',
-    dataIndex: 'no',
+    dataIndex: 'invoiceUrl',
     width: 120,
+    customRender: (column) => {
+      const deductUrl = column.record.invoiceUrl;
+      if (deductUrl == undefined) {
+        return;
+      }
+      return <FilePptOutlined style="font-size:25px" onClick={() => window.open(deductUrl)} />;
+    },
   },
   {
     title: '总经理审核',
-    dataIndex: 'no',
+    dataIndex: 'status',
     width: 120,
+    customRender: (column) => {
+      if (column.record.status == -1) {
+        return '未提交审核';
+      } else if (column.record.status == 0) {
+        return '待审核';
+      } else if (column.record.status == 1) {
+        return '审核通过';
+      } else if (column.record.status == 2) {
+        return '审核驳回';
+      }
+    },
   },
 ];
diff --git a/src/views/project/finance/receive/FinanceEdit.vue b/src/views/project/finance/receive/FinanceEdit.vue
index b901b16..3202b41 100644
--- a/src/views/project/finance/receive/FinanceEdit.vue
+++ b/src/views/project/finance/receive/FinanceEdit.vue
@@ -30,10 +30,11 @@
   import { getEmailList } from '/@/api/sys/config';
   import { updateAmount } from '@/api/project/invoice';
 
+  const emit = defineEmits(['success']);
   const schemas: FormSchema[] = [
     {
       field: 'actualReceivableAmount',
-      component: 'Input',
+      component: 'InputNumber',
       labelWidth: 250,
       colProps: {
         span: 23,
@@ -42,7 +43,7 @@
     },
     {
       field: 'actualPayedAmount1',
-      component: 'Input',
+      component: 'InputNumber',
       labelWidth: 250,
       colProps: {
         span: 23,
@@ -51,7 +52,7 @@
     },
     {
       field: 'actualPayedAmount2',
-      component: 'Input',
+      component: 'InputNumber',
       labelWidth: 250,
       colProps: {
         span: 23,
@@ -60,7 +61,7 @@
     },
     {
       field: 'actualPayedAmount3',
-      component: 'Input',
+      component: 'InputNumber',
       labelWidth: 250,
       colProps: {
         span: 23,
@@ -69,7 +70,7 @@
     },
     {
       field: 'otherAmount',
-      component: 'Input',
+      component: 'InputNumber',
       labelWidth: 250,
       colProps: {
         span: 23,
@@ -108,5 +109,7 @@
     await updateAmount({
       ...updatedValues,
     });
+    emit('success');
+    closeDrawer();
   }
 </script>
diff --git a/src/views/project/finance/receive/InvoiceAnalysis.vue b/src/views/project/finance/receive/InvoiceAnalysis.vue
index 3a1387d..970a09e 100644
--- a/src/views/project/finance/receive/InvoiceAnalysis.vue
+++ b/src/views/project/finance/receive/InvoiceAnalysis.vue
@@ -3,51 +3,137 @@
     v-bind="$attrs"
     @register="register"
     title="收款单分析"
-    width="700px"
-    :bodyStyle="{ height: '400px' }"
+    width="80%"
+    :isDetail="true"
+    :showDetailBack="false"
     @ok="handleOk"
+    @visible-change="handleShow"
   >
-    <a-space direction="vertical">
-      <div style="margin: 16px 0"></div>
-      <div class="divAll">
-        <div
-          style="
-            margin-left: 22px;
-            margin-right: 5px;
-            width: 100px;
-            text-align: center;
-            line-height: 30px;
-          "
-          >生产科对账单号</div
-        ><a-input v-model:value="Input1" placeholder="请输入" style="width: 320px" />
-      </div>
-      <div class="divAll">
-        <div
-          style="
-            margin-left: 0px;
-            margin-right: 1px;
-            width: 180px;
-            text-align: center;
-            line-height: 30px;
-          "
-          >生产科应付款日期</div
-        ><a-input v-model:value="Input2" disabled />
-      </div> </a-space
-  ></BasicModal>
+    <div class="p-4">
+      <BasicTable @register="registerTable">
+        <template #bodyCell="{ column, record }">
+          <template v-if="column.key === 'action'"> </template>
+        </template>
+      </BasicTable>
+    </div>
+  </BasicModal>
 </template>
 <script lang="ts" setup>
   import { BasicModal, useModalInner } from '@/components/Modal';
   import { computed, ref } from 'vue';
-  import { getRefundDate } from '@/api/project/invoice';
+  import { invoiceAnalysis, exportAnalysis } from '@/api/project/invoice';
+  import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table';
+  // 处理弹窗的确定按钮点击事件
+  import axios from 'axios';
 
-  const Input1 = ref('');
-  const Input2 = ref();
+  const columnsAnalysis: BasicColumn[] = [
+    {
+      title: '客户编码',
+      dataIndex: 'actualPayedAmount',
+      width: 50,
+      customRender: (res) => {
+        // console.log(res, 56562);
+        return res.record.exportVOS[0].customerCode;
+      },
+    },
+    {
+      title: '实际应付金额总计',
+      dataIndex: 'actualPayedAmount',
+      width: 50,
+    },
+    {
+      title: '实际应收金额总计',
+      dataIndex: 'actualReceivableAmount',
+      width: 50,
+    },
+    {
+      title: '客户总价',
+      dataIndex: 'customerTotalPrice',
+      width: 50,
+    },
+    {
+      title: '发生扣款金额总计',
+      dataIndex: 'deductAmount',
+      width: 50,
+    },
+    {
+      title: '实际应收',
+      dataIndex: 'otherAmount',
+      width: 50,
+    },
+    {
+      title: '其他费用金额汇总',
+      dataIndex: 'otherTotalAmount',
+      width: 50,
+    },
+  ];
+  // const ids = ref<number[]>([]);
+  const ids = ref();
+  // const res = ref();
 
   const [register, { closeModal }] = useModalInner(async (data) => {
-    Input2.value = getRefundDate(data.data);
-    console.log(Input2.value, 5656);
+    ids.value = data.data;
+    setTimeout(() => {
+      reload();
+    }, 50);
   });
+  const [registerTable, { reload }] = useTable({
+    // api: () => invoiceAnalysis({ ids: ids.value }),
+    api: async () => {
+      const res = await invoiceAnalysis({ ids: ids.value });
+      const arrayRes = ref([]);
+      arrayRes.value.push(res);
+      console.log(res, 56561);
+      return arrayRes.value;
+    },
+    columns: columnsAnalysis,
+    bordered: true,
+  });
+  function handleShow(visible: boolean) {
+    reload();
+  }
+  const searchData = ref({});
   async function handleOk() {
+    // 构造符合 API 要求的参数
+    const idss = ids.value;
+    // await exportAnalysis({ ids: ids });
+    axios
+      .post(
+        '/basic-api/order/erp/invoice_bill/export',
+        { ids: idss },
+        {
+          responseType: 'blob', // 设置响应类型为 'blob'
+        },
+      )
+      .then((response) => {
+        // 创建一个 Blob 对象来保存二进制数据
+        const blob = new Blob([response.data], { type: 'application/zip' });
+        const getFormattedDate = (): string => {
+          const date = new Date();
+
+          const year = date.getFullYear();
+          const month = String(date.getMonth() + 1).padStart(2, '0');
+          const day = String(date.getDate()).padStart(2, '0');
+
+          const hours = String(date.getHours()).padStart(2, '0');
+          const minutes = String(date.getMinutes()).padStart(2, '0');
+          const seconds = String(date.getSeconds()).padStart(2, '0');
+
+          return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+        };
+        const date = getFormattedDate();
+        // 创建一个链接元素用于下载
+        const link = document.createElement('a');
+        link.href = window.URL.createObjectURL(blob);
+        link.download = `收款单分析${date}.xlsx`; // 你可以为文件命名
+        document.body.appendChild(link);
+        link.click(); // 自动点击链接,触发下载
+        console.log(link, 5656);
+        document.body.removeChild(link); // 下载完成后移除链接
+      })
+      .catch((error) => {
+        console.error(error);
+      });
     closeModal();
   }
 </script>
diff --git a/src/views/project/finance/receive/InvoiceDetail.vue b/src/views/project/finance/receive/InvoiceDetail.vue
index 33c71b6..aeed728 100644
--- a/src/views/project/finance/receive/InvoiceDetail.vue
+++ b/src/views/project/finance/receive/InvoiceDetail.vue
@@ -13,6 +13,9 @@
         <BasicTable @register="registerTable">
           <template #bodyCell="{ column, record }">
             <template v-if="column.key === 'action'"> </template>
+            <template v-if="column.key === 'picUrl'">
+              <img :z-index="100000" :width="50" :height="50" :src="record?.smallPicUrl" />
+            </template>
           </template>
         </BasicTable>
       </div>
@@ -31,22 +34,52 @@
     {
       title: '客户编码',
       dataIndex: 'customerCode',
-      width: 50,
+      width: 100,
     },
     {
       title: '项目号',
       dataIndex: 'projectNo',
-      width: 60,
+      width: 100,
     },
     {
       title: '内部编码',
       dataIndex: 'innerNo',
-      width: 60,
+      width: 100,
     },
     {
       title: '客户po号',
       dataIndex: 'customerPo',
-      width: 60,
+      width: 100,
+    },
+    {
+      title: '客户STYLE',
+      width: 150,
+      dataIndex: 'customerStyle',
+    },
+    {
+      title: 'Model(REFERENCE)',
+      width: 150,
+      dataIndex: 'modeleLo',
+    },
+    {
+      title: '订单图片',
+      width: 150,
+      dataIndex: 'picUrl',
+    },
+    {
+      title: '数量',
+      width: 150,
+      dataIndex: 'orderCount',
+    },
+    {
+      title: '客户单价$',
+      width: 150,
+      dataIndex: 'orderCount',
+    },
+    {
+      title: '客户总价$',
+      width: 150,
+      dataIndex: 'orderCount',
     },
   ];
   const invoiceNo = ref();
@@ -59,7 +92,10 @@
     invoiceNo: invoiceNo.value,
   });
   const [registerTable] = useTable({
-    api: () => getBaseInvoice({ invoiceNo: invoiceNo.value }),
+    api: () => {
+      const res = getBaseInvoice({ invoiceNo: invoiceNo.value });
+      return res;
+    },
     columns: columns,
     bordered: true,
   });
diff --git a/src/views/project/finance/receive/TrackEdit.vue b/src/views/project/finance/receive/TrackEdit.vue
index e77bac6..ebc3630 100644
--- a/src/views/project/finance/receive/TrackEdit.vue
+++ b/src/views/project/finance/receive/TrackEdit.vue
@@ -26,10 +26,7 @@
             :action="updateDeductUrl"
             @change="handleChange"
           >
-            <a-button>
-              <!-- <upload-outlined></upload-outlined> -->
-              上传扣款单
-            </a-button>
+            <a-button> 上传扣款单 </a-button>
           </a-upload>
         </a-space>
       </div>
@@ -48,16 +45,17 @@
   import type { UploadProps } from 'ant-design-vue';
   import { updateDeduct } from '@/api/project/invoice';
 
+  const emit = defineEmits(['success']);
   const fileList = ref<UploadProps['fileList']>([]);
 
-  const input1 = ref('');
+  const input1 = ref();
   const deductUrl = ref();
   const id = ref();
   const invoiceNo = ref();
+  const uploadUrl = ref('http://47.104.8.35:18000/api/localStorage/upload_file_oss?name=');
   const updateDeductUrl = ref('http://47.104.8.35:18000/api/localStorage/upload_file_oss?name=');
 
   const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
-    console.log(data, 56561);
     id.value = data.data.id;
     invoiceNo.value = data.data.invoiceNo;
     input1.value = data.data.deductAmount;
@@ -66,21 +64,31 @@
 
   function handleChange(info) {
     if (info.file.status == 'done') {
-      updateDeductUrl.value = info.file.response.data.deductUrl;
+      updateDeductUrl.value = info.file.response.data.fileUrl;
       deductUrl.value = updateDeductUrl.value;
     }
   }
   function beforeUpload(info) {
-    updateDeductUrl.value += info.name;
+    updateDeductUrl.value = uploadUrl.value + info.name;
   }
 
   //完成编辑
   async function handleSubmit() {
+    const requestData = {
+      id: id.value,
+      invoiceNo: invoiceNo.value,
+      deductAmount: input1.value,
+      deductUrl: deductUrl.value,
+    };
     await updateDeduct({
       id: id.value,
       invoiceNo: invoiceNo.value,
       deductAmount: input1.value,
       deductUrl: deductUrl.value,
     });
+    // await updateDeduct(requestData);
+    fileList.value = [];
+    emit('success');
+    closeDrawer();
   }
 </script>
diff --git a/src/views/project/finance/receive/index.vue b/src/views/project/finance/receive/index.vue
index 23ce78a..88d4904 100644
--- a/src/views/project/finance/receive/index.vue
+++ b/src/views/project/finance/receive/index.vue
@@ -3,9 +3,9 @@
     <BasicTable @register="registerTable">
       <template #toolbar>
         <a-button type="primary" @click="handleInvoiceAnalysis">收款单分析</a-button>
-        <FinanceEdit @register="registerFinanceEdit" />
+        <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" />
         <InvoiceAnalysis @register="registerInvoiceAnalysis" />
-        <TrackEdit @register="registerTrackEdit" />
+        <TrackEdit @register="registerTrackEdit" @success="handleSuccess" />
         <InvoiceDetail @register="registerInvoiceDetail" />
       </template>
       <template #bodyCell="{ column, record }">
@@ -42,7 +42,7 @@
   </div>
 </template>
 <script lang="ts" setup>
-  import { defineComponent } from 'vue';
+  import { computed, defineComponent, ref } from 'vue';
   import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table';
   import { searchFormSchema, columns } from './receive.data';
   import FinanceEdit from './FinanceEdit.vue';
@@ -50,25 +50,37 @@
   import InvoiceAnalysis from './InvoiceAnalysis.vue';
   import InvoiceDetail from './InvoiceDetail.vue';
   import { useDrawer } from '/@/components/Drawer';
-  import { getInvoice, deleteInvoice, commit } from '@/api/project/invoice';
+  import { getInvoice, deleteInvoice, commit, getBaseInvoice } from '@/api/project/invoice';
   import { useModal } from '/@/components/Modal';
   import { FilePptOutlined } from '@ant-design/icons-vue';
   import { icon } from 'ant-design-vue';
+  import { ROLE } from './type.d';
+  import { useUserStoreWithOut } from '/@/store/modules/user';
+  import { useMessage } from '/@/hooks/web/useMessage';
 
   const [registerInvoiceAnalysis, { openModal: openInvoiceAnalysis }] = useModal();
 
   const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer();
   const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer();
   const [registerInvoiceDetail, { openDrawer: openInvoiceDetail }] = useDrawer();
-
-  const [registerTable] = useTable({
+  const checkedKeys = ref<Array<string | number>>([]);
+  const userStore = useUserStoreWithOut();
+  const user = userStore.getUserInfo;
+  const role = computed(() => {
+    return user?.roleSmallVO?.code;
+  });
+  const [registerTable, { reload }] = useTable({
     title: '',
     api: getInvoice,
     columns: columns,
     bordered: true,
+    clickToRowSelect: false,
     rowKey: 'id',
     rowSelection: {
       type: 'checkbox',
+      selectedRowKeys: checkedKeys,
+      onSelect,
+      onSelectAll,
     },
     formConfig: {
       labelWidth: 120,
@@ -88,6 +100,98 @@
       // slots: { customRender: 'action' },
     },
   });
+
+  type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count]
+
+  const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref
+
+  // 选择函数
+  async function onSelect(record: any, selected: boolean) {
+    if (selected) {
+      const res = await getBaseInvoice({ invoiceNo: record.invoiceNo });
+      const customerCode = res[0].customerCode;
+
+      const index = selectedCustomCodes.value.findIndex(([code]) => code === customerCode);
+
+      if (index !== -1) {
+        // 如果存在,增加计数
+        selectedCustomCodes.value[index][1] += 1;
+      } else {
+        // 如果不存在,添加新项 [customerCode, 1]
+        selectedCustomCodes.value.push([customerCode, 1]);
+      }
+
+      checkedKeys.value = [...checkedKeys.value, record.id];
+    } else {
+      const res = await getBaseInvoice({ invoiceNo: record.invoiceNo });
+      const customerCode = res[0].customerCode;
+
+      const index = selectedCustomCodes.value.findIndex(([code]) => code === customerCode);
+
+      if (index !== -1) {
+        if (selectedCustomCodes.value[index][1] > 1) {
+          // 如果计数大于 1,减少计数
+          selectedCustomCodes.value[index][1] -= 1;
+        } else {
+          // 如果计数为 1,移除该项
+          selectedCustomCodes.value.splice(index, 1);
+        }
+      }
+
+      checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id);
+    }
+    console.log(selectedCustomCodes.value, 56561);
+    console.log(checkedKeys.value, 56562);
+  }
+
+  async function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) {
+    const changeIds = changeRows.map((item) => item.id);
+    const changeCustomerCodes = await Promise.all(
+      changeRows.map(async (item) => {
+        const res = await getBaseInvoice({ invoiceNo: item.invoiceNo });
+        return res[0].customerCode;
+      }),
+    );
+
+    if (selected) {
+      // 添加到 checkedKeys
+      checkedKeys.value = [...checkedKeys.value, ...changeIds];
+
+      // 处理每个 customerCode
+      changeCustomerCodes.forEach((code) => {
+        const index = selectedCustomCodes.value.findIndex(
+          ([customerCode]) => customerCode === code,
+        );
+        if (index !== -1) {
+          // 如果存在,增加计数
+          selectedCustomCodes.value[index][1] += 1;
+        } else {
+          // 如果不存在,添加新项 [customerCode, 1]
+          selectedCustomCodes.value.push([code, 1]);
+        }
+      });
+    } else {
+      // 从 checkedKeys 中移除
+      checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id));
+
+      // 处理每个 customerCode
+      changeCustomerCodes.forEach((code) => {
+        const index = selectedCustomCodes.value.findIndex(
+          ([customerCode]) => customerCode === code,
+        );
+        if (index !== -1) {
+          if (selectedCustomCodes.value[index][1] > 1) {
+            // 如果计数大于 1,减少计数
+            selectedCustomCodes.value[index][1] -= 1;
+          } else {
+            // 如果计数为 1,移除该项
+            selectedCustomCodes.value.splice(index, 1);
+          }
+        }
+      });
+    }
+  }
+
   function handleFinanceEdit(record) {
     openFinanceEdit(true, {
       data: record,
@@ -101,18 +205,40 @@
   function handleDelete(record) {
     const id: string[] = Array.isArray(record.id) ? record.id : [record.id];
     deleteInvoice({ ids: id });
+    setTimeout(() => {
+      reload();
+    }, 50);
   }
   function handleCommit(record) {
     commit({ id: record.id });
+    setTimeout(() => {
+      reload();
+    }, 50);
   }
   function handleInvoiceDetail(record) {
     openInvoiceDetail(true, {
       data: record,
     });
   }
+  const { createMessage } = useMessage();
+  const { error } = createMessage;
   function handleInvoiceAnalysis(record) {
+    if (checkedKeys.value.length == 0) {
+      error('请选择订单');
+      return;
+    }
+    if (selectedCustomCodes.value.length > 1) {
+      error('勾选订单的客户编码需一致');
+      return;
+    }
     openInvoiceAnalysis(true, {
-      data: record,
+      data: checkedKeys.value,
     });
   }
+
+  function handleSuccess() {
+    setTimeout(() => {
+      reload();
+    }, 50);
+  }
 </script>
diff --git a/src/views/project/finance/receive/receive.data.tsx b/src/views/project/finance/receive/receive.data.tsx
index 06b71ce..4948b58 100644
--- a/src/views/project/finance/receive/receive.data.tsx
+++ b/src/views/project/finance/receive/receive.data.tsx
@@ -7,16 +7,33 @@ import { ref } from 'vue';
 
 export const searchFormSchema: FormSchema[] = [
   {
-    field: 'invoice',
+    field: 'invoiceNo',
     label: 'Invoice编号',
-    component: 'Select',
-    colProps: { span: 8 },
+    component: 'Input',
+    colProps: { span: 6 },
   },
   {
-    field: 'nickName',
+    field: 'status',
     label: '总经理审核',
+    component: 'Select',
+    colProps: { span: 6 },
+    componentProps: {
+      options: [
+        { label: '未提交审核', value: -1 },
+        { label: '待审核', value: 0 },
+        { label: '审核通过', value: 1 },
+        { label: '审核驳回', value: 2 },
+      ],
+    },
+  },
+  {
+    field: 'customerCode',
+    label: '客户编码',
     component: 'Input',
-    colProps: { span: 8 },
+    colProps: {
+      span: 6,
+    },
+    // labelWidth: 140,
   },
 ];
 
@@ -51,6 +68,9 @@ export const columns: BasicColumn[] = [
     width: 80,
     customRender: (column) => {
       const deductUrl = column.record.deductUrl;
+      if (deductUrl == undefined) {
+        return;
+      }
       return <FilePptOutlined style="font-size:25px" onClick={() => window.open(deductUrl)} />;
     },
   },
@@ -96,3 +116,45 @@ export const columns: BasicColumn[] = [
     },
   },
 ];
+
+export const columnsAnalysis: BasicColumn[] = [
+  {
+    title: '实际应付金额总计',
+    dataIndex: 'actualPayedAmount',
+    width: 50,
+    // customRender: (column) => {
+    //   console.log(column, 5656666);
+    //   return 1;
+    // },
+  },
+  {
+    title: '实际应收金额总计',
+    dataIndex: 'actualReceivableAmount',
+    width: 50,
+  },
+  {
+    title: '客户总价',
+    dataIndex: 'customerTotalPrice',
+    width: 50,
+  },
+  {
+    title: '发生扣款金额总计',
+    dataIndex: 'deductAmount',
+    width: 50,
+  },
+  {
+    title: '实际应收金额总计',
+    dataIndex: 'actualReceivableAmount',
+    width: 50,
+  },
+  {
+    title: '实际应收',
+    dataIndex: 'otherAmount',
+    width: 50,
+  },
+  {
+    title: '其他费用金额汇总',
+    dataIndex: 'otherTotalAmount',
+    width: 50,
+  },
+];
diff --git a/src/views/project/finance/receive/type.d.ts b/src/views/project/finance/receive/type.d.ts
new file mode 100644
index 0000000..83a35d3
--- /dev/null
+++ b/src/views/project/finance/receive/type.d.ts
@@ -0,0 +1,9 @@
+export enum ROLE {
+  ADMIN = 'admin', // 超管
+  CUSTOM_ADMIN = 'custom_admin', // 客户管理员
+  DATA_REPORT_USER = 'data_report_user', //数据分析员
+  BUSINESS = 'business_user', // 业务员
+  TRACKER = 'tracker_user', // 跟单员
+  INSPECT = 'inspect_user', // 质检员
+  PRODUCE = 'produce_user', //生产科
+}
diff --git a/src/views/project/order/ExportModal.vue b/src/views/project/order/ExportModal.vue
index 4a6d44d..828a3d1 100644
--- a/src/views/project/order/ExportModal.vue
+++ b/src/views/project/order/ExportModal.vue
@@ -162,7 +162,6 @@
         //导出选中的订单
         fieldVO.orderIds = props.ids;
         exportLoading.value = true;
-        console.log(fieldVO, 5656);
         await orderExport({ ...searchData.value, fieldVO });
         exportLoading.value = false;
 
diff --git a/src/views/project/order/FormDetail/index.vue b/src/views/project/order/FormDetail/index.vue
index 023a91e..a0d6d6d 100644
--- a/src/views/project/order/FormDetail/index.vue
+++ b/src/views/project/order/FormDetail/index.vue
@@ -324,10 +324,10 @@
               trackFormPanelRef?.value?.setFieldsValue({
                 ...toRaw(data.trackStageInfo),
               });
-              ppUpdate.value = data.trackStageInfo.ppConfirmResult;
-              shipUpdate.value = data.trackStageInfo.shippmentSampleConfirmTime;
-              altexUpdate.value = data.trackStageInfo.aitexTestFinishTime;
-              sgsUpdate.value = data.trackStageInfo.sgsTestFinishTime;
+              ppUpdate.value = data?.trackStageInfo?.ppConfirmResult;
+              shipUpdate.value = data?.trackStageInfo?.shippmentSampleConfirmTime;
+              altexUpdate.value = data?.trackStageInfo?.aitexTestFinishTime;
+              sgsUpdate.value = data?.trackStageInfo?.sgsTestFinishTime;
             }
 
             if (inspectionFormPanelRef.value) {
@@ -408,19 +408,30 @@
                 forms.inspectionStageInfo = inspectionFormPanelRef?.value?.getFieldsValue() || {};
               }
               //跟单信息标记
-              if (forms.trackStageInfo.ppConfirmResult !== ppUpdate.value) {
+              if (
+                forms.trackStageInfo?.ppConfirmResult !== undefined &&
+                forms.trackStageInfo?.ppConfirmResult !== ppUpdate.value
+              ) {
                 forms.trackStageInfo.ppConfirmTime = getFormattedDate();
               }
-              if (forms.trackStageInfo.shippmentSampleConfirmResult !== shipUpdate.value) {
+              if (
+                forms.trackStageInfo?.shippmentSampleConfirmResult !== undefined &&
+                forms.trackStageInfo?.shippmentSampleConfirmResult !== shipUpdate.value
+              ) {
                 forms.trackStageInfo.shippmentSampleConfirmTime = getFormattedDate();
               }
-              if (forms.trackStageInfo.aitexTestFinishResult !== altexUpdate.value) {
+              if (
+                forms.trackStageInfo?.aitexTestFinishResult !== altexUpdate.value &&
+                forms.trackStageInfo?.aitexTestFinishResult !== undefined
+              ) {
                 forms.trackStageInfo.aitexTestFinishTime = getFormattedDate();
               }
-              if (forms.trackStageInfo.sgsTestFinishResult !== sgsUpdate.value) {
+              if (
+                forms.trackStageInfo?.sgsTestFinishResult !== sgsUpdate.value &&
+                forms.trackStageInfo?.sgsTestFinishResult !== undefined
+              ) {
                 forms.trackStageInfo.sgsTestFinishTime = getFormattedDate();
               }
-              // console.log(forms.trackStageInfo, 5656);
               await orderUpdate(forms);
               closeDrawer();
               emit('success', {});
@@ -440,6 +451,9 @@
             };
             await orderCreate(forms);
             closeDrawer();
+            setTimeout(() => {
+              reload();
+            }, 50);
             emit('success', {});
           }
         } catch (error) {
diff --git a/src/views/project/order/InvoiceCreate.vue b/src/views/project/order/InvoiceCreate.vue
index 91b15b0..4fe9d99 100644
--- a/src/views/project/order/InvoiceCreate.vue
+++ b/src/views/project/order/InvoiceCreate.vue
@@ -32,7 +32,7 @@
   import { BasicModal, useModalInner } from '@/components/Modal';
   import { computed, ref } from 'vue';
   import type { UploadProps } from 'ant-design-vue';
-  import { getRefundDate, getInvoice } from '@/api/project/invoice';
+  import { getRefundDate, getInvoice, createInvoice } from '@/api/project/invoice';
 
   const fileList = ref<UploadProps['fileList']>([]);
 
@@ -43,13 +43,14 @@
   const orderIds = ref();
 
   const [register, { closeModal }] = useModalInner(async (data) => {
-    const res = getRefundDate(data.data);
-    Input2.value = res.data;
+    const ids = data.data;
+    const res = await getRefundDate({ orderIds: ids });
+    Input2.value = res;
     orderIds.value = data.data;
   });
   // const title = ref('');
   async function handleOk() {
-    await getInvoice({
+    await createInvoice({
       invoiceNo: Input1.value,
       bgUrl: bgUrl.value,
       backRefundDate: Input2.value,
@@ -59,7 +60,7 @@
   }
   function handleChange(info) {
     if (info.file.status == 'done') {
-      bgUrl.value = info.file.response.data;
+      bgUrl.value = info.file.response.data.fileUrl;
     }
   }
   function beforeUpload(info) {
diff --git a/src/views/project/order/PassCalculate.vue b/src/views/project/order/PassCalculate.vue
index b8d14f9..629054a 100644
--- a/src/views/project/order/PassCalculate.vue
+++ b/src/views/project/order/PassCalculate.vue
@@ -7,37 +7,32 @@
     :bodyStyle="{ height: '100px' }"
     @ok="handleOk"
   >
-    <div style="margin-left: 10px; font-size: 16px">一次通过率:{{ result }}</div>
+    <div style="margin-left: 10px; font-size: 16px">一次通过率:{{ num }}</div>
   </BasicModal>
 </template>
 <script lang="ts" setup>
   import { BasicModal, useModalInner } from '@/components/Modal';
   import { computed, ref } from 'vue';
+  import { passCalculate } from '@/api/project/order';
 
   const [register, { closeModal }] = useModalInner(async (data) => {
-    console.log(data, 56562);
     title.value = data.title;
+    const id = data.check[0];
+    const opinionType = ref();
+    if (data.title == '确认意见') {
+      opinionType.value = 'pp样品确认意见';
+    } else if (data.title == '生产样品') {
+      opinionType.value = 'shipment sample确认意见';
+    } else if (data.title == '测试样品') {
+      opinionType.value = 'Altex测试结果';
+    }
+    num.value = await passCalculate({ orderId: id, opinionType: opinionType.value });
   });
   const title = ref('');
-  const result = computed(() => {
-    const res = 1234;
-    return res;
-  });
-  // onMounted(async () => {
-  //       // 获取包装费用和客户编码的关联关系
-  //       const res = await getConfigList({
-  //         page: 1,
-  //         pageSize: 1000,
-  //         // relationCode: 'packetPrice',
-  //       });
-
-  //       configList.value = res?.items || [];
-
-  //       // 获取业务员
-  //       const res1 = await getUserList({ page: 1, pageSize: 1000 });
-  //       businessUsers.value = res1.items
+  const num = ref();
 
   async function handleOk() {
     closeModal();
+    num.value = '';
   }
 </script>
diff --git a/src/views/project/order/ProductInvoice.vue b/src/views/project/order/ProductInvoice.vue
index bcb8d93..51990f6 100644
--- a/src/views/project/order/ProductInvoice.vue
+++ b/src/views/project/order/ProductInvoice.vue
@@ -38,16 +38,22 @@
 <script lang="ts" setup>
   import { BasicModal, useModalInner } from '@/components/Modal';
   import { computed, ref } from 'vue';
-  import { getRefundDate } from '@/api/project/invoice';
+  import { payDate, checkCreate } from '@/api/project/invoice';
 
   const Input1 = ref('');
   const Input2 = ref();
-
+  const res = ref();
   const [register, { closeModal }] = useModalInner(async (data) => {
-    Input2.value = getRefundDate(data.data);
-    console.log(Input2.value, 5656);
+    res.value = data.data;
+    Input2.value = await payDate({ orderIds: res.value });
+    console.log(Input2.value, 565656);
   });
   async function handleOk() {
+    await checkCreate({
+      orderIds: res.value,
+      payedDate: Input2.value,
+      checkNo: Input1.value,
+    });
     closeModal();
   }
 </script>
diff --git a/src/views/project/order/ProductText.vue b/src/views/project/order/ProductText.vue
index c29253f..47da7bd 100644
--- a/src/views/project/order/ProductText.vue
+++ b/src/views/project/order/ProductText.vue
@@ -50,7 +50,7 @@
   </BasicModal>
 </template>
 <script lang="ts">
-  import { defineComponent, ref, computed } from 'vue';
+  import { defineComponent, ref, computed, onMounted, onUpdated } from 'vue';
   import { BasicModal, useModalInner } from '/@/components/Modal';
   import { RadioGroup } from 'ant-design-vue';
   import { EyeOutlined, FilePptOutlined } from '@ant-design/icons-vue';
@@ -74,7 +74,12 @@
       const isShow1 = ref(true); //选择公司页面
       const isShow2 = ref(false); //生成PDF页面
       const pdf = ref(['/pdf.png']);
-      const [register, { setModalProps, closeModal }] = useModalInner(async (data) => {});
+      const [register, { setModalProps, closeModal }] = useModalInner(async (data) => {
+        // if (data.customers.length == 0) {
+        //   error('请选择订单');
+        //   closeModal();
+        // }
+      });
       const options = computed(() => {
         // 运营总监-基本信息,跟单,质检
         return [
@@ -114,27 +119,29 @@
           isShow2.value = false;
         }
       }
-      //判断选择公司与客户编码是否对应
-      function validateCustomerCodes(customerCodes: string[], chooseCompany: string): boolean {
-        for (const code of customerCodes) {
-          const expectedCompanyValue = customerCodeToCompanyMap[code];
-          if (expectedCompanyValue === undefined) {
-            // 如果代码不在映射中,不需要对应公司
+      function validateCompany(selectedCodes: any, company: string): boolean {
+        for (const [customerCode] of selectedCodes) {
+          const mappedCompany = customerCodeToCompanyMap[customerCode];
+
+          if (mappedCompany === undefined) {
+            // 如果 customerCode 不在 customerCodeToCompanyMap 中,跳过
+            console.warn(`Customer code ${customerCode} not found in the mapping, skipping.`);
             continue;
           }
-          if (customerCodeToCompanyMap[code] !== chooseCompany) {
-            // 如果属于 customerCodes 的值与其公司不匹配,返回 false
+
+          if (mappedCompany !== company) {
+            // 如果有一个不匹配,返回 false
             return false;
           }
         }
-        return true; // 如果所有 customerCodes 内的代码正确匹配,返回 true
+        // 如果所有匹配,返回 true
+        return true;
       }
       //生成pdf
       // const customerCodeList: string[] = props.customerCodes;
       function handleProduct() {
-        const customerCodeList: string[] = props.customerCodes;
-        const areValid = validateCustomerCodes(customerCodeList, choose.value);
-        console.log(customerCodeList, 5656, props.customerCodes);
+        const customerCodeList = props.customerCodes;
+        const areValid = validateCompany(customerCodeList, choose.value);
         //如果选错了,弹出提示
         if (!areValid) {
           error('勾选订单与选择的公司不匹配');
diff --git a/src/views/project/order/TrackHistory.vue b/src/views/project/order/TrackHistory.vue
index 82788c1..a9921f7 100644
--- a/src/views/project/order/TrackHistory.vue
+++ b/src/views/project/order/TrackHistory.vue
@@ -21,10 +21,10 @@
               </template>
               <template #description>
                 <div class="description">
-                  {{ item.modifyTime }}
+                  {{ item.showOpinionType }}
                 </div>
                 <div class="info">
-                  <!-- <div><span>操作时间:</span>{{ formatToDateTime(item.createTime) }}</div> -->
+                  <div>操作时间:{{ item.modifyTime }}</div>
                 </div>
               </template>
             </a-list-item-meta>
@@ -54,20 +54,43 @@
   const orderId = ref('');
   // const activeKey = ref(1);
 
+  function removeTFromTimestamp(timestamp: string): string {
+    // 使用 replace 方法将 "T" 替换为空字符串
+    return timestamp.replace('T', ' ');
+  }
+
   const getOrderOptLogFunc = async (data, page) => {
     console.log('%c [ data ]-135', 'font-size:13px; background:pink; color:#bf2c9f;', data);
     const res = await trackHistory({ orderId: data, page: page, pageSize: 20 });
     list1.value = res;
-    // total1.value = res.total;
-    // page1.value = page;
+    for (const item of list1.value) {
+      item.modifyTime = removeTFromTimestamp(item.modifyTime);
+      item.showOpinionType = modifyConfirmResult(item.field, item.modifyTime);
+    }
   };
   const [register] = useDrawerInner((data) => {
-    console.log(data, 5656);
     orderId.value = data.id;
     // const res = await trackHistory({ orderId: data, page: page, pageSize: 20 });
     getOrderOptLogFunc(orderId.value, 1);
   });
+  function modifyConfirmResult(Result: string, Time: string): string {
+    // 获取 Time 的日期部分,去掉时间
+    let datePart = Time.split(' ')[0]; // 获取日期部分
+    datePart += ' ';
+    // 找到第一个"."的位置
+    const dotIndex = Result.indexOf('.');
 
+    // 如果找到了".",则进行拼接
+    if (dotIndex !== -1) {
+      // 生成新的结果
+      const modifiedResult = `${Result.slice(0, dotIndex + 1)}${datePart}${Result.slice(
+        dotIndex + 1,
+      )}`;
+      return modifiedResult;
+    }
+    // 如果没有找到".",直接返回原始字符串
+    return Result;
+  }
   const pagination1 = computed(() => {
     return {
       show: true,
diff --git a/src/views/project/order/index.vue b/src/views/project/order/index.vue
index c9f71ad..ca2b535 100644
--- a/src/views/project/order/index.vue
+++ b/src/views/project/order/index.vue
@@ -31,32 +31,36 @@
       <template #bodyCell="{ column, record }">
         <template v-if="column.key === 'action'">
           <TableAction
-            :actions="[
-              {
-                // 数据分析没有编辑权限
-                ...(role !== ROLE.DATA_REPORT_USER && {
-                  label: '编辑',
-                  // icon: 'ic:outline-delete-outline',
-                  onClick: handleEdit.bind(null, record),
-                }),
-              },
-              {
-                ...(role !== ROLE.DATA_REPORT_USER && {
-                  label: '申请权限',
-                  // icon: 'ic:outline-delete-outline',
-                  onClick: handleCheck.bind(null, record),
-                }),
-              },
-              // {
-              //   ...(role !== ROLE.DATA_REPORT_USER && {
-              //     label: '申请',
-              //     // icon: 'ic:outline-delete-outline',
-              //     onClick: handleCheck.bind(null, record),
-              //   }),
-              // },
-            ]"
+            :actions="
+              role !== ROLE.PRODUCE
+                ? [
+                    {
+                      // 数据分析没有编辑权限
+                      ...(role !== ROLE.DATA_REPORT_USER && {
+                        label: '编辑',
+                        // icon: 'ic:outline-delete-outline',
+                        onClick: handleEdit.bind(null, record),
+                      }),
+                    },
+                    {
+                      ...(role !== ROLE.DATA_REPORT_USER && {
+                        label: '申请权限',
+                        // icon: 'ic:outline-delete-outline',
+                        onClick: handleCheck.bind(null, record),
+                      }),
+                    },
+                    // {
+                    //   ...(role !== ROLE.DATA_REPORT_USER && {
+                    //     label: '申请',
+                    //     // icon: 'ic:outline-delete-outline',
+                    //     onClick: handleCheck.bind(null, record),
+                    //   }),
+                    // },
+                  ]
+                : []
+            "
             :dropDownActions="
-              role !== ROLE.DATA_REPORT_USER
+              role !== ROLE.DATA_REPORT_USER && role !== ROLE.PRODUCE
                 ? [
                     {
                       label: '历史记录',
@@ -120,9 +124,10 @@
           @change="handleChange"
           class="passCalculate"
           dropdown-class-name="dropdown-class"
+          v-if="role === ROLE.ADMIN || role === ROLE.TRACKER || role === ROLE.BUSINESS"
         >
-          <a-select-option value1="confirm">一次通过率</a-select-option>
-          <a-select-option value="确认样品" @click="handlePassModal('确认样品')"
+          <a-select-option value1="一次通过率">一次通过率</a-select-option>
+          <a-select-option value="确认样品" @click="handlePassModal('确认意见')"
             >确认样品</a-select-option
           >
           <a-select-option value="生产样品" @click="handlePassModal('生产样品')"
@@ -142,7 +147,12 @@
           >比重计算</a-button
         >
         <!-- 质检角色不能导出任何信息 -->
-        <a-button type="primary" @click="handleExportModal">导出</a-button>
+        <a-button
+          type="primary"
+          @click="handleExportModal"
+          v-if="role === ROLE.ADMIN || role === ROLE.TRACKER || role === ROLE.BUSINESS"
+          >导出</a-button
+        >
         <a-button
           type="primary"
           @click="handleProfitModal"
@@ -208,6 +218,8 @@
   import { useUserStoreWithOut } from '/@/store/modules/user';
   import { ROLE } from './type.d';
   import { getUserList } from '/@/api/project/account';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { getBaseInvoice } from '/@/api/project/invoice';
 
   const orderStore = useOrderStoreWithOut();
   const userStore = useUserStoreWithOut();
@@ -234,7 +246,7 @@
     },
     setup() {
       const checkedKeys = ref<Array<string | number>>([]);
-      const selectedCustomCodes = ref<Array<string>>([]);
+      // const selectedCustomCodes = ref<Array<string>>([]);
       const [profitModalRegister, { openModal: openProfitModal }] = useModal();
       const [invoiceCreateModalRegister, { openModal: openInvoiceCreateModal }] = useModal();
       const [productInvoiceModalRegister, { openModal: openProductInvoiceModal }] = useModal();
@@ -279,6 +291,7 @@
         pagination: {
           total: 60,
         },
+        clickToRowSelect: false,
         columns: getOrderColumns(user?.roleSmallVO?.code),
         useSearchForm: true,
         formConfig: formConfig,
@@ -292,47 +305,165 @@
           onSelect,
           onSelectAll,
         },
-        actionColumn: {
-          width: 160,
-          title: 'Action',
-          dataIndex: 'action',
-          // slots: { customRender: 'action' },
-        },
+        // actionColumn: {
+        //   width: 160,
+        //   title: 'Action',
+        //   dataIndex: 'action',
+        //   // slots: { customRender: 'action' },
+        // },
+        actionColumn:
+          role.value !== ROLE.PRODUCE
+            ? {
+                width: 160,
+                title: 'Action',
+                dataIndex: 'action',
+                // slots: { customRender: 'action' },
+              }
+            : undefined,
       });
       function getFormValues() {
         console.log(getForm().getFieldsValue());
       }
-      function onSelect(record, selected) {
+
+      type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count]
+      type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count]
+
+      const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref
+      const selectedProductionDepartment = ref<ProductionDepartmentEntry[]>([]); // 创建一个二维数组的 ref
+
+      // 单选处理函数
+      function onSelect(
+        record: { customerCode: string; productionDepartment: string; id: string },
+        selected: boolean,
+      ) {
+        // 查找 customerCode 在 selectedCustomCodes 中的位置
+        const customerCodeIndex = selectedCustomCodes.value.findIndex(
+          ([customerCode]) => customerCode === record.customerCode,
+        );
+
+        // 查找 productionDepartment 在 selectedProductionDepartment 中的位置
+        const productionDepartmentIndex = selectedProductionDepartment.value.findIndex(
+          ([department]) => department === record.productionDepartment,
+        );
+
         if (selected) {
-          if (!selectedCustomCodes.value.includes(record.customerCode)) {
-            // 如果不包含,则添加到 selectedCustomCodes
-            selectedCustomCodes.value = [...selectedCustomCodes.value, record.customerCode];
-          }
+          // 添加到 checkedKeys
           checkedKeys.value = [...checkedKeys.value, record.id];
+
+          // 更新 selectedCustomCodes
+          if (customerCodeIndex !== -1) {
+            // 如果已存在,增加计数
+            selectedCustomCodes.value[customerCodeIndex][1] += 1;
+          } else {
+            // 如果不存在,添加新项 [customerCode, 1]
+            selectedCustomCodes.value.push([record.customerCode, 1]);
+          }
+
+          // 更新 selectedProductionDepartment
+          if (productionDepartmentIndex !== -1) {
+            // 如果已存在,增加计数
+            selectedProductionDepartment.value[productionDepartmentIndex][1] += 1;
+          } else {
+            // 如果不存在,添加新项 [productionDepartment, 1]
+            selectedProductionDepartment.value.push([record.productionDepartment, 1]);
+          }
         } else {
+          // 从 checkedKeys 中移除
           checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id);
-          selectedCustomCodes.value = selectedCustomCodes.value.filter(
-            (customerCode) => customerCode !== record.customerCode,
-          );
+
+          // 更新 selectedCustomCodes
+          if (customerCodeIndex !== -1) {
+            if (selectedCustomCodes.value[customerCodeIndex][1] > 1) {
+              selectedCustomCodes.value[customerCodeIndex][1] -= 1;
+            } else {
+              selectedCustomCodes.value.splice(customerCodeIndex, 1);
+            }
+          }
+
+          // 更新 selectedProductionDepartment
+          if (productionDepartmentIndex !== -1) {
+            if (selectedProductionDepartment.value[productionDepartmentIndex][1] > 1) {
+              selectedProductionDepartment.value[productionDepartmentIndex][1] -= 1;
+            } else {
+              selectedProductionDepartment.value.splice(productionDepartmentIndex, 1);
+            }
+          }
         }
+
+        console.log('5656Checked Keys:', checkedKeys.value);
+        console.log('5656Selected Customer Codes:', selectedCustomCodes.value);
+        console.log('5656Selected Production Departments:', selectedProductionDepartment.value);
       }
-      function onSelectAll(selected, selectedRows, changeRows) {
+
+      // 全选处理函数
+      function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) {
         const changeIds = changeRows.map((item) => item.id);
         const changeCustomerCodes = changeRows.map((item) => item.customerCode);
+        const changeProductionDepartments = changeRows.map((item) => item.productionDepartment);
+
         if (selected) {
+          // 添加到 checkedKeys
           checkedKeys.value = [...checkedKeys.value, ...changeIds];
-          // 创建一个集合来去除重复的代码
-          const allCodes = new Set([...selectedCustomCodes.value, ...changeCustomerCodes]);
-          // 将集合转换回数组
-          selectedCustomCodes.value = Array.from(allCodes);
+
+          // 更新 selectedCustomCodes
+          changeCustomerCodes.forEach((code) => {
+            const index = selectedCustomCodes.value.findIndex(
+              ([customerCode]) => customerCode === code,
+            );
+            if (index !== -1) {
+              selectedCustomCodes.value[index][1] += 1;
+            } else {
+              selectedCustomCodes.value.push([code, 1]);
+            }
+          });
+
+          // 更新 selectedProductionDepartment
+          changeProductionDepartments.forEach((department) => {
+            const index = selectedProductionDepartment.value.findIndex(
+              ([prodDepartment]) => prodDepartment === department,
+            );
+            if (index !== -1) {
+              selectedProductionDepartment.value[index][1] += 1;
+            } else {
+              selectedProductionDepartment.value.push([department, 1]);
+            }
+          });
         } else {
-          checkedKeys.value = checkedKeys.value.filter((id) => {
-            return !changeIds.includes(id);
+          // 从 checkedKeys 中移除
+          checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id));
+
+          // 更新 selectedCustomCodes
+          changeCustomerCodes.forEach((code) => {
+            const index = selectedCustomCodes.value.findIndex(
+              ([customerCode]) => customerCode === code,
+            );
+            if (index !== -1) {
+              if (selectedCustomCodes.value[index][1] > 1) {
+                selectedCustomCodes.value[index][1] -= 1;
+              } else {
+                selectedCustomCodes.value.splice(index, 1);
+              }
+            }
           });
-          selectedCustomCodes.value = selectedCustomCodes.value.filter((customerCode) => {
-            return !changeCustomerCodes.includes(customerCode);
+
+          // 更新 selectedProductionDepartment
+          changeProductionDepartments.forEach((department) => {
+            const index = selectedProductionDepartment.value.findIndex(
+              ([prodDepartment]) => prodDepartment === department,
+            );
+            if (index !== -1) {
+              if (selectedProductionDepartment.value[index][1] > 1) {
+                selectedProductionDepartment.value[index][1] -= 1;
+              } else {
+                selectedProductionDepartment.value.splice(index, 1);
+              }
+            }
           });
         }
+
+        console.log('5656Checked Keys:', checkedKeys.value);
+        console.log('5656Selected Customer Codes:', selectedCustomCodes.value);
+        console.log('5656Selected Production Departments:', selectedProductionDepartment.value);
       }
 
       function handleEdit(record, e) {
@@ -377,10 +508,20 @@
         });
       }
 
-      function handleInvoiceCreateModal() {
+      function handleInvoiceCreateModal(record) {
         const form = getForm();
         const values = form.getFieldsValue();
+        if (checkedKeys.value.length == 0) {
+          error('请选择订单');
+          return;
+        }
+        if (selectedCustomCodes.value.length > 1) {
+          error('勾选订单的客户编码需一致');
+          return;
+        }
         openInvoiceCreateModal(true, {
+          record: record,
+          customersCodes: selectedCustomCodes.value,
           data: checkedKeys.value,
           searchData: values,
         });
@@ -389,6 +530,14 @@
       function handleProductInvoiceModal() {
         const form = getForm();
         const values = form.getFieldsValue();
+        if (checkedKeys.value.length == 0) {
+          error('请选择订单');
+          return;
+        }
+        if (selectedProductionDepartment.value.length > 1) {
+          error('勾选订单的生产科需一致');
+          return;
+        }
         openProductInvoiceModal(true, {
           data: checkedKeys.value,
           searchData: values,
@@ -401,35 +550,46 @@
       function handlePassModal(title) {
         const form = getForm();
         const values = form.getFieldsValue();
-        if (title == '确认样品') {
-          openPassModal(true, {
-            check: checkedKeys.value,
-            data: values,
-            title: title,
-          });
-          return false;
-        } else if (title == '生产样品') {
-          openPassModal(true, {
-            check: checkedKeys.value,
-            data: values,
-            title: title,
-          });
-          return false;
-        } else if (title == '测试样品') {
-          openPassModal(true, {
-            check: checkedKeys.value,
-            data: values,
-            title: title,
-          });
-          return false;
-        }
+        openPassModal(true, {
+          check: checkedKeys.value,
+          title: title,
+          searchData: values,
+        });
       }
-
+      // const form = getForm();
+      // const values = form.getFieldsValue();
+      //   if (title == '确认样品') {
+      //     openPassModal(true, {
+      //       check: checkedKeys.value,
+      //       title: title,
+      //     });
+      //     return false;
+      //   } else if (title == '生产样品') {
+      //     openPassModal(true, {
+      //       check: checkedKeys.value,
+      //       title: title,
+      //     });
+      //     return false;
+      //   } else if (title == '测试样品') {
+      //     openPassModal(true, {
+      //       check: checkedKeys.value,
+      //       title: title,
+      //     });
+      //     return false;
+      //   }
+      // }
+      const { createMessage } = useMessage();
+      const { error } = createMessage;
       function handleProductModal() {
         const form = getForm();
         const values = form.getFieldsValue();
-
+        console.log(selectedCustomCodes.value, 5656);
+        if (selectedCustomCodes.value.length == 0) {
+          error('请选择订单');
+          return;
+        }
         openProductModal(true, {
+          customers: selectedCustomCodes.value,
           data: values,
         });
       }
diff --git a/src/views/project/order/tableData.tsx b/src/views/project/order/tableData.tsx
index ea8a07a..61a7c8a 100644
--- a/src/views/project/order/tableData.tsx
+++ b/src/views/project/order/tableData.tsx
@@ -12,6 +12,8 @@ import { formatToDate } from '/@/utils/dateUtil';
 
 const innerNoOptions = ref([]);
 const projectNoOptions = ref([]);
+const orderStore = useOrderStoreWithOut();
+// const { productionDepartment: productionDepartmentOptions } = useOrderInfo(orderStore);
 
 // 可选择的列
 export const SELECT_FIELD_COLUMNS = [
@@ -353,6 +355,24 @@ export const ORDER_LIST_PROFIT_FIELDS = [
   },
 ];
 
+function modifyConfirmResult(ppConfirmResult: string, ppConfirmTime: string): string {
+  // 获取 ppConfirmTime 的日期部分,去掉时间
+  let datePart = ppConfirmTime.split(' ')[0]; // 获取日期部分
+  datePart += ' ';
+  // 找到第一个"."的位置
+  const dotIndex = ppConfirmResult.indexOf('.');
+
+  // 如果找到了".",则进行拼接
+  if (dotIndex !== -1) {
+    // 生成新的结果
+    const modifiedResult = `${ppConfirmResult.slice(0, dotIndex + 1)}${datePart}${ppConfirmResult.slice(dotIndex + 1)}`;
+    return modifiedResult;
+  }
+
+  // 如果没有找到".",直接返回原始字符串
+  return ppConfirmResult;
+}
+
 export const ORDER_LIST_TRACK_FIELDS = [
   {
     title: '跟单信息',
@@ -370,13 +390,17 @@ export const ORDER_LIST_TRACK_FIELDS = [
       },
       {
         title: 'pp样品确认意见',
-        width: 150,
+        width: 180,
         dataIndex: 'ppConfirmResult',
         customRender: (column) => {
           const { record } = column || {};
-          if (record?.trackStageInfo?.ppConfirmResult !== undefined) {
+          if (
+            record?.trackStageInfo?.ppConfirmResult !== undefined &&
+            record?.trackStageInfo?.ppConfirmTime !== undefined
+          ) {
             const ppUpdate = record?.trackStageInfo?.ppConfirmResult;
-            const ppUpdate2 = ppUpdate + '123';
+            const ppUpdateTime = record?.trackStageInfo?.ppConfirmTime;
+            const ppUpdate2 = modifyConfirmResult(ppUpdate, ppUpdateTime);
             return ppUpdate2;
           } else {
             return record?.trackStageInfo?.ppConfirmResult;
@@ -407,7 +431,17 @@ export const ORDER_LIST_TRACK_FIELDS = [
         dataIndex: 'shippmentSampleConfirmResult',
         customRender: (column) => {
           const { record } = column || {};
-          return record?.trackStageInfo?.shippmentSampleConfirmResult;
+          if (
+            record?.trackStageInfo?.shippmentSampleConfirmResult !== undefined &&
+            record?.trackStageInfo?.shippmentSampleConfirmTime !== undefined
+          ) {
+            const shipUpdate = record?.trackStageInfo?.shippmentSampleConfirmResult;
+            const shipUpdateTime = record?.trackStageInfo?.shippmentSampleConfirmTime;
+            const shipUpdate2 = modifyConfirmResult(shipUpdate, shipUpdateTime);
+            return shipUpdate2;
+          } else {
+            return record?.trackStageInfo?.shippmentSampleConfirmResult;
+          }
         },
       },
       {
@@ -434,7 +468,17 @@ export const ORDER_LIST_TRACK_FIELDS = [
         dataIndex: 'aitexTestFinishResult',
         customRender: (column) => {
           const { record } = column || {};
-          return record?.trackStageInfo?.aitexTestFinishResult;
+          if (
+            record?.trackStageInfo?.aitexTestFinishResult !== undefined &&
+            record?.trackStageInfo?.aitexTestFinishTime !== undefined
+          ) {
+            const aitexUpdate = record?.trackStageInfo?.aitexTestFinishResult;
+            const aitexUpdateTime = record?.trackStageInfo?.aitexTestFinishTime;
+            const aitexUpdate2 = modifyConfirmResult(aitexUpdate, aitexUpdateTime);
+            return aitexUpdate2;
+          } else {
+            return record?.trackStageInfo?.aitexTestFinishResult;
+          }
         },
       },
       {
@@ -452,7 +496,17 @@ export const ORDER_LIST_TRACK_FIELDS = [
         dataIndex: 'sgsTestFinishResult',
         customRender: (column) => {
           const { record } = column || {};
-          return record?.trackStageInfo?.sgsTestFinishResult;
+          if (
+            record?.trackStageInfo?.sgsTestFinishResult !== undefined &&
+            record?.trackStageInfo?.sgsTestFinishTime !== undefined
+          ) {
+            const sgsUpdate = record?.trackStageInfo?.sgsTestFinishResult;
+            const sgsUpdateTime = record?.trackStageInfo?.sgsTestFinishTime;
+            const sgsUpdate2 = modifyConfirmResult(sgsUpdate, sgsUpdateTime);
+            return sgsUpdate2;
+          } else {
+            return record?.trackStageInfo?.sgsTestFinishResult;
+          }
         },
       },
       {
@@ -725,6 +779,9 @@ export const FIELDS_BASE_INFO = [
   {
     field: 'productionDepartment',
     component: 'Select',
+    // componentProps: {
+    //   options: productionDepartmentOptions,
+    // },
     labelWidth: 150,
     label: '生产科',
     rules: [{ required: true }],
@@ -1122,29 +1179,29 @@ export const FIELDS_TRACK_STAGE_INFO = [
   },
   {
     field: 'latestArrivalTime',
-    component: 'Select',
-    componentProps: {
-      options: [
-        {
-          label: 'ok',
-          value: 'ok',
-        },
-      ],
-    },
+    component: 'DatePicker',
+    // componentProps: {
+    //   options: [
+    //     {
+    //       label: 'ok',
+    //       value: 'ok',
+    //     },
+    //   ],
+    // },
     label: '最晚包材到货时间',
     labelWidth: 250,
   },
   {
     field: 'latestBkTime',
-    component: 'Select',
-    componentProps: {
-      options: [
-        {
-          label: 'ok',
-          value: 'ok',
-        },
-      ],
-    },
+    component: 'DatePicker',
+    // componentProps: {
+    //   options: [
+    //     {
+    //       label: 'ok',
+    //       value: 'ok',
+    //     },
+    //   ],
+    // },
     label: '最晚订舱+报关资料时间',
     labelWidth: 250,
   },
diff --git a/vite.config.ts b/vite.config.ts
index d6a6ad3..950069d 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -21,6 +21,7 @@ export default defineApplicationConfig({
       proxy: {
         '/basic-api/order': {
           target: 'http://47.104.8.35:18000',
+          // target: 'http://39.108.227.113:8000',
           // target: 'http://localhost:8000',
           // target: 'http://39.108.227.113:3000/mock/35',
           // http://39.108.227.113:8000/order/erp/captcha/get_img_captcha_code
@@ -30,6 +31,8 @@ export default defineApplicationConfig({
         },
         '/api/localStorage/upload': {
           target: 'http://47.104.8.35:18000',
+          // target: 'http://39.108.227.113:8000',
+          // target: '192.168.31.250:18000',
           // target: 'http://localhost:8000',
           changeOrigin: true,
           ws: true,
--
libgit2 0.23.3