From 04e6c52ec39eb580a13c51d7b533210688ff31a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9A=93=E6=9C=88=E5=BD=92=E5=B0=98?= Date: Tue, 11 Feb 2025 17:38:05 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/en.yaml | 5 + locales/zh-CN.yaml | 5 + src/api/system.ts | 96 +++++- src/views/system/role/components/form.vue | 141 ++++++++ src/views/system/role/index.vue | 340 ++++++++++++++++++ src/views/system/role/utils/hook.tsx | 402 ++++++++++++++++++++++ types/system.d.ts | 52 +++ 7 files changed, 1038 insertions(+), 3 deletions(-) create mode 100644 src/views/system/role/components/form.vue create mode 100644 src/views/system/role/index.vue create mode 100644 src/views/system/role/utils/hook.tsx diff --git a/locales/en.yaml b/locales/en.yaml index c1856d8..1cc1599 100644 --- a/locales/en.yaml +++ b/locales/en.yaml @@ -25,6 +25,11 @@ buttons:Add: Add buttons:Update: Update buttons:Delete: Delete buttons:Export: Export +buttons:Save: Save +buttons:Permission: Permission +buttons:ExpandOrCollapse: Expand Or Collapse +buttons:CheckAllOrCheckOutAll: Check All Or Check Out All +buttons:Linked: Linked search:Total: Total search:History: History search:Collect: Collect diff --git a/locales/zh-CN.yaml b/locales/zh-CN.yaml index c4e28b8..9c44537 100644 --- a/locales/zh-CN.yaml +++ b/locales/zh-CN.yaml @@ -25,6 +25,11 @@ buttons:Add: 添加 buttons:Update: 修改 buttons:Delete: 删除 buttons:Export: 导出 +buttons:Save: 保存 +buttons:Permission: 权限 +buttons:ExpandOrCollapse: 展开或折叠 +buttons:CheckAllOrCheckOutAll: 全选或者全不选 +buttons:Linked: 联动 search:Total: 共 search:History: 搜索历史 search:Collect: 收藏 diff --git a/src/api/system.ts b/src/api/system.ts index 0574fe9..1d6a412 100644 --- a/src/api/system.ts +++ b/src/api/system.ts @@ -1,5 +1,10 @@ import { http } from "@/utils/http"; -import type { DepartmentInfo, PermissionInfo } from "types/system"; +import type { + DepartmentInfo, + PermissionInfo, + RoleInfo, + RolePermissionInfo +} from "types/system"; import { filterEmptyObject } from "./utils"; // ---------------------------部门相关------------------------------------- @@ -31,7 +36,7 @@ type GetDepartmentListParams = { }; /**获取部门列表 */ export const getDepartmentListAPI = (params: GetDepartmentListParams) => { - return http.request>( + return http.request>( "get", `/api/department/list`, { @@ -135,7 +140,7 @@ type GetPermissionListParams = { /**获取权限列表 */ export const getPermissionListAPI = (params: GetPermissionListParams) => { - return http.request>( + return http.request>( "get", `/api/permission/list`, { @@ -224,3 +229,88 @@ export const putUpdatePermissionAPI = ( data }); }; + +/** + * 获取角色权限列表 + * @param id 角色ID + * @returns + */ +export const getRolePermissionsAPI = (id: string) => { + return http.request>( + "get", + `/api/role/permissionList/${id}` + ); +}; + +/** + * 更新角色权限信息 + * @param id 角色ID + * @param data 角色权限列表 + * @returns + */ +export const putUpdateRolePermissionsAPI = ( + id: string, + data: { + permission_ids: string[]; + } +) => { + return http.request("put", `/api/role/updatePermission/${id}`, { + data + }); +}; + +// -----------------------------角色相关----------------------------------- + +type GetRoleListParams = { + /**当前页 */ + page: number; + /**每页数量 */ + pageSize: number; + /**角色名称 */ + name?: string; + /**角色标识符 */ + code?: string; + /**角色描述 */ + description?: string; + /**所属部门ID */ + department_id?: string; +}; + +/**获取角色列表 */ +export const getRoleListAPI = (params: GetRoleListParams) => { + return http.request>("get", `/api/role/list`, { + params: filterEmptyObject(params) + }); +}; + +/**添加角色参数 */ +type AddRoleParams = { + /**角色姓名 */ + name: string; + /**角色标识 */ + code: string; + /**角色描述 */ + description: string; + /**所属部门ID */ + department_id: string; + /**状态 */ + status: number | string; +}; + +/**更新角色数据 */ +export const putUpdateRoleAPI = (data: AddRoleParams, id: string) => { + return http.request("post", `/api/role/update/${id}`, { + data + }); +}; + +/**添加角色数据 */ +export const postAddRoleAPI = (data: AddRoleParams) => { + return http.request("post", `/api/role/add`, { + data + }); +}; +/**删除角色 */ +export const deleteRoleAPI = (id: string) => { + return http.request("post", `/api/role/delete/${id}`); +}; diff --git a/src/views/system/role/components/form.vue b/src/views/system/role/components/form.vue new file mode 100644 index 0000000..d0533f2 --- /dev/null +++ b/src/views/system/role/components/form.vue @@ -0,0 +1,141 @@ + + + diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue new file mode 100644 index 0000000..0ab6b96 --- /dev/null +++ b/src/views/system/role/index.vue @@ -0,0 +1,340 @@ + + + + + diff --git a/src/views/system/role/utils/hook.tsx b/src/views/system/role/utils/hook.tsx new file mode 100644 index 0000000..ad002da --- /dev/null +++ b/src/views/system/role/utils/hook.tsx @@ -0,0 +1,402 @@ +import dayjs from "dayjs"; +import editForm from "../components/form.vue"; +import { message } from "@/utils/message"; + +import { + deleteRoleAPI, + getPermissionListAPI, + getRoleListAPI, + postAddRoleAPI, + putUpdateRoleAPI, + getRolePermissionsAPI, + putUpdateRolePermissionsAPI, + getDepartmentListAPI +} from "@/api/system"; + +import { handleTree } from "@/utils/tree"; +import { usePublicHooks } from "../../hooks"; +import { getKeyList } from "@pureadmin/utils"; +import { transformI18n } from "@/plugins/i18n"; +import { addDialog } from "@/components/ReDialog"; +import type { PaginationProps } from "@pureadmin/table"; +import { type Ref, reactive, ref, onMounted, h, watch, toRaw } from "vue"; +import type { + DepartmentInfo, + RoleInfo, + RolePermissionInfo +} from "types/system"; + +export const useRole = (treeRef: Ref) => { + /**查询表单 */ + const form = reactive({ + name: "", + code: "", + status: "", + department_id: "", + description: "" + }); + /** + * 表单Ref + */ + const formRef = ref(); + /** + * 数据列表 + */ + const dataList = ref([]); + /** + * 加载状态 + */ + const loading = ref(true); + /** + * 标签样式 + */ + const { tagStyle } = usePublicHooks(); + /**树形列表id列表 */ + const treeIds = ref([]); + /** + * 树形列表 + */ + const treeProps = { + value: "id", + label: "title", + children: "children" + }; + /** + * 分页参数 + */ + const pagination = reactive({ + total: 0, + pageSize: 10, + currentPage: 1, + background: true + }); + const curRow = ref(); + /** + * 树形列表数据 + */ + const treeData = ref([]); + /**是否显示 */ + const isShow = ref(false); + /**是否关联 */ + const isLinkage = ref(false); + /**查询值 */ + const treeSearchValue = ref(""); + /**是否展开 */ + const isExpandAll = ref(false); + /**是否全选 */ + const isSelectAll = ref(false); + const columns: TableColumnList = [ + { + label: "角色名称", + prop: "name", + minWidth: 120 + }, + { + label: "角色标识", + prop: "code", + minWidth: 150 + }, + { + label: "状态", + minWidth: 130, + cellRenderer: ({ row, props }) => ( + + {row.status === 1 ? "启用" : "停用"} + + ) + }, + { + label: "角色描述", + prop: "description", + minWidth: 150 + }, + { + label: "所属部门", + prop: "department_name", + minWidth: 150 + }, + { + label: "创建时间", + minWidth: 180, + prop: "create_time", + formatter: ({ create_time }) => + dayjs(create_time).format("YYYY-MM-DD HH:mm:ss") + }, + { + label: "更新时间", + minWidth: 180, + prop: "update_time", + formatter: ({ update_time }) => + dayjs(update_time).format("YYYY-MM-DD HH:mm:ss") + }, + { + label: "操作", + fixed: "right", + width: 300, + slot: "operation" + } + ]; + /** + * 初次查询 + */ + const onSearch = async () => { + loading.value = true; + const data = await getRoleListAPI({ + page: pagination.currentPage, + pageSize: pagination.pageSize, + ...toRaw(form) + }); + dataList.value = data.data.result; + pagination.total = data.data.total; + pagination.currentPage = data.data.page; + + setTimeout(() => { + loading.value = false; + }, 500); + }; + const resetForm = formEl => { + if (!formEl) return; + formEl.resetFields(); + onSearch(); + }; + /**处理页码变化 */ + const handleSizeChange = async (val: number) => { + const res = await getRoleListAPI({ + page: pagination.currentPage, + pageSize: val + }); + if (res.code === 200) { + const data = res.data; + dataList.value = data.result; + pagination.total = data.total; + pagination.currentPage = data.page; + } + }; + /**处理每页数量变化 */ + const handleCurrentChange = async (val: number) => { + const res = await getRoleListAPI({ + page: val, + pageSize: pagination.pageSize + }); + if (res.code === 200) { + const data = res.data; + dataList.value = data.result; + pagination.total = data.total; + pagination.currentPage = data.page; + } + }; + + const handleDelete = async (row: RoleInfo) => { + const res = await deleteRoleAPI(row.id); + if (res.code === 200) { + message(`您删除了角色名称为${row.name}的这条数据`, { type: "success" }); + onSearch(); + } else { + message(`删除失败!`, { type: "error" }); + } + }; + const openDialog = (title = "新增", row?: RoleInfo) => { + addDialog({ + title: `${title}角色`, + props: { + formInline: { + id: row?.id ?? "", + name: row?.name ?? "", + code: row?.code ?? "", + description: row?.description ?? "", + status: row?.status ?? 1, + department_id: row?.department_id ?? "" + } + }, + width: "40%", + draggable: true, + fullscreenIcon: true, + closeOnClickModal: false, + contentRenderer: () => + h(editForm, { + ref: formRef, + formInline: { + id: row?.id ?? "", + name: row?.name ?? "", + code: row?.code ?? "", + description: row?.description ?? "", + status: row?.status ?? 1, + department_id: row?.department_id ?? "" + } + }), + beforeSure: (done, { options }) => { + const FormRef = formRef.value.getRef(); + let curData = options.props.formInline as RoleInfo; + function chores() { + message(`您${title}了角色名称为${curData.name}的这条数据`, { + type: "success" + }); + done(); // 关闭弹框 + onSearch(); // 刷新表格数据 + } + FormRef.validate(async (valid: any) => { + if (valid) { + console.log("curData", curData); + // 表单规则校验通过 + if (title === "新增") { + // 实际开发先调用新增接口,再进行下面操作 + const res = await postAddRoleAPI(curData); + if (res.code === 200) { + chores(); + } else { + message(`添加失败!`, { + type: "error" + }); + done(); + } + } else { + // 实际开发先调用修改接口,再进行下面操作 + const res = await putUpdateRoleAPI(curData, row.id); + if (res.code === 200) { + chores(); + } else { + message(`修改失败!`, { + type: "error" + }); + done(); + } + } + } + }); + } + }); + }; + + /** + * 角色权限 + */ + const handleMenu = async (row?: RolePermissionInfo) => { + const { id } = row; + if (id) { + curRow.value = row; + isShow.value = true; + const res = await getRolePermissionsAPI(id); + if (res.success) { + treeRef.value.setCheckedKeys( + getKeyList(res.data.result, "permission_id") + ); + isExpandAll.value = true; + } else { + treeRef.value.setCheckedKeys([]); + isExpandAll.value = true; + } + } else { + curRow.value = null; + isShow.value = false; + isExpandAll.value = false; + } + }; + + /** 高亮当前权限选中行 */ + const rowStyle = ({ row: { id } }) => { + return { + cursor: "pointer", + background: id === curRow.value?.id ? "var(--el-fill-color-light)" : "" + }; + }; + /**保存角色权限 */ + const handleSave = async () => { + const { id, name } = curRow.value; + // 根据用户 id 调用实际项目中菜单权限修改接口 + let permissions = treeRef.value.getCheckedKeys(); + let halfCheckedKeys = treeRef.value.getHalfCheckedKeys(); + permissions = [...new Set(permissions.concat(halfCheckedKeys))]; + const res = await putUpdateRolePermissionsAPI(id, { + permission_ids: permissions + }); + if (res.code === 200) { + message(`角色名称为${name}的权限修改成功~`, { + type: "success" + }); + } else { + message(`角色名称为${name}的权限修改失败!`, { + type: "error" + }); + } + }; + /**查询权限变化 */ + const onQueryChanged = (query: string) => { + treeRef.value!.filter(query); + }; + + /**过滤方法 */ + const filterMethod = (query: string, node) => { + return transformI18n(node.title)!.includes(query); + }; + /**部门列表 */ + const departments = ref([]); + /**获取部门列表 */ + const getDepartments = async () => { + const res = await getDepartmentListAPI({ page: 1, pageSize: 9999 }); + if (res.code === 200) { + departments.value = formatHigherOptions(res.data.result); + } else { + departments.value = []; + } + }; + const formatHigherOptions = treeList => { + // 根据返回数据的status字段值判断追加是否禁用disabled字段,返回处理后的树结构,用于上级部门级联选择器的展示 + if (!treeList || !treeList.length) return; + const newTreeList = []; + for (let i = 0; i < treeList.length; i++) { + treeList[i].disabled = treeList[i].status === 0 ? true : false; + formatHigherOptions(treeList[i].children); + newTreeList.push(treeList[i]); + } + return newTreeList; + }; + + onMounted(async () => { + onSearch(); + const res = await getPermissionListAPI({ page: 1, pageSize: 99999 }); + const data = res.data.result; + treeIds.value = getKeyList(data, "id"); + treeData.value = handleTree(data, "id", "parent_id"); + await getDepartments(); + }); + watch(isExpandAll, val => { + val + ? treeRef.value.setExpandedKeys(treeIds.value) + : treeRef.value.setExpandedKeys([]); + }); + + watch(isSelectAll, val => { + val + ? treeRef.value.setCheckedKeys(treeIds.value) + : treeRef.value.setCheckedKeys([]); + }); + + return { + form, + isShow, + curRow, + loading, + columns, + dataList, + treeData, + treeProps, + isLinkage, + pagination, + isExpandAll, + isSelectAll, + treeSearchValue, + departments, + rowStyle, + onSearch, + resetForm, + openDialog, + handleMenu, + handleSave, + handleDelete, + filterMethod, + transformI18n, + onQueryChanged, + handleSizeChange, + handleCurrentChange + }; +}; diff --git a/types/system.d.ts b/types/system.d.ts index 76fec6e..34c6dc7 100644 --- a/types/system.d.ts +++ b/types/system.d.ts @@ -119,3 +119,55 @@ export type PermissionInfo = { /** 是否显示父菜单 */ show_parent: boolean; }; + +/**角色信息类型 */ +export type RoleInfo = { + /**角色ID */ + id: string; + /**状态 */ + status: number; + /**创建时间 */ + create_time: string; + /**修改时间 */ + update_time: string; + /**部门名称 */ + name: string; + /**角色标识符 */ + code: string; + /**角色描述 */ + description: string; + /**角色部门ID */ + department_id: string; +}; + +/** 角色权限关联信息类型 */ +export type RolePermissionInfo = { + /** 主键ID */ + id: string; + /** 创建人 */ + create_by: string; + /** 创建时间 */ + create_time: string; + /** 更新人 */ + update_by: string; + /** 更新时间 */ + update_time: string; + /** 角色ID */ + role_id: string; + /** 角色名称 */ + role_name: string; + /** 角色编码 */ + role_code: string; + /** 权限ID */ + permission_id: string; + /** + * 权限父ID + */ + permission_parent_id: string; + /** 权限名称 */ + permission_name: string; + /** 权限编码 */ + permission_code: string; + /** 权限类型 */ + permission_type: string; +};