feat
parent
3eaa364f29
commit
286cbb496c
|
|
@ -125,6 +125,18 @@ export const QUAL_MONITOR_STATUS_OPTIONS = [
|
||||||
{ value: "person_rate", label: "人员比例预警" },
|
{ value: "person_rate", label: "人员比例预警" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/** 资质保持监控-业务范围专业能力配备标准 */
|
||||||
|
export const QUAL_MONITOR_STANDARD_ROWS = [
|
||||||
|
{ scope: "煤炭开采业", standard: "安全、机械、电气、采矿、通风、地质、矿建各 1 名及以上" },
|
||||||
|
{ scope: "金属、非金属矿及其他矿采选业", standard: "安全、机械、电气、采矿、通风、地质、水工结构各 1 名及以上" },
|
||||||
|
{ scope: "陆地石油和天然气开采业", standard: "安全、机械、电气、采油、储运各 1 名及以上" },
|
||||||
|
{ scope: "陆上油气管道运输业", standard: "油气储运 2 名及以上,设备、仪表、电气、防腐、安全各 1 名及以上" },
|
||||||
|
{ scope: "石油加工业,化学原料、化学品及医药制造业", standard: "化工工艺、化工机械、仪表自动化、电气、安全各 2 名及以上" },
|
||||||
|
{ scope: "烟花爆竹制造业和仓储业", standard: "火炸药(爆炸技术)、机械、电气、安全各 1 名及以上" },
|
||||||
|
{ scope: "金属冶炼", standard: "安全、机械、电气、冶金、有色金属各 1 名及以上" },
|
||||||
|
{ scope: "民用爆炸物品行业", standard: "火炸药(爆炸技术)10 名,机械、电气、安全各 2 名及以上" },
|
||||||
|
];
|
||||||
|
|
||||||
/** 证书类型选项 */
|
/** 证书类型选项 */
|
||||||
export const CERT_TYPE_OPTIONS = [
|
export const CERT_TYPE_OPTIONS = [
|
||||||
{ value: "registered_safety_engineer", label: "注册安全工程师" },
|
{ value: "registered_safety_engineer", label: "注册安全工程师" },
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import {
|
||||||
QUAL_MONITOR_STATUS_MAP,
|
QUAL_MONITOR_STATUS_MAP,
|
||||||
QUAL_MONITOR_CONDITION_ITEMS,
|
QUAL_MONITOR_CONDITION_ITEMS,
|
||||||
QUAL_MONITOR_STATUS_OPTIONS,
|
QUAL_MONITOR_STATUS_OPTIONS,
|
||||||
|
QUAL_MONITOR_STANDARD_ROWS,
|
||||||
} from "~/enumerate/constant";
|
} from "~/enumerate/constant";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
|
|
||||||
|
|
@ -112,6 +113,7 @@ const QualMonitor = (props) => {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [detailVisible, setDetailVisible] = useState(false);
|
const [detailVisible, setDetailVisible] = useState(false);
|
||||||
const [detailRecord, setDetailRecord] = useState(null);
|
const [detailRecord, setDetailRecord] = useState(null);
|
||||||
|
const [standardVisible, setStandardVisible] = useState(false);
|
||||||
const [data, setData] = useState([]);
|
const [data, setData] = useState([]);
|
||||||
|
|
||||||
const { qualReview, queryQualMonitorPage, queryQualMonitorCondition, queryQualMonitoringPageStatistics } = props;
|
const { qualReview, queryQualMonitorPage, queryQualMonitorCondition, queryQualMonitoringPageStatistics } = props;
|
||||||
|
|
@ -326,11 +328,7 @@ const QualMonitor = (props) => {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 资质条件来源说明 */}
|
|
||||||
<div className="source-note">
|
|
||||||
<strong>页面定位:</strong>
|
|
||||||
资质保持监控是监管信息看板,展示机构具备哪些资质、资质条件是否保持、每个结论来自哪些字段。系统命中异常后自动生成风险消息,发函、整改、机构反馈、复核闭环等办理流程全部在“风险预警中心”完成。
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 搜索表单 */}
|
{/* 搜索表单 */}
|
||||||
<SearchForm
|
<SearchForm
|
||||||
|
|
@ -371,6 +369,15 @@ const QualMonitor = (props) => {
|
||||||
onFinish={onFinish}
|
onFinish={onFinish}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div className="qm-toolbar">
|
||||||
|
<span className="qm-toolbar-hint">
|
||||||
|
机构列表:先看机构具备哪些资质/业务范围,再看各保持条件和来源字段。
|
||||||
|
</span>
|
||||||
|
<Button size="small" onClick={() => setStandardVisible(true)}>
|
||||||
|
检查口径
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* 数据表格 */}
|
{/* 数据表格 */}
|
||||||
<Table
|
<Table
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
|
|
@ -447,6 +454,32 @@ const QualMonitor = (props) => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
{/* 检查口径弹窗 */}
|
||||||
|
<Modal
|
||||||
|
title="资质条件检查口径"
|
||||||
|
open={standardVisible}
|
||||||
|
onCancel={() => setStandardVisible(false)}
|
||||||
|
width={760}
|
||||||
|
footer={
|
||||||
|
<Button onClick={() => setStandardVisible(false)}>关闭</Button>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="check-note">
|
||||||
|
<strong>资质保持条件:</strong>
|
||||||
|
监管端按独立法人、资产场所、人员数量及比例、负责人、制度、承诺书、网站、失信记录、属地要求和专业能力标准建立检查项。
|
||||||
|
</div>
|
||||||
|
<Table
|
||||||
|
rowKey="scope"
|
||||||
|
size="small"
|
||||||
|
pagination={false}
|
||||||
|
columns={[
|
||||||
|
{ title: "业务范围", dataIndex: "scope", width: 200 },
|
||||||
|
{ title: "专业能力配备标准", dataIndex: "standard" },
|
||||||
|
]}
|
||||||
|
dataSource={QUAL_MONITOR_STANDARD_ROWS}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,19 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 工具栏
|
||||||
|
.qm-toolbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.qm-toolbar-hint {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #64748b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 核查口径说明
|
// 核查口径说明
|
||||||
.check-note {
|
.check-note {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
|
|
|
||||||
|
|
@ -323,8 +323,8 @@ const EvalProjectCreate = (props) => {
|
||||||
rules={[{ required: true, message: "请选择是否法定项目" }]}
|
rules={[{ required: true, message: "请选择是否法定项目" }]}
|
||||||
>
|
>
|
||||||
<Radio.Group>
|
<Radio.Group>
|
||||||
<Radio value={true}>是</Radio>
|
<Radio value={true}>是,纳入监管端监管</Radio>
|
||||||
<Radio value={false}>否</Radio>
|
<Radio value={false}>否,仅机构内部管理</Radio>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,18 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Tag, Button, Card, Table, Select, Input, Flex, Typography, message, Popover, Image } from "antd";
|
import {
|
||||||
|
Tag,
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
Table,
|
||||||
|
Select,
|
||||||
|
Input,
|
||||||
|
Flex,
|
||||||
|
Typography,
|
||||||
|
message,
|
||||||
|
Popover,
|
||||||
|
Image,
|
||||||
|
Collapse,
|
||||||
|
} from "antd";
|
||||||
import { CheckCircleFilled } from "@ant-design/icons";
|
import { CheckCircleFilled } from "@ant-design/icons";
|
||||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
import { NS_SAFETY_EVAL_BUSINESS } from "~/enumerate/namespace";
|
import { NS_SAFETY_EVAL_BUSINESS } from "~/enumerate/namespace";
|
||||||
|
|
@ -23,18 +36,15 @@ const ControlContent = (props) => {
|
||||||
// 过程控制审核
|
// 过程控制审核
|
||||||
const [rows, setRows] = useState([]);
|
const [rows, setRows] = useState([]);
|
||||||
|
|
||||||
|
|
||||||
// 项目归档
|
// 项目归档
|
||||||
const [files, setFiles] = useState([]);
|
const [files, setFiles] = useState([]);
|
||||||
|
|
||||||
|
|
||||||
// 机构负责人签发
|
// 机构负责人签发
|
||||||
const [approvalOpinion, setApprovalOpinion] = useState("");
|
const [approvalOpinion, setApprovalOpinion] = useState("");
|
||||||
|
|
||||||
const fetchDetail = () => {
|
const fetchDetail = () => {
|
||||||
props.evalProcessControlDetail({ projectId }).then((res) => {
|
props.evalProcessControlDetail({ projectId }).then((res) => {
|
||||||
if (res?.success) {
|
if (res?.success) {
|
||||||
|
|
||||||
if (res?.data?.signTaskPersonCo) {
|
if (res?.data?.signTaskPersonCo) {
|
||||||
setSelectPeople({
|
setSelectPeople({
|
||||||
value: res?.data?.signTaskPersonCo?.signerPersonnelId,
|
value: res?.data?.signTaskPersonCo?.signerPersonnelId,
|
||||||
|
|
@ -68,7 +78,6 @@ const ControlContent = (props) => {
|
||||||
|
|
||||||
if (processControl?.opinionContent) {
|
if (processControl?.opinionContent) {
|
||||||
setApprovalOpinion(processControl.opinionContent);
|
setApprovalOpinion(processControl.opinionContent);
|
||||||
|
|
||||||
}
|
}
|
||||||
}, [processControlDetail]);
|
}, [processControlDetail]);
|
||||||
|
|
||||||
|
|
@ -89,13 +98,12 @@ const ControlContent = (props) => {
|
||||||
const isSignatureCompleted =
|
const isSignatureCompleted =
|
||||||
processControl?.reviewerSignatureTaskStatus === "completed";
|
processControl?.reviewerSignatureTaskStatus === "completed";
|
||||||
|
|
||||||
|
const canArchive = isSignatureCompleted;
|
||||||
const canArchive = isSignatureCompleted ;
|
|
||||||
|
|
||||||
// 过程控制签字提交(confirm)
|
// 过程控制签字提交(confirm)
|
||||||
const handleConfirm = async (resultCode) => {
|
const handleConfirm = async (resultCode) => {
|
||||||
if (!projectId) return;
|
if (!projectId) return;
|
||||||
if(!rows.every((r) => r.reviewConclusion)){
|
if (!rows.every((r) => r.reviewConclusion)) {
|
||||||
message.error("请填写所有核查项的结果");
|
message.error("请填写所有核查项的结果");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -202,7 +210,11 @@ const ControlContent = (props) => {
|
||||||
render: (val) => {
|
render: (val) => {
|
||||||
let files = [];
|
let files = [];
|
||||||
if (typeof val === "string") {
|
if (typeof val === "string") {
|
||||||
try { files = JSON.parse(val); } catch { files = []; }
|
try {
|
||||||
|
files = JSON.parse(val);
|
||||||
|
} catch {
|
||||||
|
files = [];
|
||||||
|
}
|
||||||
} else if (Array.isArray(val)) {
|
} else if (Array.isArray(val)) {
|
||||||
files = val;
|
files = val;
|
||||||
}
|
}
|
||||||
|
|
@ -212,17 +224,12 @@ const ControlContent = (props) => {
|
||||||
<Popover
|
<Popover
|
||||||
title="附件列表"
|
title="附件列表"
|
||||||
content={
|
content={
|
||||||
<Flex vertical gap={4} >
|
<Flex vertical gap={4}>
|
||||||
{files.map((f, i) => {
|
{files.map((f, i) => {
|
||||||
const url = f.url || f.response?.url;
|
const url = f.url || f.response?.url;
|
||||||
return isImage(f.name) ? (
|
return isImage(f.name) ? (
|
||||||
<Flex key={f.uid || i} align="center" gap={4}>
|
<Flex key={f.uid || i} align="center" gap={4}>
|
||||||
{(
|
{<Image src={url} width={80} />}
|
||||||
<Image
|
|
||||||
src={url}
|
|
||||||
width={80}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
) : (
|
) : (
|
||||||
<a
|
<a
|
||||||
|
|
@ -250,7 +257,6 @@ const ControlContent = (props) => {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const STEP_ITEMS = [
|
const STEP_ITEMS = [
|
||||||
|
|
@ -300,7 +306,45 @@ const ControlContent = (props) => {
|
||||||
pagination={false}
|
pagination={false}
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
|
<Collapse
|
||||||
|
|
||||||
|
style={{ marginTop: 12 }}
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
key: "checklist",
|
||||||
|
label: "过程控制完整核查清单(13项)",
|
||||||
|
children: (
|
||||||
|
<ol
|
||||||
|
style={{
|
||||||
|
margin: 0,
|
||||||
|
paddingLeft: 20,
|
||||||
|
fontSize: 13,
|
||||||
|
color: "#475569",
|
||||||
|
lineHeight: 1.8,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<li>合同签订前是否进行项目风险分析。</li>
|
||||||
|
<li>是否签订技术服务合同。</li>
|
||||||
|
<li>是否下达项目任务通知单。</li>
|
||||||
|
<li>是否有项目组成立和项目负责人任命记录。</li>
|
||||||
|
<li>是否编制项目实施计划。</li>
|
||||||
|
<li>现场检查记录是否完整、有效。</li>
|
||||||
|
<li>是否有书面整改通知单并由被评价单位盖章或签字确认。</li>
|
||||||
|
<li>
|
||||||
|
是否进行现场复查,复查单是否双方签名或盖章并注明日期。
|
||||||
|
</li>
|
||||||
|
<li>是否有现场勘查、整改复查影像资料。</li>
|
||||||
|
<li>是否完成内审、技审并保留审核记录、签字和日期。</li>
|
||||||
|
<li>委托方提供资料是否齐全并由被评价单位盖章。</li>
|
||||||
|
<li>
|
||||||
|
委托方资料、评价过程资料和评价报告存档是否符合要求。
|
||||||
|
</li>
|
||||||
|
<li>存档资料是否完整且具有可追溯性。</li>
|
||||||
|
</ol>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
<Flex justify="flex-end" gap={8} style={{ padding: "12px 0" }}>
|
<Flex justify="flex-end" gap={8} style={{ padding: "12px 0" }}>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
|
|
@ -435,7 +479,6 @@ const ControlContent = (props) => {
|
||||||
align="center"
|
align="center"
|
||||||
style={{ marginTop: 12, paddingBottom: 16 }}
|
style={{ marginTop: 12, paddingBottom: 16 }}
|
||||||
>
|
>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={handleArchive}
|
onClick={handleArchive}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue