refactor: 代码重构优化(VueUse使用)
This commit is contained in:
parent
ecdbb7027f
commit
f33b8d352d
|
|
@ -1,13 +1,13 @@
|
|||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { ILoginData, TokenResult, VerifyCode } from './types';
|
||||
import { LoginData, LoginResult } from './types';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param data {LoginForm}
|
||||
* @param data {LoginData}
|
||||
* @returns
|
||||
*/
|
||||
export function loginApi(data: ILoginData): AxiosPromise<TokenResult> {
|
||||
export function loginApi(data: LoginData): AxiosPromise<LoginResult> {
|
||||
return request({
|
||||
url: '/api/v1/auth/login',
|
||||
method: 'post',
|
||||
|
|
@ -24,13 +24,3 @@ export function logoutApi() {
|
|||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片验证码
|
||||
*/
|
||||
export function getCaptcha(): AxiosPromise<VerifyCode> {
|
||||
return request({
|
||||
url: '/captcha?t=' + new Date().getTime().toString(),
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,15 @@
|
|||
/**
|
||||
* 登录数据类型
|
||||
* 登录请求
|
||||
*/
|
||||
export interface ILoginData {
|
||||
export interface LoginData {
|
||||
username: string;
|
||||
password: string;
|
||||
/**
|
||||
* 验证码Code
|
||||
*/
|
||||
//verifyCode: string;
|
||||
/**
|
||||
* 验证码Code服务端缓存key(UUID)
|
||||
*/
|
||||
// verifyCodeKey: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token响应类型
|
||||
* 登录详情
|
||||
*/
|
||||
export interface TokenResult {
|
||||
export interface LoginResult {
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
expires: number;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { UserForm, UserInfo, UserPageResult, UserQuery } from './types';
|
||||
import { UserForm, UserInfo, UserPageVO, UserQuery } from './types';
|
||||
|
||||
/**
|
||||
* 登录成功后获取用户信息(昵称、头像、权限集合和角色集合)
|
||||
|
|
@ -19,7 +19,7 @@ export function getUserInfo(): AxiosPromise<UserInfo> {
|
|||
*/
|
||||
export function listUserPages(
|
||||
queryParams: UserQuery
|
||||
): AxiosPromise<UserPageResult> {
|
||||
): AxiosPromise<PageResult<UserPageVO[]>> {
|
||||
return request({
|
||||
url: '/api/v1/users/pages',
|
||||
method: 'get',
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export interface UserInfo {
|
|||
}
|
||||
|
||||
/**
|
||||
* 用户查询参数
|
||||
* 用户查询对象类型
|
||||
*/
|
||||
export interface UserQuery extends PageQuery {
|
||||
keywords: string;
|
||||
|
|
@ -18,48 +18,102 @@ export interface UserQuery extends PageQuery {
|
|||
}
|
||||
|
||||
/**
|
||||
* 用户分页列表项声明
|
||||
* 用户分页对象
|
||||
*/
|
||||
export interface UserType {
|
||||
id: string;
|
||||
username: string;
|
||||
nickname: string;
|
||||
mobile: string;
|
||||
gender: number;
|
||||
avatar: string;
|
||||
email: string;
|
||||
status: number;
|
||||
deptName: string;
|
||||
roleNames: string;
|
||||
createTime: string;
|
||||
export interface UserPageVO {
|
||||
/**
|
||||
* 用户头像地址
|
||||
*/
|
||||
avatar?: string;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
createTime?: Date;
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
deptName?: string;
|
||||
/**
|
||||
* 用户邮箱
|
||||
*/
|
||||
email?: string;
|
||||
/**
|
||||
* 性别
|
||||
*/
|
||||
genderLabel?: string;
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
id?: number;
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
mobile?: string;
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
nickname?: string;
|
||||
/**
|
||||
* 角色名称,多个使用英文逗号(,)分割
|
||||
*/
|
||||
roleNames?: string;
|
||||
/**
|
||||
* 用户状态(1:启用;0:禁用)
|
||||
*/
|
||||
status?: number;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
username?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户分页项类型声明
|
||||
*/
|
||||
export type UserPageResult = PageResult<UserType[]>;
|
||||
|
||||
/**
|
||||
* 用户表单类型声明
|
||||
* 用户表单类型
|
||||
*/
|
||||
export interface UserForm {
|
||||
id: number | undefined;
|
||||
deptId: number;
|
||||
username: string;
|
||||
nickname: string;
|
||||
password: string;
|
||||
mobile: string;
|
||||
email: string;
|
||||
gender: number;
|
||||
status: number;
|
||||
remark: string;
|
||||
roleIds: number[];
|
||||
/**
|
||||
* 用户头像
|
||||
*/
|
||||
avatar?: string;
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
deptId?: number;
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
email?: string;
|
||||
/**
|
||||
* 性别
|
||||
*/
|
||||
gender?: number;
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
id?: number;
|
||||
mobile?: string;
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
nickname?: string;
|
||||
/**
|
||||
* 角色ID集合
|
||||
*/
|
||||
roleIds?: number[];
|
||||
/**
|
||||
* 用户状态(1:正常;0:禁用)
|
||||
*/
|
||||
status?: number;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
username?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户导入表单类型声明
|
||||
* 用户导入视图对象类型
|
||||
*/
|
||||
export interface UserImportData {
|
||||
export interface UserImportVO {
|
||||
deptId: number;
|
||||
roleIds: number[];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
// 自定义国际化配置
|
||||
import { createI18n } from 'vue-i18n';
|
||||
import { localStorage } from '@/utils/localStorage';
|
||||
|
||||
// 本地语言包
|
||||
import enLocale from './en';
|
||||
|
|
@ -22,7 +21,7 @@ const messages = {
|
|||
*/
|
||||
export const getLanguage = () => {
|
||||
// 本地缓存获取
|
||||
let language = localStorage.get('language');
|
||||
let language = localStorage.getItem('language');
|
||||
if (language) {
|
||||
return language;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { isExternal } from '@/utils/validate';
|
||||
import { isExternal } from '@/utils/index';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import path from 'path-browserify';
|
||||
import { isExternal } from '@/utils/validate';
|
||||
import { isExternal } from '@/utils/index';
|
||||
import AppLink from './Link.vue';
|
||||
|
||||
import { translateRouteTitleI18n } from '@/utils/i18n';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import router from '@/router';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { usePermissionStoreHook } from '@/store/modules/permission';
|
||||
|
||||
|
|
@ -14,11 +13,10 @@ const whiteList = ['/login'];
|
|||
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
NProgress.start();
|
||||
|
||||
const hasToken = getToken();
|
||||
const hasToken = localStorage.getItem('accessToken');
|
||||
if (hasToken) {
|
||||
if (to.path === '/login') {
|
||||
//
|
||||
// 登录成功,跳转到首页
|
||||
next({ path: '/' });
|
||||
} else {
|
||||
const userStore = useUserStoreHook();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
|
||||
import { usePermissionStoreHook } from '@/store/modules/permission';
|
||||
|
||||
export const Layout = () => import('@/layout/index.vue');
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,44 @@
|
|||
// 系统设置
|
||||
interface DefaultSettings {
|
||||
/**
|
||||
* 系统title
|
||||
*/
|
||||
title: string;
|
||||
|
||||
/**
|
||||
* 是否显示设置
|
||||
*/
|
||||
showSettings: boolean;
|
||||
/**
|
||||
* 是否显示多标签导航
|
||||
*/
|
||||
tagsView: boolean;
|
||||
/**
|
||||
*是否固定头部
|
||||
*/
|
||||
fixedHeader: boolean;
|
||||
/**
|
||||
* 是否显示侧边栏Logo
|
||||
*/
|
||||
sidebarLogo: boolean;
|
||||
errorLog: string;
|
||||
/**
|
||||
* 导航栏布局
|
||||
*/
|
||||
layout: string;
|
||||
/**
|
||||
* 主题模式
|
||||
*/
|
||||
theme: string;
|
||||
|
||||
/**
|
||||
* 布局大小
|
||||
*/
|
||||
size: string;
|
||||
|
||||
/**
|
||||
* 语言
|
||||
*/
|
||||
language: string;
|
||||
}
|
||||
|
||||
const defaultSettings: DefaultSettings = {
|
||||
|
|
@ -15,9 +47,10 @@ const defaultSettings: DefaultSettings = {
|
|||
tagsView: true,
|
||||
fixedHeader: false,
|
||||
sidebarLogo: true,
|
||||
errorLog: 'production',
|
||||
layout: 'left',
|
||||
theme: 'dark'
|
||||
theme: 'dark', // dark | light
|
||||
size: 'default', // default |large |small
|
||||
language: 'zh-cn' // zh-cn| en
|
||||
};
|
||||
|
||||
export default defaultSettings;
|
||||
|
|
|
|||
|
|
@ -1,38 +1,21 @@
|
|||
import {
|
||||
getSidebarStatus,
|
||||
setSidebarStatus,
|
||||
getSize,
|
||||
setSize,
|
||||
setLanguage
|
||||
} from '@/utils/localStorage';
|
||||
import { defineStore } from 'pinia';
|
||||
import { getLanguage } from '@/lang/index';
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import { useStorage } from '@vueuse/core';
|
||||
import defaultSettings from '@/settings';
|
||||
|
||||
// Element Plus 语言包
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn';
|
||||
import en from 'element-plus/es/locale/lang/en';
|
||||
|
||||
export enum DeviceType {
|
||||
mobile,
|
||||
desktop
|
||||
}
|
||||
|
||||
export enum SizeType {
|
||||
default,
|
||||
large,
|
||||
small
|
||||
}
|
||||
|
||||
// setup
|
||||
export const useAppStore = defineStore('app', () => {
|
||||
// state
|
||||
const device = useStorage<string>('device', 'desktop');
|
||||
const size = ref(getSize() || 'default');
|
||||
const language = ref(getLanguage());
|
||||
const device = useStorage('device', 'desktop');
|
||||
const size = useStorage('size', defaultSettings.size);
|
||||
const language = useStorage('language', defaultSettings.language);
|
||||
|
||||
const sidebarStatus = useStorage('sidebarStatus', 'closed');
|
||||
const sidebar = reactive({
|
||||
opened: getSidebarStatus() !== 'closed',
|
||||
opened: sidebarStatus.value !== 'closed',
|
||||
withoutAnimation: false
|
||||
});
|
||||
|
||||
|
|
@ -49,22 +32,22 @@ export const useAppStore = defineStore('app', () => {
|
|||
sidebar.opened = !sidebar.opened;
|
||||
sidebar.withoutAnimation = withoutAnimation;
|
||||
if (sidebar.opened) {
|
||||
setSidebarStatus('opened');
|
||||
sidebarStatus.value = 'opened';
|
||||
} else {
|
||||
setSidebarStatus('closed');
|
||||
sidebarStatus.value = 'closed';
|
||||
}
|
||||
}
|
||||
|
||||
function closeSideBar(withoutAnimation: boolean) {
|
||||
sidebar.opened = false;
|
||||
sidebar.withoutAnimation = withoutAnimation;
|
||||
setSidebarStatus('closed');
|
||||
sidebarStatus.value = 'closed';
|
||||
}
|
||||
|
||||
function openSideBar(withoutAnimation: boolean) {
|
||||
sidebar.opened = true;
|
||||
sidebar.withoutAnimation = withoutAnimation;
|
||||
setSidebarStatus('opened');
|
||||
sidebarStatus.value = 'opened';
|
||||
}
|
||||
|
||||
function toggleDevice(val: string) {
|
||||
|
|
@ -73,12 +56,10 @@ export const useAppStore = defineStore('app', () => {
|
|||
|
||||
function changeSize(val: string) {
|
||||
size.value = val;
|
||||
setSize(val);
|
||||
}
|
||||
|
||||
function changeLanguage(val: string) {
|
||||
language.value = val;
|
||||
setLanguage(val);
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,32 +1,14 @@
|
|||
import { defineStore } from 'pinia';
|
||||
import defaultSettings from '../../settings';
|
||||
import { ref } from 'vue';
|
||||
import defaultSettings from '@/settings';
|
||||
import { useStorage } from '@vueuse/core';
|
||||
|
||||
/**
|
||||
* 主题类型
|
||||
*/
|
||||
export enum ThemeType {
|
||||
light,
|
||||
dark
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局类型
|
||||
*/
|
||||
export enum LayoutType {
|
||||
left,
|
||||
top,
|
||||
mix
|
||||
}
|
||||
|
||||
export const useSettingsStore = defineStore('setting', () => {
|
||||
// state
|
||||
const showSettings = ref<boolean>(defaultSettings.showSettings);
|
||||
const tagsView = useStorage<boolean>('tagsView', defaultSettings.tagsView);
|
||||
|
||||
const showSettings = ref<boolean>(defaultSettings.showSettings);
|
||||
const fixedHeader = ref<boolean>(defaultSettings.fixedHeader);
|
||||
const sidebarLogo = ref<boolean>(defaultSettings.sidebarLogo);
|
||||
const theme = useStorage('vueuse-color-scheme', defaultSettings.theme);
|
||||
|
||||
const layout = useStorage<string>('layout', defaultSettings.layout);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,37 +1,35 @@
|
|||
import { defineStore } from 'pinia';
|
||||
|
||||
import { getToken, setToken, removeToken } from '@/utils/auth';
|
||||
import { loginApi, logoutApi } from '@/api/auth';
|
||||
import { getUserInfo } from '@/api/user';
|
||||
import { resetRouter } from '@/router';
|
||||
import { store } from '@/store';
|
||||
import { ILoginData } from '@/api/auth/types';
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { LoginData } from '@/api/auth/types';
|
||||
import { UserInfo } from '@/api/user/types';
|
||||
|
||||
import { useStorage } from '@vueuse/core';
|
||||
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
// state
|
||||
const token = ref<string>(getToken() || '');
|
||||
const token = useStorage('accessToken', '');
|
||||
const nickname = ref<string>('');
|
||||
const avatar = ref<string>('');
|
||||
const roles = ref<Array<string>>([]); // 用户角色编码集合 → 判断路由权限
|
||||
const perms = ref<Array<string>>([]); // 用户权限编码集合 → 判断按钮权限
|
||||
|
||||
// actions
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
* @param loginData
|
||||
* @returns
|
||||
*/
|
||||
function login(loginData: ILoginData) {
|
||||
function login(loginData: LoginData) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
loginApi(loginData)
|
||||
.then(response => {
|
||||
const { accessToken } = response.data;
|
||||
token.value = accessToken;
|
||||
setToken(accessToken);
|
||||
resolve();
|
||||
})
|
||||
.catch(error => {
|
||||
|
|
@ -80,7 +78,6 @@ export const useUserStore = defineStore('user', () => {
|
|||
|
||||
// 重置
|
||||
function resetToken() {
|
||||
removeToken();
|
||||
token.value = '';
|
||||
nickname.value = '';
|
||||
avatar.value = '';
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
/**
|
||||
* window.localStorage 浏览器永久缓存
|
||||
*/
|
||||
export const localStorage = {
|
||||
// 设置永久缓存
|
||||
set(key: string, val: any) {
|
||||
window.localStorage.setItem(key, JSON.stringify(val));
|
||||
},
|
||||
// 获取永久缓存
|
||||
get(key: string) {
|
||||
const json: any = window.localStorage.getItem(key);
|
||||
return JSON.parse(json);
|
||||
},
|
||||
// 移除永久缓存
|
||||
remove(key: string) {
|
||||
window.localStorage.removeItem(key);
|
||||
},
|
||||
// 移除全部永久缓存
|
||||
clear() {
|
||||
window.localStorage.clear();
|
||||
}
|
||||
};
|
||||
|
||||
// 侧边栏状态(显示/隐藏)
|
||||
const SidebarStatusKey = 'sidebarStatus';
|
||||
export function getSidebarStatus() {
|
||||
return localStorage.get(SidebarStatusKey);
|
||||
}
|
||||
|
||||
export function setSidebarStatus(sidebarStatus: string) {
|
||||
localStorage.set(SidebarStatusKey, sidebarStatus);
|
||||
}
|
||||
// 布局大小
|
||||
const SizeKey = 'size';
|
||||
|
||||
export function getSize() {
|
||||
return localStorage.get(SizeKey);
|
||||
}
|
||||
|
||||
export function setSize(size: string) {
|
||||
localStorage.set(SizeKey, size);
|
||||
}
|
||||
|
||||
// 语言
|
||||
const LanguageKey = 'language';
|
||||
|
||||
export function getLanguage() {
|
||||
return localStorage.get(LanguageKey);
|
||||
}
|
||||
|
||||
export function setLanguage(language: string) {
|
||||
localStorage.set(LanguageKey, language);
|
||||
}
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
import axios, { InternalAxiosRequestConfig, AxiosResponse } from 'axios';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
|
||||
// 创建 axios 实例
|
||||
|
|
@ -20,7 +18,7 @@ service.interceptors.request.use(
|
|||
}
|
||||
const user = useUserStoreHook();
|
||||
if (user.token) {
|
||||
config.headers.Authorization = getToken();
|
||||
config.headers.Authorization = localStorage.getItem('accessToken');
|
||||
}
|
||||
return config;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ import {
|
|||
} from '@element-plus/icons-vue';
|
||||
import {
|
||||
UserForm,
|
||||
UserImportData,
|
||||
UserImportVO,
|
||||
UserQuery,
|
||||
UserType
|
||||
UserPageVO
|
||||
} from '@/api/user/types';
|
||||
|
||||
const deptTreeRef = ref(ElTree); // 部门树
|
||||
|
|
@ -65,7 +65,7 @@ const state = reactive({
|
|||
ids: [] as number[],
|
||||
// 总条数
|
||||
total: 0,
|
||||
userList: [] as UserType[],
|
||||
userList: [] as UserPageVO[],
|
||||
dialog: {
|
||||
visible: false
|
||||
} as DialogType,
|
||||
|
|
@ -110,7 +110,7 @@ const state = reactive({
|
|||
title: '用户导入',
|
||||
visible: false
|
||||
} as DialogType,
|
||||
importFormData: {} as UserImportData,
|
||||
importFormData: {} as UserImportVO,
|
||||
excelFile: undefined as any,
|
||||
excelFilelist: [] as File[]
|
||||
});
|
||||
|
|
@ -396,7 +396,7 @@ function handleExcelChange(file: UploadFile) {
|
|||
/**
|
||||
* Excel文件上传
|
||||
*/
|
||||
function submitImportForm() {
|
||||
function uploadUser() {
|
||||
importFormRef.value.validate((valid: any) => {
|
||||
if (valid) {
|
||||
if (!state.excelFile) {
|
||||
|
|
@ -805,7 +805,7 @@ onMounted(() => {
|
|||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitImportForm">确 定</el-button>
|
||||
<el-button type="primary" @click="uploadUser">确 定</el-button>
|
||||
<el-button @click="closeImportDialog">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
Loading…
Reference in New Issue