safety-eval-service-frontend/src/pages/Container/SafetyEvalBusiness/ProjectFlow/RiskAnalysisContent.js

526 lines
18 KiB
JavaScript
Raw Normal View History

2026-07-24 15:27:56 +08:00
import React, { useEffect, useState, useRef } from "react";
2026-07-20 15:03:26 +08:00
import {
Tag,
Button,
Card,
Row,
Col,
Table,
Form,
Input,
Select,
Radio,
DatePicker,
Flex,
2026-07-22 16:06:26 +08:00
message,
Spin,
2026-07-24 15:27:56 +08:00
Modal,
2026-07-20 15:03:26 +08:00
} from "antd";
2026-07-22 16:06:26 +08:00
import dayjs from "dayjs";
import { Connect } from "@cqsjjb/jjb-dva-runtime";
import { NS_SAFETY_EVAL_BUSINESS } from "~/enumerate/namespace";
import { QUALIFICATION_INDUSTRY_OPTIONS } from "~/enumerate/enterpriseOptions";
import { tools } from "@cqsjjb/jjb-common-lib";
2026-07-20 15:03:26 +08:00
2026-07-22 16:06:26 +08:00
const { router } = tools;
2026-07-20 15:03:26 +08:00
const { TextArea } = Input;
2026-07-22 16:06:26 +08:00
const EVAL_TYPE_OPTIONS = [
{ label: "安全预评价", value: "PRE" },
{ label: "安全验收评价", value: "ACCEPT" },
{ label: "安全现状评价", value: "STATUS" },
];
const RiskAnalysisContent = (props) => {
2026-07-20 15:03:26 +08:00
const [form] = Form.useForm();
2026-07-22 16:06:26 +08:00
const projectId = router.query?.id;
2026-07-20 15:03:26 +08:00
2026-07-22 16:06:26 +08:00
const {
safetyEvalBusiness,
evalRiskAnalysisGet,
evalRiskAnalysisSave,
evalRiskAnalysisPeopleSave,
} = props;
const {
riskAnalysisLoading,
evalProjectDetailLoading,
riskAnalysisSaveLoading,
2026-07-22 17:59:55 +08:00
evalProjectDetailData,
2026-07-22 16:06:26 +08:00
} = safetyEvalBusiness || {};
2026-07-20 15:03:26 +08:00
2026-07-22 16:06:26 +08:00
// 查询风险分析数据回显
2026-07-24 15:27:56 +08:00
const [participantModalOpen, setParticipantModalOpen] = useState(false);
const [selectedParticipantIds, setSelectedParticipantIds] = useState([]);
const addParticipantRef = useRef(null);
2026-07-22 16:06:26 +08:00
const fetchData = async () => {
if (!projectId) return;
2026-07-20 15:03:26 +08:00
2026-07-22 16:06:26 +08:00
const res = await evalRiskAnalysisGet({ projectId });
if (res?.success !== false && res?.data) {
form.setFieldsValue({
...res.data,
analysisDate: res.data.analysisDate
? dayjs(res.data.analysisDate)
: undefined,
});
} else {
form.setFieldsValue({
2026-07-22 17:59:55 +08:00
evalTypeCode: evalProjectDetailData.evalTypeCode,
projectName: evalProjectDetailData.projectName,
industryName: evalProjectDetailData.industryCode,
2026-07-22 16:06:26 +08:00
});
}
};
2026-07-20 15:03:26 +08:00
2026-07-22 16:06:26 +08:00
useEffect(() => {
2026-07-22 17:59:55 +08:00
if (evalProjectDetailData?.id) {
2026-07-22 16:06:26 +08:00
fetchData();
}
2026-07-22 17:59:55 +08:00
}, [projectId, evalProjectDetailData?.id]);
2026-07-20 15:03:26 +08:00
2026-07-22 16:06:26 +08:00
// 保存
const handleSave = async (statusCode) => {
const values = await form.validateFields();
const { analysisDate, ...rest } = values;
2026-07-24 11:05:09 +08:00
if (!rest.participants?.length) {
message.warning("请选择风险分析人员");
return;
}
2026-07-22 16:06:26 +08:00
const res = await evalRiskAnalysisSave({
...rest,
projectId,
statusCode,
analysisDate: analysisDate
? analysisDate.format("YYYY-MM-DD")
: undefined,
});
if (res?.success && res.data && rest.participants?.length) {
const result = await evalRiskAnalysisPeopleSave(
rest.participants.map((item) => {
return {
...item,
riskId: res.data.id,
};
}),
);
if (result.success) {
message.success(statusCode === 2 ? "风险分析已完成" : "已暂存");
2026-07-23 17:41:28 +08:00
props.getDetail()
2026-07-22 16:06:26 +08:00
}
}
};
return (
<Spin spinning={evalProjectDetailLoading || riskAnalysisLoading}>
<div>
<div className="pf-permission">
<Tag color="blue" className="pf-tag">
市场部经办人 / 市场部经理
</Tag>
<span className="pf-desc">
市场部组织前置条件调查和风险分析相关职能部门参与市场部经理依据分析结果决定是否签订技术服务合同
</span>
</div>
<Card
title="安全评价风险分析记录表受控编号QAPJ-CX-1-JL01"
styles={{ header: { textAlign: "center" } }}
>
<Form form={form} layout="vertical">
<Row gutter={16}>
<Col span={12}>
<Form.Item label="风险分析时间" name="analysisDate">
<DatePicker className="pf-w-full" allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="评价项目名称" name="projectName">
<Input
placeholder="请输入评价项目名称"
maxLength={50}
allowClear
/>
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={12}>
<Form.Item label="评价类别" name="evalTypeCode">
<Select placeholder="请选择评价类别" allowClear>
{EVAL_TYPE_OPTIONS.map((opt) => (
<Select.Option key={opt.value} value={opt.value}>
{opt.label}
</Select.Option>
))}
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="所属行业" name="industryName">
<Select placeholder="请选择所属行业" allowClear>
{QUALIFICATION_INDUSTRY_OPTIONS.map((opt) => (
<Select.Option key={opt.value} value={opt.value}>
{opt.label}
</Select.Option>
))}
</Select>
</Form.Item>
</Col>
</Row>
<Form.Item label="评价范围" name="evalScope">
2026-07-20 15:03:26 +08:00
<TextArea
2026-07-22 16:06:26 +08:00
rows={2}
placeholder="明确本项目安全评价对象、装置、区域及委托范围"
maxLength={200}
showCount
2026-07-20 15:03:26 +08:00
/>
</Form.Item>
2026-07-22 16:06:26 +08:00
<Form.Item label="是否在公司资质业务范围内" name="inBizScopeFlag">
2026-07-20 15:03:26 +08:00
<Radio.Group>
2026-07-22 16:06:26 +08:00
<Radio value={1}></Radio>
<Radio value={2}></Radio>
2026-07-20 15:03:26 +08:00
</Radio.Group>
</Form.Item>
2026-07-22 16:06:26 +08:00
<Card
type="inner"
size="small"
title="一、被评价单位基本概况"
className="pf-section"
>
<Form.Item name="unitOverview">
<TextArea
rows={4}
placeholder="填写项目简介、投资规模、地理位置、周边环境、主要设施及客户要求"
maxLength={500}
showCount
/>
</Form.Item>
</Card>
2026-07-20 15:03:26 +08:00
2026-07-22 16:06:26 +08:00
<Card
type="inner"
size="small"
title="二、项目行业风险特性分析"
className="pf-section"
>
<Form.Item name="industryRiskDesc">
<TextArea
rows={3}
placeholder="分析项目所属行业的主要危险、有害因素"
maxLength={500}
showCount
/>
</Form.Item>
<div className="pf-hint-blue">
应结合项目行业特点地理位置周边环境和评价类别填写非常规项目应通过风险分析会议形成记录
2026-07-20 15:03:26 +08:00
</div>
</Card>
2026-07-22 16:06:26 +08:00
<Card
type="inner"
size="small"
title="三、评价机构符合情况"
className="pf-section"
>
<Form.Item
label="1评价人员专业构成是否满足该项目的评价需求"
name="staffMatchCode"
>
<Radio.Group>
<Radio value={1}>满足</Radio>
<Radio value={2}>不满足</Radio>
</Radio.Group>
</Form.Item>
<Form.Item
label="2是否需要聘请相关技术专家"
name="needExpertCode"
>
<Radio.Group>
<Radio value={2}>不需要</Radio>
<Radio value={1}>需要</Radio>
</Radio.Group>
</Form.Item>
<Form.Item
label="3是否有能力承担该项目的评价风险"
name="capabilityCode"
>
<Radio.Group>
<Radio value={1}></Radio>
<Radio value={2}></Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="4项目的可行性分析" name="feasibleCode">
<Radio.Group>
<Radio value={1}>可行</Radio>
<Radio value={2}>不可行</Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="5项目的经济性分析" name="economicCode">
<Radio.Group>
<Radio value={1}>有经济效益</Radio>
<Radio value={2}>无经济效益</Radio>
</Radio.Group>
</Form.Item>
2026-07-20 15:03:26 +08:00
</Card>
2026-07-22 16:06:26 +08:00
<Card
type="inner"
size="small"
title="风险分析结论"
className="pf-section"
>
<Form.Item label="风险程度" name="riskLevelCode">
<Radio.Group>
<Radio value={1}>低度</Radio>
<Radio value={2}>中度</Radio>
<Radio value={3}>高度</Radio>
</Radio.Group>
</Form.Item>
<div className="pf-risk-note">
中度化工金属非金属矿山金属冶炼陆地油气开采等行业评价项目
2026-07-20 15:03:26 +08:00
</div>
2026-07-22 16:06:26 +08:00
<Form.Item label="合同签订" name="signContractCode">
<Radio.Group>
<Radio value={1}>签合同</Radio>
<Radio value={2}>不签合同</Radio>
</Radio.Group>
</Form.Item>
<div className="pf-hint-blue">
系统建议当前条件具备签约基础最终结论由市场部经理批准
2026-07-20 15:03:26 +08:00
</div>
</Card>
2026-07-22 16:06:26 +08:00
<Card type="inner" size="small" title="参与风险分析人员签字">
<Form.List name="participants">
2026-07-24 15:27:56 +08:00
{(fields, { add, remove }) => {
addParticipantRef.current = add;
return (
2026-07-22 16:06:26 +08:00
<>
<Table
dataSource={fields}
columns={[
{
title: "姓名",
dataIndex: "name",
render: (_, field) => {
const { key, ...fieldProps } = field;
return (
<Form.Item
{...fieldProps}
name={[field.name, "personnelName"]}
noStyle
>
<Input
placeholder="姓名"
2026-07-24 15:27:56 +08:00
disabled
2026-07-22 16:06:26 +08:00
maxLength={20}
allowClear
/>
</Form.Item>
);
},
},
{
title: "部门/岗位",
dataIndex: "deptName",
render: (_, field) => {
const { key, ...fieldProps } = field;
return (
<Form.Item
{...fieldProps}
name={[field.name, "deptName"]}
noStyle
>
<Input
placeholder="部门/岗位"
2026-07-24 15:27:56 +08:00
disabled
2026-07-22 16:06:26 +08:00
maxLength={20}
allowClear
/>
</Form.Item>
);
},
},
{
title: "分析意见",
dataIndex: "opinion",
render: (_, field) => {
const { key, ...fieldProps } = field;
return (
<Form.Item
{...fieldProps}
name={[field.name, "opinion"]}
noStyle
>
<Input
placeholder="填写分析意见"
maxLength={30}
allowClear
/>
</Form.Item>
);
},
},
{
title: "签字状态",
render: (_, field) => (
<Button size="small">发起APP签字</Button>
),
},
{
title: "操作",
render: (_, field) =>
fields.length > 1 ? (
<Button
type="link"
danger
size="small"
onClick={() => remove(field.name)}
>
删除
</Button>
) : null,
},
]}
rowKey={(_, index) => index}
pagination={false}
/>
<Button
type="dashed"
size="small"
style={{ marginTop: 8 }}
2026-07-24 15:27:56 +08:00
onClick={() => {
setSelectedParticipantIds([]);
setParticipantModalOpen(true);
}}
2026-07-22 16:06:26 +08:00
>
添加参与人员
</Button>
</>
2026-07-24 15:27:56 +08:00
);
}}
2026-07-22 16:06:26 +08:00
</Form.List>
</Card>
2026-07-24 15:27:56 +08:00
<Modal
title="选择参与人员"
open={participantModalOpen}
onCancel={() => setParticipantModalOpen(false)}
onOk={() => {
const selected = (evalProjectDetailData?.participants || []).filter(
(p) => selectedParticipantIds.includes(p.id),
);
selected.forEach((p) => {
addParticipantRef.current?.({
personnelName: p.name,
deptName: p.deptName,
opinion: "",
});
});
setParticipantModalOpen(false);
}}
>
<Table
dataSource={(() => {
const existing = (form.getFieldValue("participants") || []).map(
(p) => p.personnelName,
);
return (evalProjectDetailData?.participants || []).filter(
(p) => !existing.includes(p.name),
);
})()}
rowKey="id"
rowSelection={{
type: "checkbox",
selectedRowKeys: selectedParticipantIds,
onChange: (keys) => setSelectedParticipantIds(keys),
getCheckboxProps: (record) => ({
disabled: false,
}),
}}
columns={[
{ title: "姓名", dataIndex: "name", width: 100 },
{ title: "部门", dataIndex: "deptName", width: 120 },
{ title: "岗位", dataIndex: "posName", width: 120 },
{ title: "能力", dataIndex: "capacity", width: 120 },
]}
pagination={false}
size="small"
locale={{ emptyText: "所有人员均已添加" }}
/>
</Modal>
2026-07-22 16:06:26 +08:00
</Form>
</Card>
<Card
title="管理办法判定提示"
size="small"
className="pf-rule-card pf-section"
>
<Row gutter={16}>
<Col span={8}>
<Card size="small" type="inner">
<div>
<strong>低度风险</strong>
</div>
<div className="pf-risk-card">
小型露天采石场加油站以及机构熟悉且开展过类似评价工作的常规项目
</div>
</Card>
</Col>
<Col span={8}>
<Card size="small" type="inner">
<div>
<strong>中度风险</strong>
</div>
<div className="pf-risk-card">
化工生产金属非金属矿山金属冶炼陆地石油和天然气开采行业的评价项目
</div>
</Card>
</Col>
<Col span={8}>
<Card size="small" type="inner">
<div>
<strong>高度风险</strong>
</div>
<div className="pf-risk-card">
机构未开展过的非常规项目原则上组织专项风险分析会议必要时总经理参加
</div>
</Card>
</Col>
</Row>
<div className="pf-reject-note">
<strong>不签合同重点条件</strong>
超出资质范围无法提供合法有效资料客户提出违法或不合理要求经济性达不到预期评价时间不能满足机构与被评价对象存在投资咨询设计监理物资供应等利益关系
</div>
</Card>
<Flex justify="flex-end" gap={8}>
<Button
onClick={() => handleSave(1)}
loading={riskAnalysisSaveLoading}
>
暂存
</Button>
2026-07-20 15:03:26 +08:00
<Button>打印记录表</Button>
2026-07-22 16:06:26 +08:00
<Button
type="primary"
onClick={() => handleSave(2)}
loading={riskAnalysisSaveLoading}
>
完成分析并保存
</Button>
2026-07-20 15:03:26 +08:00
</Flex>
2026-07-22 16:06:26 +08:00
</div>
</Spin>
2026-07-20 15:03:26 +08:00
);
};
2026-07-22 16:06:26 +08:00
export default Connect([NS_SAFETY_EVAL_BUSINESS], true)(RiskAnalysisContent);