commit
5c3c98f4fd
|
|
@ -0,0 +1,66 @@
|
||||||
|
{
|
||||||
|
"openapi": "3.0.1",
|
||||||
|
"info": {
|
||||||
|
"title": "资质备案人员分页查询",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"/safetyEval/org-personnel/filing/page": {
|
||||||
|
"get": {
|
||||||
|
"summary": "资质备案人员分页查询",
|
||||||
|
"tags": ["人员信息管理"],
|
||||||
|
"parameters": [
|
||||||
|
{ "name": "current", "in": "query", "schema": { "type": "integer", "format": "int64", "default": 1 } },
|
||||||
|
{ "name": "size", "in": "query", "schema": { "type": "integer", "format": "int64", "default": 10 } },
|
||||||
|
{ "name": "orders", "in": "query", "schema": { "type": "string" } },
|
||||||
|
{ "name": "startTime", "in": "query", "schema": { "type": "string" } },
|
||||||
|
{ "name": "endTime", "in": "query", "schema": { "type": "string" } },
|
||||||
|
{ "name": "keyword", "in": "query", "schema": { "type": "string" } },
|
||||||
|
{ "name": "orgId", "in": "query", "schema": { "type": "integer", "format": "int64" } },
|
||||||
|
{ "name": "personName", "in": "query", "schema": { "type": "string" } }
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/PageResponseQualFilingPersonnelInfoCO" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"PageResponseQualFilingPersonnelInfoCO": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"success": { "type": "boolean" },
|
||||||
|
"code": { "type": "string" },
|
||||||
|
"message": { "type": "string" },
|
||||||
|
"errMessage": { "type": "string" },
|
||||||
|
"data": { "type": "array", "items": { "$ref": "#/components/schemas/QualFilingPersonnelInfoCO" } },
|
||||||
|
"total": { "type": "integer", "format": "int64" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"QualFilingPersonnelInfoCO": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": { "type": "string", "description": "主键ID (后端 Long / int64,前端按字符串保证精度)" },
|
||||||
|
"filingId": { "type": "string", "description": "备案ID (后端 Long / int64)" },
|
||||||
|
"sourcePersonnelId": { "type": "string", "description": "原始人员ID (后端 Long / int64)" },
|
||||||
|
"personName": { "type": "string", "description": "人员姓名" },
|
||||||
|
"deptName": { "type": "string", "description": "部门名称" },
|
||||||
|
"positionName": { "type": "string", "description": "岗位名称" },
|
||||||
|
"genderCode": { "type": "integer", "description": "性别编码(1男2女)" },
|
||||||
|
"genderName": { "type": "string", "description": "性别名称" },
|
||||||
|
"birthDate": { "type": "string", "description": "出生日期" },
|
||||||
|
"registerEngineerFlag": { "type": "integer", "description": "是否注册安全工程师(1是2否)" },
|
||||||
|
"evaluatorCertNo": { "type": "string", "description": "评价师证书编号" },
|
||||||
|
"professionalCapabilityCodeList": { "type": "array", "items": { "type": "string" }, "description": "能力codeList" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
// GET /safetyEval/org-personnel/filing/page
|
||||||
|
// spec: ./spec.json
|
||||||
|
|
||||||
|
export interface QualFilingPersonnelPageQuery {
|
||||||
|
current?: number;
|
||||||
|
size?: number;
|
||||||
|
orders?: string;
|
||||||
|
startTime?: string;
|
||||||
|
endTime?: string;
|
||||||
|
keyword?: string;
|
||||||
|
orgId?: string;
|
||||||
|
personName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface QualFilingPersonnelInfoCO {
|
||||||
|
id: string;
|
||||||
|
filingId: string;
|
||||||
|
sourcePersonnelId: string;
|
||||||
|
personName: string;
|
||||||
|
deptName?: string;
|
||||||
|
positionName?: string;
|
||||||
|
genderCode: number; // 1男 2女
|
||||||
|
genderName?: string;
|
||||||
|
birthDate?: string;
|
||||||
|
registerEngineerFlag: number; // 1是 2否
|
||||||
|
evaluatorCertNo?: string;
|
||||||
|
professionalCapabilityCodeList?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PageResponseQualFilingPersonnelInfoCO {
|
||||||
|
success: boolean;
|
||||||
|
code?: string;
|
||||||
|
message?: string;
|
||||||
|
errMessage?: string;
|
||||||
|
data: QualFilingPersonnelInfoCO[];
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
|
|
@ -482,4 +482,36 @@ export const NATIONAL_COUNTIES = (() => {
|
||||||
return result;
|
return result;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
/** 专业能力枚举 */
|
||||||
|
export const CAPABILITY_OPTIONS = [
|
||||||
|
{ label: "安全", value: "SAFETY" },
|
||||||
|
{ label: "机械", value: "MECHANICAL" },
|
||||||
|
{ label: "电气", value: "ELECTRICAL" },
|
||||||
|
{ label: "采矿", value: "MINING" },
|
||||||
|
{ label: "通风", value: "VENTILATION" },
|
||||||
|
{ label: "矿建", value: "MINE_CONSTRUCTION" },
|
||||||
|
{ label: "地质", value: "GEOLOGY" },
|
||||||
|
{ label: "水工结构", value: "HYDRAULIC_STRUCTURE" },
|
||||||
|
{ label: "采油", value: "OIL_PRODUCTION" },
|
||||||
|
{ label: "储运", value: "STORAGE_AND_TRANSPORT" },
|
||||||
|
{ label: "油气储运", value: "OIL_GAS_STORAGE_TRANSPORT" },
|
||||||
|
{ label: "工艺设备与控制", value: "PROCESS_EQUIPMENT_CONTROL" },
|
||||||
|
{ label: "自动化(仪表)", value: "AUTOMATION_INSTRUMENT" },
|
||||||
|
{ label: "防腐", value: "ANTICORROSION" },
|
||||||
|
{ label: "化工工艺", value: "CHEMICAL_PROCESS" },
|
||||||
|
{ label: "化工机械", value: "CHEMICAL_MECHANICAL" },
|
||||||
|
{ label: "自动化", value: "AUTOMATION" },
|
||||||
|
{ label: "火炸药", value: "EXPLOSIVES" },
|
||||||
|
{ label: "爆炸技术", value: "EXPLOSION_TECHNOLOGY" },
|
||||||
|
{ label: "冶金", value: "METALLURGY" },
|
||||||
|
{ label: "有色金属", value: "NONFERROUS_METAL" },
|
||||||
|
{ label: "设备", value: "EQUIPMENT" },
|
||||||
|
{ label: "仪表", value: "INSTRUMENT" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const CAPABILITY_MAP = CAPABILITY_OPTIONS.reduce((acc, cur) => {
|
||||||
|
acc[cur.value] = cur.label;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,21 @@
|
||||||
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
|
||||||
import { Button, Form, Input, Modal, Table } from "antd";
|
import { Button, Form, Input, Modal, Table } from "antd";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { NS_STAFF_INFO } from "~/enumerate/namespace";
|
import { apiGet } from "~/utils/enterpriseInfo/http";
|
||||||
import { TITLE_LEVEL_MAP } from "~/enumerate/enterpriseOptions";
|
import { CAPABILITY_MAP, GENDER_MAP } from "~/enumerate/constant";
|
||||||
import StaffViewModal from "~/components/StaffViewModal";
|
import StaffViewModal from "~/components/StaffViewModal";
|
||||||
|
|
||||||
function OrgPersonnelSelectModalInner(props) {
|
function calcAge(birthDate) {
|
||||||
|
if (!birthDate) return "-";
|
||||||
|
const birth = new Date(birthDate);
|
||||||
|
if (isNaN(birth.getTime())) return "-";
|
||||||
|
const now = new Date();
|
||||||
|
let age = now.getFullYear() - birth.getFullYear();
|
||||||
|
const m = now.getMonth() - birth.getMonth();
|
||||||
|
if (m < 0 || (m === 0 && now.getDate() < birth.getDate())) age--;
|
||||||
|
return age >= 0 ? age : "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function OrgPersonnelSelectModal(props) {
|
||||||
const { open, onCancel, onConfirm, existingIds = [] } = props;
|
const { open, onCancel, onConfirm, existingIds = [] } = props;
|
||||||
const [searchForm] = Form.useForm();
|
const [searchForm] = Form.useForm();
|
||||||
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
||||||
|
|
@ -18,14 +28,13 @@ function OrgPersonnelSelectModalInner(props) {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const values = searchForm.getFieldsValue();
|
const values = searchForm.getFieldsValue();
|
||||||
const res = await props.staffInfoList({
|
const res = await apiGet("/safetyEval/org-personnel/filing/page", {
|
||||||
current: page,
|
current: page,
|
||||||
size: pageSize,
|
size: pageSize,
|
||||||
userName: values.staffName || undefined,
|
personName: values.personName || undefined,
|
||||||
employmentStatusCode: 1,
|
|
||||||
});
|
});
|
||||||
if (res?.success !== false) {
|
if (res?.success !== false) {
|
||||||
setDataSource(res?.data || []);
|
setDataSource((res?.data || []).map((item) => ({ ...item, age: calcAge(item.birthDate) })));
|
||||||
setPagination((prev) => ({ ...prev, current: page, pageSize, total: res?.total || 0 }));
|
setPagination((prev) => ({ ...prev, current: page, pageSize, total: res?.total || 0 }));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -62,14 +71,14 @@ function OrgPersonnelSelectModalInner(props) {
|
||||||
<Modal
|
<Modal
|
||||||
open={open}
|
open={open}
|
||||||
title="添加备案人员"
|
title="添加备案人员"
|
||||||
width={800}
|
width={900}
|
||||||
destroyOnHidden
|
destroyOnHidden
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
onOk={handleOk}
|
onOk={handleOk}
|
||||||
okText="确认添加"
|
okText="确认添加"
|
||||||
>
|
>
|
||||||
<Form form={searchForm} layout="inline" style={{ marginBottom: 16 }}>
|
<Form form={searchForm} layout="inline" style={{ marginBottom: 16 }}>
|
||||||
<Form.Item name="staffName">
|
<Form.Item name="personName">
|
||||||
<Input placeholder="人员姓名搜索" allowClear />
|
<Input placeholder="人员姓名搜索" allowClear />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
|
|
@ -94,15 +103,28 @@ function OrgPersonnelSelectModalInner(props) {
|
||||||
showTotal: (t) => `共 ${t} 条`,
|
showTotal: (t) => `共 ${t} 条`,
|
||||||
onChange: (page, pageSize) => getData(page, pageSize),
|
onChange: (page, pageSize) => getData(page, pageSize),
|
||||||
}}
|
}}
|
||||||
scroll={ { y: 400 }}
|
scroll={{ x: 1100, y: 400 }}
|
||||||
columns={[
|
columns={[
|
||||||
{ title: "人员姓名", dataIndex: "userName", ellipsis: true },
|
{ title: "人员姓名", dataIndex: "personName", ellipsis: true, width: 100 },
|
||||||
{ title: "类型", dataIndex: "personTypeName" },
|
{ title: "部门", dataIndex: "deptName", ellipsis: true, width: 150 },
|
||||||
|
{ title: "岗位", dataIndex: "positionName", ellipsis: true, width: 120 },
|
||||||
{ title: "职称", dataIndex: "titleName", ellipsis: true, render: (_, record) => TITLE_LEVEL_MAP[record.titleCode] ?? (record.titleCode || "-") },
|
{ title: "性别", dataIndex: "genderCode", width: 70, render: (v) => GENDER_MAP[v] || "-" },
|
||||||
|
{ title: "年龄", dataIndex: "age", width: 70 },
|
||||||
|
{ title: "注册安全工程师", dataIndex: "registerEngineerFlag", width: 130, render: (v) => v === 1 ? "是" : "否" },
|
||||||
|
{ title: "评价师", dataIndex: "evaluatorCertNo", width: 80, render: (v) => v ? "是" : "否" },
|
||||||
|
{
|
||||||
|
title: "能力",
|
||||||
|
render: (_, record) => {
|
||||||
|
const codes = record.professionalCapabilityCodeList || [];
|
||||||
|
return codes.length
|
||||||
|
? codes.map((code) => CAPABILITY_MAP[code] || code).join("、")
|
||||||
|
: "-";
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: "操作",
|
||||||
width: 80,
|
width: 80,
|
||||||
|
fixed: "right",
|
||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
<Button type="link" size="small" onClick={() => setViewId(record.id)}>查看</Button>
|
<Button type="link" size="small" onClick={() => setViewId(record.id)}>查看</Button>
|
||||||
),
|
),
|
||||||
|
|
@ -113,11 +135,8 @@ function OrgPersonnelSelectModalInner(props) {
|
||||||
<StaffViewModal
|
<StaffViewModal
|
||||||
open={!!viewId}
|
open={!!viewId}
|
||||||
currentId={viewId}
|
currentId={viewId}
|
||||||
|
|
||||||
onCancel={() => setViewId("")}
|
onCancel={() => setViewId("")}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Connect([NS_STAFF_INFO], true)(OrgPersonnelSelectModalInner);
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,20 @@
|
||||||
import { Button, Modal, Space, Table } from "antd";
|
import { Button, Modal, Space, Table } from "antd";
|
||||||
import { useState } from "react";
|
import { useMemo, useState } from "react";
|
||||||
import { TITLE_LEVEL_MAP } from "~/enumerate/enterpriseOptions";
|
import { CAPABILITY_MAP, GENDER_MAP } from "~/enumerate/constant";
|
||||||
import StaffViewModal from "~/components/StaffViewModal";
|
import StaffViewModal from "~/components/StaffViewModal";
|
||||||
import OrgPersonnelSelectModal from "./OrgPersonnelSelectModal";
|
import OrgPersonnelSelectModal from "./OrgPersonnelSelectModal";
|
||||||
|
|
||||||
|
function calcAge(birthDate) {
|
||||||
|
if (!birthDate) return "-";
|
||||||
|
const birth = new Date(birthDate);
|
||||||
|
if (isNaN(birth.getTime())) return "-";
|
||||||
|
const now = new Date();
|
||||||
|
let age = now.getFullYear() - birth.getFullYear();
|
||||||
|
const m = now.getMonth() - birth.getMonth();
|
||||||
|
if (m < 0 || (m === 0 && now.getDate() < birth.getDate())) age--;
|
||||||
|
return age >= 0 ? age : "-";
|
||||||
|
}
|
||||||
|
|
||||||
const PersonnelStep=({
|
const PersonnelStep=({
|
||||||
personnelList = [],
|
personnelList = [],
|
||||||
disabled,
|
disabled,
|
||||||
|
|
@ -14,6 +25,11 @@ const PersonnelStep=({
|
||||||
const [viewId, setViewId] = useState("");
|
const [viewId, setViewId] = useState("");
|
||||||
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
||||||
|
|
||||||
|
const tableData = useMemo(
|
||||||
|
() => personnelList.map((item) => ({ ...item, age: item.age ?? calcAge(item.birthDate) })),
|
||||||
|
[personnelList],
|
||||||
|
);
|
||||||
|
|
||||||
const existingIds = personnelList.map((item) => String(item.sourcePersonnelId || item.id || ""));
|
const existingIds = personnelList.map((item) => String(item.sourcePersonnelId || item.id || ""));
|
||||||
|
|
||||||
const handleBatchRemove = () => {
|
const handleBatchRemove = () => {
|
||||||
|
|
@ -50,21 +66,34 @@ const PersonnelStep=({
|
||||||
size="small"
|
size="small"
|
||||||
rowKey={(record) => String(record.sourcePersonnelId || record.id)}
|
rowKey={(record) => String(record.sourcePersonnelId || record.id)}
|
||||||
pagination={false}
|
pagination={false}
|
||||||
scroll={{ y: 400 }}
|
scroll={{ x: 1200, y: 400 }}
|
||||||
dataSource={personnelList}
|
dataSource={tableData}
|
||||||
rowSelection={!disabled ? {
|
rowSelection={!disabled ? {
|
||||||
selectedRowKeys,
|
selectedRowKeys,
|
||||||
onChange: setSelectedRowKeys,
|
onChange: setSelectedRowKeys,
|
||||||
} : undefined}
|
} : undefined}
|
||||||
columns={[
|
columns={[
|
||||||
{ title: "序号", width: 60, render: (_, __, index) => index + 1 },
|
{ title: "序号", width: 60, render: (_, __, index) => index + 1 },
|
||||||
{ title: "人员姓名", dataIndex: "userName", render: (_, record) => record.userName || record.personName },
|
{ title: "人员姓名", dataIndex: "personName" },
|
||||||
{ title: "类型", dataIndex: "personTypeName" },
|
{ title: "部门", dataIndex: "deptName", ellipsis: true },
|
||||||
|
{ title: "岗位", dataIndex: "positionName", ellipsis: true },
|
||||||
{ title: "职称", dataIndex: "titleName", render: (_, record) => TITLE_LEVEL_MAP[record.titleCode] ?? (record.titleCode || "-") },
|
{ title: "性别", dataIndex: "genderCode", width: 70, render: (v) => GENDER_MAP[v] || "-" },
|
||||||
|
{ title: "年龄", dataIndex: "age", width: 70 },
|
||||||
|
{ title: "注册安全工程师", dataIndex: "registerEngineerFlag", width: 120, render: (v) => v === 1 ? "是" : "否" },
|
||||||
|
{ title: "评价师", dataIndex: "evaluatorCertNo", width: 80, render: (v) => v ? "是" : "否" },
|
||||||
|
{
|
||||||
|
title: "能力",
|
||||||
|
render: (_, record) => {
|
||||||
|
const codes = record.professionalCapabilityCodeList || [];
|
||||||
|
return codes.length
|
||||||
|
? codes.map((code) => CAPABILITY_MAP[code] || code).join("、")
|
||||||
|
: "-";
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: "操作",
|
||||||
width: 140,
|
width: 140,
|
||||||
|
fixed: "right",
|
||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
<Space size="small">
|
<Space size="small">
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -396,6 +396,13 @@ function FilingFormPage(props) {
|
||||||
title={MODE_TITLE[mode] || "资质备案表单"}
|
title={MODE_TITLE[mode] || "资质备案表单"}
|
||||||
history={props.history}
|
history={props.history}
|
||||||
previous
|
previous
|
||||||
|
extra={
|
||||||
|
!readOnly && mode !== FILING_FORM_MODE.CHANGE ? (
|
||||||
|
<Button loading={submitting} onClick={() => handleVerifyConfirm({ isSaveDraft: true })}>
|
||||||
|
暂存
|
||||||
|
</Button>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<Spin spinning={ submitting}>
|
<Spin spinning={ submitting}>
|
||||||
<Tabs
|
<Tabs
|
||||||
|
|
@ -428,11 +435,6 @@ function FilingFormPage(props) {
|
||||||
)}
|
)}
|
||||||
{!readOnly && isLastStep && (
|
{!readOnly && isLastStep && (
|
||||||
<>
|
<>
|
||||||
{ mode !== FILING_FORM_MODE.CHANGE && (
|
|
||||||
<Button loading={submitting} onClick={()=>handleVerifyConfirm({isSaveDraft:true})}>
|
|
||||||
暂存
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
<Button type="primary" onClick={handleSubmitRequest}>
|
<Button type="primary" onClick={handleSubmitRequest}>
|
||||||
{mode === FILING_FORM_MODE.FILED ? "提交填报" : "提交申请"}
|
{mode === FILING_FORM_MODE.FILED ? "提交填报" : "提交申请"}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ export function mapEquipRowToFilingEquipment(row = {}) {
|
||||||
id: `local-equip-${id}`,
|
id: `local-equip-${id}`,
|
||||||
sourceEquipmentId: id,
|
sourceEquipmentId: id,
|
||||||
deviceName: row.deviceName,
|
deviceName: row.deviceName,
|
||||||
|
equipmentValue: row.equipmentValue,
|
||||||
deviceModel: row.deviceModel,
|
deviceModel: row.deviceModel,
|
||||||
manufacturer: row.manufacturer,
|
manufacturer: row.manufacturer,
|
||||||
calibrationReportUrl: row.calibrationReportUrl || "",
|
calibrationReportUrl: row.calibrationReportUrl || "",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue