223 lines
6.4 KiB
JavaScript
223 lines
6.4 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
||
import {
|
||
Tag,
|
||
Button,
|
||
Card,
|
||
Table,
|
||
Input,
|
||
Flex,
|
||
Popover,
|
||
Image,
|
||
Row,
|
||
Col,
|
||
DatePicker,
|
||
Form,
|
||
message,
|
||
} from "antd";
|
||
import dayjs from "dayjs";
|
||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||
import { NS_SAFETY_EVAL_BUSINESS } from "~/enumerate/namespace";
|
||
import { tools } from "@cqsjjb/jjb-common-lib";
|
||
|
||
const { router } = tools;
|
||
|
||
const ArchiveContent = ({ readOnly, ...props }) => {
|
||
const projectId = router.query?.id;
|
||
const { processControlDetail, processControlFiles, evalProjectDetailData } =
|
||
props.safetyEvalBusiness || {};
|
||
const { processControl } = processControlDetail || {};
|
||
|
||
const [files, setFiles] = useState([]);
|
||
const [archiveForm] = Form.useForm();
|
||
|
||
const fetchDetail = () => {
|
||
props.evalProcessControlDetail({ projectId });
|
||
};
|
||
|
||
const fetchFiles = () => {
|
||
props.evalProcessControlFiles({ projectId });
|
||
};
|
||
|
||
useEffect(() => {
|
||
if (projectId) {
|
||
fetchDetail();
|
||
fetchFiles();
|
||
}
|
||
}, [projectId]);
|
||
|
||
useEffect(() => {
|
||
if (processControlDetail) {
|
||
archiveForm.setFieldsValue({
|
||
projectNo: evalProjectDetailData.projectNo,
|
||
archiveTransferorName: processControlDetail.archiveTransferorName || "",
|
||
archiveArchivistName: processControlDetail.archiveArchivistName || "",
|
||
archiveDate: processControlDetail.archiveDate
|
||
? dayjs(processControlDetail.archiveDate)
|
||
: null,
|
||
});
|
||
}
|
||
}, [processControlDetail]);
|
||
|
||
useEffect(() => {
|
||
if (processControlFiles) {
|
||
setFiles(processControlFiles);
|
||
}
|
||
}, [processControlFiles]);
|
||
|
||
const isSignatureCompleted =
|
||
processControl?.reviewerSignatureTaskStatus === "completed";
|
||
const canArchive = isSignatureCompleted;
|
||
|
||
const handleArchive = async () => {
|
||
if (!projectId) return;
|
||
const values = await archiveForm.validateFields();
|
||
const res = await props.evalProcessControlArchive({ projectId, ...values });
|
||
if (res?.success !== false) {
|
||
message.success("项目已归档入库");
|
||
fetchDetail();
|
||
props.getDetail?.();
|
||
}
|
||
};
|
||
|
||
const isImage = (name) =>
|
||
/\.(jpg|jpeg|png|gif|webp|bmp|svg)$/i.test(name || "");
|
||
|
||
const fileColumns = [
|
||
{ title: "流程名称", dataIndex: "processName", ellipsis: true },
|
||
{ title: "条目名称", dataIndex: "itemName", ellipsis: true },
|
||
{
|
||
title: "文件",
|
||
dataIndex: "projectDocUrl",
|
||
render: (val) => {
|
||
let fileList = [];
|
||
if (typeof val === "string") {
|
||
try {
|
||
fileList = JSON.parse(val);
|
||
} catch {
|
||
fileList = [];
|
||
}
|
||
} else if (Array.isArray(val)) {
|
||
fileList = val;
|
||
}
|
||
if (!fileList.length) return "-";
|
||
return (
|
||
<Flex vertical gap={2}>
|
||
<Popover
|
||
title="附件列表"
|
||
content={
|
||
<Flex vertical gap={4}>
|
||
{fileList.map((f, i) => {
|
||
const url = f.url || f.response?.url;
|
||
return isImage(f.name) ? (
|
||
<Flex key={f.uid || i} align="center" gap={4}>
|
||
{<Image src={url} width={80} />}
|
||
</Flex>
|
||
) : (
|
||
<a
|
||
key={f.uid || i}
|
||
style={{ cursor: "pointer" }}
|
||
onClick={() => window.open(url)}
|
||
>
|
||
{f.name || "查看文件"}
|
||
</a>
|
||
);
|
||
})}
|
||
</Flex>
|
||
}
|
||
trigger="hover"
|
||
placement="topLeft"
|
||
>
|
||
<a
|
||
onClick={(e) => e.preventDefault()}
|
||
style={{ cursor: "pointer" }}
|
||
>
|
||
{fileList.length}个附件
|
||
</a>
|
||
</Popover>
|
||
</Flex>
|
||
);
|
||
},
|
||
},
|
||
];
|
||
|
||
return (
|
||
<Card
|
||
title="项目归档"
|
||
style={{ marginBottom: 16 }}
|
||
styles={{ body: { paddingBottom: 0 } }}
|
||
>
|
||
<div className="pf-permission">
|
||
<Tag color="blue" className="pf-tag">
|
||
项目归档
|
||
</Tag>
|
||
<span className="pf-desc">
|
||
项目过程文件清单,确认签字完成后归档入库
|
||
</span>
|
||
</div>
|
||
|
||
<Table
|
||
dataSource={files}
|
||
columns={fileColumns}
|
||
rowKey={(record) =>
|
||
`${record.processName}-${record.materialName}-${record.itemName}`
|
||
}
|
||
pagination={false}
|
||
size="small"
|
||
/>
|
||
|
||
<Form form={archiveForm} layout="vertical" disabled={readOnly}>
|
||
<Row gutter={16} style={{ marginTop: 16, marginBottom: 16 }}>
|
||
<Col span={6}>
|
||
<Form.Item label="项目编号" name="projectNo">
|
||
<Input placeholder="请输入项目编号" disabled />
|
||
</Form.Item>
|
||
</Col>
|
||
<Col span={6}>
|
||
<Form.Item label="移交人" name="archiveTransferorName" rules={[{ required: true, message: "请输入移交人" }]}>
|
||
<Input placeholder="请输入移交人" allowClear maxLength={10} />
|
||
</Form.Item>
|
||
</Col>
|
||
<Col span={6}>
|
||
<Form.Item label="档案管理员" name="archiveArchivistName" rules={[{ required: true, message: "请输入档案管理员" }]}>
|
||
<Input placeholder="请输入档案管理员" allowClear maxLength={10} />
|
||
</Form.Item>
|
||
</Col>
|
||
{processControlDetail?.archiveDate && (
|
||
<Col span={6}>
|
||
<Form.Item label="入库日期" name="archiveDate">
|
||
<DatePicker style={{ width: "100%" }} disabled />
|
||
</Form.Item>
|
||
</Col>
|
||
)}
|
||
</Row>
|
||
</Form>
|
||
|
||
<Flex
|
||
justify="space-between"
|
||
align="center"
|
||
style={{ marginTop: 12, paddingBottom: 16 }}
|
||
>
|
||
{!readOnly && (
|
||
<Button
|
||
type="primary"
|
||
onClick={handleArchive}
|
||
loading={props.safetyEvalBusiness?.processControlArchiveLoading}
|
||
disabled={!canArchive}
|
||
title={
|
||
!canArchive
|
||
? !isSignatureCompleted
|
||
? "需签字完成后才可归档"
|
||
: "需生成归档交接单后才可归档"
|
||
: ""
|
||
}
|
||
>
|
||
双方签字并确认入库
|
||
</Button>
|
||
)}
|
||
</Flex>
|
||
</Card>
|
||
);
|
||
};
|
||
|
||
export default Connect([NS_SAFETY_EVAL_BUSINESS], true)(ArchiveContent);
|