AddOrUpdate.tsx 10.5 KB
import {
  postOrderErpTicketsUpload,
  postProcureBillAddOrModify,
} from '@/services';
import { useModel } from '@@/exports';
import { UploadOutlined } from '@ant-design/icons';
import {
  ActionType,
  EditableProTable,
  ModalForm,
  ProCard,
  ProColumns,
  ProForm,
  ProFormDependency,
  ProFormField,
  ProFormSwitch,
  ProFormTextArea,
} from '@ant-design/pro-components';
import { Button, Form, Upload, 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 为 procureBillDetailList 中的每个元素添加 key
  useEffect(() => {
    if (record?.procureBillDetailList) {
      const updatedProcureBillDetailList = record.procureBillDetailList.map(
        (item) => ({
          ...item,
          key: item.key || `key-${Math.random().toString(36).substr(2, 9)}`, // 动态生成唯一 key
        }),
      );
      setProcessedRecord({
        ...record,
        procureBillDetailList: updatedProcureBillDetailList,
      });
    }
  }, [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) => {
          console.log('option111111' + JSON.stringify(option));
          const currentTableData = editorFormRef.current?.getRowsData?.();
          if (currentTableData) {
            const updatedData = [...currentTableData];
            updatedData[rowIndex] = {
              ...updatedData[rowIndex],
              productUnitName: option.productUnitName,
              productUnitPrice: option.productUnitPrice,
            };
            formRef.current?.setFieldsValue({
              procureBillDetailList: 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: '附件',
      dataIndex: 'annexUpload',
      renderFormItem: (_, { record }) => (
        <Upload
          fileList={
            record.annexList?.map((url) => ({
              uid: url,
              name: url.split('/').pop(),
              status: 'done',
              url,
            })) || []
          }
          onPreview={(file) => {
            window.open(file.url || file.thumbUrl); // 打开文件预览
          }}
          customRequest={async (options) => {
            const { file, onSuccess, onError } = options;

            const formData = new FormData();
            formData.append('file', file);

            try {
              const res = await postOrderErpTicketsUpload({
                data: formData,
                headers: { 'Content-Type': 'multipart/form-data' },
              });

              if (res.message === '成功') {
                message.success(`${file.name} 上传成功`);

                // 更新文件列表
                const currentData = formRef.current?.getFieldValue(
                  'procureBillDetailList',
                );
                const currentRow = currentData.find(
                  (row) => row.key === record.key,
                );
                const existingAnnex = currentRow?.annexList || []; // 取现有的 annex 数据

                const updatedAnnex = [...existingAnnex, res.data]; // 合并新的文件 URL

                // 更新表单数据
                const updatedData = currentData.map((row) =>
                  row.key === record.key
                    ? { ...row, annexList: updatedAnnex }
                    : row,
                );
                formRef.current?.setFieldValue(
                  'procureBillDetailList',
                  updatedData,
                );

                onSuccess?.('上传成功');
              } else {
                message.error(`${file.name} 上传失败`);
                onError?.(new Error('上传失败'));
              }
            } catch (error) {
              message.error(`${file.name} 上传错误`);
              onError?.(error);
            }
          }}
          onRemove={(file) => {
            const currentData =
              formRef.current?.getFieldValue('procureBillDetailList') || [];
            const updatedData = currentData.map((row) => {
              if (row.key === record.key) {
                return {
                  ...row,
                  annexList: row.annexList.filter((url) => url !== file.url), // 移除对应文件 URL
                };
              }
              return row;
            });

            formRef.current?.setFieldsValue({
              procureBillDetailList: updatedData,
            });

            // 触发状态更新
            setProcessedRecord((prevRecord) => ({
              ...prevRecord,
              procureBillDetailList: updatedData,
            }));
          }}
        >
          <Button icon={<UploadOutlined />}>上传附件</Button>
        </Upload>
      ),
      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: '附件',
      hideInTable: true,
      dataIndex: 'annexList',
    },
    {
      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(
              'procureBillDetailList',
            );
            formRef.current?.setFieldsValue({
              table: tableDataSource.filter((item) => item.key !== record.key),
            });
          }}
        >
          删除
        </a>,
      ],
    },
  ];

  const [form] = Form.useForm();
  return (
    <ModalForm
      formRef={formRef}
      initialValues={processedRecord}
      validateTrigger="onBlur"
      title="新建表单"
      trigger={
        record?.id ? (
          <Button type="link">修改</Button>
        ) : (
          <Button type="primary">新建</Button>
        )
      }
      form={form}
      autoFocusFirstInput
      width={1500}
      modalProps={{
        destroyOnClose: true,
        onCancel: () => console.log('run'),
      }}
      submitTimeout={2000}
      onFinish={async (values) => {
        const res = await postProcureBillAddOrModify({
          data: {
            ...record,
            ...values,
          },
        });
        if (res) {
          message.success(res.message);
          onfinish();
        }
        return true;
      }}
    >
      <EditableProTable
        rowKey="key"
        scroll={{
          x: 960,
        }}
        editableFormRef={editorFormRef}
        headerTitle="可编辑表格"
        maxLength={5}
        name="procureBillDetailList"
        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];
          },
        }}
      />
      <ProForm.Item>
        <ProCard title="表格数据" headerBordered collapsible defaultCollapsed>
          <ProFormDependency name={['procureBillDetailList']}>
            {({ procureBillDetailList }) => (
              <ProFormField
                ignoreFormItem
                fieldProps={{
                  style: {
                    width: '100%',
                  },
                }}
                mode="read"
                valueType="jsonCode"
                text={JSON.stringify(procureBillDetailList)}
              />
            )}
          </ProFormDependency>
        </ProCard>
      </ProForm.Item>
      <ProFormTextArea name="notes" label="备注" />
    </ModalForm>
  );
};