Merge branch 'dev' of http://47.92.113.182:3000/cq_anquan/safety-eval-service-frontend into dev
commit
2d08e2e9e5
|
|
@ -15,7 +15,7 @@ module.exports = {
|
|||
API_HOST: "http://192.168.0.134",
|
||||
//API_HOST: "http://192.168.0.150", //太浅
|
||||
// API_HOST: "http://192.168.0.152",
|
||||
//API_HOST: "http://192.168.0.103", //huwei
|
||||
// API_HOST: "http://192.168.0.103", //huwei
|
||||
},
|
||||
production: {
|
||||
// 应用后端分支名称,部署上线需要
|
||||
|
|
|
|||
|
|
@ -224,10 +224,10 @@ function PersonnelInfoPage(props) {
|
|||
},
|
||||
{
|
||||
title: "能力",
|
||||
width: 80,
|
||||
width: 260,
|
||||
dataIndex: "abilityNames",
|
||||
ellipsis: true,
|
||||
render: (text) => "暂无",
|
||||
render: (text) => text || '暂无',
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
|
|
@ -394,6 +394,7 @@ function StaffFormModal({
|
|||
};
|
||||
|
||||
const loadBasicDisciplineMajors = async () => {
|
||||
|
||||
await queryBasicDisciplineMajor({ pageSize: 999 });
|
||||
};
|
||||
|
||||
|
|
@ -449,6 +450,7 @@ function StaffFormModal({
|
|||
}
|
||||
|
||||
form.setFieldsValue(setFields);
|
||||
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) setDetailLoading(false);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import {
|
|||
DatePicker,
|
||||
Space,
|
||||
ConfigProvider,
|
||||
Tag,
|
||||
Tooltip,
|
||||
} from "antd";
|
||||
import {
|
||||
PlusOutlined,
|
||||
|
|
@ -101,6 +103,30 @@ const getFileExt = (name = "") => {
|
|||
return parts.length > 1 ? parts.pop().toUpperCase() : "PDF";
|
||||
};
|
||||
|
||||
/** 解析 JSON 文件列表,渲染为可下载链接列表 */
|
||||
const renderFileLinks = (jsonStr) => {
|
||||
if (!jsonStr) return "-";
|
||||
try {
|
||||
const files = JSON.parse(jsonStr);
|
||||
if (!Array.isArray(files) || files.length === 0) return "-";
|
||||
return files.map((f, i) => (
|
||||
<div key={i} className="erl-file-cell" style={{ marginBottom: 4 }}>
|
||||
<i>{getFileExt(f.name || f.url)}</i>
|
||||
<a
|
||||
href={f.url}
|
||||
download={f.name}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{f.name || "未命名文件"}
|
||||
</a>
|
||||
</div>
|
||||
));
|
||||
} catch {
|
||||
return jsonStr;
|
||||
}
|
||||
};
|
||||
|
||||
const getOptionLabel = (options, value) =>
|
||||
options.find((item) => item.value === value)?.label || value || "-";
|
||||
|
||||
|
|
@ -131,6 +157,8 @@ const EvalReportLibrary = (props) => {
|
|||
const [rectifyVisible, setRectifyVisible] = useState(false);
|
||||
const [rectifyRecord, setRectifyRecord] = useState(null);
|
||||
const [uploadedFile, setUploadedFile] = useState(null);
|
||||
const [contractFiles, setContractFiles] = useState([]);
|
||||
const [processDocFiles, setProcessDocFiles] = useState([]);
|
||||
|
||||
const {
|
||||
evalReportPageLoading,
|
||||
|
|
@ -188,6 +216,8 @@ const EvalReportLibrary = (props) => {
|
|||
|
||||
const handleOpenAdd = () => {
|
||||
setUploadedFile(null);
|
||||
setContractFiles([]);
|
||||
setProcessDocFiles([]);
|
||||
uploadForm.resetFields();
|
||||
uploadForm.setFieldsValue({
|
||||
reportYear: dayjs().year(),
|
||||
|
|
@ -225,6 +255,40 @@ const EvalReportLibrary = (props) => {
|
|||
}
|
||||
};
|
||||
|
||||
// 合同文件上传
|
||||
const handleContractUploadChange = (info) => {
|
||||
if (info.file.status === "error") {
|
||||
message.error(`${info.file.name} 上传失败`);
|
||||
return;
|
||||
}
|
||||
const doneFiles = info.fileList
|
||||
.filter((f) => f.status === "done" && f.response?.data)
|
||||
.map((f) => ({
|
||||
uid: f.uid,
|
||||
url: f.response.data.url || f.response.data.fileUrl || "",
|
||||
name: f.response.data.name || f.response.data.fileName || f.name,
|
||||
}))
|
||||
.filter((f) => f.url);
|
||||
setContractFiles(doneFiles);
|
||||
};
|
||||
|
||||
// 其他过程文档上传
|
||||
const handleProcessDocUploadChange = (info) => {
|
||||
if (info.file.status === "error") {
|
||||
message.error(`${info.file.name} 上传失败`);
|
||||
return;
|
||||
}
|
||||
const doneFiles = info.fileList
|
||||
.filter((f) => f.status === "done" && f.response?.data)
|
||||
.map((f) => ({
|
||||
uid: f.uid,
|
||||
url: f.response.data.url || f.response.data.fileUrl || "",
|
||||
name: f.response.data.name || f.response.data.fileName || f.name,
|
||||
}))
|
||||
.filter((f) => f.url);
|
||||
setProcessDocFiles(doneFiles);
|
||||
};
|
||||
|
||||
const handleAddOk = async () => {
|
||||
const values = await uploadForm.validateFields().catch(() => null);
|
||||
if (!values) return;
|
||||
|
|
@ -252,6 +316,8 @@ const EvalReportLibrary = (props) => {
|
|||
SECRET_LEVEL_OPTIONS,
|
||||
values.secretLevelCode,
|
||||
),
|
||||
contractFileUrls: contractFiles.length > 0 ? JSON.stringify(contractFiles) : undefined,
|
||||
processDocUrls: processDocFiles.length > 0 ? JSON.stringify(processDocFiles) : undefined,
|
||||
remarks: values.remarks,
|
||||
submitToRegulator: values.submitToRegulator === 1,
|
||||
};
|
||||
|
|
@ -838,6 +904,50 @@ const EvalReportLibrary = (props) => {
|
|||
<Select options={SECRET_LEVEL_OPTIONS} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Form.Item label="合同上传">
|
||||
<Upload
|
||||
name="file"
|
||||
action={UPLOAD_ACTION}
|
||||
headers={{ token: sessionStorage.getItem("token") || "" }}
|
||||
onChange={handleContractUploadChange}
|
||||
accept=".pdf,.doc,.docx,.jpg,.jpeg,.png,.zip,.rar"
|
||||
maxCount={20}
|
||||
beforeUpload={(file) => {
|
||||
const isLt100M = file.size / 1024 / 1024 <= 100;
|
||||
if (!isLt100M) {
|
||||
message.error("单个文件不超过 100MB");
|
||||
return Upload.LIST_IGNORE;
|
||||
}
|
||||
return true;
|
||||
}}
|
||||
>
|
||||
<Button icon={<UploadOutlined />}>选择合同文件</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Form.Item label="其他过程文档">
|
||||
<Upload
|
||||
name="file"
|
||||
action={UPLOAD_ACTION}
|
||||
headers={{ token: sessionStorage.getItem("token") || "" }}
|
||||
onChange={handleProcessDocUploadChange}
|
||||
accept=".pdf,.doc,.docx,.jpg,.jpeg,.png,.zip,.rar"
|
||||
maxCount={20}
|
||||
beforeUpload={(file) => {
|
||||
const isLt100M = file.size / 1024 / 1024 <= 100;
|
||||
if (!isLt100M) {
|
||||
message.error("单个文件不超过 100MB");
|
||||
return Upload.LIST_IGNORE;
|
||||
}
|
||||
return true;
|
||||
}}
|
||||
>
|
||||
<Button icon={<UploadOutlined />}>选择过程文档</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Form.Item name="remarks" label="备注">
|
||||
<TextArea
|
||||
|
|
@ -921,6 +1031,12 @@ const EvalReportLibrary = (props) => {
|
|||
<span>{detailData.fileName || "-"}</span>
|
||||
</div>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="合同文件" span={2}>
|
||||
{renderFileLinks(detailData.contractFileUrls)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="过程文档" span={2}>
|
||||
{renderFileLinks(detailData.processDocUrls)}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="备注" span={2}>
|
||||
{detailData.remarks || "-"}
|
||||
</Descriptions.Item>
|
||||
|
|
|
|||
|
|
@ -210,6 +210,17 @@ const getFileExtLabel = (name = "") => {
|
|||
return ext && ext !== name ? ext.toUpperCase() : "PDF";
|
||||
};
|
||||
|
||||
/** 解析存储的 JSON 文件列表字符串,返回数组 */
|
||||
const parseFileList = (jsonStr) => {
|
||||
if (!jsonStr) return [];
|
||||
try {
|
||||
const arr = JSON.parse(jsonStr);
|
||||
return Array.isArray(arr) ? arr : [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const EvalReportDatabase = (props) => {
|
||||
const [searchForm] = Form.useForm();
|
||||
const [exportForm] = Form.useForm();
|
||||
|
|
@ -310,6 +321,19 @@ const EvalReportDatabase = (props) => {
|
|||
getData(pagination);
|
||||
};
|
||||
|
||||
/** 下载指定 URL 的文件 */
|
||||
const handleFileDownload = (fileUrl, fileName) => {
|
||||
if (!fileUrl) {
|
||||
message.warning("文件地址不存在");
|
||||
return;
|
||||
}
|
||||
const hide = message.loading("正在下载...", 0);
|
||||
downloadFileByUrl(fileUrl, fileName)
|
||||
.then(() => message.success("下载已开始"))
|
||||
.catch(() => message.error("下载失败,请稍后重试"))
|
||||
.finally(() => hide());
|
||||
};
|
||||
|
||||
const handleViewDetail = async (record) => {
|
||||
setDetailData(null);
|
||||
setDetailVisible(true);
|
||||
|
|
@ -822,13 +846,59 @@ const EvalReportDatabase = (props) => {
|
|||
headers={["文件名称", "文件类型", "版本"]}
|
||||
rows={[
|
||||
[
|
||||
detailData.fileName || detailData.reportName || "正式安全评价报告.pdf",
|
||||
<span
|
||||
style={{ color: "#1677ff", cursor: "pointer" }}
|
||||
onClick={() =>
|
||||
handleFileDownload(
|
||||
detailData.fileUrl,
|
||||
detailData.fileName || detailData.reportName || "正式安全评价报告.pdf"
|
||||
)
|
||||
}
|
||||
>
|
||||
{detailData.fileName || detailData.reportName || "正式安全评价报告.pdf"}
|
||||
</span>,
|
||||
getFileExtLabel(detailData.fileName),
|
||||
"V1.0",
|
||||
],
|
||||
]}
|
||||
/>
|
||||
</ModalSection>
|
||||
<ModalSection
|
||||
title="合同文件"
|
||||
desc="查看上传的合同文件。"
|
||||
>
|
||||
<ProtoTable
|
||||
headers={["文件名称", "文件类型"]}
|
||||
rows={parseFileList(detailData.contractFileUrls).map((f) => [
|
||||
<span
|
||||
key={f.url}
|
||||
style={{ color: "#1677ff", cursor: "pointer" }}
|
||||
onClick={() => handleFileDownload(f.url, f.name || "未命名文件")}
|
||||
>
|
||||
{f.name || "未命名文件"}
|
||||
</span>,
|
||||
getFileExtLabel(f.name || f.url),
|
||||
])}
|
||||
/>
|
||||
</ModalSection>
|
||||
<ModalSection
|
||||
title="其他过程文档"
|
||||
desc="查看上传的过程文档。"
|
||||
>
|
||||
<ProtoTable
|
||||
headers={["文件名称", "文件类型"]}
|
||||
rows={parseFileList(detailData.processDocUrls).map((f) => [
|
||||
<span
|
||||
key={f.url}
|
||||
style={{ color: "#1677ff", cursor: "pointer" }}
|
||||
onClick={() => handleFileDownload(f.url, f.name || "未命名文件")}
|
||||
>
|
||||
{f.name || "未命名文件"}
|
||||
</span>,
|
||||
getFileExtLabel(f.name || f.url),
|
||||
])}
|
||||
/>
|
||||
</ModalSection>
|
||||
</>
|
||||
) : (
|
||||
<div className="redb-loading">
|
||||
|
|
|
|||
Loading…
Reference in New Issue