From 386bf8b4d3ac6c6637f40861ed42aab056a11905 Mon Sep 17 00:00:00 2001
From: z <2199297992@qq.com>
Date: Tue, 21 Jan 2025 11:40:29 +0800
Subject: [PATCH] feat(product): 优化采购管理功能

---
 src/pages/product/procure/index.tsx                         | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
 src/pages/product/productCollect/components/AddOrUpdate.tsx | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------
 2 files changed, 313 insertions(+), 74 deletions(-)

diff --git a/src/pages/product/procure/index.tsx b/src/pages/product/procure/index.tsx
index baa87e5..5d873d9 100644
--- a/src/pages/product/procure/index.tsx
+++ b/src/pages/product/procure/index.tsx
@@ -1,15 +1,27 @@
 import ButtonConfirm from '@/components/ButtomConfirm';
 import { RESPONSE_CODE } from '@/constants/enum';
 import AddOrUpdate from '@/pages/product/procure/components/AddOrUpdate';
-import { postProcureBillDelete, postProcureBillPage } from '@/services';
+import {
+  postProcureBillDelete,
+  postProcureBillPage,
+  postServiceConstProcureBillAuditStatus,
+} from '@/services';
+import { enumToSelect } from '@/utils';
 import { ProTable, type ActionType } from '@ant-design/pro-components';
 import { message } from 'antd';
 import { useRef } from 'react';
+import Audit from './components/Audit';
 
 export default () => {
   const actionRef = useRef<ActionType>();
   const columns = [
     {
+      title: '单号',
+      dataIndex: 'id',
+      ellipsis: true,
+      hideInSearch: true,
+    },
+    {
       title: '创建时间',
       dataIndex: 'createTime',
       ellipsis: true,
@@ -52,32 +64,84 @@ export default () => {
       hideInSearch: true,
     },
     {
+      title: '采购单号',
+      dataIndex: 'id',
+      ellipsis: true,
+      hideInTable: true,
+    },
+    {
+      title: '创建人',
+      dataIndex: 'createByNameLike',
+      ellipsis: true,
+      hideInTable: true,
+    },
+    {
+      title: '创建时间',
+      valueType: 'dateTimeRange',
+      hideInTable: true,
+      search: {
+        transform: (value) => {
+          if (value) {
+            return {
+              createTimeGe: value[0],
+              createTimeLe: value[1],
+            };
+          }
+        },
+      },
+    },
+    {
+      title: '审核状态',
+      valueType: 'select',
+      key: 'auditStatus',
+      dataIndex: 'auditStatus',
+      filters: true,
+      onFilter: true,
+      hideInTable: true,
+      request: async () => {
+        const res = await postServiceConstProcureBillAuditStatus();
+        return enumToSelect(res.data);
+      },
+    },
+    {
       title: '操作',
       valueType: 'option',
       key: 'option',
       render: (text, record) => [
-        <AddOrUpdate
-          key="update"
-          record={record}
-          onfinish={() => {
-            actionRef.current?.reload();
-          }}
-        />,
-        <ButtonConfirm
-          key="delete"
-          className="p-0"
-          title={'确认删除该记录?'}
-          text="删除"
-          onConfirm={async () => {
-            let res = await postProcureBillDelete({
-              query: { id: record.id },
-            });
-            if (res) {
-              message.success(res.message);
+        record.paths?.includes('UPDATE') && (
+          <AddOrUpdate
+            key="update"
+            record={record}
+            onfinish={() => {
               actionRef.current?.reload();
-            }
-          }}
-        />,
+            }}
+          />
+        ),
+        record.paths?.includes('UPDATE') && (
+          <ButtonConfirm
+            key="delete"
+            className="p-0"
+            title={'确认删除该记录?'}
+            text="删除"
+            onConfirm={async () => {
+              let res = await postProcureBillDelete({
+                query: { id: record.id },
+              });
+              if (res) {
+                message.success(res.message);
+                actionRef.current?.reload();
+              }
+            }}
+          />
+        ),
+        record.paths?.includes('AUDIT') && (
+          <Audit
+            recordId={record.id}
+            onClose={() => {
+              actionRef.current?.reload();
+            }}
+          ></Audit>
+        ),
       ],
     },
   ];
@@ -128,7 +192,41 @@ export default () => {
               },
               { title: '数量', dataIndex: 'number', key: 'number' },
               { title: '小计', dataIndex: 'totalPrice', key: 'totalPrice' },
-              { title: '附件', dataIndex: 'annex', key: 'annex' },
+              {
+                title: '附件',
+                dataIndex: 'annex',
+                key: 'annex',
+                render: (_, record) => (
+                  <div>
+                    {record.annexList?.map((url, index) => {
+                      const shortName =
+                        url.split('/').pop()?.slice(0, 15) ||
+                        `附件 ${index + 1}`;
+                      return (
+                        <a
+                          key={index}
+                          href={url}
+                          target="_blank"
+                          rel="noopener noreferrer"
+                          title={url} // 悬停显示完整链接
+                          style={{
+                            display: 'block',
+                            marginBottom: '4px',
+                            whiteSpace: 'nowrap',
+                            overflow: 'hidden',
+                            textOverflow: 'ellipsis',
+                            maxWidth: '200px', // 限制显示宽度
+                          }}
+                        >
+                          {shortName.length < url.split('/').pop()?.length
+                            ? `${shortName}...`
+                            : shortName}
+                        </a>
+                      );
+                    })}
+                  </div>
+                ),
+              },
               { title: '备注', dataIndex: 'notes', key: 'notes' },
             ]}
             headerTitle={false}
