Merge remote-tracking branch 'origin/dev-tmp1' into dev-tmp1
# Conflicts: # jjb.config.jsdev-tmp1
commit
c0a0261561
|
|
@ -13,8 +13,8 @@ module.exports = {
|
|||
//API_HOST: "http://localhost:80",
|
||||
|
||||
// API_HOST: "http://192.168.0.134",
|
||||
API_HOST: "http://192.168.0.150", //太浅
|
||||
// API_HOST: "https://gbs-gateway.qhdsafety.com",
|
||||
// API_HOST: "http://192.168.0.150", //太浅
|
||||
API_HOST: "https://gbs-gateway.qhdsafety.com",
|
||||
// API_HOST: "http://192.168.0.103", //huwei
|
||||
},
|
||||
production: {
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
姓名
|
||||
{userName}
|
||||
性别
|
||||
{gender}
|
||||
出生日期
|
||||
{birthDate}
|
||||
现住址
|
||||
{currentAddress}
|
||||
办公地址
|
||||
{officeAddress}
|
||||
职业资格等级及证书号码
|
||||
{qualificationText}
|
||||
注册安全工程师证书编号
|
||||
{certNo}
|
||||
身份证件号码
|
||||
{idCardNo}
|
||||
联系电话
|
||||
{phone}
|
||||
学历学位
|
||||
{education}
|
||||
毕业院校及专业
|
||||
{schoolMajor}
|
||||
出版学术专著、专利、科技发明及获奖情况
|
||||
{publications}
|
||||
自我申报的专业能力及认定方式
|
||||
{capability}
|
||||
申报专业能力证明材料
|
||||
{certFiles}
|
||||
主要学习工作经历
|
||||
{workExperience}
|
||||
本人签字
|
||||
|
||||
从业机构确认
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
安全评价师简历表
|
||||
姓 名
|
||||
{userName}
|
||||
性 别
|
||||
{gender}
|
||||
出生日期
|
||||
{birthDate}
|
||||
现住址
|
||||
{currentAddress}
|
||||
办公地址
|
||||
{officeAddress}
|
||||
职业资格等级及证书号码
|
||||
{qualificationText}
|
||||
注册安全工程师证书编号
|
||||
{certNo}
|
||||
身份证件号码
|
||||
{idCardNo}
|
||||
联系电话
|
||||
{phone}
|
||||
学 历
|
||||
学 位
|
||||
全日制教育
|
||||
{education}
|
||||
毕业院校及专业
|
||||
{schoolMajor}
|
||||
|
||||
在职教育
|
||||
{ZYeducation}
|
||||
毕业院校及专业
|
||||
{ZYschoolMajor}
|
||||
出版学术专著、专利、科技发明、获得科技进步奖、发表学术论文等情况
|
||||
{publications}
|
||||
自我申报的专业能力及认定方式
|
||||
{capability}
|
||||
申报专业能力证明材料
|
||||
{certFiles}
|
||||
主要学习工作经历:
|
||||
{workExperience}
|
||||
签字:
|
||||
从业机构确认意见(盖章)
|
||||
|
||||
年 月 日
|
||||
注:1.专职安全评价师应全部填写;2.专业能力证明材料根据《安全评价师专业能力对照表》的认定要求填报;3.学习简历从大学开始(包括大学毕业后的继续教育)。
|
||||
|
||||
|
|
@ -9,7 +9,7 @@ import {
|
|||
} from "~/enumerate/constant";
|
||||
import "./index.less";
|
||||
|
||||
const RESUME_TEMPLATE_URL = "https://test-dragon-yf-pub.oss-cn-hangzhou.aliyuncs.com/jjb/6a86d212e4b072649bfb8a6e.docx";
|
||||
const RESUME_TEMPLATE_URL = "https://test-dragon-yf-pub.oss-cn-hangzhou.aliyuncs.com/jjb/6a87b61be4b063db1579e790.docx";
|
||||
|
||||
const GENDER_MAP = { 1: "男", 2: "女" };
|
||||
|
||||
|
|
@ -93,6 +93,8 @@ export default function StaffResumeModal({
|
|||
const regCert = info.registeredSafetyEngineerCert;
|
||||
const regCertFiles = parseFileList(regCert?.certAttachmentUrl);
|
||||
|
||||
const isZyEducation = info.educationTypeName === "在职教育";
|
||||
|
||||
const educationText = [info.educationTypeName, info.educationLevelName]
|
||||
.filter(Boolean)
|
||||
.join("") || "-";
|
||||
|
|
@ -132,8 +134,11 @@ export default function StaffResumeModal({
|
|||
certNo: display(regCert?.certNo),
|
||||
idCardNo: maskIdCard(info.idCardNo),
|
||||
phone: maskPhone(info.account),
|
||||
education: educationText,
|
||||
schoolMajor: schoolMajorText,
|
||||
// 全日制填 education/schoolMajor,在职教育填 ZYeducation/ZYschoolMajor
|
||||
education: isZyEducation ? "" : info.educationLevelName,
|
||||
schoolMajor: isZyEducation ? "" : schoolMajorText,
|
||||
ZYeducation: isZyEducation ? info.educationLevelName : "",
|
||||
ZYschoolMajor: isZyEducation ? schoolMajorText : "",
|
||||
publications: info.publications || "无",
|
||||
capability: capabilityText,
|
||||
certFiles:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import { PROJECT_TYPE_MAP } from "~/enumerate/constant";
|
|||
import WpsEditor from "~/pages/Container/WpsEditor";
|
||||
import RiskAnalysisContent from "~/pages/Container/SafetyEvalBusiness/ProjectFlow/RiskAnalysisContent";
|
||||
import InternalReviewContent from "~/pages/Container/SafetyEvalBusiness/ProjectFlow/InternalReviewContent";
|
||||
import TeamContent from "~/pages/Container/SafetyEvalBusiness/ProjectFlow/TeamContent";
|
||||
import TechnicalReviewContent from "~/pages/Container/SafetyEvalBusiness/ProjectFlow/TechnicalReviewContent";
|
||||
import ControlContent from "~/pages/Container/SafetyEvalBusiness/ProjectFlow/ControlContent";
|
||||
import ArchiveContent from "~/pages/Container/SafetyEvalBusiness/ProjectFlow/ArchiveContent";
|
||||
|
|
@ -153,7 +154,7 @@ const ContractPanel = ({ data, loading }) => {
|
|||
<Card
|
||||
type="inner"
|
||||
size="small"
|
||||
title="合同扫描件"
|
||||
title="项目合同扫描件"
|
||||
className="epm-detail-section"
|
||||
>
|
||||
{scanFiles.map((file, idx) => renderFile(file, idx))}
|
||||
|
|
@ -163,76 +164,6 @@ const ContractPanel = ({ data, loading }) => {
|
|||
);
|
||||
};
|
||||
|
||||
// ===== 项目组人员面板 =====
|
||||
const TeamPanel = ({ data, loading }) => {
|
||||
|
||||
if (!data || data.length === 0)
|
||||
return <Empty description="暂无项目组人员数据" />;
|
||||
|
||||
const columns = [
|
||||
{ title: "姓名", dataIndex: "personnelName", width: 100 },
|
||||
{ title: "部门/岗位", dataIndex: "deptName", width: 160, ellipsis: true },
|
||||
{
|
||||
title: "项目角色",
|
||||
dataIndex: "role",
|
||||
width: 200,
|
||||
render: (roles) =>
|
||||
(Array.isArray(roles) ? roles : [roles])
|
||||
.map((r) => ROLE_DEFINITIONS_MAP[r] || r)
|
||||
.join("、"),
|
||||
},
|
||||
{
|
||||
title: "资质与专业",
|
||||
dataIndex: "capacity",
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "主要职责",
|
||||
dataIndex: "responsibility",
|
||||
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>
|
||||
|
||||
</div>
|
||||
<Table
|
||||
dataSource={data}
|
||||
columns={columns}
|
||||
rowKey="personnelId"
|
||||
pagination={false}
|
||||
size="small"
|
||||
scroll={{ x: 800 }}
|
||||
/>
|
||||
</>
|
||||
};
|
||||
|
||||
// ===== 踏勘情况面板 =====
|
||||
const SurveyPanel = ({ personnel, attachments, loading, detailData }) => {
|
||||
|
|
@ -394,7 +325,7 @@ const EvalProjectMonitorDetail = (props) => {
|
|||
const [teamMembers, setTeamMembers] = useState([]);
|
||||
const [surveyPersonnel, setSurveyPersonnel] = useState([]);
|
||||
const [surveyAttachments, setSurveyAttachments] = useState({});
|
||||
const [activeKey, setActiveKey] = useState("BUSINESS_CONTRACT");
|
||||
const [activeKey, setActiveKey] = useState("RISK_ANALYSIS");
|
||||
const [wpsVisible, setWpsVisible] = useState(false);
|
||||
|
||||
const fetchContract = async () => {
|
||||
|
|
@ -405,13 +336,6 @@ const EvalProjectMonitorDetail = (props) => {
|
|||
}
|
||||
};
|
||||
|
||||
const fetchTeam = async () => {
|
||||
if (!projectId) return;
|
||||
const res = await evalProjectMemberPage({ projectId });
|
||||
if (res?.success !== false && res?.data) {
|
||||
setTeamMembers(res.data);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchSurvey = async () => {
|
||||
if (!projectId) return;
|
||||
|
|
@ -437,7 +361,7 @@ const EvalProjectMonitorDetail = (props) => {
|
|||
getDocByProjectId({ projectId });
|
||||
}
|
||||
fetchContract();
|
||||
fetchTeam();
|
||||
|
||||
fetchSurvey();
|
||||
}, []);
|
||||
|
||||
|
|
@ -521,10 +445,11 @@ const EvalProjectMonitorDetail = (props) => {
|
|||
);
|
||||
|
||||
return (
|
||||
<PageLayout history={props.history} previous title="安评项目监管详情">
|
||||
<PageLayout history={props.history} previous title="安评项目监管详情" footer={<div id="pf-footer-slot" />}>
|
||||
{projectInfo}
|
||||
<Tabs
|
||||
activeKey={activeKey}
|
||||
destroyOnHidden
|
||||
onChange={(key) => {
|
||||
if (key === "REPORT_PREPARATION") {
|
||||
if (!wpsDoc?.fileId) {
|
||||
|
|
@ -552,7 +477,7 @@ const EvalProjectMonitorDetail = (props) => {
|
|||
{
|
||||
key: "PROJECT_GROUP",
|
||||
label: renderTabLabel("项目组人员", "PROJECT_GROUP"),
|
||||
children: <TeamPanel data={teamMembers} loading={memberLoading} />,
|
||||
children: <TeamContent readOnly />,
|
||||
},
|
||||
{
|
||||
key: "SITE_SURVEY",
|
||||
|
|
@ -591,16 +516,7 @@ const EvalProjectMonitorDetail = (props) => {
|
|||
disabled: controlLocked,
|
||||
children: <ControlContent readOnly />,
|
||||
},
|
||||
{
|
||||
key: "ARCHIVE",
|
||||
label: renderLockableTabLabel(
|
||||
"项目归档",
|
||||
evalProjectDetailData?.archiveFlag === 1,
|
||||
archiveLocked,
|
||||
),
|
||||
disabled: archiveLocked,
|
||||
children: <ArchiveContent readOnly />,
|
||||
},
|
||||
|
||||
]}
|
||||
/>
|
||||
{wpsVisible && (
|
||||
|
|
|
|||
|
|
@ -178,15 +178,15 @@ const ControlContent = ({ readOnly, ...props }) => {
|
|||
];
|
||||
|
||||
const reviewerSignatureTaskStatusMap = {
|
||||
dispatched: "已下发",
|
||||
dispatched: "待APP签字",
|
||||
non_dispatched: "过程控制签字提交",
|
||||
completed: "已完成",
|
||||
completed: "已手写签字",
|
||||
}
|
||||
|
||||
const OrgHeadSignatureTaskStatusMap = {
|
||||
dispatched: "已下发",
|
||||
dispatched: "待APP签字",
|
||||
non_dispatched: "下发APP签字",
|
||||
completed: "已完成",
|
||||
completed: "已手写签字",
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -221,7 +221,6 @@ const ControlContent = ({ readOnly, ...props }) => {
|
|||
<Card
|
||||
title="过程控制审核"
|
||||
style={{ marginBottom: 16 }}
|
||||
styles={{ body: { paddingBottom: 0 } }}
|
||||
>
|
||||
<Table
|
||||
dataSource={rows}
|
||||
|
|
@ -236,7 +235,7 @@ const ControlContent = ({ readOnly, ...props }) => {
|
|||
</div>
|
||||
<Image src={processControl?.reviewerSignatureUrl} width={120} height={80} />
|
||||
</div>}
|
||||
<Collapse
|
||||
{!readOnly&&<Collapse
|
||||
style={{ marginTop: 12 }}
|
||||
items={[
|
||||
{
|
||||
|
|
@ -273,7 +272,7 @@ const ControlContent = ({ readOnly, ...props }) => {
|
|||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
/>}
|
||||
</Card>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import {
|
|||
Col,
|
||||
message,
|
||||
Tooltip,
|
||||
Popover,
|
||||
Image,
|
||||
Collapse,
|
||||
} from "antd";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
|
|
@ -76,8 +78,8 @@ const InternalReviewContent = ({ readOnly, ...props }) => {
|
|||
|
||||
const isDispatched = ["dispatched", 'completed'].includes(internalReview?.reviewerSignatureTaskStatus);
|
||||
const textMap={
|
||||
"dispatched": "已下发",
|
||||
"completed": "已完成",
|
||||
"dispatched": "待APP签字",
|
||||
"completed": "已手写签字",
|
||||
};
|
||||
|
||||
const problemCount = rows.filter(
|
||||
|
|
@ -273,17 +275,40 @@ const InternalReviewContent = ({ readOnly, ...props }) => {
|
|||
label: r.personnelName,
|
||||
}))}
|
||||
/>
|
||||
{(() => {
|
||||
const btn = (
|
||||
<Button
|
||||
size="small"
|
||||
onClick={handleAssign}
|
||||
loading={internalReviewAssignLoading || props.safetyEvalBusiness?.internalReviewConfirmLoading}
|
||||
disabled={isDispatched || !selectedReviewer || readOnly}
|
||||
>
|
||||
{textMap[internalReview?.reviewerSignatureTaskStatus] || '下发App签字'}
|
||||
{textMap[internalReview?.reviewerSignatureTaskStatus] || '发起APP签字'}
|
||||
</Button>
|
||||
);
|
||||
|
||||
// 已签字且有签字图片时,悬停展示签字图片(disabled 按钮不触发 hover,需用 span 包裹)
|
||||
if (internalReview?.reviewerSignatureUrl) {
|
||||
return (
|
||||
<Popover
|
||||
placement="topRight"
|
||||
content={
|
||||
<Image
|
||||
className="pf-sign-img"
|
||||
src={internalReview.reviewerSignatureUrl}
|
||||
alt="签字图片"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<span>{btn}</span>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
return btn;
|
||||
})()}
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Collapse
|
||||
{!readOnly &&<Collapse
|
||||
style={{marginTop: '12px'}}
|
||||
items={[
|
||||
{
|
||||
|
|
@ -316,7 +341,7 @@ const InternalReviewContent = ({ readOnly, ...props }) => {
|
|||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
/>}
|
||||
{!readOnly && (
|
||||
<LayoutFooterPortal slotId="pf-footer-slot">
|
||||
<Flex justify="flex-end" gap={8}>
|
||||
|
|
|
|||
|
|
@ -566,21 +566,20 @@ const RiskAnalysisContent = ({ readOnly, ...props }) => {
|
|||
return btn;
|
||||
},
|
||||
},
|
||||
{
|
||||
!readOnly && {
|
||||
title: "操作",
|
||||
render: (_, field) => (
|
||||
<Button
|
||||
type="link"
|
||||
danger
|
||||
size="small"
|
||||
disabled={readOnly}
|
||||
onClick={() => remove(field.name)}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
]}
|
||||
].filter(Boolean)}
|
||||
rowKey={(_, index) => index}
|
||||
pagination={false}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@ const TeamContent = ({ readOnly, ...props }) => {
|
|||
ellipsis: true,
|
||||
render: (roles) => roles.map((r) => r.duty).join(";"),
|
||||
},
|
||||
{
|
||||
!readOnly && {
|
||||
title: "操作",
|
||||
width: 80,
|
||||
fixed: "right",
|
||||
|
|
@ -369,14 +369,13 @@ const TeamContent = ({ readOnly, ...props }) => {
|
|||
type="link"
|
||||
danger
|
||||
size="small"
|
||||
disabled={readOnly}
|
||||
onClick={() => handleRemovePerson(record.personnelId)}
|
||||
>
|
||||
移除
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
];
|
||||
].filter(Boolean);
|
||||
|
||||
// 参与风险分析人员签字(去掉分析意见、只能选择一个人)
|
||||
const signerColumns = [
|
||||
|
|
@ -422,7 +421,7 @@ const TeamContent = ({ readOnly, ...props }) => {
|
|||
return btn;
|
||||
},
|
||||
},
|
||||
{
|
||||
!readOnly && {
|
||||
title: "操作",
|
||||
width: 80,
|
||||
render: (_, record) => (
|
||||
|
|
@ -430,14 +429,13 @@ const TeamContent = ({ readOnly, ...props }) => {
|
|||
type="link"
|
||||
danger
|
||||
size="small"
|
||||
disabled={readOnly}
|
||||
onClick={() => handleRemoveSigner(record.personnelId)}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
];
|
||||
].filter(Boolean);
|
||||
|
||||
return (
|
||||
<Spin spinning={memberLoading || memberParticipantListLoading}>
|
||||
|
|
@ -535,7 +533,7 @@ const TeamContent = ({ readOnly, ...props }) => {
|
|||
)}
|
||||
</Card>
|
||||
|
||||
<details className="pf-role-guide">
|
||||
{!readOnly &&<details className="pf-role-guide">
|
||||
<summary className="pf-role-guide-title">
|
||||
查看11类项目角色职责说明
|
||||
</summary>
|
||||
|
|
@ -554,19 +552,19 @@ const TeamContent = ({ readOnly, ...props }) => {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
</details>
|
||||
</details>}
|
||||
|
||||
{!readOnly && (
|
||||
{ (
|
||||
<LayoutFooterPortal slotId="pf-footer-slot">
|
||||
<Flex justify="flex-end" gap={8}>
|
||||
<Button onClick={handleExport}>导出Word</Button>
|
||||
<Button
|
||||
{!readOnly &&<Button
|
||||
type="primary"
|
||||
loading={memberSaveLoading || memberParticipantSaveLoading}
|
||||
onClick={handleSave}
|
||||
>
|
||||
确认项目组
|
||||
</Button>
|
||||
</Button>}
|
||||
</Flex>
|
||||
</LayoutFooterPortal>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import {
|
|||
Typography,
|
||||
message,
|
||||
Tooltip,
|
||||
Popover,
|
||||
Image,
|
||||
Collapse,
|
||||
} from "antd";
|
||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||
|
|
@ -74,8 +76,8 @@ const TechnicalReviewContent = ({ readOnly, ...props }) => {
|
|||
|
||||
const isDispatched = ["dispatched", 'completed'].includes(techReview?.reviewerSignatureTaskStatus);
|
||||
const textMap={
|
||||
"dispatched": "已下发",
|
||||
"completed": "已完成",
|
||||
"dispatched": "待APP签字",
|
||||
"completed": "已手写签字",
|
||||
};
|
||||
|
||||
const handleAssign = async () => {
|
||||
|
|
@ -272,17 +274,40 @@ const TechnicalReviewContent = ({ readOnly, ...props }) => {
|
|||
label: r.personnelName,
|
||||
}))}
|
||||
/>
|
||||
{(() => {
|
||||
const btn = (
|
||||
<Button
|
||||
size="small"
|
||||
onClick={handleAssign}
|
||||
loading={props.safetyEvalBusiness?.techReviewAssignLoading || props.safetyEvalBusiness?.techReviewConfirmLoading}
|
||||
disabled={isDispatched || !selectedReviewer || readOnly}
|
||||
>
|
||||
{textMap[techReview?.reviewerSignatureTaskStatus] || '下发App签字'}
|
||||
{textMap[techReview?.reviewerSignatureTaskStatus] || '发起APP签字'}
|
||||
</Button>
|
||||
);
|
||||
|
||||
// 已签字且有签字图片时,悬停展示签字图片(disabled 按钮不触发 hover,需用 span 包裹)
|
||||
if (techReview?.reviewerSignatureUrl) {
|
||||
return (
|
||||
<Popover
|
||||
placement="topRight"
|
||||
content={
|
||||
<Image
|
||||
className="pf-sign-img"
|
||||
src={techReview.reviewerSignatureUrl}
|
||||
alt="签字图片"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<span>{btn}</span>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
return btn;
|
||||
})()}
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Collapse
|
||||
{!readOnly &&<Collapse
|
||||
style={{ marginTop: "12px" }}
|
||||
items={[
|
||||
{
|
||||
|
|
@ -315,7 +340,7 @@ const TechnicalReviewContent = ({ readOnly, ...props }) => {
|
|||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
/>}
|
||||
{!readOnly && (
|
||||
<LayoutFooterPortal slotId="pf-footer-slot">
|
||||
<Flex justify="flex-end" gap={8}>
|
||||
|
|
|
|||
Loading…
Reference in New Issue