From 9bac6333fbf029e6303e5c54d604113762ef010a Mon Sep 17 00:00:00 2001 From: pan <13329870472@163.com> Date: Mon, 18 Mar 2024 15:53:25 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E7=B3=BB=E7=BB=9F=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/en.yaml | 1 + locales/zh-CN.yaml | 3 +- mock/asyncRoutes.ts | 9 + src/api/system/dept.ts | 73 ++++++ src/api/system/job.ts | 64 +++++ src/api/system/menu.ts | 78 ++++++ src/api/system/role.ts | 90 +++++++ src/api/system/user.ts | 158 ++++++++++++ src/views/components/date-picker.vue | 53 ++++ src/views/login/index.vue | 2 +- src/views/system/dept/form.vue | 35 ++- src/views/system/dept/index.vue | 136 ++++++++--- src/views/system/dept/utils/hook.tsx | 186 +++++++++++--- src/views/system/dept/utils/types.ts | 7 +- src/views/system/hooks.ts | 4 +- src/views/system/job/form.vue | 80 ++++++ src/views/system/job/index.vue | 229 +++++++++++++++++ src/views/system/job/utils/hook.tsx | 271 ++++++++++++++++++++ src/views/system/job/utils/rule.ts | 8 + src/views/system/job/utils/types.ts | 19 ++ src/views/system/menu/README.md | 26 -- src/views/system/menu/form.vue | 326 ------------------------- src/views/system/menu/index.vue | 157 ------------ src/views/system/menu/utils/enums.ts | 94 ------- src/views/system/menu/utils/hook.tsx | 223 ----------------- src/views/system/menu/utils/rule.ts | 10 - src/views/system/menu/utils/types.ts | 29 --- src/views/system/role/form.vue | 102 ++++++-- src/views/system/role/index.vue | 303 ++++++++++++----------- src/views/system/role/tree.vue | 213 ++++++++++++++++ src/views/system/role/utils/hook.tsx | 212 ++++++++-------- src/views/system/role/utils/rule.ts | 16 +- src/views/system/role/utils/types.ts | 10 +- src/views/system/user/form/index.vue | 89 +++++-- src/views/system/user/form/role.vue | 16 +- src/views/system/user/index.vue | 58 +++-- src/views/system/user/info.vue | 241 ++++++++++++++++++ src/views/system/user/svg/expand.svg | 2 +- src/views/system/user/svg/unexpand.svg | 2 +- src/views/system/user/tree.vue | 4 +- src/views/system/user/upload.vue | 14 +- src/views/system/user/utils/hook.tsx | 218 +++++++++++------ src/views/system/user/utils/info.tsx | 321 ++++++++++++++++++++++++ src/views/system/user/utils/rule.ts | 72 +++++- src/views/system/user/utils/types.ts | 12 +- 45 files changed, 2871 insertions(+), 1405 deletions(-) create mode 100644 src/api/system/dept.ts create mode 100644 src/api/system/job.ts create mode 100644 src/api/system/menu.ts create mode 100644 src/api/system/role.ts create mode 100644 src/api/system/user.ts create mode 100644 src/views/components/date-picker.vue create mode 100644 src/views/system/job/form.vue create mode 100644 src/views/system/job/index.vue create mode 100644 src/views/system/job/utils/hook.tsx create mode 100644 src/views/system/job/utils/rule.ts create mode 100644 src/views/system/job/utils/types.ts delete mode 100644 src/views/system/menu/README.md delete mode 100644 src/views/system/menu/form.vue delete mode 100644 src/views/system/menu/index.vue delete mode 100644 src/views/system/menu/utils/enums.ts delete mode 100644 src/views/system/menu/utils/hook.tsx delete mode 100644 src/views/system/menu/utils/rule.ts delete mode 100644 src/views/system/menu/utils/types.ts create mode 100644 src/views/system/role/tree.vue create mode 100644 src/views/system/user/info.vue create mode 100644 src/views/system/user/utils/info.tsx diff --git a/locales/en.yaml b/locales/en.yaml index d5e9f1a..e640aa7 100644 --- a/locales/en.yaml +++ b/locales/en.yaml @@ -38,6 +38,7 @@ menus: hsRole: Role Manage hsSystemMenu: Menu Manage hsDept: Dept Manage + hsJob: Job Manage hssysMonitor: System Monitor hsOnlineUser: Online User hsLoginLog: Login Log diff --git a/locales/zh-CN.yaml b/locales/zh-CN.yaml index 858ac2a..3bc337b 100644 --- a/locales/zh-CN.yaml +++ b/locales/zh-CN.yaml @@ -35,9 +35,10 @@ menus: hsAbout: 关于 hssysManagement: 系统管理 hsUser: 用户管理 - hsRole: 角色管理 + hsRole: 权限管理 hsSystemMenu: 菜单管理 hsDept: 部门管理 + hsJob: 角色管理 hssysMonitor: 系统监控 hsOnlineUser: 在线用户 hsLoginLog: 登录日志 diff --git a/mock/asyncRoutes.ts b/mock/asyncRoutes.ts index a71e45e..2766612 100644 --- a/mock/asyncRoutes.ts +++ b/mock/asyncRoutes.ts @@ -51,6 +51,15 @@ const systemManagementRouter = { title: "menus.hsDept", roles: ["admin"] } + }, + { + path: "/system/job/index", + name: "SystemJob", + meta: { + icon: "ri:account-circle-fill", + title: "menus.hsDept", + roles: ["admin"] + } } ] }; diff --git a/src/api/system/dept.ts b/src/api/system/dept.ts new file mode 100644 index 0000000..7e60b4d --- /dev/null +++ b/src/api/system/dept.ts @@ -0,0 +1,73 @@ +import { http } from "@/utils/http"; +import { PageQuery, type ApiAbstract } from "@/utils/http/ApiAbstract"; +import { baseUrlApi } from "../utils"; + +export class Dept { + createBy: string; + createTime: Date; + deptSort: number; + enabled: boolean; + hasChildren: boolean; + id: number; + pid: number; + status: number; + label: string; + leaf: boolean; + name: string; + subCount: number; + updateBy: string; + updateTime: Date; + menus: any[]; +} +export class DeptQueryCriteria extends PageQuery { + name: string; + enabled: boolean; + pid: number; + pidIsNull: boolean; + createTime: Array; +} + +export const getDepts = (params: DeptQueryCriteria | any) => { + return http.request>("get", baseUrlApi("dept"), { + params + }); +}; +export const getDeptTree = (params?: DeptQueryCriteria | any) => { + return http.request>("get", baseUrlApi("dept/treeAll"), { + params + }); +}; + +export const getDeptSuperior = (ids: Number[]) => { + const data = ids.length || ids.length === 0 ? ids : Array.of(ids); + return http.request>("post", baseUrlApi("dept/superior"), { + data + }); +}; + +export const add = (data: Partial) => { + return http.request>("post", baseUrlApi("dept"), { + data + }); +}; + +export const del = (ids: number[] | any) => { + return http.request("delete", baseUrlApi("dept"), { + data: ids + }); +}; +export const edit = (data: Partial) => { + return http.request>("put", baseUrlApi("dept"), { + data + }); +}; +export const download = (data: Partial) => { + return http.request( + "get", + baseUrlApi("dept/download"), + { + data + }, + { responseType: "blob" } + ); +}; diff --git a/src/api/system/job.ts b/src/api/system/job.ts new file mode 100644 index 0000000..4df629e --- /dev/null +++ b/src/api/system/job.ts @@ -0,0 +1,64 @@ +import { http } from "@/utils/http"; +import { + type ApiAbstract, + type Page, + PageQuery, + VersionEntity +} from "@/utils/http/ApiAbstract"; +import { baseUrlApi } from "../utils"; + +export class Job extends VersionEntity { + id: number; + /** + * 岗位名称 + */ + name: string; + + /** + * 岗位排序 + */ + jobSort: number; + + /** + * 是否启用 + */ + enabled: boolean; +} +export class JobQueryCriteria extends PageQuery { + name: string; + enabled: boolean; + createTime: Date[]; +} + +export const get = (params?: number | any) => { + return http.request>>("get", baseUrlApi("job"), { + params + }); +}; + +export const add = (data: Partial) => { + return http.request("post", baseUrlApi("job"), { + data + }); +}; + +export const del = (ids: number[] | any) => { + return http.request("delete", baseUrlApi("job"), { + data: ids + }); +}; +export const edit = (data: Partial) => { + return http.request("put", baseUrlApi("job"), { + data + }); +}; +export const download = (data: Partial) => { + return http.request( + "get", + baseUrlApi("job/download"), + { + data + }, + { responseType: "blob" } + ); +}; diff --git a/src/api/system/menu.ts b/src/api/system/menu.ts new file mode 100644 index 0000000..6240e5f --- /dev/null +++ b/src/api/system/menu.ts @@ -0,0 +1,78 @@ +import { http } from "@/utils/http"; +import { PageQuery, type ApiAbstract } from "@/utils/http/ApiAbstract"; +import { baseUrlApi } from "../utils"; + +export class Menu { + id: number; + + children: Menu[]; + + type: number; + + permission: string; + + title: string; + + menuSort: number; + + path: string; + + component: string; + + pid: number; + + subCount: number; + + iframe: boolean; + + cache: boolean; + + hidden: boolean; + + componentName: string; + + icon: string; +} +export class MenuQueryCriteria extends PageQuery { + blurry: string; + pid: number; + createTime: Date[]; +} +export const menuTree = (ids: number[]) => { + return http.request>("post", baseUrlApi("menus/tree"), { + data: ids + }); +}; + +export const get = (params: number | any) => { + return http.request>("get", baseUrlApi("menus"), { + params + }); +}; + +export const add = (data: Partial) => { + return http.request("post", baseUrlApi("menus"), { + data + }); +}; + +export const del = (ids: number[] | any) => { + return http.request("delete", baseUrlApi("menus"), { + data: ids + }); +}; +export const edit = (data: Partial) => { + return http.request>("put", baseUrlApi("menus"), { + data + }); +}; +export const download = (data: Partial) => { + return http.request( + "get", + baseUrlApi("menus/download"), + { + data + }, + { responseType: "blob" } + ); +}; diff --git a/src/api/system/role.ts b/src/api/system/role.ts new file mode 100644 index 0000000..c276943 --- /dev/null +++ b/src/api/system/role.ts @@ -0,0 +1,90 @@ +import { http } from "@/utils/http"; +import { type ApiAbstract, PageQuery } from "@/utils/http/ApiAbstract"; +import { baseUrlApi } from "../utils"; +import type { Dept } from "./dept"; + +export class Role { + id: number; + /** + * 用户 + */ + users: any; + /** + * 菜单 + */ + menus: any; + /** + * 部门 + */ + depts: Dept[] | any[]; + /** + * 名称 + */ + name: string; + /** + * 数据权限,全部 、 本级 、 自定义 + */ + dataScope: string; + /** + * 级别,数值越小,级别越大 + */ + level: number; + /** + * 描述 + */ + description: string; +} +export class RoleQueryCriteria extends PageQuery { + blurry: string; + createTime: Date[]; +} +export const getAll = (data: Partial) => { + return http.request("get", baseUrlApi("roles/all"), { + data + }); +}; + +export const get = (params?: number | any) => { + return http.request>("get", baseUrlApi("roles"), { + params + }); +}; + +export const getLevel = () => { + return http.request("get", baseUrlApi("roles/level")); +}; + +export const editMenu = data => { + return http.request("put", baseUrlApi("roles/menu"), { data }); +}; +export const add = (data: Partial) => { + return http.request("post", baseUrlApi("roles"), { + data + }); +}; + +export const del = (ids: number[] | any) => { + return http.request("delete", baseUrlApi("roles"), { + data: ids + }); +}; +export const edit = (data: Partial) => { + return http.request>("put", baseUrlApi("roles"), { + data + }); +}; +export const menus = (data: Partial) => { + return http.request("put", baseUrlApi("roles/menu"), { + data + }); +}; +export const download = (data: Partial) => { + return http.request( + "get", + baseUrlApi("roles/download"), + { + data + }, + { responseType: "blob" } + ); +}; diff --git a/src/api/system/user.ts b/src/api/system/user.ts new file mode 100644 index 0000000..3aa4838 --- /dev/null +++ b/src/api/system/user.ts @@ -0,0 +1,158 @@ +import { http } from "@/utils/http"; +import { + type ApiAbstract, + PageQuery, + VersionEntity +} from "@/utils/http/ApiAbstract"; +import { baseUrlApi } from "../utils"; +import type { Role } from "./role"; +import type { Job } from "./job"; +import type { Dept } from "./dept"; +import { encrypt } from "@/utils/rsaEncrypt"; + +export class User extends VersionEntity { + id: number; + /** + * 用户角色 + */ + roles: Role[]; + /** + * 用户岗位 + */ + jobs: Job[]; + /** + * 用户部门 + */ + dept: Dept; + /** + * 用户名称 + */ + username: string; + /** + * 用户昵称 + */ + nickName: string; + /** + * 邮箱 + */ + email: string; + /** + * 电话号码 + */ + phone: string; + /** + * 用户性别 + */ + gender: string; + /** + * 头像真实名称 + */ + avatarName: string; + /** + * 头像存储的路径 + */ + avatarPath: string; + /** + * 密码 + */ + password: string; + /** + * 是否启用 + */ + enabled: string; + /** + * 是否为admin账号 + */ + isAdmin: boolean; + /** + * 最后修改密码的时间 + */ + pwdResetTime: Date; +} +export class UserQueryCriteria extends PageQuery { + name: string; + deptId: number; + deptIds: number[]; + enabled: boolean; + createTime: Date[]; +} + +export const get = (params: number | any) => { + return http.request>("get", baseUrlApi("users"), { + params + }); +}; + +export const add = (data: Partial) => { + return http.request("post", baseUrlApi("users"), { + data + }); +}; + +export const del = (ids: number[] | any) => { + return http.request("delete", baseUrlApi("users"), { + data: ids + }); +}; +export const edit = (data: Partial) => { + return http.request("put", baseUrlApi("users"), { + data + }); +}; +export const download = (data: Partial) => { + return http.request( + "get", + baseUrlApi("users/download"), + { + data + }, + { responseType: "blob" } + ); +}; + +export const updateAvatarByid = ({ id, avatar }) => { + const formData = new FormData(); + formData.append("avatar", avatar, "avatar.jpg"); + return http.request("post", baseUrlApi("/users/updateAvatar/" + id), { + data: formData, + // 请求超时时间 + timeout: 60000, + headers: { + "Content-Type": "multipart/form-data", + filename: "avatar.png" + } + }); +}; + +export function updatePass({ oldPass, newPass }) { + const data = { + oldPass: encrypt(oldPass), + newPass: encrypt(newPass) + }; + return http.request("post", baseUrlApi("users/updatePass"), { + data + }); +} + +export function resetEmail(data) { + return http.request("post", baseUrlApi("/code/resetEmail?email=" + data)); +} + +export function updateEmail(form) { + const data = { + password: encrypt(form.pass), + email: form.email + }; + return http.request("post", baseUrlApi("users/updateEmail/" + form.code), { + data + }); +} +export function editUser(data) { + return http.request("put", baseUrlApi("users/center"), { + data + }); +} + +export function getLog() { + return http.request("get", baseUrlApi("logs/user")); +} diff --git a/src/views/components/date-picker.vue b/src/views/components/date-picker.vue new file mode 100644 index 0000000..89355d3 --- /dev/null +++ b/src/views/components/date-picker.vue @@ -0,0 +1,53 @@ + + + diff --git a/src/views/login/index.vue b/src/views/login/index.vue index 58b9a72..e805242 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -58,7 +58,7 @@ const { locale, translationCh, translationEn } = useTranslationLang(); const ruleForm = reactive({ username: "admin", - password: "admin123", + password: "123456", verifyCode: "" }); diff --git a/src/views/system/dept/form.vue b/src/views/system/dept/form.vue index 2cec5fc..e3edfc3 100644 --- a/src/views/system/dept/form.vue +++ b/src/views/system/dept/form.vue @@ -1,5 +1,5 @@ @@ -41,22 +47,16 @@ defineExpose({ getRef }); @@ -103,8 +103,7 @@ defineExpose({ getRef }); { + multipleSelection.value = val; + if (val != null && val.length > 0) { + value2.value = false; + } else { + value2.value = true; + } +}; + +async function deleteAll() { + ElMessageBox.confirm( + `确认要删除所选的${multipleSelection.value.length}个部门吗?`, + "系统提示", + { + confirmButtonText: "确定", + cancelButtonText: "取消", + type: "warning", + dangerouslyUseHTMLString: true, + draggable: true + } + ) + .then(() => { + Dept.del(multipleSelection.value.map(dept => dept.id)); + message("已删除所选的部门", { + type: "success" + }); + onSearch(); + }) + .catch(() => { + onSearch(); + }); +} +const load = ( + row: Partial, + treeNode: unknown, + resolve: (date: Partial[]) => void +) => { + let queryDept = { pid: row?.id }; + if (!row?.id) { + queryDept = null; + } + Dept.getDepts(queryDept).then(contentData => { + // 调用' resolve '回调以返回子节点数据并指示加载完成。 + resolve(contentData.data.content); + }); +}; +const exportClick = async () => { + const response: Blob = await Dept.download(null); + const a = document.createElement("a"); + const url = window.URL.createObjectURL(response); // 创建媒体流 url ,详细了解可自己查 URL.createObjectURL(推荐 MDN ) + + a.href = url; + a.style.display = "none"; + document.body.appendChild(a); + a.click(); + a.parentNode.removeChild(a); + window.URL.revokeObjectURL(url); // 删除创建的媒体流 url 对象 + message("导出成功", { + type: "success" + }); +}; const formRef = ref(); const tableRef = ref(); +const value2 = ref(true); const { form, loading, columns, dataList, + multipleSelection, onSearch, resetForm, openDialog, - handleDelete, - handleSelectionChange + handleDelete } = useDept(); @@ -41,24 +107,27 @@ const { v-model="form.name" placeholder="请输入部门名称" clearable - class="!w-[180px]" + class="!w-[200px]" /> - - + + + + + @@ -71,12 +140,12 @@ const { -