ux: 部门字段统一改为下拉选择(组织架构部门树)
将以下页面的部门输入框从 Input 改为 Select 下拉选择, 数据源为组织架构部门树(带层级缩进): 1. roster/modals.tsx - RehireModal 重新入职弹窗 2. roster/modals.tsx - AddEmployeeModal 添加员工弹窗 3. roster/BasicInfo.tsx - 编辑员工基本信息 4. Contracts.tsx - 合同管理新增员工弹窗 下拉选项从 /departments 接口获取,按树形结构展示, 提交时传部门名称字符串(保持后端兼容)。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { Plus, Search, Paperclip, Trash2, X, FileText, Download } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { rosterApi, employeeApi, attachmentApi } from '../lib/api-services'
|
||||
import api from '../lib/api'
|
||||
import Card from '../components/ui/Card'
|
||||
import Button from '../components/ui/Button'
|
||||
import { Input, Label, Select } from '../components/ui/Input'
|
||||
@@ -217,6 +218,20 @@ function AddEmployeeModal({ open, onClose, onSubmit, loading, error }: {
|
||||
loading: boolean
|
||||
error: any
|
||||
}) {
|
||||
// 拉取组织架构部门列表,用于部门下拉选择
|
||||
const { data: departments = [] } = useQuery({
|
||||
queryKey: ['departments'],
|
||||
queryFn: () => api.get('/departments').then(r => r.data),
|
||||
})
|
||||
// 构建部门树形下拉选项(带层级缩进)
|
||||
const deptOptions: { id: string; label: string; level: number }[] = []
|
||||
const buildDeptOptions = (items: any[], parentId: string | null, level: number) => {
|
||||
items.filter(d => d.parentId === parentId).sort((a, b) => a.sortOrder - b.sortOrder).forEach(d => {
|
||||
deptOptions.push({ id: d.id, label: d.name, level })
|
||||
buildDeptOptions(items, d.id, level + 1)
|
||||
})
|
||||
}
|
||||
buildDeptOptions(departments, null, 0)
|
||||
const [form, setForm] = useState({
|
||||
name: '',
|
||||
department: '',
|
||||
@@ -280,7 +295,12 @@ function AddEmployeeModal({ open, onClose, onSubmit, loading, error }: {
|
||||
</div>
|
||||
<div>
|
||||
<Label>部门 *</Label>
|
||||
<Input value={form.department} onChange={(e) => setForm({ ...form, department: e.target.value })} placeholder="如:技术部" />
|
||||
<Select value={form.department} onChange={(e) => setForm({ ...form, department: e.target.value })}>
|
||||
<option value="">请选择部门</option>
|
||||
{deptOptions.map(d => (
|
||||
<option key={d.id} value={d.label}>{' '.repeat(d.level)}{d.label}</option>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
||||
import { attachmentApi, employeeApi, socialInsuranceApi } from '../../lib/api-services'
|
||||
import { useConfirm } from '../../hooks/useConfirm'
|
||||
import { copyToClipboard } from '../../lib/clipboard'
|
||||
import api from '../../lib/api'
|
||||
import Card from "../../components/ui/Card"
|
||||
import Button from "../../components/ui/Button"
|
||||
import { Input, Label, Select } from "../../components/ui/Input"
|
||||
@@ -58,6 +59,21 @@ export default function BasicInfo({ profile, employeeId, attachments }: { profil
|
||||
return `${(bytes / 1024 / 1024).toFixed(1)}MB`
|
||||
}
|
||||
|
||||
// 拉取组织架构部门列表,用于部门下拉选择
|
||||
const { data: departments = [] } = useQuery({
|
||||
queryKey: ['departments'],
|
||||
queryFn: () => api.get('/departments').then(r => r.data),
|
||||
})
|
||||
// 构建部门树形下拉选项(带层级缩进)
|
||||
const deptOptions: { id: string; label: string; level: number }[] = []
|
||||
const buildDeptOptions = (items: any[], parentId: string | null, level: number) => {
|
||||
items.filter(d => d.parentId === parentId).sort((a, b) => a.sortOrder - b.sortOrder).forEach(d => {
|
||||
deptOptions.push({ id: d.id, label: d.name, level })
|
||||
buildDeptOptions(items, d.id, level + 1)
|
||||
})
|
||||
}
|
||||
buildDeptOptions(departments, null, 0)
|
||||
|
||||
const [form, setForm] = useState({
|
||||
department: profile.department || '',
|
||||
position: profile.position || '',
|
||||
@@ -346,7 +362,7 @@ export default function BasicInfo({ profile, employeeId, attachments }: { profil
|
||||
<div className="grid md:grid-cols-2 gap-3">
|
||||
<div><Label>姓名(不可编辑)</Label><Input value={profile.name} disabled /></div>
|
||||
<div><Label>证件号码(不可编辑)</Label><Input value={profile.idCardNumber || ''} disabled /></div>
|
||||
<div><Label>部门</Label><Input value={form.department} onChange={(e) => setForm({ ...form, department: e.target.value })} /></div>
|
||||
<div><Label>部门</Label><Select value={form.department} onChange={(e) => setForm({ ...form, department: e.target.value })}><option value="">请选择部门</option>{deptOptions.map(d => <option key={d.id} value={d.label}>{' '.repeat(d.level)}{d.label}</option>)}</Select></div>
|
||||
<div><Label>性别</Label><Select value={form.gender} onChange={(e) => setForm({ ...form, gender: e.target.value as '男' | '女' })}><option value="男">男</option><option value="女">女</option></Select></div>
|
||||
{form.gender === '女' && (
|
||||
<div><Label>女性岗位类型</Label><Select value={form.femaleWorkerType} onChange={(e) => setForm({ ...form, femaleWorkerType: e.target.value as '' | 'CADRE' | 'WORKER' })}><option value="">未选择</option><option value="CADRE">干部/管理岗</option><option value="WORKER">工人/操作岗</option></Select></div>
|
||||
|
||||
@@ -408,6 +408,20 @@ export function RehireModal({ employee, onClose, onSubmit, loading, error }: {
|
||||
},
|
||||
staleTime: Infinity,
|
||||
})
|
||||
// 拉取组织架构部门列表,用于部门下拉选择
|
||||
const { data: departments = [] } = useQuery({
|
||||
queryKey: ['departments'],
|
||||
queryFn: () => api.get('/departments').then(r => r.data),
|
||||
})
|
||||
// 构建部门树形下拉选项(带层级缩进)
|
||||
const deptOptions: { id: string; label: string; level: number }[] = []
|
||||
const buildDeptOptions = (items: any[], parentId: string | null, level: number) => {
|
||||
items.filter(d => d.parentId === parentId).sort((a, b) => a.sortOrder - b.sortOrder).forEach(d => {
|
||||
deptOptions.push({ id: d.id, label: d.name, level })
|
||||
buildDeptOptions(items, d.id, level + 1)
|
||||
})
|
||||
}
|
||||
buildDeptOptions(departments, null, 0)
|
||||
const defaultEndDate = (() => {
|
||||
const d = new Date()
|
||||
d.setFullYear(d.getFullYear() + 3)
|
||||
@@ -543,7 +557,12 @@ export function RehireModal({ employee, onClose, onSubmit, loading, error }: {
|
||||
</div>
|
||||
<div>
|
||||
<Label>部门 *</Label>
|
||||
<Input value={form.department} onChange={(e) => setForm({ ...form, department: e.target.value })} placeholder="如:技术部" />
|
||||
<Select value={form.department} onChange={(e) => setForm({ ...form, department: e.target.value })}>
|
||||
<option value="">请选择部门</option>
|
||||
{deptOptions.map(d => (
|
||||
<option key={d.id} value={d.label}>{' '.repeat(d.level)}{d.label}</option>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
@@ -665,6 +684,20 @@ export function AddEmployeeModal({ onClose, onSubmit, loading, error }: {
|
||||
},
|
||||
staleTime: Infinity,
|
||||
})
|
||||
// 拉取组织架构部门列表,用于部门下拉选择
|
||||
const { data: departments = [] } = useQuery({
|
||||
queryKey: ['departments'],
|
||||
queryFn: () => api.get('/departments').then(r => r.data),
|
||||
})
|
||||
// 构建部门树形下拉选项(带层级缩进)
|
||||
const deptOptions: { id: string; label: string; level: number }[] = []
|
||||
const buildDeptOptions = (items: any[], parentId: string | null, level: number) => {
|
||||
items.filter(d => d.parentId === parentId).sort((a, b) => a.sortOrder - b.sortOrder).forEach(d => {
|
||||
deptOptions.push({ id: d.id, label: d.name, level })
|
||||
buildDeptOptions(items, d.id, level + 1)
|
||||
})
|
||||
}
|
||||
buildDeptOptions(departments, null, 0)
|
||||
const defaultEndDate = (() => {
|
||||
const d = new Date()
|
||||
d.setFullYear(d.getFullYear() + 3)
|
||||
@@ -872,7 +905,7 @@ export function AddEmployeeModal({ onClose, onSubmit, loading, error }: {
|
||||
{/* 基本信息 */}
|
||||
<div className="grid grid-cols-4 gap-4">
|
||||
<div><Label>姓名 *</Label><Input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} placeholder="员工姓名" /></div>
|
||||
<div><Label>部门 *</Label><Input value={form.department} onChange={(e) => setForm({ ...form, department: e.target.value })} placeholder="如:技术部" /></div>
|
||||
<div><Label>部门 *</Label><Select value={form.department} onChange={(e) => setForm({ ...form, department: e.target.value })}><option value="">请选择部门</option>{deptOptions.map(d => <option key={d.id} value={d.label}>{' '.repeat(d.level)}{d.label}</option>)}</Select></div>
|
||||
<div><Label>职务/岗位</Label><Input value={form.position} onChange={(e) => setForm({ ...form, position: e.target.value })} placeholder="如:前端工程师" /></div>
|
||||
<div><Label>证件号码 *</Label><Input value={form.idCardNumber} onChange={(e) => handleIdCardChange(e.target.value)} placeholder="18位" maxLength={18} /></div>
|
||||
{idCardDuplicate?.exists && (
|
||||
|
||||
Reference in New Issue
Block a user