2026-06-30 17:32:29 +08:00
|
|
|
|
/** 资质申请前置条件核验(提交前展示,对齐原型) */
|
|
|
|
|
|
|
|
|
|
|
|
/** 人员相关三项暂不校验(机构库数据不足),恢复时改为 false */
|
|
|
|
|
|
const SKIP_PERSONNEL_VERIFY = true;
|
|
|
|
|
|
|
|
|
|
|
|
const KEY_POSITIONS = ["负责人", "技术负责人", "质量负责人"];
|
|
|
|
|
|
|
|
|
|
|
|
function ratio(count, total) {
|
|
|
|
|
|
if (!total) {
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
return count / total;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function includesSeniorTitle(titleName = "") {
|
|
|
|
|
|
return String(titleName).includes("高级");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function includesMidTitle(titleName = "") {
|
|
|
|
|
|
return String(titleName).includes("中级") || includesSeniorTitle(titleName);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function isRegisterEngineer(record = {}) {
|
|
|
|
|
|
const flag = record.registerEngineerFlag;
|
|
|
|
|
|
return flag === 1 || flag === true || flag === "1";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function verifyFilingPrerequisites(detail = {}) {
|
|
|
|
|
|
const items = [];
|
|
|
|
|
|
const fixedAsset = Number(detail.fixedAssetAmount) || 0;
|
|
|
|
|
|
items.push({
|
|
|
|
|
|
key: "entity",
|
|
|
|
|
|
label: "主体资格",
|
|
|
|
|
|
desc: "独立法人资格,固定资产不少于一千万元",
|
|
|
|
|
|
passed: fixedAsset >= 1000,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const workplaceArea = Number(detail.workplaceArea) || 0;
|
|
|
|
|
|
const equipmentCount = (detail.equipmentList || []).length;
|
|
|
|
|
|
items.push({
|
|
|
|
|
|
key: "facility",
|
|
|
|
|
|
label: "场所与设备",
|
|
|
|
|
|
desc: "工作场所建筑面积不少于1000㎡,检测检验设施设备原值不少于800万元",
|
|
|
|
|
|
passed: workplaceArea >= 1000 && (equipmentCount > 0 || fixedAsset >= 800),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const personnel = detail.personnelList || [];
|
|
|
|
|
|
const total = personnel.length;
|
|
|
|
|
|
const regEngineerCount = personnel.filter(isRegisterEngineer).length;
|
|
|
|
|
|
const midTitleCount = personnel.filter((p) => includesMidTitle(p.titleName)).length;
|
|
|
|
|
|
const seniorTitleCount = personnel.filter((p) => includesSeniorTitle(p.titleName)).length;
|
|
|
|
|
|
|
|
|
|
|
|
items.push({
|
|
|
|
|
|
key: "personnelStructure",
|
|
|
|
|
|
label: "人员数量与结构",
|
|
|
|
|
|
desc: "专职技术人员≥25人,中级注安师≥30%,中级职称≥50%,高级职称≥30%",
|
|
|
|
|
|
passed: SKIP_PERSONNEL_VERIFY || (
|
|
|
|
|
|
total >= 25
|
|
|
|
|
|
&& ratio(regEngineerCount, total) >= 0.3
|
|
|
|
|
|
&& ratio(midTitleCount, total) >= 0.5
|
|
|
|
|
|
&& ratio(seniorTitleCount, total) >= 0.3
|
|
|
|
|
|
),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const withExperience = personnel.filter((p) => {
|
|
|
|
|
|
const exp = String(p.workExperience || "");
|
|
|
|
|
|
return exp.length >= 4 || /[2-9]\s*年|[二三四五六七八九十]年/.test(exp);
|
|
|
|
|
|
}).length;
|
|
|
|
|
|
|
|
|
|
|
|
items.push({
|
|
|
|
|
|
key: "personnelExp",
|
|
|
|
|
|
label: "人员资历",
|
|
|
|
|
|
desc: "专职技术人员在本行业领域工作二年以上",
|
|
|
|
|
|
passed: SKIP_PERSONNEL_VERIFY || (total >= 25 && ratio(withExperience, total) >= 0.8),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const keyOk = KEY_POSITIONS.every((pos) => personnel.some(
|
|
|
|
|
|
(p) => String(p.positionName || "").includes(pos) && includesSeniorTitle(p.titleName),
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
items.push({
|
|
|
|
|
|
key: "keyPosition",
|
|
|
|
|
|
label: "关键岗位要求",
|
|
|
|
|
|
desc: "负责人、技术负责人、质量负责人具有高级职称,工作八年以上",
|
|
|
|
|
|
passed: SKIP_PERSONNEL_VERIFY || keyOk,
|
|
|
|
|
|
});
|
2026-07-01 17:57:42 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// const mgmtUploaded=detail.materials.every((m) => m.attachmentUrl);
|
|
|
|
|
|
|
|
|
|
|
|
// items.push({
|
|
|
|
|
|
// key: "mgmtSystem",
|
|
|
|
|
|
// label: "管理体系",
|
|
|
|
|
|
// desc: mgmtUploaded? "管理体系文件已上传" : "尚未上传管理体系文件",
|
|
|
|
|
|
// passed: mgmtUploaded,
|
|
|
|
|
|
// });
|
2026-06-30 17:32:29 +08:00
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
passed: items.every((item) => item.passed),
|
|
|
|
|
|
items,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|