From 7257164250381b93353933df1430a0420027c377 Mon Sep 17 00:00:00 2001 From: linfeng <2819853134@qq.com> Date: Thu, 27 Mar 2025 08:59:02 +0800 Subject: [PATCH] lin --- apps/server/src/models/staff/staff.router.ts | 1 + apps/server/src/models/staff/staff.service.ts | 2 + .../admin/staffinfo-manage/defaultFields.ts | 11 +- .../staffinfo-manage/staffFieldManage.tsx | 36 +- apps/web/src/app/main/staffinfo_show/page.tsx | 2 +- .../main/staffinfo_show/staffmessage_page.tsx | 130 +++++ .../main/staffinfo_show/stafftable/page.tsx | 2 +- .../src/app/main/staffinfo_write/infoCard.tsx | 7 +- .../staffinfo_write/staffinfo_write.page.tsx | 83 ++- .../src/app/main/staffinformation/page.tsx | 519 ------------------ apps/web/src/routes/index.tsx | 2 +- packages/common/prisma/schema.prisma | 63 +-- 12 files changed, 236 insertions(+), 622 deletions(-) create mode 100644 apps/web/src/app/main/staffinfo_show/staffmessage_page.tsx delete mode 100644 apps/web/src/app/main/staffinformation/page.tsx diff --git a/apps/server/src/models/staff/staff.router.ts b/apps/server/src/models/staff/staff.router.ts index 609474a..9fb0446 100755 --- a/apps/server/src/models/staff/staff.router.ts +++ b/apps/server/src/models/staff/staff.router.ts @@ -140,5 +140,6 @@ export class StaffRouter { .mutation(({ input }) => { return this.staffService.setCustomFieldValue(input as any); }), + }); } diff --git a/apps/server/src/models/staff/staff.service.ts b/apps/server/src/models/staff/staff.service.ts index c8d75d1..0ffcde0 100755 --- a/apps/server/src/models/staff/staff.service.ts +++ b/apps/server/src/models/staff/staff.service.ts @@ -255,4 +255,6 @@ export class StaffService extends BaseService { }, }); } + + } diff --git a/apps/web/src/app/admin/staffinfo-manage/defaultFields.ts b/apps/web/src/app/admin/staffinfo-manage/defaultFields.ts index 7b99fcf..f849947 100644 --- a/apps/web/src/app/admin/staffinfo-manage/defaultFields.ts +++ b/apps/web/src/app/admin/staffinfo-manage/defaultFields.ts @@ -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 = [ // 基本信息组 - { name: 'username', label: '用户名', type: 'text',required: true, group: '基本信息', order: 1 }, - // { name: 'showname', label: '显示名称', type: 'text', group: '基本信息', order: 2 }, + // { name: 'username', label: '用户名', type: 'text',required: true, group: '基本信息', order: 1 }, { name: 'idNumber', label: '身份证号', type: 'text', group: '基本信息', order: 3 }, { name: 'officerId', label: '警号', type: 'text', group: '基本信息', order: 4 }, { name: 'phoneNumber', label: '手机号', type: 'text', group: '基本信息', order: 5 }, @@ -35,7 +38,7 @@ export const defaultFields = [ group: '基本信息', order: 9 }, { name: 'source', label: '来源', type: 'text', group: '基本信息', order: 10 }, - {name: 'department', label: '部门', type: 'text', group: '基本信息', order: 11 }, + // 政治信息组 { name: 'politicalStatus', diff --git a/apps/web/src/app/admin/staffinfo-manage/staffFieldManage.tsx b/apps/web/src/app/admin/staffinfo-manage/staffFieldManage.tsx index e2f3f61..1e87380 100644 --- a/apps/web/src/app/admin/staffinfo-manage/staffFieldManage.tsx +++ b/apps/web/src/app/admin/staffinfo-manage/staffFieldManage.tsx @@ -63,6 +63,24 @@ const StaffFieldManage = () => { 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 () => { 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 (
diff --git a/apps/web/src/app/main/staffinfo_show/page.tsx b/apps/web/src/app/main/staffinfo_show/page.tsx index 07912f1..144b0b7 100644 --- a/apps/web/src/app/main/staffinfo_show/page.tsx +++ b/apps/web/src/app/main/staffinfo_show/page.tsx @@ -5,7 +5,7 @@ import _ from "lodash"; import { useMainContext } from "../layout/MainProvider"; import StaffTable from "./stafftable/page"; -export default function StaffMessage() { +export default function StaffMessageGG() { const { form, formValue, setFormValue, setVisible, setSearchValue, editingRecord } = useMainContext(); useEffect(() => { diff --git a/apps/web/src/app/main/staffinfo_show/staffmessage_page.tsx b/apps/web/src/app/main/staffinfo_show/staffmessage_page.tsx new file mode 100644 index 0000000..6c0a193 --- /dev/null +++ b/apps/web/src/app/main/staffinfo_show/staffmessage_page.tsx @@ -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([]); + const [columnDefs, setColumnDefs] = useState([]); + const [selectedRows, setSelectedRows] = useState([]); + 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 ( + + <> + + +
+

人员总览

+ setSelectedRows(e.api.getSelectedRows())} + rowSelection="multiple" + /> +
+ + + ); +} \ No newline at end of file diff --git a/apps/web/src/app/main/staffinfo_show/stafftable/page.tsx b/apps/web/src/app/main/staffinfo_show/stafftable/page.tsx index 3463aec..220fe2c 100644 --- a/apps/web/src/app/main/staffinfo_show/stafftable/page.tsx +++ b/apps/web/src/app/main/staffinfo_show/stafftable/page.tsx @@ -146,7 +146,7 @@ export default function StaffTable() { }; const columnDefs: (ColDef | ColGroupDef)[] = [ { - field: 'username', + field: 'showname', headerName: '姓名', pinned: 'left', // floatingFilter: true // 确保启用浮动过滤器 diff --git a/apps/web/src/app/main/staffinfo_write/infoCard.tsx b/apps/web/src/app/main/staffinfo_write/infoCard.tsx index 78a96b7..89b4c4e 100644 --- a/apps/web/src/app/main/staffinfo_write/infoCard.tsx +++ b/apps/web/src/app/main/staffinfo_write/infoCard.tsx @@ -2,7 +2,7 @@ import { Input, Button } from 'antd'; import React, { useState, useRef, useEffect } from 'react'; type InfoCardProps = { - onAdd: (content: string) => void; + onAdd: (content: string[]) => void; onHeightChange?: (height: number) => void; // 添加高度变化回调 } @@ -35,8 +35,9 @@ const InfoCard: React.FC = ({ onAdd, onHeightChange }) => { const handleAdd = () => { if (content) { - onAdd(content); - setAddedContents([...addedContents, content]); + const newContents = [...addedContents, content]; // 创建包含所有内容的新数组 + onAdd(newContents); // 将累积数组传递给父组件 + setAddedContents(newContents); setContent(''); } } diff --git a/apps/web/src/app/main/staffinfo_write/staffinfo_write.page.tsx b/apps/web/src/app/main/staffinfo_write/staffinfo_write.page.tsx index 9b8fe79..9ca5c1a 100644 --- a/apps/web/src/app/main/staffinfo_write/staffinfo_write.page.tsx +++ b/apps/web/src/app/main/staffinfo_write/staffinfo_write.page.tsx @@ -3,7 +3,8 @@ import { useState, useMemo, useEffect } from "react"; import { useStaff } from "@nice/client"; import { areaOptions } from './area-options'; 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 [form] = Form.useForm(); const [loading, setLoading] = useState(false); @@ -19,8 +20,13 @@ const StaffInfoWrite = () => { // 添加状态来跟踪每个文本区域的高度 const [textAreaHeights, setTextAreaHeights] = useState>({}); - const handleAdd = (content: string) => { - setInfoCards([...infoCards, { content }]); + const handleAdd = (content: string[]) => { + // 将数组内容展开为独立对象 + 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) { case 'text': - return ; + if(field.name === 'department'){ + return ; + }else{ + return ; + } case 'number': return ; case 'date': @@ -136,7 +146,11 @@ const StaffInfoWrite = () => { }} > { + handleAdd(contents); + // 同步更新表单字段值 + form.setFieldValue(field.name, contents); + }} onHeightChange={(height) => { setTextAreaHeights(prev => ({ ...prev, @@ -165,37 +179,47 @@ const StaffInfoWrite = () => { setLoading(true); // 创建基础员工记录 - if (!values.username) { - message.error("用户名不能为空"); + if (!values.showname) { + message.error("姓名不能为空"); return; } // 创建基础员工记录 - console.log('准备创建用户,数据:', { username: values.username }); + console.log('准备创建用户,数据:', { showname: values.showname }); const staff = await create.mutateAsync({ data: { - username: values.username, - password: '123456' + showname: values.showname, + deptId: values.department? values.department : null, } }); console.log('创建员工记录:', staff); // 过滤有效字段并转换值 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]) => { - const field = fields && Array.isArray(fields) ? fields.find((f: any) => f.name === fieldName) : undefined; - let processedValue = value; + const field = fields && Array.isArray(fields) ? + fields.find((f: any) => f.name === fieldName) : undefined; // 处理特殊字段类型 - if (field?.type === 'date') { - processedValue = value.toString(); - } else if (field?.type === 'cascader' && Array.isArray(value)) { - processedValue = value.join('/'); + let processedValue = value; + if (field?.type === 'date') { //日期类型 + processedValue = (value as Date)?.toISOString(); + } 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 }; }) - .filter(item => item.field?.id); // 过滤有效字段定义 + .filter(item => item.field?.id); // 批量提交自定义字段 await Promise.all( @@ -240,6 +264,27 @@ const StaffInfoWrite = () => { }} className="space-y-6 mt-6" > + {/* 新增基础信息区块 */} +
+ +
+ {baseFields.map((field) => ( + + {renderField(field, '系统默认信息')} + + ))} +
+
{Object.entries(fieldGroups).map(([groupName, groupFields]) => (

{groupName}

@@ -247,7 +292,7 @@ const StaffInfoWrite = () => { 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" : ""} `}> - {groupFields.map((field: any) => ( + {(groupFields as any[])?.map((field: any) => ( {field.label}} diff --git a/apps/web/src/app/main/staffinformation/page.tsx b/apps/web/src/app/main/staffinformation/page.tsx deleted file mode 100644 index 5c7c50c..0000000 --- a/apps/web/src/app/main/staffinformation/page.tsx +++ /dev/null @@ -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([]); - const [punishmentsList, setPunishmentsList] = useState([]); - const [equipmentList, setEquipmentList] = useState([]); // 新增装备列表 - const [projectsList, setProjectsList] = useState([]); // 新增任务列表 - 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 ( -
-

人员信息填报

-
{ - console.log('表单验证失败:', errorInfo); - }} - className="space-y-6" - > - {/* 个人基本信息 */} -
-

个人基本信息

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - { - return path.some(option => - typeof option.label === 'string' && - option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1 - ); - } - }} - changeOnSelect - /> - -
-
- - {/* 政治信息 */} -
-

政治信息

-
- - - - - - -
-
- - {/* 职务信息 */} -
-

职务信息

-
- - - - - - - - - - - - - - - -
-
- - {/* 入职信息 */} -
-

入职信息

-
- - - - - - - - - - - - - - - - - - - - - - - - -
-
- - {/* 教育背景 */} -
-

教育背景

-
- - - - - - - - - - - - - - - - - - -
-
- - {/* 培训信息 */} -
-

培训信息

-
- - - - - - - prevValues.hasTrain !== currentValues.hasTrain} - > - {({ getFieldValue }) => ( -
- - - - - - - - - -
- )} -
-
-
- - {/* 鉴定信息 */} -
-

鉴定信息

-
- - - - - - - prevValues.hasCert !== currentValues.hasCert} - > - {({ getFieldValue }) => ( -
- - - - - - -
- )} -
-
-
- - {/* 工作信息 */} -
-

工作信息

-
-
-
- - -
-
- {equipmentList.map((equipment, index) => ( -
- {equipment} - -
- ))} -
-
-
-
- - -
-
- {projectsList.map((mission, index) => ( -
- {mission} - -
- ))} -
-
-
-
- - -
-
- {rewardsList.map((reward, index) => ( -
- {reward} - -
- ))} -
-
-
-
- - -
-
- {punishmentsList.map((punishment, index) => ( -
- {punishment} - -
- ))} -
-
-
-
- -
-
- - -
-
-
- - { - setIsModalVisible(false); - modalForm.resetFields(); - }} - > -
- -