Merge remote-tracking branch 'origin/dev' into dev
commit
149cc8811f
|
|
@ -12,9 +12,9 @@ module.exports = {
|
||||||
// 可通过环境变量覆盖: SAFETY_EVAL_API_HOST=http://192.168.x.x:8095
|
// 可通过环境变量覆盖: SAFETY_EVAL_API_HOST=http://192.168.x.x:8095
|
||||||
//API_HOST: "https://gbs-gateway.qhdsafety.com",
|
//API_HOST: "https://gbs-gateway.qhdsafety.com",
|
||||||
|
|
||||||
API_HOST: "http://192.168.0.152",
|
|
||||||
//API_HOST: "http://192.168.0.150", //太浅
|
|
||||||
//API_HOST: "http://192.168.0.152",
|
//API_HOST: "http://192.168.0.152",
|
||||||
|
//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: {
|
production: {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
|
|
||||||
|
|
||||||
export const identifyPartList = declareRequest(
|
|
||||||
"coursewareLoading",
|
|
||||||
"Post > @/risk/busIdentifyPart/list",
|
|
||||||
);
|
|
||||||
|
|
@ -123,3 +123,8 @@ export const queryOrgSelectList = declareRequest(
|
||||||
"Get > /safetyEval/org-info/select/list",
|
"Get > /safetyEval/org-info/select/list",
|
||||||
'orgSelectList: [] | res.data || []',
|
'orgSelectList: [] | res.data || []',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const fetchQualOnSiteReviewResultDetail = declareRequest(
|
||||||
|
"siteReviewResultLoading",
|
||||||
|
"Get > /safetyEval/qual-on-site-review/result-detail/{id}",
|
||||||
|
);
|
||||||
|
|
@ -78,3 +78,23 @@ export const evalProjectDocSave = declareRequest(
|
||||||
"evalProjectDocSaveLoading",
|
"evalProjectDocSaveLoading",
|
||||||
"Post > @/safetyEval/institution/eval-project-doc/save",
|
"Post > @/safetyEval/institution/eval-project-doc/save",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const evalProjectProgressStat = declareRequest(
|
||||||
|
"evalProjectProgressLoading",
|
||||||
|
"Get > /safetyEval/institution/eval-project/progress-stat",
|
||||||
|
);
|
||||||
|
|
||||||
|
export const evalProjectProgressPage = declareRequest(
|
||||||
|
"evalProjectProgressPageLoading",
|
||||||
|
"Get > /safetyEval/institution/eval-project/progress-page",
|
||||||
|
);
|
||||||
|
|
||||||
|
export const evalProjectRiskWarningStat = declareRequest(
|
||||||
|
"riskWarningStatLoading",
|
||||||
|
"Get > /safetyEval/institution/eval-project/risk-warning-stat",
|
||||||
|
);
|
||||||
|
|
||||||
|
export const evalProjectRiskWarningPage = declareRequest(
|
||||||
|
"riskWarningPageLoading",
|
||||||
|
"Get > /safetyEval/institution/eval-project/risk-warning-page",
|
||||||
|
);
|
||||||
|
|
@ -332,3 +332,23 @@ export const MATERIAL_TYPE_MAP = MATERIAL_TYPE_OPTIONS.reduce((acc, cur) => {
|
||||||
acc[cur.value] = cur.label;
|
acc[cur.value] = cur.label;
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
|
/** 风险预警 — 风险等级映射 */
|
||||||
|
export const RISK_LEVEL_MAP = {
|
||||||
|
HIGH: { color: "error", text: "高风险" },
|
||||||
|
MIDDLE: { color: "warning", text: "中风险" },
|
||||||
|
LOW: { color: "default", text: "低风险" },
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 风险预警 — 处理状态映射 */
|
||||||
|
export const RISK_STATUS_MAP = {
|
||||||
|
UNHANDLED: { color: "error", text: "未处理" },
|
||||||
|
PROCESSING: { color: "warning", text: "处理中" },
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 项目进度 — 进度状态映射 */
|
||||||
|
export const PROGRESS_STATUS_MAP = {
|
||||||
|
NORMAL: { color: "success", text: "正常" },
|
||||||
|
NEAR: { color: "warning", text: "项目临期" },
|
||||||
|
DELAY: { color: "error", text: "项目延期" },
|
||||||
|
};
|
||||||
|
|
@ -212,10 +212,20 @@ const menuItems = [
|
||||||
icon: <FileTextOutlined />,
|
icon: <FileTextOutlined />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "/safetyEval/container/SafetyEvalBusiness/EvalProject/ProjectDocLibrary",
|
key: "/safetyEval/container/SafetyEvalBusiness/ProjectDocLibrary",
|
||||||
label: "项目资料管理",
|
label: "项目资料管理",
|
||||||
icon: <FileTextOutlined />,
|
icon: <FileTextOutlined />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "/safetyEval/container/SafetyEvalBusiness/Progress",
|
||||||
|
label: "项目进度管理",
|
||||||
|
icon: <BarChartOutlined />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "/safetyEval/container/SafetyEvalBusiness/RiskWarning",
|
||||||
|
label: "风险预警管理",
|
||||||
|
icon: <ExperimentOutlined />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "/safetyEval/container/SafetyEvalBusiness/CustomerManage",
|
key: "/safetyEval/container/SafetyEvalBusiness/CustomerManage",
|
||||||
label: "安评客户管理",
|
label: "安评客户管理",
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ const SiteReviewNotice = (props) => {
|
||||||
updateQualOnSiteReview,
|
updateQualOnSiteReview,
|
||||||
uploadQualOnSiteReviewResult,
|
uploadQualOnSiteReviewResult,
|
||||||
fetchQualOnSiteReviewDetail,
|
fetchQualOnSiteReviewDetail,
|
||||||
|
fetchQualOnSiteReviewResultDetail,
|
||||||
queryOrgSelectList,
|
queryOrgSelectList,
|
||||||
resetModelState,
|
resetModelState,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
@ -145,8 +146,16 @@ const SiteReviewNotice = (props) => {
|
||||||
resultForm.setFieldsValue({
|
resultForm.setFieldsValue({
|
||||||
institution: record.unitName,
|
institution: record.unitName,
|
||||||
reviewDateStart: record.reviewDateStart,
|
reviewDateStart: record.reviewDateStart,
|
||||||
reviewLeader: record.reviewLeader || "",
|
});
|
||||||
reviewOpinion: record.reviewOpinion || "",
|
fetchQualOnSiteReviewResultDetail({ id: record.id }).then((res) => {
|
||||||
|
if (res?.success !== false && res?.data) {
|
||||||
|
const detail = res.data;
|
||||||
|
resultForm.setFieldsValue({
|
||||||
|
reviewLeader: detail.reviewLeader || "",
|
||||||
|
reviewResult: detail.reviewResult,
|
||||||
|
reviewOpinion: detail.reviewOpinion || "",
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
setResultModalOpen(true);
|
setResultModalOpen(true);
|
||||||
};
|
};
|
||||||
|
|
@ -210,9 +219,7 @@ const SiteReviewNotice = (props) => {
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div style={{ fontSize: 13, color: "#666", marginBottom: 16 }}>
|
|
||||||
向安全评价机构下发现场审查时间、地点和审查组安排,并接收审查结果文件。
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Row gutter={16} style={{ marginBottom: 16 }}>
|
<Row gutter={16} style={{ marginBottom: 16 }}>
|
||||||
<Col span={8}>
|
<Col span={8}>
|
||||||
|
|
|
||||||
|
|
@ -125,23 +125,28 @@ const CustomerManage = (props) => {
|
||||||
title: "确认删除",
|
title: "确认删除",
|
||||||
content: "确定要删除这个客户吗?",
|
content: "确定要删除这个客户吗?",
|
||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
await props.customerDelete({ data: record.id });
|
const res = await props.customerDelete({ data: record.id });
|
||||||
|
if (res?.success !== false) {
|
||||||
message.success("删除成功");
|
message.success("删除成功");
|
||||||
getData();
|
getData();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCreateSubmit = () => {
|
const handleCreateSubmit = () => {
|
||||||
modalForm.validateFields().then(async (values) => {
|
modalForm.validateFields().then(async (values) => {
|
||||||
|
let res;
|
||||||
if (editingId) {
|
if (editingId) {
|
||||||
await props.customerModify({ ...values, id: editingId });
|
res = await props.customerModify({ ...values, id: editingId });
|
||||||
} else {
|
} else {
|
||||||
await props.customerSave(values);
|
res = await props.customerSave(values);
|
||||||
}
|
}
|
||||||
|
if (res.success) {
|
||||||
message.success(editingId ? "修改成功" : "创建成功");
|
message.success(editingId ? "修改成功" : "创建成功");
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
getData();
|
getData();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -184,7 +189,7 @@ const CustomerManage = (props) => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: "操作",
|
||||||
width: 260,
|
width: 220,
|
||||||
fixed: "right",
|
fixed: "right",
|
||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
<Space>
|
<Space>
|
||||||
|
|
@ -335,8 +340,15 @@ const CustomerManage = (props) => {
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form.Item name="industryCode" label="所属行业">
|
<Form.Item
|
||||||
<Select placeholder="请选择" allowClear>
|
name="industryCode"
|
||||||
|
label="所属行业"
|
||||||
|
getValueFromEvent={(value) => value.join(",")}
|
||||||
|
getValueProps={(value) => ({
|
||||||
|
value: value ? value.split(",").filter(Boolean) : [],
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<Select mode="multiple" placeholder="请选择" allowClear>
|
||||||
{QUALIFICATION_INDUSTRY_OPTIONS.map((opt) => (
|
{QUALIFICATION_INDUSTRY_OPTIONS.map((opt) => (
|
||||||
<Select.Option key={opt.value} value={opt.value}>
|
<Select.Option key={opt.value} value={opt.value}>
|
||||||
{opt.label}
|
{opt.label}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import {tools} from "@cqsjjb/jjb-common-lib";
|
||||||
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
||||||
import { NS_SAFETY_EVAL_BUSINESS } from "~/enumerate/namespace";
|
import { NS_SAFETY_EVAL_BUSINESS } from "~/enumerate/namespace";
|
||||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
|
import { QUALIFICATION_INDUSTRY_OPTIONS } from "~/enumerate/enterpriseOptions";
|
||||||
import BaiduMapPicker from "~/components/BaiduMapPicker";
|
import BaiduMapPicker from "~/components/BaiduMapPicker";
|
||||||
import { district } from "~/enumerate/constant";
|
import { district } from "~/enumerate/constant";
|
||||||
import { phoneRule } from "~/utils/validators";
|
import { phoneRule } from "~/utils/validators";
|
||||||
|
|
@ -39,7 +40,11 @@ const EvalProjectCreate = (props) => {
|
||||||
const projectId = router.query?.id;
|
const projectId = router.query?.id;
|
||||||
const isView = projectId;
|
const isView = projectId;
|
||||||
|
|
||||||
const { evalProjectSaveLoading, evalProjectDetailLoading, customerPage: customerList } = props.safetyEvalBusiness;
|
const {
|
||||||
|
evalProjectSaveLoading,
|
||||||
|
evalProjectDetailLoading,
|
||||||
|
customerPage: customerList,
|
||||||
|
} = props.safetyEvalBusiness;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
props.customerPage({ current: 1, size: 999 });
|
props.customerPage({ current: 1, size: 999 });
|
||||||
|
|
@ -55,12 +60,18 @@ const EvalProjectCreate = (props) => {
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
...data,
|
...data,
|
||||||
planStartDate: data.planStartDate ? dayjs(data.planStartDate) : undefined,
|
planStartDate: data.planStartDate
|
||||||
|
? dayjs(data.planStartDate)
|
||||||
|
: undefined,
|
||||||
planEndDate: data.planEndDate ? dayjs(data.planEndDate) : undefined,
|
planEndDate: data.planEndDate ? dayjs(data.planEndDate) : undefined,
|
||||||
});
|
});
|
||||||
if (data.participants?.length) {
|
if (data.participants?.length) {
|
||||||
setSelectedParticipants(
|
setSelectedParticipants(
|
||||||
data.participants.map((p) => ({ id: p.id, userName: p.name, ...p })),
|
data.participants.map((p) => ({
|
||||||
|
id: p.id,
|
||||||
|
userName: p.name,
|
||||||
|
...p,
|
||||||
|
})),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -94,13 +105,12 @@ const EvalProjectCreate = (props) => {
|
||||||
};
|
};
|
||||||
if (isView) {
|
if (isView) {
|
||||||
params.id = projectId;
|
params.id = projectId;
|
||||||
await props.evalProjectSave(params);
|
|
||||||
message.success("修改成功");
|
|
||||||
} else {
|
|
||||||
await props.evalProjectSave(params);
|
|
||||||
message.success("创建成功");
|
|
||||||
}
|
}
|
||||||
|
const res = await props.evalProjectSave(params);
|
||||||
|
if (res?.success) {
|
||||||
|
message.success(isView ? "修改成功" : "创建成功");
|
||||||
props.history.goBack();
|
props.history.goBack();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -115,7 +125,8 @@ const EvalProjectCreate = (props) => {
|
||||||
history={props.history}
|
history={props.history}
|
||||||
previous
|
previous
|
||||||
footer={
|
footer={
|
||||||
!isView && <Flex gap={24}>
|
!isView && (
|
||||||
|
<Flex gap={24}>
|
||||||
<Button onClick={() => props.history.goBack()}>取消</Button>
|
<Button onClick={() => props.history.goBack()}>取消</Button>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
|
|
@ -125,6 +136,7 @@ const EvalProjectCreate = (props) => {
|
||||||
提交并返回项目列表
|
提交并返回项目列表
|
||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
loading={detailLoading}
|
loading={detailLoading}
|
||||||
>
|
>
|
||||||
|
|
@ -174,7 +186,9 @@ const EvalProjectCreate = (props) => {
|
||||||
showSearch
|
showSearch
|
||||||
optionFilterProp="label"
|
optionFilterProp="label"
|
||||||
onChange={(value, option) => {
|
onChange={(value, option) => {
|
||||||
const customer = customerList?.find((item) => item.id === value);
|
const customer = customerList?.find(
|
||||||
|
(item) => item.id === value,
|
||||||
|
);
|
||||||
console.log(customer);
|
console.log(customer);
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
customerContactName: customer?.principalName || "",
|
customerContactName: customer?.principalName || "",
|
||||||
|
|
@ -226,7 +240,7 @@ const EvalProjectCreate = (props) => {
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form.Item name="projectLeaderName" label="项目负责人">
|
<Form.Item name="projectLeaderName" label="项目负责人">
|
||||||
<Input placeholder="请输入" maxLength={50} />
|
<Input placeholder="请输入" maxLength={30} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
@ -241,6 +255,21 @@ const EvalProjectCreate = (props) => {
|
||||||
<DatePicker style={{ width: "100%" }} placeholder="请选择" />
|
<DatePicker style={{ width: "100%" }} placeholder="请选择" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item
|
||||||
|
name="industryCode"
|
||||||
|
label="所属行业"
|
||||||
|
|
||||||
|
>
|
||||||
|
<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>
|
</Row>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,9 +74,11 @@ const EvalProject = (props) => {
|
||||||
title: "确认删除",
|
title: "确认删除",
|
||||||
content: "确定要删除这个项目吗?",
|
content: "确定要删除这个项目吗?",
|
||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
await props.evalProjectDelete({ data: [record.id] });
|
const res = await props.evalProjectDelete({ data: [record.id] });
|
||||||
|
if (res?.success !== false) {
|
||||||
message.success("删除成功");
|
message.success("删除成功");
|
||||||
getData();
|
getData();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -107,7 +109,7 @@ const EvalProject = (props) => {
|
||||||
width: 100,
|
width: 100,
|
||||||
render: (phase) => {
|
render: (phase) => {
|
||||||
const color = phase === "延期" ? "error" : phase === "正常" ? "success" : undefined;
|
const color = phase === "延期" ? "error" : phase === "正常" ? "success" : undefined;
|
||||||
return <Tag color={color}>{phase || "-"}</Tag>;
|
return phase ? <Tag color={color}>{phase}</Tag> : "";
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,326 @@
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
Table,
|
||||||
|
Button,
|
||||||
|
Tag,
|
||||||
|
Modal,
|
||||||
|
Row,
|
||||||
|
Col,
|
||||||
|
Card,
|
||||||
|
Statistic,
|
||||||
|
Descriptions,
|
||||||
|
Steps,
|
||||||
|
Tooltip,
|
||||||
|
} from "antd";
|
||||||
|
import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
|
||||||
|
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
||||||
|
import SearchForm from "@cqsjjb/jjb-react-admin-component/SearchForm";
|
||||||
|
import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper";
|
||||||
|
import { NS_SAFETY_EVAL_BUSINESS } from "~/enumerate/namespace";
|
||||||
|
import { PROGRESS_STATUS_MAP } from "~/enumerate/constant";
|
||||||
|
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
|
import { tools } from "@cqsjjb/jjb-common-lib";
|
||||||
|
import "./index.less";
|
||||||
|
|
||||||
|
const { router } = tools;
|
||||||
|
|
||||||
|
const ProjectProgress = (props) => {
|
||||||
|
const [searchForm] = Form.useForm();
|
||||||
|
const [dataSource, setDataSource] = useState([]);
|
||||||
|
const [total, setTotal] = useState(0);
|
||||||
|
const [statData, setStatData] = useState({});
|
||||||
|
const [detailModalVisible, setDetailModalVisible] = useState(false);
|
||||||
|
const [currentRecord, setCurrentRecord] = useState(null);
|
||||||
|
|
||||||
|
const { evalProjectProgressPageLoading } = props.safetyEvalBusiness;
|
||||||
|
|
||||||
|
const getStat = async () => {
|
||||||
|
const res = await props.evalProjectProgressStat();
|
||||||
|
if (res?.success !== false) {
|
||||||
|
setStatData(res?.data || {});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getData = async () => {
|
||||||
|
const params = {
|
||||||
|
...router.query,
|
||||||
|
current: router.query.current || 1,
|
||||||
|
size: router.query.size || 10,
|
||||||
|
};
|
||||||
|
const res = await props.evalProjectProgressPage(params);
|
||||||
|
if (res?.success !== false) {
|
||||||
|
setDataSource(res?.data || []);
|
||||||
|
setTotal(res?.total || 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
searchForm.setFieldsValue(router.query);
|
||||||
|
getStat();
|
||||||
|
getData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleSearch = (values) => {
|
||||||
|
router.query = { ...router.query, ...values, current: 1, size: 10 };
|
||||||
|
getData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReset = (values) => {
|
||||||
|
searchForm.resetFields();
|
||||||
|
router.query = { ...values, current: 1, size: 10 };
|
||||||
|
getData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePageChange = (pagination) => {
|
||||||
|
router.query = {
|
||||||
|
...router.query,
|
||||||
|
current: pagination.current,
|
||||||
|
size: pagination.pageSize,
|
||||||
|
};
|
||||||
|
getData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleView = (record) => {
|
||||||
|
setCurrentRecord(record);
|
||||||
|
setDetailModalVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderProgressDots = (nodes) => {
|
||||||
|
if (!nodes || nodes.length === 0) return <span className="pp-progress-empty">暂无进度</span>;
|
||||||
|
const total = nodes.length;
|
||||||
|
const done = nodes.filter((n) => n.statusCode === 3).length;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="pp-progress-dots">
|
||||||
|
{nodes.map((node, idx) => {
|
||||||
|
const dotClass =
|
||||||
|
node.statusCode === 3 ? "pp-progress-dot-done" :
|
||||||
|
node.statusCode === 2 ? "pp-progress-dot-doing" :
|
||||||
|
node.statusCode === 4 ? "pp-progress-dot-error" :
|
||||||
|
"pp-progress-dot-wait";
|
||||||
|
return (
|
||||||
|
<Tooltip key={node.nodeCode || idx} title={`${node.nodeName}: ${node.statusName}`}>
|
||||||
|
<span className={`pp-progress-dot ${dotClass}`} />
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div className="pp-progress-text">
|
||||||
|
{done}/{total} · {Math.round((done / total) * 100)}%
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{ title: "项目编号", dataIndex: "projectNo", width: 100 },
|
||||||
|
{
|
||||||
|
title: "客户/项目",
|
||||||
|
width: 180,
|
||||||
|
render: (_, record) => (
|
||||||
|
<div>
|
||||||
|
<div className="pp-project-name">{record.projectName}</div>
|
||||||
|
<div className="pp-customer-name">{record.customerName}</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{ title: "评价类别", dataIndex: "evalTypeName", width: 110 },
|
||||||
|
{ title: "负责人", dataIndex: "projectLeaderName", width: 100, ellipsis: true },
|
||||||
|
{
|
||||||
|
title: "项目进度",
|
||||||
|
width: 240,
|
||||||
|
render: (_, record) => renderProgressDots(record.projectNode),
|
||||||
|
},
|
||||||
|
{ title: "项目结束日期", dataIndex: "planEndDate", width: 120 },
|
||||||
|
{
|
||||||
|
title: "项目状态",
|
||||||
|
dataIndex: "progressStatusCode",
|
||||||
|
width: 130,
|
||||||
|
render: (code, record) => {
|
||||||
|
const cfg = PROGRESS_STATUS_MAP[code];
|
||||||
|
const daysText =
|
||||||
|
record.remainingDays >= 0
|
||||||
|
? `剩余${record.remainingDays}天`
|
||||||
|
: `超期${Math.abs(record.remainingDays)}天`;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>{cfg ? <Tag color={cfg.color}>{cfg.text}-{daysText}</Tag> : <Tag>{code}</Tag>}</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "操作",
|
||||||
|
width: 80,
|
||||||
|
fixed: "right",
|
||||||
|
render: (_, record) => (
|
||||||
|
<Button type="link" size="small" onClick={() => handleView(record)}>
|
||||||
|
查看
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageLayout title="项目进度管理">
|
||||||
|
|
||||||
|
<Row gutter={16} className="pp-stat-row">
|
||||||
|
<Col span={6}>
|
||||||
|
<Card size="small">
|
||||||
|
<Statistic
|
||||||
|
title="项目总数"
|
||||||
|
value={statData.totalCount ?? "-"}
|
||||||
|
suffix={<span className="pp-stat-suffix">当前机构名下评价项目</span>}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card size="small">
|
||||||
|
<Statistic
|
||||||
|
title="正常项目"
|
||||||
|
value={statData.normalCount ?? "-"}
|
||||||
|
valueStyle={{ color: "#52c41a" }}
|
||||||
|
suffix={<span className="pp-stat-suffix">距项目结束日期超过3天</span>}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card size="small">
|
||||||
|
<Statistic
|
||||||
|
title="项目临期"
|
||||||
|
value={statData.nearExpiryCount ?? "-"}
|
||||||
|
valueStyle={{ color: "#faad14" }}
|
||||||
|
suffix={<span className="pp-stat-suffix">项目结束前3天自动提醒</span>}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card size="small">
|
||||||
|
<Statistic
|
||||||
|
title="项目延期"
|
||||||
|
value={statData.delayedCount ?? "-"}
|
||||||
|
valueStyle={{ color: "#ff4d4f" }}
|
||||||
|
suffix={<span className="pp-stat-suffix">已超过项目结束日期</span>}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<SearchForm
|
||||||
|
form={searchForm}
|
||||||
|
loading={false}
|
||||||
|
style={{ marginBottom: 16 }}
|
||||||
|
formLine={[
|
||||||
|
<Form.Item key="keyword" name="keyword">
|
||||||
|
<ControlWrapper.Input
|
||||||
|
label="项目名称/客户名称"
|
||||||
|
placeholder="项目名称/客户名称"
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
</Form.Item>,
|
||||||
|
<Form.Item key="progressStatus" name="progressStatus">
|
||||||
|
<ControlWrapper.Select
|
||||||
|
label="项目状态"
|
||||||
|
placeholder="全部"
|
||||||
|
allowClear
|
||||||
|
options={[
|
||||||
|
{ label: "正常", value: "NORMAL" },
|
||||||
|
{ label: "项目临期", value: "NEAR" },
|
||||||
|
{ label: "项目延期", value: "DELAY" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>,
|
||||||
|
]}
|
||||||
|
onFinish={handleSearch}
|
||||||
|
onReset={handleReset}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<Table
|
||||||
|
rowKey="id"
|
||||||
|
columns={columns}
|
||||||
|
dataSource={dataSource}
|
||||||
|
loading={evalProjectProgressPageLoading}
|
||||||
|
scroll={{ y: props.scrollY, x: 1100 }}
|
||||||
|
pagination={{
|
||||||
|
total,
|
||||||
|
current: router.query.current || 1,
|
||||||
|
pageSize: router.query.size || 10,
|
||||||
|
showSizeChanger: true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
showTotal: (total) => `共 ${total} 条`,
|
||||||
|
}}
|
||||||
|
onChange={handlePageChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
title="项目进度详情"
|
||||||
|
open={detailModalVisible}
|
||||||
|
onCancel={() => setDetailModalVisible(false)}
|
||||||
|
footer={null}
|
||||||
|
width={680}
|
||||||
|
destroyOnHide={true}
|
||||||
|
>
|
||||||
|
{currentRecord && (
|
||||||
|
<>
|
||||||
|
<Descriptions column={2} bordered size="small" className="pp-detail-desc">
|
||||||
|
<Descriptions.Item label="项目编号">{currentRecord.projectNo}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="项目名称">{currentRecord.projectName}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="客户名称">{currentRecord.customerName}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="客户负责人">{currentRecord.customerContactName}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="评价类型">{currentRecord.evalTypeName}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="项目负责人">{currentRecord.projectLeaderName}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="项目结束日期">{currentRecord.planEndDate}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="剩余天数">
|
||||||
|
<span
|
||||||
|
className={`pp-remaining-days ${
|
||||||
|
currentRecord.remainingDays < 0 ? "pp-remaining-danger" :
|
||||||
|
currentRecord.remainingDays <= 3 ? "pp-remaining-warn" :
|
||||||
|
"pp-remaining-normal"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{currentRecord.remainingDays >= 0 ? `${currentRecord.remainingDays}天` : `已超期${Math.abs(currentRecord.remainingDays)}天`}
|
||||||
|
</span>
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="项目状态" span={2}>
|
||||||
|
<Tag color={PROGRESS_STATUS_MAP[currentRecord.progressStatusCode]?.color}>
|
||||||
|
{currentRecord.progressStatusName}
|
||||||
|
</Tag>
|
||||||
|
</Descriptions.Item>
|
||||||
|
</Descriptions>
|
||||||
|
|
||||||
|
<div className="pp-node-title">项目节点进度</div>
|
||||||
|
<Steps
|
||||||
|
direction="vertical"
|
||||||
|
current={-1}
|
||||||
|
items={
|
||||||
|
currentRecord.projectNode?.map((node) => ({
|
||||||
|
title: node.nodeName,
|
||||||
|
status:
|
||||||
|
node.statusCode === 3
|
||||||
|
? "finish"
|
||||||
|
: node.statusCode === 2
|
||||||
|
? "process"
|
||||||
|
: node.statusCode === 4
|
||||||
|
? "error"
|
||||||
|
: "wait",
|
||||||
|
description: node.statusName,
|
||||||
|
})) || []
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Modal>
|
||||||
|
</PageLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Connect(
|
||||||
|
[NS_SAFETY_EVAL_BUSINESS],
|
||||||
|
true,
|
||||||
|
)(AntdTableFuncControl(ProjectProgress));
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
.pp {
|
||||||
|
// 统计卡片区域
|
||||||
|
&-stat-row {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-stat-suffix {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 进度圆点容器
|
||||||
|
&-progress-dots {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-progress-dot {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&-done { background: #52c41a; }
|
||||||
|
&-doing { background: #1677ff; }
|
||||||
|
&-error { background: #ff4d4f; }
|
||||||
|
&-wait { background: #e8e8e8; }
|
||||||
|
}
|
||||||
|
|
||||||
|
&-progress-text {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-progress-empty {
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 客户/项目列
|
||||||
|
&-project-name {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-customer-name {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 详情弹窗 - Descriptions 间距
|
||||||
|
&-detail-desc {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 剩余天数
|
||||||
|
&-remaining-days {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
&-remaining-normal { color: #52c41a; }
|
||||||
|
&-remaining-warn { color: #faad14; }
|
||||||
|
&-remaining-danger { color: #ff4d4f; }
|
||||||
|
|
||||||
|
// 节点进度标题
|
||||||
|
&-node-title {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -90,7 +90,7 @@ const ProjectDocLibrary = (props) => {
|
||||||
|
|
||||||
const handleUploadSubmit = async () => {
|
const handleUploadSubmit = async () => {
|
||||||
const values = await uploadForm.validateFields();
|
const values = await uploadForm.validateFields();
|
||||||
await props.evalProjectDocSave({
|
const res = await props.evalProjectDocSave({
|
||||||
projectId: values.projectId,
|
projectId: values.projectId,
|
||||||
projectDocUrl: values.file.map((item) => ({
|
projectDocUrl: values.file.map((item) => ({
|
||||||
project_doc_url: item.url,
|
project_doc_url: item.url,
|
||||||
|
|
@ -98,9 +98,11 @@ const ProjectDocLibrary = (props) => {
|
||||||
materialType: values.materialType,
|
materialType: values.materialType,
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
|
if (res?.success !== false) {
|
||||||
message.success("上传成功");
|
message.success("上传成功");
|
||||||
setUploadModalOpen(false);
|
setUploadModalOpen(false);
|
||||||
getData();
|
getData();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
|
|
@ -0,0 +1,336 @@
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
Table,
|
||||||
|
Button,
|
||||||
|
Tag,
|
||||||
|
Modal,
|
||||||
|
Row,
|
||||||
|
Col,
|
||||||
|
Card,
|
||||||
|
Statistic,
|
||||||
|
Space,
|
||||||
|
message,
|
||||||
|
} from "antd";
|
||||||
|
import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
|
||||||
|
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
||||||
|
import SearchForm from "@cqsjjb/jjb-react-admin-component/SearchForm";
|
||||||
|
import ControlWrapper from "@cqsjjb/jjb-react-admin-component/ControlWrapper";
|
||||||
|
import { NS_SAFETY_EVAL_BUSINESS } from "~/enumerate/namespace";
|
||||||
|
import { RISK_LEVEL_MAP, RISK_STATUS_MAP } from "~/enumerate/constant";
|
||||||
|
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
|
import { tools } from "@cqsjjb/jjb-common-lib";
|
||||||
|
import "./index.less";
|
||||||
|
|
||||||
|
const { router } = tools;
|
||||||
|
|
||||||
|
const RiskWarning = (props) => {
|
||||||
|
const [searchForm] = Form.useForm();
|
||||||
|
const [dataSource, setDataSource] = useState([]);
|
||||||
|
const [total, setTotal] = useState(0);
|
||||||
|
const [statData, setStatData] = useState({});
|
||||||
|
const [handleModalVisible, setHandleModalVisible] = useState(false);
|
||||||
|
const [currentRecord, setCurrentRecord] = useState(null);
|
||||||
|
|
||||||
|
const { riskWarningPageLoading } = props.safetyEvalBusiness;
|
||||||
|
|
||||||
|
const getStat = async () => {
|
||||||
|
const res = await props.evalProjectRiskWarningStat();
|
||||||
|
if (res?.success !== false) {
|
||||||
|
setStatData(res?.data || {});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getData = async () => {
|
||||||
|
const params = {
|
||||||
|
...router.query,
|
||||||
|
current: router.query.current || 1,
|
||||||
|
size: router.query.size || 10,
|
||||||
|
};
|
||||||
|
const res = await props.evalProjectRiskWarningPage(params);
|
||||||
|
if (res?.success !== false) {
|
||||||
|
setDataSource(res?.data || []);
|
||||||
|
setTotal(res?.total || 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
searchForm.setFieldsValue(router.query);
|
||||||
|
getStat();
|
||||||
|
getData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleSearch = (values) => {
|
||||||
|
router.query = { ...router.query, ...values, current: 1, size: 10 };
|
||||||
|
getData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReset = (values) => {
|
||||||
|
searchForm.resetFields();
|
||||||
|
router.query = { ...values, current: 1, size: 10 };
|
||||||
|
getData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePageChange = (pagination) => {
|
||||||
|
router.query = {
|
||||||
|
...router.query,
|
||||||
|
current: pagination.current,
|
||||||
|
size: pagination.pageSize,
|
||||||
|
};
|
||||||
|
getData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleProcess = (record) => {
|
||||||
|
setCurrentRecord(record);
|
||||||
|
setHandleModalVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCloseRisk = async (record) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "确认闭环",
|
||||||
|
content: `确定将"${record.projectName}"的风险标记为闭环吗?`,
|
||||||
|
onOk: async () => {
|
||||||
|
// TODO: 调用闭环接口
|
||||||
|
message.success("已闭环");
|
||||||
|
getData();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{ title: "项目编号", dataIndex: "projectNo", width: 130 },
|
||||||
|
{
|
||||||
|
title: "项目/客户",
|
||||||
|
width: 240,
|
||||||
|
render: (_, record) => (
|
||||||
|
<div>
|
||||||
|
<div className="rw-project-name">{record.projectName}</div>
|
||||||
|
<div className="rw-customer-name">{record.customerName}</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "风险等级",
|
||||||
|
dataIndex: "riskLevelCode",
|
||||||
|
width: 100,
|
||||||
|
render: (code) => {
|
||||||
|
const cfg = RISK_LEVEL_MAP[code];
|
||||||
|
return cfg ? <Tag color={cfg.color}>{cfg.text}</Tag> : <Tag>{code}</Tag>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ title: "预警类型", dataIndex: "warningTypeName", width: 100 },
|
||||||
|
{
|
||||||
|
title: "触发条件",
|
||||||
|
dataIndex: "triggerCondition",
|
||||||
|
ellipsis: true,
|
||||||
|
width: 260,
|
||||||
|
},
|
||||||
|
{ title: "责任人", dataIndex: "responsiblePerson", width: 90 },
|
||||||
|
{ title: "预警时间", dataIndex: "warningTime", width: 110 },
|
||||||
|
{
|
||||||
|
title: "状态",
|
||||||
|
dataIndex: "statusCode",
|
||||||
|
width: 90,
|
||||||
|
render: (code) => {
|
||||||
|
const cfg = RISK_STATUS_MAP[code];
|
||||||
|
return cfg ? <Tag color={cfg.color}>{cfg.text}</Tag> : <Tag>{code}</Tag>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "操作",
|
||||||
|
width: 130,
|
||||||
|
fixed: "right",
|
||||||
|
render: (_, record) => (
|
||||||
|
<Space>
|
||||||
|
<Button type="link" size="small" onClick={() => handleProcess(record)}>
|
||||||
|
处理
|
||||||
|
</Button>
|
||||||
|
<Button type="link" size="small" onClick={() => handleCloseRisk(record)}>
|
||||||
|
闭环
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageLayout title="风险预警管理">
|
||||||
|
<Row gutter={16} className="rw-stat-row">
|
||||||
|
<Col span={6}>
|
||||||
|
<Card size="small">
|
||||||
|
<Statistic
|
||||||
|
title="预警总数"
|
||||||
|
value={statData.totalCount ?? "-"}
|
||||||
|
suffix={<span className="rw-stat-suffix">来自项目过程控制与周期规则</span>}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card size="small">
|
||||||
|
<Statistic
|
||||||
|
title="高风险"
|
||||||
|
value={statData.highRiskCount ?? "-"}
|
||||||
|
valueStyle={{ color: "#ff4d4f" }}
|
||||||
|
suffix={<span className="rw-stat-suffix">延期、逾期、重大整改</span>}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card size="small">
|
||||||
|
<Statistic
|
||||||
|
title="处理中"
|
||||||
|
value={statData.processingCount ?? "-"}
|
||||||
|
valueStyle={{ color: "#faad14" }}
|
||||||
|
suffix={<span className="rw-stat-suffix">已分派但未闭环</span>}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card size="small">
|
||||||
|
<Statistic
|
||||||
|
title="本周新增"
|
||||||
|
value={statData.weekNewCount ?? "-"}
|
||||||
|
valueStyle={{ color: "#52c41a" }}
|
||||||
|
suffix={<span className="rw-stat-suffix">需在周例会确认</span>}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<SearchForm
|
||||||
|
form={searchForm}
|
||||||
|
loading={false}
|
||||||
|
style={{ marginBottom: 16 }}
|
||||||
|
formLine={[
|
||||||
|
<Form.Item key="projectOrCustomer" name="projectOrCustomer">
|
||||||
|
<ControlWrapper.Input
|
||||||
|
label="项目/客户"
|
||||||
|
placeholder="项目或客户名称"
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
</Form.Item>,
|
||||||
|
<Form.Item key="riskLevel" name="riskLevel">
|
||||||
|
<ControlWrapper.Select
|
||||||
|
label="风险等级"
|
||||||
|
placeholder="全部"
|
||||||
|
allowClear
|
||||||
|
options={[
|
||||||
|
{ label: "高风险", value: "HIGH" },
|
||||||
|
{ label: "中风险", value: "MIDDLE" },
|
||||||
|
{ label: "低风险", value: "LOW" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>,
|
||||||
|
<Form.Item key="warningType" name="warningType">
|
||||||
|
<ControlWrapper.Select
|
||||||
|
label="预警类型"
|
||||||
|
placeholder="全部"
|
||||||
|
allowClear
|
||||||
|
options={[
|
||||||
|
{ label: "进度风险", value: "PROGRESS" },
|
||||||
|
{ label: "周期风险", value: "CYCLE" },
|
||||||
|
{ label: "质量风险", value: "QUALITY" },
|
||||||
|
{ label: "人员风险", value: "PERSONNEL" },
|
||||||
|
{ label: "归档风险", value: "ARCHIVE" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>,
|
||||||
|
]}
|
||||||
|
onFinish={handleSearch}
|
||||||
|
onReset={handleReset}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 12,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span style={{ fontSize: 13, color: "#999" }}>
|
||||||
|
处理按钮会打开处置面板;标记闭环会直接更新行状态。
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Table
|
||||||
|
rowKey="id"
|
||||||
|
columns={columns}
|
||||||
|
dataSource={dataSource}
|
||||||
|
loading={riskWarningPageLoading}
|
||||||
|
scroll={{ y: props.scrollY, x: 1300 }}
|
||||||
|
pagination={{
|
||||||
|
total,
|
||||||
|
current: router.query.current || 1,
|
||||||
|
pageSize: router.query.size || 10,
|
||||||
|
showSizeChanger: true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
showTotal: (total) => `共 ${total} 条`,
|
||||||
|
}}
|
||||||
|
onChange={handlePageChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
title="风险处置"
|
||||||
|
open={handleModalVisible}
|
||||||
|
onCancel={() => setHandleModalVisible(false)}
|
||||||
|
footer={null}
|
||||||
|
width={600}
|
||||||
|
destroyOnHide={true}
|
||||||
|
>
|
||||||
|
{currentRecord && (
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
<strong>项目:</strong>
|
||||||
|
{currentRecord.projectName}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>风险等级:</strong>
|
||||||
|
<Tag color={RISK_LEVEL_MAP[currentRecord.riskLevelCode]?.color}>
|
||||||
|
{currentRecord.riskLevelName}
|
||||||
|
</Tag>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>预警类型:</strong>
|
||||||
|
{currentRecord.warningTypeName}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>触发条件:</strong>
|
||||||
|
{currentRecord.triggerCondition}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>责任人:</strong>
|
||||||
|
{currentRecord.responsiblePerson}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>预警时间:</strong>
|
||||||
|
{currentRecord.warningTime}
|
||||||
|
</p>
|
||||||
|
<div style={{ textAlign: "right", marginTop: 24 }}>
|
||||||
|
<Space>
|
||||||
|
<Button onClick={() => setHandleModalVisible(false)}>取消</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
message.success("处理完成");
|
||||||
|
setHandleModalVisible(false);
|
||||||
|
getData();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
确认处理
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Modal>
|
||||||
|
</PageLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Connect(
|
||||||
|
[NS_SAFETY_EVAL_BUSINESS],
|
||||||
|
true,
|
||||||
|
)(AntdTableFuncControl(RiskWarning));
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
.rw {
|
||||||
|
&-stat-row {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-stat-suffix {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-note {
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: #f6f8fa;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #555;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
border: 1px solid #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-project-name {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-customer-name {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue