lin
This commit is contained in:
parent
538f2f5b38
commit
7257164250
|
@ -140,5 +140,6 @@ export class StaffRouter {
|
||||||
.mutation(({ input }) => {
|
.mutation(({ input }) => {
|
||||||
return this.staffService.setCustomFieldValue(input as any);
|
return this.staffService.setCustomFieldValue(input as any);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,4 +255,6 @@ export class StaffService extends BaseService<Prisma.StaffDelegate> {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import { areaOptions } from "@web/src/data/area-options";
|
export const baseFields = [
|
||||||
|
{ name: 'showname', label: '姓名', type: 'text', required: true, group: '基本信息', order: 1 },
|
||||||
|
{name: 'department', label: '部门', type: 'text', group: '基本信息', order: 2 , required: true},
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
export const defaultFields = [
|
export const defaultFields = [
|
||||||
// 基本信息组
|
// 基本信息组
|
||||||
{ name: 'username', label: '用户名', type: 'text',required: true, group: '基本信息', order: 1 },
|
// { name: 'username', label: '用户名', type: 'text',required: true, group: '基本信息', order: 1 },
|
||||||
// { name: 'showname', label: '显示名称', type: 'text', group: '基本信息', order: 2 },
|
|
||||||
{ name: 'idNumber', label: '身份证号', type: 'text', group: '基本信息', order: 3 },
|
{ name: 'idNumber', label: '身份证号', type: 'text', group: '基本信息', order: 3 },
|
||||||
{ name: 'officerId', label: '警号', type: 'text', group: '基本信息', order: 4 },
|
{ name: 'officerId', label: '警号', type: 'text', group: '基本信息', order: 4 },
|
||||||
{ name: 'phoneNumber', label: '手机号', type: 'text', group: '基本信息', order: 5 },
|
{ name: 'phoneNumber', label: '手机号', type: 'text', group: '基本信息', order: 5 },
|
||||||
|
@ -35,7 +38,7 @@ export const defaultFields = [
|
||||||
group: '基本信息',
|
group: '基本信息',
|
||||||
order: 9 },
|
order: 9 },
|
||||||
{ name: 'source', label: '来源', type: 'text', group: '基本信息', order: 10 },
|
{ name: 'source', label: '来源', type: 'text', group: '基本信息', order: 10 },
|
||||||
{name: 'department', label: '部门', type: 'text', group: '基本信息', order: 11 },
|
|
||||||
|
|
||||||
// 政治信息组
|
// 政治信息组
|
||||||
{ name: 'politicalStatus',
|
{ name: 'politicalStatus',
|
||||||
|
|
|
@ -63,6 +63,24 @@ const StaffFieldManage = () => {
|
||||||
message.error('字段删除失败');
|
message.error('字段删除失败');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleBatchDelete = async () => {
|
||||||
|
if (selectedRowKeys.length === 0) {
|
||||||
|
message.warning('请选择要删除的字段');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await Promise.all(
|
||||||
|
selectedRowKeys.map(async (id: string) => {
|
||||||
|
await deleteCustomField.mutateAsync(id);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
message.success('批量删除成功');
|
||||||
|
setSelectedRowKeys([]);
|
||||||
|
} catch (error) {
|
||||||
|
message.error('批量删除失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -93,23 +111,7 @@ const StaffFieldManage = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBatchDelete = async () => {
|
|
||||||
if (selectedRowKeys.length === 0) {
|
|
||||||
message.warning('请选择要删除的字段');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await Promise.all(
|
|
||||||
selectedRowKeys.map(async (id: string) => {
|
|
||||||
await deleteCustomField.mutateAsync(id);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
message.success('批量删除成功');
|
|
||||||
setSelectedRowKeys([]);
|
|
||||||
} catch (error) {
|
|
||||||
message.error('批量删除失败');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white p-6 rounded-lg shadow">
|
<div className="bg-white p-6 rounded-lg shadow">
|
||||||
|
|
|
@ -5,7 +5,7 @@ import _ from "lodash";
|
||||||
import { useMainContext } from "../layout/MainProvider";
|
import { useMainContext } from "../layout/MainProvider";
|
||||||
import StaffTable from "./stafftable/page";
|
import StaffTable from "./stafftable/page";
|
||||||
|
|
||||||
export default function StaffMessage() {
|
export default function StaffMessageGG() {
|
||||||
const { form, formValue, setFormValue, setVisible, setSearchValue, editingRecord } = useMainContext();
|
const { form, formValue, setFormValue, setVisible, setSearchValue, editingRecord } = useMainContext();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
import { useState, useEffect, useMemo, useCallback } from 'react';
|
||||||
|
import { AgGridReact } from 'ag-grid-react';
|
||||||
|
import { api, useStaff } from "@nice/client";
|
||||||
|
import 'ag-grid-community/styles/ag-grid.css';
|
||||||
|
import 'ag-grid-community/styles/ag-theme-alpine.css';
|
||||||
|
import { SetFilterModule } from 'ag-grid-enterprise';
|
||||||
|
import { Button, message } from 'antd';
|
||||||
|
|
||||||
|
export default function StaffMessage() {
|
||||||
|
const [rowData, setRowData] = useState<any[]>([]);
|
||||||
|
const [columnDefs, setColumnDefs] = useState<any[]>([]);
|
||||||
|
const [selectedRows, setSelectedRows] = useState<any[]>([]);
|
||||||
|
const { useCustomFields, softDeleteByIds } = useStaff();
|
||||||
|
const fields = useCustomFields();
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const { data: staffData } = api.staff.findMany.useQuery({
|
||||||
|
where: {
|
||||||
|
deletedAt: null
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
fieldValues: {
|
||||||
|
include: {
|
||||||
|
// 添加这两个关联字段
|
||||||
|
staff: { select: { id: true } }, // 关联员工ID
|
||||||
|
field: { select: { id: true } } // 关联字段ID
|
||||||
|
}
|
||||||
|
},
|
||||||
|
department: true
|
||||||
|
}
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
const actionColumns = [{
|
||||||
|
field:"action",
|
||||||
|
width: 50,
|
||||||
|
checkboxSelection: true,
|
||||||
|
headerCheckboxSelection: true,
|
||||||
|
pinned: 'left'
|
||||||
|
}]
|
||||||
|
|
||||||
|
// 新增编辑处理函数
|
||||||
|
const handleEdit = useCallback(async () => {
|
||||||
|
if (selectedRows.length === 0) return;
|
||||||
|
if (selectedRows.length > 1) {
|
||||||
|
message.error('只能选择一个员工进行编辑');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(selectedRows[0]);
|
||||||
|
}, [selectedRows]);
|
||||||
|
|
||||||
|
// 新增删除处理函数
|
||||||
|
const handleDelete = useCallback(async () => {
|
||||||
|
if (selectedRows.length === 0) return;
|
||||||
|
try {
|
||||||
|
await softDeleteByIds.mutateAsync({
|
||||||
|
ids: selectedRows?.map(row => row.id)
|
||||||
|
});
|
||||||
|
message.success('删除成功');
|
||||||
|
} catch (error) {
|
||||||
|
message.error('删除失败');
|
||||||
|
}
|
||||||
|
// 重新获取数据或本地过滤已删除项
|
||||||
|
}, [selectedRows]);
|
||||||
|
|
||||||
|
// 缓存基础列定义
|
||||||
|
const baseColumns = useMemo(() => [
|
||||||
|
{
|
||||||
|
field: 'showname',
|
||||||
|
headerName: '姓名',
|
||||||
|
filter: 'agSetColumnFilter',
|
||||||
|
pinned: 'left'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'deptId',
|
||||||
|
headerName: '所属部门',
|
||||||
|
valueGetter: params => params.data.department?.name,
|
||||||
|
filter: 'agSetColumnFilter'
|
||||||
|
}
|
||||||
|
], []);
|
||||||
|
|
||||||
|
// 缓存动态列定义
|
||||||
|
const dynamicColumns = useMemo(() =>
|
||||||
|
(fields.data || [] as any).map(field => ({
|
||||||
|
field: field.name,
|
||||||
|
headerName: field.label || field.name,
|
||||||
|
filter: 'agSetColumnFilter',
|
||||||
|
valueGetter: params => {
|
||||||
|
// 从 fieldValues 对象中获取值
|
||||||
|
return params.data.fieldValues?.find(
|
||||||
|
(fv: any) => fv.fieldId === field.id
|
||||||
|
)?.value;
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
[fields.data]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 合并列定义
|
||||||
|
useEffect(() => {
|
||||||
|
setColumnDefs([...actionColumns, ...baseColumns, ...dynamicColumns]);
|
||||||
|
}, [baseColumns, dynamicColumns]);
|
||||||
|
|
||||||
|
// 更新行数据
|
||||||
|
useEffect(() => {
|
||||||
|
staffData && setRowData(staffData);
|
||||||
|
}, [staffData]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
<>
|
||||||
|
<Button className='mr-2' danger onClick={handleDelete} style={{ marginBottom: '10px' }}>批量删除</Button>
|
||||||
|
<Button type="primary" onClick={handleEdit} style={{ marginBottom: '10px' }}>编辑</Button>
|
||||||
|
<div className="ag-theme-alpine" style={{ height: 500, width: '100%', padding: '20px' }}>
|
||||||
|
<h1 className="text-2xl mb-4">人员总览</h1>
|
||||||
|
<AgGridReact
|
||||||
|
modules={[SetFilterModule]}
|
||||||
|
rowData={rowData}
|
||||||
|
columnDefs={columnDefs}
|
||||||
|
pagination={true}
|
||||||
|
paginationPageSize={10}
|
||||||
|
onSelectionChanged={e => setSelectedRows(e.api.getSelectedRows())}
|
||||||
|
rowSelection="multiple"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button onClick={() => {
|
||||||
|
console.log('字段配置:', fields.data);
|
||||||
|
console.log('员工数据:', staffData);
|
||||||
|
}}>调试数据</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -146,7 +146,7 @@ export default function StaffTable() {
|
||||||
};
|
};
|
||||||
const columnDefs: (ColDef | ColGroupDef)[] = [
|
const columnDefs: (ColDef | ColGroupDef)[] = [
|
||||||
{
|
{
|
||||||
field: 'username',
|
field: 'showname',
|
||||||
headerName: '姓名',
|
headerName: '姓名',
|
||||||
pinned: 'left',
|
pinned: 'left',
|
||||||
// floatingFilter: true // 确保启用浮动过滤器
|
// floatingFilter: true // 确保启用浮动过滤器
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Input, Button } from 'antd';
|
||||||
import React, { useState, useRef, useEffect } from 'react';
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
|
|
||||||
type InfoCardProps = {
|
type InfoCardProps = {
|
||||||
onAdd: (content: string) => void;
|
onAdd: (content: string[]) => void;
|
||||||
onHeightChange?: (height: number) => void; // 添加高度变化回调
|
onHeightChange?: (height: number) => void; // 添加高度变化回调
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,8 +35,9 @@ const InfoCard: React.FC<InfoCardProps> = ({ onAdd, onHeightChange }) => {
|
||||||
|
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
if (content) {
|
if (content) {
|
||||||
onAdd(content);
|
const newContents = [...addedContents, content]; // 创建包含所有内容的新数组
|
||||||
setAddedContents([...addedContents, content]);
|
onAdd(newContents); // 将累积数组传递给父组件
|
||||||
|
setAddedContents(newContents);
|
||||||
setContent('');
|
setContent('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,8 @@ import { useState, useMemo, useEffect } from "react";
|
||||||
import { useStaff } from "@nice/client";
|
import { useStaff } from "@nice/client";
|
||||||
import { areaOptions } from './area-options';
|
import { areaOptions } from './area-options';
|
||||||
import InfoCard from './infoCard';
|
import InfoCard from './infoCard';
|
||||||
|
import DepartmentSelect from "@web/src/components/models/department/department-select";
|
||||||
|
import { baseFields } from "@web/src/app/admin/staffinfo-manage/defaultFields";
|
||||||
const StaffInfoWrite = () => {
|
const StaffInfoWrite = () => {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
@ -19,8 +20,13 @@ const StaffInfoWrite = () => {
|
||||||
// 添加状态来跟踪每个文本区域的高度
|
// 添加状态来跟踪每个文本区域的高度
|
||||||
const [textAreaHeights, setTextAreaHeights] = useState<Record<string, number>>({});
|
const [textAreaHeights, setTextAreaHeights] = useState<Record<string, number>>({});
|
||||||
|
|
||||||
const handleAdd = (content: string) => {
|
const handleAdd = (content: string[]) => {
|
||||||
setInfoCards([...infoCards, { content }]);
|
// 将数组内容展开为独立对象
|
||||||
|
const newItems = content.map(text => ({ content: text }));
|
||||||
|
setInfoCards(prev => [
|
||||||
|
...prev.filter(item => !content.includes(item.content)),
|
||||||
|
...newItems
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在组件中添加监听字段变化
|
// 在组件中添加监听字段变化
|
||||||
|
@ -111,7 +117,11 @@ const StaffInfoWrite = () => {
|
||||||
// 根据字段类型渲染不同的组件
|
// 根据字段类型渲染不同的组件
|
||||||
switch (field.type) {
|
switch (field.type) {
|
||||||
case 'text':
|
case 'text':
|
||||||
return <Input disabled={isDisabled} />;
|
if(field.name === 'department'){
|
||||||
|
return <DepartmentSelect disabled={isDisabled} />;
|
||||||
|
}else{
|
||||||
|
return <Input disabled={isDisabled} />;
|
||||||
|
}
|
||||||
case 'number':
|
case 'number':
|
||||||
return <InputNumber disabled={isDisabled} />;
|
return <InputNumber disabled={isDisabled} />;
|
||||||
case 'date':
|
case 'date':
|
||||||
|
@ -136,7 +146,11 @@ const StaffInfoWrite = () => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<InfoCard
|
<InfoCard
|
||||||
onAdd={handleAdd}
|
onAdd={(contents) => {
|
||||||
|
handleAdd(contents);
|
||||||
|
// 同步更新表单字段值
|
||||||
|
form.setFieldValue(field.name, contents);
|
||||||
|
}}
|
||||||
onHeightChange={(height) => {
|
onHeightChange={(height) => {
|
||||||
setTextAreaHeights(prev => ({
|
setTextAreaHeights(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
|
@ -165,37 +179,47 @@ const StaffInfoWrite = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
// 创建基础员工记录
|
// 创建基础员工记录
|
||||||
if (!values.username) {
|
if (!values.showname) {
|
||||||
message.error("用户名不能为空");
|
message.error("姓名不能为空");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建基础员工记录
|
// 创建基础员工记录
|
||||||
console.log('准备创建用户,数据:', { username: values.username });
|
console.log('准备创建用户,数据:', { showname: values.showname });
|
||||||
const staff = await create.mutateAsync({
|
const staff = await create.mutateAsync({
|
||||||
data: {
|
data: {
|
||||||
username: values.username,
|
showname: values.showname,
|
||||||
password: '123456'
|
deptId: values.department? values.department : null,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log('创建员工记录:', staff);
|
console.log('创建员工记录:', staff);
|
||||||
// 过滤有效字段并转换值
|
// 过滤有效字段并转换值
|
||||||
const validEntries = Object.entries(values)
|
const validEntries = Object.entries(values)
|
||||||
.filter(([key, value]) => key !== 'username' && value !== undefined && value !== null && value !== '')
|
.filter(([key, value]) =>
|
||||||
|
key !== 'showname' && // 新增排除 showname
|
||||||
|
key !== 'username' &&
|
||||||
|
key !== 'department' &&
|
||||||
|
value !== undefined &&
|
||||||
|
value !== null &&
|
||||||
|
value !== ''
|
||||||
|
)
|
||||||
.map(([fieldName, value]) => {
|
.map(([fieldName, value]) => {
|
||||||
const field = fields && Array.isArray(fields) ? fields.find((f: any) => f.name === fieldName) : undefined;
|
const field = fields && Array.isArray(fields) ?
|
||||||
let processedValue = value;
|
fields.find((f: any) => f.name === fieldName) : undefined;
|
||||||
|
|
||||||
// 处理特殊字段类型
|
// 处理特殊字段类型
|
||||||
if (field?.type === 'date') {
|
let processedValue = value;
|
||||||
processedValue = value.toString();
|
if (field?.type === 'date') { //日期类型
|
||||||
} else if (field?.type === 'cascader' && Array.isArray(value)) {
|
processedValue = (value as Date)?.toISOString();
|
||||||
processedValue = value.join('/');
|
} else if (field?.type === 'cascader' && Array.isArray(value)) { //级联选择器
|
||||||
|
processedValue = value?.join('/');
|
||||||
|
}else if(field?.type === 'textarea'){ //多行文本
|
||||||
|
processedValue = (value as string[])?.join(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
return { field, value: processedValue };
|
return { field, value: processedValue };
|
||||||
})
|
})
|
||||||
.filter(item => item.field?.id); // 过滤有效字段定义
|
.filter(item => item.field?.id);
|
||||||
|
|
||||||
// 批量提交自定义字段
|
// 批量提交自定义字段
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
|
@ -240,6 +264,27 @@ const StaffInfoWrite = () => {
|
||||||
}}
|
}}
|
||||||
className="space-y-6 mt-6"
|
className="space-y-6 mt-6"
|
||||||
>
|
>
|
||||||
|
{/* 新增基础信息区块 */}
|
||||||
|
<div className="bg-blue-45 p-6 rounded-lg shadow relative mb-6">
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-6">
|
||||||
|
{baseFields.map((field) => (
|
||||||
|
<Form.Item
|
||||||
|
key={field.name}
|
||||||
|
label={field.label}
|
||||||
|
name={field.name}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: field.required,
|
||||||
|
message: `请输入${field.label}`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{renderField(field, '系统默认信息')}
|
||||||
|
</Form.Item>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{Object.entries(fieldGroups).map(([groupName, groupFields]) => (
|
{Object.entries(fieldGroups).map(([groupName, groupFields]) => (
|
||||||
<div key={groupName} className="bg-white p-6 rounded-lg shadow relative">
|
<div key={groupName} className="bg-white p-6 rounded-lg shadow relative">
|
||||||
<h2 className="text-lg font-semibold mb-4">{groupName}</h2>
|
<h2 className="text-lg font-semibold mb-4">{groupName}</h2>
|
||||||
|
@ -247,7 +292,7 @@ const StaffInfoWrite = () => {
|
||||||
grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-12
|
grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-12
|
||||||
${groupName === "工作信息" ? "md:[&>*:nth-child(odd)]:col-start-1 md:[&>*:nth-child(even)]:col-start-2" : ""}
|
${groupName === "工作信息" ? "md:[&>*:nth-child(odd)]:col-start-1 md:[&>*:nth-child(even)]:col-start-2" : ""}
|
||||||
`}>
|
`}>
|
||||||
{groupFields.map((field: any) => (
|
{(groupFields as any[])?.map((field: any) => (
|
||||||
<Form.Item
|
<Form.Item
|
||||||
key={field.id}
|
key={field.id}
|
||||||
label={<span className="block mb-2">{field.label}</span>}
|
label={<span className="block mb-2">{field.label}</span>}
|
||||||
|
|
|
@ -1,519 +0,0 @@
|
||||||
"use client";
|
|
||||||
|
|
||||||
import { Button, Form, Input, Select, DatePicker, Radio, message, Modal, Cascader, InputNumber } from "antd";
|
|
||||||
import { useState } from "react";
|
|
||||||
import dayjs from "dayjs";
|
|
||||||
import { useStaff } from "@nice/client";
|
|
||||||
import DepartmentChildrenSelect from "@web/src/components/models/department/department-children-select";
|
|
||||||
import { areaOptions } from '../staffinfo_write/area-options';
|
|
||||||
import DepartmentSelect from "@web/src/components/models/department/department-select";
|
|
||||||
const { TextArea } = Input;
|
|
||||||
|
|
||||||
const StaffInformation = () => {
|
|
||||||
const [modalForm] = Form.useForm();
|
|
||||||
const [form] = Form.useForm();
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
|
||||||
const [modalType, setModalType] = useState<'awards' | 'punishments' | 'equipment' | 'projects'>('awards');
|
|
||||||
const [rewardsList, setRewardsList] = useState<string[]>([]);
|
|
||||||
const [punishmentsList, setPunishmentsList] = useState<string[]>([]);
|
|
||||||
const [equipmentList, setEquipmentList] = useState<string[]>([]); // 新增装备列表
|
|
||||||
const [projectsList, setProjectsList] = useState<string[]>([]); // 新增任务列表
|
|
||||||
const {create, update} = useStaff();
|
|
||||||
|
|
||||||
const showModal = (type: 'awards' | 'punishments' | 'equipment' | 'projects') => {
|
|
||||||
setModalType(type);
|
|
||||||
setIsModalVisible(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleModalOk = async () => {
|
|
||||||
try {
|
|
||||||
const values = await modalForm.validateFields();
|
|
||||||
const value = values[modalType];
|
|
||||||
|
|
||||||
if (value) {
|
|
||||||
switch(modalType) {
|
|
||||||
case 'awards':
|
|
||||||
setRewardsList([...rewardsList, value]);
|
|
||||||
break;
|
|
||||||
case 'punishments':
|
|
||||||
setPunishmentsList([...punishmentsList, value]);
|
|
||||||
break;
|
|
||||||
case 'equipment':
|
|
||||||
setEquipmentList([...equipmentList, value]);
|
|
||||||
break;
|
|
||||||
case 'projects':
|
|
||||||
setProjectsList([...projectsList, value]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
modalForm.resetFields();
|
|
||||||
setIsModalVisible(false);
|
|
||||||
message.success(
|
|
||||||
modalType === 'awards' ? '奖励信息添加成功' :
|
|
||||||
modalType === 'punishments' ? '处分信息添加成功' :
|
|
||||||
modalType === 'equipment' ? '装备信息添加成功' : '任务信息添加成功'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
message.warning('请输入内容');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onFinish = async (values: any) => {
|
|
||||||
console.log('开始提交表单');
|
|
||||||
|
|
||||||
try {
|
|
||||||
setLoading(true);
|
|
||||||
const formattedValues = {
|
|
||||||
...values,
|
|
||||||
birthplace: values.birthplace?.join('/'), // 将数组转换为以'/'分隔的字符串
|
|
||||||
awards: rewardsList.join(','),
|
|
||||||
punishments: punishmentsList.join(','),
|
|
||||||
equipment: equipmentList.join(','),
|
|
||||||
projects: projectsList.join(','),
|
|
||||||
hireDate: values.hireDate?.toISOString(),
|
|
||||||
seniority: values.seniority?.toISOString(),
|
|
||||||
currentPositionDate: values.currentPositionDate?.toISOString(),
|
|
||||||
rankDate: values.rankDate?.toISOString(), // 修改这里
|
|
||||||
};
|
|
||||||
|
|
||||||
await create.mutateAsync(
|
|
||||||
{
|
|
||||||
data: formattedValues
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log('提交的表单数据:', formattedValues);
|
|
||||||
console.log('奖励列表:', rewardsList);
|
|
||||||
console.log('处分列表:', punishmentsList);
|
|
||||||
|
|
||||||
message.success("信息提交成功");
|
|
||||||
} catch (error) {
|
|
||||||
console.error('提交出错:', error);
|
|
||||||
message.error("提交失败,请重试");
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = (e: React.MouseEvent) => {
|
|
||||||
e.preventDefault(); // 阻止默认行为
|
|
||||||
console.log('提交按钮被点击');
|
|
||||||
form.submit();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="max-w-4xl mx-auto p-6">
|
|
||||||
<h1 className="text-2xl font-bold mb-6">人员信息填报</h1>
|
|
||||||
<Form
|
|
||||||
form={form}
|
|
||||||
layout="vertical"
|
|
||||||
onFinish={onFinish}
|
|
||||||
onFinishFailed={(errorInfo) => {
|
|
||||||
console.log('表单验证失败:', errorInfo);
|
|
||||||
}}
|
|
||||||
className="space-y-6"
|
|
||||||
>
|
|
||||||
{/* 个人基本信息 */}
|
|
||||||
<div className="bg-white p-6 rounded-lg shadow">
|
|
||||||
<h2 className="text-lg font-semibold mb-4">个人基本信息</h2>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<Form.Item label="姓名" name="username" rules={[{ required: true }]}>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="身份证号" name="idNumber" rules={[{required: true}]}>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="警号" name="officerId">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="手机号" name="phoneNumber">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="人员类型" name="type">
|
|
||||||
<Select>
|
|
||||||
<Select.Option value="警官">警官</Select.Option>
|
|
||||||
<Select.Option value="文职">文职</Select.Option>
|
|
||||||
<Select.Option value="警士">警士</Select.Option>
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="性别" name="sex">
|
|
||||||
<Radio.Group>
|
|
||||||
<Radio value={true}>男</Radio>
|
|
||||||
<Radio value={false}>女</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label='年龄' name='age'>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="血型" name="bloodType">
|
|
||||||
<Select>
|
|
||||||
<Select.Option value="A">A型</Select.Option>
|
|
||||||
<Select.Option value="B">B型</Select.Option>
|
|
||||||
<Select.Option value="O">O型</Select.Option>
|
|
||||||
<Select.Option value="AB">AB型</Select.Option>
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label="籍贯"
|
|
||||||
name="birthplace"
|
|
||||||
rules={[{ required: true, message: '请选择籍贯' }]}
|
|
||||||
>
|
|
||||||
<Cascader
|
|
||||||
options={areaOptions}
|
|
||||||
placeholder="请选择省/市/区"
|
|
||||||
className="w-full"
|
|
||||||
expandTrigger="hover"
|
|
||||||
showSearch={{
|
|
||||||
filter: (inputValue, path) => {
|
|
||||||
return path.some(option =>
|
|
||||||
typeof option.label === 'string' &&
|
|
||||||
option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
changeOnSelect
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 政治信息 */}
|
|
||||||
<div className="bg-white p-6 rounded-lg shadow">
|
|
||||||
<h2 className="text-lg font-semibold mb-4">政治信息</h2>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<Form.Item label="政治面貌" name="politicalStatus">
|
|
||||||
<Select>
|
|
||||||
<Select.Option value="中共党员">中共党员</Select.Option>
|
|
||||||
<Select.Option value="中共预备党员">中共预备党员</Select.Option>
|
|
||||||
<Select.Option value="共青团员">共青团员</Select.Option>
|
|
||||||
<Select.Option value="群众">群众</Select.Option>
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="党内职务" name="partyPosition">
|
|
||||||
<Select>
|
|
||||||
<Select.Option value="党委书记">党委书记</Select.Option>
|
|
||||||
<Select.Option value="委员">委员</Select.Option>
|
|
||||||
<Select.Option value="党支部书记">党支部书记</Select.Option>
|
|
||||||
<Select.Option value="党支部委员">党支部委员</Select.Option>
|
|
||||||
<Select.Option value="无">无</Select.Option>
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 职务信息 */}
|
|
||||||
<div className="bg-white p-6 rounded-lg shadow">
|
|
||||||
<h2 className="text-lg font-semibold mb-4">职务信息</h2>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<Form.Item label = "部门" name="deptId" >
|
|
||||||
<DepartmentSelect/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="衔职级别" name="rank">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="衔职时间" name="rankDate">
|
|
||||||
<DatePicker className="w-full" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="代理职务" name="proxyPosition">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="岗位" name="post">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 入职信息 */}
|
|
||||||
<div className="bg-white p-6 rounded-lg shadow">
|
|
||||||
<h2 className="text-lg font-semibold mb-4">入职信息</h2>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<Form.Item label="入职时间" name="hireDate">
|
|
||||||
<DatePicker className="w-full" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="工龄认定时间" name="seniority">
|
|
||||||
<DatePicker className="w-full" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="是否二次入职" name="isReentry" initialValue={false}>
|
|
||||||
<Radio.Group>
|
|
||||||
<Radio value={true}>是</Radio>
|
|
||||||
<Radio value={false}>否</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="来源类别" name="source">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="现岗位开始时间" name="currentPositionDate">
|
|
||||||
<DatePicker className="w-full" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="是否延期服役" name="isExtended" initialValue={false}>
|
|
||||||
<Radio.Group>
|
|
||||||
<Radio value={true}>是</Radio>
|
|
||||||
<Radio value={false}>否</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 教育背景 */}
|
|
||||||
<div className="bg-white p-6 rounded-lg shadow">
|
|
||||||
<h2 className="text-lg font-semibold mb-4">教育背景</h2>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<Form.Item label="学历" name="education">
|
|
||||||
<Select>
|
|
||||||
<Select.Option value="高中">高中</Select.Option>
|
|
||||||
<Select.Option value="专科">专科</Select.Option>
|
|
||||||
<Select.Option value="本科">本科</Select.Option>
|
|
||||||
<Select.Option value="硕士">硕士</Select.Option>
|
|
||||||
<Select.Option value="博士">博士</Select.Option>
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="学历形式" name="educationType">
|
|
||||||
<Select>
|
|
||||||
<Select.Option value="全日制">全日制</Select.Option>
|
|
||||||
<Select.Option value="非全日制">非全日制</Select.Option>
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="是否毕业" name="isGraduated">
|
|
||||||
<Radio.Group>
|
|
||||||
<Radio value={true}>是</Radio>
|
|
||||||
<Radio value={false}>否</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="专业" name="major">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="外语能力" name="foreignLang">
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 培训信息 */}
|
|
||||||
<div className="bg-white p-6 rounded-lg shadow">
|
|
||||||
<h2 className="text-lg font-semibold mb-4">培训信息</h2>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<Form.Item label="是否参加培训" name="hasTrain" initialValue={false}>
|
|
||||||
<Radio.Group>
|
|
||||||
<Radio value={true}>是</Radio>
|
|
||||||
<Radio value={false}>否</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
noStyle
|
|
||||||
shouldUpdate={(prevValues, currentValues) => prevValues.hasTrain !== currentValues.hasTrain}
|
|
||||||
>
|
|
||||||
{({ getFieldValue }) => (
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-1 gap-4">
|
|
||||||
<Form.Item label="培训类型" name="trainType">
|
|
||||||
<Input disabled={!getFieldValue('hasTrain')} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="培训机构" name="trainInstitute">
|
|
||||||
<Input disabled={!getFieldValue('hasTrain')} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="培训专业" name="trainMajor">
|
|
||||||
<Input disabled={!getFieldValue('hasTrain')} />
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 鉴定信息 */}
|
|
||||||
<div className="bg-white p-6 rounded-lg shadow">
|
|
||||||
<h2 className="text-lg font-semibold mb-4">鉴定信息</h2>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<Form.Item label="是否参加鉴定" name="hasCert" initialValue={false}>
|
|
||||||
<Radio.Group>
|
|
||||||
<Radio value={true}>是</Radio>
|
|
||||||
<Radio value={false}>否</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
noStyle
|
|
||||||
shouldUpdate={(prevValues, currentValues) => prevValues.hasCert !== currentValues.hasCert}
|
|
||||||
>
|
|
||||||
{({ getFieldValue }) => (
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-1 gap-4">
|
|
||||||
<Form.Item label="鉴定等级" name="certRank">
|
|
||||||
<Input disabled={!getFieldValue('hasCert')} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="鉴定工种" name="certWork">
|
|
||||||
<Input disabled={!getFieldValue('hasCert')} />
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 工作信息 */}
|
|
||||||
<div className="bg-white p-6 rounded-lg shadow">
|
|
||||||
<h2 className="text-lg font-semibold mb-4">工作信息</h2>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<div>
|
|
||||||
<div className="flex justify-between items-center mb-2">
|
|
||||||
<label>操作维护装备</label>
|
|
||||||
<Button type="primary" onClick={() => showModal('equipment')}>
|
|
||||||
添加装备
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className="border p-2 min-h-[100px] rounded">
|
|
||||||
{equipmentList.map((equipment, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="mb-2 p-2 bg-gray-50 rounded-md border border-gray-200 flex justify-between items-center"
|
|
||||||
>
|
|
||||||
<span>{equipment}</span>
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
danger
|
|
||||||
onClick={() => {
|
|
||||||
setEquipmentList(equipmentList.filter((_, i) => i !== index));
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
删除
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="flex justify-between items-center mb-2">
|
|
||||||
<label>任务经历</label>
|
|
||||||
<Button type="primary" onClick={() => showModal('projects')}>
|
|
||||||
添加任务
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className="border p-2 min-h-[100px] rounded">
|
|
||||||
{projectsList.map((mission, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="mb-2 p-2 bg-gray-50 rounded-md border border-gray-200 flex justify-between items-center"
|
|
||||||
>
|
|
||||||
<span>{mission}</span>
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
danger
|
|
||||||
onClick={() => {
|
|
||||||
setProjectsList(projectsList.filter((_, i) => i !== index));
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
删除
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="flex justify-between items-center mb-2">
|
|
||||||
<label>奖励信息</label>
|
|
||||||
<Button type="primary" onClick={() => showModal('awards')}>
|
|
||||||
添加奖励
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className="border p-2 min-h-[100px] rounded">
|
|
||||||
{rewardsList.map((reward, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="mb-2 p-2 bg-gray-50 rounded-md border border-gray-200 flex justify-between items-center"
|
|
||||||
>
|
|
||||||
<span>{reward}</span>
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
danger
|
|
||||||
onClick={() => {
|
|
||||||
setRewardsList(rewardsList.filter((_, i) => i !== index));
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
删除
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="flex justify-between items-center mb-2">
|
|
||||||
<label>处分信息</label>
|
|
||||||
<Button type="primary" onClick={() => showModal('punishments')}>
|
|
||||||
添加处分
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className="border p-2 min-h-[100px] rounded">
|
|
||||||
{punishmentsList.map((punishment, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="mb-2 p-2 bg-gray-50 rounded-md border border-gray-200 flex justify-between items-center"
|
|
||||||
>
|
|
||||||
<span>{punishment}</span>
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
danger
|
|
||||||
onClick={() => {
|
|
||||||
setPunishmentsList(punishmentsList.filter((_, i) => i !== index));
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
删除
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-white p-6 rounded-lg shadow">
|
|
||||||
<div className="flex justify-end space-x-4">
|
|
||||||
<Button onClick={() => form.resetFields()}>重置</Button>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
onClick={handleSubmit}
|
|
||||||
loading={loading}
|
|
||||||
>
|
|
||||||
提交
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Form>
|
|
||||||
|
|
||||||
<Modal
|
|
||||||
title={
|
|
||||||
modalType === 'awards' ? '添加奖励信息' :
|
|
||||||
modalType === 'punishments' ? '添加处分信息' :
|
|
||||||
modalType === 'equipment' ? '添加装备信息' : '添加任务信息'
|
|
||||||
}
|
|
||||||
open={isModalVisible}
|
|
||||||
onOk={handleModalOk}
|
|
||||||
onCancel={() => {
|
|
||||||
setIsModalVisible(false);
|
|
||||||
modalForm.resetFields();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Form form={modalForm}>
|
|
||||||
<Form.Item
|
|
||||||
label={
|
|
||||||
modalType === 'awards' ? '奖励内容' :
|
|
||||||
modalType === 'punishments' ? '处分内容' :
|
|
||||||
modalType === 'equipment' ? '装备信息' : '任务信息'
|
|
||||||
}
|
|
||||||
name={modalType}
|
|
||||||
rules={[{ required: true, message: '请输入内容' }]}
|
|
||||||
>
|
|
||||||
<TextArea
|
|
||||||
rows={4}
|
|
||||||
placeholder={
|
|
||||||
modalType === 'awards' ? '请输入获得的表彰奖励信息' :
|
|
||||||
modalType === 'punishments' ? '请输入处分信息' :
|
|
||||||
modalType === 'equipment' ? '请输入装备信息' : '请输入任务经历详情'
|
|
||||||
}
|
|
||||||
maxLength={500}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default StaffInformation;
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
import ErrorPage from "../app/error";
|
import ErrorPage from "../app/error";
|
||||||
import LoginPage from "../app/login";
|
import LoginPage from "../app/login";
|
||||||
import HomePage from "../app/main/home/page";
|
import HomePage from "../app/main/home/page";
|
||||||
import StaffMessage from "../app/main/staffinfo_show/page";
|
import StaffMessage from "../app/main/staffinfo_show/staffmessage_page";
|
||||||
import MainLayout from "../app/main/layout/MainLayout";
|
import MainLayout from "../app/main/layout/MainLayout";
|
||||||
import DailyPage from "../app/main/daily/page";
|
import DailyPage from "../app/main/daily/page";
|
||||||
import Dashboard from "../app/main/home/page";
|
import Dashboard from "../app/main/home/page";
|
||||||
|
|
|
@ -433,7 +433,7 @@ model StaffField {
|
||||||
createdAt DateTime @default(now()) @map("created_at")
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
updatedAt DateTime @updatedAt @map("updated_at")
|
updatedAt DateTime @updatedAt @map("updated_at")
|
||||||
deletedAt DateTime? @map("deleted_at")
|
deletedAt DateTime? @map("deleted_at")
|
||||||
StaffFieldValue StaffFieldValue[]
|
StaffFieldValue StaffFieldValue[] @relation("StaffFieldToValue") // 添加级联删除
|
||||||
|
|
||||||
@@index([group])
|
@@index([group])
|
||||||
@@index([order])
|
@@index([order])
|
||||||
|
@ -446,7 +446,7 @@ model StaffFieldValue {
|
||||||
fieldId String @map("field_id")
|
fieldId String @map("field_id")
|
||||||
value String? // 字段值
|
value String? // 字段值
|
||||||
staff Staff @relation(fields: [staffId], references: [id])
|
staff Staff @relation(fields: [staffId], references: [id])
|
||||||
field StaffField @relation(fields: [fieldId], references: [id])
|
field StaffField @relation("StaffFieldToValue",fields: [fieldId], references: [id], onDelete: Cascade) // 添加级联删除
|
||||||
createdAt DateTime @default(now()) @map("created_at")
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
updatedAt DateTime @updatedAt @map("updated_at")
|
updatedAt DateTime @updatedAt @map("updated_at")
|
||||||
|
|
||||||
|
@ -459,64 +459,13 @@ model StaffFieldValue {
|
||||||
model Staff {
|
model Staff {
|
||||||
// 基础信息
|
// 基础信息
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
username String @unique @map("username")
|
username String? @unique @map("username")
|
||||||
password String? @map("password")
|
password String? @map("password")
|
||||||
showname String? @map("showname")
|
showname String? @map("showname")
|
||||||
avatar String? @map("avatar")
|
avatar String? @map("avatar")
|
||||||
enabled Boolean? @default(true)
|
enabled Boolean? @default(true)
|
||||||
|
officerId String? @map("officer_id")
|
||||||
// 个人基本信息
|
phoneNumber String? @map("phone_number")
|
||||||
idNumber String? @unique @map("id_number") // 身份证号
|
|
||||||
type String? @map("type") // 人员类型
|
|
||||||
officerId String? @unique @map("officer_id") // 警号
|
|
||||||
phoneNumber String? @unique @map("phone_number") // 手机号
|
|
||||||
age Int? @map("age") // 年龄
|
|
||||||
sex Boolean? @map("sex") // 性别
|
|
||||||
bloodType String? @map("blood_type") // 血型
|
|
||||||
birthplace String? @map("birthplace") // 籍贯
|
|
||||||
source String? @map("source") // 来源
|
|
||||||
|
|
||||||
// 政治信息
|
|
||||||
politicalStatus String? @map("political_status") // 政治面貌
|
|
||||||
partyPosition String? @map("party_position") // 党内职务
|
|
||||||
|
|
||||||
// 职务信息
|
|
||||||
rank String? @map("rank") // 衔职级别
|
|
||||||
rankDate DateTime? @map("rank_date") // 衔职时间
|
|
||||||
proxyPosition String? @map("proxy_position") // 代理职务
|
|
||||||
post String? @map("post") // 岗位
|
|
||||||
|
|
||||||
// 入职相关信息
|
|
||||||
hireDate DateTime? @map("hire_date") // 入职时间
|
|
||||||
seniority DateTime? @map("seniority_date") // 工龄认定时间
|
|
||||||
sourceType String? @map("source_type") // 来源类型
|
|
||||||
isReentry Boolean? @default(false) @map("is_reentry") // 是否二次入职
|
|
||||||
isExtended Boolean? @default(false) @map("is_extended") // 是否延期服役
|
|
||||||
currentPositionDate DateTime? @map("current_position_date") // 现岗位开始时间
|
|
||||||
|
|
||||||
// 教育背景
|
|
||||||
education String? @map("education") // 学历
|
|
||||||
educationType String? @map("education_type") // 学历形式
|
|
||||||
isGraduated Boolean? @default(true) @map("is_graduated") // 是否毕业
|
|
||||||
major String? @map("major") // 专业
|
|
||||||
foreignLang String? @map("foreign_lang") // 外语能力
|
|
||||||
|
|
||||||
// 培训
|
|
||||||
trainType String? @map("train_type") // 培训类型
|
|
||||||
trainInstitute String? @map("train_institute") // 培训机构
|
|
||||||
trainMajor String? @map("train_major") // 培训专业
|
|
||||||
hasTrain Boolean? @default(false) @map("has_train") // 是否参加培训
|
|
||||||
|
|
||||||
//鉴定
|
|
||||||
certRank String? @map("cert_rank") // 鉴定等级
|
|
||||||
certWork String? @map("cert_work") // 鉴定工种
|
|
||||||
hasCert Boolean? @default(false) @map("has_cert") // 是否参加鉴定
|
|
||||||
|
|
||||||
// 工作信息
|
|
||||||
equipment String? @map("equipment") // 操作维护装备
|
|
||||||
projects String? @map("projects") // 演训任务经历
|
|
||||||
awards String? @map("awards") // 奖励信息
|
|
||||||
punishments String? @map("staff_punishments") // 处分信息
|
|
||||||
|
|
||||||
// 部门关系
|
// 部门关系
|
||||||
domainId String? @map("domain_id")
|
domainId String? @map("domain_id")
|
||||||
|
@ -547,7 +496,7 @@ model Staff {
|
||||||
logs SystemLog[] @relation("log_operator")
|
logs SystemLog[] @relation("log_operator")
|
||||||
// 添加自定义字段值关联
|
// 添加自定义字段值关联
|
||||||
fieldValues StaffFieldValue[]
|
fieldValues StaffFieldValue[]
|
||||||
|
|
||||||
@@index([officerId])
|
@@index([officerId])
|
||||||
@@index([deptId])
|
@@index([deptId])
|
||||||
@@index([domainId])
|
@@index([domainId])
|
||||||
|
|
Loading…
Reference in New Issue