feat
parent
8b2d97eb47
commit
396a534bf5
|
|
@ -163,6 +163,16 @@ export const evalProjectMemberSave = declareRequest(
|
||||||
"Post > @/safetyEval/institution/eval-project-member/save",
|
"Post > @/safetyEval/institution/eval-project-member/save",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const evalProjectMemberParticipantSave = declareRequest(
|
||||||
|
"memberParticipantSaveLoading",
|
||||||
|
"Post > @/safetyEval/institution/eval-project-member/participant/save",
|
||||||
|
);
|
||||||
|
|
||||||
|
export const evalProjectMemberParticipantList = declareRequest(
|
||||||
|
"memberParticipantListLoading",
|
||||||
|
"Get > /safetyEval/institution/eval-project-member/participant/list",
|
||||||
|
);
|
||||||
|
|
||||||
// ===== 项目预警(安评业务提醒) =====
|
// ===== 项目预警(安评业务提醒) =====
|
||||||
|
|
||||||
export const projectWaringStat = declareRequest(
|
export const projectWaringStat = declareRequest(
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import {
|
||||||
Button,
|
Button,
|
||||||
message,
|
message,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
|
import { PictureOutlined } from "@ant-design/icons";
|
||||||
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout";
|
||||||
import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
|
import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd";
|
||||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
|
|
@ -231,6 +232,25 @@ const TeamPanel = ({ data, loading }) => {
|
||||||
const SurveyPanel = ({ personnel, attachments, loading, detailData }) => {
|
const SurveyPanel = ({ personnel, attachments, loading, detailData }) => {
|
||||||
if (loading) return <Empty />;
|
if (loading) return <Empty />;
|
||||||
|
|
||||||
|
|
||||||
|
/** 打卡时间后追加人脸照片图标:faceUrl 逗号分隔,第1张为签到、第2张为签退 */
|
||||||
|
const renderTimeWithFace = (time, record, idx) => {
|
||||||
|
const url = record?.faceUrl?.split(",")[idx];
|
||||||
|
if (!url) return time || "-";
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{time}
|
||||||
|
<Popover
|
||||||
|
content={<Image src={url} width={240} />}
|
||||||
|
title="人脸照片"
|
||||||
|
trigger="hover"
|
||||||
|
>
|
||||||
|
<PictureOutlined style={{ marginLeft: 6, color: "#1677ff", cursor: "pointer" }} />
|
||||||
|
</Popover>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const personnelColumns = [
|
const personnelColumns = [
|
||||||
{ title: "人员", dataIndex: "personnelName", width: 100 },
|
{ title: "人员", dataIndex: "personnelName", width: 100 },
|
||||||
{
|
{
|
||||||
|
|
@ -263,8 +283,8 @@ const SurveyPanel = ({ personnel, attachments, loading, detailData }) => {
|
||||||
</Tag>
|
</Tag>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{ title: "签到时间", dataIndex: "singInTime", width: 140 },
|
{ title: "签到时间", dataIndex: "singInTime" , render: (time, record)=>{return renderTimeWithFace(time, record, 0);}},
|
||||||
{ title: "签退时间", dataIndex: "signOutTime", width: 140 },
|
{ title: "签退时间", dataIndex: "signOutTime" , render: (time, record)=>{return renderTimeWithFace(time, record, 1);}},
|
||||||
{
|
{
|
||||||
title: "现场照片",
|
title: "现场照片",
|
||||||
dataIndex: "sceneUrl",
|
dataIndex: "sceneUrl",
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@ import {
|
||||||
Checkbox,
|
Checkbox,
|
||||||
message,
|
message,
|
||||||
Spin,
|
Spin,
|
||||||
|
Card,
|
||||||
|
Popover,
|
||||||
|
Image,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
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";
|
||||||
|
|
@ -20,10 +23,22 @@ import LayoutFooterPortal from "~/components/LayoutFooterPortal";
|
||||||
const { router } = tools;
|
const { router } = tools;
|
||||||
|
|
||||||
const TeamContent = ({ readOnly, ...props }) => {
|
const TeamContent = ({ readOnly, ...props }) => {
|
||||||
const { safetyEvalBusiness, evalProjectMemberPage, evalProjectMemberSave } =
|
const {
|
||||||
props;
|
safetyEvalBusiness,
|
||||||
const { evalProjectDetailData, memberLoading, memberSaveLoading } =
|
evalProjectMemberPage,
|
||||||
safetyEvalBusiness || {};
|
evalProjectMemberSave,
|
||||||
|
evalProjectMemberParticipantSave,
|
||||||
|
evalProjectMemberParticipantList,
|
||||||
|
evalSignTaskSave,
|
||||||
|
} = props;
|
||||||
|
const {
|
||||||
|
evalProjectDetailData,
|
||||||
|
memberLoading,
|
||||||
|
memberSaveLoading,
|
||||||
|
memberParticipantSaveLoading,
|
||||||
|
memberParticipantListLoading,
|
||||||
|
evalSignTaskSaveLoading,
|
||||||
|
} = safetyEvalBusiness || {};
|
||||||
const participants = evalProjectDetailData?.participants || [];
|
const participants = evalProjectDetailData?.participants || [];
|
||||||
const projectId = router.query?.id;
|
const projectId = router.query?.id;
|
||||||
|
|
||||||
|
|
@ -31,6 +46,11 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
const [selectedRole, setSelectedRole] = useState(null);
|
const [selectedRole, setSelectedRole] = useState(null);
|
||||||
const [selectedPersons, setSelectedPersons] = useState([]);
|
const [selectedPersons, setSelectedPersons] = useState([]);
|
||||||
const [teamMembers, setTeamMembers] = useState([]);
|
const [teamMembers, setTeamMembers] = useState([]);
|
||||||
|
// 参与风险分析人员签字
|
||||||
|
const [participantModalOpen, setParticipantModalOpen] = useState(false);
|
||||||
|
const [selectedParticipantIds, setSelectedParticipantIds] = useState([]);
|
||||||
|
|
||||||
|
const [signers, setSigners] = useState([]);
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
if (!projectId) return;
|
if (!projectId) return;
|
||||||
|
|
@ -49,6 +69,11 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// 参与签字人员(查询接口:参与人列表)
|
||||||
|
const signRes = await evalProjectMemberParticipantList({ projectId });
|
||||||
|
if (signRes?.success !== false) {
|
||||||
|
setSigners(signRes?.data || []);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -98,16 +123,15 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 一人只能担任一个单人唯一角色
|
// 一人只能担任一个单人唯一角色
|
||||||
const uniqueRoleValues = ROLE_DEFINITIONS.filter(
|
const uniqueRoleValues = ROLE_DEFINITIONS.filter((r) => r.unique).map(
|
||||||
(r) => r.unique,
|
(r) => r.value,
|
||||||
).map((r) => r.value);
|
);
|
||||||
const conflict = selectedPersons.find((personId) => {
|
const conflict = selectedPersons.find((personId) => {
|
||||||
const member = teamMembers.find((m) => m.personnelId === personId);
|
const member = teamMembers.find((m) => m.personnelId === personId);
|
||||||
return (
|
return (
|
||||||
member &&
|
member &&
|
||||||
member.roles.some(
|
member.roles.some(
|
||||||
(r) =>
|
(r) => uniqueRoleValues.includes(r.role) && r.role !== selectedRole,
|
||||||
uniqueRoleValues.includes(r.role) && r.role !== selectedRole,
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
@ -156,14 +180,68 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
setTeamMembers((prev) => prev.filter((m) => m.personnelId !== personnelId));
|
setTeamMembers((prev) => prev.filter((m) => m.personnelId !== personnelId));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSave = async () => {
|
// 发起APP签字
|
||||||
const allRoles = teamMembers.flatMap((m) => m.roles.map((r) => r.role));
|
const handleSignApp = async (index) => {
|
||||||
if (!allRoles.includes("PROJECT_LEAD")) {
|
const participant = signers[index];
|
||||||
message.warning("请先配置项目负责人(项目组组长)");
|
if (!participant?.personnelId) {
|
||||||
|
message.warning("该人员信息不完整,请先保存后再发起签字");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!allRoles.includes("PROCESS_CONTROL_LEAD")) {
|
// 发起签字前先保存签字人员
|
||||||
message.warning("请先配置过程控制负责人");
|
const saveRes = await evalProjectMemberParticipantSave(
|
||||||
|
signers.map((s, idx) => ({
|
||||||
|
id: s.id,
|
||||||
|
projectId,
|
||||||
|
personnelId: s.personnelId,
|
||||||
|
personnelName: s.personnelName,
|
||||||
|
deptName: s.deptName,
|
||||||
|
signStatusCode: s.signStatusCode,
|
||||||
|
signFileUrl: s.signFileUrl,
|
||||||
|
sortOrder: idx + 1,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
if (saveRes?.success === false) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await evalSignTaskSave({
|
||||||
|
projectId,
|
||||||
|
nodeCode: "PROJECT_GROUP",
|
||||||
|
bizRefId: projectId || undefined,
|
||||||
|
signerPersonnelId: participant.personnelId,
|
||||||
|
taskTitle: "项目组成立签字",
|
||||||
|
taskStatusCode: 1,
|
||||||
|
});
|
||||||
|
if (res?.success) {
|
||||||
|
message.success("已发起APP签字");
|
||||||
|
setSigners((prev) =>
|
||||||
|
prev.map((s, i) => (i === index ? { ...s, signStatusCode: 1 } : s)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRemoveSigner = (personnelId) => {
|
||||||
|
setSigners((prev) => prev.filter((s) => s.personnelId !== personnelId));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
const allRoles = teamMembers.flatMap((m) => m.roles.map((r) => r.role));
|
||||||
|
const requiredRoles = [
|
||||||
|
{ value: "REPORT_COMPILER", name: "报告编制人" },
|
||||||
|
{ value: "INTERNAL_AUDITOR", name: "内审人" },
|
||||||
|
{ value: "PROJECT_LEAD", name: "项目负责人(项目组组长)" },
|
||||||
|
{ value: "TECHNICAL_LEAD", name: "技术负责人" },
|
||||||
|
{ value: "PROCESS_CONTROL_LEAD", name: "过程控制负责人" },
|
||||||
|
];
|
||||||
|
const missing = requiredRoles.find((r) => !allRoles.includes(r.value));
|
||||||
|
if (missing) {
|
||||||
|
message.warning(`请先配置${missing.name}(最少1人)`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 校验签字人员是否已完成签字
|
||||||
|
if (signers.length && !signers.every((s) => s.signStatusCode === 2)) {
|
||||||
|
message.warning("签字人员尚未全部完成签字,请先完成签字后再确认项目组");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const payload = teamMembers.map((m) => ({
|
const payload = teamMembers.map((m) => ({
|
||||||
|
|
@ -178,6 +256,22 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
}));
|
}));
|
||||||
const res = await evalProjectMemberSave(payload);
|
const res = await evalProjectMemberSave(payload);
|
||||||
if (res?.success !== false) {
|
if (res?.success !== false) {
|
||||||
|
// 保存签字人员(保存项目经理签字人)
|
||||||
|
if (signers.length) {
|
||||||
|
const signRes = await evalProjectMemberParticipantSave(
|
||||||
|
signers.map((s, idx) => ({
|
||||||
|
id: s.id,
|
||||||
|
projectId,
|
||||||
|
personnelId: s.personnelId,
|
||||||
|
personnelName: s.personnelName,
|
||||||
|
deptName: s.deptName,
|
||||||
|
signStatusCode: s.signStatusCode,
|
||||||
|
signFileUrl: s.signFileUrl,
|
||||||
|
sortOrder: idx + 1,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
if (signRes?.success === false) return;
|
||||||
|
}
|
||||||
message.success("保存成功");
|
message.success("保存成功");
|
||||||
fetchData();
|
fetchData();
|
||||||
props.getDetail();
|
props.getDetail();
|
||||||
|
|
@ -196,7 +290,8 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
render: (roles, record) => (
|
render: (roles, record) => (
|
||||||
<div style={{ display: "flex", flexWrap: "wrap", gap: 4 }}>
|
<div style={{ display: "flex", flexWrap: "wrap", gap: 4 }}>
|
||||||
{roles.map((r) => {
|
{roles.map((r) => {
|
||||||
const inOnly = r.role === "PROJECT_LEAD" || r.role === "PROCESS_CONTROL_LEAD";
|
const inOnly =
|
||||||
|
r.role === "PROJECT_LEAD" || r.role === "PROCESS_CONTROL_LEAD";
|
||||||
return (
|
return (
|
||||||
<Tag
|
<Tag
|
||||||
key={r.role}
|
key={r.role}
|
||||||
|
|
@ -251,8 +346,69 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// 参与风险分析人员签字(去掉分析意见、只能选择一个人)
|
||||||
|
const signerColumns = [
|
||||||
|
{ title: "姓名", dataIndex: "personnelName", ellipsis: true },
|
||||||
|
{ title: "部门/岗位", dataIndex: "deptName", ellipsis: true },
|
||||||
|
{
|
||||||
|
title: "签字状态",
|
||||||
|
render: (_, record, index) => {
|
||||||
|
const value = record.signStatusCode;
|
||||||
|
const signFileUrl = record.signFileUrl;
|
||||||
|
let text = "发起APP签字";
|
||||||
|
if (value === 1) text = "待APP签字";
|
||||||
|
if (value === 2) text = "已手写签字";
|
||||||
|
|
||||||
|
const btn = (
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
loading={evalSignTaskSaveLoading || memberParticipantSaveLoading}
|
||||||
|
disabled={value === 1 || value === 2 || readOnly}
|
||||||
|
onClick={() => handleSignApp(index)}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
|
||||||
|
// 已签字且有签字图片时,悬停展示签字图片(disabled 按钮不触发 hover,需用 span 包裹)
|
||||||
|
if (value === 2 && signFileUrl) {
|
||||||
|
return (
|
||||||
|
<Popover
|
||||||
|
placement="topRight"
|
||||||
|
content={
|
||||||
|
<Image
|
||||||
|
className="pf-sign-img"
|
||||||
|
src={signFileUrl}
|
||||||
|
alt="签字图片"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span>{btn}</span>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return btn;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "操作",
|
||||||
|
width: 80,
|
||||||
|
render: (_, record) => (
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
danger
|
||||||
|
size="small"
|
||||||
|
disabled={readOnly}
|
||||||
|
onClick={() => handleRemoveSigner(record.personnelId)}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Spin spinning={memberLoading}>
|
<Spin spinning={memberLoading || memberParticipantListLoading}>
|
||||||
<div>
|
<div>
|
||||||
<div className="pf-permission">
|
<div className="pf-permission">
|
||||||
<Tag color="blue" className="pf-tag">
|
<Tag color="blue" className="pf-tag">
|
||||||
|
|
@ -270,18 +426,16 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
title: "已配置人员",
|
title: "已配置人员",
|
||||||
value: `${teamMembers.length} 人`,
|
value: `${teamMembers.length} 人`,
|
||||||
valueColor: "#1e293b",
|
valueColor: "#1e293b",
|
||||||
|
|
||||||
iconBg: "#eff6ff",
|
iconBg: "#eff6ff",
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "roleCoverage",
|
key: "roleCoverage",
|
||||||
title: "已覆盖角色",
|
title: "已覆盖角色",
|
||||||
value: `${new Set(allRoles).size} / 11`,
|
value: `${new Set(allRoles).size} / 11`,
|
||||||
valueColor: "#1677ff",
|
valueColor: "#1677ff",
|
||||||
|
|
||||||
iconBg: "#e6f4ff",
|
iconBg: "#e6f4ff",
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "projectLead",
|
key: "projectLead",
|
||||||
|
|
@ -290,7 +444,6 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
valueColor: allRoles.includes("PROJECT_LEAD")
|
valueColor: allRoles.includes("PROJECT_LEAD")
|
||||||
? "#52c41a"
|
? "#52c41a"
|
||||||
: "#faad14",
|
: "#faad14",
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "processControlLead",
|
key: "processControlLead",
|
||||||
|
|
@ -301,7 +454,6 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
valueColor: allRoles.includes("PROCESS_CONTROL_LEAD")
|
valueColor: allRoles.includes("PROCESS_CONTROL_LEAD")
|
||||||
? "#52c41a"
|
? "#52c41a"
|
||||||
: "#faad14",
|
: "#faad14",
|
||||||
|
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
@ -322,6 +474,35 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
scroll={{ x: 1600, y: 320 }}
|
scroll={{ x: 1600, y: 320 }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
type="inner"
|
||||||
|
size="small"
|
||||||
|
title="下发至部门经理或负责人签字"
|
||||||
|
style={{ marginTop: 16 }}
|
||||||
|
>
|
||||||
|
<Table
|
||||||
|
dataSource={signers}
|
||||||
|
columns={signerColumns}
|
||||||
|
rowKey="personnelId"
|
||||||
|
pagination={false}
|
||||||
|
scroll={{ x: 800 }}
|
||||||
|
/>
|
||||||
|
{!readOnly && (
|
||||||
|
<Button
|
||||||
|
type="dashed"
|
||||||
|
size="small"
|
||||||
|
style={{ marginTop: 8 }}
|
||||||
|
disabled={signers.length >= 1}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedParticipantIds([]);
|
||||||
|
setParticipantModalOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
+ 添加参与人员
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
|
||||||
<details className="pf-role-guide">
|
<details className="pf-role-guide">
|
||||||
<summary className="pf-role-guide-title">
|
<summary className="pf-role-guide-title">
|
||||||
查看11类项目角色职责说明
|
查看11类项目角色职责说明
|
||||||
|
|
@ -348,7 +529,7 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
<Flex justify="flex-end" gap={8}>
|
<Flex justify="flex-end" gap={8}>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
loading={memberSaveLoading}
|
loading={memberSaveLoading || memberParticipantSaveLoading}
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
>
|
>
|
||||||
确认项目组
|
确认项目组
|
||||||
|
|
@ -444,6 +625,60 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
title="选择参与人员"
|
||||||
|
width={650}
|
||||||
|
open={participantModalOpen}
|
||||||
|
onCancel={() => setParticipantModalOpen(false)}
|
||||||
|
onOk={() => {
|
||||||
|
if (signers.length >= 1) {
|
||||||
|
message.warning("该签字人员最多只能配置1人");
|
||||||
|
setParticipantModalOpen(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const selected = participants.filter((p) =>
|
||||||
|
selectedParticipantIds.includes(p.id),
|
||||||
|
);
|
||||||
|
selected.forEach((p) => {
|
||||||
|
setSigners((prev) => {
|
||||||
|
if (prev.some((s) => s.personnelId === p.id)) return prev;
|
||||||
|
return [
|
||||||
|
...prev,
|
||||||
|
{
|
||||||
|
personnelId: p.id,
|
||||||
|
personnelName: p.name,
|
||||||
|
deptName: p.deptName,
|
||||||
|
projectId,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
setParticipantModalOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Table
|
||||||
|
dataSource={(() => {
|
||||||
|
const existing = signers.map((s) => s.personnelId);
|
||||||
|
return participants.filter((p) => !existing.includes(p.id));
|
||||||
|
})()}
|
||||||
|
rowKey="id"
|
||||||
|
rowSelection={{
|
||||||
|
type: "radio",
|
||||||
|
selectedRowKeys: selectedParticipantIds,
|
||||||
|
onChange: (keys) => setSelectedParticipantIds(keys),
|
||||||
|
}}
|
||||||
|
columns={[
|
||||||
|
{ title: "姓名", dataIndex: "name", width: 100 },
|
||||||
|
{ title: "部门", dataIndex: "deptName", width: 120 },
|
||||||
|
{ title: "岗位", dataIndex: "posName", width: 120 },
|
||||||
|
{ title: "能力", dataIndex: "capacity", width: 200 },
|
||||||
|
]}
|
||||||
|
pagination={false}
|
||||||
|
size="small"
|
||||||
|
locale={{ emptyText: "所有人员均已添加" }}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
</Spin>
|
</Spin>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue