fix: 组织架构部门下拉改为花名册相同的树形缩进模式

- 使用 buildDeptOptions 递归构建树形选项
- 用全角空格 ' '.repeat(level) 实现层级缩进
- 与花名册员工详情编辑的部门下拉保持一致
This commit is contained in:
freedakgmail
2026-08-18 22:14:17 +08:00
parent 04f119a53a
commit 1c5fde0b03
+19 -43
View File
@@ -51,27 +51,15 @@ export default function OrgChart() {
onError: (err: any) => toast.error(err?.response?.data?.error?.message || '删除失败'), onError: (err: any) => toast.error(err?.response?.data?.error?.message || '删除失败'),
}) })
// 构建部门层级路径映射,如 "总公司 / 技术部 / 前端组" // 构建部门树形下拉选项(带层级缩进)
const buildDeptPath = (departments: any[]): Record<string, string> => { const deptOptions: { id: string; label: string; level: number }[] = []
const map: Record<string, string> = {} const buildDeptOptions = (items: any[], parentId: string | null, level: number) => {
const byId: Record<string, any> = {} items.filter(d => d.parentId === parentId).sort((a, b) => a.sortOrder - b.sortOrder).forEach(d => {
departments.forEach(d => { byId[d.id] = d }) deptOptions.push({ id: d.id, label: d.name, level })
const getPath = (d: any): string => { buildDeptOptions(items, d.id, level + 1)
if (map[d.id]) return map[d.id] })
const parts: string[] = [d.name]
let cur = d
while (cur.parentId && byId[cur.parentId]) {
cur = byId[cur.parentId]
parts.unshift(cur.name)
} }
const path = parts.join(' / ') buildDeptOptions(departments, null, 0)
map[d.id] = path
return path
}
departments.forEach(d => getPath(d))
return map
}
const deptPathMap = buildDeptPath(departments)
const toggleExpand = (id: string) => { const toggleExpand = (id: string) => {
setExpanded(prev => { setExpanded(prev => {
@@ -202,9 +190,9 @@ export default function OrgChart() {
<div> <div>
<Label></Label> <Label></Label>
<Select value={form.parentId} onChange={(e) => setForm({ ...form, parentId: e.target.value })}> <Select value={form.parentId} onChange={(e) => setForm({ ...form, parentId: e.target.value })}>
{departments.filter((d: any) => d.id !== editing?.id).sort((a: any, b: any) => (deptPathMap[a.id] || a.name).localeCompare(deptPathMap[b.id] || b.name)).map((d: any) => ( {deptOptions.filter(d => d.id !== editing?.id).map(d => (
<option key={d.id} value={d.id}> <option key={d.id} value={d.id}>
{d.level === 0 && !d.parentId ? `${d.name}(公司)` : deptPathMap[d.id] || d.name} {' '.repeat(d.level)}{d.label}
</option> </option>
))} ))}
</Select> </Select>
@@ -237,27 +225,15 @@ function PositionTab({ positions, departments }: { positions: any[]; departments
const [editing, setEditing] = useState<any>(null) const [editing, setEditing] = useState<any>(null)
const [form, setForm] = useState<any>({ name: '', departmentId: '', headcount: 0, level: '', description: '' }) const [form, setForm] = useState<any>({ name: '', departmentId: '', headcount: 0, level: '', description: '' })
// 构建部门层级路径 // 构建部门树形下拉选项(带层级缩进)
const buildDeptPath = (depts: any[]): Record<string, string> => { const deptOptions: { id: string; label: string; level: number }[] = []
const map: Record<string, string> = {} const buildDeptOptions = (items: any[], parentId: string | null, level: number) => {
const byId: Record<string, any> = {} items.filter(d => d.parentId === parentId).sort((a, b) => a.sortOrder - b.sortOrder).forEach(d => {
depts.forEach(d => { byId[d.id] = d }) deptOptions.push({ id: d.id, label: d.name, level })
const getPath = (d: any): string => { buildDeptOptions(items, d.id, level + 1)
if (map[d.id]) return map[d.id] })
const parts: string[] = [d.name]
let cur = d
while (cur.parentId && byId[cur.parentId]) {
cur = byId[cur.parentId]
parts.unshift(cur.name)
} }
const path = parts.join(' / ') buildDeptOptions(departments, null, 0)
map[d.id] = path
return path
}
depts.forEach(d => getPath(d))
return map
}
const deptPathMap = buildDeptPath(departments)
const createMutation = useMutation({ const createMutation = useMutation({
mutationFn: (data: any) => editing ? api.put(`/positions/${editing.id}`, data) : api.post('/positions', data), mutationFn: (data: any) => editing ? api.put(`/positions/${editing.id}`, data) : api.post('/positions', data),
@@ -332,7 +308,7 @@ function PositionTab({ positions, departments }: { positions: any[]; departments
<Label></Label> <Label></Label>
<Select value={form.departmentId} onChange={(e) => setForm({ ...form, departmentId: e.target.value })}> <Select value={form.departmentId} onChange={(e) => setForm({ ...form, departmentId: e.target.value })}>
<option value=""></option> <option value=""></option>
{departments.sort((a: any, b: any) => (deptPathMap[a.id] || a.name).localeCompare(deptPathMap[b.id] || b.name)).map(d => <option key={d.id} value={d.id}>{deptPathMap[d.id] || d.name}</option>)} {deptOptions.map(d => <option key={d.id} value={d.id}>{' '.repeat(d.level)}{d.label}</option>)}
</Select> </Select>
</div> </div>
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">