diff --git a/src/api/safetyEvalBusiness/index.js b/src/api/safetyEvalBusiness/index.js index 417c2a5..2b9ab08 100644 --- a/src/api/safetyEvalBusiness/index.js +++ b/src/api/safetyEvalBusiness/index.js @@ -133,4 +133,16 @@ export const evalProjectMemberPage = declareRequest( export const evalProjectMemberSave = declareRequest( "memberSaveLoading", "Post > @/safetyEval/institution/eval-project-member/save", +); + +// ===== 项目预警(安评业务提醒) ===== + +export const projectWaringStat = declareRequest( + "projectWaringStatLoading", + "Get > /safetyEval/project-waring/stat", +); + +export const projectWaringRemindPage = declareRequest( + "projectWaringRemindPageLoading", + "Get > /safetyEval/project-waring/remind-page", ); \ No newline at end of file diff --git a/src/enumerate/constant/index.js b/src/enumerate/constant/index.js index 8e59e2e..3f063d7 100644 --- a/src/enumerate/constant/index.js +++ b/src/enumerate/constant/index.js @@ -351,4 +351,22 @@ export const PROGRESS_STATUS_MAP = { NORMAL: { color: "success", text: "正常" }, NEAR: { color: "warning", text: "项目临期" }, DELAY: { color: "error", text: "项目延期" }, -}; \ No newline at end of file +}; + +/** 安评业务提醒 — 提醒等级映射 */ +export const WARING_STATUS_MAP = { + first: { color: "success", text: "首次预警" }, + second: { color: "warning", text: "二次提醒" }, + urgent: { color: "error", text: "紧急预警" }, + overdue: { color: "default", text: "已逾期" }, + normal: { color: "default", text: "正常" }, +}; + +/** 安评业务提醒 — 提醒等级筛选选项 */ +export const WARING_STATUS_OPTIONS = [ + { label: "首次预警(6个月)", value: "first" }, + { label: "二次提醒(3个月)", value: "second" }, + { label: "紧急预警(1个月)", value: "urgent" }, + { label: "已逾期", value: "overdue" }, + { label: "正常", value: "normal" }, +]; \ No newline at end of file diff --git a/src/pages/Container/Layout/menuConfig.js b/src/pages/Container/Layout/menuConfig.js index 221b8bc..9056f92 100644 --- a/src/pages/Container/Layout/menuConfig.js +++ b/src/pages/Container/Layout/menuConfig.js @@ -21,6 +21,7 @@ import { FormOutlined, CheckCircleOutlined, SyncOutlined, + BellOutlined, } from "@ant-design/icons"; const menuItems = [ @@ -236,6 +237,11 @@ const menuItems = [ label: "安评客户管理", icon: , }, + { + key: "/safetyEval/container/SafetyEvalBusiness/BusinessReminder", + label: "安评业务提醒", + icon: , + }, ], }, { diff --git a/src/pages/Container/SafetyEvalBusiness/BusinessReminder/index.js b/src/pages/Container/SafetyEvalBusiness/BusinessReminder/index.js new file mode 100644 index 0000000..0014d0b --- /dev/null +++ b/src/pages/Container/SafetyEvalBusiness/BusinessReminder/index.js @@ -0,0 +1,258 @@ +import React, { useState, useEffect } from "react"; +import { + Form, + Table, + Button, + Tag, + Row, + Col, + Card, + Statistic, + Space, +} 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 { WARING_STATUS_MAP, WARING_STATUS_OPTIONS } from "~/enumerate/constant"; +import { Connect } from "@cqsjjb/jjb-dva-runtime"; +import { tools } from "@cqsjjb/jjb-common-lib"; +import "./index.less"; + +const { router } = tools; + +const INDUSTRY_OPTIONS = [ + { label: "危险化学品", value: "DANGEROUS_CHEMICAL" }, + { label: "非煤矿山", value: "NON_COAL_MINE" }, + { label: "城镇燃气", value: "URBAN_GAS" }, + { label: "一般工贸", value: "GENERAL_TRADE" }, +]; + +const BusinessReminder = (props) => { + const [searchForm] = Form.useForm(); + const [dataSource, setDataSource] = useState([]); + const [total, setTotal] = useState(0); + const [statData, setStatData] = useState({}); + + const { projectWaringRemindPageLoading } = props.safetyEvalBusiness; + + const getStat = async () => { + const res = await props.projectWaringStat(); + 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.projectWaringRemindPage(params); + if (res?.success !== false) { + setDataSource(res?.data || []); + setTotal(res?.totalCount || 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 handleViewCustomer = (record) => { + // TODO: 查看企业资料 + }; + + const formatCycle = (days) => { + if (!days) return "-"; + const years = days / 365; + if (years >= 1) { + return Number.isInteger(years) ? `${years}年` : `${years.toFixed(1)}年`; + } + return `${days}天`; + }; + + const renderWaringStatus = (status) => { + const cfg = WARING_STATUS_MAP[status]; + if (!cfg) return {status}; + const labelMap = { + first: "首次预警 · 6个月", + second: "二次提醒 · 3个月", + urgent: "紧急预警 · 1个月", + overdue: "已逾期", + normal: "正常", + }; + return {labelMap[status] || cfg.text}; + }; + + const columns = [ + { title: "客户名称", dataIndex: "customerName", width: 180, ellipsis: true }, + { title: "行业 / 场景", dataIndex: "industryCode", width: 160, ellipsis: true }, + { title: "最近报告完成日", dataIndex: "archiveDate", width: 140 }, + { + title: "周期", + dataIndex: "cycleDate", + width: 100, + render: (val) => formatCycle(val), + }, + { title: "下次应开展", dataIndex: "reassessmentDate", width: 120 }, + { + title: "提醒等级", + dataIndex: "waringStatus", + width: 140, + render: (val) => renderWaringStatus(val), + }, + { title: "业务负责人", dataIndex: "projectLeaderName", width: 100, ellipsis: true }, + { + title: "操作", + width: 120, + fixed: "right", + render: (_, record) => ( + + ), + }, + ]; + + return ( + + + + + + 按行业周期和属地要求维护} + /> + + + + + 到期前6个月启动商务对接} + /> + + + + + 到期前3个月正式委托启动} + /> + + + + + 到期前1个月加快编制评审} + /> + + + + +
+ 提醒时间规则: + 到期前6个月首次预警,提示启动商务对接和项目排期;到期前3个月二次提醒,提示正式委托启动;到期前1个月紧急预警,提示加快报告编制与评审;超过到期日自动转为已逾期。 +
+ + + + , + + + , + + + , + ]} + onFinish={handleSearch} + onReset={handleReset} + /> + +
+ + 下一次应开展日期 = 最近一次正式报告完成日期 + 对应行业评价周期 + + + + + +
+ + `共 ${total} 条`, + }} + onChange={handlePageChange} + /> + + ); +}; + +export default Connect( + [NS_SAFETY_EVAL_BUSINESS], + true, +)(AntdTableFuncControl(BusinessReminder)); \ No newline at end of file diff --git a/src/pages/Container/SafetyEvalBusiness/BusinessReminder/index.less b/src/pages/Container/SafetyEvalBusiness/BusinessReminder/index.less new file mode 100644 index 0000000..3ac7591 --- /dev/null +++ b/src/pages/Container/SafetyEvalBusiness/BusinessReminder/index.less @@ -0,0 +1,38 @@ +.br { + &-header-desc { + font-size: 13px; + color: #999; + margin-bottom: 16px; + } + + &-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; + } + + &-toolbar { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 12px; + } + + &-toolbar-hint { + font-size: 13px; + color: #999; + } +} \ No newline at end of file