为了实现这个功能我们和后端定义了数据结构
data:{id:‘’,formInfo:'',formInfo2:'',formInfo3:'',formInfo4:'', ......deailData:[ // 明细数据 // saleData 查询带出的对应明细序列号数据{ id:'', ocopyId:'', copyId:'', odoId:'', ......, saleData:[ { id:'', ocopyId:'', odoId:'', ......,} ] },{ id:'', ocopyId:'', copyId:'', odoId:'', ......, saleData:[ { id:'', ocopyId:'', odoId:'', ......,} ] },{ id:'', ocopyId:'', copyId:'', odoId:'', ......, saleData:[ { id:'', ocopyId:'', odoId:'', ......,} ] }]
}
代码入下
/*** 编辑页面*/ import React from 'react';import { TForm, ELImport_3, ElNotification, ElRowContainer, TCollapse } from '@/cloudt/component';import { TEditTable } from '@/cloudt/pro-component';import {getDetailColumns,getSerialButtons,getDetailButtons,getTopButtons,getBasicForm,getControlForm,getReceivingForm,getSerialEdittabColumns,} from './config';import dayjs from 'dayjs';import { asserts } from '@/utils';import { save, getDetailById, getFileCode } from './service';import { FileUpload } from '@/cloudt/component/ItemComponent';import { maths } from '@/utils';import { Spin } from 'antd';import { closeCurrentToPath, frameHistoryPush } from '@/cloudt/frame-history';interface Props {match: any;}interface State {loading: boolean;pageType: string;id: string | number;bascicFormData: any;OrderInfoData: Array<any>;recvCountryCode: any;fileList: Array<any>;preSelectedRow: Record<string, any> | null; //记录上次选中的明细行importRequestParams: Record<string, any>;}class SaleOrderEdit extends React.Component<Props, State> {basicFormRef: any; //基础信息表单refcontrolFormRef: any; //制单信息receiveFormRef: any; //客户收货信息表单refdeatilTableRef: any; //明细信息可编辑表格refserialTableRef: any; // 序列号refimportModalRef: any; //导入组件refconstructor(props) {super(props);this.state = {fileList: [],id: this.props.match?.params?.id, //单据idpageType: this.props.match.path.includes('/edit/') ? 'edit' : 'view', // 编辑或详情页面loading: false, // 页面级loadingbascicFormData: {}, //基本信息OrderInfoData: [], //明细数据recvCountryCode: '', // 国家preSelectedRow: null,importRequestParams: {},};}async componentDidMount() {await this.getDetail(this.state.id);}getDetail = async (id) => {this.setState({loading: true,});const res = await getDetailById(id);if (res && res.success) {const bascicFormData = await this.handleBasicFormData(res?.data);const newSalSoDSaveVOList = this.handleDetailEditData(res?.data?.odoDList);// 查询附件const fileCode = res.data?.fileCode;if (fileCode) {await this.handleFilesData(res.data?.fileCode.split(','));}this.setState({bascicFormData,OrderInfoData: newSalSoDSaveVOList,});} else {ElNotification({type: 'error',message: res.msg || '查询失败',});}this.setState({loading: false,});};handleBasicFormData = async (data) => {const basicData = {...data,recvArea: [data?.recvProvince, data?.recvCity, data?.recvCounty],whId: {whId: data?.whId,whCode: data?.whCode,whName: data?.whName,// deter2: data?.deter2,// deter2Name: data?.deter2Name,},};this.setState({recvCountryCode: data?.recvCountry,});return basicData;};handleFilesData = async (fileCode) => {const res = await getFileCode(fileCode);if (res && res.success) {this.setState({fileList: res.data,});}};/*** 查详情明细行数据处理 -- 明细行原始数据*/handleDetailEditData = (odoDSaveVOList) => {const newSalSoDSaveVOList =odoDSaveVOList &&Array.isArray(odoDSaveVOList) &&odoDSaveVOList.map((item) => {return {...item,// createTime: asserts.isExist(item?.createTime) ? dayjs(item?.createTime).format('YYYY-MM-DD') : null,// modifyTime: asserts.isExist(item?.modifyTime) ? dayjs(item?.modifyTime).format('YYYY-MM-DD') : null,serialRespVOs: item.serialRespVOs ? item.serialRespVOs : [],lotNo: item?.lotNo,};});return newSalSoDSaveVOList;};// 明细信息行选择事件 更新下边的序号编辑handleOrderInfoSelect = async (selectedRowKeys, selectedRows) => {await this.deatilTableRef.quitEditState(); // 明细行退出编辑状态await this.serialTableRef.quitEditState(); // 序列号退出编辑状态const TableValues = await this.serialTableRef.getRows(); // 获取序列号数据const detailSelectedRow = selectedRows[0];if (this.state.preSelectedRow) {this.deatilTableRef.updateRows({ serialRespVOs: TableValues }, [this.state.preSelectedRow.id]);}const nowSerialData = detailSelectedRow?.serialRespVOs;await this.serialTableRef?.clearRows(); //清除可编辑表格的数据this.serialTableRef?.addRows(nowSerialData); //重新添加查询的数据this.setState({preSelectedRow: detailSelectedRow,});};// 明细行复制handleCopy = async (selectedRowKeys, selectedRows) => {const selectedRow = selectedRows[0];const isCopyedRow = selectedRow.ocopyId;if (isCopyedRow) {return ElNotification({type: 'warning',message: '不能复制已经复制的信息,请重新选择',});}await this.deatilTableRef.quitEditState();const dataSouce = await this.deatilTableRef.getRows();const index = dataSouce?.findLastIndex((v) => selectedRow?.relateDocLineno === v.relateDocLineno);const copyRow = {...selectedRow,odoId: this.state.id, // 单头idocopyId: selectedRow.id, // 复制行时把id给ocopyId,id: maths.genFakeId(-1),demandQty: null,qty: 0,serialRespVOs: [],};dataSouce.splice(index + 1, 0, copyRow);await this.deatilTableRef.clearRows();await this.deatilTableRef.addRows(dataSouce);};// 明细信息行删除事件handleDelClick = async (selectedRowKeys, selectedRows) => {const selectedRow = selectedRows[0];const isCopyedRow = selectedRow.ocopyId;if (!isCopyedRow) {return ElNotification({type: 'warning',message: '只能删除复制行,请重新选择',});}// 删除明细信息this.deatilTableRef.removeRowsByKeys(selectedRowKeys, 'rowKey');await this.serialTableRef.quitEditState(); // 序列号退出编辑状态await this.serialTableRef?.clearRows(); //清除可编辑表格的数据};// 序列号信息添加handleAddDataRow = async () => {const selectionData = await this.deatilTableRef?.getSelectionData();if (selectionData.selectedRows.length !== 1) {return ElNotification({type: 'warning',message: '请选中一行明细',});}const detailSelectedRow = selectionData.selectedRows[0];const newRow = {id: maths.genFakeId(-1),odoId: this.state.id, // 关联单idodoDid: detailSelectedRow?.id, // 序列号新增时,赋值选中的明细行id};this.serialTableRef?.addRow(newRow); //重新添加查询的数据};// 序列号信息删除handleDistributionDelete = async (selectedRowKeys) => {await this.serialTableRef.quitEditState();this.serialTableRef.removeRowsByKeys(selectedRowKeys, 'rowKey');};// 序列号导入handleImport = async () => {const selectionData = await this.deatilTableRef?.getSelectionData();if (selectionData.selectedRows.length !== 1) {return ElNotification({type: 'warning',message: '请选中一行明细',});}this.setState({importRequestParams: { odoDid: selectionData.selectedRows[0].id, odoId: this.state.id },});this.importModalRef.openModal();};// 导入方法回调importCallBack = async (res) => {if (res && res.success) {const importSuccessData = res.data.map((x) => {return {...x,id: maths.genFakeId(-1),};});this.serialTableRef?.addRows(importSuccessData);ElNotification({type: 'success',message: '操作成功!',});} else if (res && !res.success) {ElNotification({type: 'error',message: res?.msg || '操作失败',});}};/*** 返回*/onBack = () => {closeCurrentToPath('/inventory/outboundDelivery/searchOrder');};// 保存saveParams = async () => {//保存之前先把序列号信息退出编辑状态,同步到明细数据中const selectionData = await this.deatilTableRef?.getSelectionData();const detailSelectedRow = selectionData?.selectedRows[0];await this.serialTableRef.quitEditState(); // 序列号退出编辑状态const serialEditTableValues = await this.serialTableRef.validateTableRows();if (!serialEditTableValues?.msg?.success) {ElNotification({type: 'warning',message: '请添加序列号必填信息!',});return;}const TableValues = await this.serialTableRef.getRows(); // 获取序列号数据if (this.state.preSelectedRow) {this.deatilTableRef.updateRows({ serialRespVOs: TableValues }, [detailSelectedRow?.id]);// this.deatilTableRef.updateRows({ serialRespVOs: TableValues }, [this.state.preSelectedRow.id]);}const data = await this.processData();if (data?.odoDSaveVOList?.length === 0) {ElNotification({type: 'warning',message: '明细信息不允许为空',});return;}if (data) {this.setState({ loading: true });const res = await save(data);this.setState({ loading: false });if (res.success) {ElNotification({type: 'success',message: res.msg || '操作成功',});this.onBack();} else {ElNotification({type: 'error',message: res.msg || res.data || '操作失败!',});}}};/*入参基本信息处理baseFormDataRes 基本信息custFormDataRes 客户信息*/paramsBasicFormData = (baseFormDataRes, custFormDataRes) => {baseFormDataRes.whId = baseFormDataRes.whId?.whId;baseFormDataRes.whCode = baseFormDataRes.whId?.whCode;baseFormDataRes.whName = baseFormDataRes.whId?.whName;custFormDataRes.recvArea = undefined;};/* delSameObjValue 数组对象相同值相加去重arr 需要处理的数组 -- editTableValues?.dataresultNum 最终计算结果的键名 -- sumConfirmQtykeyName 用于计算判断的键名 这里是以数组的方式传过来的可以这支持接收多个参数判断】 -- relateDocLinenokeyValue 用于计算结果的键名 这里是以数组的方式传过来的可以这支持接收多个参数判断】 对应的键值为number类型 -- qty*/delSameObjValue = (arr, resultNum, keyName, keyValue) => {const warp = new Map();arr.forEach((i) => {const str = keyName.map((v) => i[v]).join('_');i[resultNum] = keyValue.reduce((p, c) => (p += i[c]), 0);warp.has(str) ? (warp.get(str)[resultNum] += i[resultNum]) : warp.set(str, i);});return Array.from(warp).map(([, v]) => v);};// 校验表单信息processData = async () => {// 基本信息const baseFormDataRes = await this.basicFormRef?.validateFields().catch(() => {ElNotification({type: 'warning',message: '请检查【基本信息】必填信息',});return Promise.reject();});// 客户信息const custFormDataRes = await this.receiveFormRef?.getFieldsValue();// 制单信息const otherFormDataRes = await this.controlFormRef?.getFieldsValue();this.paramsBasicFormData(baseFormDataRes, custFormDataRes);// 附件信息const { fileList } = this.state;const fileCodes =Array.isArray(fileList) &&fileList?.map((x) => {return x.fileCode;});const fileCode = fileCodes.toString();// 商品明细信息await this.deatilTableRef.quitEditState(); //保存退出明细行编辑状态const editTableValues = await this.deatilTableRef.validateTableRows();const sum = this.delSameObjValue(editTableValues?.data, 'sumConfirmQty', ['relateDocLineno'], ['qty']);const flag = sum.some((val) => val.sumConfirmQty !== val.demandQty);if (flag) {return ElNotification({type: 'warning',message: '相同【来源单据行号】的数据信息【实发数量】必须等于【要求发货数量】!',});}if (!editTableValues?.msg?.success) {return ElNotification({type: 'warning',message: '请添加明细必填信息!',});}const ruleLotFlagAddlotNo = editTableValues?.data.some((item) => item.lotFlag && (item.lotNo === null || item.lotNo === ''),);if (ruleLotFlagAddlotNo) {return ElNotification({type: 'warning',message: '明细商品中包含【启用批次】,请检查并完善【批次】',});}const itemDataSource = editTableValues?.data?.map((item) => {return {...item,odoId: this.state.id,lotNo: item?.lotNo?.lotNo,olotNo: item?.orlotNo,odoSerialSaveVOs: item.serialRespVOs ? item.serialRespVOs : [],sumConfirmQty: undefined, // 提示汇总字段不要serialRespVOs: undefined, // 返回的数组字段不要orlotNo: undefined,};});// 根据公司查询组织return {...this.state.bascicFormData,id: this.state.bascicFormData?.id, //复制按钮时,入参需要处理...baseFormDataRes, //基础信息...custFormDataRes, //客户信息...otherFormDataRes, // 制单信息odoDSaveVOList: itemDataSource, // 明细fileCode, // 附件odoDList: undefined,};};render() {const {pageType,bascicFormData: bascicFormDate,loading,OrderInfoData,fileList,importRequestParams,} = this.state;return (<Spin spinning={loading}><div className="inner-content"><ElRowContainer onBack={this.onBack} blocks={getTopButtons(this.saveParams, pageType)} position="top" /><TCollapse className="formAlignment" title="基本信息" levelOne><TFormdata={bascicFormDate}onRef={(ref) => {this.basicFormRef = ref;}}formProps={getBasicForm(pageType)}/><TCollapse title="收货信息" defaultOpen={false} className="formAlignment"><TFormdata={bascicFormDate}onRef={(ref) => {this.receiveFormRef = ref;}}formProps={getReceivingForm(this.state.recvCountryCode)}/></TCollapse><TCollapse title="制单信息" defaultOpen={false} className="formAlignment"><TFormdata={bascicFormDate}onRef={(ref) => {this.controlFormRef = ref;}}formProps={getControlForm()}/></TCollapse></TCollapse><TCollapse title="明细信息"><TEditTabletableId="middleGround_inventoryCenter_supply_saleorder_orderDetail"borderedrowKey="id"scroll={{ y: 20000 }}onRef={(ref) => (this.deatilTableRef = ref)}dataSource={OrderInfoData}actionButtons={getDetailButtons(pageType, this.handleCopy, this.handleDelClick)}needToolBar={true}columns={getDetailColumns(pageType, this)}rowSelectionConfig={{type: 'radio',fixed: true,disabledRowIds: [],onChange: ({ selectedRowKeys, selectedRows }) => {this.handleOrderInfoSelect(selectedRowKeys, selectedRows);},}}defaultTableConfig={{onBottomPressEnter: 'trigger',onTableIntoEdit: 'dbclick',}}/></TCollapse><TCollapse title="序列号信息"><TEditTabletableId="middleGround_inventoryCenter_supply_saleorder_distributionInformation"rowKey="id"borderedscroll={{ y: 'calc(100vh - 430px)' }}dataSource={[]}actionButtons={getSerialButtons(pageType,this.handleAddDataRow,this.handleDistributionDelete,this.handleImport,)}onRef={(ref) => (this.serialTableRef = ref)}columns={getSerialEdittabColumns(pageType)}/></TCollapse><TCollapse title="相关附件" levelOne={true}><FileUploaduseType="outTable"fileListLen={999}uploadInfo="支持所有类型文件,文件不能超过10M"value={fileList}onUploadErr={(err) => {ElNotification({type: 'error',message: err?.msg || '上传失败',});}}onRemoveErr={(err) => {ElNotification({type: 'error',message: err?.msg || '删除失败',});}}onChange={(value) => {this.setState({fileList: value,});}}multiple={true}fileList={fileList}prefix="/cloudt/system"disabled={pageType === 'view'}/></TCollapse><ELImport_3push={frameHistoryPush}prefix="/yst/inv"templateCode="INV_ODO_SERIAL_IMPORT"downTemplateConfig={{mode: 'templateCode',fileName: '序列号导入模版',}}importConfig={{mode: 'request',url: '/yst/inv/inv/odod/serial/importOdoSerial',maxSize: 1,sizeUnit: 'MB',note: '仅支持xlsx文件,不能大于20mb',accept: 'xlsx|xls|xlsx',onSuccess: this.importCallBack,}}requestParams={importRequestParams}onRef={(ref) => (this.importModalRef = ref)}/></div></Spin>);}}export default SaleOrderEdit;