供应商

This commit is contained in:
孙景学
2025-06-24 10:52:30 +08:00
parent f24a87a15c
commit c1267c8228
116 changed files with 16058 additions and 1 deletions

View File

@ -0,0 +1,257 @@
import React, { useEffect, useState } from 'react';
import { Modal, Table, Button, Radio, Input, Upload, message, Spin } from 'antd';
import { reviewInfo, uploadFile } from '../services'; // 你的接口
interface ResultModalProps {
visible: boolean;
record?: { id?: string; [key: string]: any } | null;
onCancel: () => void;
onSubmit: (payload: any) => void;
}
// 单元格内容
type CellValue = {
reviewResult?: 0 | 1; // 0合格 1不合格
remark?: string;
file?: any;
};
const ResultModal: React.FC<ResultModalProps> = ({
visible,
record,
onCancel,
onSubmit
}) => {
const [suppliers, setSuppliers] = useState<any[]>([]);
const [items, setItems] = useState<any[]>([]);
const [cellData, setCellData] = useState<{
[itemId: string]: { [supplierId: string]: CellValue }
}>({});
const [loading, setLoading] = useState(false);
// 备注弹窗
const [remarksModalVisible, setRemarksModalVisible] = useState(false);
const [remarks, setRemarks] = useState('');
const [fileList, setFileList] = useState<any[]>([]);
const [currentCell, setCurrentCell] = useState<{ itemId: string, supplierId: string } | null>(null);
// 拉取评审数据
useEffect(() => {
if (visible && record?.id) {
setLoading(true);
reviewInfo({ id: record.id, userId: 'E0001' })
.then((res: any) => {
const data = res?.data || [];
setSuppliers(data);
// 用第一家供应商的coscoAccessItemList生成所有评审项
const firstSupplier = data[0] || {};
const itemList = (firstSupplier.coscoAccessItemList || []).filter((i: { itemType:string } ) => i.itemType !== 'summary');
setItems(itemList);
// 初始化 cellData
const newCellData: any = {};
itemList.forEach((item: any) => {
newCellData[item.id] = {};
data.forEach((sup: any) => {
newCellData[item.id][sup.supplierId] = {};
});
});
setCellData(newCellData);
})
.finally(() => setLoading(false));
}
}, [visible, record]);
// 单选
const handleRadioChange = (itemId: string, supplierId: string, value: string) => {
setCellData(prev => ({
...prev,
[itemId]: {
...prev[itemId],
[supplierId]: {
...prev[itemId]?.[supplierId],
reviewResult: value === '合格' ? 0 : 1
}
}
}));
};
// 打开备注弹窗
const openRemarksModal = (itemId: string, supplierId: string) => {
setCurrentCell({ itemId, supplierId });
const cell = cellData[itemId]?.[supplierId] || {};
setRemarks(cell.remark || '');
setFileList(cell.file
? [{
uid: '-1',
name: cell.file.fileName,
status: 'done',
url: cell.file.fileUrl,
response: cell.file
}]
: []);
setRemarksModalVisible(true);
};
// 上传
const uploadProps = {
fileList,
maxCount: 1,
onRemove: () => setFileList([]),
customRequest: async (options: any) => {
const res = await uploadFile(options.file);
const fileObj = res;
setFileList([{
uid: options.file.uid,
name: fileObj.fileName,
status: 'done',
url: fileObj.url,
response: fileObj
}]);
message.success('文件上传成功');
options.onSuccess && options.onSuccess(res, options.file);
}
};
// 备注提交
const handleSubmitRemarks = () => {
if (!currentCell) return;
setCellData(prev => ({
...prev,
[currentCell.itemId]: {
...prev[currentCell.itemId],
[currentCell.supplierId]: {
...prev[currentCell.itemId]?.[currentCell.supplierId],
remark: remarks,
file: fileList[0]?.response || undefined
}
}
}));
setRemarksModalVisible(false);
};
// 提交
const handleSubmit = () => {
// 组装参数
let result: any[] = [];
items.forEach(item => {
suppliers.forEach(sup => {
const cell = cellData?.[item.id]?.[sup.supplierId];
if (cell && cell.reviewResult !== undefined) {
result.push({
id: item.id,
reviewResult: cell.reviewResult,
remark: cell.remark || '',
coscoAccessTtemAttachments: cell.file || undefined
});
}
});
});
console.log(items,'items');
console.log(result,'result');
onSubmit && onSubmit({ coscoAccessUserItemList: result });
};
// 组装表头
const columns = [
{
title: '评审项',
dataIndex: 'itemName',
key: 'itemName',
width: 200,
fixed: 'left'
},
...suppliers.map(sup => ({
title: sup.supplierName,
dataIndex: sup.supplierId,
key: sup.supplierId,
width: 300,
render: (_: any, row: any) => {
const v = cellData?.[row.key]?.[sup.supplierId] || {};
console.log(sup,'sup');
return (
<div>
<Radio.Group
value={
v.reviewResult === 0
? '合格'
: v.reviewResult === 1
? '不合格'
: undefined
}
onChange={e => handleRadioChange(row.key, sup.supplierId, e.target.value)}
>
<Radio value="合格"></Radio>
<Radio value="不合格"></Radio>
</Radio.Group>
<Button type="link" onClick={() => openRemarksModal(row.key, sup.supplierId)}></Button>
{v.remark && <span style={{ color: '#aaa', fontSize: 12 }}></span>}
{v.file && <span style={{ color: '#52c41a', fontSize: 12, marginLeft: 8 }}></span>}
</div>
);
}
}))
];
// 行数据
const tableData = items.map(item => ({
key: item.id,
itemName: item.itemName
}));
return (
<Modal
title="评审结果"
visible={visible}
onCancel={onCancel}
footer={[
<Button key="cancel" onClick={onCancel}></Button>,
<Button key="submit" type="primary" onClick={handleSubmit}></Button>
]}
width={1000}
bodyStyle={{ maxHeight: '60vh', overflowY: 'auto' }}
centered
destroyOnClose
>
<Spin spinning={loading}>
<Table
dataSource={tableData}
columns={columns}
pagination={false}
bordered
scroll={{ x: 300 * suppliers.length + 200 }}
/>
</Spin>
<Modal
title="备注/上传附件"
visible={remarksModalVisible}
onCancel={() => setRemarksModalVisible(false)}
footer={[
<Button key="cancel" onClick={() => setRemarksModalVisible(false)}></Button>,
<Button key="submit" type="primary" onClick={handleSubmitRemarks}></Button>
]}
destroyOnClose
>
<Input.TextArea
rows={4}
placeholder="请输入备注"
value={remarks}
onChange={e => setRemarks(e.target.value)}
/>
<Upload {...uploadProps}>
<Button style={{ marginTop: 12 }}></Button>
</Upload>
</Modal>
</Modal>
);
};
export default ResultModal;