dev_1.2
tangjie 2026-07-28 13:58:58 +08:00
parent 7aa52f77fe
commit 23a6e35604
3 changed files with 180 additions and 97 deletions

View File

@ -71,7 +71,6 @@ const InternalReviewContent = (props) => {
setRows(next); setRows(next);
}; };
const isDispatched = const isDispatched =
internalReview?.reviewerSignatureTaskStatus === "dispatched"; internalReview?.reviewerSignatureTaskStatus === "dispatched";
const problemCount = rows.filter( const problemCount = rows.filter(
@ -80,41 +79,51 @@ const InternalReviewContent = (props) => {
const handleAssign = async () => { const handleAssign = async () => {
if (!projectId) return; if (!projectId) return;
const res = await props.evalInternalReviewAssign({ projectId, signTaskPersonCmd:{ await handleConfirm("not_passed");
signerPersonnelId: selectedReviewer, const res = await props.evalInternalReviewAssign({
signerName: reviewers.find((item) => item.personnelId === selectedReviewer)?.personnelName , projectId,
} }); signTaskPersonCmd: {
signerPersonnelId: selectedReviewer,
signerName: reviewers.find(
(item) => item.personnelId === selectedReviewer,
)?.personnelName,
},
});
if (res?.success !== false) { if (res?.success !== false) {
message.success("已下发签字任务"); message.success("已下发签字任务");
fetchDetail();
} }
}; };
const handleConfirm = async (resultCode) => { const handleConfirm = async (resultCode) => {
if (!projectId) return; return new Promise(async (resolve, reject) => {
const payload = { if (!projectId) return;
id: internalReview?.id, const payload = {
projectId, id: internalReview?.id,
resultCode, projectId,
opinionContent: overallOpinion, resultCode,
reviewItems: rows.map((r) => ({ opinionContent: overallOpinion,
bizType: "eval_internal_review", reviewItems: rows.map((r) => ({
bizId: internalReview?.id, bizType: "eval_internal_review",
reviewDimensionCode: r.reviewDimensionCode, bizId: internalReview?.id,
reviewDimensionName: r.reviewDimensionName, reviewDimensionCode: r.reviewDimensionCode,
reviewFocus: r.reviewFocus, reviewDimensionName: r.reviewDimensionName,
reviewConclusion: r.reviewConclusion, reviewFocus: r.reviewFocus,
reviewOpinion: r.reviewOpinion, reviewConclusion: r.reviewConclusion,
})), reviewOpinion: r.reviewOpinion,
}; })),
const res = await props.evalInternalReviewConfirm(payload); };
if (res?.success !== false) { const res = await props.evalInternalReviewConfirm(payload);
message.success( if (res?.success !== false) {
resultCode === "passed" ? "已提交" : "已保存", message.success(resultCode === "passed" ? "已提交" : "已保存");
); resolve(res);
fetchDetail(); if (resultCode === "passed") {
props.getDetail?.(); props.getDetail?.();
} }
}
else{
reject(res);
}
});
}; };
const columns = [ const columns = [
@ -128,7 +137,9 @@ const InternalReviewContent = (props) => {
<Select <Select
value={val} value={val}
size="small" size="small"
style={{ width: 100 }} style={{ width: 130 }}
allowClear
placeholder="请选择结论"
onChange={(v) => updateRow(idx, "reviewConclusion", v)} onChange={(v) => updateRow(idx, "reviewConclusion", v)}
> >
{CONCLUSION_OPTIONS.map((opt) => ( {CONCLUSION_OPTIONS.map((opt) => (
@ -169,9 +180,20 @@ const InternalReviewContent = (props) => {
<Col span={8}> <Col span={8}>
<Card size="small"> <Card size="small">
<Typography.Text type="secondary">内审人</Typography.Text> <Typography.Text type="secondary">内审人</Typography.Text>
<div style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}> <div
<Tooltip title={(reviewers || []).map((r) => r.personnelName).join("、")}> style={{
<strong>{(reviewers || []).map((r) => r.personnelName).join("、") || "-"}</strong> overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
}}
>
<Tooltip
title={(reviewers || []).map((r) => r.personnelName).join("、")}
>
<strong>
{(reviewers || []).map((r) => r.personnelName).join("、") ||
"-"}
</strong>
</Tooltip> </Tooltip>
</div> </div>
</Card> </Card>
@ -213,6 +235,9 @@ const InternalReviewContent = (props) => {
<TextArea <TextArea
rows={2} rows={2}
value={overallOpinion} value={overallOpinion}
allowClear
placeholder="请输入总体审核意见"
maxLength={120}
onChange={(e) => setOverallOpinion(e.target.value)} onChange={(e) => setOverallOpinion(e.target.value)}
style={{ marginTop: 4 }} style={{ marginTop: 4 }}
/> />
@ -237,7 +262,6 @@ const InternalReviewContent = (props) => {
onClick={handleAssign} onClick={handleAssign}
loading={internalReviewAssignLoading} loading={internalReviewAssignLoading}
disabled={isDispatched || !selectedReviewer} disabled={isDispatched || !selectedReviewer}
> >
{isDispatched ? "已下发APP签字" : "下发APP签字"} {isDispatched ? "已下发APP签字" : "下发APP签字"}
</Button> </Button>

View File

@ -61,6 +61,13 @@ const NoticePanel = () => (
下载模板 下载模板
</Button> </Button>
</div> </div>
<AttachmentUpload
name="PRACTICE_NOTIFICATION"
label="从业告知书"
maxCount={1}
accept=".docx"
extra="仅支持上传 Word 格式文件"
/>
</div> </div>
); );
@ -111,19 +118,72 @@ const InspectionPanel = ({ dataSource = [], evalProjectDetailData = {} }) => {
<span>签到日期{dataSource?.[0]?.singInTime ? dayjs(dataSource?.[0]?.singInTime).format('YYYY-MM-DD') : '-'}</span> <span>签到日期{dataSource?.[0]?.singInTime ? dayjs(dataSource?.[0]?.singInTime).format('YYYY-MM-DD') : '-'}</span>
</div> </div>
</Card> </Card>
<AttachmentUpload
name="SITE_INSPECTION_FORM"
label="现场检查表"
maxCount={10}
accept=".pdf,.doc,.docx,.xls,.xlsx"
extra="检查表应包含项目名称检查日期检查人员检查依据逐项检查结果和不符合项记录上传后与人员打卡记录共同作为现场踏勘凭证
支持ExcelWordPDF和清晰扫描件"
/>
</div> </div>
); );
}; };
const SimpleUploadPanel = ({ index, title, desc }) => ( const RectificationNoticePanel = () => (
<div> <div>
<div className="pf-section-header"> <div className="pf-section-header">
<div> <div>
<span style={{ fontSize: 20, fontWeight: 600, color: "#1677ff", marginRight: 8 }}>{index}</span> <span style={{ fontSize: 20, fontWeight: 600, color: "#1677ff", marginRight: 8 }}>03</span>
<Typography.Text strong style={{ fontSize: 15 }}>{title}</Typography.Text> <Typography.Text strong style={{ fontSize: 15 }}>整改通知单上传</Typography.Text>
<Typography.Paragraph type="secondary" style={{ margin: 0 }}>{desc}</Typography.Paragraph> <Typography.Paragraph type="secondary" style={{ margin: 0 }}>本节点不在线编制整改通知只归档机构已出具的整改通知单文件上传成功即完成后续可替换修改</Typography.Paragraph>
</div> </div>
</div> </div>
<AttachmentUpload
name="RECTIFICATION_NOTICE"
label="整改通知单"
maxCount={10}
accept=".pdf,.doc,.docx,.jpg,.jpeg,.png,.xls,.xlsx"
extra="支持 PDF、Word、JPG、PNG、Excel 格式,最多上传 10 个文件"
/>
</div>
);
const EnterpriseRectificationPanel = () => (
<div>
<div className="pf-section-header">
<div>
<span style={{ fontSize: 20, fontWeight: 600, color: "#1677ff", marginRight: 8 }}>04</span>
<Typography.Text strong style={{ fontSize: 15 }}>企业整改报告上传</Typography.Text>
<Typography.Paragraph type="secondary" style={{ margin: 0 }}>企业线下提交整改报告由机构人员上传归档本系统不提供企业在线提交和逐项整改流程</Typography.Paragraph>
</div>
</div>
<AttachmentUpload
name="ENTERPRISE_RECTIFICATION"
label="企业整改报告"
maxCount={10}
accept=".pdf,.doc,.docx,.jpg,.jpeg,.png,.zip,.rar,.7z"
extra="支持 PDF、Word、压缩包、图片格式最多上传 10 个文件"
/>
</div>
);
const RectificationReviewPanel = () => (
<div>
<div className="pf-section-header">
<div>
<span style={{ fontSize: 20, fontWeight: 600, color: "#1677ff", marginRight: 8 }}>05</span>
<Typography.Text strong style={{ fontSize: 15 }}>整改复查单上传</Typography.Text>
<Typography.Paragraph type="secondary" style={{ margin: 0 }}>机构人员现场复查后将经双方签字确认的整改复查单上传归档上传后本节点自动标记完成</Typography.Paragraph>
</div>
</div>
<AttachmentUpload
name="RECTIFICATION_REVIEW"
label="整改情况复查单"
maxCount={10}
accept=".pdf,.doc,.docx,.jpg,.jpeg,.png,.xls,.xlsx"
extra="支持 PDF、Word、JPG、PNG、Excel 格式,最多上传 10 个文件"
/>
</div> </div>
); );
@ -217,39 +277,22 @@ const SurveyContent = (props) => {
items={STAGES.map((s) => ({ title: s.label }))} items={STAGES.map((s) => ({ title: s.label }))}
/> />
{activeStage === "PRACTICE_NOTIFICATION" && <NoticePanel />}
{activeStage === "SITE_INSPECTION_FORM" && <InspectionPanel dataSource={surveyPersonnel} evalProjectDetailData={evalProjectDetailData} />}
{activeStage === "RECTIFICATION_NOTICE" && (
<SimpleUploadPanel
index="03" title="整改通知单上传"
desc="本节点不在线编制整改通知,只归档机构已出具的《整改通知单》文件;上传成功即完成,后续可替换修改。"
/>
)}
{activeStage === "ENTERPRISE_RECTIFICATION" && (
<SimpleUploadPanel
index="04" title="企业整改报告上传"
desc="企业线下提交《整改报告》后,由机构人员上传归档;本系统不提供企业在线提交和逐项整改流程。"
/>
)}
{activeStage === "RECTIFICATION_REVIEW" && (
<SimpleUploadPanel
index="05" title="整改复查单上传"
desc="机构人员现场复查后,将经双方签字确认的《整改复查单》上传归档;上传后本节点自动标记完成。"
/>
)}
<Form form={form} layout="vertical"> <Form form={form} layout="vertical">
{STAGES.map((s) => ( <div style={{ display: activeStage === "PRACTICE_NOTIFICATION" ? "block" : "none" }}>
<div key={s.key} style={{ display: s.key === activeStage ? "block" : "none" }}> <NoticePanel />
<AttachmentUpload </div>
name={s.key} <div style={{ display: activeStage === "SITE_INSPECTION_FORM" ? "block" : "none" }}>
label="上传附件" <InspectionPanel dataSource={surveyPersonnel} evalProjectDetailData={evalProjectDetailData} />
maxCount={10} </div>
accept=".pdf,.doc,.docx,.jpg,.jpeg,.png,.xls,.xlsx" <div style={{ display: activeStage === "RECTIFICATION_NOTICE" ? "block" : "none" }}>
extra="支持 PDF、Word、JPG、PNG、Excel 格式,最多上传 10 个文件" <RectificationNoticePanel />
/> </div>
</div> <div style={{ display: activeStage === "ENTERPRISE_RECTIFICATION" ? "block" : "none" }}>
))} <EnterpriseRectificationPanel />
</div>
<div style={{ display: activeStage === "RECTIFICATION_REVIEW" ? "block" : "none" }}>
<RectificationReviewPanel />
</div>
</Form> </Form>
<Flex justify="flex-end" gap={8} style={{ marginTop: 16 }}> <Flex justify="flex-end" gap={8} style={{ marginTop: 16 }}>

View File

@ -76,6 +76,7 @@ const TechnicalReviewContent = (props) => {
const handleAssign = async () => { const handleAssign = async () => {
if (!projectId) return; if (!projectId) return;
await handleConfirm("2");
const res = await props.evalTechReviewAssign({ const res = await props.evalTechReviewAssign({
projectId, projectId,
signTaskPersonCmd: { signTaskPersonCmd: {
@ -87,35 +88,40 @@ const TechnicalReviewContent = (props) => {
}); });
if (res?.success !== false) { if (res?.success !== false) {
message.success("已下发签字任务"); message.success("已下发签字任务");
fetchDetail();
} }
}; };
const handleConfirm = async (resultCode) => { const handleConfirm = async (resultCode) => {
if (!projectId) return; if (!projectId) return;
const payload = { return new Promise(async (resolve, reject) => {
id: techReview?.id, const payload = {
projectId, id: techReview?.id,
resultCode, projectId,
opinionContent: overallOpinion, resultCode,
reviewItems: rows.map((r) => ({ opinionContent: overallOpinion,
bizType: "eval_tech_review", reviewItems: rows.map((r) => ({
bizId: techReview?.id, bizType: "eval_tech_review",
reviewDimensionCode: r.reviewDimensionCode, bizId: techReview?.id,
reviewDimensionName: r.reviewDimensionName, reviewDimensionCode: r.reviewDimensionCode,
reviewFocus: r.reviewFocus, reviewDimensionName: r.reviewDimensionName,
reviewConclusion: r.reviewConclusion, reviewFocus: r.reviewFocus,
reviewOpinion: r.reviewOpinion, reviewConclusion: r.reviewConclusion,
})), reviewOpinion: r.reviewOpinion,
}; })),
const res = await props.evalTechReviewConfirm(payload); };
if (res?.success !== false) { const res = await props.evalTechReviewConfirm(payload);
message.success( if (res?.success !== false) {
resultCode === "1" ? "已确认技审并提交过程控制" : "已保存", resolve(res);
); message.success(
fetchDetail(); resultCode === "1" ? "已确认技审并提交过程控制" : "已保存",
props.getDetail?.(); );
} if (resultCode === "1") {
props.getDetail?.();
}
} else {
reject(res);
}
});
}; };
const columns = [ const columns = [
@ -129,7 +135,9 @@ const TechnicalReviewContent = (props) => {
<Select <Select
value={val} value={val}
size="small" size="small"
style={{ width: 100 }} style={{ width: 130 }}
allowClear
placeholder="请选择结论"
onChange={(v) => updateRow(idx, "reviewConclusion", v)} onChange={(v) => updateRow(idx, "reviewConclusion", v)}
> >
{CONCLUSION_OPTIONS.map((opt) => ( {CONCLUSION_OPTIONS.map((opt) => (
@ -228,6 +236,9 @@ const TechnicalReviewContent = (props) => {
<TextArea <TextArea
rows={2} rows={2}
value={overallOpinion} value={overallOpinion}
allowClear
placeholder="请输入技术审核意见"
maxLength={120}
onChange={(e) => setOverallOpinion(e.target.value)} onChange={(e) => setOverallOpinion(e.target.value)}
style={{ marginTop: 4 }} style={{ marginTop: 4 }}
/> />
@ -259,7 +270,12 @@ const TechnicalReviewContent = (props) => {
</Flex> </Flex>
<Flex justify="flex-end" gap={8} style={{ marginTop: 16 }}> <Flex justify="flex-end" gap={8} style={{ marginTop: 16 }}>
<Button onClick={() => handleConfirm("2")}>保存意见</Button> <Button
loading={props.safetyEvalBusiness?.techReviewConfirmLoading}
onClick={() => handleConfirm("2")}
>
保存意见
</Button>
<Button <Button
type="primary" type="primary"
onClick={() => handleConfirm("1")} onClick={() => handleConfirm("1")}