🔨 修改路由配置.
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import type { MenuQueryResponse } from '@/api/system/menu';
|
||||
import axios from 'axios';
|
||||
|
||||
/**
|
||||
@@ -17,45 +16,15 @@ export interface LoginResponse {
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户权限响应
|
||||
* 用户登录
|
||||
*/
|
||||
export interface UserPermissionResponse {
|
||||
user: {
|
||||
id: number;
|
||||
username: string;
|
||||
nickname: string;
|
||||
avatar: string;
|
||||
systemPreference: Record<string, any>;
|
||||
tippedKeys: Array<string>;
|
||||
};
|
||||
roles: Array<string>;
|
||||
permissions: Array<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
export function login(data: LoginRequest) {
|
||||
export function userLogin(data: LoginRequest) {
|
||||
return axios.post<LoginResponse>('/infra/auth/login', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登出
|
||||
* 用户登出
|
||||
*/
|
||||
export function logout() {
|
||||
export function userLogout() {
|
||||
return axios.get('/infra/auth/logout');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
export function getUserPermission() {
|
||||
return axios.get<UserPermissionResponse>('/infra/user-permission/user');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单列表
|
||||
*/
|
||||
export function getMenuList() {
|
||||
return axios.get<Array<MenuQueryResponse>>('/infra/user-permission/menu');
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import axios from 'axios';
|
||||
export interface UserUpdatePasswordRequest {
|
||||
beforePassword?: string;
|
||||
password?: string;
|
||||
checkPassword?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
39
orion-visor-ui/src/api/user/permission.ts
Normal file
39
orion-visor-ui/src/api/user/permission.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import type { MenuQueryResponse } from '@/api/system/menu';
|
||||
import axios from 'axios';
|
||||
|
||||
/**
|
||||
* 用户权限响应
|
||||
*/
|
||||
export interface UserPermissionResponse {
|
||||
user: UserBaseResponse;
|
||||
roles: Array<string>;
|
||||
permissions: Array<string>;
|
||||
systemPreference: Record<string, any>;
|
||||
tippedKeys: Array<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户基础信息
|
||||
*/
|
||||
export interface UserBaseResponse {
|
||||
id: number;
|
||||
username: string;
|
||||
nickname: string;
|
||||
avatar: string;
|
||||
passwordUpdateStatus: number;
|
||||
passwordUpdateReason: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
export function getUserPermission() {
|
||||
return axios.get<UserPermissionResponse>('/infra/user-permission/user');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单列表
|
||||
*/
|
||||
export function getUserMenuList() {
|
||||
return axios.get<Array<MenuQueryResponse>>('/infra/user-permission/menu');
|
||||
}
|
||||
@@ -122,7 +122,6 @@
|
||||
// 关闭左侧
|
||||
const currentRouteIdx = findCurrentRouteIndex();
|
||||
copyTagList.splice(1, props.index - 1);
|
||||
|
||||
tabBarStore.freshTabList(copyTagList);
|
||||
if (currentRouteIdx < index) {
|
||||
await router.push({ name: itemData.name });
|
||||
@@ -131,7 +130,6 @@
|
||||
// 关闭右侧
|
||||
const currentRouteIdx = findCurrentRouteIndex();
|
||||
copyTagList.splice(props.index + 1);
|
||||
|
||||
tabBarStore.freshTabList(copyTagList);
|
||||
if (currentRouteIdx > index) {
|
||||
await router.push({ name: itemData.name });
|
||||
@@ -154,7 +152,8 @@
|
||||
} else {
|
||||
// 关闭全部
|
||||
tabBarStore.resetTabList();
|
||||
await router.push({ name: DEFAULT_ROUTE_NAME });
|
||||
// 跳转到首页 添加 query 强行刷新
|
||||
await router.push({ name: DEFAULT_ROUTE_NAME, query: { _: Date.now() } });
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<a-modal v-model:visible="visible"
|
||||
modal-class="modal-form-large"
|
||||
title-align="start"
|
||||
title="重置密码"
|
||||
title="修改密码"
|
||||
:top="120"
|
||||
:align-center="false"
|
||||
:draggable="true"
|
||||
@@ -16,16 +16,25 @@
|
||||
<a-form :model="formModel"
|
||||
ref="formRef"
|
||||
label-align="right"
|
||||
:rules="rules"
|
||||
:auto-label-width="true">
|
||||
<!-- 密码 -->
|
||||
<a-form-item field="beforePassword" label="原始密码">
|
||||
:rules="rules">
|
||||
<!-- 原始密码 -->
|
||||
<a-form-item field="beforePassword"
|
||||
label="原始密码"
|
||||
hide-label>
|
||||
<a-input-password v-model="formModel.beforePassword" placeholder="请输入原始密码" />
|
||||
</a-form-item>
|
||||
<!-- 密码 -->
|
||||
<a-form-item field="password" label="新密码">
|
||||
<!-- 新密码 -->
|
||||
<a-form-item field="password"
|
||||
label="新密码"
|
||||
hide-label>
|
||||
<a-input-password v-model="formModel.password" placeholder="请输入新密码" />
|
||||
</a-form-item>
|
||||
<!-- 确认密码 -->
|
||||
<a-form-item field="checkPassword"
|
||||
label="确认密码"
|
||||
hide-label>
|
||||
<a-input-password v-model="formModel.checkPassword" placeholder="请再次输入新密码" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</a-modal>
|
||||
@@ -38,12 +47,13 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { FieldRule } from '@arco-design/web-vue';
|
||||
import type { UserUpdatePasswordRequest } from '@/api/user/mine';
|
||||
import { ref } from 'vue';
|
||||
import { md5 } from '@/utils';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import useVisible from '@/hooks/visible';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { md5 } from '@/utils';
|
||||
import { updateCurrentUserPassword } from '@/api/user/mine';
|
||||
|
||||
const emits = defineEmits(['updated']);
|
||||
@@ -63,8 +73,26 @@
|
||||
minLength: 8,
|
||||
maxLength: 32,
|
||||
message: '新密码长度需要在 8-32 位之间'
|
||||
}, {
|
||||
validator: (value, cb) => {
|
||||
if (formModel.value.beforePassword === value) {
|
||||
cb('新密码不能和原始密码相同');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}],
|
||||
};
|
||||
checkPassword: [{
|
||||
required: true,
|
||||
message: '请再次输入新密码'
|
||||
}, {
|
||||
validator: (value, cb) => {
|
||||
if (formModel.value.password !== value) {
|
||||
cb('两次输入的密码不一致');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}],
|
||||
} as Record<string, FieldRule | FieldRule[]>;
|
||||
|
||||
const formRef = ref();
|
||||
const formModel = ref<UserUpdatePasswordRequest>({});
|
||||
@@ -73,7 +101,8 @@
|
||||
const open = () => {
|
||||
formModel.value = {
|
||||
beforePassword: undefined,
|
||||
password: undefined
|
||||
password: undefined,
|
||||
checkPassword: undefined,
|
||||
};
|
||||
setVisible(true);
|
||||
};
|
||||
@@ -89,16 +118,6 @@
|
||||
if (error) {
|
||||
return false;
|
||||
}
|
||||
// 相同校验
|
||||
if (formModel.value.beforePassword === formModel.value.password) {
|
||||
formRef.value.setFields({
|
||||
password: {
|
||||
status: 'error',
|
||||
message: '新密码不能和原始密码相同'
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
// 修改
|
||||
await updateCurrentUserPassword({
|
||||
beforePassword: md5(formModel.value.beforePassword as string),
|
||||
|
||||
@@ -22,9 +22,7 @@ export default function usePermission() {
|
||||
const element = menuConfig.shift();
|
||||
if (element?.name === route.name) exist = true;
|
||||
if (element?.children) {
|
||||
menuConfig.push(
|
||||
...(element.children as unknown as RouteRecordNormalized[])
|
||||
);
|
||||
menuConfig.push(...(element.children as unknown as RouteRecordNormalized[]));
|
||||
}
|
||||
}
|
||||
return exist;
|
||||
|
||||
@@ -24,12 +24,15 @@ export default function useResponsive(immediate?: boolean) {
|
||||
}
|
||||
|
||||
const debounceFn = useDebounceFn(resizeHandler, 100);
|
||||
|
||||
onMounted(() => {
|
||||
if (immediate) debounceFn();
|
||||
});
|
||||
|
||||
onBeforeMount(() => {
|
||||
addEventListen(window, 'resize', debounceFn);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
removeEventListen(window, 'resize', debounceFn);
|
||||
});
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
import { useUserStore } from '@/store';
|
||||
import { LOGIN_ROUTE_NAME } from '@/router/constants';
|
||||
|
||||
export default function useUser() {
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 退出登录
|
||||
const logout = async () => {
|
||||
const logout = async (msg: string = '已退出登录') => {
|
||||
await userStore.logout();
|
||||
Message.success('已退出登录');
|
||||
await router.push({ name: 'login' });
|
||||
if (msg) {
|
||||
Message.success(msg);
|
||||
}
|
||||
await router.push({ name: LOGIN_ROUTE_NAME });
|
||||
};
|
||||
|
||||
// 退出并重定向
|
||||
@@ -20,7 +22,7 @@ export default function useUser() {
|
||||
const currentRoute = router.currentRoute.value;
|
||||
Message.success('已退出登录');
|
||||
await router.push({
|
||||
name: logoutTo || 'login',
|
||||
name: logoutTo || LOGIN_ROUTE_NAME,
|
||||
query: {
|
||||
...router.currentRoute.value.query,
|
||||
redirect: currentRoute.name as string,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import type { RouteLocationNormalized } from 'vue-router';
|
||||
import type { TagProps } from '@/store/modules/tab-bar/types';
|
||||
|
||||
export const LOGIN_ROUTE_NAME = 'login';
|
||||
|
||||
export const REDIRECT_ROUTE_NAME = 'redirect';
|
||||
|
||||
export const LOGIN_ROUTE_NAME = 'login';
|
||||
export const UPDATE_PASSWORD_ROUTE_NAME = 'updatePassword';
|
||||
|
||||
export const FORBIDDEN_ROUTER_NAME = 'forbidden';
|
||||
|
||||
@@ -24,6 +26,7 @@ export const DEFAULT_ROUTER = { name: DEFAULT_ROUTE_NAME, children: [] };
|
||||
export const WHITE_ROUTER_LIST = [
|
||||
{ name: LOGIN_ROUTE_NAME, children: [] },
|
||||
{ name: REDIRECT_ROUTE_NAME, children: [] },
|
||||
{ name: UPDATE_PASSWORD_ROUTE_NAME, children: [] },
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -34,16 +37,6 @@ export const STATUS_ROUTER_LIST = [
|
||||
{ name: FORBIDDEN_ROUTER_NAME, children: [] },
|
||||
];
|
||||
|
||||
/**
|
||||
* 默认 tab 页面
|
||||
*/
|
||||
export const DEFAULT_TAB = {
|
||||
title: '工作台',
|
||||
name: DEFAULT_ROUTE_NAME,
|
||||
path: DEFAULT_ROUTE_FULL_PATH,
|
||||
fullPath: DEFAULT_ROUTE_FULL_PATH,
|
||||
};
|
||||
|
||||
/**
|
||||
* router 转 tag
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Router } from 'vue-router';
|
||||
import NProgress from 'nprogress';
|
||||
import { useMenuStore } from '@/store';
|
||||
import { NOT_FOUND_ROUTER_NAME, WHITE_ROUTER_LIST } from '../constants';
|
||||
import NProgress from 'nprogress';
|
||||
import usePermission from '@/hooks/permission';
|
||||
|
||||
export default function setupPermissionGuard(router: Router) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { LocationQueryRaw, Router } from 'vue-router';
|
||||
import type { RouteLocationRaw, Router } from 'vue-router';
|
||||
import NProgress from 'nprogress';
|
||||
import { useUserStore } from '@/store';
|
||||
import { isLogin } from '@/utils/auth';
|
||||
import { LOGIN_ROUTE_NAME, UPDATE_PASSWORD_ROUTE_NAME } from '@/router/constants';
|
||||
|
||||
/**
|
||||
* 初始化用户登录路由守卫
|
||||
@@ -11,40 +12,49 @@ export default function setupUserLoginInfoGuard(router: Router) {
|
||||
NProgress.start();
|
||||
const userStore = useUserStore();
|
||||
if (isLogin()) {
|
||||
// 获取用户信息
|
||||
if (userStore.id) {
|
||||
// 跳转
|
||||
next();
|
||||
} else {
|
||||
try {
|
||||
// 获取用户信息
|
||||
await userStore.info();
|
||||
next();
|
||||
const info = await userStore.getUserInfo();
|
||||
if (info.user.passwordUpdateStatus === 1) {
|
||||
// 跳转到修改密码页面
|
||||
next({
|
||||
name: UPDATE_PASSWORD_ROUTE_NAME,
|
||||
query: { reason: info.user.passwordUpdateReason },
|
||||
} as RouteLocationRaw);
|
||||
} else {
|
||||
// 跳转
|
||||
next();
|
||||
}
|
||||
} catch (error) {
|
||||
// 获取失败退出登录
|
||||
await userStore.logout();
|
||||
next({
|
||||
name: 'login',
|
||||
name: LOGIN_ROUTE_NAME,
|
||||
query: {
|
||||
redirect: to.name,
|
||||
...to.query,
|
||||
} as LocationQueryRaw,
|
||||
});
|
||||
},
|
||||
} as RouteLocationRaw);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 未登录跳转到登录页
|
||||
if (to.name === 'login') {
|
||||
if (to.name === LOGIN_ROUTE_NAME) {
|
||||
// 未登录跳转到登录页
|
||||
next();
|
||||
return;
|
||||
} else {
|
||||
// 跳转到登录页
|
||||
next({
|
||||
name: LOGIN_ROUTE_NAME,
|
||||
query: {
|
||||
redirect: to.name,
|
||||
...to.query,
|
||||
},
|
||||
} as RouteLocationRaw);
|
||||
}
|
||||
// 跳转到登录页
|
||||
next({
|
||||
name: 'login',
|
||||
query: {
|
||||
redirect: to.name,
|
||||
...to.query,
|
||||
} as LocationQueryRaw,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { RouteLocationRaw } from 'vue-router';
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import NProgress from 'nprogress';
|
||||
import { appRoutes } from './routes';
|
||||
import BASE_ROUTERS from './routes/base';
|
||||
import createRouteGuard from './guard';
|
||||
import { openWindow } from '@/utils';
|
||||
import { isStandaloneMode } from '@/utils/env';
|
||||
import createRouteGuard from './guard';
|
||||
import baseRouters from './routes/base';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
NProgress.configure({ showSpinner: false });
|
||||
@@ -14,7 +14,7 @@ NProgress.configure({ showSpinner: false });
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
...BASE_ROUTERS,
|
||||
...baseRouters,
|
||||
...appRoutes,
|
||||
],
|
||||
scrollBehavior() {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
import { DEFAULT_ROUTE_FULL_PATH, FORBIDDEN_ROUTER_NAME, LOGIN_ROUTE_NAME, NOT_FOUND_ROUTER_NAME, REDIRECT_ROUTE_NAME, } from '@/router/constants';
|
||||
import {
|
||||
DEFAULT_ROUTE_FULL_PATH,
|
||||
FORBIDDEN_ROUTER_NAME,
|
||||
LOGIN_ROUTE_NAME,
|
||||
NOT_FOUND_ROUTER_NAME,
|
||||
REDIRECT_ROUTE_NAME,
|
||||
UPDATE_PASSWORD_ROUTE_NAME,
|
||||
} from '@/router/constants';
|
||||
|
||||
// 默认布局
|
||||
export const DEFAULT_LAYOUT = () => import('@/layout/default-layout.vue');
|
||||
@@ -8,13 +15,13 @@ export const DEFAULT_LAYOUT = () => import('@/layout/default-layout.vue');
|
||||
export const FULL_LAYOUT = () => import('@/layout/full-layout.vue');
|
||||
|
||||
// 根页面
|
||||
export const ROOT_ROUTER: RouteRecordRaw = {
|
||||
export const ROOT_ROUTE: RouteRecordRaw = {
|
||||
path: '/',
|
||||
redirect: DEFAULT_ROUTE_FULL_PATH,
|
||||
};
|
||||
|
||||
// 登录页面
|
||||
export const LOGIN_ROUTER: RouteRecordRaw = {
|
||||
export const LOGIN_ROUTE: RouteRecordRaw = {
|
||||
path: '/login',
|
||||
name: LOGIN_ROUTE_NAME,
|
||||
meta: {
|
||||
@@ -24,7 +31,7 @@ export const LOGIN_ROUTER: RouteRecordRaw = {
|
||||
};
|
||||
|
||||
// 重定向页面
|
||||
export const REDIRECT_ROUTER: RouteRecordRaw = {
|
||||
export const REDIRECT_ROUTE: RouteRecordRaw = {
|
||||
path: '/redirect',
|
||||
name: 'redirectWrapper',
|
||||
component: DEFAULT_LAYOUT,
|
||||
@@ -46,14 +53,24 @@ export const REDIRECT_ROUTER: RouteRecordRaw = {
|
||||
],
|
||||
};
|
||||
|
||||
// 修改密码
|
||||
export const UPDATE_PASSWORD_ROUTE: RouteRecordRaw = {
|
||||
path: '/update-password',
|
||||
name: UPDATE_PASSWORD_ROUTE_NAME,
|
||||
component: () => import('@/views/base/update-password/index.vue'),
|
||||
meta: {
|
||||
locale: '修改密码'
|
||||
},
|
||||
};
|
||||
|
||||
// 403 页面
|
||||
export const FORBIDDEN_ROUTE: RouteRecordRaw = {
|
||||
path: '/403',
|
||||
name: FORBIDDEN_ROUTER_NAME,
|
||||
component: () => import('@/views/base/status/forbidden/index.vue'),
|
||||
meta: {
|
||||
locale: '403'
|
||||
},
|
||||
component: () => import('@/views/base/status/forbidden/index.vue'),
|
||||
};
|
||||
|
||||
// 404 页面
|
||||
@@ -61,16 +78,17 @@ export const NOT_FOUND_ROUTE: RouteRecordRaw = {
|
||||
// path: '/:pathMatch(.*)*',
|
||||
path: '/404',
|
||||
name: NOT_FOUND_ROUTER_NAME,
|
||||
component: () => import('@/views/base/status/not-found/index.vue'),
|
||||
meta: {
|
||||
locale: '404'
|
||||
},
|
||||
component: () => import('@/views/base/status/not-found/index.vue'),
|
||||
};
|
||||
|
||||
export default [
|
||||
ROOT_ROUTER,
|
||||
LOGIN_ROUTER,
|
||||
REDIRECT_ROUTER,
|
||||
ROOT_ROUTE,
|
||||
LOGIN_ROUTE,
|
||||
REDIRECT_ROUTE,
|
||||
UPDATE_PASSWORD_ROUTE,
|
||||
NOT_FOUND_ROUTE,
|
||||
FORBIDDEN_ROUTE
|
||||
];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { AppRouteRecordRaw } from '../types';
|
||||
import { DEFAULT_LAYOUT } from '../base';
|
||||
import { DEFAULT_ROUTE_FULL_PATH, DEFAULT_ROUTE_NAME } from '@/router/constants';
|
||||
|
||||
const DASHBOARD: AppRouteRecordRaw = {
|
||||
name: 'dashboard',
|
||||
@@ -7,8 +8,8 @@ const DASHBOARD: AppRouteRecordRaw = {
|
||||
component: DEFAULT_LAYOUT,
|
||||
children: [
|
||||
{
|
||||
name: 'workplace',
|
||||
path: '/workplace',
|
||||
name: DEFAULT_ROUTE_NAME,
|
||||
path: DEFAULT_ROUTE_FULL_PATH,
|
||||
component: () => import('@/views/dashboard/workplace/index.vue'),
|
||||
},
|
||||
],
|
||||
|
||||
@@ -4,8 +4,8 @@ import type { MenuQueryResponse } from '@/api/system/menu';
|
||||
import router from '@/router';
|
||||
import { defineStore } from 'pinia';
|
||||
import { Notification } from '@arco-design/web-vue';
|
||||
import { getMenuList } from '@/api/user/auth';
|
||||
import { EnabledStatus } from '@/types/const';
|
||||
import { getUserMenuList } from '@/api/user/permission';
|
||||
|
||||
export default defineStore('menu', {
|
||||
state: (): MenuState => ({
|
||||
@@ -54,7 +54,7 @@ export default defineStore('menu', {
|
||||
async fetchMenu() {
|
||||
try {
|
||||
// 查询菜单
|
||||
const { data } = await getMenuList();
|
||||
const { data } = await getUserMenuList();
|
||||
// 转换菜单
|
||||
this.serverMenus = data.map(s => {
|
||||
// 构建父目录
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import type { TabBarState, TagProps } from './types';
|
||||
import { defineStore } from 'pinia';
|
||||
import { DEFAULT_ROUTE_NAME, DEFAULT_TAB } from '@/router/constants';
|
||||
import { isString } from '@/utils/is';
|
||||
|
||||
export default defineStore('tabBar', {
|
||||
state: (): TabBarState => ({
|
||||
cacheTabList: new Set([DEFAULT_ROUTE_NAME]),
|
||||
tagList: [DEFAULT_TAB],
|
||||
cacheTabList: new Set([]),
|
||||
tagList: [],
|
||||
}),
|
||||
|
||||
getters: {
|
||||
@@ -55,9 +54,8 @@ export default defineStore('tabBar', {
|
||||
|
||||
// 重设 tab
|
||||
resetTabList() {
|
||||
this.tagList = [DEFAULT_TAB];
|
||||
this.tagList = [];
|
||||
this.cacheTabList.clear();
|
||||
this.cacheTabList.add(DEFAULT_ROUTE_NAME);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { UserState } from './types';
|
||||
import type { LoginRequest } from '@/api/user/auth';
|
||||
import { getUserPermission, login as userLogin, logout as userLogout } from '@/api/user/auth';
|
||||
import { userLogin, userLogout } from '@/api/user/auth';
|
||||
import { md5 } from '@/utils';
|
||||
import { defineStore } from 'pinia';
|
||||
import { clearToken, setToken } from '@/utils/auth';
|
||||
import { md5 } from '@/utils';
|
||||
import { removeRouteListener } from '@/utils/route-listener';
|
||||
import { getUserPermission } from '@/api/user/permission';
|
||||
import { useAppStore, useCacheStore, useMenuStore, useTabBarStore, useTipsStore } from '@/store';
|
||||
|
||||
export default defineStore('user', {
|
||||
@@ -25,15 +26,15 @@ export default defineStore('user', {
|
||||
|
||||
actions: {
|
||||
// 设置用户信息
|
||||
setInfo(partial: Partial<UserState>) {
|
||||
setUserInfo(partial: Partial<UserState>) {
|
||||
this.$patch(partial);
|
||||
},
|
||||
|
||||
// 获取用户信息
|
||||
async info() {
|
||||
async getUserInfo() {
|
||||
const { data } = await getUserPermission();
|
||||
// 设置用户信息
|
||||
this.setInfo({
|
||||
this.setUserInfo({
|
||||
id: data.user.id,
|
||||
username: data.user.username,
|
||||
nickname: data.user.nickname,
|
||||
@@ -42,11 +43,10 @@ export default defineStore('user', {
|
||||
permission: data.permissions,
|
||||
});
|
||||
// 设置用户偏好
|
||||
const appStore = useAppStore();
|
||||
appStore.updateSettings(data.user.systemPreference);
|
||||
useAppStore().updateSettings(data.systemPreference);
|
||||
// 设置已经提示的key
|
||||
const tipsStore = useTipsStore();
|
||||
tipsStore.set(data.user.tippedKeys);
|
||||
useTipsStore().set(data.tippedKeys);
|
||||
return data;
|
||||
},
|
||||
|
||||
// 登录
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
import { useUserStore } from '@/store';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { isDemoMode } from '@/utils/env';
|
||||
import { DEFAULT_ROUTE_NAME } from '@/router/constants';
|
||||
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
@@ -83,7 +84,7 @@
|
||||
// 跳转路由
|
||||
const { redirect, ...othersQuery } = router.currentRoute.value.query;
|
||||
router.push({
|
||||
name: (redirect as string) || 'workplace',
|
||||
name: (redirect as string) || DEFAULT_ROUTE_NAME,
|
||||
query: {
|
||||
...othersQuery,
|
||||
},
|
||||
|
||||
@@ -23,6 +23,12 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'login',
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Notification } from '@arco-design/web-vue';
|
||||
import { reLoginTipsKey } from '@/types/symbol';
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
<template>
|
||||
<div></div>
|
||||
<div />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'redirect',
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
|
||||
@@ -1,44 +1,34 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<a-result class="result" status="403" subtitle="您没有访问该资源的权限" />
|
||||
<div class="operation-row">
|
||||
<a-button class="mr8" key="back" type="primary" @click="logout">重新登录</a-button>
|
||||
<a-button key="back" type="primary" @click="to('workplace')">返回工作台</a-button>
|
||||
</div>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="() => logout()">重新登录</a-button>
|
||||
<a-button type="primary" @click="() => $router.push(DEFAULT_ROUTE_NAME)">返回工作台</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useUserStore } from '@/store';
|
||||
|
||||
const router = useRouter();
|
||||
const to = (name: string) => {
|
||||
router.push({ name: name });
|
||||
};
|
||||
|
||||
// 重新登录
|
||||
const logout = () => {
|
||||
const userStore = useUserStore();
|
||||
userStore.logout();
|
||||
to('login');
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'forbidden',
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import useUser from '@/hooks/user';
|
||||
import { DEFAULT_ROUTE_NAME } from '@/router/constants';
|
||||
|
||||
const { logout } = useUser();
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.content {
|
||||
// padding-top: 100px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -95px;
|
||||
margin-top: -121px;
|
||||
margin-left: -96px;
|
||||
margin-top: -124px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,44 +1,34 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<a-result class="result" status="404" subtitle="糟糕! 页面不见了!" />
|
||||
<div class="operation-row">
|
||||
<a-button class="mr8" key="back" type="primary" @click="logout">重新登录</a-button>
|
||||
<a-button key="back" type="primary" @click="to('workplace')">返回工作台</a-button>
|
||||
</div>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="() => logout()">重新登录</a-button>
|
||||
<a-button type="primary" @click="() => $router.push(DEFAULT_ROUTE_NAME)">返回工作台</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useUserStore } from '@/store';
|
||||
|
||||
const router = useRouter();
|
||||
const to = (name: string) => {
|
||||
router.push({ name: name });
|
||||
};
|
||||
|
||||
// 重新登录
|
||||
const logout = () => {
|
||||
const userStore = useUserStore();
|
||||
userStore.logout();
|
||||
to('login');
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'notFound',
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import useUser from '@/hooks/user';
|
||||
import { DEFAULT_ROUTE_NAME } from '@/router/constants';
|
||||
|
||||
const { logout } = useUser();
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.content {
|
||||
// padding-top: 100px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -95px;
|
||||
margin-top: -121px;
|
||||
margin-left: -96px;
|
||||
margin-top: -124px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
165
orion-visor-ui/src/views/base/update-password/index.vue
Normal file
165
orion-visor-ui/src/views/base/update-password/index.vue
Normal file
@@ -0,0 +1,165 @@
|
||||
<template>
|
||||
<a-spin class="content" :loading="loading">
|
||||
<!-- 原因 -->
|
||||
<p class="reason">{{ reason }}</p>
|
||||
<!-- 表单 -->
|
||||
<a-form :model="formModel"
|
||||
ref="formRef"
|
||||
label-align="right"
|
||||
:rules="rules">
|
||||
<!-- 原始密码 -->
|
||||
<a-form-item field="beforePassword"
|
||||
label="原始密码"
|
||||
hide-label>
|
||||
<a-input-password v-model="formModel.beforePassword" placeholder="请输入原始密码" />
|
||||
</a-form-item>
|
||||
<!-- 新密码 -->
|
||||
<a-form-item field="password"
|
||||
label="新密码"
|
||||
hide-label>
|
||||
<a-input-password v-model="formModel.password" placeholder="请输入新密码" />
|
||||
</a-form-item>
|
||||
<!-- 确认密码 -->
|
||||
<a-form-item field="checkPassword"
|
||||
label="确认密码"
|
||||
hide-label>
|
||||
<a-input-password v-model="formModel.checkPassword" placeholder="请再次输入新密码" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<!-- 按钮 -->
|
||||
<a-space>
|
||||
<!-- 确认修改 -->
|
||||
<a-button class="action"
|
||||
type="primary"
|
||||
@click="doUpdate">
|
||||
确认修改
|
||||
</a-button>
|
||||
<!-- 退出登录 -->
|
||||
<a-button class="action"
|
||||
type="primary"
|
||||
@click="() => logout()">
|
||||
退出登录
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'updatePassword',
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { UserUpdatePasswordRequest } from '@/api/user/mine';
|
||||
import type { FieldRule } from '@arco-design/web-vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { md5 } from '@/utils';
|
||||
import useUser from '@/hooks/user';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { useDictStore } from '@/store';
|
||||
import { dictKeys, updatePasswordReasonKey } from './types/const';
|
||||
import { updateCurrentUserPassword } from '@/api/user/mine';
|
||||
|
||||
const { logout } = useUser();
|
||||
const { loading, setLoading } = useLoading();
|
||||
|
||||
const rules = {
|
||||
beforePassword: [{
|
||||
required: true,
|
||||
message: '请输入原始密码'
|
||||
}],
|
||||
password: [{
|
||||
required: true,
|
||||
message: '请输入新密码'
|
||||
}, {
|
||||
minLength: 8,
|
||||
maxLength: 32,
|
||||
message: '新密码长度需要在 8-32 位之间'
|
||||
}, {
|
||||
validator: (value, cb) => {
|
||||
if (formModel.value.beforePassword === value) {
|
||||
cb('新密码不能和原始密码相同');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}],
|
||||
checkPassword: [{
|
||||
required: true,
|
||||
message: '请再次输入新密码'
|
||||
}, {
|
||||
validator: (value, cb) => {
|
||||
if (formModel.value.password !== value) {
|
||||
cb('两次输入的密码不一致');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}],
|
||||
} as Record<string, FieldRule | FieldRule[]>;
|
||||
|
||||
const reason = ref();
|
||||
const formRef = ref();
|
||||
const formModel = ref<UserUpdatePasswordRequest>({});
|
||||
|
||||
// 确认修改
|
||||
const doUpdate = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
// 验证参数
|
||||
const error = await formRef.value.validate();
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
// 修改密码
|
||||
await updateCurrentUserPassword({
|
||||
beforePassword: md5(formModel.value.beforePassword as string),
|
||||
password: md5(formModel.value.password as string)
|
||||
});
|
||||
// 退出登录
|
||||
await logout('修改成功');
|
||||
} catch (e) {
|
||||
return;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
const reasonKey = useRoute().query?.reason;
|
||||
if (reasonKey) {
|
||||
const { loadKeys, getDictValue } = useDictStore();
|
||||
// 加载字典值
|
||||
await loadKeys(dictKeys);
|
||||
// 获取原因
|
||||
reason.value = getDictValue(updatePasswordReasonKey, reasonKey);
|
||||
} else {
|
||||
reason.value = '修改密码';
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.content {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -96px;
|
||||
margin-top: -168px;
|
||||
text-align: center;
|
||||
|
||||
.reason {
|
||||
text-align: left;
|
||||
margin-bottom: 16px;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
font-size: 16px;
|
||||
color: var(--color-text-2);
|
||||
}
|
||||
|
||||
.action {
|
||||
width: 148px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,5 @@
|
||||
// 修改密码原因
|
||||
export const updatePasswordReasonKey = 'updatePasswordReason';
|
||||
|
||||
// 加载的字典值
|
||||
export const dictKeys = [updatePasswordReasonKey];
|
||||
Reference in New Issue
Block a user