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:
selfrelease
2026-08-16 09:23:24 +08:00
parent 9a826c16b0
commit dd0e84a219
3 changed files with 73 additions and 4 deletions
+35 -2
View File
@@ -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 && (