feat(菜单模块):添加菜单模块

- 优化登录流程
- 添加服务器端获取菜单
This commit is contained in:
vertoryao 2024-12-25 17:03:45 +08:00
parent 6b25c03d37
commit 586bd23203
9 changed files with 117 additions and 120 deletions

View File

@ -177,5 +177,5 @@ export function getUserDetail(id: number) {
} }
export function getMenuList() { export function getMenuList() {
return axios.post<RouteRecordNormalized[]>('/api/user/menu'); return axios.get<RouteRecordNormalized[]>('/api/rest/user/menu');
} }

View File

@ -1,6 +1,6 @@
<template> <template>
<a-spin style="display: block" :loading="loading"> <a-spin style="display: block" :loading="loading">
<a-tabs v-model:activeKey="messageType" type="rounded" destroy-on-hide> <a-tabs v-model:active-key="messageType" type="rounded" destroy-on-hide>
<a-tab-pane v-for="item in tabList" :key="item.key"> <a-tab-pane v-for="item in tabList" :key="item.key">
<template #title> <template #title>
<span> {{ item.title }}{{ formatUnreadLength(item.key) }} </span> <span> {{ item.title }}{{ formatUnreadLength(item.key) }} </span>

View File

@ -12,6 +12,6 @@
"globalSettings": false, "globalSettings": false,
"device": "desktop", "device": "desktop",
"tabBar": false, "tabBar": false,
"menuFromServer": false, "menuFromServer": true,
"serverMenu": [] "serverMenu": []
} }

View File

@ -29,7 +29,7 @@ const SYSTEM: AppRouteRecordRaw = {
meta: { meta: {
locale: 'menu.system.role', locale: 'menu.system.role',
requiresAuth: true, requiresAuth: true,
permissions: ['admin'], permissions: ['*'],
}, },
}, },
{ {
@ -39,7 +39,7 @@ const SYSTEM: AppRouteRecordRaw = {
meta: { meta: {
locale: 'menu.system.dept', locale: 'menu.system.dept',
requiresAuth: true, requiresAuth: true,
permissions: ['admin'], permissions: ['*'],
}, },
}, },
{ {
@ -49,7 +49,7 @@ const SYSTEM: AppRouteRecordRaw = {
meta: { meta: {
locale: 'menu.system.user', locale: 'menu.system.user',
requiresAuth: true, requiresAuth: true,
permissions: ['admin'], permissions: ['*'],
}, },
}, },
{ {
@ -59,7 +59,7 @@ const SYSTEM: AppRouteRecordRaw = {
meta: { meta: {
locale: '权限管理', locale: '权限管理',
requiresAuth: true, requiresAuth: true,
permissions: ['admin'], permissions: ['*'],
}, },
}, },
], ],

View File

@ -13,6 +13,7 @@ export interface UserState {
id?: number; id?: number;
role?: RoleRecord; role?: RoleRecord;
roles?: RoleRecord[]; roles?: RoleRecord[];
permissions?: string[] | '' | '*' | 'admin' | 'user' | 'auditor'; // permissions?: string[] | '' | '*' | 'admin' | 'user' | 'auditor';
permissions?: string[];
authorities?: string[]; authorities?: string[];
} }

View File

