import { PlusOutlined } from "@ant-design/icons"; import { Connect } from "@cqsjjb/jjb-dva-runtime"; import { Button, Empty, Form, Input, message, Modal, Select, Space, Tree, Table, TreeSelect, } from "antd"; import { AntdTableFuncControl } from "@cqsjjb/jjb-common-decorator/antd"; import TableAction from "@cqsjjb/jjb-react-admin-component/TableAction"; import { useEffect, useMemo, useRef, useState } from "react"; import PageLayout from "@cqsjjb/jjb-react-admin-component/PageLayout"; import SearchForm from "@cqsjjb/jjb-react-admin-component/SearchForm"; import { NS_ORG_DEPARTMENT, NS_ORG_POSITION, NS_STAFF_INFO, } from "~/enumerate/namespace"; import { asId, sameId } from "~/utils/enterpriseInfo/idUtil"; function findDeptNode(nodes = [], id) { for (const node of nodes) { if (sameId(node.id, id)) { return node; } if (node.children?.length) { const found = findDeptNode(node.children, id); if (found) { return found; } } } return null; } function toSelectedDept(node) { if (!node) { return null; } return { id: asId(node.id), deptName: node.deptName || node.title, managerAccount: node.managerAccount, managerName: node.managerName, deptLevelName: node.deptLevelName, }; } function DepartmentPositionPage(props) { const {orgPosition}=props; const {orgPositionLoading}=orgPosition; const [selectedDept, setSelectedDept] = useState(null); const [treeData, setTreeData] = useState([]); const [deptModalOpen, setDeptModalOpen] = useState(false); const [positionModalOpen, setPositionModalOpen] = useState(false); const [currentId, setCurrentId] = useState(""); const [filterKeyword, setFilterKeyword] = useState(""); const [staffOptions, setStaffOptions] = useState([]); const [positionForm] = Form.useForm(); const [modalForm] = Form.useForm(); const [dataSource, setDataSource] = useState([]); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(false); const [pageIndex, setPageIndex] = useState(1); const [pageSize, setPageSize] = useState(10); useEffect(() => { (async () => { try { const res = await props.staffInfoList?.({ pageIndex: 1, pageSize: 500, }); setStaffOptions( (res?.data || []).map((s) => ({ label: `${s.userName ?? s.staffName}(${s.account})`, value: s.account, staffName: s.userName ?? s.staffName, })), ); } catch (err) { console.warn("[DepartmentPosition] load staff options failed:", err); } })(); }, []); const fetchPositionData = async (page = 1, size = 10) => { if (!selectedDept?.id) return; setLoading(true); try { const formData = positionForm.getFieldsValue(); const res = await props.orgPositionList({ ...formData, pageIndex: page, pageSize: size, deptId: asId(selectedDept.id), }); setDataSource(res?.data || []); setTotal(res?.totalCount || 0); } catch { setDataSource([]); setTotal(0); } finally { setLoading(false); } }; const loadTree = async () => { try { const res = await props.orgDepartmentTree(); const tree = res?.data || []; setTreeData(tree); if (tree.length) { setSelectedDept(toSelectedDept(tree[0])); } } catch (err) { console.warn("[DepartmentPosition] loadTree failed:", err); setTreeData([]); } }; useEffect(() => { loadTree(); }, []); useEffect(() => { if (selectedDept?.id) { fetchPositionData(1, 10); } }, [selectedDept?.id]); const filteredTree = useMemo(() => { if (!filterKeyword) { return treeData; } const filterNodes = (nodes) => { return nodes .map((node) => { const children = node.children ? filterNodes(node.children) : []; const match = (node.deptName || node.title)?.includes(filterKeyword); if (match || children.length) { return { ...node, children }; } return null; }) .filter(Boolean); }; return filterNodes(treeData); }, [treeData, filterKeyword]); const onDeleteDept = (id) => { Modal.confirm({ title: "提示", content: "数据将会删除,您是否确认删除?", okText: "是", cancelText: "否", onOk: async () => { const res = await props.orgDepartmentRemove({ data: id }); if (res?.success !== false) { message.success("删除成功"); if (sameId(selectedDept?.id, id)) { setSelectedDept(null); } loadTree(); } }, }); }; const onDeletePosition = (id) => { Modal.confirm({ title: "提示", content: "数据将会删除,您是否确认删除?", okText: "是", cancelText: "否", onOk: async () => { const res = await props.orgPositionRemove({ data: id }); if (res?.success !== false) { message.success("删除成功"); fetchPositionData(1, 10); } }, }); }; const closeDeptModal = () => { modalForm.resetFields(); setCurrentId(""); setDeptModalOpen(false); }; const closePositionModal = () => { modalForm.resetFields(); setCurrentId(""); setPositionModalOpen(false); }; const openDeptModal = (record) => { setCurrentId(asId(record?.id) || ""); setDeptModalOpen(true); }; const openPositionModal = (record) => { if (!selectedDept?.id) { message.warning("请先选择部门"); return; } setCurrentId(asId(record?.id) || ""); modalForm.resetFields(); if (record) { modalForm.setFieldsValue({ ...record, deptId: asId(record.deptId || selectedDept.id), deptName: record.deptName || selectedDept.deptName, }); } else { modalForm.setFieldsValue({ deptId: asId(selectedDept.id), deptName: selectedDept.deptName, }); } setPositionModalOpen(true); }; const submitPosition = async (values) => { const request = currentId ? props.orgPositionEdit : props.orgPositionAdd; const payload = { ...values }; if (currentId) { payload.id = currentId; } payload.deptId = asId(values.deptId || selectedDept?.id); const res = await request(payload); if (res?.success !== false) { message.success(currentId ? "编辑成功" : "添加成功"); closePositionModal(); fetchPositionData(pageIndex, pageSize); } else { message.error(res?.message || "操作失败"); } }; return (
setFilterKeyword(e.target.value)} /> { setSelectedDept(toSelectedDept(node)); }} />
{selectedDept?.id ? ( <>
当前部门: {selectedDept.deptName}
, ]} onFinish={() => fetchPositionData(1, 10)} style={{ marginBottom: 16 }} /> ( )} columns={[ { title: "名称", dataIndex: "positionName" }, { title: "职责", dataIndex: "dutyDesc" }, { title: "备注", dataIndex: "remark" }, { title: "操作", width: 160, render: (_, record) => ( ), }, ]} dataSource={dataSource} loading={loading} pagination={{ current: pageIndex, pageSize, total, showSizeChanger: true, showTotal: (t) => `共 ${t} 条`, }} scroll={{ y: props.scrollY }} onChange={(pag) => { setPageIndex(pag.current); setPageSize(pag.pageSize); fetchPositionData(pag.current, pag.pageSize); }} /> ) : ( )} {deptModalOpen && ( )} {positionModalOpen && (
)} ); } function resolveManagerAccount(dept, options) { if (dept?.managerAccount) { return dept.managerAccount; } if (dept?.managerName) { const matched = options.find((item) => item.staffName === dept.managerName); return matched?.value; } return undefined; } function DeptFormModal({ open, currentId, staffOptions, treeData, requestAdd, requestEdit, requestDetails, onCancel, onSuccess, selectedDeptId, }) { const [form] = Form.useForm(); const [submitting, setSubmitting] = useState(false); const [detailLoading, setDetailLoading] = useState(false); const staffOptionsRef = useRef(staffOptions); const treeDataRef = useRef(treeData); const requestDetailsRef = useRef(requestDetails); staffOptionsRef.current = staffOptions; treeDataRef.current = treeData; requestDetailsRef.current = requestDetails; useEffect(() => { if (!open) { return; } form.resetFields(); if (!currentId) { return; } let cancelled = false; setDetailLoading(true); const loadDetail = async () => { let dept = null; const getDetails = requestDetailsRef.current; if (typeof getDetails === "function") { try { const res = await getDetails({ id: currentId }); dept = res?.data || null; } catch { dept = null; } } if (!dept) { dept = findDeptNode(treeDataRef.current, currentId); } if (!cancelled && dept) { form.setFieldsValue({ ...dept, managerAccount: resolveManagerAccount(dept, staffOptionsRef.current), managerName: dept.managerName, }); } }; loadDetail().finally(() => { if (!cancelled) { setDetailLoading(false); } }); return () => { cancelled = true; }; }, [open, currentId]); const onManagerChange = (account) => { const staff = staffOptions.find((s) => s.value === account); form.setFieldValue("managerName", staff?.staffName || ""); }; const handleSubmit = async (values) => { try { setSubmitting(true); const request = currentId ? requestEdit : requestAdd; const payload = { ...values }; if (currentId) { payload.id = currentId; } const res = await request(payload); if (res?.success !== false) { message.success(currentId ? "编辑成功" : "添加成功"); form.resetFields(); onCancel(); await onSuccess(); } else { message.error(res?.message || "操作失败"); } } finally { setSubmitting(false); } }; return (
); } export default Connect( [NS_ORG_DEPARTMENT, NS_ORG_POSITION, NS_STAFF_INFO], true, )(AntdTableFuncControl(DepartmentPositionPage));