parent
a240ff04d2
commit
f797606c44
|
|
@ -5,4 +5,10 @@ NODE_ENV='development'
|
||||||
|
|
||||||
VITE_APP_TITLE = 'vue3-element-admin'
|
VITE_APP_TITLE = 'vue3-element-admin'
|
||||||
VITE_APP_PORT = 3000
|
VITE_APP_PORT = 3000
|
||||||
|
|
||||||
|
# API请求前缀
|
||||||
VITE_APP_BASE_API = '/dev-api'
|
VITE_APP_BASE_API = '/dev-api'
|
||||||
|
|
||||||
|
# proxy代理配置
|
||||||
|
VITE_APP_TARGET_URL = 'http://localhost:3000'
|
||||||
|
VITE_APP_TARGET_BASE_API = ''
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,10 @@
|
||||||
|
|
||||||
VITE_APP_TITLE = 'vue3-element-admin'
|
VITE_APP_TITLE = 'vue3-element-admin'
|
||||||
VITE_APP_PORT = 3000
|
VITE_APP_PORT = 3000
|
||||||
VITE_APP_BASE_API = '/prod-api'
|
|
||||||
|
# API请求前缀
|
||||||
|
VITE_APP_BASE_API = 'http://vapi.youlai.tech'
|
||||||
|
|
||||||
|
# proxy代理配置
|
||||||
|
VITE_APP_TARGET_URL = "http://vapi.youlai.tech"
|
||||||
|
VITE_APP_TARGET_BASE_API = ''
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,6 @@ NODE_ENV='staging'
|
||||||
|
|
||||||
VITE_APP_TITLE = 'vue3-element-admin'
|
VITE_APP_TITLE = 'vue3-element-admin'
|
||||||
VITE_APP_PORT = 3000
|
VITE_APP_PORT = 3000
|
||||||
|
|
||||||
|
VITE_APP_TARGET_URL = 'http://localhost:3000';
|
||||||
VITE_APP_BASE_API = '/prod--api'
|
VITE_APP_BASE_API = '/prod--api'
|
||||||
|
|
|
||||||
|
|
@ -266,4 +266,4 @@
|
||||||
"watchWithFilter": true,
|
"watchWithFilter": true,
|
||||||
"whenever": true
|
"whenever": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
root: true,
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
es2021: true,
|
es2021: true,
|
||||||
|
|
@ -10,11 +11,16 @@ module.exports = {
|
||||||
"plugin:vue/vue3-recommended",
|
"plugin:vue/vue3-recommended",
|
||||||
"./.eslintrc-auto-import.json",
|
"./.eslintrc-auto-import.json",
|
||||||
"prettier",
|
"prettier",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"plugin:prettier/recommended",
|
||||||
],
|
],
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
ecmaVersion: "latest",
|
ecmaVersion: "latest",
|
||||||
sourceType: "module",
|
sourceType: "module",
|
||||||
parser: "@typescript-eslint/parser",
|
parser: "@typescript-eslint/parser",
|
||||||
|
project: "./tsconfig.*?.json",
|
||||||
|
createDefaultProgram: false,
|
||||||
|
extraFileExtensions: [".vue"],
|
||||||
},
|
},
|
||||||
plugins: ["vue", "@typescript-eslint"],
|
plugins: ["vue", "@typescript-eslint"],
|
||||||
rules: {
|
rules: {
|
||||||
|
|
@ -23,6 +29,41 @@ module.exports = {
|
||||||
"@typescript-eslint/no-explicit-any": "off", // 关闭any类型的警告
|
"@typescript-eslint/no-explicit-any": "off", // 关闭any类型的警告
|
||||||
"vue/no-v-model-argument": "off",
|
"vue/no-v-model-argument": "off",
|
||||||
"@typescript-eslint/no-non-null-assertion": "off",
|
"@typescript-eslint/no-non-null-assertion": "off",
|
||||||
|
"@typescript-eslint/ban-ts-ignore": "off",
|
||||||
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
|
"@typescript-eslint/ban-types": "off",
|
||||||
|
"@typescript-eslint/explicit-function-return-type": "off",
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/no-var-requires": "off",
|
||||||
|
"@typescript-eslint/no-empty-function": "off",
|
||||||
|
"@typescript-eslint/no-use-before-define": "off",
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "off",
|
||||||
|
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||||
|
"vue/script-setup-uses-vars": "error",
|
||||||
|
"vue/no-reserved-component-names": "off",
|
||||||
|
"vue/custom-event-name-casing": "off",
|
||||||
|
"vue/attributes-order": "off",
|
||||||
|
"vue/one-component-per-file": "off",
|
||||||
|
"vue/html-closing-bracket-newline": "off",
|
||||||
|
"vue/max-attributes-per-line": "off",
|
||||||
|
"vue/multiline-html-element-content-newline": "off",
|
||||||
|
"vue/singleline-html-element-content-newline": "off",
|
||||||
|
"vue/attribute-hyphenation": "off",
|
||||||
|
"vue/require-default-prop": "off",
|
||||||
|
"vue/require-explicit-emits": "off",
|
||||||
|
"vue/html-self-closing": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
html: {
|
||||||
|
void: "always",
|
||||||
|
normal: "never",
|
||||||
|
component: "always",
|
||||||
|
},
|
||||||
|
svg: "always",
|
||||||
|
math: "always",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"vue/multi-word-component-names": "off",
|
||||||
},
|
},
|
||||||
// eslint不能对html文件生效
|
// eslint不能对html文件生效
|
||||||
overrides: [
|
overrides: [
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ dist-ssr
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
|
||||||
*.suo
|
*.suo
|
||||||
*.ntvs*
|
*.ntvs*
|
||||||
*.njsproj
|
*.njsproj
|
||||||
|
|
@ -15,3 +14,4 @@ dist-ssr
|
||||||
|
|
||||||
package-lock.json
|
package-lock.json
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
|
stats.html
|
||||||
|
|
|
||||||
|
|
@ -8,3 +8,4 @@ public
|
||||||
*.md
|
*.md
|
||||||
|
|
||||||
src/assets
|
src/assets
|
||||||
|
stats.html
|
||||||
|
|
|
||||||
|
|
@ -8,3 +8,4 @@ public
|
||||||
*.md
|
*.md
|
||||||
|
|
||||||
src/assets
|
src/assets
|
||||||
|
stats.html
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"recommendations": ["Vue.volar"]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,146 @@
|
||||||
|
{
|
||||||
|
"typescript.tsdk": "./node_modules/typescript/lib",
|
||||||
|
"npm.packageManager": "pnpm",
|
||||||
|
"editor.tabSize": 2,
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
"files.eol": "\n",
|
||||||
|
"search.exclude": {
|
||||||
|
"**/node_modules": true,
|
||||||
|
"**/*.log": true,
|
||||||
|
"**/*.log*": true,
|
||||||
|
"**/bower_components": true,
|
||||||
|
"**/dist": true,
|
||||||
|
"**/elehukouben": true,
|
||||||
|
"**/.git": true,
|
||||||
|
"**/.gitignore": true,
|
||||||
|
"**/.svn": true,
|
||||||
|
"**/.DS_Store": true,
|
||||||
|
"**/.idea": true,
|
||||||
|
"**/.vscode": false,
|
||||||
|
"**/yarn.lock": true,
|
||||||
|
"**/tmp": true,
|
||||||
|
"out": true,
|
||||||
|
"dist": true,
|
||||||
|
"node_modules": true,
|
||||||
|
"CHANGELOG.md": true,
|
||||||
|
"examples": true,
|
||||||
|
"res": true,
|
||||||
|
"screenshots": true,
|
||||||
|
"yarn-error.log": true,
|
||||||
|
"**/.yarn": true
|
||||||
|
},
|
||||||
|
"files.exclude": {
|
||||||
|
"**/.cache": true,
|
||||||
|
"**/.editorconfig": true,
|
||||||
|
"**/.eslintcache": true,
|
||||||
|
"**/bower_components": true,
|
||||||
|
"**/.idea": true,
|
||||||
|
"**/tmp": true,
|
||||||
|
"**/.git": true,
|
||||||
|
"**/.svn": true,
|
||||||
|
"**/.hg": true,
|
||||||
|
"**/CVS": true,
|
||||||
|
"**/.DS_Store": true
|
||||||
|
},
|
||||||
|
"files.watcherExclude": {
|
||||||
|
"**/.git/objects/**": true,
|
||||||
|
"**/.git/subtree-cache/**": true,
|
||||||
|
"**/.vscode/**": true,
|
||||||
|
"**/node_modules/**": true,
|
||||||
|
"**/tmp/**": true,
|
||||||
|
"**/bower_components/**": true,
|
||||||
|
"**/dist/**": true,
|
||||||
|
"**/yarn.lock": true
|
||||||
|
},
|
||||||
|
"material-icon-theme.folders.color": "#42a5f5",
|
||||||
|
"material-icon-theme.folders.theme": "specific",
|
||||||
|
"material-icon-theme.activeIconPack": "vue_vuex",
|
||||||
|
"path-intellisense.mappings": {
|
||||||
|
"@/": "${workspaceRoot}/src/"
|
||||||
|
},
|
||||||
|
"[javascriptreact]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[typescript]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[typescriptreact]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[html]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[css]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[less]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[scss]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[markdown]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
|
||||||
|
"source.fixAll.eslint": true
|
||||||
|
},
|
||||||
|
"[vue]": {
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll.eslint": true,
|
||||||
|
"source.fixAll.stylelint": true
|
||||||
|
},
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"i18n-ally.localesPaths": ["src/locales/lang"],
|
||||||
|
"i18n-ally.keystyle": "nested",
|
||||||
|
"i18n-ally.sortKeys": true,
|
||||||
|
"i18n-ally.namespace": true,
|
||||||
|
"i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
|
||||||
|
"i18n-ally.enabledParsers": ["ts"],
|
||||||
|
"i18n-ally.sourceLanguage": "en",
|
||||||
|
"i18n-ally.displayLanguage": "zh-CN",
|
||||||
|
"i18n-ally.enabledFrameworks": ["vue", "react"],
|
||||||
|
"cSpell.words": [
|
||||||
|
"antd",
|
||||||
|
"antv",
|
||||||
|
"brotli",
|
||||||
|
"browserslist",
|
||||||
|
"codemirror",
|
||||||
|
"commitlint",
|
||||||
|
"cropperjs",
|
||||||
|
"echarts",
|
||||||
|
"ERUDA",
|
||||||
|
"esnext",
|
||||||
|
"esno",
|
||||||
|
"iconify",
|
||||||
|
"INTLIFY",
|
||||||
|
"lint-staged",
|
||||||
|
"lintstagedrc",
|
||||||
|
"logicflow",
|
||||||
|
"mkcert",
|
||||||
|
"mockjs",
|
||||||
|
"nprogress",
|
||||||
|
"persistedstate",
|
||||||
|
"pinia",
|
||||||
|
"pnpm",
|
||||||
|
"qrcode",
|
||||||
|
"sider",
|
||||||
|
"sortablejs",
|
||||||
|
"stylelint",
|
||||||
|
"tailwindcss",
|
||||||
|
"tdesign",
|
||||||
|
"tinymce",
|
||||||
|
"unocss",
|
||||||
|
"unplugin",
|
||||||
|
"vben",
|
||||||
|
"vditor",
|
||||||
|
"Vite",
|
||||||
|
"vitejs",
|
||||||
|
"vueuse",
|
||||||
|
"windi",
|
||||||
|
"windicss",
|
||||||
|
"zxcvbn"
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,341 @@
|
||||||
|
import { MockMethod } from "vite-plugin-mock";
|
||||||
|
const url = "/api/v1/menus/routes";
|
||||||
|
const method = "get";
|
||||||
|
const data = {
|
||||||
|
code: "00000",
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
path: "/system",
|
||||||
|
component: "Layout",
|
||||||
|
redirect: "/system/user",
|
||||||
|
meta: {
|
||||||
|
title: "系统管理",
|
||||||
|
icon: "system",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "user",
|
||||||
|
component: "system/user/index",
|
||||||
|
name: "User",
|
||||||
|
meta: {
|
||||||
|
title: "用户管理",
|
||||||
|
icon: "user",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "role",
|
||||||
|
component: "system/role/index",
|
||||||
|
name: "Role",
|
||||||
|
meta: {
|
||||||
|
title: "角色管理",
|
||||||
|
icon: "role",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "menu",
|
||||||
|
component: "system/menu/index",
|
||||||
|
name: "Menu",
|
||||||
|
meta: {
|
||||||
|
title: "菜单管理",
|
||||||
|
icon: "menu",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "dept",
|
||||||
|
component: "system/dept/index",
|
||||||
|
name: "Dept",
|
||||||
|
meta: {
|
||||||
|
title: "部门管理",
|
||||||
|
icon: "tree",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "dict",
|
||||||
|
component: "system/dict/index",
|
||||||
|
name: "Dict",
|
||||||
|
meta: {
|
||||||
|
title: "字典管理",
|
||||||
|
icon: "dict",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/api",
|
||||||
|
component: "Layout",
|
||||||
|
meta: {
|
||||||
|
title: "接口",
|
||||||
|
icon: "api",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "apidoc",
|
||||||
|
component: "demo/api-doc",
|
||||||
|
name: "Apidoc",
|
||||||
|
meta: {
|
||||||
|
title: "接口文档",
|
||||||
|
icon: "api",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/external-link",
|
||||||
|
component: "Layout",
|
||||||
|
redirect: "noredirect",
|
||||||
|
meta: {
|
||||||
|
title: "外部链接",
|
||||||
|
icon: "link",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "https://juejin.cn/post/7228990409909108793",
|
||||||
|
meta: {
|
||||||
|
title: "document",
|
||||||
|
icon: "document",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/multi-level",
|
||||||
|
component: "Layout",
|
||||||
|
redirect: "/multi-level/multi-level1",
|
||||||
|
meta: {
|
||||||
|
title: "多级菜单",
|
||||||
|
icon: "multi_level",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "multi-level1",
|
||||||
|
component: "demo/multi-level/level1",
|
||||||
|
redirect: "/multi-level/multi-level2",
|
||||||
|
meta: {
|
||||||
|
title: "菜单一级",
|
||||||
|
icon: "",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "multi-level2",
|
||||||
|
component: "demo/multi-level/children/level2",
|
||||||
|
redirect: "/multi-level/multi-level2/multi-level3-1",
|
||||||
|
meta: {
|
||||||
|
title: "菜单二级",
|
||||||
|
icon: "",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "multi-level3-1",
|
||||||
|
component: "demo/multi-level/children/children/level3-1",
|
||||||
|
name: "MultiLevel31",
|
||||||
|
meta: {
|
||||||
|
title: "菜单三级-1",
|
||||||
|
icon: "",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "multi-level3-2",
|
||||||
|
component: "demo/multi-level/children/children/level3-2",
|
||||||
|
name: "MultiLevel32",
|
||||||
|
meta: {
|
||||||
|
title: "菜单三级-2",
|
||||||
|
icon: "",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/component",
|
||||||
|
component: "Layout",
|
||||||
|
meta: {
|
||||||
|
title: "组件封装",
|
||||||
|
icon: "menu",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "wang-editor",
|
||||||
|
component: "demo/wang-editor",
|
||||||
|
name: "WangEditor",
|
||||||
|
meta: {
|
||||||
|
title: "富文本编辑器",
|
||||||
|
icon: "",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "upload",
|
||||||
|
component: "demo/upload",
|
||||||
|
name: "Upload",
|
||||||
|
meta: {
|
||||||
|
title: "图片上传",
|
||||||
|
icon: "",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "icon-selector",
|
||||||
|
component: "demo/icon-selector",
|
||||||
|
name: "IconSelector",
|
||||||
|
meta: {
|
||||||
|
title: "图标选择器",
|
||||||
|
icon: "",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "dict-demo",
|
||||||
|
component: "demo/dict",
|
||||||
|
name: "DictDemo",
|
||||||
|
meta: {
|
||||||
|
title: "字典组件",
|
||||||
|
icon: "",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "taginput",
|
||||||
|
component: "demo/taginput",
|
||||||
|
name: "Taginput",
|
||||||
|
meta: {
|
||||||
|
title: "标签输入框",
|
||||||
|
icon: "",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "signature",
|
||||||
|
component: "demo/signature",
|
||||||
|
name: "Signature",
|
||||||
|
meta: {
|
||||||
|
title: "签名",
|
||||||
|
icon: "",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "table",
|
||||||
|
component: "demo/table",
|
||||||
|
name: "Table",
|
||||||
|
meta: {
|
||||||
|
title: "表格",
|
||||||
|
icon: "",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/function",
|
||||||
|
component: "Layout",
|
||||||
|
meta: {
|
||||||
|
title: "功能演示",
|
||||||
|
icon: "menu",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "websocket",
|
||||||
|
component: "demo/websocket",
|
||||||
|
name: "Websocket",
|
||||||
|
meta: {
|
||||||
|
title: "Websocket",
|
||||||
|
icon: "",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "other",
|
||||||
|
component: "demo/other",
|
||||||
|
meta: {
|
||||||
|
title: "敬请期待...",
|
||||||
|
icon: "",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
msg: "一切ok",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
url: url,
|
||||||
|
method: method,
|
||||||
|
response: () => {
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] as MockMethod[];
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
import { MockMethod } from "vite-plugin-mock";
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
url: "/api/hello_world",
|
||||||
|
method: "get",
|
||||||
|
response: (request) => {
|
||||||
|
return {
|
||||||
|
msg: "hello world",
|
||||||
|
headers: request.headers,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "/api/v1/auth/captcha",
|
||||||
|
method: "get",
|
||||||
|
response: () => {
|
||||||
|
return {
|
||||||
|
code: "00000",
|
||||||
|
data: {
|
||||||
|
verifyCodeKey: "534b8ef2b0a24121bec76391ddd159f9",
|
||||||
|
verifyCodeBase64:
|
||||||
|
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAAkCAIAAADNSmkJAAAFKUlEQVR4Xu2ZXUwcVRiGV70wMWo08V5NvPXCrDbFaGpMaZW2hqQxaoiJTRsaMBCNSYtpa2JTKiFSelFa+Q/QZcMWqEhBlh+htbEpZhMrBQrlJ0hBywLLyrJ0WZbje3bqOvPNLHPWrDvdOE9ONmfe78zkzMs335wzWJhJQrBQweS/wTQ6QWgYHdoIOcecOe05O+t2WkutO+p2ZF3Ksg/YV9ZW6FATYajR3nveg60H9327r3O8c35lHgp+r05dPdJzBL73TPSQ8SaCKIxGLsPlop+K0JHrEkPuoT31e5qGmmjARACF0agYyGVNlyVm/pzZXrN9fHGcBkz0UBid+31u93i3XFFT80vN8cvHqWqih8Lo1NpUqS5vwh3vnd223VQ10UNh9NbyrcFQUK6oCawHUipSqGqiB83oBf+CXFGDMp1mS6OqiR4Ko7FexkpOrqhpHGw82nOUqiZ6KIzGrkRuorW0dJMmOy+hOCfYGzb2RBFv6HRO0gEJw/U7y+pgL1bwmTxexN6sZ31TdEwEhdG+gA+7EqyXpUO1uZH20cWL8hMTRt1N9tBXzCJrOIRoCPJpSO2RAp4HmtCdIfZ+2JWgEBN9LbR28seTGU0Zue1tMLp+YIAMSADzfvbkKX4/eb28j4YODiGin3heqmIlLja5hAUCu+nmGY3JWKvpMAlqNGgebsauBOvlqSX+JEx7p7EbTLen53XlzfmWUioqXikrc68Y8N2juJ/fyVsNChGHEE//rBANYWaZz+TRQqpLaBgNsPfDrgSpbS21YtV87IdjrlkX9JZbt5DOma2t9ITo5F+5glN22WwL/n+yDv00mw06orKxOqQ5+J04hhViwzAXETIcJDVm8uxZqktoGx2Nj9t43Wgaul/ERQiGQvtbWnDWgZYW9CXlQFjZ/7ciyHNn+Z2MexTimIeLz59TiIln0M1e+IbPpOAaDUnEYPTi6iqKxpbycs/qKo1tCslfKcffPn9enuMiPPY1vxO/ckeFQ4h46cdGqUWoidE/y54q5tPY5WDrGzQqIXot4BgchEE57e00IMCw2/1qZSVO/7SjA78o9INzcxsbrL+fnTnDDh9mmZn8F30oG1Hm+nABv5mQMopDS/h1HxtqTzWbABMe9sxpPoe9zezeOo1GELqWhPS8t46M0IAYHbdvR1aHbaOjbjfLz2eFhez6dba4yAfgF30o0BFVE8+Mjh/wFxPI+I5mAEHU6Ls+38vhTFwOBGhMDF8gkFpbC5ffsdv/uBs6dIj19dExEtARVXv9YNbop8NFY3aZ6gRRo+tu3IBHnzmdNCBMXldXJKPfL74WzWUJRE+coDUknqsOdZXQbAJYwluVTbOZI3Qt8GFzMwxyjo3RgBiN4fr+elXVpZGRLWXl6PdOTtJBSlBDUK/lnIrjOlrtqWYTQDJaF6FrTXu9sOa1ysrVoM5HVE1GFxZQcyJ/p+xzv6K/rbr6N6+XDpUBl0tKFIrbz78qWB6YnWFMCBld4XLBms+7df75ook/GNzb0GCV7U1Qfz9p64TyQWNjYD3qe9rj4SMJtQP3MyjSDPzWIRHPjH7X4YAvfXoPuyZf9Pbi3PcuXIh4mp3NllYC6XY79C+jl2o8PBipxjnBttn4MgMNnWgfcRJGPI2OL8hTj3LloIlmRicvBhiNykvecpqoa3RSY4DRcLAwyicuOepVR1JjgNFYHWONHL04czTX0UmNAUYD7Pr+xc4wqTHGaBb2OtZvHUmNYUazcA2J6etdUmOk0f8rTKMTxF91RG0D1SwYGwAAAABJRU5ErkJggg==",
|
||||||
|
},
|
||||||
|
msg: "一切ok",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "/api/v1/auth/login",
|
||||||
|
method: "post",
|
||||||
|
response: () => {
|
||||||
|
return {
|
||||||
|
code: "00000",
|
||||||
|
data: {
|
||||||
|
accessToken:
|
||||||
|
"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImp0aSI6IjE2YWJkNTlkOTAxNzQwZDliYmI3ZjczODBhZDkyNzNhIiwidXNlcklkIjoyLCJ1c2VybmFtZSI6ImFkbWluIiwiZGVwdElkIjoxLCJkYXRhU2NvcGUiOjEsImF1dGhvcml0aWVzIjpbIlJPTEVfQURNSU4iXSwiZXhwIjoxNjkxMTAzMzgyfQ.P4cuIfmPepl3HuguhMS7NXn5a7IUPpsLbmtA_rHOhHk",
|
||||||
|
tokenType: "Bearer",
|
||||||
|
refreshToken: null,
|
||||||
|
expires: null,
|
||||||
|
},
|
||||||
|
msg: "一切ok",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "/api/v1/users/me",
|
||||||
|
method: "get",
|
||||||
|
response: () => {
|
||||||
|
return {
|
||||||
|
code: "00000",
|
||||||
|
data: {
|
||||||
|
userId: 2,
|
||||||
|
nickname: "系统管理员",
|
||||||
|
avatar:
|
||||||
|
"https://oss.youlai.tech/youlai-boot/2023/05/16/811270ef31f548af9cffc026dfc3777b.gif",
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
perms: [
|
||||||
|
"sys:menu:delete",
|
||||||
|
"sys:dept:edit",
|
||||||
|
"sys:dict_type:add",
|
||||||
|
"sys:dict:edit",
|
||||||
|
"sys:dict:delete",
|
||||||
|
"sys:dict_type:edit",
|
||||||
|
"sys:menu:add",
|
||||||
|
"sys:user:add",
|
||||||
|
"sys:role:edit",
|
||||||
|
"sys:dept:delete",
|
||||||
|
"sys:user:edit",
|
||||||
|
"sys:user:delete",
|
||||||
|
"sys:user:reset_pwd",
|
||||||
|
"sys:dept:add",
|
||||||
|
"sys:role:delete",
|
||||||
|
"sys:dict_type:delete",
|
||||||
|
"sys:menu:edit",
|
||||||
|
"sys:dict:add",
|
||||||
|
"sys:role:add",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
msg: "一切ok",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "/api/v1/auth/logout",
|
||||||
|
method: "delete",
|
||||||
|
response: () => {
|
||||||
|
return {
|
||||||
|
code: "00000",
|
||||||
|
data: {},
|
||||||
|
msg: "string",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] as MockMethod[];
|
||||||
19
package.json
19
package.json
|
|
@ -2,11 +2,10 @@
|
||||||
"name": "vue3-element-admin",
|
"name": "vue3-element-admin",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"preinstall": "npx only-allow pnpm",
|
"preinstall": "npx only-allow pnpm",
|
||||||
"dev": "vite serve --mode development",
|
"dev": "vite serve --mode development",
|
||||||
"build:prod": "vite build --mode production &&vue-tsc --noEmit",
|
"build:prod": "vite build --mode production && vue-tsc --noEmit",
|
||||||
"prepare": "husky install",
|
"prepare": "husky install",
|
||||||
"lint:eslint": "eslint --fix --ext .ts,.js,.vue ./src ",
|
"lint:eslint": "eslint --fix --ext .ts,.js,.vue ./src ",
|
||||||
"lint:prettier": "prettier --write \"**/*.{js,cjs,ts,json,tsx,css,less,scss,vue,html,md}\"",
|
"lint:prettier": "prettier --write \"**/*.{js,cjs,ts,json,tsx,css,less,scss,vue,html,md}\"",
|
||||||
|
|
@ -68,7 +67,6 @@
|
||||||
"@types/lodash": "^4.14.195",
|
"@types/lodash": "^4.14.195",
|
||||||
"@types/nprogress": "^0.2.0",
|
"@types/nprogress": "^0.2.0",
|
||||||
"@types/path-browserify": "^1.0.0",
|
"@types/path-browserify": "^1.0.0",
|
||||||
"@types/xlsx": "^0.0.36",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.6",
|
"@typescript-eslint/eslint-plugin": "^5.59.6",
|
||||||
"@typescript-eslint/parser": "^5.59.6",
|
"@typescript-eslint/parser": "^5.59.6",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
|
|
@ -76,6 +74,7 @@
|
||||||
"cz-git": "^1.6.1",
|
"cz-git": "^1.6.1",
|
||||||
"eslint": "^8.40.0",
|
"eslint": "^8.40.0",
|
||||||
"eslint-config-prettier": "^8.8.0",
|
"eslint-config-prettier": "^8.8.0",
|
||||||
|
"eslint-plugin-import": "^2.28.0",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"eslint-plugin-vue": "^9.13.0",
|
"eslint-plugin-vue": "^9.13.0",
|
||||||
"fast-glob": "^3.2.11",
|
"fast-glob": "^3.2.11",
|
||||||
|
|
@ -85,14 +84,15 @@
|
||||||
"postcss-html": "^1.5.0",
|
"postcss-html": "^1.5.0",
|
||||||
"postcss-scss": "^4.0.6",
|
"postcss-scss": "^4.0.6",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
|
"rollup-plugin-visualizer": "^5.9.2",
|
||||||
"sass": "^1.58.3",
|
"sass": "^1.58.3",
|
||||||
"stylelint": "^15.7.0",
|
"stylelint": "^15.10.2",
|
||||||
"stylelint-config-html": "^1.1.0",
|
"stylelint-config-html": "^1.1.0",
|
||||||
"stylelint-config-recess-order": "^4.0.0",
|
"stylelint-config-recess-order": "^4.0.0",
|
||||||
"stylelint-config-recommended-scss": "11.0.0 ",
|
"stylelint-config-recommended-scss": "^12.0.0",
|
||||||
"stylelint-config-recommended-vue": "^1.4.0",
|
"stylelint-config-recommended-vue": "^1.5.0",
|
||||||
"stylelint-config-standard": "^33.0.0",
|
"stylelint-config-standard": "^34.0.0",
|
||||||
"stylelint-config-standard-scss": "^9.0.0",
|
"stylelint-config-standard-scss": "^10.0.0",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
"unocss": "^0.51.13",
|
"unocss": "^0.51.13",
|
||||||
"unplugin-auto-import": "^0.15.3",
|
"unplugin-auto-import": "^0.15.3",
|
||||||
|
|
@ -100,8 +100,9 @@
|
||||||
"unplugin-vue-components": "^0.24.1",
|
"unplugin-vue-components": "^0.24.1",
|
||||||
"vite": "^4.4.2",
|
"vite": "^4.4.2",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
|
"vite-plugin-mock": "^3.0.0",
|
||||||
"vite-plugin-svg-icons": "^2.0.1",
|
"vite-plugin-svg-icons": "^2.0.1",
|
||||||
"vue-tsc": "^1.6.5 "
|
"vue-tsc": "^1.7.0 "
|
||||||
},
|
},
|
||||||
"repository": "https://gitee.com/youlaiorg/vue3-element-admin.git",
|
"repository": "https://gitee.com/youlaiorg/vue3-element-admin.git",
|
||||||
"author": "有来开源组织",
|
"author": "有来开源组织",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ElConfigProvider } from 'element-plus';
|
import { ElConfigProvider } from "element-plus";
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from "@/store/modules/app";
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import request from '@/utils/request';
|
import request from "@/utils/request";
|
||||||
import { AxiosPromise } from 'axios';
|
import { AxiosPromise } from "axios";
|
||||||
import { DeptForm, DeptQuery, DeptVO } from './types';
|
import { DeptForm, DeptQuery, DeptVO } from "./types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门树形表格
|
* 部门树形表格
|
||||||
|
|
@ -9,9 +9,9 @@ import { DeptForm, DeptQuery, DeptVO } from './types';
|
||||||
*/
|
*/
|
||||||
export function listDepts(queryParams?: DeptQuery): AxiosPromise<DeptVO[]> {
|
export function listDepts(queryParams?: DeptQuery): AxiosPromise<DeptVO[]> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/dept',
|
url: "/api/v1/dept",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: queryParams
|
params: queryParams,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -20,8 +20,8 @@ export function listDepts(queryParams?: DeptQuery): AxiosPromise<DeptVO[]> {
|
||||||
*/
|
*/
|
||||||
export function listDeptOptions(): AxiosPromise<[]> {
|
export function listDeptOptions(): AxiosPromise<[]> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/dept/options',
|
url: "/api/v1/dept/options",
|
||||||
method: 'get'
|
method: "get",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,8 +32,8 @@ export function listDeptOptions(): AxiosPromise<[]> {
|
||||||
*/
|
*/
|
||||||
export function getDeptForm(id: number): AxiosPromise<DeptForm> {
|
export function getDeptForm(id: number): AxiosPromise<DeptForm> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/dept/' + id + '/form',
|
url: "/api/v1/dept/" + id + "/form",
|
||||||
method: 'get'
|
method: "get",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,9 +44,9 @@ export function getDeptForm(id: number): AxiosPromise<DeptForm> {
|
||||||
*/
|
*/
|
||||||
export function addDept(data: DeptForm) {
|
export function addDept(data: DeptForm) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/dept',
|
url: "/api/v1/dept",
|
||||||
method: 'post',
|
method: "post",
|
||||||
data: data
|
data: data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,9 +58,9 @@ export function addDept(data: DeptForm) {
|
||||||
*/
|
*/
|
||||||
export function updateDept(id: number, data: DeptForm) {
|
export function updateDept(id: number, data: DeptForm) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/dept/' + id,
|
url: "/api/v1/dept/" + id,
|
||||||
method: 'put',
|
method: "put",
|
||||||
data: data
|
data: data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,7 +71,7 @@ export function updateDept(id: number, data: DeptForm) {
|
||||||
*/
|
*/
|
||||||
export function deleteDept(ids: string) {
|
export function deleteDept(ids: string) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/dept/' + ids,
|
url: "/api/v1/dept/" + ids,
|
||||||
method: 'delete'
|
method: "delete",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import request from '@/utils/request';
|
import request from "@/utils/request";
|
||||||
import { AxiosPromise } from 'axios';
|
import { AxiosPromise } from "axios";
|
||||||
import { FileInfo } from './types';
|
import { FileInfo } from "./types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传文件
|
* 上传文件
|
||||||
|
|
@ -9,14 +9,14 @@ import { FileInfo } from './types';
|
||||||
*/
|
*/
|
||||||
export function uploadFileApi(file: File): AxiosPromise<FileInfo> {
|
export function uploadFileApi(file: File): AxiosPromise<FileInfo> {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', file);
|
formData.append("file", file);
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/files',
|
url: "/api/v1/files",
|
||||||
method: 'post',
|
method: "post",
|
||||||
data: formData,
|
data: formData,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'multipart/form-data'
|
"Content-Type": "multipart/form-data",
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -27,8 +27,8 @@ export function uploadFileApi(file: File): AxiosPromise<FileInfo> {
|
||||||
*/
|
*/
|
||||||
export function deleteFileApi(filePath?: string) {
|
export function deleteFileApi(filePath?: string) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/files',
|
url: "/api/v1/files",
|
||||||
method: 'delete',
|
method: "delete",
|
||||||
params: { filePath: filePath }
|
params: { filePath: filePath },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import request from '@/utils/request';
|
import request from "@/utils/request";
|
||||||
import { AxiosPromise } from 'axios';
|
import { AxiosPromise } from "axios";
|
||||||
import { MenuQuery, MenuVO, MenuForm } from './types';
|
import { MenuQuery, MenuVO, MenuForm } from "./types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取路由列表
|
* 获取路由列表
|
||||||
*/
|
*/
|
||||||
export function listRoutes() {
|
export function listRoutes() {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/menus/routes',
|
url: "/api/v1/menus/routes",
|
||||||
method: 'get'
|
method: "get",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -19,9 +19,9 @@ export function listRoutes() {
|
||||||
*/
|
*/
|
||||||
export function listMenus(queryParams: MenuQuery): AxiosPromise<MenuVO[]> {
|
export function listMenus(queryParams: MenuQuery): AxiosPromise<MenuVO[]> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/menus',
|
url: "/api/v1/menus",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: queryParams
|
params: queryParams,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,8 +30,8 @@ export function listMenus(queryParams: MenuQuery): AxiosPromise<MenuVO[]> {
|
||||||
*/
|
*/
|
||||||
export function listMenuOptions(): AxiosPromise<OptionType[]> {
|
export function listMenuOptions(): AxiosPromise<OptionType[]> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/menus/options',
|
url: "/api/v1/menus/options",
|
||||||
method: 'get'
|
method: "get",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,8 +42,8 @@ export function listMenuOptions(): AxiosPromise<OptionType[]> {
|
||||||
*/
|
*/
|
||||||
export function getMenuForm(id: number): AxiosPromise<MenuForm> {
|
export function getMenuForm(id: number): AxiosPromise<MenuForm> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/menus/' + id + '/form',
|
url: "/api/v1/menus/" + id + "/form",
|
||||||
method: 'get'
|
method: "get",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,9 +54,9 @@ export function getMenuForm(id: number): AxiosPromise<MenuForm> {
|
||||||
*/
|
*/
|
||||||
export function addMenu(data: MenuForm) {
|
export function addMenu(data: MenuForm) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/menus',
|
url: "/api/v1/menus",
|
||||||
method: 'post',
|
method: "post",
|
||||||
data: data
|
data: data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,9 +68,9 @@ export function addMenu(data: MenuForm) {
|
||||||
*/
|
*/
|
||||||
export function updateMenu(id: string, data: MenuForm) {
|
export function updateMenu(id: string, data: MenuForm) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/menus/' + id,
|
url: "/api/v1/menus/" + id,
|
||||||
method: 'put',
|
method: "put",
|
||||||
data: data
|
data: data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,7 +81,7 @@ export function updateMenu(id: string, data: MenuForm) {
|
||||||
*/
|
*/
|
||||||
export function deleteMenu(id: number) {
|
export function deleteMenu(id: number) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/menus/' + id,
|
url: "/api/v1/menus/" + id,
|
||||||
method: 'delete'
|
method: "delete",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { MenuTypeEnum } from '@/enums/MenuTypeEnum';
|
import { MenuTypeEnum } from "@/enums/MenuTypeEnum";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 菜单查询参数类型
|
* 菜单查询参数类型
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import request from '@/utils/request';
|
import request from "@/utils/request";
|
||||||
import { AxiosPromise } from 'axios';
|
import { AxiosPromise } from "axios";
|
||||||
import { RoleQuery, RolePageResult, RoleForm } from './types';
|
import { RoleQuery, RolePageResult, RoleForm } from "./types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取角色分页数据
|
* 获取角色分页数据
|
||||||
|
|
@ -11,9 +11,9 @@ export function getRolePage(
|
||||||
queryParams?: RoleQuery
|
queryParams?: RoleQuery
|
||||||
): AxiosPromise<RolePageResult> {
|
): AxiosPromise<RolePageResult> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/roles/page',
|
url: "/api/v1/roles/page",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: queryParams
|
params: queryParams,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -26,9 +26,9 @@ export function listRoleOptions(
|
||||||
queryParams?: RoleQuery
|
queryParams?: RoleQuery
|
||||||
): AxiosPromise<OptionType[]> {
|
): AxiosPromise<OptionType[]> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/roles/options',
|
url: "/api/v1/roles/options",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: queryParams
|
params: queryParams,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,8 +39,8 @@ export function listRoleOptions(
|
||||||
*/
|
*/
|
||||||
export function getRoleMenuIds(roleId: number): AxiosPromise<number[]> {
|
export function getRoleMenuIds(roleId: number): AxiosPromise<number[]> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/roles/' + roleId + '/menuIds',
|
url: "/api/v1/roles/" + roleId + "/menuIds",
|
||||||
method: 'get'
|
method: "get",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,9 +54,9 @@ export function updateRoleMenus(
|
||||||
data: number[]
|
data: number[]
|
||||||
): AxiosPromise<any> {
|
): AxiosPromise<any> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/roles/' + roleId + '/menus',
|
url: "/api/v1/roles/" + roleId + "/menus",
|
||||||
method: 'put',
|
method: "put",
|
||||||
data: data
|
data: data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,8 +67,8 @@ export function updateRoleMenus(
|
||||||
*/
|
*/
|
||||||
export function getRoleForm(id: number): AxiosPromise<RoleForm> {
|
export function getRoleForm(id: number): AxiosPromise<RoleForm> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/roles/' + id + '/form',
|
url: "/api/v1/roles/" + id + "/form",
|
||||||
method: 'get'
|
method: "get",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,9 +79,9 @@ export function getRoleForm(id: number): AxiosPromise<RoleForm> {
|
||||||
*/
|
*/
|
||||||
export function addRole(data: RoleForm) {
|
export function addRole(data: RoleForm) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/roles',
|
url: "/api/v1/roles",
|
||||||
method: 'post',
|
method: "post",
|
||||||
data: data
|
data: data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,9 +93,9 @@ export function addRole(data: RoleForm) {
|
||||||
*/
|
*/
|
||||||
export function updateRole(id: number, data: RoleForm) {
|
export function updateRole(id: number, data: RoleForm) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/roles/' + id,
|
url: "/api/v1/roles/" + id,
|
||||||
method: 'put',
|
method: "put",
|
||||||
data: data
|
data: data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@ export function updateRole(id: number, data: RoleForm) {
|
||||||
*/
|
*/
|
||||||
export function deleteRoles(ids: string) {
|
export function deleteRoles(ids: string) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/roles/' + ids,
|
url: "/api/v1/roles/" + ids,
|
||||||
method: 'delete'
|
method: "delete",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import request from '@/utils/request';
|
import request from "@/utils/request";
|
||||||
import { AxiosPromise } from 'axios';
|
import { AxiosPromise } from "axios";
|
||||||
import { UserForm, UserInfo, UserPageVO, UserQuery } from './types';
|
import { UserForm, UserInfo, UserPageVO, UserQuery } from "./types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录成功后获取用户信息(昵称、头像、权限集合和角色集合)
|
* 登录成功后获取用户信息(昵称、头像、权限集合和角色集合)
|
||||||
*/
|
*/
|
||||||
export function getUserInfo(): AxiosPromise<UserInfo> {
|
export function getUserInfo(): AxiosPromise<UserInfo> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/users/me',
|
url: "/api/v1/users/me",
|
||||||
method: 'get'
|
method: "get",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -21,9 +21,9 @@ export function getUserPage(
|
||||||
queryParams: UserQuery
|
queryParams: UserQuery
|
||||||
): AxiosPromise<PageResult<UserPageVO[]>> {
|
): AxiosPromise<PageResult<UserPageVO[]>> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/users/page',
|
url: "/api/v1/users/page",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: queryParams
|
params: queryParams,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,8 +34,8 @@ export function getUserPage(
|
||||||
*/
|
*/
|
||||||
export function getUserForm(userId: number): AxiosPromise<UserForm> {
|
export function getUserForm(userId: number): AxiosPromise<UserForm> {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/users/' + userId + '/form',
|
url: "/api/v1/users/" + userId + "/form",
|
||||||
method: 'get'
|
method: "get",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,9 +46,9 @@ export function getUserForm(userId: number): AxiosPromise<UserForm> {
|
||||||
*/
|
*/
|
||||||
export function addUser(data: any) {
|
export function addUser(data: any) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/users',
|
url: "/api/v1/users",
|
||||||
method: 'post',
|
method: "post",
|
||||||
data: data
|
data: data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,9 +60,9 @@ export function addUser(data: any) {
|
||||||
*/
|
*/
|
||||||
export function updateUser(id: number, data: UserForm) {
|
export function updateUser(id: number, data: UserForm) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/users/' + id,
|
url: "/api/v1/users/" + id,
|
||||||
method: 'put',
|
method: "put",
|
||||||
data: data
|
data: data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,9 +74,9 @@ export function updateUser(id: number, data: UserForm) {
|
||||||
*/
|
*/
|
||||||
export function updateUserStatus(id: number, status: number) {
|
export function updateUserStatus(id: number, status: number) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/users/' + id + '/status',
|
url: "/api/v1/users/" + id + "/status",
|
||||||
method: 'patch',
|
method: "patch",
|
||||||
params: { status: status }
|
params: { status: status },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,9 +88,9 @@ export function updateUserStatus(id: number, status: number) {
|
||||||
*/
|
*/
|
||||||
export function updateUserPassword(id: number, password: string) {
|
export function updateUserPassword(id: number, password: string) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/users/' + id + '/password',
|
url: "/api/v1/users/" + id + "/password",
|
||||||
method: 'patch',
|
method: "patch",
|
||||||
params: { password: password }
|
params: { password: password },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,8 +101,8 @@ export function updateUserPassword(id: number, password: string) {
|
||||||
*/
|
*/
|
||||||
export function deleteUsers(ids: string) {
|
export function deleteUsers(ids: string) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/users/' + ids,
|
url: "/api/v1/users/" + ids,
|
||||||
method: 'delete'
|
method: "delete",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,9 +113,9 @@ export function deleteUsers(ids: string) {
|
||||||
*/
|
*/
|
||||||
export function downloadTemplateApi() {
|
export function downloadTemplateApi() {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/users/template',
|
url: "/api/v1/users/template",
|
||||||
method: 'get',
|
method: "get",
|
||||||
responseType: 'arraybuffer'
|
responseType: "arraybuffer",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,10 +127,10 @@ export function downloadTemplateApi() {
|
||||||
*/
|
*/
|
||||||
export function exportUser(queryParams: UserQuery) {
|
export function exportUser(queryParams: UserQuery) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/users/_export',
|
url: "/api/v1/users/_export",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: queryParams,
|
params: queryParams,
|
||||||
responseType: 'arraybuffer'
|
responseType: "arraybuffer",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,14 +141,14 @@ export function exportUser(queryParams: UserQuery) {
|
||||||
*/
|
*/
|
||||||
export function importUser(deptId: number, file: File) {
|
export function importUser(deptId: number, file: File) {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', file);
|
formData.append("file", file);
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/users/_import',
|
url: "/api/v1/users/_import",
|
||||||
method: 'post',
|
method: "post",
|
||||||
params: { deptId: deptId },
|
params: { deptId: deptId },
|
||||||
data: formData,
|
data: formData,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'multipart/form-data'
|
"Content-Type": "multipart/form-data",
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
:key="option.value"
|
:key="option.value"
|
||||||
:label="option.label"
|
:label="option.label"
|
||||||
:value="option.value"
|
:value="option.value"
|
||||||
></el-option>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,8 @@ onMounted(() => {
|
||||||
class="cursor-pointer text-[#999] absolute right-[10px] top-0 height-[32px] leading-[32px]"
|
class="cursor-pointer text-[#999] absolute right-[10px] top-0 height-[32px] leading-[32px]"
|
||||||
@click="visible = !visible"
|
@click="visible = !visible"
|
||||||
>
|
>
|
||||||
<i-ep-caret-top v-show="visible"></i-ep-caret-top>
|
<i-ep-caret-top v-show="visible" />
|
||||||
<i-ep-caret-bottom v-show="!visible"></i-ep-caret-bottom>
|
<i-ep-caret-bottom v-show="!visible" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ onBeforeUnmount(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div ref="rightPanel" :class="{ show: show }">
|
<div ref="rightPanel" :class="{ show: show }">
|
||||||
<div class="right-panel-overlay" />
|
<div class="right-panel-overlay"></div>
|
||||||
<div class="right-panel-container">
|
<div class="right-panel-container">
|
||||||
<div
|
<div
|
||||||
class="right-panel-btn"
|
class="right-panel-btn"
|
||||||
|
|
@ -67,7 +67,7 @@ onBeforeUnmount(() => {
|
||||||
<i-ep-setting v-show="!show" />
|
<i-ep-setting v-show="!show" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<slot />
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from "@/store/modules/app";
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const sizeOptions = ref([
|
const sizeOptions = ref([
|
||||||
{ label: '默认', value: 'default' },
|
{ label: "默认", value: "default" },
|
||||||
{ label: '大型', value: 'large' },
|
{ label: "大型", value: "large" },
|
||||||
{ label: '小型', value: 'small' }
|
{ label: "小型", value: "small" },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function handleSizeChange(size: string) {
|
function handleSizeChange(size: string) {
|
||||||
appStore.changeSize(size);
|
appStore.changeSize(size);
|
||||||
ElMessage.success('切换布局大小成功');
|
ElMessage.success("切换布局大小成功");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,34 @@
|
||||||
/**
|
/**
|
||||||
* getRePosFromStr 正则匹配字段返回位置信息
|
* getRePosFromStr 正则匹配字段返回位置信息
|
||||||
* */
|
* */
|
||||||
export function getRePosFromStr(text: any = '', re: any = /\$.+?\$/g) {
|
export function getRePosFromStr(text: any = "", re: any = /\$.+?\$/g) {
|
||||||
const lines = text.split('\n')
|
const lines = text.split("\n");
|
||||||
const positions: any = []
|
const positions: any = [];
|
||||||
let m
|
let m;
|
||||||
for (let i = 0; i < lines.length; i++) {
|
for (let i = 0; i < lines.length; i++) {
|
||||||
const l = lines[i]
|
const l = lines[i];
|
||||||
while ((m = re.exec(l)) !== null) {
|
while ((m = re.exec(l)) !== null) {
|
||||||
var tag = m[0].substring(1, m[0].length - 1)
|
const tag = m[0].substring(1, m[0].length - 1);
|
||||||
positions.push({
|
positions.push({
|
||||||
line: i,
|
line: i,
|
||||||
start: m.index,
|
start: m.index,
|
||||||
stop: m.index + m[0].length,
|
stop: m.index + m[0].length,
|
||||||
tag,
|
tag,
|
||||||
})
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return positions
|
}
|
||||||
|
return positions;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 输入框模式
|
* 输入框模式
|
||||||
*/
|
*/
|
||||||
export enum MODE {
|
export enum MODE {
|
||||||
// 文本
|
// 文本
|
||||||
TEXT = 1,
|
TEXT = 1,
|
||||||
// 公式
|
// 公式
|
||||||
FORMULA,
|
FORMULA,
|
||||||
// 只允许选择tag
|
// 只允许选择tag
|
||||||
ONLYTAG,
|
ONLYTAG,
|
||||||
// 日期
|
// 日期
|
||||||
DATE
|
DATE,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,4 +71,4 @@ onBeforeUnmount(() => {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style src="@wangeditor/editor/dist/css/style.css"></style>
|
<style src="@wangeditor/editor/dist/css/style.css"></style>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import type { App } from 'vue';
|
import type { App } from "vue";
|
||||||
|
|
||||||
import { hasPerm } from './permission';
|
import { hasPerm } from "./permission";
|
||||||
|
|
||||||
// 全局注册 directive
|
// 全局注册 directive
|
||||||
export function setupDirective(app: App<Element>) {
|
export function setupDirective(app: App<Element>) {
|
||||||
// 使 v-hasPerm 在所有组件中都可用
|
// 使 v-hasPerm 在所有组件中都可用
|
||||||
app.directive('hasPerm', hasPerm);
|
app.directive("hasPerm", hasPerm);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { useUserStoreHook } from '@/store/modules/user';
|
import { useUserStoreHook } from "@/store/modules/user";
|
||||||
import { Directive, DirectiveBinding } from 'vue';
|
import { Directive, DirectiveBinding } from "vue";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按钮权限
|
* 按钮权限
|
||||||
|
|
@ -8,7 +8,7 @@ export const hasPerm: Directive = {
|
||||||
mounted(el: HTMLElement, binding: DirectiveBinding) {
|
mounted(el: HTMLElement, binding: DirectiveBinding) {
|
||||||
// 「超级管理员」拥有所有的按钮权限
|
// 「超级管理员」拥有所有的按钮权限
|
||||||
const { roles, perms } = useUserStoreHook();
|
const { roles, perms } = useUserStoreHook();
|
||||||
if (roles.includes('ROOT')) {
|
if (roles.includes("ROOT")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// 「其他角色」按钮权限校验
|
// 「其他角色」按钮权限校验
|
||||||
|
|
@ -16,7 +16,7 @@ export const hasPerm: Directive = {
|
||||||
if (value) {
|
if (value) {
|
||||||
const requiredPerms = value; // DOM绑定需要的按钮权限标识
|
const requiredPerms = value; // DOM绑定需要的按钮权限标识
|
||||||
|
|
||||||
const hasPerm = perms?.some(perm => {
|
const hasPerm = perms?.some((perm) => {
|
||||||
return requiredPerms.includes(perm);
|
return requiredPerms.includes(perm);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -28,7 +28,7 @@ export const hasPerm: Directive = {
|
||||||
"need perms! Like v-has-perm=\"['sys:user:add','sys:user:edit']\""
|
"need perms! Like v-has-perm=\"['sys:user:add','sys:user:edit']\""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -41,7 +41,7 @@ export const hasRole: Directive = {
|
||||||
if (value) {
|
if (value) {
|
||||||
const requiredRoles = value; // DOM绑定需要的角色编码
|
const requiredRoles = value; // DOM绑定需要的角色编码
|
||||||
const { roles } = useUserStoreHook();
|
const { roles } = useUserStoreHook();
|
||||||
const hasRole = roles.some(perm => {
|
const hasRole = roles.some((perm) => {
|
||||||
return requiredRoles.includes(perm);
|
return requiredRoles.includes(perm);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -51,5 +51,5 @@ export const hasRole: Directive = {
|
||||||
} else {
|
} else {
|
||||||
throw new Error("need roles! Like v-has-role=\"['admin','test']\"");
|
throw new Error("need roles! Like v-has-role=\"['admin','test']\"");
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,18 @@ export enum MenuTypeEnum {
|
||||||
/**
|
/**
|
||||||
* 目录
|
* 目录
|
||||||
*/
|
*/
|
||||||
CATALOG = 'CATALOG',
|
CATALOG = "CATALOG",
|
||||||
/**
|
/**
|
||||||
* 菜单
|
* 菜单
|
||||||
*/
|
*/
|
||||||
MENU = 'MENU',
|
MENU = "MENU",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按钮
|
* 按钮
|
||||||
*/
|
*/
|
||||||
BUTTON = 'BUTTON',
|
BUTTON = "BUTTON",
|
||||||
/**
|
/**
|
||||||
* 外链
|
* 外链
|
||||||
*/
|
*/
|
||||||
EXTLINK = 'EXTLINK'
|
EXTLINK = "EXTLINK",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
import { createI18n } from 'vue-i18n';
|
import { createI18n } from "vue-i18n";
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from "@/store/modules/app";
|
||||||
|
// 本地语言包
|
||||||
|
import enLocale from "./package/en";
|
||||||
|
import zhCnLocale from "./package/zh-cn";
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
// 本地语言包
|
|
||||||
import enLocale from './package/en';
|
|
||||||
import zhCnLocale from './package/zh-cn';
|
|
||||||
|
|
||||||
const messages = {
|
const messages = {
|
||||||
'zh-cn': {
|
"zh-cn": {
|
||||||
...zhCnLocale
|
...zhCnLocale,
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
...enLocale
|
...enLocale,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const i18n = createI18n({
|
const i18n = createI18n({
|
||||||
legacy: false,
|
legacy: false,
|
||||||
locale: appStore.language,
|
locale: appStore.language,
|
||||||
messages: messages,
|
messages: messages,
|
||||||
globalInjection: true
|
globalInjection: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default i18n;
|
export default i18n;
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
export default {
|
export default {
|
||||||
// 路由国际化
|
// 路由国际化
|
||||||
route: {
|
route: {
|
||||||
dashboard: 'Dashboard',
|
dashboard: "Dashboard",
|
||||||
document: 'Document'
|
document: "Document",
|
||||||
},
|
},
|
||||||
// 登录页面国际化
|
// 登录页面国际化
|
||||||
login: {
|
login: {
|
||||||
title: 'vue3-element-admin',
|
title: "vue3-element-admin",
|
||||||
username: 'Username',
|
username: "Username",
|
||||||
password: 'Password',
|
password: "Password",
|
||||||
login: 'Login',
|
login: "Login",
|
||||||
verifyCode: 'Verify Code',
|
verifyCode: "Verify Code",
|
||||||
},
|
},
|
||||||
// 导航栏国际化
|
// 导航栏国际化
|
||||||
navbar: {
|
navbar: {
|
||||||
dashboard: 'Dashboard',
|
dashboard: "Dashboard",
|
||||||
logout: 'Logout',
|
logout: "Logout",
|
||||||
document: 'Document',
|
document: "Document",
|
||||||
gitee: 'Gitee'
|
gitee: "Gitee",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
export default {
|
export default {
|
||||||
// 路由国际化
|
// 路由国际化
|
||||||
route: {
|
route: {
|
||||||
dashboard: '首页',
|
dashboard: "首页",
|
||||||
document: '项目文档'
|
document: "项目文档",
|
||||||
},
|
},
|
||||||
// 登录页面国际化
|
// 登录页面国际化
|
||||||
login: {
|
login: {
|
||||||
title: 'vue3-element-admin',
|
title: "vue3-element-admin",
|
||||||
username: '用户名',
|
username: "用户名",
|
||||||
password: '密码',
|
password: "密码",
|
||||||
login: '登 录',
|
login: "登 录",
|
||||||
verifyCode: '验证码'
|
verifyCode: "验证码",
|
||||||
},
|
},
|
||||||
// 导航栏国际化
|
// 导航栏国际化
|
||||||
navbar: {
|
navbar: {
|
||||||
dashboard: '首页',
|
dashboard: "首页",
|
||||||
logout: '注销',
|
logout: "注销",
|
||||||
document: '项目文档',
|
document: "项目文档",
|
||||||
gitee: '码云'
|
gitee: "码云",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ onMounted(() => {
|
||||||
class="inline-block w-[30px] h-[30px] cursor-pointer"
|
class="inline-block w-[30px] h-[30px] cursor-pointer"
|
||||||
:style="{ background: color }"
|
:style="{ background: color }"
|
||||||
@click="changeThemeColor(color)"
|
@click="changeThemeColor(color)"
|
||||||
/>
|
></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<el-divider>导航设置</el-divider>
|
<el-divider>导航设置</el-divider>
|
||||||
|
|
@ -98,8 +98,8 @@ onMounted(() => {
|
||||||
"
|
"
|
||||||
@click="changeLayout('left')"
|
@click="changeLayout('left')"
|
||||||
>
|
>
|
||||||
<div />
|
<div></div>
|
||||||
<div />
|
<div></div>
|
||||||
</li>
|
</li>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip content="顶部模式" placement="bottom">
|
<el-tooltip content="顶部模式" placement="bottom">
|
||||||
|
|
@ -110,8 +110,8 @@ onMounted(() => {
|
||||||
"
|
"
|
||||||
@click="changeLayout('top')"
|
@click="changeLayout('top')"
|
||||||
>
|
>
|
||||||
<div />
|
<div></div>
|
||||||
<div />
|
<div></div>
|
||||||
</li>
|
</li>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip content="混合模式" placement="bottom">
|
<el-tooltip content="混合模式" placement="bottom">
|
||||||
|
|
@ -122,8 +122,8 @@ onMounted(() => {
|
||||||
"
|
"
|
||||||
@click="changeLayout('mix')"
|
@click="changeLayout('mix')"
|
||||||
>
|
>
|
||||||
<div />
|
<div></div>
|
||||||
<div />
|
<div></div>
|
||||||
</li>
|
</li>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from 'vue';
|
import { computed } from "vue";
|
||||||
import { isExternal } from '@/utils/index';
|
import { isExternal } from "@/utils/index";
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
|
import { useAppStore } from "@/store/modules/app";
|
||||||
|
|
||||||
import { useAppStore } from '@/store/modules/app';
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const sidebar = computed(() => appStore.sidebar);
|
const sidebar = computed(() => appStore.sidebar);
|
||||||
|
|
@ -12,16 +13,16 @@ const device = computed(() => appStore.device);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
to: {
|
to: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
function push() {
|
function push() {
|
||||||
if (device.value === 'mobile' && sidebar.value.opened == true) {
|
if (device.value === "mobile" && sidebar.value.opened == true) {
|
||||||
appStore.closeSideBar(false);
|
appStore.closeSideBar(false);
|
||||||
}
|
}
|
||||||
router.push(props.to).catch(err => {
|
router.push(props.to).catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -29,9 +30,9 @@ function push() {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<a v-if="isExternal(to)" :href="to" target="_blank" rel="noopener">
|
<a v-if="isExternal(to)" :href="to" target="_blank" rel="noopener">
|
||||||
<slot />
|
<slot></slot>
|
||||||
</a>
|
</a>
|
||||||
<div v-else @click="push">
|
<div v-else @click="push">
|
||||||
<slot />
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useSettingsStore } from '@/store/modules/settings';
|
import { useSettingsStore } from "@/store/modules/settings";
|
||||||
|
|
||||||
const settingsStore = useSettingsStore();
|
const settingsStore = useSettingsStore();
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
collapse: {
|
collapse: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const logo = ref(new URL(`../../../assets/logo.png`, import.meta.url).href);
|
const logo = ref(new URL(`../../../assets/logo.png`, import.meta.url).href);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import path from 'path-browserify';
|
import path from "path-browserify";
|
||||||
import { isExternal } from '@/utils/index';
|
import { isExternal } from "@/utils/index";
|
||||||
import AppLink from './Link.vue';
|
import AppLink from "./Link.vue";
|
||||||
|
|
||||||
import { translateRouteTitleI18n } from '@/utils/i18n';
|
import { translateRouteTitleI18n } from "@/utils/i18n";
|
||||||
import SvgIcon from '@/components/SvgIcon/index.vue';
|
import SvgIcon from "@/components/SvgIcon/index.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
/**
|
/**
|
||||||
|
|
@ -12,7 +12,7 @@ const props = defineProps({
|
||||||
*/
|
*/
|
||||||
item: {
|
item: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -20,8 +20,8 @@ const props = defineProps({
|
||||||
*/
|
*/
|
||||||
basePath: {
|
basePath: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const onlyOneChild = ref(); // 临时变量,唯一子路由
|
const onlyOneChild = ref(); // 临时变量,唯一子路由
|
||||||
|
|
@ -53,7 +53,7 @@ function hasOneShowingChild(children = [], parent: any) {
|
||||||
|
|
||||||
// 2:如果无子路由, 复制当前路由信息作为其子路由,满足只拥有一个子路由的条件,所以返回 true
|
// 2:如果无子路由, 复制当前路由信息作为其子路由,满足只拥有一个子路由的条件,所以返回 true
|
||||||
if (showingChildren.length === 0) {
|
if (showingChildren.length === 0) {
|
||||||
onlyOneChild.value = { ...parent, path: '', noShowingChildren: true };
|
onlyOneChild.value = { ...parent, path: "", noShowingChildren: true };
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ defineExpose({
|
||||||
:vertical="false"
|
:vertical="false"
|
||||||
@wheel.prevent="handleScroll"
|
@wheel.prevent="handleScroll"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot></slot>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import { getCurrentInstance, ComponentInternalInstance } from "vue";
|
||||||
getCurrentInstance,
|
|
||||||
nextTick,
|
|
||||||
ref,
|
|
||||||
watch,
|
|
||||||
onMounted,
|
|
||||||
ComponentInternalInstance,
|
|
||||||
} from "vue";
|
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
|
|
||||||
import path from "path-browserify";
|
import path from "path-browserify";
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export { default as Navbar } from './Navbar.vue';
|
export { default as Navbar } from "./Navbar.vue";
|
||||||
export { default as AppMain } from './AppMain.vue';
|
export { default as AppMain } from "./AppMain.vue";
|
||||||
export { default as Settings } from './Settings/index.vue';
|
export { default as Settings } from "./Settings/index.vue";
|
||||||
export { default as TagsView } from './TagsView/index.vue';
|
export { default as TagsView } from "./TagsView/index.vue";
|
||||||
|
|
|
||||||
24
src/main.ts
24
src/main.ts
|
|
@ -1,21 +1,21 @@
|
||||||
import { createApp } from 'vue';
|
import { createApp } from "vue";
|
||||||
import App from './App.vue';
|
import App from "./App.vue";
|
||||||
import router from '@/router';
|
import router from "@/router";
|
||||||
import { setupStore } from '@/store';
|
import { setupStore } from "@/store";
|
||||||
import { setupDirective } from '@/directive';
|
import { setupDirective } from "@/directive";
|
||||||
|
|
||||||
import '@/permission';
|
import "@/permission";
|
||||||
|
|
||||||
// 本地SVG图标
|
// 本地SVG图标
|
||||||
import 'virtual:svg-icons-register';
|
import "virtual:svg-icons-register";
|
||||||
|
|
||||||
// 国际化
|
// 国际化
|
||||||
import i18n from '@/lang/index';
|
import i18n from "@/lang/index";
|
||||||
|
|
||||||
// 样式
|
// 样式
|
||||||
import 'element-plus/theme-chalk/dark/css-vars.css';
|
import "element-plus/theme-chalk/dark/css-vars.css";
|
||||||
import '@/styles/index.scss';
|
import "@/styles/index.scss";
|
||||||
import 'uno.css';
|
import "uno.css";
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
// 全局注册 自定义指令(directive)
|
// 全局注册 自定义指令(directive)
|
||||||
|
|
@ -23,4 +23,4 @@ setupDirective(app);
|
||||||
// 全局注册 状态管理(store)
|
// 全局注册 状态管理(store)
|
||||||
setupStore(app);
|
setupStore(app);
|
||||||
|
|
||||||
app.use(router).use(i18n).mount('#app');
|
app.use(router).use(i18n).mount("#app");
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||||
|
|
||||||
import NProgress from "nprogress";
|
import NProgress from "nprogress";
|
||||||
import "nprogress/nprogress.css";
|
import "nprogress/nprogress.css";
|
||||||
|
|
||||||
NProgress.configure({ showSpinner: false }); // 进度条
|
NProgress.configure({ showSpinner: false }); // 进度条
|
||||||
|
|
||||||
const permissionStore = usePermissionStoreHook();
|
const permissionStore = usePermissionStoreHook();
|
||||||
|
|
|
||||||
|
|
@ -46,17 +46,35 @@ export const constantRoutes: RouteRecordRaw[] = [
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: "/ext",
|
||||||
|
component: Layout,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "google",
|
||||||
|
component: import("@/views/demo/google.vue"),
|
||||||
|
name: "google",
|
||||||
|
meta: {
|
||||||
|
title: "Google",
|
||||||
|
icon: "client",
|
||||||
|
hidden: false,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
// 外部链接
|
// 外部链接
|
||||||
/*{
|
// {
|
||||||
path: '/external-link',
|
// path: "/external-link",
|
||||||
component: Layout,
|
// component: Layout,
|
||||||
children: [
|
// children: [ {
|
||||||
{
|
// component: () => import("@/views/external-link/index.vue"),
|
||||||
path: 'https://www.cnblogs.com/haoxianrui/',
|
// path: "https://www.cnblogs.com/haoxianrui/",
|
||||||
meta: { title: '外部链接', icon: 'link' }
|
// meta: { title: "外部链接", icon: "link" },
|
||||||
}
|
// },
|
||||||
]
|
// ],
|
||||||
}*/
|
// },
|
||||||
// 多级嵌套路由
|
// 多级嵌套路由
|
||||||
/* {
|
/* {
|
||||||
path: '/nested',
|
path: '/nested',
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
declare module 'xlsx/xlsx.mjs'
|
declare module "xlsx/xlsx.mjs";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { App } from 'vue';
|
import type { App } from "vue";
|
||||||
import { createPinia } from 'pinia';
|
import { createPinia } from "pinia";
|
||||||
|
|
||||||
const store = createPinia();
|
const store = createPinia();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ html.dark {
|
||||||
--w-e-textarea-bg-color: var(--el-bg-color-overlay);
|
--w-e-textarea-bg-color: var(--el-bg-color-overlay);
|
||||||
--w-e-textarea-color: var(--el-text-color-regulary);
|
--w-e-textarea-color: var(--el-text-color-regulary);
|
||||||
--w-e-textarea-slight-border-color: var(--el-color-primary);
|
--w-e-textarea-slight-border-color: var(--el-color-primary);
|
||||||
--w-e-textarea-slight-bg-color: rgba(var(--el-color-primary-rgb), .1);
|
--w-e-textarea-slight-bg-color: rgb(var(--el-color-primary-rgb) 0.1);
|
||||||
--w-e-textarea-selected-border-color: var(--el-color-primary);
|
--w-e-textarea-selected-border-color: var(--el-color-primary);
|
||||||
--w-e-textarea-border-color: var(--el-color-info-light-5);
|
--w-e-textarea-border-color: var(--el-color-info-light-5);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// 导出 variables.module.scss 变量提供给TypeScript使用
|
// 导出 variables.module.scss 变量提供给TypeScript使用
|
||||||
:export {
|
:export {
|
||||||
menuBg: $menuBg;
|
menuBg: $menuBg;
|
||||||
menuText: $menuText;
|
menuText: $menuText;
|
||||||
menuActiveText: $menuActiveText
|
menuActiveText: $menuActiveText;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
// wang-editor textarea
|
// wang-editor textarea
|
||||||
--w-e-textarea-slight-border-color: var(--el-color-primary);
|
--w-e-textarea-slight-border-color: var(--el-color-primary);
|
||||||
--w-e-textarea-slight-bg-color: rgba(var(--el-color-primary-rgb), .1);
|
--w-e-textarea-slight-bg-color: rgb(var(--el-color-primary-rgb) 0.1);
|
||||||
--w-e-textarea-selected-border-color: var(--el-color-primary);
|
--w-e-textarea-selected-border-color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
// translate router.meta.title, be used in breadcrumb sidebar tagsview
|
// translate router.meta.title, be used in breadcrumb sidebar tagsview
|
||||||
import i18n from '@/lang/index';
|
import i18n from "@/lang/index";
|
||||||
|
|
||||||
export function translateRouteTitleI18n(title: any) {
|
export function translateRouteTitleI18n(title: any) {
|
||||||
// 判断是否存在国际化配置,如果没有原生返回
|
// 判断是否存在国际化配置,如果没有原生返回
|
||||||
const hasKey = i18n.global.te('route.' + title);
|
const hasKey = i18n.global.te("route." + title);
|
||||||
if (hasKey) {
|
if (hasKey) {
|
||||||
const translatedTitle = i18n.global.t('route.' + title);
|
const translatedTitle = i18n.global.t("route." + title);
|
||||||
return translatedTitle;
|
return translatedTitle;
|
||||||
}
|
}
|
||||||
return title;
|
return title;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import axios, { InternalAxiosRequestConfig, AxiosResponse } from 'axios';
|
import axios, { InternalAxiosRequestConfig, AxiosResponse } from "axios";
|
||||||
import { useUserStoreHook } from '@/store/modules/user';
|
import { useUserStoreHook } from "@/store/modules/user";
|
||||||
|
|
||||||
// 创建 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" },
|
||||||
});
|
});
|
||||||
|
|
||||||
// 请求拦截器
|
// 请求拦截器
|
||||||
|
|
@ -26,7 +26,7 @@ service.interceptors.request.use(
|
||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
(response: AxiosResponse) => {
|
(response: AxiosResponse) => {
|
||||||
const { code, msg } = response.data;
|
const { code, msg } = response.data;
|
||||||
if (code === '00000') {
|
if (code === "00000") {
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
// 响应数据为二进制流处理(Excel导出)
|
// 响应数据为二进制流处理(Excel导出)
|
||||||
|
|
@ -34,23 +34,23 @@ service.interceptors.response.use(
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElMessage.error(msg || '系统出错');
|
ElMessage.error(msg || "系统出错");
|
||||||
return Promise.reject(new Error(msg || 'Error'));
|
return Promise.reject(new Error(msg || "Error"));
|
||||||
},
|
},
|
||||||
(error: any) => {
|
(error: any) => {
|
||||||
if (error.response.data) {
|
if (error.response.data) {
|
||||||
const { code, msg } = error.response.data;
|
const { code, msg } = error.response.data;
|
||||||
// token 过期,重新登录
|
// token 过期,重新登录
|
||||||
if (code === 'A0230') {
|
if (code === "A0230") {
|
||||||
ElMessageBox.confirm('当前页面已失效,请重新登录', '提示', {
|
ElMessageBox.confirm("当前页面已失效,请重新登录", "提示", {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: "确定",
|
||||||
type: 'warning'
|
type: "warning",
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
window.location.href = '/';
|
window.location.href = "/";
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(msg || '系统出错');
|
ElMessage.error(msg || "系统出错");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.reject(error.message);
|
return Promise.reject(error.message);
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ export const scrollTo = (to: number, duration: number, callback?: any) => {
|
||||||
const change = to - start;
|
const change = to - start;
|
||||||
const increment = 20;
|
const increment = 20;
|
||||||
let currentTime = 0;
|
let currentTime = 0;
|
||||||
duration = typeof duration === 'undefined' ? 500 : duration;
|
duration = typeof duration === "undefined" ? 500 : duration;
|
||||||
const animateScroll = function () {
|
const animateScroll = function () {
|
||||||
// increment the time
|
// increment the time
|
||||||
currentTime += increment;
|
currentTime += increment;
|
||||||
|
|
@ -59,7 +59,7 @@ export const scrollTo = (to: number, duration: number, callback?: any) => {
|
||||||
if (currentTime < duration) {
|
if (currentTime < duration) {
|
||||||
requestAnimFrame(animateScroll);
|
requestAnimFrame(animateScroll);
|
||||||
} else {
|
} else {
|
||||||
if (callback && typeof callback === 'function') {
|
if (callback && typeof callback === "function") {
|
||||||
// the animation is done so lets callback
|
// the animation is done so lets callback
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,12 @@
|
||||||
<div class="title">
|
<div class="title">
|
||||||
业绩柱状图
|
业绩柱状图
|
||||||
<el-tooltip effect="dark" content="点击试试下载" placement="bottom">
|
<el-tooltip effect="dark" content="点击试试下载" placement="bottom">
|
||||||
<i-ep-download
|
<i-ep-download class="download" @click="downloadEchart" />
|
||||||
class="download"
|
|
||||||
@click="downloadEchart"
|
|
||||||
></i-ep-download>
|
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div :id="id" :class="className" :style="{ height, width }" />
|
<div :id="id" :class="className" :style="{ height, width }"></div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,96 +1,96 @@
|
||||||
<!-- 漏斗图 -->
|
<!-- 漏斗图 -->
|
||||||
<template>
|
<template>
|
||||||
<div :id="id" :class="className" :style="{ height, width }" />
|
<div :id="id" :class="className" :style="{ height, width }"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from "echarts";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'funnelChart'
|
default: "funnelChart",
|
||||||
},
|
},
|
||||||
className: {
|
className: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: "",
|
||||||
},
|
},
|
||||||
width: {
|
width: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '200px',
|
default: "200px",
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
height: {
|
height: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '200px',
|
default: "200px",
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
title: {
|
title: {
|
||||||
show: true,
|
show: true,
|
||||||
text: '订单线索转化漏斗图',
|
text: "订单线索转化漏斗图",
|
||||||
x: 'center',
|
x: "center",
|
||||||
padding: 15,
|
padding: 15,
|
||||||
textStyle: {
|
textStyle: {
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontStyle: 'normal',
|
fontStyle: "normal",
|
||||||
fontWeight: 'bold',
|
fontWeight: "bold",
|
||||||
color: '#337ecc'
|
color: "#337ecc",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
left: '2%',
|
left: "2%",
|
||||||
right: '2%',
|
right: "2%",
|
||||||
bottom: '10%',
|
bottom: "10%",
|
||||||
containLabel: true
|
containLabel: true,
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
x: 'center',
|
x: "center",
|
||||||
y: 'bottom',
|
y: "bottom",
|
||||||
data: ['Show', 'Click', 'Visit', 'Inquiry', 'Order']
|
data: ["Show", "Click", "Visit", "Inquiry", "Order"],
|
||||||
},
|
},
|
||||||
|
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: 'Funnel',
|
name: "Funnel",
|
||||||
type: 'funnel',
|
type: "funnel",
|
||||||
left: '20%',
|
left: "20%",
|
||||||
top: 60,
|
top: 60,
|
||||||
bottom: 60,
|
bottom: 60,
|
||||||
width: '60%',
|
width: "60%",
|
||||||
sort: 'descending',
|
sort: "descending",
|
||||||
gap: 2,
|
gap: 2,
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
position: 'inside'
|
position: "inside",
|
||||||
},
|
},
|
||||||
labelLine: {
|
labelLine: {
|
||||||
length: 10,
|
length: 10,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
width: 1,
|
width: 1,
|
||||||
type: 'solid'
|
type: "solid",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
borderColor: '#fff',
|
borderColor: "#fff",
|
||||||
borderWidth: 1
|
borderWidth: 1,
|
||||||
},
|
},
|
||||||
emphasis: {
|
emphasis: {
|
||||||
label: {
|
label: {
|
||||||
fontSize: 20
|
fontSize: 20,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
data: [
|
data: [
|
||||||
{ value: 60, name: 'Visit' },
|
{ value: 60, name: "Visit" },
|
||||||
{ value: 40, name: 'Inquiry' },
|
{ value: 40, name: "Inquiry" },
|
||||||
{ value: 20, name: 'Order' },
|
{ value: 20, name: "Order" },
|
||||||
{ value: 80, name: 'Click' },
|
{ value: 80, name: "Click" },
|
||||||
{ value: 100, name: 'Show' }
|
{ value: 100, name: "Show" },
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
@ -99,7 +99,7 @@ onMounted(() => {
|
||||||
);
|
);
|
||||||
chart.setOption(options);
|
chart.setOption(options);
|
||||||
|
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener("resize", () => {
|
||||||
chart.resize();
|
chart.resize();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,69 +2,69 @@
|
||||||
<template>
|
<template>
|
||||||
<el-card>
|
<el-card>
|
||||||
<template #header> 产品分类饼图 </template>
|
<template #header> 产品分类饼图 </template>
|
||||||
<div :id="id" :class="className" :style="{ height, width }" />
|
<div :id="id" :class="className" :style="{ height, width }"></div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from "echarts";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'pieChart'
|
default: "pieChart",
|
||||||
},
|
},
|
||||||
className: {
|
className: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: "",
|
||||||
},
|
},
|
||||||
width: {
|
width: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '200px',
|
default: "200px",
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
height: {
|
height: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '200px',
|
default: "200px",
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const options = {
|
const options = {
|
||||||
grid: {
|
grid: {
|
||||||
left: '2%',
|
left: "2%",
|
||||||
right: '2%',
|
right: "2%",
|
||||||
bottom: '10%',
|
bottom: "10%",
|
||||||
containLabel: true
|
containLabel: true,
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
top: 'bottom',
|
top: "bottom",
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#999'
|
color: "#999",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: 'Nightingale Chart',
|
name: "Nightingale Chart",
|
||||||
type: 'pie',
|
type: "pie",
|
||||||
radius: [50, 130],
|
radius: [50, 130],
|
||||||
center: ['50%', '50%'],
|
center: ["50%", "50%"],
|
||||||
roseType: 'area',
|
roseType: "area",
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
borderRadius: 1,
|
borderRadius: 1,
|
||||||
color: function (params: any) {
|
color: function (params: any) {
|
||||||
//自定义颜色
|
//自定义颜色
|
||||||
const colorList = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'];
|
const colorList = ["#409EFF", "#67C23A", "#E6A23C", "#F56C6C"];
|
||||||
return colorList[params.dataIndex];
|
return colorList[params.dataIndex];
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
data: [
|
data: [
|
||||||
{ value: 26, name: '家用电器' },
|
{ value: 26, name: "家用电器" },
|
||||||
{ value: 27, name: '户外运动' },
|
{ value: 27, name: "户外运动" },
|
||||||
{ value: 24, name: '汽车用品' },
|
{ value: 24, name: "汽车用品" },
|
||||||
{ value: 23, name: '手机数码' }
|
{ value: 23, name: "手机数码" },
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
@ -72,7 +72,7 @@ onMounted(() => {
|
||||||
document.getElementById(props.id) as HTMLDivElement
|
document.getElementById(props.id) as HTMLDivElement
|
||||||
);
|
);
|
||||||
chart.setOption(options);
|
chart.setOption(options);
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener("resize", () => {
|
||||||
chart.resize();
|
chart.resize();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,89 +2,89 @@
|
||||||
<template>
|
<template>
|
||||||
<el-card>
|
<el-card>
|
||||||
<template #header> 订单状态雷达图 </template>
|
<template #header> 订单状态雷达图 </template>
|
||||||
<div :id="id" :class="className" :style="{ height, width }" />
|
<div :id="id" :class="className" :style="{ height, width }"></div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from "echarts";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'radarChart'
|
default: "radarChart",
|
||||||
},
|
},
|
||||||
className: {
|
className: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: "",
|
||||||
},
|
},
|
||||||
width: {
|
width: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '200px',
|
default: "200px",
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
height: {
|
height: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '200px',
|
default: "200px",
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
grid: {
|
grid: {
|
||||||
left: '2%',
|
left: "2%",
|
||||||
right: '2%',
|
right: "2%",
|
||||||
bottom: '10%',
|
bottom: "10%",
|
||||||
containLabel: true
|
containLabel: true,
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
x: 'center',
|
x: "center",
|
||||||
y: 'bottom',
|
y: "bottom",
|
||||||
data: ['预定数量', '下单数量', '发货数量'],
|
data: ["预定数量", "下单数量", "发货数量"],
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#999'
|
color: "#999",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
radar: {
|
radar: {
|
||||||
// shape: 'circle',
|
// shape: 'circle',
|
||||||
radius: '60%',
|
radius: "60%",
|
||||||
indicator: [
|
indicator: [
|
||||||
{ name: '家用电器' },
|
{ name: "家用电器" },
|
||||||
{ name: '服装箱包' },
|
{ name: "服装箱包" },
|
||||||
{ name: '运动户外' },
|
{ name: "运动户外" },
|
||||||
{ name: '手机数码' },
|
{ name: "手机数码" },
|
||||||
{ name: '汽车用品' },
|
{ name: "汽车用品" },
|
||||||
{ name: '家具厨具' }
|
{ name: "家具厨具" },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: 'Budget vs spending',
|
name: "Budget vs spending",
|
||||||
type: 'radar',
|
type: "radar",
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
color: function (params: any) {
|
color: function (params: any) {
|
||||||
//自定义颜色
|
//自定义颜色
|
||||||
const colorList = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'];
|
const colorList = ["#409EFF", "#67C23A", "#E6A23C", "#F56C6C"];
|
||||||
return colorList[params.dataIndex];
|
return colorList[params.dataIndex];
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
value: [400, 400, 400, 400, 400, 400],
|
value: [400, 400, 400, 400, 400, 400],
|
||||||
name: '预定数量'
|
name: "预定数量",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: [300, 300, 300, 300, 300, 300],
|
value: [300, 300, 300, 300, 300, 300],
|
||||||
name: '下单数量'
|
name: "下单数量",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: [200, 200, 200, 200, 200, 200],
|
value: [200, 200, 200, 200, 200, 200],
|
||||||
name: '发货数量'
|
name: "发货数量",
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
@ -93,7 +93,7 @@ onMounted(() => {
|
||||||
);
|
);
|
||||||
chart.setOption(options);
|
chart.setOption(options);
|
||||||
|
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener("resize", () => {
|
||||||
chart.resize();
|
chart.resize();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useUserStore } from "@/store/modules/user";
|
||||||
|
import { useTransition, TransitionPresets } from "@vueuse/core";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
// eslint-disable-next-line vue/no-reserved-component-names
|
// eslint-disable-next-line vue/no-reserved-component-names
|
||||||
name: "Dashboard",
|
name: "Dashboard",
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
import { useUserStore } from "@/store/modules/user";
|
|
||||||
import { useTransition, TransitionPresets } from "@vueuse/core";
|
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
const date: Date = new Date();
|
const date: Date = new Date();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!-- 接口文档 -->
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<iframe
|
||||||
|
src="https://creator.xiaohongshu.com/"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
frameborder="0"
|
||||||
|
></iframe>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.app-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
/* 84 = navbar + tags-view = 50 + 34 */
|
||||||
|
height: calc(100vh - 50px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hasTagsView {
|
||||||
|
.app-container {
|
||||||
|
height: calc(100vh - 84px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -15,8 +15,8 @@
|
||||||
<div class="label-wrap" @click="handleClickHead(oneCol)">
|
<div class="label-wrap" @click="handleClickHead(oneCol)">
|
||||||
<div>{{ oneCol.label }}</div>
|
<div>{{ oneCol.label }}</div>
|
||||||
<template v-if="oneCol.order">
|
<template v-if="oneCol.order">
|
||||||
<i-ep-sort-up v-if="oneCol.order === 'asc'"></i-ep-sort-up>
|
<i-ep-sort-up v-if="oneCol.order === 'asc'" />
|
||||||
<i-ep-sort-down v-else></i-ep-sort-down>
|
<i-ep-sort-down v-else />
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
trigger="click"
|
trigger="click"
|
||||||
@command="(command: string) => handleCommand(command, oneCol)"
|
@command="(command: string) => handleCommand(command, oneCol)"
|
||||||
>
|
>
|
||||||
<i-ep-arrow-down class="action-more"></i-ep-arrow-down>
|
<i-ep-arrow-down class="action-more" />
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<template v-if="oneCol.prop === 'id'">
|
<template v-if="oneCol.prop === 'id'">
|
||||||
|
|
@ -56,7 +56,7 @@
|
||||||
action=""
|
action=""
|
||||||
:http-request="handleUploadFile"
|
:http-request="handleUploadFile"
|
||||||
>
|
>
|
||||||
<i-ep-upload-filled class="icon"></i-ep-upload-filled>
|
<i-ep-upload-filled class="icon" />
|
||||||
<div class="el-upload__text">拖拽excel到这里</div>
|
<div class="el-upload__text">拖拽excel到这里</div>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
<div v-loading="loading" class="excel-table-wrap">
|
<div v-loading="loading" class="excel-table-wrap">
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<!-- wangEditor富文本编辑器示例 -->
|
<!-- wangEditor富文本编辑器示例 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Editor from "@/components/WangEditor/index.vue";
|
import Editor from "@/components/WangEditor/index.vue";
|
||||||
|
|
||||||
const value = ref("初始内容");
|
const value = ref("初始内容");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
<!-- websocket 示例 -->
|
<!-- websocket 示例 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { sendToAll, sendToUser } from "@/api/websocket";
|
import { sendToAll, sendToUser } from "@/api/websocket"; // 点对点消息列表
|
||||||
|
|
||||||
|
import { useUserStore } from "@/store/modules/user";
|
||||||
|
|
||||||
|
import { useWebSocket } from "@vueuse/core";
|
||||||
|
|
||||||
const inputVal = ref("初始内容");
|
const inputVal = ref("初始内容");
|
||||||
|
|
||||||
const topicMsgs = ref<string[]>(["接收到一条主题消息"]); // 主题消息列表
|
const topicMsgs = ref<string[]>(["接收到一条主题消息"]); // 主题消息列表
|
||||||
const p2pMsgs = ref<string[]>(["接收到一条点对线消息"]); // 点对点消息列表
|
const p2pMsgs = ref<string[]>(["接收到一条点对线消息"]);
|
||||||
|
|
||||||
import { useUserStore } from "@/store/modules/user";
|
|
||||||
|
|
||||||
const userId = useUserStore().userId;
|
const userId = useUserStore().userId;
|
||||||
|
|
||||||
import { useWebSocket } from "@vueuse/core";
|
|
||||||
|
|
||||||
const { data, status, close, send, open } = useWebSocket(
|
const { data, status, close, send, open } = useWebSocket(
|
||||||
"ws://localhost:8989/ws",
|
"ws://localhost:8989/ws",
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
<!-- setup 无法设置组件名称,组件名称keepAlive必须 -->
|
|
||||||
<script lang="ts">
|
|
||||||
export default {
|
|
||||||
name: "Page401",
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, toRefs } from "vue";
|
import { reactive, toRefs } from "vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
|
||||||
|
defineComponent({
|
||||||
|
name: "Page401",
|
||||||
|
});
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
errGif: new URL(`../../assets/401_images/401.gif`, import.meta.url).href,
|
errGif: new URL(`../../assets/401_images/401.gif`, import.meta.url).href,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div style="margin-bottom: 15px">Your roles: {{ roles }}</div>
|
||||||
|
Switch roles:
|
||||||
|
<el-radio-group v-model="switchRoles">
|
||||||
|
<el-radio-button label="EDITOR" />
|
||||||
|
<el-radio-button label="ADMIN" />
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useUserStoreHook } from "@/store/modules/user";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
|
||||||
|
const emit = defineEmits(["change"]);
|
||||||
|
const store = storeToRefs(useUserStoreHook());
|
||||||
|
const { roles } = store;
|
||||||
|
|
||||||
|
const switchRoles = computed({
|
||||||
|
get: () => roles.value[0],
|
||||||
|
set: (val) => {
|
||||||
|
roles.value = [val];
|
||||||
|
emit("change");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<switch-roles @change="handleRolesChange" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import router from "@/router";
|
||||||
|
import SwitchRoles from "./components/SwitchRoles.vue";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
// eslint-disable-next-line
|
||||||
|
name: "PagePermission",
|
||||||
|
inheritAttrs: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleRolesChange() {
|
||||||
|
console.log("roles changed");
|
||||||
|
router.push({ path: "/permission/page?" + new Date() });
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div />
|
<div></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from "vue-router";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -11,5 +11,5 @@ const router = useRouter();
|
||||||
const { params, query } = route;
|
const { params, query } = route;
|
||||||
const { path } = params;
|
const { path } = params;
|
||||||
|
|
||||||
router.replace({ path: '/' + path, query });
|
router.replace({ path: "/" + path, query });
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,4 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineOptions({
|
|
||||||
name: "Dept",
|
|
||||||
inheritAttrs: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getDeptForm,
|
getDeptForm,
|
||||||
deleteDept,
|
deleteDept,
|
||||||
|
|
@ -15,6 +10,11 @@ import {
|
||||||
|
|
||||||
import { DeptVO, DeptForm, DeptQuery } from "@/api/dept/types";
|
import { DeptVO, DeptForm, DeptQuery } from "@/api/dept/types";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "Dept",
|
||||||
|
inheritAttrs: false,
|
||||||
|
});
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref(ElForm);
|
||||||
const deptFormRef = ref(ElForm);
|
const deptFormRef = ref(ElForm);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,5 @@
|
||||||
<!-- 字典数据 -->
|
<!-- 字典数据 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineOptions({
|
|
||||||
name: "DictData",
|
|
||||||
inheritAttrs: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getDictPage,
|
getDictPage,
|
||||||
getDictFormData,
|
getDictFormData,
|
||||||
|
|
@ -14,6 +9,11 @@ import {
|
||||||
} from "@/api/dict";
|
} from "@/api/dict";
|
||||||
import { DictPageVO, DictForm, DictQuery } from "@/api/dict/types";
|
import { DictPageVO, DictForm, DictQuery } from "@/api/dict/types";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "DictData",
|
||||||
|
inheritAttrs: false,
|
||||||
|
});
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
typeCode: {
|
typeCode: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|
@ -311,7 +311,7 @@ onMounted(() => {
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input v-model="formData.remark" type="textarea"></el-input>
|
<el-input v-model="formData.remark" type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,5 @@
|
||||||
<!--字典类型-->
|
<!--字典类型-->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineOptions({
|
|
||||||
name: "DictType",
|
|
||||||
inheritAttrs: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getDictTypePage,
|
getDictTypePage,
|
||||||
getDictTypeForm,
|
getDictTypeForm,
|
||||||
|
|
@ -17,6 +12,11 @@ import DictData from "@/views/system/dict/DictData.vue";
|
||||||
|
|
||||||
import { DictTypePageVO, DictTypeQuery, DictTypeForm } from "@/api/dict/types";
|
import { DictTypePageVO, DictTypeQuery, DictTypeForm } from "@/api/dict/types";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "DictType",
|
||||||
|
inheritAttrs: false,
|
||||||
|
});
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref(ElForm);
|
||||||
const dataFormRef = ref(ElForm);
|
const dataFormRef = ref(ElForm);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,4 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineOptions({
|
|
||||||
// eslint-disable-next-line vue/no-reserved-component-names
|
|
||||||
name: "Menu",
|
|
||||||
inheritAttrs: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
import { MenuQuery, MenuForm, MenuVO } from "@/api/menu/types";
|
import { MenuQuery, MenuForm, MenuVO } from "@/api/menu/types";
|
||||||
import {
|
import {
|
||||||
listMenus,
|
listMenus,
|
||||||
|
|
@ -20,6 +14,12 @@ import { MenuTypeEnum } from "@/enums/MenuTypeEnum";
|
||||||
import SvgIcon from "@/components/SvgIcon/index.vue";
|
import SvgIcon from "@/components/SvgIcon/index.vue";
|
||||||
import IconSelect from "@/components/IconSelect/index.vue";
|
import IconSelect from "@/components/IconSelect/index.vue";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
// eslint-disable-next-line vue/no-reserved-component-names
|
||||||
|
name: "Menu",
|
||||||
|
inheritAttrs: false,
|
||||||
|
});
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref(ElForm);
|
||||||
const menuFormRef = ref(ElForm);
|
const menuFormRef = ref(ElForm);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,4 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineOptions({
|
|
||||||
name: "Role",
|
|
||||||
inheritAttrs: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getRolePage,
|
getRolePage,
|
||||||
updateRole,
|
updateRole,
|
||||||
|
|
@ -17,6 +12,11 @@ import { listMenuOptions } from "@/api/menu";
|
||||||
|
|
||||||
import { RolePageVO, RoleForm, RoleQuery } from "@/api/role/types";
|
import { RolePageVO, RoleForm, RoleQuery } from "@/api/role/types";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "Role",
|
||||||
|
inheritAttrs: false,
|
||||||
|
});
|
||||||
|
|
||||||
const queryFormRef = ref(ElForm);
|
const queryFormRef = ref(ElForm);
|
||||||
const roleFormRef = ref(ElForm);
|
const roleFormRef = ref(ElForm);
|
||||||
const menuRef = ref(ElTree);
|
const menuRef = ref(ElTree);
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,6 @@
|
||||||
/**
|
/**
|
||||||
* @see {@link https://vuejs.org/api/sfc-script-setup.html#defineoptions}
|
* @see {@link https://vuejs.org/api/sfc-script-setup.html#defineoptions}
|
||||||
*/
|
*/
|
||||||
defineOptions({
|
|
||||||
name: "User",
|
|
||||||
inheritAttrs: false,
|
|
||||||
});
|
|
||||||
import { UploadFile } from "element-plus";
|
import { UploadFile } from "element-plus";
|
||||||
import {
|
import {
|
||||||
getUserPage,
|
getUserPage,
|
||||||
|
|
@ -24,6 +20,11 @@ import { listRoleOptions } from "@/api/role";
|
||||||
|
|
||||||
import { UserForm, UserQuery, UserPageVO } from "@/api/user/types";
|
import { UserForm, UserQuery, UserPageVO } from "@/api/user/types";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "User",
|
||||||
|
inheritAttrs: false,
|
||||||
|
});
|
||||||
|
|
||||||
const deptTreeRef = ref(ElTree); // 部门树
|
const deptTreeRef = ref(ElTree); // 部门树
|
||||||
const queryFormRef = ref(ElForm); // 查询表单
|
const queryFormRef = ref(ElForm); // 查询表单
|
||||||
const userFormRef = ref(ElForm); // 用户表单
|
const userFormRef = ref(ElForm); // 用户表单
|
||||||
|
|
@ -383,7 +384,7 @@ onMounted(() => {
|
||||||
:filter-node-method="handleDeptFilter"
|
:filter-node-method="handleDeptFilter"
|
||||||
default-expand-all
|
default-expand-all
|
||||||
@node-click="handleDeptNodeClick"
|
@node-click="handleDeptNodeClick"
|
||||||
></el-tree>
|
/>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
|
|
@ -524,7 +525,7 @@ onMounted(() => {
|
||||||
align="center"
|
align="center"
|
||||||
prop="createTime"
|
prop="createTime"
|
||||||
width="180"
|
width="180"
|
||||||
></el-table-column>
|
/>
|
||||||
<el-table-column label="操作" fixed="right" width="220">
|
<el-table-column label="操作" fixed="right" width="220">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
|
"noLib": false,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
|
|
@ -20,7 +21,13 @@
|
||||||
"allowSyntheticDefaultImports": true /* 允许默认导入 */,
|
"allowSyntheticDefaultImports": true /* 允许默认导入 */,
|
||||||
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */
|
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.vue", "src/types/**/*.d.ts"],
|
"include": [
|
||||||
"exclude": ["node_modules", "dist", "**/*.js"],
|
"src/**/*.ts",
|
||||||
"references": [{ "path": "./tsconfig.node.json" }]
|
"src/**/*.vue",
|
||||||
|
"src/types/**/*.d.ts",
|
||||||
|
"mock/**/*.ts",
|
||||||
|
"vite.config.ts"
|
||||||
|
],
|
||||||
|
"exclude": ["node_modules", "dist", "**/*.js"]
|
||||||
|
// "references": [{ "path": "./tsconfig.node.json" }]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"composite": true,
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "Node",
|
|
||||||
"allowSyntheticDefaultImports": true
|
|
||||||
},
|
|
||||||
"include": ["vite.config.ts"]
|
|
||||||
}
|
|
||||||
|
|
@ -11,6 +11,9 @@ import IconsResolver from "unplugin-icons/resolver";
|
||||||
|
|
||||||
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
|
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
|
||||||
|
|
||||||
|
import { viteMockServe } from "vite-plugin-mock";
|
||||||
|
import visualizer from "rollup-plugin-visualizer";
|
||||||
|
|
||||||
import UnoCSS from "unocss/vite";
|
import UnoCSS from "unocss/vite";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
|
|
@ -20,6 +23,7 @@ const pathSrc = path.resolve(__dirname, "src");
|
||||||
|
|
||||||
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
||||||
const env = loadEnv(mode, process.cwd());
|
const env = loadEnv(mode, process.cwd());
|
||||||
|
|
||||||
return {
|
return {
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
|
|
@ -45,11 +49,15 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
||||||
proxy: {
|
proxy: {
|
||||||
// 反向代理解决跨域
|
// 反向代理解决跨域
|
||||||
[env.VITE_APP_BASE_API]: {
|
[env.VITE_APP_BASE_API]: {
|
||||||
target: "http://vapi.youlai.tech", // 线上接口地址
|
// target: "http://vapi.youlai.tech", // 线上接口地址
|
||||||
// target: 'http://localhost:8989', // 本地接口地址 , 后端工程仓库地址:https://gitee.com/youlaiorg/youlai-boot
|
// target: 'http://localhost:3001', // 本地接口地址 , 后端工程仓库地址:https://gitee.com/youlaiorg/youlai-boot
|
||||||
|
target: env.VITE_APP_TARGET_URL,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) =>
|
rewrite: (path) =>
|
||||||
path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""), // 替换 /dev-api 为 target 接口地址
|
path.replace(
|
||||||
|
new RegExp("^" + env.VITE_APP_BASE_API),
|
||||||
|
env.VITE_APP_TARGET_BASE_API
|
||||||
|
), // 替换 /dev-api 为 target 接口地址
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -112,6 +120,20 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
||||||
algorithm: "gzip", // 压缩算法
|
algorithm: "gzip", // 压缩算法
|
||||||
ext: ".gz", // 文件类型
|
ext: ".gz", // 文件类型
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
viteMockServe({
|
||||||
|
ignore: /^\_/,
|
||||||
|
mockPath: "mock",
|
||||||
|
enable: mode === "development",
|
||||||
|
// https://github.com/anncwb/vite-plugin-mock/issues/9
|
||||||
|
}),
|
||||||
|
|
||||||
|
visualizer({
|
||||||
|
filename: "./stats.html",
|
||||||
|
open: false,
|
||||||
|
gzipSize: true,
|
||||||
|
brotliSize: true,
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
// 预加载项目必需的组件
|
// 预加载项目必需的组件
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue