chore: 🔨 合并冲突解决
This commit is contained in:
@@ -9,3 +9,4 @@ public
|
|||||||
|
|
||||||
src/assets
|
src/assets
|
||||||
stats.html
|
stats.html
|
||||||
|
pnpm-lock.yaml
|
||||||
|
|||||||
28
.prettierrc
28
.prettierrc
@@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
"arrowParens": "always",
|
|
||||||
"bracketSameLine": false,
|
|
||||||
"bracketSpacing": true,
|
|
||||||
"embeddedLanguageFormatting": "auto",
|
|
||||||
"htmlWhitespaceSensitivity": "ignore",
|
|
||||||
"insertPragma": false,
|
|
||||||
"jsxSingleQuote": false,
|
|
||||||
"printWidth": 100,
|
|
||||||
"proseWrap": "preserve",
|
|
||||||
"quoteProps": "as-needed",
|
|
||||||
"requirePragma": false,
|
|
||||||
"semi": true,
|
|
||||||
"singleQuote": false,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"trailingComma": "es5",
|
|
||||||
"useTabs": false,
|
|
||||||
"vueIndentScriptAndStyle": false,
|
|
||||||
"endOfLine": "auto",
|
|
||||||
"overrides": [
|
|
||||||
{
|
|
||||||
"files": "*.html",
|
|
||||||
"options": {
|
|
||||||
"parser": "html"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
41
.prettierrc.yaml
Normal file
41
.prettierrc.yaml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# 在单参数箭头函数中始终添加括号
|
||||||
|
arrowParens: "always"
|
||||||
|
# JSX 多行元素的闭合标签另起一行
|
||||||
|
bracketSameLine: false
|
||||||
|
# 对象字面量中的括号之间添加空格
|
||||||
|
bracketSpacing: true
|
||||||
|
# 自动格式化嵌入的代码(如 Markdown 和 HTML 内的代码)
|
||||||
|
embeddedLanguageFormatting: "auto"
|
||||||
|
# 忽略 HTML 空白敏感度,将空白视为非重要内容
|
||||||
|
htmlWhitespaceSensitivity: "ignore"
|
||||||
|
# 不插入 @prettier 的 pragma 注释
|
||||||
|
insertPragma: false
|
||||||
|
# 在 JSX 中使用双引号
|
||||||
|
jsxSingleQuote: false
|
||||||
|
# 每行代码的最大长度限制为 100 字符
|
||||||
|
printWidth: 100
|
||||||
|
# 在 Markdown 中保留原有的换行格式
|
||||||
|
proseWrap: "preserve"
|
||||||
|
# 仅在必要时添加对象属性的引号
|
||||||
|
quoteProps: "as-needed"
|
||||||
|
# 不要求文件开头插入 @prettier 的 pragma 注释
|
||||||
|
requirePragma: false
|
||||||
|
# 在语句末尾添加分号
|
||||||
|
semi: true
|
||||||
|
# 使用双引号而不是单引号
|
||||||
|
singleQuote: false
|
||||||
|
# 缩进使用 2 个空格
|
||||||
|
tabWidth: 2
|
||||||
|
# 在多行元素的末尾添加逗号(ES5 支持的对象、数组等)
|
||||||
|
trailingComma: "es5"
|
||||||
|
# 使用空格而不是制表符缩进
|
||||||
|
useTabs: false
|
||||||
|
# Vue 文件中的 <script> 和 <style> 不增加额外的缩进
|
||||||
|
vueIndentScriptAndStyle: false
|
||||||
|
# 根据系统自动检测换行符
|
||||||
|
endOfLine: "auto"
|
||||||
|
# 对 HTML 文件应用特定格式化规则
|
||||||
|
overrides:
|
||||||
|
- files: "*.html"
|
||||||
|
options:
|
||||||
|
parser: "html"
|
||||||
44
package.json
44
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vue3-element-admin",
|
"name": "vue3-element-admin",
|
||||||
"version": "2.18.5",
|
"version": "2.19.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -54,65 +54,65 @@
|
|||||||
"codemirror": "^5.65.18",
|
"codemirror": "^5.65.18",
|
||||||
"codemirror-editor-vue3": "^2.8.0",
|
"codemirror-editor-vue3": "^2.8.0",
|
||||||
"echarts": "^5.5.1",
|
"echarts": "^5.5.1",
|
||||||
"element-plus": "^2.8.5",
|
"element-plus": "^2.8.7",
|
||||||
"exceljs": "^4.4.0",
|
"exceljs": "^4.4.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"path-to-regexp": "^6.3.0",
|
"path-to-regexp": "^6.3.0",
|
||||||
"pinia": "^2.2.4",
|
"pinia": "^2.2.6",
|
||||||
"qs": "^6.13.0",
|
"qs": "^6.13.0",
|
||||||
"sortablejs": "^1.15.3",
|
"sortablejs": "^1.15.3",
|
||||||
"vue": "^3.5.11",
|
"vue": "^3.5.12",
|
||||||
"vue-i18n": "9.9.1",
|
"vue-i18n": "9.9.1",
|
||||||
"vue-router": "^4.4.5"
|
"vue-router": "^4.4.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^19.5.0",
|
"@commitlint/cli": "^19.5.0",
|
||||||
"@commitlint/config-conventional": "^19.5.0",
|
"@commitlint/config-conventional": "^19.5.0",
|
||||||
"@eslint/js": "^9.12.0",
|
"@eslint/js": "^9.14.0",
|
||||||
"@types/codemirror": "^5.60.15",
|
"@types/codemirror": "^5.60.15",
|
||||||
"@types/lodash": "^4.17.10",
|
"@types/lodash": "^4.17.13",
|
||||||
"@types/node": "^22.7.5",
|
"@types/node": "^22.9.0",
|
||||||
"@types/nprogress": "^0.2.3",
|
"@types/nprogress": "^0.2.3",
|
||||||
"@types/path-browserify": "^1.0.3",
|
"@types/path-browserify": "^1.0.3",
|
||||||
"@types/qs": "^6.9.16",
|
"@types/qs": "^6.9.17",
|
||||||
"@types/sortablejs": "^1.15.8",
|
"@types/sortablejs": "^1.15.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.8.1",
|
"@typescript-eslint/eslint-plugin": "^8.14.0",
|
||||||
"@typescript-eslint/parser": "^8.8.1",
|
"@typescript-eslint/parser": "^8.14.0",
|
||||||
"@vitejs/plugin-vue": "^5.1.4",
|
"@vitejs/plugin-vue": "^5.1.5",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"commitizen": "^4.3.1",
|
"commitizen": "^4.3.1",
|
||||||
"cz-git": "1.9.4",
|
"cz-git": "1.9.4",
|
||||||
"eslint": "^9.12.0",
|
"eslint": "^9.14.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"eslint-plugin-vue": "^9.29.0",
|
"eslint-plugin-vue": "^9.31.0",
|
||||||
"globals": "^15.11.0",
|
"globals": "^15.12.0",
|
||||||
"husky": "^9.1.6",
|
"husky": "^9.1.6",
|
||||||
"lint-staged": "^15.2.10",
|
"lint-staged": "^15.2.10",
|
||||||
"postcss": "^8.4.47",
|
"postcss": "^8.4.49",
|
||||||
"postcss-html": "^1.7.0",
|
"postcss-html": "^1.7.0",
|
||||||
"postcss-scss": "^4.0.9",
|
"postcss-scss": "^4.0.9",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"sass": "^1.79.5",
|
"sass": "^1.80.6",
|
||||||
"stylelint": "^16.9.0",
|
"stylelint": "^16.10.0",
|
||||||
"stylelint-config-html": "^1.1.0",
|
"stylelint-config-html": "^1.1.0",
|
||||||
"stylelint-config-recess-order": "^5.1.1",
|
"stylelint-config-recess-order": "^5.1.1",
|
||||||
"stylelint-config-recommended-scss": "^14.1.0",
|
"stylelint-config-recommended-scss": "^14.1.0",
|
||||||
"stylelint-config-recommended-vue": "^1.5.0",
|
"stylelint-config-recommended-vue": "^1.5.0",
|
||||||
"stylelint-config-standard": "^36.0.1",
|
"stylelint-config-standard": "^36.0.1",
|
||||||
"terser": "^5.34.1",
|
"terser": "^5.36.0",
|
||||||
"typescript": "5.5.4",
|
"typescript": "5.5.4",
|
||||||
"typescript-eslint": "^8.8.1",
|
"typescript-eslint": "^8.14.0",
|
||||||
"unocss": "^0.63.4",
|
"unocss": "^0.63.6",
|
||||||
"unplugin-auto-import": "^0.18.3",
|
"unplugin-auto-import": "^0.18.3",
|
||||||
"unplugin-vue-components": "^0.27.4",
|
"unplugin-vue-components": "^0.27.4",
|
||||||
"vite": "^5.4.8",
|
"vite": "^5.4.11",
|
||||||
"vite-plugin-mock-dev-server": "^1.8.0",
|
"vite-plugin-mock-dev-server": "^1.8.0",
|
||||||
"vite-plugin-svg-icons": "^2.0.1",
|
"vite-plugin-svg-icons": "^2.0.1",
|
||||||
"vue-eslint-parser": "^9.4.3",
|
"vue-eslint-parser": "^9.4.3",
|
||||||
"vue-tsc": "^2.1.6"
|
"vue-tsc": "^2.1.10"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0"
|
"node": ">=18.0.0"
|
||||||
|
|||||||
1232
pnpm-lock.yaml
generated
1232
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@ import request from "@/utils/request";
|
|||||||
const AUTH_BASE_URL = "/api/v1/auth";
|
const AUTH_BASE_URL = "/api/v1/auth";
|
||||||
|
|
||||||
const AuthAPI = {
|
const AuthAPI = {
|
||||||
/** 登录 接口*/
|
/** 登录接口*/
|
||||||
login(data: LoginData) {
|
login(data: LoginData) {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("username", data.username);
|
formData.append("username", data.username);
|
||||||
@@ -20,7 +20,19 @@ const AuthAPI = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/** 注销 接口*/
|
/** 刷新 token 接口*/
|
||||||
|
refreshToken(refreshToken: string) {
|
||||||
|
return request<any, LoginResult>({
|
||||||
|
url: `${AUTH_BASE_URL}/refresh-token`,
|
||||||
|
method: "post",
|
||||||
|
data: { refreshToken: refreshToken },
|
||||||
|
headers: {
|
||||||
|
Authorization: "no-auth",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 注销接口*/
|
||||||
logout() {
|
logout() {
|
||||||
return request({
|
return request({
|
||||||
url: `${AUTH_BASE_URL}/logout`,
|
url: `${AUTH_BASE_URL}/logout`,
|
||||||
@@ -28,7 +40,7 @@ const AuthAPI = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/** 获取验证码 接口*/
|
/** 获取验证码接口*/
|
||||||
getCaptcha() {
|
getCaptcha() {
|
||||||
return request<any, CaptchaResult>({
|
return request<any, CaptchaResult>({
|
||||||
url: `${AUTH_BASE_URL}/captcha`,
|
url: `${AUTH_BASE_URL}/captcha`,
|
||||||
@@ -53,14 +65,14 @@ export interface LoginData {
|
|||||||
|
|
||||||
/** 登录响应 */
|
/** 登录响应 */
|
||||||
export interface LoginResult {
|
export interface LoginResult {
|
||||||
/** 访问token */
|
/** 访问令牌 */
|
||||||
accessToken?: string;
|
accessToken: string;
|
||||||
/** 过期时间(单位:毫秒) */
|
/** 刷新令牌 */
|
||||||
expires?: number;
|
refreshToken: string;
|
||||||
/** 刷新token */
|
/** 令牌类型 */
|
||||||
refreshToken?: string;
|
tokenType: string;
|
||||||
/** token 类型 */
|
/** 过期时间(秒) */
|
||||||
tokenType?: string;
|
expiresIn: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 验证码响应 */
|
/** 验证码响应 */
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ const ConfigAPI = {
|
|||||||
|
|
||||||
refreshCache() {
|
refreshCache() {
|
||||||
return request({
|
return request({
|
||||||
url: `${CONFIG_BASE_URL}`,
|
url: `${CONFIG_BASE_URL}/refresh`,
|
||||||
method: "patch",
|
method: "PUT",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ const UserAPI = {
|
|||||||
url: `${USER_BASE_URL}/export`,
|
url: `${USER_BASE_URL}/export`,
|
||||||
method: "get",
|
method: "get",
|
||||||
params: queryParams,
|
params: queryParams,
|
||||||
responseType: "arraybuffer",
|
responseType: "blob",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,12 @@ export const enum ResultEnum {
|
|||||||
ERROR = "B0001",
|
ERROR = "B0001",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 令牌无效或过期
|
* 访问令牌无效或过期
|
||||||
*/
|
*/
|
||||||
TOKEN_INVALID = "A0230",
|
ACCESS_TOKEN_INVALID = "A0230",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新令牌无效或过期
|
||||||
|
*/
|
||||||
|
REFRESH_TOKEN_INVALID = "A0231",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
(hasOneShowingChild(item.children, item) &&
|
(hasOneShowingChild(item.children, item) &&
|
||||||
(!onlyOneChild.children || onlyOneChild.noShowingChildren) &&
|
(!onlyOneChild.children || onlyOneChild.noShowingChildren) &&
|
||||||
!item.meta?.alwaysShow) ||
|
!item.meta?.alwaysShow) ||
|
||||||
// 父节点即使配置了始终显示,但无子节点,也显示未叶子节点
|
// 父节点即使配置了始终显示,但无子节点,也显示为叶子节点
|
||||||
(item.meta?.alwaysShow && !item.children)
|
(item.meta?.alwaysShow && !item.children)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
@@ -33,11 +33,7 @@
|
|||||||
<!--【非叶子节点】显示含多个子节点的父菜单,或始终显示的单子节点 -->
|
<!--【非叶子节点】显示含多个子节点的父菜单,或始终显示的单子节点 -->
|
||||||
<el-sub-menu v-else :index="resolvePath(item.path)" teleported>
|
<el-sub-menu v-else :index="resolvePath(item.path)" teleported>
|
||||||
<template #title>
|
<template #title>
|
||||||
<SidebarMenuItemTitle
|
<SidebarMenuItemTitle v-if="item.meta" :icon="item.meta.icon" :title="item.meta.title" />
|
||||||
v-if="item.meta"
|
|
||||||
:icon="item.meta.icon"
|
|
||||||
:title="item.meta.title"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<SidebarMenuItem
|
<SidebarMenuItem
|
||||||
@@ -98,10 +94,7 @@ const onlyOneChild = ref();
|
|||||||
* @param parent 父级路由
|
* @param parent 父级路由
|
||||||
* @returns 是否仅有一个可见子节点
|
* @returns 是否仅有一个可见子节点
|
||||||
*/
|
*/
|
||||||
function hasOneShowingChild(
|
function hasOneShowingChild(children: RouteRecordRaw[] = [], parent: RouteRecordRaw) {
|
||||||
children: RouteRecordRaw[] = [],
|
|
||||||
parent: RouteRecordRaw
|
|
||||||
) {
|
|
||||||
// 过滤出可见子节点
|
// 过滤出可见子节点
|
||||||
const showingChildren = children.filter((route: RouteRecordRaw) => {
|
const showingChildren = children.filter((route: RouteRecordRaw) => {
|
||||||
if (!route.meta?.hidden) {
|
if (!route.meta?.hidden) {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import "virtual:svg-icons-register";
|
|||||||
|
|
||||||
// 样式
|
// 样式
|
||||||
import "element-plus/theme-chalk/dark/css-vars.css";
|
import "element-plus/theme-chalk/dark/css-vars.css";
|
||||||
|
// 暗黑模式自定义变量
|
||||||
|
import "@/styles/dark/css-vars.css";
|
||||||
import "@/styles/index.scss";
|
import "@/styles/index.scss";
|
||||||
import "uno.css";
|
import "uno.css";
|
||||||
import "animate.css";
|
import "animate.css";
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
import type {
|
import type { NavigationGuardNext, RouteLocationNormalized, RouteRecordRaw } from "vue-router";
|
||||||
NavigationGuardNext,
|
|
||||||
RouteLocationNormalized,
|
|
||||||
RouteRecordRaw,
|
|
||||||
} from "vue-router";
|
|
||||||
import NProgress from "@/utils/nprogress";
|
import NProgress from "@/utils/nprogress";
|
||||||
import { getToken } from "@/utils/auth";
|
import { getToken } from "@/utils/auth";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
@@ -22,15 +18,14 @@ export function setupPermission() {
|
|||||||
next({ path: "/" });
|
next({ path: "/" });
|
||||||
} else {
|
} else {
|
||||||
const permissionStore = usePermissionStore();
|
const permissionStore = usePermissionStore();
|
||||||
// 判断路由是否加载过
|
// 判断路由是否加载完成
|
||||||
if (permissionStore.isRoutesLoaded) {
|
if (permissionStore.isRoutesLoaded) {
|
||||||
if (to.matched.length === 0) {
|
if (to.matched.length === 0) {
|
||||||
// 路由未匹配,跳转到404
|
// 路由未匹配,跳转到404
|
||||||
next("/404");
|
next("/404");
|
||||||
} else {
|
} else {
|
||||||
// 动态设置页面标题
|
// 动态设置页面标题
|
||||||
const title =
|
const title = (to.params.title as string) || (to.query.title as string);
|
||||||
(to.params.title as string) || (to.query.title as string);
|
|
||||||
if (title) {
|
if (title) {
|
||||||
to.meta.title = title;
|
to.meta.title = title;
|
||||||
}
|
}
|
||||||
@@ -40,14 +35,12 @@ export function setupPermission() {
|
|||||||
try {
|
try {
|
||||||
// 生成动态路由
|
// 生成动态路由
|
||||||
const dynamicRoutes = await permissionStore.generateRoutes();
|
const dynamicRoutes = await permissionStore.generateRoutes();
|
||||||
dynamicRoutes.forEach((route: RouteRecordRaw) =>
|
dynamicRoutes.forEach((route: RouteRecordRaw) => router.addRoute(route));
|
||||||
router.addRoute(route)
|
next({ ...to, replace: true });
|
||||||
);
|
|
||||||
next({ ...to, replace: true }); // 添加动态路由后重新导航
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
// 路由加载失败,重置 token 并重定向到登录页
|
// 路由加载失败,重置 token 并重定向到登录页
|
||||||
await useUserStore().clearUserSession();
|
await useUserStore().clearUserData();
|
||||||
redirectToLogin(to, next);
|
redirectToLogin(to, next);
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
}
|
}
|
||||||
@@ -60,7 +53,7 @@ export function setupPermission() {
|
|||||||
} else {
|
} else {
|
||||||
// 不在白名单,重定向到登录页
|
// 不在白名单,重定向到登录页
|
||||||
redirectToLogin(to, next);
|
redirectToLogin(to, next);
|
||||||
NProgress.done(); // 关闭进度条
|
NProgress.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -72,10 +65,7 @@ export function setupPermission() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 重定向到登录页 */
|
/** 重定向到登录页 */
|
||||||
function redirectToLogin(
|
function redirectToLogin(to: RouteLocationNormalized, next: NavigationGuardNext) {
|
||||||
to: RouteLocationNormalized,
|
|
||||||
next: NavigationGuardNext
|
|
||||||
) {
|
|
||||||
const params = new URLSearchParams(to.query as Record<string, string>);
|
const params = new URLSearchParams(to.query as Record<string, string>);
|
||||||
const queryString = params.toString();
|
const queryString = params.toString();
|
||||||
const redirect = queryString ? `${to.path}?${queryString}` : to.path;
|
const redirect = queryString ? `${to.path}?${queryString}` : to.path;
|
||||||
@@ -83,10 +73,7 @@ function redirectToLogin(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 判断是否有权限 */
|
/** 判断是否有权限 */
|
||||||
export function hasAuth(
|
export function hasAuth(value: string | string[], type: "button" | "role" = "button") {
|
||||||
value: string | string[],
|
|
||||||
type: "button" | "role" = "button"
|
|
||||||
) {
|
|
||||||
const { roles, perms } = useUserStore().userInfo;
|
const { roles, perms } = useUserStore().userInfo;
|
||||||
|
|
||||||
// 超级管理员 拥有所有权限
|
// 超级管理员 拥有所有权限
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ const defaultSettings: AppSettings = {
|
|||||||
layout: LayoutEnum.LEFT,
|
layout: LayoutEnum.LEFT,
|
||||||
// 主题,根据操作系统的色彩方案自动选择
|
// 主题,根据操作系统的色彩方案自动选择
|
||||||
theme: mediaQueryList.matches ? ThemeEnum.DARK : ThemeEnum.LIGHT,
|
theme: mediaQueryList.matches ? ThemeEnum.DARK : ThemeEnum.LIGHT,
|
||||||
|
// 组件大小 default | medium | small | large
|
||||||
size: SizeEnum.DEFAULT,
|
size: SizeEnum.DEFAULT,
|
||||||
|
// 语言
|
||||||
language: LanguageEnum.ZH_CN,
|
language: LanguageEnum.ZH_CN,
|
||||||
// 主题颜色
|
// 主题颜色
|
||||||
themeColor: "#4080FF",
|
themeColor: "#4080FF",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useDictStoreHook } from "@/store/modules/dict";
|
|||||||
import AuthAPI, { type LoginData } from "@/api/auth";
|
import AuthAPI, { type LoginData } from "@/api/auth";
|
||||||
import UserAPI, { type UserInfo } from "@/api/system/user";
|
import UserAPI, { type UserInfo } from "@/api/system/user";
|
||||||
|
|
||||||
import { setToken, clearToken } from "@/utils/auth";
|
import { setToken, setRefreshToken, getRefreshToken, clearToken } from "@/utils/auth";
|
||||||
|
|
||||||
export const useUserStore = defineStore("user", () => {
|
export const useUserStore = defineStore("user", () => {
|
||||||
const userInfo = useStorage<UserInfo>("userInfo", {} as UserInfo);
|
const userInfo = useStorage<UserInfo>("userInfo", {} as UserInfo);
|
||||||
@@ -20,8 +20,9 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
AuthAPI.login(loginData)
|
AuthAPI.login(loginData)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
const { tokenType, accessToken } = data;
|
const { tokenType, accessToken, refreshToken } = data;
|
||||||
setToken(tokenType + " " + accessToken); // Bearer eyJhbGciOiJIUzI1NiJ9.xxx.xxx
|
setToken(tokenType + " " + accessToken); // Bearer eyJhbGciOiJIUzI1NiJ9.xxx.xxx
|
||||||
|
setRefreshToken(refreshToken);
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -59,7 +60,7 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
AuthAPI.logout()
|
AuthAPI.logout()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
clearUserSession();
|
clearUserData();
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -69,11 +70,31 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清理用户会话
|
* 刷新 token
|
||||||
|
*/
|
||||||
|
function refreshToken() {
|
||||||
|
const refreshToken = getRefreshToken();
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
AuthAPI.refreshToken(refreshToken)
|
||||||
|
.then((data) => {
|
||||||
|
const { tokenType, accessToken, refreshToken } = data;
|
||||||
|
setToken(tokenType + " " + accessToken);
|
||||||
|
setRefreshToken(refreshToken);
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(" refreshToken 刷新失败", error);
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理用户数据
|
||||||
*
|
*
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function clearUserSession() {
|
function clearUserData() {
|
||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve) => {
|
||||||
clearToken();
|
clearToken();
|
||||||
usePermissionStoreHook().resetRouter();
|
usePermissionStoreHook().resetRouter();
|
||||||
@@ -87,7 +108,8 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
getUserInfo,
|
getUserInfo,
|
||||||
login,
|
login,
|
||||||
logout,
|
logout,
|
||||||
clearUserSession,
|
clearUserData,
|
||||||
|
refreshToken,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
7
src/styles/dark/css-vars.css
Normal file
7
src/styles/dark/css-vars.css
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* 暗黑模式通过 CSS 自定义变量,官方链接:https://element-plus.org/zh-CN/guide/dark-mode.html#%E9%80%9A%E8%BF%87-css */
|
||||||
|
html.dark {
|
||||||
|
.el-table {
|
||||||
|
/* 自定义表格选中高亮时当前行的背景颜色 */
|
||||||
|
--el-table-current-row-bg-color: var(--el-fill-color-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,27 @@
|
|||||||
const TOKEN_KEY = "admin-token";
|
// 访问 token 缓存的 key
|
||||||
|
const ACCESS_TOKEN_KEY = "access_token";
|
||||||
|
// 刷新 token 缓存的 key
|
||||||
|
const REFRESH_TOKEN_KEY = "refresh_token";
|
||||||
|
|
||||||
function getToken(): string {
|
function getToken(): string {
|
||||||
return localStorage.getItem(TOKEN_KEY) || "";
|
return localStorage.getItem(ACCESS_TOKEN_KEY) || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function setToken(token: string) {
|
function setToken(token: string) {
|
||||||
return localStorage.setItem(TOKEN_KEY, token);
|
localStorage.setItem(ACCESS_TOKEN_KEY, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRefreshToken(): string {
|
||||||
|
return localStorage.getItem(REFRESH_TOKEN_KEY) || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function setRefreshToken(token: string) {
|
||||||
|
localStorage.setItem(REFRESH_TOKEN_KEY, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearToken() {
|
function clearToken() {
|
||||||
return localStorage.removeItem(TOKEN_KEY);
|
localStorage.removeItem(ACCESS_TOKEN_KEY);
|
||||||
|
localStorage.removeItem(REFRESH_TOKEN_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { getToken, setToken, clearToken };
|
export { getToken, setToken, clearToken, getRefreshToken, setRefreshToken };
|
||||||
|
|||||||
@@ -1,44 +1,38 @@
|
|||||||
import axios, {
|
import axios, { type InternalAxiosRequestConfig, type AxiosResponse } from "axios";
|
||||||
type InternalAxiosRequestConfig,
|
|
||||||
type AxiosResponse,
|
|
||||||
} from "axios";
|
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import { useUserStoreHook } from "@/store/modules/user";
|
import { useUserStoreHook } from "@/store/modules/user";
|
||||||
import { ResultEnum } from "@/enums/ResultEnum";
|
import { ResultEnum } from "@/enums/ResultEnum";
|
||||||
import { getToken } from "@/utils/auth";
|
import { getToken } from "@/utils/auth";
|
||||||
|
import router from "@/router";
|
||||||
|
|
||||||
// 创建 axios 实例
|
// 创建 axios 实例
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: import.meta.env.VITE_APP_BASE_API,
|
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||||
timeout: 50000,
|
timeout: 50000,
|
||||||
headers: { "Content-Type": "application/json;charset=utf-8" },
|
headers: { "Content-Type": "application/json;charset=utf-8" },
|
||||||
paramsSerializer: (params) => {
|
paramsSerializer: (params) => qs.stringify(params),
|
||||||
return qs.stringify(params);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 请求拦截器
|
// 请求拦截器
|
||||||
service.interceptors.request.use(
|
service.interceptors.request.use(
|
||||||
(config: InternalAxiosRequestConfig) => {
|
(config: InternalAxiosRequestConfig) => {
|
||||||
const accessToken = getToken();
|
const accessToken = getToken();
|
||||||
if (accessToken) {
|
// 如果 Authorization 设置为 no-auth,则不携带 Token,用于登录、刷新 Token 等接口
|
||||||
|
if (config.headers.Authorization !== "no-auth" && accessToken) {
|
||||||
config.headers.Authorization = accessToken;
|
config.headers.Authorization = accessToken;
|
||||||
|
} else {
|
||||||
|
delete config.headers.Authorization;
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
(error: any) => {
|
(error) => Promise.reject(error)
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 响应拦截器
|
// 响应拦截器
|
||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
(response: AxiosResponse) => {
|
(response: AxiosResponse) => {
|
||||||
// 检查配置的响应类型是否为二进制类型('blob' 或 'arraybuffer'), 如果是,直接返回响应对象
|
// 如果响应是二进制流,则直接返回,用于下载文件、Excel 导出等
|
||||||
if (
|
if (response.config.responseType === "blob") {
|
||||||
response.config.responseType === "blob" ||
|
|
||||||
response.config.responseType === "arraybuffer"
|
|
||||||
) {
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,21 +44,15 @@ service.interceptors.response.use(
|
|||||||
ElMessage.error(msg || "系统出错");
|
ElMessage.error(msg || "系统出错");
|
||||||
return Promise.reject(new Error(msg || "Error"));
|
return Promise.reject(new Error(msg || "Error"));
|
||||||
},
|
},
|
||||||
(error: any) => {
|
async (error: any) => {
|
||||||
// 异常处理 非 2xx 状态码 会进入这里
|
const { config, response } = error;
|
||||||
if (error.response.data) {
|
if (response) {
|
||||||
const { code, msg } = error.response.data;
|
const { code, msg } = response.data;
|
||||||
if (code === ResultEnum.TOKEN_INVALID) {
|
if (code === ResultEnum.ACCESS_TOKEN_INVALID) {
|
||||||
ElNotification({
|
// Token 过期,刷新 Token
|
||||||
title: "提示",
|
return handleTokenRefresh(config);
|
||||||
message: "您的会话已过期,请重新登录",
|
} else if (code === ResultEnum.REFRESH_TOKEN_INVALID) {
|
||||||
type: "info",
|
return Promise.reject(new Error(msg || "Error"));
|
||||||
});
|
|
||||||
useUserStoreHook()
|
|
||||||
.clearUserSession()
|
|
||||||
.then(() => {
|
|
||||||
location.reload();
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(msg || "系统出错");
|
ElMessage.error(msg || "系统出错");
|
||||||
}
|
}
|
||||||
@@ -74,3 +62,50 @@ service.interceptors.response.use(
|
|||||||
);
|
);
|
||||||
|
|
||||||
export default service;
|
export default service;
|
||||||
|
|
||||||
|
// 刷新 Token 的锁
|
||||||
|
let isRefreshing = false;
|
||||||
|
// 因 Token 过期导致失败的请求队列
|
||||||
|
let requestsQueue: Array<() => void> = [];
|
||||||
|
|
||||||
|
// 刷新 Token 处理
|
||||||
|
async function handleTokenRefresh(config: InternalAxiosRequestConfig) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const requestCallback = () => {
|
||||||
|
config.headers.Authorization = getToken();
|
||||||
|
resolve(service(config));
|
||||||
|
};
|
||||||
|
|
||||||
|
requestsQueue.push(requestCallback);
|
||||||
|
|
||||||
|
if (!isRefreshing) {
|
||||||
|
isRefreshing = true;
|
||||||
|
|
||||||
|
// 刷新 Token
|
||||||
|
useUserStoreHook()
|
||||||
|
.refreshToken()
|
||||||
|
.then(() => {
|
||||||
|
// Token 刷新成功,执行请求队列
|
||||||
|
requestsQueue.forEach((callback) => callback());
|
||||||
|
requestsQueue = [];
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log("handleTokenRefresh error", error);
|
||||||
|
// Token 刷新失败,清除用户数据并跳转到登录
|
||||||
|
ElNotification({
|
||||||
|
title: "提示",
|
||||||
|
message: "您的会话已过期,请重新登录",
|
||||||
|
type: "info",
|
||||||
|
});
|
||||||
|
useUserStoreHook()
|
||||||
|
.clearUserData()
|
||||||
|
.then(() => {
|
||||||
|
router.push("/login");
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
isRefreshing = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,43 +12,31 @@
|
|||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">
|
<el-button type="primary" icon="search" @click="handleQuery">搜索</el-button>
|
||||||
<template #icon>
|
<el-button icon="refresh" @click="handleResetQuery">重置</el-button>
|
||||||
<Search />
|
|
||||||
</template>
|
|
||||||
搜索
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="handleResetQuery">
|
|
||||||
<template #icon>
|
|
||||||
<Refresh />
|
|
||||||
</template>
|
|
||||||
重置
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-card shadow="never" class="table-wrapper">
|
<el-card shadow="never">
|
||||||
<template #header>
|
<div class="mb-10px">
|
||||||
<el-button
|
<el-button
|
||||||
v-hasPerm="['sys:config:add']"
|
v-hasPerm="['sys:config:add']"
|
||||||
type="success"
|
type="success"
|
||||||
|
icon="plus"
|
||||||
@click="handleOpenDialog()"
|
@click="handleOpenDialog()"
|
||||||
>
|
>
|
||||||
<template #icon>
|
|
||||||
<Plus />
|
|
||||||
</template>
|
|
||||||
新增
|
新增
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-hasPerm="['sys:config:refresh']"
|
v-hasPerm="['sys:config:refresh']"
|
||||||
color="#626aef"
|
color="#626aef"
|
||||||
|
icon="RefreshLeft"
|
||||||
@click="handleRefreshCache"
|
@click="handleRefreshCache"
|
||||||
>
|
>
|
||||||
<el-icon><RefreshLeft /></el-icon>
|
|
||||||
刷新缓存
|
刷新缓存
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</div>
|
||||||
|
|
||||||
<el-table
|
<el-table
|
||||||
ref="dataTableRef"
|
ref="dataTableRef"
|
||||||
@@ -58,30 +46,10 @@
|
|||||||
@selection-change="handleSelectionChange"
|
@selection-change="handleSelectionChange"
|
||||||
>
|
>
|
||||||
<el-table-column type="index" label="序号" width="60" />
|
<el-table-column type="index" label="序号" width="60" />
|
||||||
<el-table-column
|
<el-table-column key="configName" label="配置名称" prop="configName" min-width="100" />
|
||||||
key="configName"
|
<el-table-column key="configKey" label="配置键" prop="configKey" min-width="100" />
|
||||||
label="配置名称"
|
<el-table-column key="configValue" label="配置值" prop="configValue" min-width="100" />
|
||||||
prop="configName"
|
<el-table-column key="remark" label="描述" prop="remark" min-width="100" />
|
||||||
min-width="100"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
key="configKey"
|
|
||||||
label="配置键"
|
|
||||||
prop="configKey"
|
|
||||||
min-width="100"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
key="configValue"
|
|
||||||
label="配置值"
|
|
||||||
prop="configValue"
|
|
||||||
min-width="100"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
key="remark"
|
|
||||||
label="描述"
|
|
||||||
prop="remark"
|
|
||||||
min-width="100"
|
|
||||||
/>
|
|
||||||
<el-table-column fixed="right" label="操作" width="220">
|
<el-table-column fixed="right" label="操作" width="220">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button
|
||||||
@@ -89,11 +57,9 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
size="small"
|
||||||
link
|
link
|
||||||
|
icon="edit"
|
||||||
@click="handleOpenDialog(scope.row.id)"
|
@click="handleOpenDialog(scope.row.id)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
|
||||||
<Edit />
|
|
||||||
</template>
|
|
||||||
编辑
|
编辑
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -101,11 +67,9 @@
|
|||||||
type="danger"
|
type="danger"
|
||||||
size="small"
|
size="small"
|
||||||
link
|
link
|
||||||
|
icon="delete"
|
||||||
@click="handleDelete(scope.row.id)"
|
@click="handleDelete(scope.row.id)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
|
||||||
<Delete />
|
|
||||||
</template>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -136,25 +100,13 @@
|
|||||||
label-width="100px"
|
label-width="100px"
|
||||||
>
|
>
|
||||||
<el-form-item label="配置名称" prop="configName">
|
<el-form-item label="配置名称" prop="configName">
|
||||||
<el-input
|
<el-input v-model="formData.configName" placeholder="请输入配置名称" :maxlength="50" />
|
||||||
v-model="formData.configName"
|
|
||||||
placeholder="请输入配置名称"
|
|
||||||
:maxlength="50"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="配置键" prop="configKey">
|
<el-form-item label="配置键" prop="configKey">
|
||||||
<el-input
|
<el-input v-model="formData.configKey" placeholder="请输入配置键" :maxlength="50" />
|
||||||
v-model="formData.configKey"
|
|
||||||
placeholder="请输入配置键"
|
|
||||||
:maxlength="50"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="配置值" prop="configValue">
|
<el-form-item label="配置值" prop="configValue">
|
||||||
<el-input
|
<el-input v-model="formData.configValue" placeholder="请输入配置值" :maxlength="100" />
|
||||||
v-model="formData.configValue"
|
|
||||||
placeholder="请输入配置值"
|
|
||||||
:maxlength="100"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="描述" prop="remark">
|
<el-form-item label="描述" prop="remark">
|
||||||
<el-input
|
<el-input
|
||||||
@@ -183,17 +135,13 @@ defineOptions({
|
|||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
import ConfigAPI, {
|
import ConfigAPI, { ConfigPageVO, ConfigForm, ConfigPageQuery } from "@/api/system/config";
|
||||||
ConfigPageVO,
|
|
||||||
ConfigForm,
|
|
||||||
ConfigPageQuery,
|
|
||||||
} from "@/api/system/config";
|
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref(ElForm);
|
||||||
const dataFormRef = ref(ElForm);
|
const dataFormRef = ref(ElForm);
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const ids = ref<number[]>([]);
|
const selectIds = ref<number[]>([]);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryParams = reactive<ConfigPageQuery>({
|
const queryParams = reactive<ConfigPageQuery>({
|
||||||
@@ -205,12 +153,11 @@ const queryParams = reactive<ConfigPageQuery>({
|
|||||||
// 系统配置表格数据
|
// 系统配置表格数据
|
||||||
const pageData = ref<ConfigPageVO[]>([]);
|
const pageData = ref<ConfigPageVO[]>([]);
|
||||||
|
|
||||||
// 弹窗
|
|
||||||
const dialog = reactive({
|
const dialog = reactive({
|
||||||
title: "",
|
title: "",
|
||||||
visible: false,
|
visible: false,
|
||||||
});
|
});
|
||||||
// 系统配置表单
|
|
||||||
const formData = reactive<ConfigForm>({
|
const formData = reactive<ConfigForm>({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
configName: "",
|
configName: "",
|
||||||
@@ -220,18 +167,12 @@ const formData = reactive<ConfigForm>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
configName: [
|
configName: [{ required: true, message: "请输入系统配置名称", trigger: "blur" }],
|
||||||
{ required: true, message: "请输入系统配置名称", trigger: "blur" },
|
configKey: [{ required: true, message: "请输入系统配置编码", trigger: "blur" }],
|
||||||
],
|
configValue: [{ required: true, message: "请输入系统配置值", trigger: "blur" }],
|
||||||
configKey: [
|
|
||||||
{ required: true, message: "请输入系统配置编码", trigger: "blur" },
|
|
||||||
],
|
|
||||||
configValue: [
|
|
||||||
{ required: true, message: "请输入系统配置值", trigger: "blur" },
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 查询系统配置 */
|
// 查询系统配置
|
||||||
function handleQuery() {
|
function handleQuery() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
ConfigAPI.getPage(queryParams)
|
ConfigAPI.getPage(queryParams)
|
||||||
@@ -243,19 +184,20 @@ function handleQuery() {
|
|||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/** 重置系统配置查询 */
|
|
||||||
|
// 重置查询
|
||||||
function handleResetQuery() {
|
function handleResetQuery() {
|
||||||
queryFormRef.value.resetFields();
|
queryFormRef.value.resetFields();
|
||||||
queryParams.pageNum = 1;
|
queryParams.pageNum = 1;
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 行复选框选中记录选中ID集合 */
|
// 行复选框选中项变化
|
||||||
function handleSelectionChange(selection: any) {
|
function handleSelectionChange(selection: any) {
|
||||||
ids.value = selection.map((item: any) => item.id);
|
selectIds.value = selection.map((item: any) => item.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 打开系统配置弹窗 */
|
// 打开系统配置弹窗
|
||||||
function handleOpenDialog(id?: number) {
|
function handleOpenDialog(id?: number) {
|
||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
if (id) {
|
if (id) {
|
||||||
@@ -269,14 +211,14 @@ function handleOpenDialog(id?: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 刷新缓存 **/
|
// 刷新缓存
|
||||||
function handleRefreshCache() {
|
function handleRefreshCache() {
|
||||||
ConfigAPI.refreshCache().then(() => {
|
ConfigAPI.refreshCache().then(() => {
|
||||||
ElMessage.success("刷新成功");
|
ElMessage.success("刷新成功");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 提交系统配置表单 */
|
// 系统配置表单提交
|
||||||
function handleSubmit() {
|
function handleSubmit() {
|
||||||
dataFormRef.value.validate((valid: any) => {
|
dataFormRef.value.validate((valid: any) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
@@ -303,32 +245,34 @@ function handleSubmit() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 关闭系统配置弹窗 */
|
// 重置表单
|
||||||
function handleCloseDialog() {
|
function resetForm() {
|
||||||
dialog.visible = false;
|
|
||||||
dataFormRef.value.resetFields();
|
dataFormRef.value.resetFields();
|
||||||
dataFormRef.value.clearValidate();
|
dataFormRef.value.clearValidate();
|
||||||
formData.id != undefined;
|
formData.id = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除系统配置 */
|
// 关闭系统配置弹窗
|
||||||
|
function handleCloseDialog() {
|
||||||
|
dialog.visible = false;
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除系统配置
|
||||||
function handleDelete(id: number) {
|
function handleDelete(id: number) {
|
||||||
ElMessageBox.confirm("确认删除该项配置?", "警告", {
|
ElMessageBox.confirm("确认删除该项配置?", "警告", {
|
||||||
confirmButtonText: "确定",
|
confirmButtonText: "确定",
|
||||||
cancelButtonText: "取消",
|
cancelButtonText: "取消",
|
||||||
type: "warning",
|
type: "warning",
|
||||||
}).then(
|
}).then(() => {
|
||||||
() => {
|
loading.value = true;
|
||||||
loading.value = true;
|
ConfigAPI.deleteById(id)
|
||||||
ConfigAPI.deleteById(id)
|
.then(() => {
|
||||||
.then(() => {
|
ElMessage.success("删除成功");
|
||||||
ElMessage.success("删除成功");
|
handleResetQuery();
|
||||||
handleResetQuery();
|
})
|
||||||
})
|
.finally(() => (loading.value = false));
|
||||||
.finally(() => (loading.value = false));
|
});
|
||||||
},
|
|
||||||
() => {}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -17,18 +17,10 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button class="filter-item" type="primary" @click="handleQuery">
|
<el-button class="filter-item" type="primary" icon="search" @click="handleQuery">
|
||||||
<template #icon>
|
|
||||||
<Search />
|
|
||||||
</template>
|
|
||||||
搜索
|
搜索
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button @click="handleResetQuery">
|
<el-button icon="refresh" @click="handleResetQuery">重置</el-button>
|
||||||
<template #icon>
|
|
||||||
<Refresh />
|
|
||||||
</template>
|
|
||||||
重置
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
@@ -38,22 +30,18 @@
|
|||||||
<el-button
|
<el-button
|
||||||
v-hasPerm="['sys:dept:add']"
|
v-hasPerm="['sys:dept:add']"
|
||||||
type="success"
|
type="success"
|
||||||
|
icon="plus"
|
||||||
@click="handleOpenDialog(0, undefined)"
|
@click="handleOpenDialog(0, undefined)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
|
||||||
<Plus />
|
|
||||||
</template>
|
|
||||||
新增
|
新增
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-hasPerm="['sys:dept:delete']"
|
v-hasPerm="['sys:dept:delete']"
|
||||||
type="danger"
|
type="danger"
|
||||||
:disabled="ids.length === 0"
|
:disabled="selectIds.length === 0"
|
||||||
|
icon="delete"
|
||||||
@click="handleDelete()"
|
@click="handleDelete()"
|
||||||
>
|
>
|
||||||
<template #icon>
|
|
||||||
<Delete />
|
|
||||||
</template>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -85,11 +73,9 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
|
icon="plus"
|
||||||
@click.stop="handleOpenDialog(scope.row.id, undefined)"
|
@click.stop="handleOpenDialog(scope.row.id, undefined)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
|
||||||
<Plus />
|
|
||||||
</template>
|
|
||||||
新增
|
新增
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -97,11 +83,9 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
|
icon="edit"
|
||||||
@click.stop="handleOpenDialog(scope.row.parentId, scope.row.id)"
|
@click.stop="handleOpenDialog(scope.row.parentId, scope.row.id)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
|
||||||
<Edit />
|
|
||||||
</template>
|
|
||||||
编辑
|
编辑
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -109,11 +93,9 @@
|
|||||||
type="danger"
|
type="danger"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
|
icon="delete"
|
||||||
@click.stop="handleDelete(scope.row.id)"
|
@click.stop="handleDelete(scope.row.id)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
|
||||||
<Delete />
|
|
||||||
</template>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -182,17 +164,16 @@ const queryFormRef = ref(ElForm);
|
|||||||
const deptFormRef = ref(ElForm);
|
const deptFormRef = ref(ElForm);
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const ids = ref<number[]>([]);
|
const selectIds = ref<number[]>([]);
|
||||||
|
const queryParams = reactive<DeptQuery>({});
|
||||||
|
|
||||||
const dialog = reactive({
|
const dialog = reactive({
|
||||||
title: "",
|
title: "",
|
||||||
visible: false,
|
visible: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const queryParams = reactive<DeptQuery>({});
|
|
||||||
const deptList = ref<DeptVO[]>();
|
const deptList = ref<DeptVO[]>();
|
||||||
|
|
||||||
const deptOptions = ref<OptionType[]>();
|
const deptOptions = ref<OptionType[]>();
|
||||||
|
|
||||||
const formData = reactive<DeptForm>({
|
const formData = reactive<DeptForm>({
|
||||||
status: 1,
|
status: 1,
|
||||||
parentId: "0",
|
parentId: "0",
|
||||||
@@ -221,9 +202,9 @@ function handleResetQuery() {
|
|||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 行复选框选中记录选中ID集合
|
// 处理选中项变化
|
||||||
function handleSelectionChange(selection: any) {
|
function handleSelectionChange(selection: any) {
|
||||||
ids.value = selection.map((item: any) => item.id);
|
selectIds.value = selection.map((item: any) => item.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -284,7 +265,7 @@ function handleSubmit() {
|
|||||||
|
|
||||||
// 删除部门
|
// 删除部门
|
||||||
function handleDelete(deptId?: number) {
|
function handleDelete(deptId?: number) {
|
||||||
const deptIds = [deptId || ids.value].join(",");
|
const deptIds = [deptId || selectIds.value].join(",");
|
||||||
|
|
||||||
if (!deptIds) {
|
if (!deptIds) {
|
||||||
ElMessage.warning("请勾选删除项");
|
ElMessage.warning("请勾选删除项");
|
||||||
|
|||||||
@@ -12,38 +12,16 @@
|
|||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery()">
|
<el-button type="primary" icon="search" @click="handleQuery()">搜索</el-button>
|
||||||
<template #icon>
|
<el-button icon="refresh" @click="handleResetQuery()">重置</el-button>
|
||||||
<Search />
|
|
||||||
</template>
|
|
||||||
搜索
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="handleResetQuery()">
|
|
||||||
<template #icon>
|
|
||||||
<Refresh />
|
|
||||||
</template>
|
|
||||||
重置
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="never">
|
||||||
<div class="mb-[10px]">
|
<div class="mb-[10px]">
|
||||||
<el-button type="success" @click="handleOpenDialog()">
|
<el-button type="success" icon="plus" @click="handleOpenDialog()">新增</el-button>
|
||||||
<template #icon>
|
<el-button type="danger" :disabled="ids.length === 0" icon="delete" @click="handleDelete()">
|
||||||
<Plus />
|
|
||||||
</template>
|
|
||||||
新增
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
type="danger"
|
|
||||||
:disabled="ids.length === 0"
|
|
||||||
@click="handleDelete()"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<Delete />
|
|
||||||
</template>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -73,22 +51,18 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
|
icon="edit"
|
||||||
@click.stop="handleOpenDialog(scope.row)"
|
@click.stop="handleOpenDialog(scope.row)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
|
||||||
<Edit />
|
|
||||||
</template>
|
|
||||||
编辑
|
编辑
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
type="danger"
|
type="danger"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
|
icon="delete"
|
||||||
@click.stop="handleDelete(scope.row.id)"
|
@click.stop="handleDelete(scope.row.id)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
|
||||||
<Delete />
|
|
||||||
</template>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -111,12 +85,7 @@
|
|||||||
width="820px"
|
width="820px"
|
||||||
@close="handleCloseDialog"
|
@close="handleCloseDialog"
|
||||||
>
|
>
|
||||||
<el-form
|
<el-form ref="dataFormRef" :model="formData" :rules="computedRules" label-width="100px">
|
||||||
ref="dataFormRef"
|
|
||||||
:model="formData"
|
|
||||||
:rules="computedRules"
|
|
||||||
label-width="100px"
|
|
||||||
>
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="never">
|
||||||
<el-form-item label="字典标签" prop="label">
|
<el-form-item label="字典标签" prop="label">
|
||||||
<el-input v-model="formData.label" placeholder="请输入字典标签" />
|
<el-input v-model="formData.label" placeholder="请输入字典标签" />
|
||||||
@@ -131,17 +100,10 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="排序">
|
<el-form-item label="排序">
|
||||||
<el-input-number
|
<el-input-number v-model="formData.sort" controls-position="right" />
|
||||||
v-model="formData.sort"
|
|
||||||
controls-position="right"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="标签类型">
|
<el-form-item label="标签类型">
|
||||||
<el-tag
|
<el-tag v-if="formData.tagType" :type="formData.tagType" class="mr-2">
|
||||||
v-if="formData.tagType"
|
|
||||||
:type="formData.tagType"
|
|
||||||
class="mr-2"
|
|
||||||
>
|
|
||||||
{{ formData.label }}
|
{{ formData.label }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
<el-radio-group v-model="formData.tagType">
|
<el-radio-group v-model="formData.tagType">
|
||||||
|
|||||||
@@ -12,38 +12,16 @@
|
|||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery()">
|
<el-button type="primary" icon="search" @click="handleQuery()">搜索</el-button>
|
||||||
<template #icon>
|
<el-button icon="refresh" @click="handleResetQuery()">重置</el-button>
|
||||||
<Search />
|
|
||||||
</template>
|
|
||||||
搜索
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="handleResetQuery()">
|
|
||||||
<template #icon>
|
|
||||||
<Refresh />
|
|
||||||
</template>
|
|
||||||
重置
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="never">
|
||||||
<div class="mb-[10px]">
|
<div class="mb-[10px]">
|
||||||
<el-button type="success" @click="handleAddClick()">
|
<el-button type="success" icon="plus" @click="handleAddClick()">新增</el-button>
|
||||||
<template #icon>
|
<el-button type="danger" :disabled="ids.length === 0" icon="delete" @click="handleDelete()">
|
||||||
<Plus />
|
|
||||||
</template>
|
|
||||||
新增
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
type="danger"
|
|
||||||
:disabled="ids.length === 0"
|
|
||||||
@click="handleDelete()"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<Delete />
|
|
||||||
</template>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -67,12 +45,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column fixed="right" label="操作" align="center" width="220">
|
<el-table-column fixed="right" label="操作" align="center" width="220">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button type="primary" link size="small" @click.stop="handleOpenDictData(scope.row)">
|
||||||
type="primary"
|
|
||||||
link
|
|
||||||
size="small"
|
|
||||||
@click.stop="handleOpenDictData(scope.row)"
|
|
||||||
>
|
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<Collection />
|
<Collection />
|
||||||
</template>
|
</template>
|
||||||
@@ -83,22 +56,18 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
|
icon="edit"
|
||||||
@click.stop="handleEditClick(scope.row.id, scope.row.name)"
|
@click.stop="handleEditClick(scope.row.id, scope.row.name)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
|
||||||
<Edit />
|
|
||||||
</template>
|
|
||||||
编辑
|
编辑
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
type="danger"
|
type="danger"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
|
icon="delete"
|
||||||
@click.stop="handleDelete(scope.row.id)"
|
@click.stop="handleDelete(scope.row.id)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
|
||||||
<Delete />
|
|
||||||
</template>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -121,22 +90,14 @@
|
|||||||
width="500px"
|
width="500px"
|
||||||
@close="handleCloseDialog"
|
@close="handleCloseDialog"
|
||||||
>
|
>
|
||||||
<el-form
|
<el-form ref="dataFormRef" :model="formData" :rules="computedRules" label-width="100px">
|
||||||
ref="dataFormRef"
|
|
||||||
:model="formData"
|
|
||||||
:rules="computedRules"
|
|
||||||
label-width="100px"
|
|
||||||
>
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="never">
|
||||||
<el-form-item label="字典名称" prop="name">
|
<el-form-item label="字典名称" prop="name">
|
||||||
<el-input v-model="formData.name" placeholder="请输入字典名称" />
|
<el-input v-model="formData.name" placeholder="请输入字典名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="字典编码" prop="dictCode">
|
<el-form-item label="字典编码" prop="dictCode">
|
||||||
<el-input
|
<el-input v-model="formData.dictCode" placeholder="请输入字典编码" />
|
||||||
v-model="formData.dictCode"
|
|
||||||
placeholder="请输入字典编码"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="状态">
|
<el-form-item label="状态">
|
||||||
@@ -147,11 +108,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="备注">
|
<el-form-item label="备注">
|
||||||
<el-input
|
<el-input v-model="formData.remark" type="textarea" placeholder="请输入备注" />
|
||||||
v-model="formData.remark"
|
|
||||||
type="textarea"
|
|
||||||
placeholder="请输入备注"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -172,11 +129,7 @@ defineOptions({
|
|||||||
inherititems: false,
|
inherititems: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
import DictAPI, {
|
import DictAPI, { DictPageQuery, DictPageVO, DictForm } from "@/api/system/dict";
|
||||||
DictPageQuery,
|
|
||||||
DictPageVO,
|
|
||||||
DictForm,
|
|
||||||
} from "@/api/system/dict";
|
|
||||||
|
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
|
|
||||||
|
|||||||
@@ -24,29 +24,14 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">
|
<el-button type="primary" icon="search" @click="handleQuery">搜索</el-button>
|
||||||
<template #icon>
|
<el-button icon="refresh" @click="handleResetQuery">重置</el-button>
|
||||||
<Search />
|
|
||||||
</template>
|
|
||||||
搜索
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="handleResetQuery">
|
|
||||||
<template #icon>
|
|
||||||
<Refresh />
|
|
||||||
</template>
|
|
||||||
重置
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="never">
|
||||||
<el-table
|
<el-table v-loading="loading" :data="pageData" highlight-current-row border>
|
||||||
v-loading="loading"
|
|
||||||
:data="pageData"
|
|
||||||
highlight-current-row
|
|
||||||
border
|
|
||||||
>
|
|
||||||
<el-table-column label="操作时间" prop="createTime" width="180" />
|
<el-table-column label="操作时间" prop="createTime" width="180" />
|
||||||
<el-table-column label="操作人" prop="operator" width="120" />
|
<el-table-column label="操作人" prop="operator" width="120" />
|
||||||
<el-table-column label="日志模块" prop="module" width="100" />
|
<el-table-column label="日志模块" prop="module" width="100" />
|
||||||
@@ -54,17 +39,8 @@
|
|||||||
<el-table-column label="IP 地址" prop="ip" width="150" />
|
<el-table-column label="IP 地址" prop="ip" width="150" />
|
||||||
<el-table-column label="地区" prop="region" width="150" />
|
<el-table-column label="地区" prop="region" width="150" />
|
||||||
<el-table-column label="浏览器" prop="browser" width="150" />
|
<el-table-column label="浏览器" prop="browser" width="150" />
|
||||||
<el-table-column
|
<el-table-column label="终端系统" prop="os" width="200" show-overflow-tooltip />
|
||||||
label="终端系统"
|
<el-table-column label="执行时间(ms)" prop="executionTime" width="150" />
|
||||||
prop="os"
|
|
||||||
width="200"
|
|
||||||
show-overflow-tooltip
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
label="执行时间(ms)"
|
|
||||||
prop="executionTime"
|
|
||||||
width="150"
|
|
||||||
/>
|
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination
|
<pagination
|
||||||
|
|||||||
@@ -11,29 +11,23 @@
|
|||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">
|
<el-button type="primary" icon="search" @click="handleQuery">搜索</el-button>
|
||||||
<template #icon><Search /></template>
|
<el-button icon="refresh" @click="handleResetQuery">重置</el-button>
|
||||||
搜索
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="handleResetQuery">
|
|
||||||
<template #icon><Refresh /></template>
|
|
||||||
重置
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-card shadow="never" class="table-wrapper">
|
<el-card shadow="never">
|
||||||
<template #header>
|
<div class="mb-10px">
|
||||||
<el-button
|
<el-button
|
||||||
v-hasPerm="['sys:menu:add']"
|
v-hasPerm="['sys:menu:add']"
|
||||||
type="success"
|
type="success"
|
||||||
|
icon="plus"
|
||||||
@click="handleOpenDialog(0)"
|
@click="handleOpenDialog(0)"
|
||||||
>
|
>
|
||||||
<template #icon><Plus /></template>
|
|
||||||
新增
|
新增
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</div>
|
||||||
|
|
||||||
<el-table
|
<el-table
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
@@ -49,9 +43,7 @@
|
|||||||
>
|
>
|
||||||
<el-table-column label="菜单名称" min-width="200">
|
<el-table-column label="菜单名称" min-width="200">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<template
|
<template v-if="scope.row.icon && scope.row.icon.startsWith('el-icon')">
|
||||||
v-if="scope.row.icon && scope.row.icon.startsWith('el-icon')"
|
|
||||||
>
|
|
||||||
<el-icon style="vertical-align: -0.15em">
|
<el-icon style="vertical-align: -0.15em">
|
||||||
<component :is="scope.row.icon.replace('el-icon-', '')" />
|
<component :is="scope.row.icon.replace('el-icon-', '')" />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
@@ -59,70 +51,29 @@
|
|||||||
<template v-else-if="scope.row.icon">
|
<template v-else-if="scope.row.icon">
|
||||||
<svg-icon :icon-class="scope.row.icon" />
|
<svg-icon :icon-class="scope.row.icon" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
|
||||||
<svg-icon icon-class="menu" />
|
|
||||||
</template>
|
|
||||||
{{ scope.row.name }}
|
{{ scope.row.name }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="类型" align="center" width="80">
|
<el-table-column label="类型" align="center" width="80">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag
|
<el-tag v-if="scope.row.type === MenuTypeEnum.CATALOG" type="warning">目录</el-tag>
|
||||||
v-if="scope.row.type === MenuTypeEnum.CATALOG"
|
<el-tag v-if="scope.row.type === MenuTypeEnum.MENU" type="success">菜单</el-tag>
|
||||||
type="warning"
|
<el-tag v-if="scope.row.type === MenuTypeEnum.BUTTON" type="danger">按钮</el-tag>
|
||||||
>
|
<el-tag v-if="scope.row.type === MenuTypeEnum.EXTLINK" type="info">外链</el-tag>
|
||||||
目录
|
|
||||||
</el-tag>
|
|
||||||
<el-tag v-if="scope.row.type === MenuTypeEnum.MENU" type="success">
|
|
||||||
菜单
|
|
||||||
</el-tag>
|
|
||||||
<el-tag v-if="scope.row.type === MenuTypeEnum.BUTTON" type="danger">
|
|
||||||
按钮
|
|
||||||
</el-tag>
|
|
||||||
<el-tag v-if="scope.row.type === MenuTypeEnum.EXTLINK" type="info">
|
|
||||||
外链
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column label="路由名称" align="left" width="150" prop="routeName" />
|
||||||
<el-table-column
|
<el-table-column label="路由路径" align="left" width="150" prop="routePath" />
|
||||||
label="路由名称"
|
<el-table-column label="组件路径" align="left" width="250" prop="component" />
|
||||||
align="left"
|
<el-table-column label="权限标识" align="center" width="200" prop="perm" />
|
||||||
width="150"
|
|
||||||
prop="routeName"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<el-table-column
|
|
||||||
label="路由路径"
|
|
||||||
align="left"
|
|
||||||
width="150"
|
|
||||||
prop="routePath"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<el-table-column
|
|
||||||
label="组件路径"
|
|
||||||
align="left"
|
|
||||||
width="250"
|
|
||||||
prop="component"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<el-table-column
|
|
||||||
label="权限标识"
|
|
||||||
align="center"
|
|
||||||
width="200"
|
|
||||||
prop="perm"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<el-table-column label="状态" align="center" width="80">
|
<el-table-column label="状态" align="center" width="80">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag v-if="scope.row.visible === 1" type="success">显示</el-tag>
|
<el-tag v-if="scope.row.visible === 1" type="success">显示</el-tag>
|
||||||
<el-tag v-else type="info">隐藏</el-tag>
|
<el-tag v-else type="info">隐藏</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="排序" align="center" width="80" prop="sort" />
|
<el-table-column label="排序" align="center" width="80" prop="sort" />
|
||||||
|
|
||||||
<el-table-column fixed="right" align="center" label="操作" width="220">
|
<el-table-column fixed="right" align="center" label="操作" width="220">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button
|
||||||
@@ -131,9 +82,9 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
|
icon="plus"
|
||||||
@click.stop="handleOpenDialog(scope.row.id)"
|
@click.stop="handleOpenDialog(scope.row.id)"
|
||||||
>
|
>
|
||||||
<template #icon><Plus /></template>
|
|
||||||
新增
|
新增
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
@@ -142,9 +93,9 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
|
icon="edit"
|
||||||
@click.stop="handleOpenDialog(undefined, scope.row.id)"
|
@click.stop="handleOpenDialog(undefined, scope.row.id)"
|
||||||
>
|
>
|
||||||
<template #icon><Edit /></template>
|
|
||||||
编辑
|
编辑
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -152,9 +103,9 @@
|
|||||||
type="danger"
|
type="danger"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
|
icon="delete"
|
||||||
@click.stop="handleDelete(scope.row.id)"
|
@click.stop="handleDelete(scope.row.id)"
|
||||||
>
|
>
|
||||||
<template #icon><Delete /></template>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -162,18 +113,8 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-drawer
|
<el-drawer v-model="dialog.visible" :title="dialog.title" size="50%" @close="handleCloseDialog">
|
||||||
v-model="dialog.visible"
|
<el-form ref="menuFormRef" :model="formData" :rules="rules" label-width="100px">
|
||||||
:title="dialog.title"
|
|
||||||
size="50%"
|
|
||||||
@close="handleCloseDialog"
|
|
||||||
>
|
|
||||||
<el-form
|
|
||||||
ref="menuFormRef"
|
|
||||||
:model="formData"
|
|
||||||
:rules="rules"
|
|
||||||
label-width="100px"
|
|
||||||
>
|
|
||||||
<el-form-item label="父级菜单" prop="parentId">
|
<el-form-item label="父级菜单" prop="parentId">
|
||||||
<el-tree-select
|
<el-tree-select
|
||||||
v-model="formData.parentId"
|
v-model="formData.parentId"
|
||||||
@@ -190,10 +131,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="菜单类型" prop="type">
|
<el-form-item label="菜单类型" prop="type">
|
||||||
<el-radio-group
|
<el-radio-group v-model="formData.type" @change="handleMenuTypeChange">
|
||||||
v-model="formData.type"
|
|
||||||
@change="handleMenuTypeChange"
|
|
||||||
>
|
|
||||||
<el-radio value="CATALOG">目录</el-radio>
|
<el-radio value="CATALOG">目录</el-radio>
|
||||||
<el-radio value="MENU">菜单</el-radio>
|
<el-radio value="MENU">菜单</el-radio>
|
||||||
<el-radio value="BUTTON">按钮</el-radio>
|
<el-radio value="BUTTON">按钮</el-radio>
|
||||||
@@ -201,30 +139,18 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item
|
<el-form-item v-if="formData.type == 'EXTLINK'" label="外链地址" prop="path">
|
||||||
v-if="formData.type == 'EXTLINK'"
|
<el-input v-model="formData.routePath" placeholder="请输入外链完整路径" />
|
||||||
label="外链地址"
|
|
||||||
prop="path"
|
|
||||||
>
|
|
||||||
<el-input
|
|
||||||
v-model="formData.routePath"
|
|
||||||
placeholder="请输入外链完整路径"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item
|
<el-form-item v-if="formData.type == MenuTypeEnum.MENU" prop="routeName">
|
||||||
v-if="formData.type == MenuTypeEnum.MENU"
|
|
||||||
prop="routeName"
|
|
||||||
>
|
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-y-center">
|
<div class="flex-y-center">
|
||||||
路由名称
|
路由名称
|
||||||
<el-tooltip placement="bottom" effect="light">
|
<el-tooltip placement="bottom" effect="light">
|
||||||
<template #content>
|
<template #content>
|
||||||
如果需要开启缓存,需保证页面 defineOptions 中的 name
|
如果需要开启缓存,需保证页面 defineOptions 中的 name 与此处一致,建议使用驼峰。
|
||||||
与此处一致,建议使用驼峰。
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-icon class="ml-1 cursor-pointer">
|
<el-icon class="ml-1 cursor-pointer">
|
||||||
<QuestionFilled />
|
<QuestionFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
@@ -235,10 +161,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="
|
v-if="formData.type == MenuTypeEnum.CATALOG || formData.type == MenuTypeEnum.MENU"
|
||||||
formData.type == MenuTypeEnum.CATALOG ||
|
|
||||||
formData.type == MenuTypeEnum.MENU
|
|
||||||
"
|
|
||||||
prop="routePath"
|
prop="routePath"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
@@ -246,8 +169,7 @@
|
|||||||
路由路径
|
路由路径
|
||||||
<el-tooltip placement="bottom" effect="light">
|
<el-tooltip placement="bottom" effect="light">
|
||||||
<template #content>
|
<template #content>
|
||||||
定义应用中不同页面对应的 URL 路径,目录需以 /
|
定义应用中不同页面对应的 URL 路径,目录需以 / 开头,菜单项不用。例如:系统管理目录
|
||||||
开头,菜单项不用。例如:系统管理目录
|
|
||||||
/system,系统管理下的用户管理菜单 user。
|
/system,系统管理下的用户管理菜单 user。
|
||||||
</template>
|
</template>
|
||||||
<el-icon class="ml-1 cursor-pointer">
|
<el-icon class="ml-1 cursor-pointer">
|
||||||
@@ -264,17 +186,13 @@
|
|||||||
<el-input v-else v-model="formData.routePath" placeholder="user" />
|
<el-input v-else v-model="formData.routePath" placeholder="user" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item
|
<el-form-item v-if="formData.type == MenuTypeEnum.MENU" prop="component">
|
||||||
v-if="formData.type == MenuTypeEnum.MENU"
|
|
||||||
prop="component"
|
|
||||||
>
|
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-y-center">
|
<div class="flex-y-center">
|
||||||
组件路径
|
组件路径
|
||||||
<el-tooltip placement="bottom" effect="light">
|
<el-tooltip placement="bottom" effect="light">
|
||||||
<template #content>
|
<template #content>
|
||||||
组件页面完整路径,相对于 src/views/,如
|
组件页面完整路径,相对于 src/views/,如 system/user/index,缺省后缀 .vue
|
||||||
system/user/index,缺省后缀 .vue
|
|
||||||
</template>
|
</template>
|
||||||
<el-icon class="ml-1 cursor-pointer">
|
<el-icon class="ml-1 cursor-pointer">
|
||||||
<QuestionFilled />
|
<QuestionFilled />
|
||||||
@@ -283,17 +201,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-input
|
<el-input v-model="formData.component" placeholder="system/user/index" style="width: 95%">
|
||||||
v-model="formData.component"
|
<template v-if="formData.type == MenuTypeEnum.MENU" #prepend>src/views/</template>
|
||||||
placeholder="system/user/index"
|
<template v-if="formData.type == MenuTypeEnum.MENU" #append>.vue</template>
|
||||||
style="width: 95%"
|
|
||||||
>
|
|
||||||
<template v-if="formData.type == MenuTypeEnum.MENU" #prepend>
|
|
||||||
src/views/
|
|
||||||
</template>
|
|
||||||
<template v-if="formData.type == MenuTypeEnum.MENU" #append>
|
|
||||||
.vue
|
|
||||||
</template>
|
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
@@ -313,35 +223,21 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div v-if="!formData.params || formData.params.length === 0">
|
<div v-if="!formData.params || formData.params.length === 0">
|
||||||
<el-button
|
<el-button type="success" plain @click="formData.params = [{ key: '', value: '' }]">
|
||||||
type="success"
|
|
||||||
plain
|
|
||||||
@click="formData.params = [{ key: '', value: '' }]"
|
|
||||||
>
|
|
||||||
添加路由参数
|
添加路由参数
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<div v-for="(item, index) in formData.params" :key="index">
|
<div v-for="(item, index) in formData.params" :key="index">
|
||||||
<el-input
|
<el-input v-model="item.key" placeholder="参数名" style="width: 100px" />
|
||||||
v-model="item.key"
|
|
||||||
placeholder="参数名"
|
|
||||||
style="width: 100px"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<span class="mx-1">=</span>
|
<span class="mx-1">=</span>
|
||||||
|
|
||||||
<el-input
|
<el-input v-model="item.value" placeholder="参数值" style="width: 100px" />
|
||||||
v-model="item.value"
|
|
||||||
placeholder="参数值"
|
|
||||||
style="width: 100px"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<el-icon
|
<el-icon
|
||||||
v-if="
|
v-if="formData.params.indexOf(item) === formData.params.length - 1"
|
||||||
formData.params.indexOf(item) === formData.params.length - 1
|
|
||||||
"
|
|
||||||
class="ml-2 cursor-pointer color-[var(--el-color-success)]"
|
class="ml-2 cursor-pointer color-[var(--el-color-success)]"
|
||||||
style="vertical-align: -0.15em"
|
style="vertical-align: -0.15em"
|
||||||
@click="formData.params.push({ key: '', value: '' })"
|
@click="formData.params.push({ key: '', value: '' })"
|
||||||
@@ -351,9 +247,7 @@
|
|||||||
<el-icon
|
<el-icon
|
||||||
class="ml-2 cursor-pointer color-[var(--el-color-danger)]"
|
class="ml-2 cursor-pointer color-[var(--el-color-danger)]"
|
||||||
style="vertical-align: -0.15em"
|
style="vertical-align: -0.15em"
|
||||||
@click="
|
@click="formData.params.splice(formData.params.indexOf(item), 1)"
|
||||||
formData.params.splice(formData.params.indexOf(item), 1)
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<DeleteFilled />
|
<DeleteFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
@@ -361,11 +255,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item
|
<el-form-item v-if="formData.type !== MenuTypeEnum.BUTTON" prop="visible" label="显示状态">
|
||||||
v-if="formData.type !== MenuTypeEnum.BUTTON"
|
|
||||||
prop="visible"
|
|
||||||
label="显示状态"
|
|
||||||
>
|
|
||||||
<el-radio-group v-model="formData.visible">
|
<el-radio-group v-model="formData.visible">
|
||||||
<el-radio :value="1">显示</el-radio>
|
<el-radio :value="1">显示</el-radio>
|
||||||
<el-radio :value="0">隐藏</el-radio>
|
<el-radio :value="0">隐藏</el-radio>
|
||||||
@@ -373,10 +263,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="
|
v-if="formData.type === MenuTypeEnum.CATALOG || formData.type === MenuTypeEnum.MENU"
|
||||||
formData.type === MenuTypeEnum.CATALOG ||
|
|
||||||
formData.type === MenuTypeEnum.MENU
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-y-center">
|
<div class="flex-y-center">
|
||||||
@@ -402,10 +289,7 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item
|
<el-form-item v-if="formData.type === MenuTypeEnum.MENU" label="缓存页面">
|
||||||
v-if="formData.type === MenuTypeEnum.MENU"
|
|
||||||
label="缓存页面"
|
|
||||||
>
|
|
||||||
<el-radio-group v-model="formData.keepAlive">
|
<el-radio-group v-model="formData.keepAlive">
|
||||||
<el-radio :value="1">开启</el-radio>
|
<el-radio :value="1">开启</el-radio>
|
||||||
<el-radio :value="0">关闭</el-radio>
|
<el-radio :value="0">关闭</el-radio>
|
||||||
@@ -422,34 +306,23 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- 权限标识 -->
|
<!-- 权限标识 -->
|
||||||
<el-form-item
|
<el-form-item v-if="formData.type == MenuTypeEnum.BUTTON" label="权限标识" prop="perm">
|
||||||
v-if="formData.type == MenuTypeEnum.BUTTON"
|
|
||||||
label="权限标识"
|
|
||||||
prop="perm"
|
|
||||||
>
|
|
||||||
<el-input v-model="formData.perm" placeholder="sys:user:add" />
|
<el-input v-model="formData.perm" placeholder="sys:user:add" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item
|
<el-form-item v-if="formData.type !== MenuTypeEnum.BUTTON" label="图标" prop="icon">
|
||||||
v-if="formData.type !== MenuTypeEnum.BUTTON"
|
|
||||||
label="图标"
|
|
||||||
prop="icon"
|
|
||||||
>
|
|
||||||
<!-- 图标选择器 -->
|
<!-- 图标选择器 -->
|
||||||
<icon-select v-model="formData.icon" />
|
<icon-select v-model="formData.icon" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item
|
<el-form-item v-if="formData.type == MenuTypeEnum.CATALOG" label="跳转路由">
|
||||||
v-if="formData.type == MenuTypeEnum.CATALOG"
|
|
||||||
label="跳转路由"
|
|
||||||
>
|
|
||||||
<el-input v-model="formData.redirect" placeholder="跳转路由" />
|
<el-input v-model="formData.redirect" placeholder="跳转路由" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
<el-button type="primary" @click="handleSubmit">确 定</el-button>
|
||||||
<el-button @click="handleCloseDialog">取 消</el-button>
|
<el-button @click="handleCloseDialog">取 消</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -481,7 +354,6 @@ const queryParams = reactive<MenuQuery>({});
|
|||||||
const menuTableData = ref<MenuVO[]>([]);
|
const menuTableData = ref<MenuVO[]>([]);
|
||||||
// 顶级菜单下拉选项
|
// 顶级菜单下拉选项
|
||||||
const menuOptions = ref<OptionType[]>([]);
|
const menuOptions = ref<OptionType[]>([]);
|
||||||
|
|
||||||
// 初始菜单表单数据
|
// 初始菜单表单数据
|
||||||
const initialMenuFormData = ref<MenuForm>({
|
const initialMenuFormData = ref<MenuForm>({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
@@ -493,10 +365,8 @@ const initialMenuFormData = ref<MenuForm>({
|
|||||||
keepAlive: 1,
|
keepAlive: 1,
|
||||||
params: [],
|
params: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
// 菜单表单数据
|
// 菜单表单数据
|
||||||
const formData = ref({ ...initialMenuFormData.value });
|
const formData = ref({ ...initialMenuFormData.value });
|
||||||
|
|
||||||
// 表单验证规则
|
// 表单验证规则
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
parentId: [{ required: true, message: "请选择顶级菜单", trigger: "blur" }],
|
parentId: [{ required: true, message: "请选择顶级菜单", trigger: "blur" }],
|
||||||
@@ -578,8 +448,10 @@ function handleMenuTypeChange() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 菜单保存提交 */
|
/**
|
||||||
function submitForm() {
|
* 提交表单
|
||||||
|
*/
|
||||||
|
function handleSubmit() {
|
||||||
menuFormRef.value.validate((isValid: boolean) => {
|
menuFormRef.value.validate((isValid: boolean) => {
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
const menuId = formData.value.id;
|
const menuId = formData.value.id;
|
||||||
|
|||||||
@@ -27,13 +27,8 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-card shadow="never" class="table-wrapper">
|
<el-card shadow="never">
|
||||||
<el-table
|
<el-table ref="dataTableRef" v-loading="loading" :data="pageData" highlight-current-row>
|
||||||
ref="dataTableRef"
|
|
||||||
v-loading="loading"
|
|
||||||
:data="pageData"
|
|
||||||
highlight-current-row
|
|
||||||
>
|
|
||||||
<el-table-column type="index" label="序号" width="60" />
|
<el-table-column type="index" label="序号" width="60" />
|
||||||
<el-table-column label="通知标题" prop="title" min-width="200" />
|
<el-table-column label="通知标题" prop="title" min-width="200" />
|
||||||
<el-table-column align="center" label="通知类型" width="150">
|
<el-table-column align="center" label="通知类型" width="150">
|
||||||
@@ -41,12 +36,7 @@
|
|||||||
<DictLabel v-model="scope.row.type" code="notice_type" />
|
<DictLabel v-model="scope.row.type" code="notice_type" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column align="center" label="发布人" prop="publisherName" width="100" />
|
||||||
align="center"
|
|
||||||
label="发布人"
|
|
||||||
prop="publisherName"
|
|
||||||
width="100"
|
|
||||||
/>
|
|
||||||
<el-table-column align="center" label="通知等级" width="100">
|
<el-table-column align="center" label="通知等级" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<DictLabel v-model="scope.row.level" code="notice_level" />
|
<DictLabel v-model="scope.row.level" code="notice_level" />
|
||||||
@@ -60,12 +50,7 @@
|
|||||||
width="150"
|
width="150"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column align="center" label="发布人" prop="publisherName" width="150" />
|
||||||
align="center"
|
|
||||||
label="发布人"
|
|
||||||
prop="publisherName"
|
|
||||||
width="150"
|
|
||||||
/>
|
|
||||||
<el-table-column align="center" label="状态" width="100">
|
<el-table-column align="center" label="状态" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag v-if="scope.row.isRead == 1" type="success">已读</el-tag>
|
<el-tag v-if="scope.row.isRead == 1" type="success">已读</el-tag>
|
||||||
@@ -74,12 +59,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column align="center" fixed="right" label="操作" width="80">
|
<el-table-column align="center" fixed="right" label="操作" width="80">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button type="primary" size="small" link @click="viewNoticeDetail(scope.row.id)">
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
link
|
|
||||||
@click="viewNoticeDetail(scope.row.id)"
|
|
||||||
>
|
|
||||||
查看
|
查看
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<div class="search-bar">
|
<div class="search-bar">
|
||||||
<el-form
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-suffix=":">
|
||||||
ref="queryFormRef"
|
|
||||||
:model="queryParams"
|
|
||||||
:inline="true"
|
|
||||||
label-suffix=":"
|
|
||||||
>
|
|
||||||
<el-form-item label="标题" prop="title">
|
<el-form-item label="标题" prop="title">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="queryParams.title"
|
v-model="queryParams.title"
|
||||||
@@ -28,14 +23,8 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery()">
|
<el-button type="primary" icon="search" @click="handleQuery()">搜索</el-button>
|
||||||
<template #icon><Search /></template>
|
<el-button icon="refresh" @click="handleResetQuery()">重置</el-button>
|
||||||
搜索
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="handleResetQuery()">
|
|
||||||
<template #icon><Refresh /></template>
|
|
||||||
重置
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
@@ -45,18 +34,18 @@
|
|||||||
<el-button
|
<el-button
|
||||||
v-hasPerm="['sys:notice:add']"
|
v-hasPerm="['sys:notice:add']"
|
||||||
type="success"
|
type="success"
|
||||||
|
icon="plus"
|
||||||
@click="handleOpenDialog()"
|
@click="handleOpenDialog()"
|
||||||
>
|
>
|
||||||
<template #icon><Plus /></template>
|
|
||||||
新增通知
|
新增通知
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-hasPerm="['sys:notice:delete']"
|
v-hasPerm="['sys:notice:delete']"
|
||||||
type="danger"
|
type="danger"
|
||||||
:disabled="ids.length === 0"
|
:disabled="selectIds.length === 0"
|
||||||
|
icon="delete"
|
||||||
@click="handleDelete()"
|
@click="handleDelete()"
|
||||||
>
|
>
|
||||||
<template #icon><Delete /></template>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -76,43 +65,23 @@
|
|||||||
<DictLabel v-model="scope.row.type" :code="'notice_type'" />
|
<DictLabel v-model="scope.row.type" :code="'notice_type'" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column align="center" label="发布人" prop="publisherName" width="150" />
|
||||||
align="center"
|
|
||||||
label="发布人"
|
|
||||||
prop="publisherName"
|
|
||||||
width="150"
|
|
||||||
/>
|
|
||||||
<el-table-column align="center" label="通知等级" width="100">
|
<el-table-column align="center" label="通知等级" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<DictLabel v-model="scope.row.level" code="notice_level" />
|
<DictLabel v-model="scope.row.level" code="notice_level" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column align="center" label="通告目标类型" prop="targetType" min-width="100">
|
||||||
align="center"
|
|
||||||
label="通告目标类型"
|
|
||||||
prop="targetType"
|
|
||||||
min-width="100"
|
|
||||||
>
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag v-if="scope.row.targetType == 1" type="warning">
|
<el-tag v-if="scope.row.targetType == 1" type="warning">全体</el-tag>
|
||||||
全体
|
<el-tag v-if="scope.row.targetType == 2" type="success">指定</el-tag>
|
||||||
</el-tag>
|
|
||||||
<el-tag v-if="scope.row.targetType == 2" type="success">
|
|
||||||
指定
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column align="center" label="发布状态" min-width="100">
|
<el-table-column align="center" label="发布状态" min-width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag v-if="scope.row.publishStatus == 0" type="info">
|
<el-tag v-if="scope.row.publishStatus == 0" type="info">未发布</el-tag>
|
||||||
未发布
|
<el-tag v-if="scope.row.publishStatus == 1" type="success">已发布</el-tag>
|
||||||
</el-tag>
|
<el-tag v-if="scope.row.publishStatus == -1" type="warning">已撤回</el-tag>
|
||||||
<el-tag v-if="scope.row.publishStatus == 1" type="success">
|
|
||||||
已发布
|
|
||||||
</el-tag>
|
|
||||||
<el-tag v-if="scope.row.publishStatus == -1" type="warning">
|
|
||||||
已撤回
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作时间" width="250">
|
<el-table-column label="操作时间" width="250">
|
||||||
@@ -126,10 +95,7 @@
|
|||||||
<span>发布时间:</span>
|
<span>发布时间:</span>
|
||||||
<span>{{ scope.row.publishTime || "-" }}</span>
|
<span>{{ scope.row.publishTime || "-" }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-else-if="scope.row.publishStatus === -1" class="flex-x-start">
|
||||||
v-else-if="scope.row.publishStatus === -1"
|
|
||||||
class="flex-x-start"
|
|
||||||
>
|
|
||||||
<span>撤回时间:</span>
|
<span>撤回时间:</span>
|
||||||
<span>{{ scope.row.revokeTime || "-" }}</span>
|
<span>{{ scope.row.revokeTime || "-" }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -141,7 +107,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
size="small"
|
||||||
link
|
link
|
||||||
@click="openNoticeDetailDialog(scope.row.id)"
|
@click="handleOpenNoticeDetailDialog(scope.row.id)"
|
||||||
>
|
>
|
||||||
查看
|
查看
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -151,7 +117,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
size="small"
|
||||||
link
|
link
|
||||||
@click="handlePublishNotice(scope.row.id)"
|
@click="handlePublish(scope.row.id)"
|
||||||
>
|
>
|
||||||
发布
|
发布
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -161,7 +127,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
size="small"
|
||||||
link
|
link
|
||||||
@click="revokeNotice(scope.row.id)"
|
@click="handleRevoke(scope.row.id)"
|
||||||
>
|
>
|
||||||
撤回
|
撤回
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -206,26 +172,18 @@
|
|||||||
width="1250"
|
width="1250"
|
||||||
@close="handleCloseDialog"
|
@close="handleCloseDialog"
|
||||||
>
|
>
|
||||||
<el-form
|
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="100px">
|
||||||
ref="dataFormRef"
|
|
||||||
:model="formData"
|
|
||||||
:rules="rules"
|
|
||||||
label-width="100px"
|
|
||||||
>
|
|
||||||
<el-form-item label="通知标题" prop="title">
|
<el-form-item label="通知标题" prop="title">
|
||||||
<el-input v-model="formData.title" placeholder="通知标题" clearable />
|
<el-input v-model="formData.title" placeholder="通知标题" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="通知内容" prop="content">
|
<el-form-item label="通知内容" prop="content">
|
||||||
<WangEditor
|
<WangEditor v-model="formData.content" style="min-height: 480px; max-height: 500px" />
|
||||||
v-model="formData.content"
|
|
||||||
style="min-height: 480px; max-height: 500px"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="通知类型" prop="type">
|
<el-form-item label="通知类型" prop="type">
|
||||||
<Dict v-model="formData.type" type="button" code="notice_type" />
|
<Dict v-model="formData.type" code="notice_type" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="通知等级" prop="level">
|
<el-form-item label="通知等级" prop="level">
|
||||||
<Dict v-model="formData.level" type="button" code="notice_level" />
|
<Dict v-model="formData.level" code="notice_level" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="目标类型" prop="targetType">
|
<el-form-item label="目标类型" prop="targetType">
|
||||||
<el-radio-group v-model="formData.targetType">
|
<el-radio-group v-model="formData.targetType">
|
||||||
@@ -233,17 +191,8 @@
|
|||||||
<el-radio :value="2">指定</el-radio>
|
<el-radio :value="2">指定</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item v-if="formData.targetType == 2" label="指定用户" prop="targetUserIds">
|
||||||
v-if="formData.targetType == 2"
|
<el-select v-model="formData.targetUserIds" multiple search placeholder="请选择指定用户">
|
||||||
label="指定用户"
|
|
||||||
prop="targetUserIds"
|
|
||||||
>
|
|
||||||
<el-select
|
|
||||||
v-model="formData.targetUserIds"
|
|
||||||
multiple
|
|
||||||
search
|
|
||||||
placeholder="请选择指定用户"
|
|
||||||
>
|
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in userOptions"
|
v-for="item in userOptions"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
@@ -271,11 +220,7 @@ defineOptions({
|
|||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
import NoticeAPI, {
|
import NoticeAPI, { NoticePageVO, NoticeForm, NoticePageQuery } from "@/api/system/notice";
|
||||||
NoticePageVO,
|
|
||||||
NoticeForm,
|
|
||||||
NoticePageQuery,
|
|
||||||
} from "@/api/system/notice";
|
|
||||||
import UserAPI from "@/api/system/user";
|
import UserAPI from "@/api/system/user";
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref(ElForm);
|
||||||
@@ -283,7 +228,7 @@ const dataFormRef = ref(ElForm);
|
|||||||
const noticeDetailRef = ref();
|
const noticeDetailRef = ref();
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const ids = ref<number[]>([]);
|
const selectIds = ref<number[]>([]);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const queryParams = reactive<NoticePageQuery>({
|
const queryParams = reactive<NoticePageQuery>({
|
||||||
@@ -327,7 +272,7 @@ const rules = reactive({
|
|||||||
type: [{ required: true, message: "请选择通知类型", trigger: "change" }],
|
type: [{ required: true, message: "请选择通知类型", trigger: "change" }],
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 查询通知公告 */
|
// 查询通知公告
|
||||||
function handleQuery() {
|
function handleQuery() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
NoticeAPI.getPage(queryParams)
|
NoticeAPI.getPage(queryParams)
|
||||||
@@ -340,19 +285,19 @@ function handleQuery() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 重置通知公告查询 */
|
// 重置查询
|
||||||
function handleResetQuery() {
|
function handleResetQuery() {
|
||||||
queryFormRef.value!.resetFields();
|
queryFormRef.value!.resetFields();
|
||||||
queryParams.pageNum = 1;
|
queryParams.pageNum = 1;
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 行复选框选中记录选中ID集合 */
|
// 行复选框选中项变化
|
||||||
function handleSelectionChange(selection: any) {
|
function handleSelectionChange(selection: any) {
|
||||||
ids.value = selection.map((item: any) => item.id);
|
selectIds.value = selection.map((item: any) => item.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 打开通知公告弹窗 */
|
// 打开通知公告弹窗
|
||||||
function handleOpenDialog(id?: number) {
|
function handleOpenDialog(id?: number) {
|
||||||
UserAPI.getOptions().then((data) => {
|
UserAPI.getOptions().then((data) => {
|
||||||
userOptions.value = data;
|
userOptions.value = data;
|
||||||
@@ -370,21 +315,23 @@ function handleOpenDialog(id?: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePublishNotice(id: number) {
|
// 发布通知公告
|
||||||
|
function handlePublish(id: number) {
|
||||||
NoticeAPI.publish(id).then(() => {
|
NoticeAPI.publish(id).then(() => {
|
||||||
ElMessage.success("发布成功");
|
ElMessage.success("发布成功");
|
||||||
handleQuery();
|
handleQuery();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function revokeNotice(id: number) {
|
// 撤回通知公告
|
||||||
|
function handleRevoke(id: number) {
|
||||||
NoticeAPI.revoke(id).then(() => {
|
NoticeAPI.revoke(id).then(() => {
|
||||||
ElMessage.success("撤回成功");
|
ElMessage.success("撤回成功");
|
||||||
handleQuery();
|
handleQuery();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 提交通知公告表单 */
|
// 通知公告表单提交
|
||||||
function handleSubmit() {
|
function handleSubmit() {
|
||||||
dataFormRef.value.validate((valid: any) => {
|
dataFormRef.value.validate((valid: any) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
@@ -411,17 +358,23 @@ function handleSubmit() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 关闭通知公告弹窗 */
|
// 重置表单
|
||||||
function handleCloseDialog() {
|
function resetForm() {
|
||||||
dialog.visible = false;
|
|
||||||
dataFormRef.value.resetFields();
|
dataFormRef.value.resetFields();
|
||||||
dataFormRef.value.clearValidate();
|
dataFormRef.value.clearValidate();
|
||||||
formData.id = undefined;
|
formData.id = undefined;
|
||||||
|
formData.targetType = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除通知公告 */
|
// 关闭通知公告弹窗
|
||||||
|
function handleCloseDialog() {
|
||||||
|
dialog.visible = false;
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除通知公告
|
||||||
function handleDelete(id?: number) {
|
function handleDelete(id?: number) {
|
||||||
const deleteIds = [id || ids.value].join(",");
|
const deleteIds = [id || selectIds.value].join(",");
|
||||||
if (!deleteIds) {
|
if (!deleteIds) {
|
||||||
ElMessage.warning("请勾选删除项");
|
ElMessage.warning("请勾选删除项");
|
||||||
return;
|
return;
|
||||||
@@ -447,8 +400,8 @@ function handleDelete(id?: number) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 打开通知公告详情弹窗 */
|
// 打开通知公告详情弹窗
|
||||||
function openNoticeDetailDialog(id: number) {
|
function handleOpenNoticeDetailDialog(id: number) {
|
||||||
noticeDetailRef.value.openNotice(id);
|
noticeDetailRef.value.openNotice(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,30 +12,16 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleQuery">
|
<el-button type="primary" icon="search" @click="handleQuery">搜索</el-button>
|
||||||
<template #icon><Search /></template>
|
<el-button icon="refresh" @click="handleResetQuery">重置</el-button>
|
||||||
搜索
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="handleResetQuery">
|
|
||||||
<template #icon><Refresh /></template>
|
|
||||||
重置
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="never">
|
||||||
<div class="mb-10px">
|
<div class="mb-10px">
|
||||||
<el-button type="success" @click="handleOpenDialog()">
|
<el-button type="success" icon="plus" @click="handleOpenDialog()">新增</el-button>
|
||||||
<template #icon><Plus /></template>
|
<el-button type="danger" :disabled="ids.length === 0" icon="delete" @click="handleDelete()">
|
||||||
新增
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
type="danger"
|
|
||||||
:disabled="ids.length === 0"
|
|
||||||
@click="handleDelete()"
|
|
||||||
>
|
|
||||||
<template #icon><Delete /></template>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -110,12 +96,7 @@
|
|||||||
width="500px"
|
width="500px"
|
||||||
@close="handleCloseDialog"
|
@close="handleCloseDialog"
|
||||||
>
|
>
|
||||||
<el-form
|
<el-form ref="roleFormRef" :model="formData" :rules="rules" label-width="100px">
|
||||||
ref="roleFormRef"
|
|
||||||
:model="formData"
|
|
||||||
:rules="rules"
|
|
||||||
label-width="100px"
|
|
||||||
>
|
|
||||||
<el-form-item label="角色名称" prop="name">
|
<el-form-item label="角色名称" prop="name">
|
||||||
<el-input v-model="formData.name" placeholder="请输入角色名称" />
|
<el-input v-model="formData.name" placeholder="请输入角色名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -165,12 +146,7 @@
|
|||||||
size="500"
|
size="500"
|
||||||
>
|
>
|
||||||
<div class="flex-x-between">
|
<div class="flex-x-between">
|
||||||
<el-input
|
<el-input v-model="permKeywords" clearable class="w-[150px]" placeholder="菜单权限名称">
|
||||||
v-model="permKeywords"
|
|
||||||
clearable
|
|
||||||
class="w-[150px]"
|
|
||||||
placeholder="菜单权限名称"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<Search />
|
<Search />
|
||||||
</template>
|
</template>
|
||||||
@@ -195,9 +171,7 @@
|
|||||||
<template #content>
|
<template #content>
|
||||||
如果只需勾选菜单权限,不需要勾选子菜单或者按钮权限,请关闭父子联动
|
如果只需勾选菜单权限,不需要勾选子菜单或者按钮权限,请关闭父子联动
|
||||||
</template>
|
</template>
|
||||||
<el-icon
|
<el-icon class="ml-1 color-[--el-color-primary] inline-block cursor-pointer">
|
||||||
class="ml-1 color-[--el-color-primary] inline-block cursor-pointer"
|
|
||||||
>
|
|
||||||
<QuestionFilled />
|
<QuestionFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
@@ -220,9 +194,7 @@
|
|||||||
</el-tree>
|
</el-tree>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button type="primary" @click="handleAssignPermSubmit">
|
<el-button type="primary" @click="handleAssignPermSubmit">确 定</el-button>
|
||||||
确 定
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="assignPermDialogVisible = false">取 消</el-button>
|
<el-button @click="assignPermDialogVisible = false">取 消</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -236,11 +208,7 @@ defineOptions({
|
|||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
import RoleAPI, {
|
import RoleAPI, { RolePageVO, RoleForm, RolePageQuery } from "@/api/system/role";
|
||||||
RolePageVO,
|
|
||||||
RoleForm,
|
|
||||||
RolePageQuery,
|
|
||||||
} from "@/api/system/role";
|
|
||||||
import MenuAPI from "@/api/system/menu";
|
import MenuAPI from "@/api/system/menu";
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref(ElForm);
|
||||||
@@ -414,9 +382,7 @@ async function handleOpenAssignPermDialog(row: RolePageVO) {
|
|||||||
RoleAPI.getRoleMenuIds(roleId)
|
RoleAPI.getRoleMenuIds(roleId)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
const checkedMenuIds = data;
|
const checkedMenuIds = data;
|
||||||
checkedMenuIds.forEach((menuId) =>
|
checkedMenuIds.forEach((menuId) => permTreeRef.value!.setChecked(menuId, true, false));
|
||||||
permTreeRef.value!.setChecked(menuId, true, false)
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user