@ -1,68 +1,68 @@
// 新建 @/utils/excel.ts // // 新建 @/utils/excel.ts
//
import saveAs from 'file-saver'; // https://www.npmjs.com/package/file-saver // import saveAs from 'file-saver'; // https://www.npmjs.com/package/file-saver
import ExcelJS from 'exceljs'; // https://github.com/exceljs/exceljs/blob/master/README_zh.md // import ExcelJS from 'exceljs'; // https://github.com/exceljs/exceljs/blob/master/README_zh.md
import * as XLSX from 'xlsx'; // https://www.npmjs.com/package/xlsx // import * as XLSX from 'xlsx'; // https://www.npmjs.com/package/xlsx
import { Message } from '@arco-design/web-vue'; // https://arco.design/vue/component/message // import { Message } from '@arco-design/web-vue'; // https://arco.design/vue/component/message
import { FileItem } from '@arco-design/web-vue/es/upload/interfaces'; // arco类型 // import { FileItem } from '@arco-design/web-vue/es/upload/interfaces'; // arco类型
//
export interface DownloadExcelPrams { // export interface DownloadExcelPrams {
columns: { title: string; key: string }[]; // columns: { title: string; key: string }[];
rows: object[]; // rows: object[];
name: string; // name: string;
} // }
//
// 导出下载文件 // // 导出下载文件
export function downloadExcel({ // export function downloadExcel({
columns, // columns,
rows, // rows,
name = '未命名文件', // name = '未命名文件',
}: DownloadExcelPrams) { // }: DownloadExcelPrams) {
const workbook = new ExcelJS.Workbook(); // const workbook = new ExcelJS.Workbook();
workbook.creator = 'Start-front'; // workbook.creator = 'Start-front';
workbook.lastModifiedBy = 'Start-front'; // workbook.lastModifiedBy = 'Start-front';
workbook.created = new Date(1985, 8, 30); // workbook.created = new Date(1985, 8, 30);
workbook.modified = new Date(); // workbook.modified = new Date();
workbook.lastPrinted = new Date(2016, 9, 27); // workbook.lastPrinted = new Date(2016, 9, 27);
//
// 将工作簿添加一个sheet页sheet1 // // 将工作簿添加一个sheet页sheet1
const sheet1 = workbook.addWorksheet(name); // const sheet1 = workbook.addWorksheet(name);
// 表头数据添加 // // 表头数据添加
sheet1.columns = columns.map((item) => ({ // sheet1.columns = columns.map((item) => ({
header: item.title, // header: item.title,
key: item.key, // key: item.key,
width: 20, // width: 20,
})); // }));
// 表格内容添加 // // 表格内容添加
rows.map((item) => sheet1.addRow(item)); // rows.map((item) => sheet1.addRow(item));
workbook.xlsx.writeBuffer().then((buffer) => { // workbook.xlsx.writeBuffer().then((buffer) => {
saveAs( // saveAs(
new Blob([buffer], { type: 'application/octet-stream' }), // new Blob([buffer], { type: 'application/octet-stream' }),
`${name}.xlsx` // `${name}.xlsx`
); // );
}); // });
} // }
//
// 读取文件为json格式 // // 读取文件为json格式
export function readExcle(fileItem: FileItem) { // export function readExcle(fileItem: FileItem) {
return new Promise((resove, reject) => { // return new Promise((resove, reject) => {
try { // try {
let workbook: XLSX.Sheet; // let workbook: XLSX.Sheet;
const reader = new FileReader(); // const reader = new FileReader();
reader.readAsBinaryString(fileItem.file as File); // 发起异步请求 // reader.readAsBinaryString(fileItem.file as File); // 发起异步请求
reader.onload = function (ev) { // reader.onload = function (ev) {
const data = ev.target?.result; // const data = ev.target?.result;
workbook = XLSX.read(data, { type: 'binary' }); // workbook = XLSX.read(data, { type: 'binary' });
const sheetNames = workbook.SheetNames; // 工作表名称集合 // const sheetNames = workbook.SheetNames; // 工作表名称集合
sheetNames.forEach((name: string) => { // sheetNames.forEach((name: string) => {
const worksheet = workbook.Sheets[name]; // 只能通过工作表名称来获取指定工作表 // const worksheet = workbook.Sheets[name]; // 只能通过工作表名称来获取指定工作表
const jsonres = XLSX.utils.sheet_to_json(worksheet); // const jsonres = XLSX.utils.sheet_to_json(worksheet);
resove(jsonres); // resove(jsonres);
}); // });
}; // onload // }; // onload
} catch (error) { // } catch (error) {
Message.error('读取失败,请选择正确文件'); // Message.error('读取失败,请选择正确文件');
reject(error); // reject(error);
} // }
}); // });
} // }

View File