@@ -139,7 +237,6 @@ export default () => {
           />
         ),
       }}
-      search={false}
       dateFormatter="string"
       headerTitle="采购管理"
       options={false}
diff --git a/src/pages/product/productCollect/components/AddOrUpdate.tsx b/src/pages/product/productCollect/components/AddOrUpdate.tsx
index 0b47ff4..89ce566 100644
--- a/src/pages/product/productCollect/components/AddOrUpdate.tsx
+++ b/src/pages/product/productCollect/components/AddOrUpdate.tsx
@@ -1,19 +1,128 @@
 import { postProductCollectBillAddOrModify } from '@/services';
 import { useModel } from '@@/exports';
 import {
+  ActionType,
+  EditableProTable,
   ModalForm,
-  ProFormDigit,
-  ProFormSelect,
-  ProFormText,
+  ProCard,
+  ProColumns,
+  ProForm,
+  ProFormDependency,
+  ProFormField,
+  ProFormSwitch,
   ProFormTextArea,
 } from '@ant-design/pro-components';
 import { Button, Form, message } from 'antd';
+import React, { useEffect, useRef, useState } from 'react';
+
+export default ({ record, onfinish }) => {
+  const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
+  const [controlled, setControlled] = useState<boolean>(false);
+  const [processedRecord, setProcessedRecord] = useState(record);
+  const formRef = useRef(null);
+  const editorFormRef = useRef(null);
+  const { getProducts } = useModel('enum');
+  const actionRef = useRef<ActionType>();
+  useEffect(() => {
+    if (record?.details) {
+      const updateddetails = record.details.map((item) => ({
+        ...item,
+        key: item.key || `key-${Math.random().toString(36).substr(2, 9)}`, // 动态生成唯一 key
+      }));
+      setProcessedRecord({
+        ...record,
+        details: updateddetails,
+      });
+    }
+  }, [record]);
+
+  const columns: ProColumns[] = [
+    {
+      title: '商品',
+      dataIndex: 'productId',
+      valueType: 'select',
+      request: async () => {
+        const res = await getProducts();
+        return res.map((item) => ({
+          ...item,
+          label: item.name,
+          value: item.id,
+          productUnitName: item.baseUnitName,
+          productUnitPrice: item.unitPrice,
+        }));
+      },
+      fieldProps: (_, { rowIndex }) => ({
+        onSelect: (value, option) => {
+          const currentTableData = editorFormRef.current?.getRowsData?.();
+          if (currentTableData) {
+            const updatedData = [...currentTableData];
+            updatedData[rowIndex] = {
+              ...updatedData[rowIndex],
+              productUnitName: option.productUnitName,
+              productUnitPrice: option.productUnitPrice,
+            };
+            formRef.current?.setFieldsValue({
+              details: updatedData,
+            });
+          }
+        },
+      }),
+    },
+    {
+      title: '单位',
+      dataIndex: 'productUnitName',
+      valueType: 'text',
+      editable: false,
+    },
+    {
+      title: '单价',
+      dataIndex: 'productUnitPrice',
+      valueType: 'digit',
+      editable: false,
+    },
+    {
+      title: '数量',
+      dataIndex: 'number',
+      valueType: 'digit',
+    },
+    {
+      title: '备注',
+      dataIndex: 'notes',
+      valueType: 'textarea',
+    },
+    {
+      title: '操作',
+      valueType: 'option',
+      render: (text, record, _, action) => [
+        <a
+          key="editable"
+          onClick={() => {
+            action?.startEditable?.(record.key);
+          }}
+        >
+          编辑
+        </a>,
+        <a
+          key="delete"
+          onClick={() => {
+            const tableDataSource = formRef.current?.getFieldValue('details');
+            formRef.current?.setFieldsValue({
+              table: tableDataSource.filter((item) => item.key !== record.key),
+            });
+          }}
+        >
+          删除
+        </a>,
+      ],
+    },
+  ];
 
-export default ({ record, onFinish }) => {
   const [form] = Form.useForm();
-  const { getWarehouse } = useModel('enum');
   return (
     <ModalForm
+      formRef={formRef}
+      initialValues={processedRecord}
+      validateTrigger="onBlur"
       title="新建表单"
       trigger={
         record?.id ? (
@@ -24,66 +133,99 @@ export default ({ record, onFinish }) => {
       }
       form={form}
       autoFocusFirstInput
+      width={1500}
       modalProps={{
         destroyOnClose: true,
         onCancel: () => console.log('run'),
       }}
       submitTimeout={2000}
       onFinish={async (values) => {
-        let res = await postProductCollectBillAddOrModify({
-          data: values,
+        const res = await postProductCollectBillAddOrModify({
+          data: {
+            ...record,
+            ...values,
+          },
         });
         if (res) {
           message.success(res.message);
-          onFinish();
+          onfinish();
         }
         return true;
       }}
     >
-      <ProFormDigit
-        label="id"
-        name="id"
-        initialValue={record?.id}
-        width="sm"
-        hidden={true}
-      />
-      <ProFormText
-        width="md"
-        initialValue={record?.productName}
-        name="productName"
-        label="申领物品"
-        rules={[{ required: true, message: '申领物品必填' }]}
-      />
-      <ProFormDigit
-        label="申领数量"
-        name="productNumber"
-        initialValue={record?.productNumber}
-        width="sm"
-        min={1}
-        rules={[{ required: true, message: '申领数量必填' }]}
-      />
-      <ProFormSelect
-        width="md"
-        request={async () => {
-          const res = await getWarehouse();
-          console.log('options:' + res);
-          let options = Object.entries(res).map(([value, label]) => ({
-            label,
-            value,
-          }));
-          console.log('options:' + options);
-          return options;
+      <EditableProTable
+        rowKey="key"
+        scroll={{
+          x: 960,
+        }}
+        editableFormRef={editorFormRef}
+        headerTitle="可编辑表格"
+        maxLength={5}
+        name="details"
+        controlled={controlled}
+        recordCreatorProps={{
+          position: 'bottom',
+          record: () => ({
+            key: `key-${Math.random().toString(36).substr(2, 9)}`,
+          }),
+        }}
+        actionRef={actionRef}
+        toolBarRender={() => [
+          <ProFormSwitch
+            key="render"
+            fieldProps={{
+              style: {
+                marginBlockEnd: 0,
+              },
+              checked: controlled,
+              onChange: (value) => {
+                setControlled(value);
+              },
+            }}
+            checkedChildren="数据更新通知 Form"
+            unCheckedChildren="保存后通知 Form"
+            noStyle
+          />,
+          <Button
+            key="rows"
+            onClick={() => {
+              const rows = editorFormRef.current?.getRowsData?.();
+              console.log(rows);
+            }}
+          >
+            获取 table 的数据
+          </Button>,
+        ]}
+        columns={columns}
+        editable={{
+          type: 'multiple',
+          editableKeys,
+          onChange: setEditableRowKeys,
+          actionRender: (row, config, defaultDom) => {
+            return [defaultDom.save, defaultDom.delete, defaultDom.cancel];
+          },
         }}
-        // initialValue={record?.warehouseCode}
-        name="warehouseCode"
-        label="申领仓库"
-        rules={[{ required: true, message: '申领仓库为必填项' }]}
-      />
-      <ProFormTextArea
-        initialValue={record?.applyRemarks}
-        name="applyRemarks"
-        label="申领备注"
       />
+      <ProForm.Item>
+        <ProCard title="表格数据" headerBordered collapsible defaultCollapsed>
+          <ProFormDependency name={['details']}>
+            {({ details }) => (
+              <ProFormField
+                ignoreFormItem
+                fieldProps={{
+                  style: {
+                    width: '100%',
+                  },
+                }}
+                mode="read"
+                valueType="jsonCode"
+                text={JSON.stringify(details)}
+              />
+            )}
+          </ProFormDependency>
+        </ProCard>
+      </ProForm.Item>
+      <ProFormTextArea name="auditRemarks" label="备注" />
     </ModalForm>
   );
 };
--
libgit2 0.23.3