|
|
|
@ -112,13 +112,24 @@ function DepartmentsContainer() { |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function DepartmentRow({ dept }) { |
|
|
|
const [expanded, setExpanded] = useState(false); |
|
|
|
const { isOpen, openModal, closeModal } = useModal(); |
|
|
|
|
|
|
|
const toggleExpand = () => { |
|
|
|
setExpanded(!expanded); |
|
|
|
}; |
|
|
|
|
|
|
|
const handleEdit = () => { |
|
|
|
openModal(); |
|
|
|
}; |
|
|
|
|
|
|
|
const handleSuccess = () => { |
|
|
|
// 刷新部门数据 |
|
|
|
window.location.reload(); // 或者调用父组件的刷新方法 |
|
|
|
}; |
|
|
|
|
|
|
|
return ( |
|
|
|
<> |
|
|
|
<tr className="border-b border-white/10"> |
|
|
|
@ -155,10 +166,16 @@ function DepartmentRow({ dept }) { |
|
|
|
</td> |
|
|
|
<td className="px-6 py-4"> |
|
|
|
<div className="flex items-center gap-x-2"> |
|
|
|
<button className="text-theme-text-secondary hover:text-theme-text-primary"> |
|
|
|
<button |
|
|
|
onClick={handleEdit} |
|
|
|
className="text-theme-text-secondary hover:text-theme-text-primary" |
|
|
|
> |
|
|
|
<Pencil className="h-4 w-4" /> |
|
|
|
</button> |
|
|
|
<button className="text-theme-text-secondary hover:text-theme-text-primary"> |
|
|
|
<button |
|
|
|
onClick={() => handleDelete(dept.deptId)} |
|
|
|
className="text-theme-text-secondary hover:text-theme-text-primary" |
|
|
|
> |
|
|
|
<Trash className="h-4 w-4" /> |
|
|
|
</button> |
|
|
|
</div> |
|
|
|
@ -169,10 +186,16 @@ function DepartmentRow({ dept }) { |
|
|
|
dept.children.map((child) => ( |
|
|
|
<DepartmentRow key={child.deptId} dept={child} /> |
|
|
|
))} |
|
|
|
<ModalWrapper isOpen={isOpen}> |
|
|
|
<EditDepartmentModal |
|
|
|
dept={dept} |
|
|
|
closeModal={closeModal} |
|
|
|
onSuccess={handleSuccess} |
|
|
|
/> |
|
|
|
</ModalWrapper> |
|
|
|
</> |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
function NewDepartmentModal({ closeModal }) { |
|
|
|
const [formData, setFormData] = useState({ |
|
|
|
deptName: "", |
|
|
|
@ -275,6 +298,89 @@ function NewDepartmentModal({ closeModal }) { |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
function EditDepartmentModal({ dept, closeModal, onSuccess }) { |
|
|
|
const [formData, setFormData] = useState({ |
|
|
|
deptName: dept.deptName, |
|
|
|
parentId: dept.parentId, |
|
|
|
orderNum: dept.orderNum, |
|
|
|
status: dept.status, |
|
|
|
}); |
|
|
|
|
|
|
|
const [departments, setDepartments] = useState([]); |
|
|
|
const [treeData, setTreeData] = useState([]); |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
async function fetchDepartments() { |
|
|
|
const _departments = await Admin.depts(); |
|
|
|
setDepartments(_departments); |
|
|
|
setTreeData(buildTree(_departments)); |
|
|
|
} |
|
|
|
fetchDepartments(); |
|
|
|
}, []); |
|
|
|
|
|
|
|
const handleSubmit = async () => { |
|
|
|
await Admin.updateDept(dept.deptId,formData); // 调用更新 API |
|
|
|
onSuccess(); // 通知父组件刷新数据 |
|
|
|
closeModal(); |
|
|
|
}; |
|
|
|
|
|
|
|
function buildTree(depts, parentId = 0) { |
|
|
|
return depts |
|
|
|
.filter((dept) => dept.parentId === parentId) |
|
|
|
.map((dept) => ({ |
|
|
|
title: dept.deptName, // 确保 title 是部门名称 |
|
|
|
value: dept.deptId, // 部门 ID |
|
|
|
children: buildTree(depts, dept.deptId), // 递归处理子部门 |
|
|
|
})); |
|
|
|
} |
|
|
|
|
|
|
|
return ( |
|
|
|
<div className="p-6"> |
|
|
|
<h2 className="text-lg font-bold text-theme-text-primary mb-4"> |
|
|
|
编辑部门 |
|
|
|
</h2> |
|
|
|
<div className="flex flex-col gap-y-4"> |
|
|
|
<div> |
|
|
|
<label className="text-sm font-medium text-theme-text-secondary block mb-2"> |
|
|
|
上级部门 |
|
|
|
</label> |
|
|
|
<TreeSelect |
|
|
|
treeData={treeData} |
|
|
|
value={formData.parentId} |
|
|
|
onChange={(value) => setFormData({ ...formData, parentId: value })} |
|
|
|
placeholder="请选择上级部门" |
|
|
|
className="w-full" |
|
|
|
dropdownStyle={{ maxHeight: 400, overflow: "auto" }} |
|
|
|
/> |
|
|
|
</div> |
|
|
|
<input |
|
|
|
type="text" |
|
|
|
placeholder="部门名称" |
|
|
|
value={formData.deptName} |
|
|
|
onChange={(e) => setFormData({ ...formData, deptName: e.target.value })} |
|
|
|
className="border-none bg-theme-settings-input-bg text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5" |
|
|
|
/> |
|
|
|
<input |
|
|
|
type="number" |
|
|
|
placeholder="排序" |
|
|
|
value={formData.orderNum} |
|
|
|
onChange={(e) => setFormData({ ...formData, orderNum: Number(e.target.value) })} |
|
|
|
className="border-none bg-theme-settings-input-bg text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5" |
|
|
|
/> |
|
|
|
<select |
|
|
|
value={formData.status} |
|
|
|
onChange={(e) => setFormData({ ...formData, status: Number(e.target.value) })} |
|
|
|
className="border-none bg-theme-settings-input-bg text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5" |
|
|
|
> |
|
|
|
<option value={0}>启用</option> |
|
|
|
<option value={1}>停用</option> |
|
|
|
</select> |
|
|
|
<CTAButton onClick={handleSubmit}>保存</CTAButton> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
// 将部门列表转换为树状结构 |
|
|
|
function buildTree(departments, parentId = 0) { |
|
|
|
return departments |
|
|
|
|