dev_1.0.1
tangjie 2026-07-20 13:38:09 +08:00
parent dccacda5d8
commit 329d5613d3
3 changed files with 753 additions and 56 deletions

View File

@ -219,6 +219,11 @@ const menuItems = [
label: "A1 模块",
icon: <ExperimentOutlined />,
},
{
key: "/safetyEval/container/WpsEditor",
label: "报告编辑器",
icon: <FileTextOutlined />,
},
],
},
];

View File

@ -1,72 +1,753 @@
import React, { useState } from "react";
import { Tabs, Tag, Alert, Button, Card } from "antd";
import { ArrowLeftOutlined } from "@ant-design/icons";
import {
Tabs,
Tag,
Alert,
Button,
Card,
Row,
Col,
Table,
Statistic,
Form,
Input,
Select,
Radio,
DatePicker,
Steps,
Empty,
} from "antd";
import { ArrowLeftOutlined, EditOutlined } from "@ant-design/icons";
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
import WpsEditor from "~/pages/Container/WpsEditor";
const PROCESS_TABS = [
{ key: "risk", index: "01", label: "风险分析", state: "已完成", stateType: "success" },
{ key: "contract", index: "02", label: "业务合同", state: "已完成", stateType: "success" },
{ key: "team", index: "03", label: "项目组", state: "已完成", stateType: "success" },
{ key: "survey", index: "04", label: "现场踏勘", state: "已完成", stateType: "success" },
{ key: "report", index: "05", label: "报告编制", state: "编制中", stateType: "processing" },
{ key: "internal", index: "06", label: "内部审核", state: "待办理", stateType: "default" },
{ key: "technical", index: "07", label: "技术审核", state: "待办理", stateType: "default" },
{ key: "control", index: "08", label: "过程控制", state: "前置未完成", stateType: "warning", locked: true },
{
key: "risk",
index: "01",
label: "风险分析",
state: "已完成",
stateType: "success",
role: "市场部经办人 / 市场部经理",
},
{
key: "contract",
index: "02",
label: "业务合同",
state: "已完成",
stateType: "success",
role: "机构管理员 / 项目负责人",
},
{
key: "team",
index: "03",
label: "项目组",
state: "已完成",
stateType: "success",
role: "评价部经理 / 机构主账号",
},
{
key: "survey",
index: "04",
label: "现场踏勘",
state: "已完成",
stateType: "success",
role: "项目组成员",
},
{
key: "report",
index: "05",
label: "报告编制",
state: "编制中",
stateType: "processing",
role: "报告编制人",
},
{
key: "internal",
index: "06",
label: "内部审核",
state: "待办理",
stateType: "default",
role: "内部审核人",
},
{
key: "technical",
index: "07",
label: "技术审核",
state: "待办理",
stateType: "default",
role: "技术负责人",
},
{
key: "control",
index: "08",
label: "过程控制",
state: "前置未完成",
stateType: "warning",
role: "过程控制负责人",
locked: true,
},
];
const { TextArea } = Input;
const RiskAnalysisContent = () => {
const [form] = Form.useForm();
return (
<div>
<div style={{ marginBottom: 12 }}>
<Tag color="blue" style={{ marginRight: 8 }}>
市场部经办人 / 市场部经理
</Tag>
<span style={{ color: "#666", fontSize: 13 }}>
市场部组织前置条件调查和风险分析相关职能部门参与市场部经理依据分析结果决定是否签订技术服务合同
</span>
</div>
<Card
title="安全评价风险分析记录表受控编号QAPJ-CX-1-JL01"
styles={{ header: { textAlign: "center" } }}
>
<Form
form={form}
layout="vertical"
initialValues={{
projectName: "华安化工园区安全预评价",
evalType: "安全预评价",
industry: "危险化学品",
scope: "华安化工园区建设项目及配套生产装置、公用工程、安全设施。",
inScope: "yes",
overview:
"重庆华安安全科技有限公司拟建设化工园区配套项目,项目位于重庆市渝北区。评价范围包括主要生产装置、储存设施、公用工程及配套安全设施,周边环境和外部安全防护距离需进一步核查。",
hazard:
"火灾、爆炸、中毒和窒息、化学灼伤、触电、机械伤害、车辆伤害、高处坠落等。",
staffQualified: "yes",
needExpert: "no",
ability: "yes",
feasible: "yes",
economic: "yes",
riskLevel: "middle",
contract: "sign",
participants: [
{ name: "张建国", dept: "市场部", opinion: "同意承接,按中度风险组织评价。" },
{ name: "李明华", dept: "评价部", opinion: "人员专业和评价周期能够满足要求。" },
],
}}
>
<Row gutter={16}>
<Col span={12}>
<Form.Item label="风险分析时间" name="analysisDate">
<DatePicker style={{ width: "100%" }} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="评价项目名称" name="projectName">
<Input />
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={12}>
<Form.Item label="评价类别" name="evalType">
<Select>
<Select.Option value="安全预评价">安全预评价</Select.Option>
<Select.Option value="安全验收评价">
安全验收评价
</Select.Option>
<Select.Option value="安全现状评价">
安全现状评价
</Select.Option>
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="所属行业" name="industry">
<Input placeholder="请输入项目所属行业" />
</Form.Item>
</Col>
</Row>
<Form.Item label="评价范围" name="scope">
<TextArea
rows={2}
placeholder="明确本项目安全评价对象、装置、区域及委托范围"
/>
</Form.Item>
<Form.Item label="是否在公司资质业务范围内" name="inScope">
<Radio.Group>
<Radio value="yes"></Radio>
<Radio value="no"></Radio>
</Radio.Group>
</Form.Item>
<Card
type="inner"
size="small"
title="一、被评价单位基本概况"
style={{ marginBottom: 16 }}
>
<Form.Item name="overview">
<TextArea
rows={4}
placeholder="填写项目简介、投资规模、地理位置、周边环境、主要设施及客户要求"
/>
</Form.Item>
</Card>
<Card
type="inner"
size="small"
title="二、项目行业风险特性分析"
style={{ marginBottom: 16 }}
>
<Form.Item name="hazard">
<TextArea
rows={3}
placeholder="分析项目所属行业的主要危险、有害因素"
/>
</Form.Item>
<div style={{ fontSize: 12, color: "#1677ff" }}>
应结合项目行业特点地理位置周边环境和评价类别填写非常规项目应通过风险分析会议形成记录
</div>
</Card>
<Card
type="inner"
size="small"
title="三、评价机构符合情况"
style={{ marginBottom: 16 }}
>
<Form.Item
label="1评价人员专业构成是否满足该项目的评价需求"
name="staffQualified"
>
<Radio.Group>
<Radio value="yes">满足</Radio>
<Radio value="no">不满足</Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="2是否需要聘请相关技术专家" name="needExpert">
<Radio.Group>
<Radio value="no">不需要</Radio>
<Radio value="yes">需要</Radio>
</Radio.Group>
</Form.Item>
<Form.Item
label="3是否有能力承担该项目的评价风险"
name="ability"
>
<Radio.Group>
<Radio value="yes"></Radio>
<Radio value="no"></Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="4项目的可行性分析" name="feasible">
<Radio.Group>
<Radio value="yes">可行</Radio>
<Radio value="no">不可行</Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="5项目的经济性分析" name="economic">
<Radio.Group>
<Radio value="yes">有经济效益</Radio>
<Radio value="no">无经济效益</Radio>
</Radio.Group>
</Form.Item>
</Card>
<Card
type="inner"
size="small"
title="风险分析结论"
style={{ marginBottom: 16 }}
>
<Form.Item label="风险程度" name="riskLevel">
<Radio.Group>
<Radio value="low">低度</Radio>
<Radio value="middle">中度</Radio>
<Radio value="high">高度</Radio>
</Radio.Group>
</Form.Item>
<div
style={{
fontSize: 12,
color: "#666",
marginTop: -12,
marginBottom: 12,
}}
>
中度化工金属非金属矿山金属冶炼陆地油气开采等行业评价项目
</div>
<Form.Item label="合同签订" name="contract">
<Radio.Group>
<Radio value="sign">签合同</Radio>
<Radio value="reject">不签合同</Radio>
</Radio.Group>
</Form.Item>
<div style={{ fontSize: 12, color: "#1677ff" }}>
系统建议当前条件具备签约基础最终结论由市场部经理批准
</div>
</Card>
<Card
type="inner"
size="small"
title="参与风险分析人员签字"
style={{ marginBottom: 16 }}
>
<Form.List name="participants">
{(fields, { add, remove }) => (
<>
<Table
dataSource={fields}
columns={[
{
title: "姓名", dataIndex: "name",
render: (_, field) => (
<Form.Item {...field} name={[field.name, "name"]} noStyle>
<Input placeholder="姓名" />
</Form.Item>
),
},
{
title: "部门/岗位", dataIndex: "dept",
render: (_, field) => (
<Form.Item {...field} name={[field.name, "dept"]} noStyle>
<Input placeholder="部门/岗位" />
</Form.Item>
),
},
{
title: "分析意见", dataIndex: "opinion",
render: (_, field) => (
<Form.Item {...field} name={[field.name, "opinion"]} noStyle>
<Input placeholder="填写分析意见" />
</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 }} onClick={() => add({ name: "", dept: "", opinion: "" })}>
添加参与人员
</Button>
</>
)}
</Form.List>
</Card>
</Form>
<div style={{ marginTop: 16, display: "flex", gap: 8 }}>
<Button>暂存</Button>
<Button>打印记录表</Button>
<Button type="primary">完成分析并保存</Button>
</div>
</Card>
<Card title="管理办法判定提示" size="small" style={{ marginTop: 16 }}>
<Row gutter={16}>
<Col span={8}>
<Card size="small" type="inner" style={{ borderColor: "#52c41a" }}>
<div>
<strong>低度风险</strong>
</div>
<div style={{ fontSize: 12, color: "#666" }}>
小型露天采石场加油站以及机构熟悉且开展过类似评价工作的常规项目
</div>
</Card>
</Col>
<Col span={8}>
<Card size="small" type="inner" style={{ borderColor: "#faad14" }}>
<div>
<strong>中度风险</strong>
</div>
<div style={{ fontSize: 12, color: "#666" }}>
化工生产金属非金属矿山金属冶炼陆地石油和天然气开采行业的评价项目
</div>
</Card>
</Col>
<Col span={8}>
<Card size="small" type="inner" style={{ borderColor: "#ff4d4f" }}>
<div>
<strong>高度风险</strong>
</div>
<div style={{ fontSize: 12, color: "#666" }}>
机构未开展过的非常规项目原则上组织专项风险分析会议必要时总经理参加
</div>
</Card>
</Col>
</Row>
<div style={{ marginTop: 8, fontSize: 12, color: "#666" }}>
<strong>不签合同重点条件</strong>
超出资质范围无法提供合法有效资料客户提出违法或不合理要求经济性达不到预期评价时间不能满足机构与被评价对象存在投资咨询设计监理物资供应等利益关系
</div>
</Card>
</div>
);
};
const ContractContent = () => (
<Card title="项目合同信息">
<Descriptions bordered column={2}>
<Descriptions.Item label="机构名称">
重庆市安全生产科学研究有限公司
</Descriptions.Item>
<Descriptions.Item label="合同编号">
HT00000000000000000001
</Descriptions.Item>
<Descriptions.Item label="项目名称" span={3}>
重庆市安全生产科学研究有限公司工程项目安全预评价
</Descriptions.Item>
<Descriptions.Item label="项目简介" span={3}>
项目简介
</Descriptions.Item>
<Descriptions.Item label="合同金额(万元)">15.00</Descriptions.Item>
<Descriptions.Item label="签订日期">2026-03-05</Descriptions.Item>
<Descriptions.Item label="合同扫描件" span={3}>
已上传 PDF
</Descriptions.Item>
</Descriptions>
<div style={{ marginTop: 16 }}>
<Button type="primary">保存合同</Button>
<Button style={{ marginLeft: 8 }}>上传合同扫描件</Button>
</div>
</Card>
);
const TeamContent = () => (
<Card title="项目组成立">
<Row gutter={16} style={{ marginBottom: 16 }}>
<Col span={6}>
<Statistic title="已配置人员" value="5" />
</Col>
<Col span={6}>
<Statistic title="已覆盖角色" value="5 / 11" />
</Col>
<Col span={6}>
<Statistic
title="项目负责人"
value="已配置"
valueStyle={{ color: "#52c41a" }}
/>
</Col>
<Col span={6}>
<Statistic
title="过程控制负责人"
value="待配置"
valueStyle={{ color: "#faad14" }}
/>
</Col>
</Row>
<Table
dataSource={[
{
id: 1,
name: "张建国",
dept: "评价一部",
role: "项目负责人",
qualification: "一级评价师/化工",
check: "通过",
duty: "制定实施计划并组织启动、初勘、检查表、现场勘查、整改复查及报告编制",
},
{
id: 2,
name: "李明华",
dept: "评价一部",
role: "报告编制人",
qualification: "二级评价师/安全",
check: "通过",
duty: "整合各专业内容形成报告初稿",
},
]}
columns={[
{ title: "姓名", dataIndex: "name" },
{ title: "部门/岗位", dataIndex: "dept" },
{ title: "项目角色", dataIndex: "role" },
{ title: "资质与专业", dataIndex: "qualification" },
{ title: "配置校验", dataIndex: "check" },
{ title: "主要职责", dataIndex: "duty", ellipsis: true },
]}
rowKey="id"
pagination={false}
/>
<div style={{ marginTop: 16 }}>
<Button type="primary"> 添加人员与角色</Button>
<Button style={{ marginLeft: 8 }}>生成项目组任命文件</Button>
<Button style={{ marginLeft: 8 }} type="primary">
确认项目组
</Button>
</div>
</Card>
);
const SurveyContent = () => (
<Card title="现场踏勘">
<Steps current={5} size="small" style={{ marginBottom: 24 }}>
<Steps.Step title="从业告知" description="已完成" />
<Steps.Step title="现场勘查" description="已完成" />
<Steps.Step title="整改通知" description="已完成" />
<Steps.Step title="企业整改" description="已完成" />
<Steps.Step title="整改复查" description="已完成" />
</Steps>
<Descriptions bordered column={2}>
<Descriptions.Item label="现场人员打卡" span={3}>
至少2名项目组专职人员完成有效签到签退
</Descriptions.Item>
<Descriptions.Item label="影像留痕" span={3}>
厂区入口生产装置区末次会议等关键影像已上传
</Descriptions.Item>
<Descriptions.Item label="检查表" span={3}>
现场检查表已上传
</Descriptions.Item>
<Descriptions.Item label="整改复查" span={3}>
整改通知和复查单双方已签字
</Descriptions.Item>
</Descriptions>
</Card>
);
const ReportContent = ({ onEdit }) => (
<Card
title="报告编制"
extra={
<Button type="primary" icon={<EditOutlined />} onClick={onEdit}>
打开报告编辑器
</Button>
}
>
<Descriptions bordered column={2}>
<Descriptions.Item label="当前模板">
安全预评价报告AQ 8001 / AQ 8002 · V3.2
</Descriptions.Item>
<Descriptions.Item label="模板依据">
AQ 8001-2007 / AQ 8002-2007
</Descriptions.Item>
<Descriptions.Item label="报告状态">编制中</Descriptions.Item>
<Descriptions.Item label="编制人">李明华</Descriptions.Item>
<Descriptions.Item label="草稿版本" span={3}>
V1.3
</Descriptions.Item>
<Descriptions.Item label="自动保存" span={3}>
已开启最近保存于 18:52
</Descriptions.Item>
</Descriptions>
</Card>
);
const InternalReviewContent = () => (
<Card title="内部审核">
<Descriptions bordered column={2}>
<Descriptions.Item label="审核版本">V1.3</Descriptions.Item>
<Descriptions.Item label="内审人">王丽萍</Descriptions.Item>
<Descriptions.Item label="审核项">7</Descriptions.Item>
<Descriptions.Item label="待修改">2</Descriptions.Item>
</Descriptions>
<Table
dataSource={[
{
id: 1,
dim: "评价依据",
focus: "充分、有效",
result: "符合",
opinion: "补充地方标准有效版本",
feedback: "已验证",
},
{
id: 2,
dim: "危险辨识",
focus: "全面、无遗漏",
result: "需修改",
opinion: "补充液氨装卸泄漏场景",
feedback: "待反馈",
},
]}
columns={[
{ title: "审核维度", dataIndex: "dim" },
{ title: "审核重点", dataIndex: "focus" },
{ title: "结论", dataIndex: "result" },
{ title: "审核意见", dataIndex: "opinion" },
{ title: "修改反馈", dataIndex: "feedback" },
]}
rowKey="id"
pagination={false}
/>
</Card>
);
const TechnicalReviewContent = () => (
<Card title="技术审核">
<Descriptions bordered column={2}>
<Descriptions.Item label="审核版本">V1.4</Descriptions.Item>
<Descriptions.Item label="技术负责人">陈志强</Descriptions.Item>
<Descriptions.Item label="专业匹配">化工安全</Descriptions.Item>
<Descriptions.Item label="备案校验">有效</Descriptions.Item>
</Descriptions>
<Table
dataSource={[
{
id: 1,
dim: "资料有效性",
focus: "现场资料和检测报告齐全有效",
result: "符合",
opinion: "资料有效",
},
{
id: 2,
dim: "危险辨识",
focus: "辨识充分、规律准确",
result: "符合",
opinion: "辨识充分",
},
{
id: 3,
dim: "评价方法",
focus: "选型合理、计算正确",
result: "需修改",
opinion: "补充事故模拟参数来源",
},
]}
columns={[
{ title: "审核维度", dataIndex: "dim" },
{ title: "技术审核重点", dataIndex: "focus" },
{ title: "结论", dataIndex: "result" },
{ title: "技术意见", dataIndex: "opinion" },
]}
rowKey="id"
pagination={false}
/>
</Card>
);
const ControlContent = () => (
<Card title="过程控制审核与归档">
<Empty description="过程控制审核须校验前7个节点全部完成并形成有效签字记录后才可办理" />
<Table
dataSource={[
{
id: 1,
item: "风险分析",
content: "合同前完成并审批签字",
result: "完整",
},
{
id: 2,
item: "项目实施计划",
content: "人员、进度、设备和分工",
result: "完整",
},
{
id: 3,
item: "从业告知与现场",
content: "告知盖章件、打卡、检查表、整改复查",
result: "完整",
},
{
id: 4,
item: "审核签字",
content: "内审、技审修改闭环及独立签字",
result: "待技审",
},
]}
columns={[
{ title: "程序审核项", dataIndex: "item" },
{ title: "核查内容", dataIndex: "content" },
{ title: "结果", dataIndex: "result" },
]}
rowKey="id"
pagination={false}
/>
</Card>
);
const ProjectFlow = (props) => {
const [activeKey, setActiveKey] = useState("risk");
const [visible, setVisible] = useState(false);
const tabItems = PROCESS_TABS.map((item) => ({
key: item.key,
disabled: item.locked,
label: (
<span>
{item.index} {item.label}
<Tag color={item.stateType} style={{ marginLeft: 8 }}>{item.state}</Tag>
</span>
),
children: (
<Card>
<div style={{ minHeight: 240, textAlign: "center", color: "#999", paddingTop: 80 }}>
{item.index} {item.label} 子流程页面
</div>
</Card>
),
}));
const handleTabChange = (key) => {
if (key === "report") {
setVisible(true);
return;
}
setActiveKey(key);
};
const tabItems = PROCESS_TABS.map((item) => {
let children = null;
switch (item.key) {
case "risk":
children = <RiskAnalysisContent />;
break;
case "contract":
children = <ContractContent />;
break;
case "team":
children = <TeamContent />;
break;
case "survey":
children = <SurveyContent />;
break;
case "report":
children = <ReportContent onEdit={() => setVisible(true)} />;
break;
case "internal":
children = <InternalReviewContent />;
break;
case "technical":
children = <TechnicalReviewContent />;
break;
case "control":
children = <ControlContent />;
break;
default:
children = <Card>{item.label} 子流程页面</Card>;
}
return {
key: item.key,
disabled: item.locked,
label: (
<span>
{item.index} {item.label}
<Tag color={item.stateType} style={{ marginLeft: 8 }}>
{item.state}
</Tag>
</span>
),
children,
};
});
return (
<PageLayout
title={
<span>
<Button
type="link"
icon={<ArrowLeftOutlined />}
onClick={() => props.history.push("MyProject")}
style={{ paddingLeft: 0 }}
>
返回
</Button>
项目法定流程工作台
</span>
<div>
<span>项目法定流程工作台</span>
<div className="pageLayout-extra">
华安化工园区安全预评价 | XP-2026-001
</div>
</div>
}
extra={<Tag color="blue">全量项目管理</Tag>}
>
<div style={{ marginBottom: 16, color: "#666" }}>
华安化工园区安全预评价 | XP-2026-001
</div>
<Alert
type="info"
showIcon
message="本工作台仅展示8个法定子流程不重复展示新增项目时填写的基本信息。各子流程均为独立页面过程控制审核须校验前7个节点全部完成并形成有效签字记录后才可办理。"
style={{ marginBottom: 16 }}
/>
<Tabs activeKey={activeKey} onChange={setActiveKey} items={tabItems} />
<Tabs activeKey={activeKey} onChange={handleTabChange} items={tabItems} />
{visible && <WpsEditor onCancel={() => setVisible(false)} />}
</PageLayout>
);
};
export default AntdTableFuncControl(ProjectFlow);
export default AntdTableFuncControl(ProjectFlow);

View File

@ -1,11 +1,13 @@
import { useState, useEffect } from "react";
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
import { Flex, Button, Tabs, Input, Tag, Progress, Typography } from "antd";
import { ArrowLeftOutlined } from "@ant-design/icons";
import WebOfficeSDK from "~/web-office-sdk-solution-v2.0.7/web-office-sdk-solution-v2.0.7.es.js";
import { createPortal } from "react-dom";
import "./index.less";
const App = () => {
const App = (props) => {
const { onCancel } = props;
const [expandedMap, setExpandedMap] = useState({});
const toggleExpand = (index) => {
@ -29,7 +31,15 @@ const App = () => {
return (
<div className="WpsEditor-container">
<PageLayout
title="测试"
title={
<Flex align="center" gap={8}>
<ArrowLeftOutlined onClick={() => {
console.log("点击了返回按钮");
onCancel()
}} />
<span>安全评价报告编制</span>
</Flex>
}
extra={
<Flex gap={12}>
<Button>保存</Button>
@ -171,6 +181,7 @@ const App = () => {
);
};
export default function WpsEditor() {
return createPortal(<App />, document.body);
export default function WpsEditor(props) {
return createPortal(<App {...props} />, document.body);
}