fix
parent
de95e1620e
commit
9f4fc71d90
|
|
@ -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: "http://localhost:80",
|
//API_HOST: "http://localhost:80",
|
||||||
|
|
||||||
API_HOST: "http://192.168.0.134",
|
// API_HOST: "http://192.168.0.134",
|
||||||
// API_HOST: "http://192.168.0.150", //太浅
|
// API_HOST: "http://192.168.0.150", //太浅
|
||||||
// API_HOST: "https://gbs-gateway.qhdsafety.com",
|
API_HOST: "https://gbs-gateway.qhdsafety.com",
|
||||||
// API_HOST: "http://192.168.0.103", //huwei
|
// API_HOST: "http://192.168.0.103", //huwei
|
||||||
},
|
},
|
||||||
production: {
|
production: {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
安全评价检测检验机构从业告知书
|
||||||
|
:
|
||||||
|
机构名称
|
||||||
|
{account}
|
||||||
|
机构资质证书编号
|
||||||
|
{qualificationCertNo}
|
||||||
|
机构信息
|
||||||
|
公开网址
|
||||||
|
{infoDisclosureUrl}
|
||||||
|
办公地址
|
||||||
|
{businessAddress}
|
||||||
|
邮政
|
||||||
|
编码
|
||||||
|
|
||||||
|
法定代表人
|
||||||
|
{legalRepresentative}
|
||||||
|
联系人
|
||||||
|
{contactName}
|
||||||
|
联系
|
||||||
|
电话
|
||||||
|
{contactPhone}
|
||||||
|
项目名称
|
||||||
|
{projectName}
|
||||||
|
项目地址
|
||||||
|
{projectAddress}
|
||||||
|
项目所属行业
|
||||||
|
{industryText}
|
||||||
|
项目组组长
|
||||||
|
{projectLeader}
|
||||||
|
联系
|
||||||
|
电话
|
||||||
|
|
||||||
|
技术服务期限
|
||||||
|
|
||||||
|
计划现场勘验
|
||||||
|
(检测检验)时间
|
||||||
|
|
||||||
|
项目组成员、专业及工作任务(安全评价机构填写)
|
||||||
|
姓 名
|
||||||
|
专 业
|
||||||
|
工作任务
|
||||||
|
{#members}{name}
|
||||||
|
{major}
|
||||||
|
{task}{/members}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
现场检测检验人员(安全生产检测检验机构填写)
|
||||||
|
姓 名
|
||||||
|
检测检验项目
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
我单位承接了 □安全评价/□安全生产检测检验项目,拟于近期开展技术服务活动,现按照规定将有关信息告知如下。
|
||||||
|
机构(盖章)
|
||||||
|
年 月
|
||||||
|
|
||||||
|
|
@ -179,6 +179,16 @@ export const evalProjectMemberPage = declareRequest(
|
||||||
"Get > /safetyEval/institution/eval-project-member/page",
|
"Get > /safetyEval/institution/eval-project-member/page",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const evalProjectEstablishedAttachSave = declareRequest(
|
||||||
|
"projectEstablishedAttachSaveLoading",
|
||||||
|
"Post > /safetyEval/institution/eval-project-member/saveProjectEstablishedAttach",
|
||||||
|
);
|
||||||
|
|
||||||
|
export const evalProjectEstablishedAttachGet = declareRequest(
|
||||||
|
"projectEstablishedAttachGetLoading",
|
||||||
|
"Get > /safetyEval/institution/eval-project-member/getProjectEstablishedAttach",
|
||||||
|
);
|
||||||
|
|
||||||
export const evalProjectMemberSave = declareRequest(
|
export const evalProjectMemberSave = declareRequest(
|
||||||
"memberSaveLoading",
|
"memberSaveLoading",
|
||||||
"Post > @/safetyEval/institution/eval-project-member/save",
|
"Post > @/safetyEval/institution/eval-project-member/save",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { Form, Image, Upload, message } from "antd";
|
import { Button, Form, Image, Upload, message } from "antd";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { PlusOutlined } from "@ant-design/icons";
|
import { PlusOutlined, UploadOutlined } from "@ant-design/icons";
|
||||||
|
|
||||||
/** 批量上传接口:一次请求上传 1~N 个文件,表单字段名为 files */
|
/** 批量上传接口:一次请求上传 1~N 个文件,表单字段名为 files */
|
||||||
const BATCH_UPLOAD_ACTION = `${window.process.env.app.API_HOST}/safetyEval/file/upload/batch`;
|
const BATCH_UPLOAD_ACTION = `${window.process.env.app.API_HOST}/safetyEval/file/upload/batch`;
|
||||||
|
|
@ -8,7 +8,23 @@ const BATCH_UPLOAD_ACTION = `${window.process.env.app.API_HOST}/safetyEval/file/
|
||||||
const isImage = (url) =>
|
const isImage = (url) =>
|
||||||
/\.(png|jpe?g|gif|bmp|webp|svg)(\?.*)?$/i.test(url || "");
|
/\.(png|jpe?g|gif|bmp|webp|svg)(\?.*)?$/i.test(url || "");
|
||||||
|
|
||||||
export default function AttachmentUpload({ name, label, disabled, maxCount, accept, extra ,rules, style, keepOriginFile }) {
|
/**
|
||||||
|
* @param {string} [listType] - 上传列表样式,默认 picture-card;传 text 时为按钮触发形态
|
||||||
|
* @param {string} [uploadText] - 触发区文案,默认“上传附件”
|
||||||
|
*/
|
||||||
|
export default function AttachmentUpload({
|
||||||
|
name,
|
||||||
|
label,
|
||||||
|
disabled,
|
||||||
|
maxCount,
|
||||||
|
accept,
|
||||||
|
extra,
|
||||||
|
rules,
|
||||||
|
style,
|
||||||
|
keepOriginFile,
|
||||||
|
listType = "picture-card",
|
||||||
|
uploadText = "上传附件",
|
||||||
|
}) {
|
||||||
const [previewImage, setPreviewImage] = useState("");
|
const [previewImage, setPreviewImage] = useState("");
|
||||||
// 同一次选择的文件先入队,等微任务结束后合并为一个批量请求
|
// 同一次选择的文件先入队,等微任务结束后合并为一个批量请求
|
||||||
const queueRef = useRef([]);
|
const queueRef = useRef([]);
|
||||||
|
|
@ -104,7 +120,7 @@ export default function AttachmentUpload({ name, label, disabled, maxCount, acce
|
||||||
>
|
>
|
||||||
<Upload
|
<Upload
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
listType="picture-card"
|
listType={listType}
|
||||||
// maxCount 为 1 时仍单选,其余场景允许一次选择多个文件
|
// maxCount 为 1 时仍单选,其余场景允许一次选择多个文件
|
||||||
multiple={!maxCount || maxCount > 1}
|
multiple={!maxCount || maxCount > 1}
|
||||||
customRequest={customRequest}
|
customRequest={customRequest}
|
||||||
|
|
@ -136,10 +152,16 @@ export default function AttachmentUpload({ name, label, disabled, maxCount, acce
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{listType === "text" ? (
|
||||||
|
<Button type="dashed" size="small" icon={<UploadOutlined />}>
|
||||||
|
{uploadText}
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
<button style={{ border: 0, background: "none" }} type="button">
|
<button style={{ border: 0, background: "none" }} type="button">
|
||||||
<PlusOutlined />
|
<PlusOutlined />
|
||||||
<div style={{ marginTop: 8 }}>上传附件</div>
|
<div style={{ marginTop: 8 }}>{uploadText}</div>
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
</Upload>
|
</Upload>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{previewImage && <Image
|
{previewImage && <Image
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,10 @@ const EvalProject = (props) => {
|
||||||
>
|
>
|
||||||
删除
|
删除
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button type="link" size="small" onClick={() =>
|
||||||
|
props.history.push(`/container/SafetyEvalBusiness/ProjectFlow?id=${record.id}&readOnly=1`)}>
|
||||||
|
项目节点
|
||||||
|
</Button>
|
||||||
</TableAction>
|
</TableAction>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -235,44 +235,7 @@ const ControlContent = ({ readOnly, ...props }) => {
|
||||||
</div>
|
</div>
|
||||||
<Image src={processControl?.reviewerSignatureUrl} width={120} height={80} />
|
<Image src={processControl?.reviewerSignatureUrl} width={120} height={80} />
|
||||||
</div>}
|
</div>}
|
||||||
{!readOnly&&<Collapse
|
|
||||||
style={{ marginTop: 12 }}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
key: "checklist",
|
|
||||||
label: "过程控制完整核查清单(13项)",
|
|
||||||
children: (
|
|
||||||
<ol
|
|
||||||
style={{
|
|
||||||
margin: 0,
|
|
||||||
paddingLeft: 20,
|
|
||||||
fontSize: 14,
|
|
||||||
color: "#475569",
|
|
||||||
lineHeight: 1.8,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<li>合同签订前是否进行项目风险分析。</li>
|
|
||||||
<li>是否签订技术服务合同。</li>
|
|
||||||
<li>是否下达项目任务通知单。</li>
|
|
||||||
<li>是否有项目组成立和项目负责人任命记录。</li>
|
|
||||||
<li>是否编制项目实施计划。</li>
|
|
||||||
<li>现场检查记录是否完整、有效。</li>
|
|
||||||
<li>是否有书面整改通知单并由被评价单位盖章或签字确认。</li>
|
|
||||||
<li>
|
|
||||||
是否进行现场复查,复查单是否双方签名或盖章并注明日期。
|
|
||||||
</li>
|
|
||||||
<li>是否有现场勘查、整改复查影像资料。</li>
|
|
||||||
<li>是否完成内审、技审并保留审核记录、签字和日期。</li>
|
|
||||||
<li>委托方提供资料是否齐全并由被评价单位盖章。</li>
|
|
||||||
<li>
|
|
||||||
委托方资料、评价过程资料和评价报告存档是否符合要求。
|
|
||||||
</li>
|
|
||||||
<li>存档资料是否完整且具有可追溯性。</li>
|
|
||||||
</ol>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>}
|
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,10 @@ 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 AttachmentUpload from "~/components/AttachmentUpload";
|
import AttachmentUpload from "~/components/AttachmentUpload";
|
||||||
import { ROLE_DEFINITIONS_MAP } from '~/enumerate/constant'
|
import { ROLE_DEFINITIONS_MAP, ROLE_DEFINITIONS } from '~/enumerate/constant'
|
||||||
|
import { QUALIFICATION_INDUSTRY_OPTIONS_MAP } from "~/enumerate/enterpriseOptions";
|
||||||
import LayoutFooterPortal from "~/components/LayoutFooterPortal";
|
import LayoutFooterPortal from "~/components/LayoutFooterPortal";
|
||||||
|
import { fillDocxTemplate } from "~/utils/fillDocxTemplate";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
|
@ -36,22 +38,9 @@ const attachRequiredRules = (label) => [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const downloadTemplate = async () => {
|
|
||||||
try {
|
|
||||||
const res = await fetch("https://test-dragon-yf-pub.oss-cn-hangzhou.aliyuncs.com/jjb/6a6bff3ee4b021a75404adfb.docx");
|
|
||||||
const blob = await res.blob();
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
const a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = "从业告知书模板.docx";
|
|
||||||
a.click();
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
} catch {
|
|
||||||
message.error("下载失败,请重试");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const NoticePanel = ({ readOnly }) => (
|
|
||||||
|
const NoticePanel = ({ readOnly, downloadTemplate }) => (
|
||||||
<div>
|
<div>
|
||||||
<div className="pf-section-header">
|
<div className="pf-section-header">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -256,7 +245,7 @@ const SurveyContent = ({ readOnly, ...props }) => {
|
||||||
const [activeStage, setActiveStage] = useState("PRACTICE_NOTIFICATION");
|
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 { evalSurveySaveAttachLoading, evalProjectDetailData } = props.safetyEvalBusiness;
|
||||||
const projectId = router.query?.id;
|
const projectId = router.query?.id;
|
||||||
const currentIdx = STAGES.findIndex((s) => s.key === activeStage);
|
const currentIdx = STAGES.findIndex((s) => s.key === activeStage);
|
||||||
const isFirst = currentIdx === 0;
|
const isFirst = currentIdx === 0;
|
||||||
|
|
@ -295,6 +284,57 @@ const SurveyContent = ({ readOnly, ...props }) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const downloadTemplate = async () => {
|
||||||
|
const orgInfo = JSON.parse(sessionStorage.getItem('orgInfo'));
|
||||||
|
const industryText = String(evalProjectDetailData.industryCode || "")
|
||||||
|
.split(",")
|
||||||
|
.map((code) => QUALIFICATION_INDUSTRY_OPTIONS_MAP[code])
|
||||||
|
.join("、");
|
||||||
|
// 项目组成员(同项目组 tab 页数据):姓名/专业/工作任务
|
||||||
|
const memberRes = await props.evalProjectMemberPage({ projectId });
|
||||||
|
const members = (memberRes?.data || []).map((item) => ({
|
||||||
|
name: item.personnelName,
|
||||||
|
major: item.capacity || "",
|
||||||
|
task:
|
||||||
|
item.responsibility ||
|
||||||
|
(item.role || [])
|
||||||
|
.map((r) => ROLE_DEFINITIONS.find((d) => d.value === r)?.summary)
|
||||||
|
.filter(Boolean)
|
||||||
|
.join("、"),
|
||||||
|
isLeader: (item.role || []).includes("PROJECT_LEAD"),
|
||||||
|
}));
|
||||||
|
// 项目组组长取自项目组成员中的 PROJECT_LEAD,展示同 namesByRole:如"张三(化工)"
|
||||||
|
const projectLeader = members
|
||||||
|
.filter((m) => m.isLeader)
|
||||||
|
.map((m) => `${m.name}${m.major ? `(${m.major})` : ""}`)
|
||||||
|
.join("、");
|
||||||
|
const data = {
|
||||||
|
account: orgInfo.account,
|
||||||
|
qualificationCertNo: orgInfo.qualificationCertNo,
|
||||||
|
infoDisclosureUrl: orgInfo.infoDisclosureUrl,
|
||||||
|
businessAddress: orgInfo.businessAddress,
|
||||||
|
legalRepresentative: orgInfo.legalRepresentative,
|
||||||
|
contactName: orgInfo.contactName,
|
||||||
|
contactPhone: orgInfo.contactPhone,
|
||||||
|
projectName: evalProjectDetailData.projectName,
|
||||||
|
projectAddress: evalProjectDetailData.customerAddress || "",
|
||||||
|
industryText,
|
||||||
|
projectLeader,
|
||||||
|
members,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
await fillDocxTemplate(
|
||||||
|
'https://gbs-cqaqpj.oss-cn-beijing.aliyuncs.com/jjb/6a913235e4b0b3767a78622d.docx',
|
||||||
|
data,
|
||||||
|
`安全评价检测检验机构从业告知书.docx`,
|
||||||
|
{ download: true },
|
||||||
|
);
|
||||||
|
message.success("导出成功");
|
||||||
|
} catch {
|
||||||
|
message.error("导出失败,请重试");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadAttachments();
|
loadAttachments();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
@ -395,7 +435,7 @@ const SurveyContent = ({ readOnly, ...props }) => {
|
||||||
|
|
||||||
<Form form={form} layout="vertical" disabled={readOnly} scrollToFirstError>
|
<Form form={form} layout="vertical" disabled={readOnly} scrollToFirstError>
|
||||||
<div style={{ display: activeStage === "PRACTICE_NOTIFICATION" ? "block" : "none" }}>
|
<div style={{ display: activeStage === "PRACTICE_NOTIFICATION" ? "block" : "none" }}>
|
||||||
<NoticePanel readOnly={readOnly} />
|
<NoticePanel readOnly={readOnly} downloadTemplate={downloadTemplate} />
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: activeStage === "SITE_INSPECTION_FORM" ? "block" : "none" }}>
|
<div style={{ display: activeStage === "SITE_INSPECTION_FORM" ? "block" : "none" }}>
|
||||||
<InspectionPanel dataSource={surveyPersonnel} evalProjectDetailData={evalProjectDetailData} readOnly={readOnly} />
|
<InspectionPanel dataSource={surveyPersonnel} evalProjectDetailData={evalProjectDetailData} readOnly={readOnly} />
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Tag,
|
Tag,
|
||||||
Button,
|
Button,
|
||||||
|
|
@ -7,6 +7,7 @@ import {
|
||||||
Modal,
|
Modal,
|
||||||
Radio,
|
Radio,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
|
Form,
|
||||||
message,
|
message,
|
||||||
Spin,
|
Spin,
|
||||||
Card,
|
Card,
|
||||||
|
|
@ -18,6 +19,7 @@ import { NS_SAFETY_EVAL_BUSINESS } from "~/enumerate/namespace";
|
||||||
import { tools } from "@cqsjjb/jjb-common-lib";
|
import { tools } from "@cqsjjb/jjb-common-lib";
|
||||||
import { ROLE_DEFINITIONS, EVAL_TYPE_MAP } from "~/enumerate/constant";
|
import { ROLE_DEFINITIONS, EVAL_TYPE_MAP } from "~/enumerate/constant";
|
||||||
import StatCardGroup from "~/components/StatCardGroup";
|
import StatCardGroup from "~/components/StatCardGroup";
|
||||||
|
import AttachmentUpload from "~/components/AttachmentUpload";
|
||||||
import LayoutFooterPortal from "~/components/LayoutFooterPortal";
|
import LayoutFooterPortal from "~/components/LayoutFooterPortal";
|
||||||
import { fillDocxTemplate } from "~/utils/fillDocxTemplate";
|
import { fillDocxTemplate } from "~/utils/fillDocxTemplate";
|
||||||
|
|
||||||
|
|
@ -33,6 +35,8 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
evalProjectMemberParticipantSave,
|
evalProjectMemberParticipantSave,
|
||||||
evalProjectMemberParticipantList,
|
evalProjectMemberParticipantList,
|
||||||
evalSignTaskSave,
|
evalSignTaskSave,
|
||||||
|
evalProjectEstablishedAttachSave,
|
||||||
|
evalProjectEstablishedAttachGet,
|
||||||
} = props;
|
} = props;
|
||||||
const {
|
const {
|
||||||
evalProjectDetailData,
|
evalProjectDetailData,
|
||||||
|
|
@ -49,6 +53,9 @@ 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([]);
|
||||||
|
// 人员任命书附件(项目成立附件 PROJECT_ESTABLISHED):局部表单承载上传,保存记录主键供更新
|
||||||
|
const [attachForm] = Form.useForm();
|
||||||
|
const establishedAttachIdRef = useRef(null);
|
||||||
// 参与风险分析人员签字
|
// 参与风险分析人员签字
|
||||||
const [participantModalOpen, setParticipantModalOpen] = useState(false);
|
const [participantModalOpen, setParticipantModalOpen] = useState(false);
|
||||||
const [selectedParticipantIds, setSelectedParticipantIds] = useState([]);
|
const [selectedParticipantIds, setSelectedParticipantIds] = useState([]);
|
||||||
|
|
@ -77,6 +84,39 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
if (signRes?.success !== false) {
|
if (signRes?.success !== false) {
|
||||||
setSigners(signRes?.data || []);
|
setSigners(signRes?.data || []);
|
||||||
}
|
}
|
||||||
|
// 人员任命书附件回显
|
||||||
|
const attachRes = await evalProjectEstablishedAttachGet({ projectId });
|
||||||
|
if (attachRes?.data) {
|
||||||
|
establishedAttachIdRef.current = attachRes.data.id || null;
|
||||||
|
let files = [];
|
||||||
|
try {
|
||||||
|
files = JSON.parse(attachRes.data.fileUrl) || [];
|
||||||
|
} catch {}
|
||||||
|
attachForm.setFieldsValue({
|
||||||
|
appointmentFiles: Array.isArray(files) ? files : [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 人员任命书上传/删除后自动保存;接口不回传主键,保存后重查同步 id 供下次更新
|
||||||
|
const handleAttachChange = async (_, { appointmentFiles: files = [] }) => {
|
||||||
|
if (readOnly) return;
|
||||||
|
if (files.some((f) => f.status === "uploading")) return;
|
||||||
|
if (files.length && files.some((f) => !(f.status === "done" && f.url))) return;
|
||||||
|
if (!files.length && !establishedAttachIdRef.current) return;
|
||||||
|
const res = await evalProjectEstablishedAttachSave({
|
||||||
|
...(establishedAttachIdRef.current
|
||||||
|
? { id: establishedAttachIdRef.current }
|
||||||
|
: {}),
|
||||||
|
projectId,
|
||||||
|
attachTypeCode: "PROJECT_ESTABLISHED",
|
||||||
|
fileUrl: JSON.stringify(files),
|
||||||
|
});
|
||||||
|
if (res?.success !== false) {
|
||||||
|
message.success("人员任命书已保存");
|
||||||
|
const getRes = await evalProjectEstablishedAttachGet({ projectId });
|
||||||
|
if (getRes?.data?.id) establishedAttachIdRef.current = getRes.data.id;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -520,11 +560,11 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
pagination={false}
|
pagination={false}
|
||||||
scroll={{ x: 800 }}
|
scroll={{ x: 800 }}
|
||||||
/>
|
/>
|
||||||
|
<Flex justify="space-between" align="flex-start" style={{ marginTop: 8 }}>
|
||||||
{!readOnly && (
|
{!readOnly && (
|
||||||
<Button
|
<Button
|
||||||
type="dashed"
|
type="dashed"
|
||||||
size="small"
|
size="small"
|
||||||
style={{ marginTop: 8 }}
|
|
||||||
disabled={signers.length >= 1}
|
disabled={signers.length >= 1}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedParticipantIds([]);
|
setSelectedParticipantIds([]);
|
||||||
|
|
@ -534,6 +574,19 @@ const TeamContent = ({ readOnly, ...props }) => {
|
||||||
+ 添加参与人员
|
+ 添加参与人员
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
<Form form={attachForm} disabled={readOnly} onValuesChange={handleAttachChange}>
|
||||||
|
<AttachmentUpload
|
||||||
|
name="appointmentFiles"
|
||||||
|
label="人员任命书"
|
||||||
|
rules={[{ required: true, message: "请上传人员任命书" }]}
|
||||||
|
maxCount={10}
|
||||||
|
accept=".pdf,.doc,.docx,.png,.jpg,.jpeg"
|
||||||
|
listType="text"
|
||||||
|
uploadText="上传人员任命书"
|
||||||
|
extra="支持 PDF、Word、PNG、JPG 格式,最多上传 10 个文件,上传完成自动保存"
|
||||||
|
/>
|
||||||
|
</Form>
|
||||||
|
</Flex>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{!readOnly &&<details className="pf-role-guide">
|
{!readOnly &&<details className="pf-role-guide">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue