feat: 给用户管理添加按钮级权限管理
This commit is contained in:
@@ -22,6 +22,8 @@ buttons:OpenText: Open
|
||||
buttons:CloseText: Close
|
||||
buttons:Search: Search
|
||||
buttons:Reset: Reset
|
||||
buttons:Details: Details
|
||||
buttons:DataList: DataList
|
||||
buttons:Add: Add
|
||||
buttons:Update: Update
|
||||
buttons:Delete: Delete
|
||||
@@ -46,7 +48,6 @@ buttons:ResetPassword: Reset Password
|
||||
buttons:RoleAllocation: Role Allocation
|
||||
buttons:PermissionDetails: Permission Details
|
||||
buttons:ForceToExit: Force Exit
|
||||
buttons:Details: Details
|
||||
search:Total: Total
|
||||
search:History: History
|
||||
search:Collect: Collect
|
||||
@@ -169,3 +170,11 @@ logout:message: Whether to exit the system?
|
||||
logout:success: Logout Success
|
||||
logout:fail: Logout Fail
|
||||
logout:cancel: Logout Cancel
|
||||
user:buttons:addRole: Add User Role
|
||||
user:buttons:deleteRole: Delete User Role
|
||||
user:buttons:updateRole: Update User Role
|
||||
user:buttons:roleInfo: User Role Info
|
||||
user:buttons:roleDataList: User Role Data List
|
||||
user:buttons:permisssionList: User Permisssion List
|
||||
user:buttons:uploadAvatar: Upload Avatar
|
||||
user:buttons:resetPassword: Reset Password
|
||||
|
||||
@@ -22,6 +22,8 @@ buttons:OpenText: 开
|
||||
buttons:CloseText: 关
|
||||
buttons:Search: 搜索
|
||||
buttons:Reset: 重置
|
||||
buttons:Details: 详情
|
||||
buttons:DataList: 数据列表
|
||||
buttons:Add: 添加
|
||||
buttons:Update: 修改
|
||||
buttons:Delete: 删除
|
||||
@@ -46,7 +48,6 @@ buttons:ResetPassword: 重置密码
|
||||
buttons:RoleAllocation: 角色分配
|
||||
buttons:PermissionDetails: 权限详情
|
||||
buttons:ForceToExit: 强制退出
|
||||
buttons:Details: 详情
|
||||
search:Total: 共
|
||||
search:History: 搜索历史
|
||||
search:Collect: 收藏
|
||||
@@ -169,3 +170,11 @@ logout:message: 是否退出当前系统?
|
||||
logout:success: 退出成功
|
||||
logout:fail: 退出失败
|
||||
logout:cancel: 退出取消
|
||||
user:buttons:addRole: 添加用户角色
|
||||
user:buttons:deleteRole: 删除用户角色
|
||||
user:buttons:updateRole: 更新用户角色
|
||||
user:buttons:roleInfo: 用户角色详情
|
||||
user:buttons:roleDataList: 用户角色列表
|
||||
user:buttons:permisssionList: 用户权限列表
|
||||
user:buttons:uploadAvatar: 上传头像
|
||||
user:buttons:resetPassword: 重置密码
|
||||
|
||||
@@ -429,7 +429,7 @@ export const deleteUserAPI = (id: string) => {
|
||||
* @param data 用户ID列表
|
||||
* @returns
|
||||
*/
|
||||
export const deleteUserListAPI = (data: { userIds: string[] }) => {
|
||||
export const deleteUserListAPI = (data: { ids: string[] }) => {
|
||||
return http.request<null>("post", `/api/user/deleteUserList`, { data });
|
||||
};
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ export const useUserStore = defineStore({
|
||||
return new Promise<ResponseResult<LoginResult>>((resolve, reject) => {
|
||||
getLogin(data)
|
||||
.then(data => {
|
||||
if (data.code === 200) {
|
||||
if (data.success) {
|
||||
setToken(data.data);
|
||||
}
|
||||
resolve(data);
|
||||
@@ -189,7 +189,7 @@ export const useUserStore = defineStore({
|
||||
return new Promise<ResponseResult<LoginResult>>((resolve, reject) => {
|
||||
refreshTokenApi(data)
|
||||
.then(data => {
|
||||
if (data.code === 200) {
|
||||
if (data.success) {
|
||||
setToken(data.data);
|
||||
}
|
||||
resolve(data);
|
||||
|
||||
@@ -109,3 +109,8 @@ export function getTokenInfo(): {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**判断是否有权限 */
|
||||
export const hasAuth = (auth: string) => {
|
||||
return useUserStoreHook().permissions.includes(auth);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { message } from "@/utils/message";
|
||||
import Avatar from "@/assets/user.png";
|
||||
import type { FormInstance } from "element-plus";
|
||||
import ReCropperPreview from "@/components/ReCropperPreview";
|
||||
import { deviceDetection } from "@pureadmin/utils";
|
||||
@@ -47,7 +48,7 @@ const handleSubmitImage = async () => {
|
||||
const res = await postUploadAvatarAPI(userInfo.id, {
|
||||
file: cropperBlob.value
|
||||
});
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
message("更新头像成功", { type: "success" });
|
||||
userInfo.avatar = `/file/${res.data.id}`;
|
||||
const user = storageLocal().getItem<object>(userInfoKey);
|
||||
@@ -71,7 +72,7 @@ const onSubmit = async (formEl: FormInstance) => {
|
||||
gender: userInfo.gender
|
||||
};
|
||||
const res = await putUpdateBaseUserInfoAPI(updateForm);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
message(res.msg, { type: "success" });
|
||||
await getUserInfo();
|
||||
} else {
|
||||
@@ -94,7 +95,10 @@ const onSubmit = async (formEl: FormInstance) => {
|
||||
<h3 class="my-8">个人信息</h3>
|
||||
<el-form ref="userInfoFormRef" label-position="top" :model="userInfo">
|
||||
<el-form-item label="头像">
|
||||
<el-avatar :size="80" :src="`/api/${userInfo.avatar}`" />
|
||||
<el-avatar
|
||||
:size="80"
|
||||
:src="userInfo.avatar ? `/api/${userInfo.avatar}` : Avatar"
|
||||
/>
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
accept="image/*"
|
||||
|
||||
@@ -2,7 +2,6 @@ import { message } from "@/utils/message";
|
||||
import { addDialog } from "@/components/ReDialog";
|
||||
import { reactive, ref, onMounted, watch } from "vue";
|
||||
import { ElForm, ElFormItem, ElInput, ElProgress } from "element-plus";
|
||||
import type { UserInfo } from "types/user";
|
||||
import { getUserInfoAPI } from "@/api/login";
|
||||
import {
|
||||
putUpdateEmailAPI,
|
||||
@@ -12,6 +11,7 @@ import {
|
||||
import { isAllEmpty, isEmail, isPhone, storageLocal } from "@pureadmin/utils";
|
||||
import { zxcvbn } from "@zxcvbn-ts/core";
|
||||
import { setUserInfo, userInfoKey } from "@/utils/auth";
|
||||
import type { UserInfo } from "types/system";
|
||||
|
||||
export const useUserInfo = () => {
|
||||
/** 密码正则(密码格式应为8-18位数字、字母、符号的任意两种组合) */
|
||||
@@ -52,10 +52,9 @@ export const useUserInfo = () => {
|
||||
nickname: "",
|
||||
phone: "",
|
||||
status: 0,
|
||||
department_id: "",
|
||||
create_time: "",
|
||||
update_time: "",
|
||||
roles: [],
|
||||
permissions: []
|
||||
update_time: ""
|
||||
});
|
||||
/**获取个人信息 */
|
||||
const getUserInfo = async () => {
|
||||
@@ -200,7 +199,7 @@ export const useUserInfo = () => {
|
||||
if (valid) {
|
||||
// 表单规则校验通过
|
||||
const res = await putUpdatePasswordAPI(passwordForm);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
done();
|
||||
message(res.msg, {
|
||||
type: "success"
|
||||
@@ -262,7 +261,7 @@ export const useUserInfo = () => {
|
||||
if (valid) {
|
||||
// 表单规则校验通过
|
||||
const res = await putUpdatePhoneAPI(phoneForm);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
done();
|
||||
message(res.msg, {
|
||||
type: "success"
|
||||
@@ -323,7 +322,7 @@ export const useUserInfo = () => {
|
||||
if (valid) {
|
||||
// 表单规则校验通过
|
||||
const res = await putUpdateEmailAPI(emailForm);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
done();
|
||||
message(res.msg, {
|
||||
type: "success"
|
||||
|
||||
@@ -91,7 +91,7 @@ const onUpdate = async (formEl: FormInstance | undefined) => {
|
||||
code: ruleForm.code,
|
||||
department_id: ruleForm.department_id
|
||||
});
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
message(transformI18n($t("login:RegisterSuccess")), {
|
||||
type: "success"
|
||||
});
|
||||
@@ -127,7 +127,7 @@ const start = async (
|
||||
title: "Register",
|
||||
mail: ruleForm.email
|
||||
});
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
clearInterval(timer.value);
|
||||
isDisabled.value = true;
|
||||
text.value = `${time}`;
|
||||
|
||||
@@ -84,7 +84,7 @@ const start = async (
|
||||
title: "Reset",
|
||||
mail: ruleForm.email
|
||||
});
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
clearInterval(timer.value);
|
||||
isDisabled.value = true;
|
||||
text.value = `${time}`;
|
||||
|
||||
@@ -202,7 +202,7 @@ export const useConfig = (tableRef: Ref) => {
|
||||
const res = await deleteConfigListAPI({
|
||||
ids: getKeyList(curSelected, "id")
|
||||
});
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
message(`已删除项目名称为 ${getKeyList(curSelected, "name")} 的数据`, {
|
||||
type: "success"
|
||||
});
|
||||
|
||||
@@ -219,7 +219,7 @@ export const useDepartment = () => {
|
||||
*/
|
||||
const handleDelete = async (row: DepartmentInfo) => {
|
||||
const res = await deleteDepartmentAPI(row.id);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
message(`您删除了部门:${row.name}及其附属部门`, { type: "success" });
|
||||
onSearch();
|
||||
} else {
|
||||
|
||||
@@ -166,7 +166,7 @@ export const useI18n = (tableRef: Ref) => {
|
||||
locale_id: form.locale_id,
|
||||
translation: form.translation
|
||||
});
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
dataList.value = res.data.result;
|
||||
pagination.total = res.data.total;
|
||||
pagination.currentPage = res.data.page;
|
||||
|
||||
@@ -156,7 +156,7 @@ export const useLocale = (tableRef: Ref) => {
|
||||
name: form.name,
|
||||
code: form.code
|
||||
});
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
dataList.value = res.data.result;
|
||||
pagination.total = res.data.total;
|
||||
pagination.currentPage = res.data.page;
|
||||
|
||||
@@ -267,7 +267,7 @@ export const usePermission = () => {
|
||||
}
|
||||
}
|
||||
const res = await postAddPermissionAPI(addForm);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
// 实际开发先调用新增接口,再进行下面操作
|
||||
chores();
|
||||
} else {
|
||||
@@ -305,7 +305,7 @@ export const usePermission = () => {
|
||||
}
|
||||
}
|
||||
const res = await putUpdatePermissionAPI(curData.id, updateForm);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
chores();
|
||||
} else {
|
||||
message(`更新失败!`, { type: "error" });
|
||||
@@ -318,7 +318,7 @@ export const usePermission = () => {
|
||||
};
|
||||
const handleDelete = async (row: PermissionInfo) => {
|
||||
const res = await deletePermissionAPI(row.id);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
message(`您删除了权限名称为${transformI18n(row.title)}的这条数据`, {
|
||||
type: "success"
|
||||
});
|
||||
|
||||
@@ -52,7 +52,7 @@ function getRef() {
|
||||
/**获取部门列表 */
|
||||
const getDepartments = async () => {
|
||||
const res = await getDepartmentListAPI({ page: 1, pageSize: 9999 });
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
departments.value = formatHigherOptions(res.data.result);
|
||||
} else {
|
||||
departments.value = [];
|
||||
|
||||
@@ -166,7 +166,7 @@ export const useRole = (treeRef: Ref) => {
|
||||
page: pagination.currentPage,
|
||||
pageSize: val
|
||||
});
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
const data = res.data;
|
||||
dataList.value = data.result;
|
||||
pagination.total = data.total;
|
||||
@@ -179,7 +179,7 @@ export const useRole = (treeRef: Ref) => {
|
||||
page: val,
|
||||
pageSize: pagination.pageSize
|
||||
});
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
const data = res.data;
|
||||
dataList.value = data.result;
|
||||
pagination.total = data.total;
|
||||
@@ -189,7 +189,7 @@ export const useRole = (treeRef: Ref) => {
|
||||
|
||||
const handleDelete = async (row: RoleInfo) => {
|
||||
const res = await deleteRoleAPI(row.id);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
message(`您删除了角色名称为${row.name}的这条数据`, { type: "success" });
|
||||
onSearch();
|
||||
} else {
|
||||
@@ -242,7 +242,7 @@ export const useRole = (treeRef: Ref) => {
|
||||
if (title === "新增") {
|
||||
// 实际开发先调用新增接口,再进行下面操作
|
||||
const res = await postAddRoleAPI(curData);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
chores();
|
||||
} else {
|
||||
message(`添加失败!`, {
|
||||
@@ -253,7 +253,7 @@ export const useRole = (treeRef: Ref) => {
|
||||
} else {
|
||||
// 实际开发先调用修改接口,再进行下面操作
|
||||
const res = await putUpdateRoleAPI(curData, row.id);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
chores();
|
||||
} else {
|
||||
message(`修改失败!`, {
|
||||
@@ -310,7 +310,7 @@ export const useRole = (treeRef: Ref) => {
|
||||
const res = await putUpdateRolePermissionsAPI(id, {
|
||||
permission_ids: permissions
|
||||
});
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
message(`角色名称为${name}的权限修改成功~`, {
|
||||
type: "success"
|
||||
});
|
||||
@@ -334,7 +334,7 @@ export const useRole = (treeRef: Ref) => {
|
||||
/**获取部门列表 */
|
||||
const getDepartments = async () => {
|
||||
const res = await getDepartmentListAPI({ page: 1, pageSize: 9999 });
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
departments.value = formatHigherOptions(res.data.result);
|
||||
} else {
|
||||
departments.value = [];
|
||||
|
||||
@@ -16,6 +16,7 @@ import EditPen from "@iconify-icons/ep/edit-pen";
|
||||
import Refresh from "@iconify-icons/ep/refresh";
|
||||
import AddFill from "@iconify-icons/ri/add-circle-line";
|
||||
import { onBeforeRouteUpdate } from "vue-router";
|
||||
import { hasAuth } from "@/utils/auth";
|
||||
defineOptions({
|
||||
name: "SystemUser"
|
||||
});
|
||||
@@ -117,6 +118,7 @@ onBeforeRouteUpdate((to, from, next) => {
|
||||
<PureTableBar title="用户管理" :columns="columns" @refresh="onSearch">
|
||||
<template #buttons>
|
||||
<el-button
|
||||
v-if="hasAuth('user:btn:addUser')"
|
||||
type="primary"
|
||||
:icon="useRenderIcon(AddFill)"
|
||||
@click="openDialog()"
|
||||
@@ -141,7 +143,11 @@ onBeforeRouteUpdate((to, from, next) => {
|
||||
{{ t("buttons:Deselect") }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-popconfirm title="是否确认删除?" @confirm="onbatchDel">
|
||||
<el-popconfirm
|
||||
v-if="hasAuth('user:btn:deleteUser')"
|
||||
title="是否确认删除?"
|
||||
@confirm="onbatchDel"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button type="danger" text class="mr-1">
|
||||
{{ t("buttons:DeleteInBatches") }}
|
||||
@@ -178,6 +184,7 @@ onBeforeRouteUpdate((to, from, next) => {
|
||||
link
|
||||
type="primary"
|
||||
:size="size"
|
||||
:disabled="!hasAuth('user:btn:updateUser')"
|
||||
:icon="useRenderIcon(EditPen)"
|
||||
@click="openDialog('修改', row)"
|
||||
>
|
||||
@@ -193,6 +200,7 @@ onBeforeRouteUpdate((to, from, next) => {
|
||||
link
|
||||
type="danger"
|
||||
:size="size"
|
||||
:disabled="!hasAuth('user:btn:deleteUser')"
|
||||
:icon="useRenderIcon(Delete)"
|
||||
>
|
||||
{{ t("buttons:Delete") }}
|
||||
@@ -216,6 +224,7 @@ onBeforeRouteUpdate((to, from, next) => {
|
||||
link
|
||||
type="primary"
|
||||
:size="size"
|
||||
:disabled="!hasAuth('user:btn:uploadAvatar')"
|
||||
:icon="useRenderIcon(Upload)"
|
||||
@click="handleUpload(row)"
|
||||
>
|
||||
@@ -228,6 +237,7 @@ onBeforeRouteUpdate((to, from, next) => {
|
||||
link
|
||||
type="primary"
|
||||
:size="size"
|
||||
:disabled="!hasAuth('user:btn:reset_password')"
|
||||
:icon="useRenderIcon(Password)"
|
||||
@click="handleReset(row)"
|
||||
>
|
||||
@@ -240,6 +250,7 @@ onBeforeRouteUpdate((to, from, next) => {
|
||||
link
|
||||
type="primary"
|
||||
:size="size"
|
||||
:disabled="!hasAuth('user:btn:updateRole')"
|
||||
:icon="useRenderIcon(Role)"
|
||||
@click="handleRole(row)"
|
||||
>
|
||||
@@ -252,6 +263,7 @@ onBeforeRouteUpdate((to, from, next) => {
|
||||
link
|
||||
type="primary"
|
||||
:size="size"
|
||||
:disabled="!hasAuth('user:btn:permissionList')"
|
||||
:icon="useRenderIcon(Menu)"
|
||||
@click="openPerDialog(row)"
|
||||
>
|
||||
|
||||
@@ -191,7 +191,7 @@ export const useUser = (tableRef: Ref, treeRef: Ref) => {
|
||||
*/
|
||||
const handleDelete = async (row: UserInfo) => {
|
||||
const res = await deleteUserAPI(row.id);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
message(`您删除了用户账号为${row.username}的这条数据`, {
|
||||
type: "success"
|
||||
});
|
||||
@@ -261,10 +261,10 @@ export const useUser = (tableRef: Ref, treeRef: Ref) => {
|
||||
// 返回当前选中的行
|
||||
const curSelected = tableRef.value.getTableRef().getSelectionRows();
|
||||
const res = await deleteUserListAPI({
|
||||
userIds: getKeyList(curSelected, "id")
|
||||
ids: getKeyList(curSelected, "id")
|
||||
});
|
||||
if (res.code === 200) {
|
||||
message(`已删除用户编号为 ${getKeyList(curSelected, "id")} 的数据`, {
|
||||
if (res.success) {
|
||||
message(res.msg, {
|
||||
type: "success"
|
||||
});
|
||||
tableRef.value.getTableRef().clearSelection();
|
||||
@@ -404,7 +404,7 @@ export const useUser = (tableRef: Ref, treeRef: Ref) => {
|
||||
}
|
||||
}
|
||||
const res = await postAddUserAPI(addForm);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
// 实际开发先调用新增接口,再进行下面操作
|
||||
chores();
|
||||
} else {
|
||||
@@ -430,7 +430,7 @@ export const useUser = (tableRef: Ref, treeRef: Ref) => {
|
||||
}
|
||||
}
|
||||
const res = await putUpdateUserAPI(curData.id, updateForm);
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
chores();
|
||||
} else {
|
||||
message(`更新失败!`, { type: "error" });
|
||||
@@ -453,14 +453,14 @@ export const useUser = (tableRef: Ref, treeRef: Ref) => {
|
||||
contentRenderer: () =>
|
||||
h(croppingUpload, {
|
||||
ref: cropRef,
|
||||
imgSrc: row.avatar || Avatar,
|
||||
imgSrc: `/api/${row.avatar}` || Avatar,
|
||||
onCropper: info => (avatarInfo.value = info)
|
||||
}),
|
||||
beforeSure: async done => {
|
||||
const res = await postUploadAvatarAPI(row.id, {
|
||||
file: avatarInfo.value.blob
|
||||
});
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
// 根据实际业务使用avatarInfo.value和row里的某些字段去调用上传头像接口即可
|
||||
message(`更新成功!`, { type: "success" });
|
||||
onSearch(); // 刷新表格数据
|
||||
@@ -541,7 +541,7 @@ export const useUser = (tableRef: Ref, treeRef: Ref) => {
|
||||
const res = await putUpdateUserPasswordAPI(row.id, {
|
||||
password: pwdForm.newPwd
|
||||
});
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
console.log(pwdForm.newPwd);
|
||||
done();
|
||||
message(`已成功重置 ${row.username} 的密码`, {
|
||||
@@ -593,7 +593,7 @@ export const useUser = (tableRef: Ref, treeRef: Ref) => {
|
||||
user_id: row.id,
|
||||
role_ids: curData.ids as string[]
|
||||
});
|
||||
if (res.code === 200) {
|
||||
if (res.success) {
|
||||
message(`${row.username}--${row.nickname}的角色信息更新成功!`, {
|
||||
type: "success",
|
||||
duration: 5000
|
||||
|
||||
Reference in New Issue
Block a user