mirror of
https://github.com/pure-admin/pure-admin-thin.git
synced 2025-04-24 23:47:17 +08:00
perf: 系统管理
This commit is contained in:
parent
9bac6333fb
commit
0838e69d23
@ -1,5 +1,6 @@
|
||||
buttons:
|
||||
hsLoginOut: LoginOut
|
||||
userInfo: user info
|
||||
hsfullscreen: FullScreen
|
||||
hsexitfullscreen: ExitFullscreen
|
||||
hsrefreshRoute: RefreshRoute
|
||||
|
@ -1,5 +1,6 @@
|
||||
buttons:
|
||||
hsLoginOut: 退出系统
|
||||
userInfo: 个人信息
|
||||
hsfullscreen: 全屏
|
||||
hsexitfullscreen: 退出全屏
|
||||
hsrefreshRoute: 刷新路由
|
||||
|
@ -7,9 +7,11 @@ import Breadcrumb from "./sidebar/breadCrumb.vue";
|
||||
import topCollapse from "./sidebar/topCollapse.vue";
|
||||
import { useTranslationLang } from "../hooks/useTranslationLang";
|
||||
import globalization from "@/assets/svg/globalization.svg?component";
|
||||
import { useDetail } from "@/router/utils";
|
||||
import LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
||||
import Setting from "@iconify-icons/ri/settings-3-line";
|
||||
import Check from "@iconify-icons/ep/check";
|
||||
import Avatar from "@iconify-icons/ep/avatar";
|
||||
|
||||
const {
|
||||
layout,
|
||||
@ -24,6 +26,7 @@ const {
|
||||
getDropdownItemStyle,
|
||||
getDropdownItemClass
|
||||
} = useNav();
|
||||
const { router } = useDetail();
|
||||
|
||||
const { t, locale, translationCh, translationEn } = useTranslationLang();
|
||||
</script>
|
||||
@ -89,6 +92,16 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu class="logout">
|
||||
<el-dropdown-item
|
||||
@click="
|
||||
router.push({
|
||||
name: 'UserInfo'
|
||||
})
|
||||
"
|
||||
>
|
||||
<IconifyIconOffline :icon="Avatar" style="margin: 5px" />
|
||||
个人中心
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="logout">
|
||||
<IconifyIconOffline
|
||||
:icon="LogoutCircleRLine"
|
||||
|
26
src/router/modules/userInfo.ts
Normal file
26
src/router/modules/userInfo.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { $t } from "@/plugins/i18n";
|
||||
import { home } from "@/router/enums";
|
||||
const Layout = () => import("@/layout/index.vue");
|
||||
|
||||
export default {
|
||||
path: "/system/user/info",
|
||||
name: "UserInfo",
|
||||
component: Layout,
|
||||
redirect: "/system/user/info",
|
||||
meta: {
|
||||
icon: "homeFilled",
|
||||
title: $t("buttons.userInfo"),
|
||||
rank: home
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "/system/user/info",
|
||||
name: "UserInfo",
|
||||
component: () => import("@/views/system/user/info.vue"),
|
||||
meta: {
|
||||
title: $t("buttons.userInfo"),
|
||||
showLink: false
|
||||
}
|
||||
}
|
||||
]
|
||||
} satisfies RouteConfigsTable;
|
@ -3,12 +3,17 @@ import {
|
||||
type RouteRecordRaw,
|
||||
type RouteComponent,
|
||||
createWebHistory,
|
||||
createWebHashHistory
|
||||
createWebHashHistory,
|
||||
useRouter,
|
||||
useRoute,
|
||||
type LocationQueryRaw,
|
||||
type RouteParamsRaw
|
||||
} from "vue-router";
|
||||
import { router } from "./index";
|
||||
import { isProxy, toRaw } from "vue";
|
||||
import { useTimeoutFn } from "@vueuse/core";
|
||||
import {
|
||||
isEmpty,
|
||||
isString,
|
||||
cloneDeep,
|
||||
isAllEmpty,
|
||||
@ -366,6 +371,67 @@ function getTopMenu(tag = false): menuType {
|
||||
return topMenu;
|
||||
}
|
||||
|
||||
function useDetail() {
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const getParameter = isEmpty(route.params) ? route.query : route.params;
|
||||
|
||||
function toDetail(
|
||||
parameter: LocationQueryRaw | RouteParamsRaw,
|
||||
model: "query" | "params"
|
||||
) {
|
||||
// ⚠️ 这里要特别注意下,因为vue-router在解析路由参数的时候会自动转化成字符串类型,比如在使用useRoute().route.query或useRoute().route.params时,得到的参数都是字符串类型
|
||||
// 所以在传参的时候,如果参数是数字类型,就需要在此处 toString() 一下,保证传参跟路由参数类型一致都是字符串,这是必不可少的环节!!!
|
||||
Object.keys(parameter).forEach(param => {
|
||||
if (!isString(parameter[param])) {
|
||||
parameter[param] = parameter[param].toString();
|
||||
}
|
||||
});
|
||||
if (model === "query") {
|
||||
// 保存信息到标签页
|
||||
useMultiTagsStoreHook().handleTags("push", {
|
||||
path: `/tabs/query-detail`,
|
||||
name: "TabQueryDetail",
|
||||
query: parameter,
|
||||
meta: {
|
||||
title: {
|
||||
zh: `No.${parameter.id} - 详情信息`,
|
||||
en: `No.${parameter.id} - DetailInfo`
|
||||
},
|
||||
// 如果使用的是非国际化精简版title可以像下面这么写
|
||||
// title: `No.${index} - 详情信息`,
|
||||
// 最大打开标签数
|
||||
dynamicLevel: 3
|
||||
}
|
||||
});
|
||||
// 路由跳转
|
||||
router.push({ name: "TabQueryDetail", query: parameter });
|
||||
} else if (model === "params") {
|
||||
useMultiTagsStoreHook().handleTags("push", {
|
||||
path: `/tabs/params-detail/:id`,
|
||||
name: "TabParamsDetail",
|
||||
params: parameter,
|
||||
meta: {
|
||||
title: {
|
||||
zh: `No.${parameter.id} - 详情信息`,
|
||||
en: `No.${parameter.id} - DetailInfo`
|
||||
}
|
||||
// 如果使用的是非国际化精简版title可以像下面这么写
|
||||
// title: `No.${index} - 详情信息`,
|
||||
}
|
||||
});
|
||||
router.push({ name: "TabParamsDetail", params: parameter });
|
||||
}
|
||||
}
|
||||
|
||||
// 用于页面刷新,重新获取浏览器地址栏参数并保存到标签页
|
||||
const initToDetail = (model: "query" | "params") => {
|
||||
if (getParameter) toDetail(getParameter, model);
|
||||
};
|
||||
|
||||
return { toDetail, initToDetail, getParameter, router };
|
||||
}
|
||||
|
||||
export {
|
||||
hasAuth,
|
||||
getAuths,
|
||||
@ -382,5 +448,6 @@ export {
|
||||
handleAliveRoute,
|
||||
formatTwoStageRoutes,
|
||||
formatFlatteningRoutes,
|
||||
filterNoPermissionTree
|
||||
filterNoPermissionTree,
|
||||
useDetail
|
||||
};
|
||||
|
@ -65,7 +65,8 @@ export function setToken(data: DataInfo<Date>) {
|
||||
function setUserKey(
|
||||
accessToken: string,
|
||||
username: string,
|
||||
roles: Array<string>
|
||||
roles: Array<string>,
|
||||
user?: any
|
||||
) {
|
||||
useUserStoreHook().SET_USERNAME(username);
|
||||
useUserStoreHook().SET_ROLES(roles);
|
||||
@ -73,13 +74,14 @@ export function setToken(data: DataInfo<Date>) {
|
||||
accessToken,
|
||||
expires,
|
||||
username,
|
||||
roles
|
||||
roles,
|
||||
user
|
||||
});
|
||||
}
|
||||
|
||||
if (data.username && data.roles) {
|
||||
const { username, roles } = data;
|
||||
setUserKey(accessToken, username, roles);
|
||||
const { username, roles, user } = data;
|
||||
setUserKey(accessToken, username, roles, user);
|
||||
} else {
|
||||
const username =
|
||||
storageLocal().getItem<DataInfo<number>>(userKey)?.username ?? "";
|
||||
|
@ -30,7 +30,7 @@ const {
|
||||
submitEditUser
|
||||
} = useUser(tableRef, treeRef);
|
||||
|
||||
const user = reactive(userInfo.value.user);
|
||||
const user = reactive(userInfo.value);
|
||||
defineOptions({
|
||||
name: "UserInfo"
|
||||
});
|
||||
@ -51,9 +51,9 @@ defineOptions({
|
||||
<el-avatar
|
||||
:size="80"
|
||||
src="https://empty"
|
||||
@click="handleUpload(userInfo.user)"
|
||||
@click="handleUpload(userInfo)"
|
||||
>
|
||||
<img :src="'/avatar/' + userInfo.user.avatarName" />
|
||||
<img :src="'/avatar/' + userInfo.avatarName" />
|
||||
</el-avatar>
|
||||
</div>
|
||||
|
||||
@ -62,28 +62,28 @@ defineOptions({
|
||||
<div style="height: 100%">
|
||||
<IconifyIconOffline class="check-zh" :icon="SignIn" />
|
||||
登录账号
|
||||
<div class="user-right">{{ userInfo.user.username }}</div>
|
||||
<div class="user-right">{{ userInfo.username }}</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<IconifyIconOffline class="check-zh" :icon="Check" />
|
||||
用户昵称
|
||||
<div class="user-right">{{ userInfo.user.nickName }}</div>
|
||||
<div class="user-right">{{ userInfo.nickName }}</div>
|
||||
</li>
|
||||
<li>
|
||||
<IconifyIconOffline class="check-zh" :icon="NodeTree" />
|
||||
所属部门
|
||||
<div class="user-right">{{ userInfo.user.dept.name }}</div>
|
||||
<div class="user-right">{{ userInfo.dept.name }}</div>
|
||||
</li>
|
||||
<li>
|
||||
<IconifyIconOffline class="check-zh" :icon="Phone" />
|
||||
手机号码
|
||||
<div class="user-right">{{ userInfo.user.phone }}</div>
|
||||
<div class="user-right">{{ userInfo.phone }}</div>
|
||||
</li>
|
||||
<li>
|
||||
<IconifyIconOffline class="check-zh" :icon="Mail" />
|
||||
用户邮箱
|
||||
<div class="user-right">{{ userInfo.user.email }}</div>
|
||||
<div class="user-right">{{ userInfo.email }}</div>
|
||||
</li>
|
||||
<li>
|
||||
<IconifyIconOffline class="check-zh" :icon="Secure" />
|
||||
|
@ -4,7 +4,7 @@ import { baseUrlAvatar } from "@/api/utils";
|
||||
import { zxcvbn } from "@zxcvbn-ts/core";
|
||||
import { isAllEmpty, isNull, isEmail } from "@pureadmin/utils";
|
||||
import { addDialog } from "@/components/ReDialog";
|
||||
import Cookies from "js-cookie";
|
||||
import { storageLocal } from "@pureadmin/utils";
|
||||
import * as User from "@/api/system/user";
|
||||
import {
|
||||
ElForm,
|
||||
@ -55,7 +55,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
||||
});
|
||||
/** 用户信息 */
|
||||
const userInfo = computed(() => {
|
||||
return JSON.parse(Cookies.get("userInfo"));
|
||||
return storageLocal().getItem("user-info").user;
|
||||
});
|
||||
/** 获取邮箱验证码 */
|
||||
const getEmailCode = email => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user