| | |
| | | import { useCallback, useEffect, useMemo, useState } from 'react'; |
| | | import { ProFormSelect, ProFormTreeSelect } from '@ant-design/pro-components'; |
| | | import { |
| | | App as AntdApp, |
| | | Button, |
| | |
| | | InputNumber, |
| | | Select, |
| | | Space, |
| | | TreeSelect, |
| | | } from 'antd'; |
| | | import { createOrg, updateOrg } from '../server'; |
| | | import { createOrg, getLeaderDetail, getLeaderOptions, updateOrg } from '../server'; |
| | | import type { DepartmentFormValues, OrgVO } from '../types'; |
| | | import { toOrgTreeSelectData } from '../utils'; |
| | | |
| | |
| | | parentId?: number; |
| | | /** 组织树,用于上级组织选择。 */ |
| | | orgTree: OrgVO[]; |
| | | /** 负责人员工下拉选项。 */ |
| | | leaderOptions: { label: string; value: number }[]; |
| | | onClose: () => void; |
| | | onSuccess: () => void; |
| | | } |
| | |
| | | record, |
| | | parentId, |
| | | orgTree, |
| | | leaderOptions, |
| | | onClose, |
| | | onSuccess, |
| | | }: DepartmentFormDrawerProps) => { |
| | |
| | | const [submitting, setSubmitting] = useState(false); |
| | | const { message } = AntdApp.useApp(); |
| | | const isEdit = mode === 'edit'; |
| | | /** 新增入口只有「新增子部门」,上级组织已确定,不允许再选择。 */ |
| | | const parentDisabled = !isEdit; |
| | | |
| | | const parentOptions = useMemo( |
| | | () => toOrgTreeSelectData(orgTree, isEdit ? record?.id : undefined), |
| | | [isEdit, orgTree, record], |
| | | ); |
| | | |
| | | /** 负责人远程搜索:按姓名 / 手机号模糊查询员工。 */ |
| | | const requestLeaderOptions = useCallback( |
| | | async ({ keyWords }: { keyWords?: string }) => { |
| | | const keyword = keyWords?.trim(); |
| | | const result = await getLeaderOptions({ |
| | | page: 1, |
| | | size: 50, |
| | | keyword: keyword || undefined, |
| | | }); |
| | | const options = (result.records ?? []).map((employee) => ({ |
| | | label: employee.name, |
| | | value: employee.id, |
| | | })); |
| | | |
| | | // 编辑时把当前负责人补进首屏选项,避免回填后显示为员工 ID。 |
| | | const currentLeaderId = isEdit ? record?.leaderId : undefined; |
| | | if ( |
| | | !keyword && |
| | | currentLeaderId && |
| | | !options.some((option) => option.value === currentLeaderId) |
| | | ) { |
| | | try { |
| | | const leader = await getLeaderDetail({ id: currentLeaderId }); |
| | | options.unshift({ label: leader.name, value: leader.id }); |
| | | } catch { |
| | | // 错误已由 request 统一提示 |
| | | } |
| | | } |
| | | |
| | | return options; |
| | | }, |
| | | [isEdit, record], |
| | | ); |
| | | |
| | | useEffect(() => { |
| | |
| | | } |
| | | }, [form, isEdit, message, onSuccess, record]); |
| | | |
| | | const title = isEdit ? '编辑部门' : parentId ? '新增子部门' : '新增部门'; |
| | | const title = isEdit ? '编辑部门' : '新增子部门'; |
| | | |
| | | return ( |
| | | <Drawer |
| | |
| | | ]} |
| | | /> |
| | | </Form.Item> |
| | | <Form.Item name="parentId" label="上级组织"> |
| | | <TreeSelect |
| | | treeData={parentOptions} |
| | | treeDefaultExpandAll |
| | | allowClear |
| | | showSearch |
| | | treeNodeFilterProp="title" |
| | | <ProFormTreeSelect |
| | | name="parentId" |
| | | label="上级组织" |
| | | placeholder="不选则作为根组织" |
| | | style={{ width: '100%' }} |
| | | disabled={parentDisabled} |
| | | fieldProps={{ |
| | | treeData: parentOptions, |
| | | treeDefaultExpandAll: true, |
| | | allowClear: true, |
| | | showSearch: true, |
| | | treeNodeFilterProp: 'title', |
| | | style: { width: '100%' }, |
| | | }} |
| | | /> |
| | | </Form.Item> |
| | | <Form.Item name="leaderId" label="负责人"> |
| | | <Select |
| | | options={leaderOptions} |
| | | <ProFormSelect |
| | | name="leaderId" |
| | | label="负责人" |
| | | rules={isEdit ? undefined : [{ required: true, message: '请选择负责人' }]} |
| | | placeholder="请输入姓名搜索负责人" |
| | | showSearch |
| | | optionFilterProp="label" |
| | | allowClear |
| | | placeholder="请选择负责人" |
| | | debounceTime={300} |
| | | request={requestLeaderOptions} |
| | | fieldProps={{ filterOption: false, style: { width: '100%' } }} |
| | | /> |
| | | </Form.Item> |
| | | <Form.Item name="region" label="所在地区"> |
| | | <Input placeholder="请输入所在地区" maxLength={50} /> |
| | | </Form.Item> |