@ -226,7 +226,7 @@
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface'; import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
import { useUserStore } from '@/store'; import { useUserStore } from '@/store';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import { downloadExcel, DownloadExcelPrams } from '@/utils/excel'; // import { downloadExcel, DownloadExcelPrams } from '@/utils/excel';
import useTableOption from '@/hooks/table-option'; import useTableOption from '@/hooks/table-option';
import UserEdit from './components/user-edit.vue'; import UserEdit from './components/user-edit.vue';
@ -348,22 +348,22 @@
}; };
// //
const generateExcel = () => { // const generateExcel = () => {
const param: DownloadExcelPrams = { // const param: DownloadExcelPrams = {
columns: [ // columns: [
{ title: '用户名', key: 'username' }, // { title: '', key: 'username' },
{ title: '昵称', key: 'nickName' }, // { title: '', key: 'nickName' },
{ title: '电话号码', key: 'phone' }, // { title: '', key: 'phone' },
{ title: '部门Id', key: 'deptId' }, // { title: 'Id', key: 'deptId' },
{ title: '角色Id', key: 'roleId' }, // { title: 'Id', key: 'roleId' },
{ title: 'email', key: 'email' }, // { title: 'email', key: 'email' },
{ title: '启用状态', key: 'enabled' }, // { title: '', key: 'enabled' },
], // ],
rows: renderData.value, // rows: renderData.value,
name: '用户表格', // name: '',
}; // };
downloadExcel(param); // downloadExcel(param);
}; // };
// //
const search = () => { const search = () => {

View File

@ -55,7 +55,6 @@
import { FormInstance } from '@arco-design/web-vue/es/form'; import { FormInstance } from '@arco-design/web-vue/es/form';
import { PasswordReSetModel, resetPassword } from '@/api/user'; import { PasswordReSetModel, resetPassword } from '@/api/user';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import useUser from '@/hooks/user';
import router from '@/router'; import router from '@/router';
import { clearToken } from '@/utils/auth'; import { clearToken } from '@/utils/auth';
@ -78,8 +77,6 @@
} }
}; };
const user = useUser();
const validate = async () => { const validate = async () => {
const vali = await formRef.value?.validate(); const vali = await formRef.value?.validate();
if (!vali) { if (!vali) {

View File

@ -2,12 +2,12 @@
<a-card :bordered="false"> <a-card :bordered="false">
<a-space :size="54"> <a-space :size="54">
<a-upload <a-upload
:custom-request="Onchange" :custom-request="() => {}"
list-type="picture-card" list-type="picture-card"
:file-list="fileList" :file-list="fileList"
:show-upload-button="true" :show-upload-button="true"
:show-file-list="false" :show-file-list="false"
@change="Onchange" @change="() => {}"
> >
<template #upload-button> <template #upload-button>
<a-avatar :size="100" class="info-avatar"> <a-avatar :size="100" class="info-avatar">
@ -49,7 +49,7 @@
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { ref } from 'vue'; import { ref } from 'vue';
import type { FileItem } from '@arco-design/web-vue/es/upload/interfaces'; import type { FileItem } from '@arco-design/web-vue/es/upload/interfaces';
import { useUserStore, useTicketStore } from '@/store'; import { useUserStore } from '@/store';
import userIcon from '@/assets/images/user-circle.png'; import userIcon from '@/assets/images/user-circle.png';
import type { DescData } from '@arco-design/web-vue/es/descriptions/interface'; import type { DescData } from '@arco-design/web-vue/es/descriptions/interface';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
@ -58,7 +58,6 @@
const userStore = useUserStore(); const userStore = useUserStore();
const { t } = useI18n(); const { t } = useI18n();
const ticketStore = useTicketStore();
const file = { const file = {
uid: '-2', uid: '-2',
@ -86,26 +85,26 @@
const fileList = ref<FileItem[]>([file]); const fileList = ref<FileItem[]>([file]);
const Onchange = async (option: any) => { // const Onchange = async (option: any) => {
const FormDatas = new FormData(); // const FormDatas = new FormData();
FormDatas.append('file', option.fileItem.file); // FormDatas.append('file', option.fileItem.file);
const res = await ticketStore.uploadFile(FormDatas); // const res = await ticketStore.uploadFile(FormDatas);
if (res.status === 200) { // if (res.status === 200) {
Message.success({ // Message.success({
content: t('upload.sucess'), // content: t('upload.sucess'),
duration: 3 * 1000, // duration: 3 * 1000,
}); // });
res.data.name = res.data.fileName; // res.data.name = res.data.fileName;
fileList.value.push(res.data); // fileList.value.push(res.data);
await selfUpdate({ avatar: res.data.id }); // await selfUpdate({ avatar: res.data.id });
await userStore.info(); // await userStore.info();
} else { // } else {
Message.error({ // Message.error({
content: t('upload.fail'), // content: t('upload.fail'),
duration: 3 * 1000, // duration: 3 * 1000,
}); // });
} // }
}; // };
</script> </script>
<style scoped lang="less"> <style scoped lang="less">