feat
parent
12b5d7b7a6
commit
bbfb21730c
|
|
@ -0,0 +1,56 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.0.1",
|
||||||
|
"info": { "title": "人员打卡信息查询", "version": "1.0.0" },
|
||||||
|
"paths": {
|
||||||
|
"/safetyEval/regulator/eval-project-monitor/survey-clock-in": {
|
||||||
|
"get": {
|
||||||
|
"summary": "人员打卡信息查询",
|
||||||
|
"tags": ["监管端-安评项目"],
|
||||||
|
"parameters": [
|
||||||
|
{ "name": "projectId", "in": "query", "required": true, "schema": { "type": "string" } }
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/SingleResponseListRegulatorEvalSurveyClockInCO" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"SingleResponseListRegulatorEvalSurveyClockInCO": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"success": { "type": "boolean" },
|
||||||
|
"code": { "type": "string" },
|
||||||
|
"message": { "type": "string" },
|
||||||
|
"errMessage": { "type": "string" },
|
||||||
|
"data": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "$ref": "#/components/schemas/RegulatorEvalSurveyClockInCO" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"RegulatorEvalSurveyClockInCO": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": { "type": "integer" },
|
||||||
|
"userName": { "type": "string" },
|
||||||
|
"role": { "type": "string" },
|
||||||
|
"faceState": { "type": "integer" },
|
||||||
|
"gpsState": { "type": "integer" },
|
||||||
|
"singInTime": { "type": "string" },
|
||||||
|
"signOutTime": { "type": "string" },
|
||||||
|
"sceneUrl": { "type": "string" },
|
||||||
|
"signatureUrl": { "type": "string" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
.api/safetyEval-regulator-eval-project-monitor-survey-clock-in-get/type.d.ts
vendored
Normal file
11
.api/safetyEval-regulator-eval-project-monitor-survey-clock-in-get/type.d.ts
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
export interface RegulatorEvalSurveyClockInCO {
|
||||||
|
id: number;
|
||||||
|
userName: string;
|
||||||
|
role: string;
|
||||||
|
faceState: number;
|
||||||
|
gpsState: number;
|
||||||
|
singInTime: string;
|
||||||
|
signOutTime: string;
|
||||||
|
sceneUrl: string;
|
||||||
|
signatureUrl: string;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.0.1",
|
||||||
|
"info": { "title": "踏勘监管分页", "version": "1.0.0" },
|
||||||
|
"paths": {
|
||||||
|
"/safetyEval/regulator/eval-project-monitor/survey-page": {
|
||||||
|
"get": {
|
||||||
|
"summary": "项目踏勘监管分页",
|
||||||
|
"tags": ["监管端-安评项目"],
|
||||||
|
"parameters": [
|
||||||
|
{ "name": "current", "in": "query", "schema": { "type": "integer", "default": 1 } },
|
||||||
|
{ "name": "size", "in": "query", "schema": { "type": "integer", "default": 10 } },
|
||||||
|
{ "name": "startTime", "in": "query", "schema": { "type": "string" } },
|
||||||
|
{ "name": "endTime", "in": "query", "schema": { "type": "string" } },
|
||||||
|
{ "name": "projectNameOrNo", "in": "query", "schema": { "type": "string" } },
|
||||||
|
{ "name": "orgId", "in": "query", "schema": { "type": "integer" } },
|
||||||
|
{ "name": "clockInStatus", "in": "query", "schema": { "type": "string" } }
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/PageResponseRegulatorEvalProjectSurveyPageCO" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"PageResponseRegulatorEvalProjectSurveyPageCO": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"success": { "type": "boolean" },
|
||||||
|
"code": { "type": "string" },
|
||||||
|
"message": { "type": "string" },
|
||||||
|
"errMessage": { "type": "string" },
|
||||||
|
"data": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "$ref": "#/components/schemas/RegulatorEvalProjectSurveyPageCO" }
|
||||||
|
},
|
||||||
|
"total": { "type": "integer" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"RegulatorEvalProjectSurveyPageCO": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": { "type": "string" },
|
||||||
|
"orgId": { "type": "string" },
|
||||||
|
"projectNo": { "type": "string" },
|
||||||
|
"projectName": { "type": "string" },
|
||||||
|
"orgName": { "type": "string" },
|
||||||
|
"expectedCount": { "type": "integer" },
|
||||||
|
"actualCount": { "type": "integer" },
|
||||||
|
"signInCount": { "type": "integer" },
|
||||||
|
"signOutCount": { "type": "integer" },
|
||||||
|
"faceCount": { "type": "integer" },
|
||||||
|
"scenePhotoCount": { "type": "integer" },
|
||||||
|
"notificationFileUrl": { "type": "string" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
export interface RegulatorEvalProjectSurveyPageCO {
|
||||||
|
id: string;
|
||||||
|
orgId: string;
|
||||||
|
projectNo: string;
|
||||||
|
projectName: string;
|
||||||
|
orgName: string;
|
||||||
|
expectedCount: number;
|
||||||
|
actualCount: number;
|
||||||
|
signInCount: number;
|
||||||
|
signOutCount: number;
|
||||||
|
faceCount: number;
|
||||||
|
scenePhotoCount: number;
|
||||||
|
notificationFileUrl: string;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.0.1",
|
||||||
|
"info": { "title": "踏勘监管统计", "version": "1.0.0" },
|
||||||
|
"paths": {
|
||||||
|
"/safetyEval/regulator/eval-project-monitor/survey-stat": {
|
||||||
|
"get": {
|
||||||
|
"summary": "项目踏勘监管统计",
|
||||||
|
"tags": ["监管端-安评项目"],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/SingleResponseRegulatorEvalProjectSurveyStatCO" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"SingleResponseRegulatorEvalProjectSurveyStatCO": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"success": { "type": "boolean" },
|
||||||
|
"code": { "type": "string" },
|
||||||
|
"message": { "type": "string" },
|
||||||
|
"errMessage": { "type": "string" },
|
||||||
|
"data": { "$ref": "#/components/schemas/RegulatorEvalProjectSurveyStatCO" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"RegulatorEvalProjectSurveyStatCO": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"notificationArchivedCount": { "type": "integer", "description": "告知书已归档数" },
|
||||||
|
"notificationAbnormalCount": { "type": "integer", "description": "告知异常数" },
|
||||||
|
"clockInNormalCount": { "type": "integer", "description": "人员打卡正常数" },
|
||||||
|
"clockInAbnormalCount": { "type": "integer", "description": "打卡异常数" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
export interface RegulatorEvalProjectSurveyStatCO {
|
||||||
|
notificationArchivedCount: number;
|
||||||
|
notificationAbnormalCount: number;
|
||||||
|
clockInNormalCount: number;
|
||||||
|
clockInAbnormalCount: number;
|
||||||
|
}
|
||||||
|
|
@ -264,3 +264,22 @@ export const evalProjectMonitorPage = declareRequest(
|
||||||
"evalProjectMonitorPageLoading",
|
"evalProjectMonitorPageLoading",
|
||||||
"Get > /safetyEval/regulator/eval-project-monitor/realtime-page",
|
"Get > /safetyEval/regulator/eval-project-monitor/realtime-page",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ===== 监管端-项目踏勘监管 =====
|
||||||
|
|
||||||
|
export const evalSurveyMonitorStat = declareRequest(
|
||||||
|
"evalSurveyMonitorStatLoading",
|
||||||
|
"Get > /safetyEval/regulator/eval-project-monitor/survey-stat",
|
||||||
|
"evalSurveyMonitorStat: {} | res.data || {}",
|
||||||
|
);
|
||||||
|
|
||||||
|
export const evalSurveyMonitorPage = declareRequest(
|
||||||
|
"evalSurveyMonitorPageLoading",
|
||||||
|
"Get > /safetyEval/regulator/eval-project-monitor/survey-page",
|
||||||
|
);
|
||||||
|
|
||||||
|
export const evalSurveyClockIn = declareRequest(
|
||||||
|
"evalSurveyClockInLoading",
|
||||||
|
"Get > /safetyEval/regulator/eval-project-monitor/survey-clock-in",
|
||||||
|
"evalSurveyClockIn: [] | res.data || []",
|
||||||
|
);
|
||||||
|
|
@ -411,6 +411,23 @@ export const MONITOR_WARING_STATUS_OPTIONS = [
|
||||||
{ label: "人员异常", value: "PERSONNEL_ABNORMAL" },
|
{ label: "人员异常", value: "PERSONNEL_ABNORMAL" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/** 监管端-项目踏勘监管 - 打卡状态筛选选项 */
|
||||||
|
export const CLOCK_IN_STATUS_OPTIONS = [
|
||||||
|
{ label: "正常", value: "normal" },
|
||||||
|
{ label: "异常", value: "abnormal" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const PROJECT_TYPE_OPTIONS = [
|
||||||
|
{ label: "新建项目", value: "NEW" },
|
||||||
|
{ label: "续评项目", value: "RENEW" },
|
||||||
|
{ label: "变更项目", value: "CHANGE" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const PROJECT_TYPE_MAP= PROJECT_TYPE_OPTIONS.reduce((acc, cur) => {
|
||||||
|
acc[cur.value] = cur.label;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
|
||||||
export const ROLE_DEFINITIONS = [
|
export const ROLE_DEFINITIONS = [
|
||||||
{ value: "MARKETING_BUSINESS_REP", name: "市场部业务员", unique: false, summary: "获取项目基础信息,形成风险分析记录;风险通过后签订合同并下达任务通知单。" },
|
{ value: "MARKETING_BUSINESS_REP", name: "市场部业务员", unique: false, summary: "获取项目基础信息,形成风险分析记录;风险通过后签订合同并下达任务通知单。" },
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import {
|
||||||
CheckCircleOutlined,
|
CheckCircleOutlined,
|
||||||
SyncOutlined,
|
SyncOutlined,
|
||||||
BellOutlined,
|
BellOutlined,
|
||||||
|
EnvironmentOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
|
|
||||||
const menuItems = [
|
const menuItems = [
|
||||||
|
|
@ -200,6 +201,11 @@ const menuItems = [
|
||||||
label: "安评项目实时监控",
|
label: "安评项目实时监控",
|
||||||
icon: <FileTextOutlined />,
|
icon: <FileTextOutlined />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "/safetyEval/container/MonitorManage/SurveyMonitor",
|
||||||
|
label: "项目踏勘监管",
|
||||||
|
icon: <EnvironmentOutlined />,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -15,18 +15,13 @@ import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
import { NS_SAFETY_EVAL_BUSINESS } from "~/enumerate/namespace";
|
import { NS_SAFETY_EVAL_BUSINESS } from "~/enumerate/namespace";
|
||||||
import { tools } from "@cqsjjb/jjb-common-lib";
|
import { tools } from "@cqsjjb/jjb-common-lib";
|
||||||
import { EVAL_TYPE_MAP, ROLE_DEFINITIONS_MAP } from "~/enumerate/constant";
|
import { EVAL_TYPE_MAP, ROLE_DEFINITIONS_MAP } from "~/enumerate/constant";
|
||||||
import { QUALIFICATION_INDUSTRY_OPTIONS_MAP } from "~/enumerate/enterpriseOptions";
|
import { PROJECT_TYPE_MAP } from "~/enumerate/constant";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
|
|
||||||
const { router } = tools;
|
const { router } = tools;
|
||||||
|
|
||||||
const PROJECT_TYPE_MAP = {
|
|
||||||
NEW: "新建项目",
|
|
||||||
RENEW: "续评项目",
|
|
||||||
CHANGE: "变更项目",
|
|
||||||
};
|
|
||||||
|
|
||||||
const YES_NO_MAP = { 1: "是", 2: "否" };
|
|
||||||
|
|
||||||
const ATTACH_TYPE_LABELS = {
|
const ATTACH_TYPE_LABELS = {
|
||||||
PRACTICE_NOTIFICATION: "从业告知书",
|
PRACTICE_NOTIFICATION: "从业告知书",
|
||||||
|
|
@ -166,8 +161,36 @@ const TeamPanel = ({ data, loading }) => {
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
let leader=null;
|
||||||
|
let processLeader=null;
|
||||||
|
data.forEach((item) => {
|
||||||
|
if (item.role.includes('PROJECT_LEAD')) {
|
||||||
|
leader = item.personnelName;
|
||||||
|
}
|
||||||
|
if (item.role.includes('PROCESS_CONTROL_LEAD')) {
|
||||||
|
processLeader = item.personnelName;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return <>
|
||||||
|
<div className="epm-detail-band">
|
||||||
|
<div className="epm-detail-band-item">
|
||||||
|
<span>项目组人数</span>
|
||||||
|
<strong>
|
||||||
|
{data.length || 0}人
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
<div className="epm-detail-band-item">
|
||||||
|
<span>项目负责人</span>
|
||||||
|
<strong>{leader || "-"}</strong>
|
||||||
|
</div>
|
||||||
|
<div className="epm-detail-band-item">
|
||||||
|
<span>过程控制负责人</span>
|
||||||
|
<strong>
|
||||||
|
{processLeader || "-"}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
return (
|
</div>
|
||||||
<Table
|
<Table
|
||||||
dataSource={data}
|
dataSource={data}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
|
|
@ -176,7 +199,7 @@ const TeamPanel = ({ data, loading }) => {
|
||||||
size="small"
|
size="small"
|
||||||
scroll={{ x: 800 }}
|
scroll={{ x: 800 }}
|
||||||
/>
|
/>
|
||||||
);
|
</>
|
||||||
};
|
};
|
||||||
|
|
||||||
// ===== 踏勘情况面板 =====
|
// ===== 踏勘情况面板 =====
|
||||||
|
|
@ -315,7 +338,7 @@ const EvalProjectMonitorDetail = (props) => {
|
||||||
const [teamMembers, setTeamMembers] = useState([]);
|
const [teamMembers, setTeamMembers] = useState([]);
|
||||||
const [surveyPersonnel, setSurveyPersonnel] = useState([]);
|
const [surveyPersonnel, setSurveyPersonnel] = useState([]);
|
||||||
const [surveyAttachments, setSurveyAttachments] = useState({});
|
const [surveyAttachments, setSurveyAttachments] = useState({});
|
||||||
const [activeKey, setActiveKey] = useState("contract");
|
const [activeKey, setActiveKey] = useState("BUSINESS_CONTRACT");
|
||||||
|
|
||||||
const fetchContract = async () => {
|
const fetchContract = async () => {
|
||||||
if (!projectId) return;
|
if (!projectId) return;
|
||||||
|
|
@ -360,6 +383,24 @@ const EvalProjectMonitorDetail = (props) => {
|
||||||
fetchSurvey();
|
fetchSurvey();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const projectNode = JSON.parse(evalProjectDetailData?.projectNode || "[]") || [];
|
||||||
|
const nodeMap = {};
|
||||||
|
projectNode.forEach((n) => {
|
||||||
|
nodeMap[n.type] = n;
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderTabLabel = (label, nodeType) => {
|
||||||
|
const done = nodeMap[nodeType]?.state === 1;
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{label}
|
||||||
|
<Tag color={done ? "success" : "default"} style={{ marginLeft: 6 }}>
|
||||||
|
{done ? "已完成" : "待办理"}
|
||||||
|
</Tag>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const projectInfo = (
|
const projectInfo = (
|
||||||
<div className="epm-detail-band">
|
<div className="epm-detail-band">
|
||||||
<div className="epm-detail-band-item">
|
<div className="epm-detail-band-item">
|
||||||
|
|
@ -377,12 +418,16 @@ const EvalProjectMonitorDetail = (props) => {
|
||||||
<div className="epm-detail-band-item">
|
<div className="epm-detail-band-item">
|
||||||
<span>评价机构</span>
|
<span>评价机构</span>
|
||||||
<strong>
|
<strong>
|
||||||
{contractData?.orgName || evalProjectDetailData?.orgName || "-"}
|
{contractData?.orgName || "-"}
|
||||||
</strong>
|
</strong>
|
||||||
</div>
|
</div>
|
||||||
<div className="epm-detail-band-item">
|
<div className="epm-detail-band-item">
|
||||||
<span>项目负责人</span>
|
<span>项目负责人</span>
|
||||||
<strong>{evalProjectDetailData?.leaderName || "-"}</strong>
|
<strong>{evalProjectDetailData?.projectLeaderName || "-"}</strong>
|
||||||
|
</div>
|
||||||
|
<div className="epm-detail-band-item">
|
||||||
|
<span>总体状态</span>
|
||||||
|
<strong>{projectNode.filter((item) => item.state === 1).length}/{projectNode.length}</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -395,20 +440,20 @@ const EvalProjectMonitorDetail = (props) => {
|
||||||
onChange={setActiveKey}
|
onChange={setActiveKey}
|
||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
key: "contract",
|
key: "BUSINESS_CONTRACT",
|
||||||
label: "项目合同",
|
label: renderTabLabel("项目合同", "BUSINESS_CONTRACT"),
|
||||||
children: (
|
children: (
|
||||||
<ContractPanel data={contractData} loading={contractLoading} />
|
<ContractPanel data={contractData} loading={contractLoading} />
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "team",
|
key: "PROJECT_GROUP",
|
||||||
label: "项目组人员",
|
label: renderTabLabel("项目组人员", "PROJECT_GROUP"),
|
||||||
children: <TeamPanel data={teamMembers} loading={memberLoading} />,
|
children: <TeamPanel data={teamMembers} loading={memberLoading} />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "survey",
|
key: "SITE_SURVEY",
|
||||||
label: "踏勘情况",
|
label: renderTabLabel("踏勘情况", "SITE_SURVEY"),
|
||||||
children: (
|
children: (
|
||||||
<SurveyPanel
|
<SurveyPanel
|
||||||
personnel={surveyPersonnel}
|
personnel={surveyPersonnel}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,354 @@
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import {
|
||||||
|
Row,
|
||||||
|
Col,
|
||||||
|
Card,
|
||||||
|
Statistic,
|
||||||
|
Table,
|
||||||
|
Tag,
|
||||||
|
Button,
|
||||||
|
Form,
|
||||||
|
Modal,
|
||||||
|
Space,
|
||||||
|
Typography,
|
||||||
|
} 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 { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
|
import { NS_SAFETY_EVAL_BUSINESS } from "~/enumerate/namespace";
|
||||||
|
import { tools } from "@cqsjjb/jjb-common-lib";
|
||||||
|
import {
|
||||||
|
CLOCK_IN_STATUS_OPTIONS,
|
||||||
|
ROLE_DEFINITIONS_MAP,
|
||||||
|
} from "~/enumerate/constant";
|
||||||
|
import "./index.less";
|
||||||
|
|
||||||
|
const { router } = tools;
|
||||||
|
|
||||||
|
const STAT_ITEMS = [
|
||||||
|
{ key: "notificationArchivedCount", title: "告知书已归档", color: "#1677ff" },
|
||||||
|
{ key: "clockInNormalCount", title: "人员打卡正常", color: "#52c41a" },
|
||||||
|
{ key: "notificationAbnormalCount", title: "告知异常", color: "#faad14" },
|
||||||
|
{ key: "clockInAbnormalCount", title: "打卡异常", color: "#ff4d4f" },
|
||||||
|
];
|
||||||
|
|
||||||
|
/** 解析文件 JSON */
|
||||||
|
const parseFileList = (raw) => {
|
||||||
|
if (!raw) return [];
|
||||||
|
try {
|
||||||
|
const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
||||||
|
return Array.isArray(parsed) ? parsed : [];
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 根据打卡数据计算状态 */
|
||||||
|
const getClockInStatus = (record) => {
|
||||||
|
if (record.actualCount < record.expectedCount) {
|
||||||
|
return { color: "error", text: "人员未到齐" };
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
record.signInCount < record.actualCount ||
|
||||||
|
record.signOutCount < record.actualCount
|
||||||
|
) {
|
||||||
|
return { color: "warning", text: "异常" };
|
||||||
|
}
|
||||||
|
return { color: "success", text: "正常" };
|
||||||
|
};
|
||||||
|
|
||||||
|
const SurveyMonitor = (props) => {
|
||||||
|
const [searchForm] = Form.useForm();
|
||||||
|
const [dataSource, setDataSource] = useState([]);
|
||||||
|
const [total, setTotal] = useState(0);
|
||||||
|
const [clockInModal, setClockInModal] = useState(false);
|
||||||
|
const [clockInData, setClockInData] = useState([]);
|
||||||
|
const [clockInProjectName, setClockInProjectName] = useState("");
|
||||||
|
|
||||||
|
const { safetyEvalBusiness, evalSurveyMonitorStat, evalSurveyMonitorPage,
|
||||||
|
evalSurveyClockIn } = props;
|
||||||
|
const { evalSurveyMonitorStatLoading, evalSurveyMonitorPageLoading,
|
||||||
|
evalSurveyClockInLoading } = safetyEvalBusiness || {};
|
||||||
|
const statData = safetyEvalBusiness?.evalSurveyMonitorStat || {};
|
||||||
|
|
||||||
|
const getStat = () => {
|
||||||
|
evalSurveyMonitorStat();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getData = async () => {
|
||||||
|
const params = {
|
||||||
|
...router.query,
|
||||||
|
current: router.query.current || 1,
|
||||||
|
size: router.query.size || 10,
|
||||||
|
};
|
||||||
|
const res = await evalSurveyMonitorPage(params);
|
||||||
|
if (res?.success !== false) {
|
||||||
|
setDataSource(res?.data || []);
|
||||||
|
setTotal(res?.total || 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
searchForm.setFieldsValue({
|
||||||
|
...router.query,
|
||||||
|
dateRange:
|
||||||
|
router.query.startTime && router.query.endTime
|
||||||
|
? [router.query.startTime, router.query.endTime]
|
||||||
|
: undefined,
|
||||||
|
});
|
||||||
|
getStat();
|
||||||
|
getData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleSearch = (values) => {
|
||||||
|
const { dateRange, ...rest } = values;
|
||||||
|
router.query = {
|
||||||
|
...rest,
|
||||||
|
startTime: dateRange?.[0]?.format?.("YYYY-MM-DD") || undefined,
|
||||||
|
endTime: dateRange?.[1]?.format?.("YYYY-MM-DD") || undefined,
|
||||||
|
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 handleViewClockIn = async (record) => {
|
||||||
|
setClockInProjectName(record.projectName);
|
||||||
|
setClockInModal(true);
|
||||||
|
const res = await evalSurveyClockIn({ projectId: record.id });
|
||||||
|
if (res?.success !== false) {
|
||||||
|
setClockInData(res?.data || []);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleViewNotice = (record) => {
|
||||||
|
const files = parseFileList(record.notificationFileUrl);
|
||||||
|
if (files.length > 0 && files[0].url) {
|
||||||
|
window.open(files[0].url, "_blank");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const clockInColumns = [
|
||||||
|
{ title: "人员", dataIndex: "userName", width: 100 },
|
||||||
|
{
|
||||||
|
title: "项目角色",
|
||||||
|
dataIndex: "role",
|
||||||
|
width: 160,
|
||||||
|
ellipsis: true,
|
||||||
|
render: (v) =>
|
||||||
|
Array.isArray(v)
|
||||||
|
? v.map((r) => ROLE_DEFINITIONS_MAP[r] || r).join("、")
|
||||||
|
: v || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "人脸识别",
|
||||||
|
dataIndex: "faceState",
|
||||||
|
width: 90,
|
||||||
|
render: (v) => (
|
||||||
|
<Tag color={v === 1 ? "success" : "error"}>
|
||||||
|
{v === 1 ? "通过" : "未通过"}
|
||||||
|
</Tag>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "GPS定位",
|
||||||
|
dataIndex: "gpsState",
|
||||||
|
width: 90,
|
||||||
|
render: (v) => (
|
||||||
|
<Tag color={v === 1 ? "success" : "error"}>
|
||||||
|
{v === 1 ? "正常" : "异常"}
|
||||||
|
</Tag>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{ title: "签到时间", dataIndex: "singInTime", width: 160 },
|
||||||
|
{ title: "签退时间", dataIndex: "signOutTime", width: 160 },
|
||||||
|
{
|
||||||
|
title: "现场照片",
|
||||||
|
dataIndex: "sceneUrl",
|
||||||
|
width: 80,
|
||||||
|
render: (v) => {
|
||||||
|
const count = v ? v.split(",").filter(Boolean).length : 0;
|
||||||
|
return count > 0 ? `${count}张` : "-";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "本人签字",
|
||||||
|
dataIndex: "signatureUrl",
|
||||||
|
width: 90,
|
||||||
|
render: (v) => (
|
||||||
|
<Tag color={v ? "success" : "default"}>
|
||||||
|
{v ? "已签字" : "未签字"}
|
||||||
|
</Tag>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{ title: "项目编号", dataIndex: "projectNo", width: 140 },
|
||||||
|
{ title: "项目名称", dataIndex: "projectName", ellipsis: true, width: 220 },
|
||||||
|
{ title: "评价机构", dataIndex: "orgName", ellipsis: true, width: 200 },
|
||||||
|
{
|
||||||
|
title: "告知书状态",
|
||||||
|
dataIndex: "notificationFileUrl",
|
||||||
|
width: 120,
|
||||||
|
render: (v) => {
|
||||||
|
const files = parseFileList(v);
|
||||||
|
return files.length > 0 ? (
|
||||||
|
<Tag color="success">已归档</Tag>
|
||||||
|
) : (
|
||||||
|
<Tag color="warning">待上传</Tag>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "应到/实到",
|
||||||
|
width: 100,
|
||||||
|
render: (_, r) => `${r.expectedCount} / ${r.actualCount}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "签到/签退",
|
||||||
|
width: 100,
|
||||||
|
render: (_, r) => `${r.signInCount} / ${r.signOutCount}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "现场照片",
|
||||||
|
dataIndex: "scenePhotoCount",
|
||||||
|
width: 90,
|
||||||
|
render: (v) => (v ? `${v}张` : "-"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "打卡状态",
|
||||||
|
width: 100,
|
||||||
|
render: (_, r) => {
|
||||||
|
const status = getClockInStatus(r);
|
||||||
|
return <Tag color={status.color}>{status.text}</Tag>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "操作",
|
||||||
|
width: 160,
|
||||||
|
fixed: "right",
|
||||||
|
render: (_, record) => (
|
||||||
|
<Space size={4}>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
disabled={!parseFileList(record.notificationFileUrl).length}
|
||||||
|
onClick={() => handleViewNotice(record)}
|
||||||
|
>
|
||||||
|
告知书
|
||||||
|
</Button>
|
||||||
|
<Button type="link" size="small" onClick={() => handleViewClockIn(record)}>
|
||||||
|
人员打卡
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageLayout title="项目踏勘监管">
|
||||||
|
<Row gutter={16} className="sm-stat-row">
|
||||||
|
{STAT_ITEMS.map((item) => (
|
||||||
|
<Col span={6} key={item.key}>
|
||||||
|
<Card size="small">
|
||||||
|
<Statistic
|
||||||
|
title={item.title}
|
||||||
|
value={statData[item.key] ?? "-"}
|
||||||
|
valueStyle={{ color: item.color }}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<SearchForm
|
||||||
|
form={searchForm}
|
||||||
|
loading={false}
|
||||||
|
style={{ marginBottom: 16 }}
|
||||||
|
formLine={[
|
||||||
|
<Form.Item key="projectNameOrNo" name="projectNameOrNo">
|
||||||
|
<ControlWrapper.Input
|
||||||
|
label="项目名称/编号"
|
||||||
|
placeholder="请输入"
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
</Form.Item>,
|
||||||
|
<Form.Item key="dateRange" name="dateRange">
|
||||||
|
<ControlWrapper.DatePicker.RangePicker
|
||||||
|
label="踏勘日期"
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
/>
|
||||||
|
</Form.Item>,
|
||||||
|
<Form.Item key="clockInStatus" name="clockInStatus">
|
||||||
|
<ControlWrapper.Select
|
||||||
|
label="打卡状态"
|
||||||
|
placeholder="全部"
|
||||||
|
allowClear
|
||||||
|
options={CLOCK_IN_STATUS_OPTIONS}
|
||||||
|
/>
|
||||||
|
</Form.Item>,
|
||||||
|
]}
|
||||||
|
onFinish={handleSearch}
|
||||||
|
onReset={handleReset}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Table
|
||||||
|
rowKey="id"
|
||||||
|
columns={columns}
|
||||||
|
dataSource={dataSource}
|
||||||
|
loading={evalSurveyMonitorPageLoading}
|
||||||
|
scroll={{ y: props.scrollY, x: 1300 }}
|
||||||
|
pagination={{
|
||||||
|
total,
|
||||||
|
current: Number(router.query.current) || 1,
|
||||||
|
pageSize: Number(router.query.size) || 10,
|
||||||
|
showSizeChanger: true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
showTotal: (t) => `共 ${t} 条`,
|
||||||
|
}}
|
||||||
|
onChange={handlePageChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
title={`人员打卡详情 - ${clockInProjectName}`}
|
||||||
|
open={clockInModal}
|
||||||
|
onCancel={() => setClockInModal(false)}
|
||||||
|
footer={null}
|
||||||
|
width={1000}
|
||||||
|
>
|
||||||
|
<Table
|
||||||
|
dataSource={clockInData}
|
||||||
|
columns={clockInColumns}
|
||||||
|
rowKey="id"
|
||||||
|
pagination={false}
|
||||||
|
size="small"
|
||||||
|
loading={evalSurveyClockInLoading}
|
||||||
|
scroll={{ x: 900 }}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
</PageLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Connect(
|
||||||
|
[NS_SAFETY_EVAL_BUSINESS],
|
||||||
|
true,
|
||||||
|
)(AntdTableFuncControl(SurveyMonitor));
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
.sm-stat-row {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,7 @@ import {
|
||||||
Spin,
|
Spin,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import {PROJECT_TYPE_OPTIONS ,EVAL_TYPE_OPTIONS} from '~/enumerate/constant';
|
||||||
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";
|
||||||
import { district } from "~/enumerate/constant";
|
import { district } from "~/enumerate/constant";
|
||||||
|
|
@ -25,17 +26,9 @@ import AttachmentUpload from "~/components/AttachmentUpload";
|
||||||
const { router } = tools;
|
const { router } = tools;
|
||||||
const { TextArea } = Input;
|
const { TextArea } = Input;
|
||||||
|
|
||||||
const PROJECT_TYPE_OPTIONS = [
|
|
||||||
{ label: "新建项目", value: "NEW" },
|
|
||||||
{ label: "续评项目", value: "RENEW" },
|
|
||||||
{ label: "变更项目", value: "CHANGE" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const EVAL_TYPE_OPTIONS = [
|
|
||||||
{ label: "安全预评价", value: "PRE" },
|
|
||||||
{ label: "安全验收评价", value: "ACCEPT" },
|
|
||||||
{ label: "安全现状评价", value: "STATUS" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const YES_NO_OPTIONS = [
|
const YES_NO_OPTIONS = [
|
||||||
{ label: "是", value: 1 },
|
{ label: "是", value: 1 },
|
||||||
|
|
|
||||||
|
|
@ -12,21 +12,13 @@ import dayjs from "dayjs";
|
||||||
const { router } = tools;
|
const { router } = tools;
|
||||||
|
|
||||||
const STAGES = [
|
const STAGES = [
|
||||||
{ key: "notice", index: "01", label: "从业告知" },
|
{ key: "PRACTICE_NOTIFICATION", index: "01", label: "从业告知" },
|
||||||
{ key: "inspection", index: "02", label: "现场勘查" },
|
{ key: "SITE_INSPECTION_FORM", index: "02", label: "现场勘查" },
|
||||||
{ key: "rectification", index: "03", label: "整改通知" },
|
{ key: "RECTIFICATION_NOTICE", index: "03", label: "整改通知" },
|
||||||
{ key: "enterprise", index: "04", label: "企业整改" },
|
{ key: "ENTERPRISE_RECTIFICATION", index: "04", label: "企业整改" },
|
||||||
{ key: "review", index: "05", label: "整改复查" },
|
{ key: "RECTIFICATION_REVIEW", index: "05", label: "整改复查" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const ATTACH_TYPE = {
|
|
||||||
notice: "PRACTICE_NOTIFICATION",
|
|
||||||
inspection: "SITE_INSPECTION_FORM",
|
|
||||||
rectification: "RECTIFICATION_NOTICE",
|
|
||||||
enterprise: "ENTERPRISE_RECTIFICATION",
|
|
||||||
review: "RECTIFICATION_REVIEW",
|
|
||||||
};
|
|
||||||
|
|
||||||
const downloadTemplate = async () => {
|
const downloadTemplate = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await fetch("https://test-dragon-yf-pub.oss-cn-hangzhou.aliyuncs.com/jjb/6a608cb30dc53ed98d0b13ae.pdf");
|
const res = await fetch("https://test-dragon-yf-pub.oss-cn-hangzhou.aliyuncs.com/jjb/6a608cb30dc53ed98d0b13ae.pdf");
|
||||||
|
|
@ -137,7 +129,7 @@ const SimpleUploadPanel = ({ index, title, desc }) => (
|
||||||
|
|
||||||
const SurveyContent = (props) => {
|
const SurveyContent = (props) => {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [activeStage, setActiveStage] = useState("notice");
|
const [activeStage, setActiveStage] = useState("PRACTICE_NOTIFICATION");
|
||||||
const [attachMap, setAttachMap] = useState({});
|
const [attachMap, setAttachMap] = useState({});
|
||||||
const [surveyPersonnel, setSurveyPersonnel] = useState([]);
|
const [surveyPersonnel, setSurveyPersonnel] = useState([]);
|
||||||
const { evalSurveyListLoading, evalSurveySaveAttachLoading, evalProjectDetailData } = props.safetyEvalBusiness;
|
const { evalSurveyListLoading, evalSurveySaveAttachLoading, evalProjectDetailData } = props.safetyEvalBusiness;
|
||||||
|
|
@ -163,8 +155,8 @@ const SurveyContent = (props) => {
|
||||||
setAttachMap(map);
|
setAttachMap(map);
|
||||||
// 回填所有步骤的附件到表单
|
// 回填所有步骤的附件到表单
|
||||||
const values = {};
|
const values = {};
|
||||||
Object.entries(ATTACH_TYPE).forEach(([, typeCode]) => {
|
STAGES.forEach((s) => {
|
||||||
values[typeCode] = map[typeCode] || [];
|
values[s.key] = map[s.key] || [];
|
||||||
});
|
});
|
||||||
form.setFieldsValue(values);
|
form.setFieldsValue(values);
|
||||||
}
|
}
|
||||||
|
|
@ -195,17 +187,17 @@ const SurveyContent = (props) => {
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
const values = form.getFieldsValue();
|
const values = form.getFieldsValue();
|
||||||
const payload = [];
|
const payload = [];
|
||||||
for (const [key, typeCode] of Object.entries(ATTACH_TYPE)) {
|
for (const s of STAGES) {
|
||||||
const fileList = values[typeCode] || [];
|
const fileList = values[s.key] || [];
|
||||||
const validFiles = fileList.filter((f) => f.status === "done" && f.url);
|
const validFiles = fileList.filter((f) => f.status === "done" && f.url);
|
||||||
if (validFiles.length === 0) {
|
if (validFiles.length === 0) {
|
||||||
setActiveStage(key);
|
setActiveStage(s.key);
|
||||||
message.warning(`请先在"${STAGES.find((s) => s.key === key).label}"步骤上传附件`);
|
message.warning(`请先在"${s.label}"步骤上传附件`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
payload.push({
|
payload.push({
|
||||||
projectId,
|
projectId,
|
||||||
attachTypeCode: typeCode,
|
attachTypeCode: s.key,
|
||||||
fileUrl: JSON.stringify(fileList),
|
fileUrl: JSON.stringify(fileList),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -225,21 +217,21 @@ const SurveyContent = (props) => {
|
||||||
items={STAGES.map((s) => ({ title: s.label }))}
|
items={STAGES.map((s) => ({ title: s.label }))}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{activeStage === "notice" && <NoticePanel />}
|
{activeStage === "PRACTICE_NOTIFICATION" && <NoticePanel />}
|
||||||
{activeStage === "inspection" && <InspectionPanel dataSource={surveyPersonnel} evalProjectDetailData={evalProjectDetailData} />}
|
{activeStage === "SITE_INSPECTION_FORM" && <InspectionPanel dataSource={surveyPersonnel} evalProjectDetailData={evalProjectDetailData} />}
|
||||||
{activeStage === "rectification" && (
|
{activeStage === "RECTIFICATION_NOTICE" && (
|
||||||
<SimpleUploadPanel
|
<SimpleUploadPanel
|
||||||
index="03" title="整改通知单上传"
|
index="03" title="整改通知单上传"
|
||||||
desc="本节点不在线编制整改通知,只归档机构已出具的《整改通知单》文件;上传成功即完成,后续可替换修改。"
|
desc="本节点不在线编制整改通知,只归档机构已出具的《整改通知单》文件;上传成功即完成,后续可替换修改。"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{activeStage === "enterprise" && (
|
{activeStage === "ENTERPRISE_RECTIFICATION" && (
|
||||||
<SimpleUploadPanel
|
<SimpleUploadPanel
|
||||||
index="04" title="企业整改报告上传"
|
index="04" title="企业整改报告上传"
|
||||||
desc="企业线下提交《整改报告》后,由机构人员上传归档;本系统不提供企业在线提交和逐项整改流程。"
|
desc="企业线下提交《整改报告》后,由机构人员上传归档;本系统不提供企业在线提交和逐项整改流程。"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{activeStage === "review" && (
|
{activeStage === "RECTIFICATION_REVIEW" && (
|
||||||
<SimpleUploadPanel
|
<SimpleUploadPanel
|
||||||
index="05" title="整改复查单上传"
|
index="05" title="整改复查单上传"
|
||||||
desc="机构人员现场复查后,将经双方签字确认的《整改复查单》上传归档;上传后本节点自动标记完成。"
|
desc="机构人员现场复查后,将经双方签字确认的《整改复查单》上传归档;上传后本节点自动标记完成。"
|
||||||
|
|
@ -247,10 +239,10 @@ const SurveyContent = (props) => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Form form={form} layout="vertical">
|
<Form form={form} layout="vertical">
|
||||||
{Object.entries(ATTACH_TYPE).map(([key, typeCode]) => (
|
{STAGES.map((s) => (
|
||||||
<div key={key} style={{ display: key === activeStage ? "block" : "none" }}>
|
<div key={s.key} style={{ display: s.key === activeStage ? "block" : "none" }}>
|
||||||
<AttachmentUpload
|
<AttachmentUpload
|
||||||
name={typeCode}
|
name={s.key}
|
||||||
label="上传附件"
|
label="上传附件"
|
||||||
maxCount={10}
|
maxCount={10}
|
||||||
accept=".pdf,.doc,.docx,.jpg,.jpeg,.png,.xls,.xlsx"
|
accept=".pdf,.doc,.docx,.jpg,.jpeg,.png,.xls,.xlsx"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue