index on main: f96885b
perf: 同步代码
2
.env
@ -3,7 +3,7 @@ VITE_PORT = 8848
|
|||||||
# title
|
# title
|
||||||
VITE_TITLE = vue-pure-admin
|
VITE_TITLE = vue-pure-admin
|
||||||
# version
|
# version
|
||||||
VITE_VERSION = 2.1.0
|
VITE_VERSION = 2.6.0
|
||||||
# open
|
# open
|
||||||
VITE_OPEN = false
|
VITE_OPEN = false
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ VITE_PORT = 8848
|
|||||||
# title
|
# title
|
||||||
VITE_TITLE = vue-pure-admin
|
VITE_TITLE = vue-pure-admin
|
||||||
# version
|
# version
|
||||||
VITE_VERSION = 2.1.0
|
VITE_VERSION = 2.6.0
|
||||||
# open
|
# open
|
||||||
VITE_OPEN = false
|
VITE_OPEN = false
|
||||||
|
|
||||||
|
5
.gitignore
vendored
@ -5,9 +5,10 @@ dist-ssr
|
|||||||
*.local
|
*.local
|
||||||
.eslintcache
|
.eslintcache
|
||||||
|
|
||||||
|
yarn.lock
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
.pnpm-error.log*
|
||||||
yarn-error.log*
|
.pnpm-debug.log
|
||||||
tests/**/coverage/
|
tests/**/coverage/
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
|
@ -3,7 +3,7 @@ command_exists () {
|
|||||||
command -v "$1" >/dev/null 2>&1
|
command -v "$1" >/dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Workaround for Windows 10, Git Bash and Yarn
|
# Workaround for Windows 10, Git Bash and Pnpm
|
||||||
if command_exists winpty && test -t 1; then
|
if command_exists winpty && test -t 1; then
|
||||||
exec < /dev/tty
|
exec < /dev/tty
|
||||||
fi
|
fi
|
||||||
|
11
.markdownlint.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"default": true,
|
||||||
|
"MD003": false,
|
||||||
|
"MD033": false,
|
||||||
|
"MD013": false,
|
||||||
|
"MD001": false,
|
||||||
|
"MD025": false,
|
||||||
|
"MD024": false,
|
||||||
|
"MD007": { "indent": 4 },
|
||||||
|
"no-hard-tabs": false
|
||||||
|
}
|
@ -2,6 +2,6 @@ module.exports = {
|
|||||||
bracketSpacing: true,
|
bracketSpacing: true,
|
||||||
jsxBracketSameLine: true,
|
jsxBracketSameLine: true,
|
||||||
singleQuote: false,
|
singleQuote: false,
|
||||||
arrowParens: "avoid",
|
arrowParens: 'avoid',
|
||||||
trailingComma: "none"
|
trailingComma: 'none'
|
||||||
};
|
};
|
||||||
|
51
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
// You should install these plugins:
|
||||||
|
// ESLint
|
||||||
|
// Prettier - Code formatter
|
||||||
|
// stylelint
|
||||||
|
// vscode-icons
|
||||||
|
// TypeScript Vue Plugin (Volar)
|
||||||
|
// Vue Language Features (Volar)
|
||||||
|
"terminal.integrated.rendererType": "dom",
|
||||||
|
"editor.formatOnType": true,
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"javascript.updateImportsOnFileMove.enabled": "always",
|
||||||
|
"[vue]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[javascript]": {
|
||||||
|
"editor.defaultFormatter": "vscode.typescript-language-features"
|
||||||
|
},
|
||||||
|
"editor.tabSize": 2,
|
||||||
|
"editor.formatOnPaste": true,
|
||||||
|
"files.autoSave": "afterDelay",
|
||||||
|
"git.confirmSync": false,
|
||||||
|
"workbench.startupEditor": "newUntitledFile",
|
||||||
|
"editor.suggestSelection": "first",
|
||||||
|
"editor.acceptSuggestionOnCommitCharacter": false,
|
||||||
|
"css.lint.propertyIgnoredDueToDisplay": "ignore",
|
||||||
|
// Prevent inline styles from being automatically formatted to all lowercase
|
||||||
|
"editor.quickSuggestions": {
|
||||||
|
"other": true,
|
||||||
|
"comments": true,
|
||||||
|
"strings": true
|
||||||
|
},
|
||||||
|
// Automatically fix some syntax errors of ts
|
||||||
|
"tslint.autoFixOnSave": true,
|
||||||
|
"files.associations": {
|
||||||
|
// Specifies the location of snippets in the suggestion widget
|
||||||
|
"editor.snippetSuggestions": "top"
|
||||||
|
},
|
||||||
|
"[css]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"cSpell.userWords": ["sourcemap", "vite"],
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll.eslint": true
|
||||||
|
},
|
||||||
|
"volar.tsPlugin": true,
|
||||||
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
|
"i18n-ally.localesPaths": [
|
||||||
|
"src/plugins/i18n"
|
||||||
|
]
|
||||||
|
}
|
22
.vscode/vue3.0.code-snippets
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"Vue3.0快速生成模板": {
|
||||||
|
"prefix": "Vue3.0",
|
||||||
|
"body": [
|
||||||
|
"<template>",
|
||||||
|
"\t<div>\n",
|
||||||
|
"\t</div>",
|
||||||
|
"</template>\n",
|
||||||
|
"<script lang='ts'>",
|
||||||
|
"export default {",
|
||||||
|
"\tsetup(){",
|
||||||
|
"\t\treturn{\n\n\t\t}",
|
||||||
|
"\t},",
|
||||||
|
"}",
|
||||||
|
"</script>\n",
|
||||||
|
"<style scoped>\n",
|
||||||
|
"</style>",
|
||||||
|
"$2"
|
||||||
|
],
|
||||||
|
"description": "Vue3.0"
|
||||||
|
}
|
||||||
|
}
|
20
.vscode/vue3.2.setup-snippets
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"Vue3.2快速生成模板": {
|
||||||
|
"prefix": "Vue3.2",
|
||||||
|
"body": [
|
||||||
|
"<!-- $1 -->",
|
||||||
|
"<script setup lang='ts'>",
|
||||||
|
"\t$2",
|
||||||
|
"</script>\n",
|
||||||
|
"<template>",
|
||||||
|
"\t<div>",
|
||||||
|
"\t\t$3",
|
||||||
|
"\t</div>",
|
||||||
|
"</template>\n",
|
||||||
|
"<style scoped>",
|
||||||
|
"\t$4",
|
||||||
|
"</style>"
|
||||||
|
],
|
||||||
|
"description": "Vue3.2"
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,13 @@
|
|||||||
<h1>vue-pure-admin精简版</h1>
|
<h1>vue-pure-admin Lite Edition</h1>
|
||||||
|
|
||||||
|
## introduce
|
||||||
|
|
||||||
|
The lite version is based on the shelf extracted from https://github.com/xiaoxian521/vue-pure-admin, which contains the main functions and is more suitable for actual project development
|
||||||
|
|
||||||
|
## Supporting video tutorial
|
||||||
|
|
||||||
|
bilibili: https://www.bilibili.com/video/BV1534y1S7HV/
|
||||||
|
|
||||||
|
## ⚠️ Note
|
||||||
|
|
||||||
|
The lite version does not accept any issues and prs. If you have any questions, please go to the full version https://github.com/xiaoxian521/vue-pure-admin/issues/new/choose to mention it, thank you! ! !
|
||||||
|
10
README.md
@ -1,11 +1,13 @@
|
|||||||
<h1>vue-pure-admin精简版</h1>
|
<h1>vue-pure-admin精简版</h1>
|
||||||
|
|
||||||
|
## 介绍
|
||||||
|
|
||||||
|
精简版是基于 https://github.com/xiaoxian521/vue-pure-admin 提炼出的架子,包含主体功能,更适合实际项目开发
|
||||||
|
|
||||||
## 配套视频教程
|
## 配套视频教程
|
||||||
|
|
||||||
bilibili:https://www.bilibili.com/video/BV1534y1S7HV/
|
bilibili:https://www.bilibili.com/video/BV1534y1S7HV/
|
||||||
|
|
||||||
## 交流群
|
## ⚠️ 注意
|
||||||
|
|
||||||
[微信交流群,点击扫码进群](https://juejin.cn/post/6948419379566477342/)
|
精简版不接受任何 issues 和 pr,如果有问题请到完整版 https://github.com/xiaoxian521/vue-pure-admin/issues/new/choose 去提,谢谢!!!
|
||||||
|
|
||||||
本人微信:18237613535,拉你进群
|
|
||||||
|
37
index.html
@ -5,7 +5,7 @@
|
|||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
<link rel="stylesheet" href="/iconfont.css" />
|
<link rel="stylesheet" href="/iconfont.css" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Pure-Admin-Thin</title>
|
<title>vue-pure-admin</title>
|
||||||
<script>
|
<script>
|
||||||
window.process = {};
|
window.process = {};
|
||||||
</script>
|
</script>
|
||||||
@ -77,8 +77,43 @@
|
|||||||
</style>
|
</style>
|
||||||
<div class="g-container">
|
<div class="g-container">
|
||||||
<p>Pure-Admin</p>
|
<p>Pure-Admin</p>
|
||||||
|
<span class="_develop"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<script>
|
||||||
|
// 此代码仅用于开发环境的友好提示,项目打包前请去掉这段js代码 This code is only used as a friendly reminder of the development environment, please remove this js code before packaging the project
|
||||||
|
window.onload = function () {
|
||||||
|
(function () {
|
||||||
|
const ua = navigator.userAgent.toLowerCase();
|
||||||
|
const re = /(msie|firefox|chrome|opera|version).*?([\d.]+)/;
|
||||||
|
const m = ua.match(re);
|
||||||
|
const Sys = {
|
||||||
|
browser: m[1].replace(/version/, "'safari"),
|
||||||
|
version: m[2]
|
||||||
|
};
|
||||||
|
|
||||||
|
const browser = Array.of("chrome", "firefox").includes(Sys.browser);
|
||||||
|
const version = parseFloat(Sys.version);
|
||||||
|
|
||||||
|
const el = document.querySelector("._develop");
|
||||||
|
|
||||||
|
if (el) {
|
||||||
|
if (browser && version >= 90) {
|
||||||
|
let success =
|
||||||
|
document.createTextNode("当前浏览器版本很适合开发!!! 😃");
|
||||||
|
el.appendChild(success);
|
||||||
|
} else {
|
||||||
|
let warn = document.createTextNode(
|
||||||
|
"当前浏览器版本不适合开发,建议使用最新版本的谷歌或者火狐浏览器!!!😯"
|
||||||
|
);
|
||||||
|
el.appendChild(warn);
|
||||||
|
el.style.color = "red";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Sys;
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
// 根据角色动态生成路由
|
// 根据角色动态生成路由
|
||||||
import { MockMethod } from "vite-plugin-mock";
|
import { MockMethod } from "vite-plugin-mock";
|
||||||
|
|
||||||
|
// http://mockjs.com/examples.html#Object
|
||||||
const permissionRouter = {
|
const permissionRouter = {
|
||||||
path: "/permission",
|
path: "/permission",
|
||||||
name: "permission",
|
name: "permission",
|
||||||
redirect: "/permission/page",
|
redirect: "/permission/page",
|
||||||
meta: {
|
meta: {
|
||||||
title: "message.permission",
|
title: "message.permission",
|
||||||
icon: "el-icon-lollipop",
|
icon: "Lollipop",
|
||||||
showLink: true,
|
showLink: true,
|
||||||
rank: 3
|
rank: 3
|
||||||
},
|
},
|
||||||
|
109
package.json
@ -1,29 +1,41 @@
|
|||||||
{
|
{
|
||||||
"name": "vue-pure-admin",
|
"name": "vue-pure-admin",
|
||||||
"version": "2.1.0",
|
"version": "2.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16",
|
||||||
|
"pnpm": ">= 6"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "cross-env --max_old_space_size=4096 vite",
|
"dev": "cross-env --max_old_space_size=4096 vite",
|
||||||
"serve": "yarn dev",
|
"serve": "pnpm dev",
|
||||||
"build": "rimraf dist && cross-env vite build",
|
"build": "rimraf dist && cross-env vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"preview:build": "yarn build && vite preview",
|
"preview:build": "pnpm build && vite preview",
|
||||||
"clean:cache": "rm -rf node_modules && rm -rf .eslintcache && yarn cache clean && yarn",
|
"clean:cache": "rm -rf node_modules && rm -rf .eslintcache && pnpm install",
|
||||||
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
|
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
|
||||||
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
|
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
|
||||||
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,css,scss,postcss,less}\" --cache --cache-location node_modules/.cache/stylelint/",
|
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,css,scss,postcss,less}\" --cache --cache-location node_modules/.cache/stylelint/",
|
||||||
"lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js",
|
"lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js",
|
||||||
"lint:pretty": "pretty-quick --staged",
|
"lint:pretty": "pretty-quick --staged",
|
||||||
"lint": "yarn lint:eslint && yarn lint:prettier && yarn lint:stylelint && yarn lint:pretty",
|
"lint": "pnpm lint:eslint && pnpm lint:prettier && pnpm lint:stylelint && pnpm lint:pretty",
|
||||||
"prepare": "husky install"
|
"prepare": "husky install",
|
||||||
|
"preinstall": "npx only-allow pnpm"
|
||||||
},
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"> 1%",
|
||||||
|
"not ie 11",
|
||||||
|
"not op_mini all"
|
||||||
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vueuse/core": "^6.5.3",
|
"@element-plus/icons": "^0.0.11",
|
||||||
|
"@vueuse/core": "^6.7.1",
|
||||||
|
"@vueuse/motion": "^2.0.0-beta.4",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"await-to-js": "^3.0.0",
|
"await-to-js": "^3.0.0",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"dayjs": "^1.10.7",
|
"dayjs": "^1.10.7",
|
||||||
"element-plus": "1.1.0-beta.24",
|
"element-plus": "1.2.0-beta.3",
|
||||||
"element-resize-detector": "^1.2.3",
|
"element-resize-detector": "^1.2.3",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
@ -33,58 +45,57 @@
|
|||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"path-to-regexp": "^6.2.0",
|
"path-to-regexp": "^6.2.0",
|
||||||
"pinia": "2.0.0-rc.10",
|
"pinia": "^2.0.0-rc.14",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"responsive-storage": "^1.0.11",
|
"responsive-storage": "^1.0.11",
|
||||||
"typescript-cookie": "^1.0.0",
|
"typescript-cookie": "^1.0.0",
|
||||||
"vue": "^3.2.20",
|
"vue": "^3.2.21",
|
||||||
"vue-i18n": "^9.2.0-beta.3",
|
"vue-i18n": "^9.2.0-beta.3",
|
||||||
"vue-router": "^4.0.11",
|
"vue-router": "^4.0.11",
|
||||||
"vue-types": "^4.1.0",
|
"vue-types": "^4.1.0"
|
||||||
"vxe-table": "^4.0.29",
|
|
||||||
"xe-utils": "3"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^13.1.0",
|
"@commitlint/cli": "13.1.0",
|
||||||
"@commitlint/config-conventional": "^13.1.0",
|
"@commitlint/config-conventional": "13.1.0",
|
||||||
"@types/element-resize-detector": "^1.1.3",
|
"@types/element-resize-detector": "1.1.3",
|
||||||
"@types/mockjs": "^1.0.3",
|
"@types/mockjs": "1.0.3",
|
||||||
"@types/node": "^14.14.14",
|
"@types/node": "14.14.14",
|
||||||
"@types/nprogress": "^0.2.0",
|
"@types/nprogress": "0.2.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.31.0",
|
"@typescript-eslint/eslint-plugin": "4.31.0",
|
||||||
"@typescript-eslint/parser": "^4.31.0",
|
"@typescript-eslint/parser": "4.31.0",
|
||||||
"@vitejs/plugin-vue": "^1.6.0",
|
"@vitejs/plugin-vue": "^1.9.4",
|
||||||
"@vitejs/plugin-vue-jsx": "^1.1.7",
|
"@vitejs/plugin-vue-jsx": "^1.2.0",
|
||||||
"@vue/compiler-sfc": "^3.2.20",
|
"@vue/compiler-sfc": "^3.2.21",
|
||||||
"@vue/eslint-config-prettier": "^6.0.0",
|
"@vue/eslint-config-prettier": "6.0.0",
|
||||||
"@vue/eslint-config-typescript": "^7.0.0",
|
"@vue/eslint-config-typescript": "7.0.0",
|
||||||
"autoprefixer": "^10.2.4",
|
"@zougt/vite-plugin-theme-preprocessor": "^1.3.12",
|
||||||
"babel-plugin-transform-remove-console": "^6.9.4",
|
"autoprefixer": "10.2.4",
|
||||||
"chalk": "^2.4.2",
|
"babel-plugin-transform-remove-console": "6.9.4",
|
||||||
"cross-env": "^7.0.3",
|
"chalk": "2.4.2",
|
||||||
"eslint": "^7.30.0",
|
"cross-env": "7.0.3",
|
||||||
"eslint-plugin-prettier": "^3.4.0",
|
"eslint": "7.30.0",
|
||||||
"eslint-plugin-vue": "^7.17.0",
|
"eslint-plugin-prettier": "3.4.0",
|
||||||
"husky": "^7.0.2",
|
"eslint-plugin-vue": "7.17.0",
|
||||||
"lint-staged": "^11.1.2",
|
"husky": "7.0.2",
|
||||||
"postcss": "^8.2.6",
|
"lint-staged": "11.1.2",
|
||||||
"postcss-import": "^14.0.0",
|
"postcss": "8.2.6",
|
||||||
"prettier": "^2.3.2",
|
"postcss-import": "14.0.0",
|
||||||
"pretty-quick": "^3.1.1",
|
"prettier": "2.3.2",
|
||||||
"rimraf": "^3.0.2",
|
"pretty-quick": "3.1.1",
|
||||||
"sass": "^1.38.0",
|
"rimraf": "3.0.2",
|
||||||
"sass-loader": "^12.1.0",
|
"sass": "^1.43.4",
|
||||||
"stylelint": "^13.13.1",
|
"sass-loader": "^12.3.0",
|
||||||
"stylelint-config-prettier": "^8.0.2",
|
"stylelint": "13.13.1",
|
||||||
"stylelint-config-standard": "^22.0.0",
|
"stylelint-config-prettier": "8.0.2",
|
||||||
"stylelint-order": "^4.1.0",
|
"stylelint-config-standard": "22.0.0",
|
||||||
"typescript": "^4.4.2",
|
"stylelint-order": "4.1.0",
|
||||||
|
"typescript": "4.4.2",
|
||||||
"unplugin-element-plus": "^0.1.0",
|
"unplugin-element-plus": "^0.1.0",
|
||||||
"vite": "^2.6.7",
|
"vite": "latest",
|
||||||
"vite-plugin-mock": "^2.9.6",
|
"vite-plugin-mock": "^2.9.6",
|
||||||
"vite-plugin-style-import": "^1.2.1",
|
"vite-plugin-style-import": "^1.2.1",
|
||||||
"vite-svg-loader": "^2.2.0",
|
"vite-svg-loader": "^2.2.0",
|
||||||
"vue-eslint-parser": "^7.10.0"
|
"vue-eslint-parser": "7.10.0"
|
||||||
},
|
},
|
||||||
"repository": "git@github.com:xiaoxian521/vue-pure-admin.git",
|
"repository": "git@github.com:xiaoxian521/vue-pure-admin.git",
|
||||||
"author": "xiaoxian521",
|
"author": "xiaoxian521",
|
||||||
|
6529
pnpm-lock.yaml
generated
Normal file
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 1.2 KiB |
@ -1,9 +1,22 @@
|
|||||||
{
|
{
|
||||||
"Version": "2.1.0",
|
"Version": "2.6.0",
|
||||||
"Title": "PureAdmin",
|
"Title": "PureAdmin",
|
||||||
"FixedHeader": true,
|
"FixedHeader": true,
|
||||||
"HiddenSideBar": false,
|
"HiddenSideBar": false,
|
||||||
"KeepAlive": true,
|
"KeepAlive": true,
|
||||||
"Locale": "zh",
|
"Locale": "zh",
|
||||||
"Layout": "vertical-dark"
|
"Layout": "vertical",
|
||||||
|
"Theme": "default",
|
||||||
|
"Grey": false,
|
||||||
|
"Weak": false,
|
||||||
|
"HideTabs": false,
|
||||||
|
"MapConfigure": {
|
||||||
|
"amapKey": "97b3248d1553172e81f168cf94ea667e",
|
||||||
|
"baiduKey": "wTHbkkEweiFqZLKunMIjcrb2RcqNXkhc",
|
||||||
|
"options": {
|
||||||
|
"resizeEnable": true,
|
||||||
|
"center": [113.6401, 34.72468],
|
||||||
|
"zoom": 12
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,8 @@ export default {
|
|||||||
[ElConfigProvider.name]: ElConfigProvider
|
[ElConfigProvider.name]: ElConfigProvider
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
// eslint-disable-next-line vue/return-in-computed-property
|
|
||||||
currentLocale() {
|
currentLocale() {
|
||||||
switch (this.$storage.locale?.locale) {
|
return this.$storage.locale?.locale === "zh" ? zhCn : en;
|
||||||
case "zh":
|
|
||||||
return zhCn;
|
|
||||||
case "en":
|
|
||||||
return en;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { http } from "/@/utils/http";
|
import { http } from "../utils/http";
|
||||||
|
|
||||||
export const getAsyncRoutes = (data?: object) => {
|
export const getAsyncRoutes = (data?: object) => {
|
||||||
return http.request("get", "/getAsyncRoutes", data);
|
return http.request("get", "/getAsyncRoutes", data);
|
||||||
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 680 KiB |
Before Width: | Height: | Size: 1.1 MiB |
BIN
src/assets/car.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
@ -1,8 +1,8 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 2208059 */
|
font-family: "iconfont"; /* Project id 2208059 */
|
||||||
src: url("iconfont.woff2?t=1634092870259") format("woff2"),
|
src: url("iconfont.woff2?t=1636197082361") format("woff2"),
|
||||||
url("iconfont.woff?t=1634092870259") format("woff"),
|
url("iconfont.woff?t=1636197082361") format("woff"),
|
||||||
url("iconfont.ttf?t=1634092870259") format("truetype");
|
url("iconfont.ttf?t=1636197082361") format("truetype");
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
@ -13,8 +13,8 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
.team-iconzuixinlianzai::before {
|
.team-iconlogo::before {
|
||||||
content: "\e6da";
|
content: "\e620";
|
||||||
}
|
}
|
||||||
|
|
||||||
.team-iconxinpin::before {
|
.team-iconxinpin::before {
|
||||||
@ -25,22 +25,6 @@
|
|||||||
content: "\e615";
|
content: "\e615";
|
||||||
}
|
}
|
||||||
|
|
||||||
.team-iconinternationality::before {
|
|
||||||
content: "\e67a";
|
|
||||||
}
|
|
||||||
|
|
||||||
.team-iconshanchu::before {
|
|
||||||
content: "\e617";
|
|
||||||
}
|
|
||||||
|
|
||||||
.team-iconshow-main-container::before {
|
|
||||||
content: "\e878";
|
|
||||||
}
|
|
||||||
|
|
||||||
.team-iconhidden-main-container::before {
|
|
||||||
content: "\e881";
|
|
||||||
}
|
|
||||||
|
|
||||||
.team-iconexit-fullscreen::before {
|
.team-iconexit-fullscreen::before {
|
||||||
content: "\e62a";
|
content: "\e62a";
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
"description": "pure-admin",
|
"description": "pure-admin",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
{
|
{
|
||||||
"icon_id": "2508809",
|
"icon_id": "22129506",
|
||||||
"name": "最新连载",
|
"name": "水能",
|
||||||
"font_class": "zuixinlianzai",
|
"font_class": "logo",
|
||||||
"unicode": "e6da",
|
"unicode": "e620",
|
||||||
"unicode_decimal": 59098
|
"unicode_decimal": 58912
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"icon_id": "7795613",
|
"icon_id": "7795613",
|
||||||
@ -26,34 +26,6 @@
|
|||||||
"unicode": "e615",
|
"unicode": "e615",
|
||||||
"unicode_decimal": 58901
|
"unicode_decimal": 58901
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"icon_id": "18367956",
|
|
||||||
"name": "中英文2 中文",
|
|
||||||
"font_class": "internationality",
|
|
||||||
"unicode": "e67a",
|
|
||||||
"unicode_decimal": 59002
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "6184565",
|
|
||||||
"name": "删除",
|
|
||||||
"font_class": "shanchu",
|
|
||||||
"unicode": "e617",
|
|
||||||
"unicode_decimal": 58903
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "9626913",
|
|
||||||
"name": "全屏",
|
|
||||||
"font_class": "show-main-container",
|
|
||||||
"unicode": "e878",
|
|
||||||
"unicode_decimal": 59512
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "9626952",
|
|
||||||
"name": "退出全屏",
|
|
||||||
"font_class": "hidden-main-container",
|
|
||||||
"unicode": "e881",
|
|
||||||
"unicode_decimal": 59521
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"icon_id": "5698509",
|
"icon_id": "5698509",
|
||||||
"name": "全屏缩小",
|
"name": "全屏缩小",
|
||||||
|
Before Width: | Height: | Size: 9.9 KiB |
1
src/assets/login/avatar.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg t="1636193306629" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1847" width="32" height="32"><path d="M410.558481 0.10861C410.558481 211.083075 109.682285 361.860579 109.682285 633.656511c0 174.943176 134.703259 316.787527 300.876196 316.787527s300.876197-141.817198 300.876197-316.787527C711.407525 361.751969 410.558481 210.974465 410.558481 0.10861z" fill="#386BF3" p-id="1848"></path><path d="M613.468671 73.664572c0 211.055922-300.876197 361.914883-300.876196 633.547901 0 174.943176 134.703259 316.787527 300.876196 316.787527s300.876197-141.817198 300.876197-316.787527c-0.054305-271.633018-300.876197-422.491979-300.876197-633.547901z" fill="#C3D2FB" p-id="1849"></path><path d="M312.592475 707.212473c0-183.713414 137.635722-312.171612 226.72288-441.390078 81.701694 106.111739 172.119322 218.740063 172.119323 367.725506a309.755045 309.755045 0 0 1-291.074166 316.516003 323.114046 323.114046 0 0 1-107.768037-242.851431z" fill="#303F5B" p-id="1850"></path></svg>
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/assets/login/bg.png
Normal file
After Width: | Height: | Size: 17 KiB |
1
src/assets/login/illustration0.svg
Normal file
After Width: | Height: | Size: 20 KiB |
1
src/assets/login/illustration1.svg
Normal file
After Width: | Height: | Size: 17 KiB |
1
src/assets/login/illustration2.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width="500" height="380" viewBox="0 0 896 529.1129" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M832.06729,623.22778s-26.37759,9.89441-38.806,32.94348S787.06,706.69574,787.06,706.69574s26.37759-9.89447,38.806-32.94348S832.06729,623.22778,832.06729,623.22778Z" transform="translate(-158 -185.8871)" fill="#3f3d56"/><path d="M867.5,657.59637s-8.64182,26.814-31.0802,40.31373-50.17651,8.57293-50.17651,8.57293,8.64175-26.81408,31.08017-40.31378S867.5,657.59637,867.5,657.59637Z" transform="translate(-158 -185.8871)" fill="#5392f0"/><rect y="527.1129" width="896" height="2" fill="#2f2e41"/><path d="M519.87238,620.97461a95.44448,95.44448,0,0,1-35.748-14.44629L485.306,604.915a93.36283,93.36283,0,0,0,34.999,14.10547c18.93164,3.40137,47.26075,1.73144,74.707-25.52735,53.41358-53.04785,104.39307-58.39062,104.90186-58.43847l.18652,1.99219c-.50146.04687-50.76806,5.31738-103.67822,57.86621-21.61328,21.46386-43.792,27.40234-61.71777,27.40234A83.49962,83.49962,0,0,1,519.87238,620.97461Z" transform="translate(-158 -185.8871)" fill="#2f2e41"/><circle cx="515.15271" cy="381.1129" r="12" fill="#2f2e41"/><circle cx="430.15271" cy="437.1129" r="12" fill="#2f2e41"/><path d="M841.5,714s-17.46191-5.41315-52.26129-10.84192L790,692.5c6-60-34-150-34-150a401.561,401.561,0,0,1,21.4693,139.0246C772.13214,672.2124,761.82056,662.16638,742,656c0,0,25.77765,22.106,33.15918,45.10175a997.84042,997.84042,0,0,0-102.02258-8.21589L682,672.5l-17,17s-7-51-22-53l11,50s-13-10-16-9l7.39746,14.79486c-49.819-.51654-109.08453,1.7356-177.76581,8.95227L476,682l-17,17s-7-51-22-53l11,50s-13-10-16-9l8.64288,17.28583Q406.9763,708.2897,370.5,714Z" transform="translate(-158 -185.8871)" fill="#3f3d56"/><path d="M565.64813,230.37817c-10.89964,11.74783,17.59745,40.25959,17.59745,40.25959s-57.70662,9.73051-53.12783,9.14083,2.20622-49.13151,2.20622-49.13151S576.54777,218.63035,565.64813,230.37817Z" transform="translate(-158 -185.8871)" fill="#a0616a"/><path d="M605.81236,356.10945l-50.139,25.6141-27.22969,15.6059s-32.09862,40.43116-38.08709,64.39234,25.92963,68.247,29.54371,72.82286a54.36088,54.36088,0,0,1,4.98908,7.42355c1.24727,1.85589,12.02944-.541,23.80342-3.06554S547.13,518.93875,547.13,518.93875s-15.02732-38.39505-16.14686-39.25912c-1.04554-.807-4.60093-7.44631-2.04309-10.35234a25.94993,25.94993,0,0,0,5.44489-8.89825,30.09064,30.09064,0,0,1,4.18709-7.94151s45.361-36.83645,59.52776-49.37835,51.82952-4.65839,51.82952-4.65839-17.78167,68.20027-22.22979,72.80616-4.929,8.70085-2.91535,16.50759,28.28157.39078,28.28157.39078L662.766,461.6996s15.74879-34.2925,24.29946-69.67451c4.27533-17.691-3.88828-28.23462-13.12073-34.35549a41.39094,41.39094,0,0,0-30.02983-5.97766l-46.34848,8.1308,32.14706-13.84923Z" transform="translate(-158 -185.8871)" fill="#2f2e41"/><path d="M420.87777,290.19133,361.02366,271.685s-24.179-31.16689-12.78824-36.6669,25.65172,26.94419,25.65172,26.94419l41.686,2.69751Z" transform="translate(-158 -185.8871)" fill="#a0616a"/><path d="M672.49431,257.78673l53.2121-33.06768s15.49333-36.27612,3.0807-38.71059-17.98787,32.56435-17.98787,32.56435l-39.64232,13.17143Z" transform="translate(-158 -185.8871)" fill="#a0616a"/><path d="M682.45318,220.40023l1.01427,39.19147-89.68779,16.025c13.19231,28.22441,9.84118,60.34675,43.04725,74.4259L524.9027,404.78717c4.9871-43.03806-15.81748-75.456-35.263-115.75876-23.68547-8.58589-51.19594-2.29078-80.33649,10.34619l-5.237-40.66416,123.87841-8.896,20.34848,7.77932,21.81842-9.17677C602.17891,238.88953,648.22076,220.77584,682.45318,220.40023Z" transform="translate(-158 -185.8871)" fill="#5392f0"/><path d="M626.64006,486.51727c-2.72,2.36681-5.25213,21.84984-5.34982,28.92023s9.21178,8.89624,14.29855,9.2494,4.47816,3.45631,7.83678,6.04854,14.39625,2.179,28.89019-2.71238-9.75274-20.92568-11.86409-21.662-11-22.78156-11-22.78156S629.36,484.15046,626.64006,486.51727Z" transform="translate(-158 -185.8871)" fill="#2f2e41"/><path d="M547.368,531.00717c3.23089,1.60043,10.61681,19.80614,12.50274,26.62107s-6.65716,10.93994-11.48848,12.5704-3.45631,4.47816-6.04855,7.83678-13.3744,5.75546-28.63472,4.696,4.13258-22.71391,5.98847-23.96118,4.86893-24.82526,4.86893-24.82526S544.13715,529.40674,547.368,531.00717Z" transform="translate(-158 -185.8871)" fill="#2f2e41"/><circle cx="389.47074" cy="35.42904" r="23.99585" fill="#a0616a"/><path d="M519.73448,218.90923a22.82668,22.82668,0,0,1-.83378-18.59281c2.35891-5.8153,7.59174-11.65569,18.87309-13.4,24.61387-3.80572,37.71267,13.43543,37.02452,19.07449s-3.99294,19.27051-3.99294,19.27051,1.47587-12.90619-4.85883-13.362-30.90178-2.37835-37.12217,4.145a14.23268,14.23268,0,0,0-3.71042,13.82977Z" transform="translate(-158 -185.8871)" fill="#2f2e41"/></svg>
|
After Width: | Height: | Size: 4.6 KiB |
1
src/assets/login/illustration3.svg
Normal file
After Width: | Height: | Size: 11 KiB |
1
src/assets/login/illustration4.svg
Normal file
After Width: | Height: | Size: 12 KiB |
1
src/assets/login/illustration5.svg
Normal file
After Width: | Height: | Size: 29 KiB |
1
src/assets/login/illustration6.svg
Normal file
After Width: | Height: | Size: 11 KiB |
1
src/assets/svg/back_top.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M2.88 18.054a35.897 35.897 0 0 1 8.531-16.32.8.8 0 0 1 1.178 0c.166.18.304.332.413.455a35.897 35.897 0 0 1 8.118 15.865c-2.141.451-4.34.747-6.584.874l-2.089 4.178a.5.5 0 0 1-.894 0l-2.089-4.178a44.019 44.019 0 0 1-6.584-.874zm6.698-1.123l1.157.066L12 19.527l1.265-2.53 1.157-.066a42.137 42.137 0 0 0 4.227-.454A33.913 33.913 0 0 0 12 4.09a33.913 33.913 0 0 0-6.649 12.387c1.395.222 2.805.374 4.227.454zM12 15a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
|
After Width: | Height: | Size: 608 B |
@ -1,195 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { ref, PropType, getCurrentInstance, watch, nextTick, toRef } from "vue";
|
|
||||||
import { useRouter, useRoute } from "vue-router";
|
|
||||||
import { initRouter } from "/@/router";
|
|
||||||
import { storageSession } from "/@/utils/storage";
|
|
||||||
|
|
||||||
export interface ContextProps {
|
|
||||||
userName: string;
|
|
||||||
passWord: string;
|
|
||||||
verify: number | null;
|
|
||||||
svg: any;
|
|
||||||
telephone?: number;
|
|
||||||
dynamicText?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
ruleForm: {
|
|
||||||
type: Object as PropType<ContextProps>
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: "onBehavior", evt: Object): void;
|
|
||||||
(e: "refreshVerify"): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
|
|
||||||
const model = toRef(props, "ruleForm");
|
|
||||||
let tips = ref<string>("注册");
|
|
||||||
let tipsFalse = ref<string>("登录");
|
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
watch(
|
|
||||||
route,
|
|
||||||
async ({ path }): Promise<void> => {
|
|
||||||
await nextTick();
|
|
||||||
path.includes("register")
|
|
||||||
? (tips.value = "登录") && (tipsFalse.value = "注册")
|
|
||||||
: (tips.value = "注册") && (tipsFalse.value = "登录");
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
const rules = ref<any>({
|
|
||||||
userName: [{ required: true, message: "请输入用户名", trigger: "blur" }],
|
|
||||||
passWord: [
|
|
||||||
{ required: true, message: "请输入密码", trigger: "blur" },
|
|
||||||
{ min: 6, message: "密码长度必须不小于6位", trigger: "blur" }
|
|
||||||
],
|
|
||||||
verify: [
|
|
||||||
{ required: true, message: "请输入验证码", trigger: "blur" },
|
|
||||||
{ type: "number", message: "验证码必须是数字类型", trigger: "blur" }
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
// 点击登录或注册
|
|
||||||
const onBehavior = (evt: Object): void => {
|
|
||||||
// @ts-expect-error
|
|
||||||
instance.refs.ruleForm.validate((valid: boolean) => {
|
|
||||||
if (valid) {
|
|
||||||
emit("onBehavior", evt);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 刷新验证码
|
|
||||||
const refreshVerify = (): void => {
|
|
||||||
emit("refreshVerify");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 表单重置
|
|
||||||
const resetForm = (): void => {
|
|
||||||
// @ts-expect-error
|
|
||||||
instance.refs.ruleForm.resetFields();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 登录、注册页面切换
|
|
||||||
const changPage = (): void => {
|
|
||||||
tips.value === "注册" ? router.push("/register") : router.push("/login");
|
|
||||||
};
|
|
||||||
|
|
||||||
const noSecret = (): void => {
|
|
||||||
storageSession.setItem("info", {
|
|
||||||
username: "admin",
|
|
||||||
accessToken: "eyJhbGciOiJIUzUxMiJ9.test"
|
|
||||||
});
|
|
||||||
initRouter("admin").then(() => {});
|
|
||||||
router.push("/");
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="info">
|
|
||||||
<el-form :model="model" :rules="rules" ref="ruleForm" class="rule-form">
|
|
||||||
<el-form-item prop="userName">
|
|
||||||
<el-input
|
|
||||||
clearable
|
|
||||||
v-model="model.userName"
|
|
||||||
placeholder="请输入用户名"
|
|
||||||
prefix-icon="el-icon-user"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="passWord">
|
|
||||||
<el-input
|
|
||||||
clearable
|
|
||||||
type="password"
|
|
||||||
show-password
|
|
||||||
v-model="model.passWord"
|
|
||||||
placeholder="请输入密码"
|
|
||||||
prefix-icon="el-icon-lock"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="verify">
|
|
||||||
<el-input
|
|
||||||
maxlength="2"
|
|
||||||
onkeyup="this.value=this.value.replace(/[^\d.]/g,'');"
|
|
||||||
v-model.number="model.verify"
|
|
||||||
placeholder="请输入验证码"
|
|
||||||
></el-input>
|
|
||||||
<span
|
|
||||||
class="verify"
|
|
||||||
title="刷新"
|
|
||||||
v-html="model.svg"
|
|
||||||
@click.prevent="refreshVerify"
|
|
||||||
></span>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" @click.prevent="onBehavior">{{
|
|
||||||
tipsFalse
|
|
||||||
}}</el-button>
|
|
||||||
<el-button @click="resetForm">重置</el-button>
|
|
||||||
<span class="tips" @click="changPage">{{ tips }}</span>
|
|
||||||
</el-form-item>
|
|
||||||
<span title="测试用户 直接登录" class="secret" @click="noSecret"
|
|
||||||
>免密登录</span
|
|
||||||
>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.info {
|
|
||||||
width: 30vw;
|
|
||||||
height: 48vh;
|
|
||||||
background: url("../../assets/login.png") no-repeat center;
|
|
||||||
background-size: cover;
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 20px;
|
|
||||||
right: 100px;
|
|
||||||
top: 30vh;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
@media screen and (max-width: 750px) {
|
|
||||||
width: 88vw;
|
|
||||||
right: 25px;
|
|
||||||
top: 22vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rule-form {
|
|
||||||
width: 80%;
|
|
||||||
|
|
||||||
.verify {
|
|
||||||
position: absolute;
|
|
||||||
margin: -10px 0 0 -120px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips {
|
|
||||||
color: #409eff;
|
|
||||||
float: right;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.secret {
|
|
||||||
color: #409eff;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,52 +1,130 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, getCurrentInstance } from "vue";
|
import {
|
||||||
|
h,
|
||||||
|
ref,
|
||||||
|
computed,
|
||||||
|
Transition,
|
||||||
|
defineComponent,
|
||||||
|
getCurrentInstance
|
||||||
|
} from "vue";
|
||||||
|
import { RouterView } from "vue-router";
|
||||||
|
import backTop from "/@/assets/svg/back_top.svg";
|
||||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
fixedHeader: Boolean
|
||||||
|
});
|
||||||
const keepAlive: Boolean = ref(
|
const keepAlive: Boolean = ref(
|
||||||
getCurrentInstance().appContext.config.globalProperties.$config?.KeepAlive
|
getCurrentInstance().appContext.config.globalProperties.$config?.KeepAlive
|
||||||
);
|
);
|
||||||
|
const instance =
|
||||||
|
getCurrentInstance().appContext.app.config.globalProperties.$storage;
|
||||||
|
|
||||||
const transition = computed(() => {
|
const transitions = computed(() => {
|
||||||
return route => {
|
return route => {
|
||||||
return route.meta.transition;
|
return route.meta.transition;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const hideTabs = computed(() => {
|
||||||
|
return instance?.sets.hideTabs;
|
||||||
|
});
|
||||||
|
const layout = computed(() => {
|
||||||
|
return instance?.layout.layout === "vertical";
|
||||||
|
});
|
||||||
|
|
||||||
|
const transitionMain = defineComponent({
|
||||||
|
render() {
|
||||||
|
return h(
|
||||||
|
Transition,
|
||||||
|
{
|
||||||
|
name:
|
||||||
|
transitions.value(this.route) &&
|
||||||
|
this.route.meta.transition.enterTransition
|
||||||
|
? "pure-classes-transition"
|
||||||
|
: (transitions.value(this.route) &&
|
||||||
|
this.route.meta.transition.name) ||
|
||||||
|
"fade-transform",
|
||||||
|
enterActiveClass:
|
||||||
|
transitions.value(this.route) &&
|
||||||
|
`animate__animated ${this.route.meta.transition.enterTransition}`,
|
||||||
|
leaveActiveClass:
|
||||||
|
transitions.value(this.route) &&
|
||||||
|
`animate__animated ${this.route.meta.transition.leaveTransition}`,
|
||||||
|
mode: "out-in",
|
||||||
|
appear: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => [this.$slots.default()]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
route: {
|
||||||
|
type: undefined,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="app-main">
|
<section
|
||||||
<el-scrollbar>
|
:class="[props.fixedHeader ? 'app-main' : 'app-main-nofixed-header']"
|
||||||
<router-view>
|
:style="[
|
||||||
<template #default="{ Component, route }">
|
hideTabs && layout ? 'padding-top: 48px;' : '',
|
||||||
<transition
|
!hideTabs && layout ? 'padding-top: 85px;' : '',
|
||||||
:name="
|
hideTabs && !layout ? 'padding-top: 62px' : '',
|
||||||
transition(route) && route.meta.transition.enterTransition
|
!hideTabs && !layout ? 'padding-top: 98px;' : ''
|
||||||
? 'pure-classes-transition'
|
]"
|
||||||
: (transition(route) && route.meta.transition.name) ||
|
>
|
||||||
'fade-transform'
|
<router-view>
|
||||||
"
|
<template #default="{ Component, route }">
|
||||||
:enter-active-class="
|
<el-scrollbar v-if="props.fixedHeader">
|
||||||
transition(route) &&
|
<el-backtop title="回到顶部" target=".app-main .el-scrollbar__wrap">
|
||||||
`animate__animated ${route.meta.transition.enterTransition}`
|
<backTop />
|
||||||
"
|
</el-backtop>
|
||||||
:leave-active-class="
|
<transitionMain :route="route">
|
||||||
transition(route) &&
|
|
||||||
`animate__animated ${route.meta.transition.leaveTransition}`
|
|
||||||
"
|
|
||||||
mode="out-in"
|
|
||||||
appear
|
|
||||||
>
|
|
||||||
<keep-alive
|
<keep-alive
|
||||||
v-if="keepAlive"
|
v-if="keepAlive"
|
||||||
:include="usePermissionStoreHook().cachePageList"
|
:include="usePermissionStoreHook().cachePageList"
|
||||||
>
|
>
|
||||||
<component :is="Component" :key="route.fullPath" />
|
<component
|
||||||
|
:is="Component"
|
||||||
|
:key="route.fullPath"
|
||||||
|
class="main-content"
|
||||||
|
/>
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
<component v-else :is="Component" :key="route.fullPath" />
|
<component
|
||||||
</transition>
|
v-else
|
||||||
</template>
|
:is="Component"
|
||||||
</router-view>
|
:key="route.fullPath"
|
||||||
</el-scrollbar>
|
class="main-content"
|
||||||
|
/>
|
||||||
|
</transitionMain>
|
||||||
|
</el-scrollbar>
|
||||||
|
<div v-else>
|
||||||
|
<transitionMain :route="route">
|
||||||
|
<keep-alive
|
||||||
|
v-if="keepAlive"
|
||||||
|
:include="usePermissionStoreHook().cachePageList"
|
||||||
|
>
|
||||||
|
<component
|
||||||
|
:is="Component"
|
||||||
|
:key="route.fullPath"
|
||||||
|
class="main-content"
|
||||||
|
/>
|
||||||
|
</keep-alive>
|
||||||
|
<component
|
||||||
|
v-else
|
||||||
|
:is="Component"
|
||||||
|
:key="route.fullPath"
|
||||||
|
class="main-content"
|
||||||
|
/>
|
||||||
|
</transitionMain>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</router-view>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -57,4 +135,14 @@ const transition = computed(() => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.app-main-nofixed-header {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100vh;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
margin: 24px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -78,6 +78,8 @@ function translationEn() {
|
|||||||
color: locale === 'zh' ? '#f4f4f5' : '#000'
|
color: locale === 'zh' ? '#f4f4f5' : '#000'
|
||||||
}"
|
}"
|
||||||
@click="translationCh"
|
@click="translationCh"
|
||||||
|
><el-icon class="check-zh" v-show="locale === 'zh'"
|
||||||
|
><check /></el-icon
|
||||||
>简体中文</el-dropdown-item
|
>简体中文</el-dropdown-item
|
||||||
>
|
>
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
@ -86,6 +88,8 @@ function translationEn() {
|
|||||||
color: locale === 'en' ? '#f4f4f5' : '#000'
|
color: locale === 'en' ? '#f4f4f5' : '#000'
|
||||||
}"
|
}"
|
||||||
@click="translationEn"
|
@click="translationEn"
|
||||||
|
><el-icon class="check-en" v-show="locale === 'en'"
|
||||||
|
><check /></el-icon
|
||||||
>English</el-dropdown-item
|
>English</el-dropdown-item
|
||||||
>
|
>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
@ -107,11 +111,13 @@ function translationEn() {
|
|||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
<i
|
<el-icon
|
||||||
class="el-icon-setting"
|
class="el-icon-setting"
|
||||||
:title="$t('message.hssystemSet')"
|
:title="$t('message.hssystemSet')"
|
||||||
@click="onPanel"
|
@click="onPanel"
|
||||||
></i>
|
>
|
||||||
|
<Setting />
|
||||||
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -191,8 +197,8 @@ function translationEn() {
|
|||||||
|
|
||||||
.el-icon-setting {
|
.el-icon-setting {
|
||||||
height: 48px;
|
height: 48px;
|
||||||
width: 40px;
|
width: 38px;
|
||||||
padding: 11px;
|
padding: 12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -218,6 +224,18 @@ function translationEn() {
|
|||||||
color: #606266;
|
color: #606266;
|
||||||
background: #f0f0f0;
|
background: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.check-zh {
|
||||||
|
position: absolute;
|
||||||
|
left: 20px;
|
||||||
|
top: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-en {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 13px;
|
||||||
|
left: 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.logout {
|
.logout {
|
||||||
|
@ -1,33 +1,18 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useEventListener, onClickOutside } from "@vueuse/core";
|
import { onClickOutside } from "@vueuse/core";
|
||||||
import { emitter } from "/@/utils/mitt";
|
import { emitter } from "/@/utils/mitt";
|
||||||
|
|
||||||
let show = ref<Boolean>(false);
|
let show = ref<Boolean>(false);
|
||||||
const target = ref(null);
|
const target = ref(null);
|
||||||
onClickOutside(target, () => {
|
onClickOutside(target, event => {
|
||||||
|
if (event.clientX > target.value.offsetLeft) return;
|
||||||
show.value = false;
|
show.value = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
const addEventClick = (): void => {
|
|
||||||
useEventListener("click", closeSidebar);
|
|
||||||
};
|
|
||||||
|
|
||||||
const closeSidebar = (evt: any): void => {
|
|
||||||
const parent = evt.target.closest(".right-panel");
|
|
||||||
if (!parent) {
|
|
||||||
show.value = false;
|
|
||||||
window.removeEventListener("click", closeSidebar);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
emitter.on("openPanel", () => {
|
emitter.on("openPanel", () => {
|
||||||
show.value = true;
|
show.value = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
addEventClick
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -37,7 +22,9 @@ defineExpose({
|
|||||||
<div class="right-panel-items">
|
<div class="right-panel-items">
|
||||||
<div class="project-configuration">
|
<div class="project-configuration">
|
||||||
<h3>项目配置</h3>
|
<h3>项目配置</h3>
|
||||||
<i class="el-icon-close" @click="show = !show"></i>
|
<el-icon title="关闭配置" class="el-icon-close" @click="show = !show">
|
||||||
|
<Close />
|
||||||
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
<div style="border-bottom: 1px solid #dcdfe6"></div>
|
<div style="border-bottom: 1px solid #dcdfe6"></div>
|
||||||
<slot />
|
<slot />
|
||||||
|
@ -1,52 +1,84 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { split } from "lodash-es";
|
|
||||||
import panel from "../panel/index.vue";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import { emitter } from "/@/utils/mitt";
|
|
||||||
import { templateRef } from "@vueuse/core";
|
|
||||||
import { debounce } from "/@/utils/debounce";
|
|
||||||
import { useAppStoreHook } from "/@/store/modules/app";
|
|
||||||
import { storageLocal, storageSession } from "/@/utils/storage";
|
|
||||||
import {
|
import {
|
||||||
reactive,
|
reactive,
|
||||||
ref,
|
ref,
|
||||||
unref,
|
unref,
|
||||||
watch,
|
watch,
|
||||||
|
computed,
|
||||||
|
nextTick,
|
||||||
useCssModule,
|
useCssModule,
|
||||||
getCurrentInstance
|
getCurrentInstance
|
||||||
} from "vue";
|
} from "vue";
|
||||||
|
import panel from "../panel/index.vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { emitter } from "/@/utils/mitt";
|
||||||
|
import { templateRef } from "@vueuse/core";
|
||||||
|
import { debounce } from "/@/utils/debounce";
|
||||||
|
import { themeColorsType } from "../../types";
|
||||||
|
import { useAppStoreHook } from "/@/store/modules/app";
|
||||||
|
import { storageLocal, storageSession } from "/@/utils/storage";
|
||||||
|
import { toggleTheme } from "@zougt/vite-plugin-theme-preprocessor/dist/browser-utils";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { isSelect } = useCssModule();
|
const { isSelect } = useCssModule();
|
||||||
|
|
||||||
const instance =
|
const instance =
|
||||||
getCurrentInstance().appContext.app.config.globalProperties.$storage;
|
getCurrentInstance().appContext.app.config.globalProperties.$storage;
|
||||||
|
|
||||||
|
const instanceConfig =
|
||||||
|
getCurrentInstance().appContext.app.config.globalProperties.$config;
|
||||||
|
|
||||||
|
let themeColors = ref<Array<themeColorsType>>([
|
||||||
|
// 暗雅(默认)
|
||||||
|
{ rgb: "27, 42, 71", themeColor: "default" },
|
||||||
|
// 明亮
|
||||||
|
{ rgb: "255, 255, 255", themeColor: "light" },
|
||||||
|
// 薄暮
|
||||||
|
{ rgb: "245, 34, 45", themeColor: "dusk" },
|
||||||
|
// 火山
|
||||||
|
{ rgb: "250, 84, 28", themeColor: "volcano" },
|
||||||
|
// 黄色
|
||||||
|
{ rgb: "250, 219, 20", themeColor: "yellow" },
|
||||||
|
// 明青
|
||||||
|
{ rgb: "19, 194, 194", themeColor: "mingQing" },
|
||||||
|
// 极光绿
|
||||||
|
{ rgb: "82, 196, 26", themeColor: "auroraGreen" },
|
||||||
|
// 粉红
|
||||||
|
{ rgb: "235, 47, 150", themeColor: "pink" },
|
||||||
|
// 酱紫
|
||||||
|
{ rgb: "114, 46, 209", themeColor: "saucePurple" }
|
||||||
|
]);
|
||||||
|
|
||||||
|
const verticalRef = templateRef<HTMLElement | null>("verticalRef", null);
|
||||||
|
const horizontalRef = templateRef<HTMLElement | null>("horizontalRef", null);
|
||||||
|
|
||||||
|
let layoutTheme =
|
||||||
|
ref(storageLocal.getItem("responsive-layout")) ||
|
||||||
|
ref({
|
||||||
|
layout: instanceConfig?.Layout ?? "vertical",
|
||||||
|
theme: instanceConfig?.Theme ?? "default"
|
||||||
|
});
|
||||||
|
|
||||||
|
// body添加layout属性,作用于src/style/sidebar.scss
|
||||||
|
if (unref(layoutTheme)) {
|
||||||
|
let layout = unref(layoutTheme).layout;
|
||||||
|
let theme = unref(layoutTheme).theme;
|
||||||
|
toggleTheme({
|
||||||
|
scopeName: `layout-theme-${theme}`
|
||||||
|
});
|
||||||
|
setLayoutModel(layout);
|
||||||
|
}
|
||||||
|
|
||||||
// 默认灵动模式
|
// 默认灵动模式
|
||||||
const markValue = ref(storageLocal.getItem("showModel") || "smart");
|
const markValue = ref(storageLocal.getItem("showModel") || "smart");
|
||||||
|
|
||||||
const logoVal = ref(storageLocal.getItem("logoVal") || "1");
|
const logoVal = ref(storageLocal.getItem("logoVal") || "1");
|
||||||
|
|
||||||
const localOperate = (key: string, value?: any, model?: string): any => {
|
|
||||||
model && model === "set"
|
|
||||||
? storageLocal.setItem(key, value)
|
|
||||||
: storageLocal.getItem(key);
|
|
||||||
};
|
|
||||||
|
|
||||||
const settings = reactive({
|
const settings = reactive({
|
||||||
greyVal: storageLocal.getItem("greyVal"),
|
greyVal: instance.sets.grey,
|
||||||
weekVal: storageLocal.getItem("weekVal"),
|
weakVal: instance.sets.weak,
|
||||||
tagsVal: storageLocal.getItem("tagsVal")
|
tabsVal: instance.sets.hideTabs
|
||||||
});
|
});
|
||||||
|
|
||||||
settings.greyVal === null
|
|
||||||
? localOperate("greyVal", false, "set")
|
|
||||||
: document.querySelector("html")?.setAttribute("class", "html-grey");
|
|
||||||
|
|
||||||
settings.weekVal === null
|
|
||||||
? localOperate("weekVal", false, "set")
|
|
||||||
: document.querySelector("html")?.setAttribute("class", "html-weakness");
|
|
||||||
|
|
||||||
function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
|
function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
|
||||||
const targetEl = target || document.body;
|
const targetEl = target || document.body;
|
||||||
let { className } = targetEl;
|
let { className } = targetEl;
|
||||||
@ -55,76 +87,62 @@ function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 灰色模式设置
|
// 灰色模式设置
|
||||||
const greyChange = ({ value }): void => {
|
const greyChange = (value): void => {
|
||||||
toggleClass(settings.greyVal, "html-grey", document.querySelector("html"));
|
toggleClass(settings.greyVal, "html-grey", document.querySelector("html"));
|
||||||
value
|
instance.sets = {
|
||||||
? localOperate("greyVal", true, "set")
|
grey: value,
|
||||||
: localOperate("greyVal", false, "set");
|
weak: instance.sets.weak,
|
||||||
|
hideTabs: instance.sets.hideTabs
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// 色弱模式设置
|
// 色弱模式设置
|
||||||
const weekChange = ({ value }): void => {
|
const weekChange = (value): void => {
|
||||||
toggleClass(
|
toggleClass(
|
||||||
settings.weekVal,
|
settings.weakVal,
|
||||||
"html-weakness",
|
"html-weakness",
|
||||||
document.querySelector("html")
|
document.querySelector("html")
|
||||||
);
|
);
|
||||||
value
|
instance.sets = {
|
||||||
? localOperate("weekVal", true, "set")
|
grey: instance.sets.grey,
|
||||||
: localOperate("weekVal", false, "set");
|
weak: value,
|
||||||
|
hideTabs: instance.sets.hideTabs
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const tagsChange = () => {
|
const tagsChange = () => {
|
||||||
let showVal = settings.tagsVal;
|
let showVal = settings.tabsVal;
|
||||||
showVal
|
instance.sets = {
|
||||||
? storageLocal.setItem("tagsVal", true)
|
grey: instance.sets.grey,
|
||||||
: storageLocal.setItem("tagsVal", false);
|
weak: instance.sets.weak,
|
||||||
|
hideTabs: showVal
|
||||||
|
};
|
||||||
emitter.emit("tagViewsChange", showVal);
|
emitter.emit("tagViewsChange", showVal);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//初始化项目配置
|
||||||
|
nextTick(() => {
|
||||||
|
settings.greyVal &&
|
||||||
|
document.querySelector("html")?.setAttribute("class", "html-grey");
|
||||||
|
settings.weakVal &&
|
||||||
|
document.querySelector("html")?.setAttribute("class", "html-weakness");
|
||||||
|
settings.tabsVal && tagsChange();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 清空缓存并返回登录页
|
||||||
function onReset() {
|
function onReset() {
|
||||||
storageLocal.clear();
|
storageLocal.clear();
|
||||||
storageSession.clear();
|
storageSession.clear();
|
||||||
|
toggleClass(false, "html-grey", document.querySelector("html"));
|
||||||
|
toggleClass(false, "html-weakness", document.querySelector("html"));
|
||||||
router.push("/login");
|
router.push("/login");
|
||||||
}
|
}
|
||||||
|
|
||||||
function onChange({ label }) {
|
function onChange(label) {
|
||||||
storageLocal.setItem("showModel", label);
|
storageLocal.setItem("showModel", label);
|
||||||
emitter.emit("tagViewsShowModel", label);
|
emitter.emit("tagViewsShowModel", label);
|
||||||
}
|
}
|
||||||
|
|
||||||
const verticalDarkDom = templateRef<HTMLElement | null>(
|
|
||||||
"verticalDarkDom",
|
|
||||||
null
|
|
||||||
);
|
|
||||||
const verticalLightDom = templateRef<HTMLElement | null>(
|
|
||||||
"verticalLightDom",
|
|
||||||
null
|
|
||||||
);
|
|
||||||
const horizontalDarkDom = templateRef<HTMLElement | null>(
|
|
||||||
"horizontalDarkDom",
|
|
||||||
null
|
|
||||||
);
|
|
||||||
const horizontalLightDom = templateRef<HTMLElement | null>(
|
|
||||||
"horizontalLightDom",
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
let dataTheme =
|
|
||||||
ref(storageLocal.getItem("responsive-layout")) ||
|
|
||||||
ref({
|
|
||||||
layout: "horizontal-dark"
|
|
||||||
});
|
|
||||||
|
|
||||||
if (unref(dataTheme)) {
|
|
||||||
// 设置主题
|
|
||||||
let theme = split(unref(dataTheme).layout, "-")[1];
|
|
||||||
window.document.body.setAttribute("data-theme", theme);
|
|
||||||
// 设置导航模式
|
|
||||||
let layout = split(unref(dataTheme).layout, "-")[0];
|
|
||||||
window.document.body.setAttribute("data-layout", layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 侧边栏Logo
|
// 侧边栏Logo
|
||||||
function logoChange() {
|
function logoChange() {
|
||||||
unref(logoVal) === "1"
|
unref(logoVal) === "1"
|
||||||
@ -141,155 +159,170 @@ function setFalse(Doms): any {
|
|||||||
|
|
||||||
watch(instance, ({ layout }) => {
|
watch(instance, ({ layout }) => {
|
||||||
switch (layout["layout"]) {
|
switch (layout["layout"]) {
|
||||||
case "vertical-dark":
|
case "vertical":
|
||||||
toggleClass(true, isSelect, unref(verticalDarkDom));
|
toggleClass(true, isSelect, unref(verticalRef));
|
||||||
debounce(
|
debounce(setFalse([horizontalRef]), 50);
|
||||||
setFalse([verticalLightDom, horizontalDarkDom, horizontalLightDom]),
|
|
||||||
50
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case "vertical-light":
|
case "horizontal":
|
||||||
toggleClass(true, isSelect, unref(verticalLightDom));
|
toggleClass(true, isSelect, unref(horizontalRef));
|
||||||
debounce(
|
debounce(setFalse([verticalRef]), 50);
|
||||||
setFalse([verticalDarkDom, horizontalDarkDom, horizontalLightDom]),
|
|
||||||
50
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "horizontal-dark":
|
|
||||||
toggleClass(true, isSelect, unref(horizontalDarkDom));
|
|
||||||
debounce(
|
|
||||||
setFalse([verticalDarkDom, verticalLightDom, horizontalLightDom]),
|
|
||||||
50
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "horizontal-light":
|
|
||||||
toggleClass(true, isSelect, unref(horizontalLightDom));
|
|
||||||
debounce(
|
|
||||||
setFalse([verticalDarkDom, verticalLightDom, horizontalDarkDom]),
|
|
||||||
50
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function setTheme(layout: string, theme: string) {
|
// 主题色 激活选择项
|
||||||
dataTheme.value.layout = `${layout}-${theme}`;
|
const getThemeColor = computed(() => {
|
||||||
window.document.body.setAttribute("data-layout", layout);
|
return current => {
|
||||||
window.document.body.setAttribute("data-theme", theme);
|
if (
|
||||||
instance.layout = { layout: `${layout}-${theme}` };
|
current === layoutTheme.value.theme &&
|
||||||
|
layoutTheme.value.theme !== "light"
|
||||||
|
) {
|
||||||
|
return "#fff";
|
||||||
|
} else if (
|
||||||
|
current === layoutTheme.value.theme &&
|
||||||
|
layoutTheme.value.theme === "light"
|
||||||
|
) {
|
||||||
|
return "#1d2b45";
|
||||||
|
} else {
|
||||||
|
return "transparent";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// 设置导航模式
|
||||||
|
function setLayoutModel(layout: string) {
|
||||||
|
layoutTheme.value.layout = layout;
|
||||||
|
window.document.body.setAttribute("layout", layout);
|
||||||
|
instance.layout = { layout, theme: layoutTheme.value.theme };
|
||||||
useAppStoreHook().setLayout(layout);
|
useAppStoreHook().setLayout(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置导航主题色
|
||||||
|
function setLayoutThemeColor(theme: string) {
|
||||||
|
layoutTheme.value.theme = theme;
|
||||||
|
toggleTheme({
|
||||||
|
scopeName: `layout-theme-${theme}`
|
||||||
|
});
|
||||||
|
instance.layout = { layout: useAppStoreHook().layout, theme };
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<panel>
|
<panel>
|
||||||
<el-divider>主题风格</el-divider>
|
<el-divider>主题风格</el-divider>
|
||||||
<ul class="theme-stley">
|
<ul class="pure-theme">
|
||||||
<el-tooltip class="item" content="左侧菜单暗色模式" placement="bottom">
|
<el-tooltip class="item" content="左侧菜单模式" placement="bottom">
|
||||||
<li
|
<li
|
||||||
:class="dataTheme.layout === 'vertical-dark' ? $style.isSelect : ''"
|
:class="layoutTheme.layout === 'vertical' ? $style.isSelect : ''"
|
||||||
ref="verticalDarkDom"
|
ref="verticalRef"
|
||||||
@click="setTheme('vertical', 'dark')"
|
@click="setLayoutModel('vertical')"
|
||||||
>
|
>
|
||||||
<div></div>
|
<div></div>
|
||||||
<div></div>
|
<div></div>
|
||||||
</li>
|
</li>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
|
||||||
<el-tooltip class="item" content="左侧菜单亮色模式" placement="bottom">
|
<el-tooltip class="item" content="顶部菜单模式" placement="bottom">
|
||||||
<li
|
<li
|
||||||
:class="dataTheme.layout === 'vertical-light' ? $style.isSelect : ''"
|
:class="layoutTheme.layout === 'horizontal' ? $style.isSelect : ''"
|
||||||
ref="verticalLightDom"
|
ref="horizontalRef"
|
||||||
@click="setTheme('vertical', 'light')"
|
@click="setLayoutModel('horizontal')"
|
||||||
>
|
>
|
||||||
<div></div>
|
<div></div>
|
||||||
<div></div>
|
<div></div>
|
||||||
</li>
|
</li>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<el-tooltip class="item" content="顶部菜单暗色模式" placement="bottom">
|
<el-divider>主题色</el-divider>
|
||||||
<li
|
<ul class="theme-color">
|
||||||
:class="dataTheme.layout === 'horizontal-dark' ? $style.isSelect : ''"
|
<li
|
||||||
ref="horizontalDarkDom"
|
v-for="(item, index) in themeColors"
|
||||||
@click="setTheme('horizontal', 'dark')"
|
:key="index"
|
||||||
|
:style="{ background: `rgb(${item.rgb})` }"
|
||||||
|
@click="setLayoutThemeColor(item.themeColor)"
|
||||||
|
>
|
||||||
|
<el-icon
|
||||||
|
style="margin: 0.1em 0.1em 0 0"
|
||||||
|
:size="17"
|
||||||
|
:color="getThemeColor(item.themeColor)"
|
||||||
>
|
>
|
||||||
<div></div>
|
<Check />
|
||||||
<div></div>
|
</el-icon>
|
||||||
</li>
|
</li>
|
||||||
</el-tooltip>
|
|
||||||
|
|
||||||
<el-tooltip class="item" content="顶部菜单亮色模式" placement="bottom">
|
|
||||||
<li
|
|
||||||
:class="
|
|
||||||
dataTheme.layout === 'horizontal-light' ? $style.isSelect : ''
|
|
||||||
"
|
|
||||||
ref="horizontalLightDom"
|
|
||||||
@click="setTheme('horizontal', 'light')"
|
|
||||||
>
|
|
||||||
<div></div>
|
|
||||||
<div></div>
|
|
||||||
</li>
|
|
||||||
</el-tooltip>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<el-divider>界面显示</el-divider>
|
<el-divider>界面显示</el-divider>
|
||||||
<ul class="setting">
|
<ul class="setting">
|
||||||
<li>
|
<li>
|
||||||
<span>灰色模式</span>
|
<span>灰色模式</span>
|
||||||
<vxe-switch
|
<el-switch
|
||||||
v-model="settings.greyVal"
|
v-model="settings.greyVal"
|
||||||
open-label="开"
|
inline-prompt
|
||||||
close-label="关"
|
inactive-color="#a6a6a6"
|
||||||
|
active-text="开"
|
||||||
|
inactive-text="关"
|
||||||
@change="greyChange"
|
@change="greyChange"
|
||||||
></vxe-switch>
|
>
|
||||||
|
</el-switch>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span>色弱模式</span>
|
<span>色弱模式</span>
|
||||||
<vxe-switch
|
<el-switch
|
||||||
v-model="settings.weekVal"
|
v-model="settings.weakVal"
|
||||||
open-label="开"
|
inline-prompt
|
||||||
close-label="关"
|
inactive-color="#a6a6a6"
|
||||||
|
active-text="开"
|
||||||
|
inactive-text="关"
|
||||||
@change="weekChange"
|
@change="weekChange"
|
||||||
></vxe-switch>
|
>
|
||||||
|
</el-switch>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span>隐藏标签页</span>
|
<span>隐藏标签页</span>
|
||||||
<vxe-switch
|
<el-switch
|
||||||
v-model="settings.tagsVal"
|
v-model="settings.tabsVal"
|
||||||
open-label="开"
|
inline-prompt
|
||||||
close-label="关"
|
inactive-color="#a6a6a6"
|
||||||
|
active-text="开"
|
||||||
|
inactive-text="关"
|
||||||
@change="tagsChange"
|
@change="tagsChange"
|
||||||
></vxe-switch>
|
>
|
||||||
|
</el-switch>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span>侧边栏Logo</span>
|
<span>侧边栏Logo</span>
|
||||||
<vxe-switch
|
<el-switch
|
||||||
v-model="logoVal"
|
v-model="logoVal"
|
||||||
open-value="1"
|
inline-prompt
|
||||||
close-value="-1"
|
active-value="1"
|
||||||
open-label="开"
|
inactive-value="-1"
|
||||||
close-label="关"
|
inactive-color="#a6a6a6"
|
||||||
|
active-text="开"
|
||||||
|
inactive-text="关"
|
||||||
@change="logoChange"
|
@change="logoChange"
|
||||||
></vxe-switch>
|
>
|
||||||
|
</el-switch>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<span>标签风格</span>
|
<span>标签风格</span>
|
||||||
<vxe-radio-group v-model="markValue" @change="onChange">
|
<el-radio-group v-model="markValue" size="small" @change="onChange">
|
||||||
<vxe-radio label="card" content="卡片"></vxe-radio>
|
<el-radio label="card">卡片</el-radio>
|
||||||
<vxe-radio label="smart" content="灵动"></vxe-radio>
|
<el-radio label="smart">灵动</el-radio>
|
||||||
</vxe-radio-group>
|
</el-radio-group>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<el-divider />
|
<el-divider />
|
||||||
<vxe-button
|
<el-button
|
||||||
status="danger"
|
type="danger"
|
||||||
style="width: 90%; margin: 24px 15px"
|
style="width: 90%; margin: 24px 15px"
|
||||||
content="清空缓存并返回登录页"
|
|
||||||
icon="fa fa-sign-out"
|
|
||||||
@click="onReset"
|
@click="onReset"
|
||||||
></vxe-button>
|
>
|
||||||
|
<i class="fa fa-sign-out"></i>
|
||||||
|
清空缓存并返回登录页</el-button
|
||||||
|
>
|
||||||
</panel>
|
</panel>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -316,10 +349,10 @@ function setTheme(layout: string, theme: string) {
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-stley {
|
.pure-theme {
|
||||||
margin-top: 25px;
|
margin-top: 25px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 180px;
|
height: 100px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
@ -356,28 +389,6 @@ function setTheme(layout: string, theme: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(2) {
|
&:nth-child(2) {
|
||||||
div {
|
|
||||||
&:nth-child(1) {
|
|
||||||
width: 30%;
|
|
||||||
height: 100%;
|
|
||||||
box-shadow: 0 0 1px #888;
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 4px 0 0 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(2) {
|
|
||||||
width: 70%;
|
|
||||||
height: 30%;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 0 1px #888;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(3) {
|
|
||||||
div {
|
div {
|
||||||
&:nth-child(1) {
|
&:nth-child(1) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -387,16 +398,29 @@ function setTheme(layout: string, theme: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:nth-child(4) {
|
.theme-color {
|
||||||
div {
|
width: 100%;
|
||||||
&:nth-child(1) {
|
height: 40px;
|
||||||
width: 100%;
|
margin-top: 20px;
|
||||||
height: 30%;
|
display: flex;
|
||||||
background: #fff;
|
justify-content: center;
|
||||||
box-shadow: 0 0 1px #888;
|
|
||||||
}
|
li {
|
||||||
}
|
float: left;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-right: 8px;
|
||||||
|
font-weight: 700;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
border: 1px solid #ddd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,11 @@ const toggleClick = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="classes.container" @click="toggleClick">
|
<div
|
||||||
|
:class="classes.container"
|
||||||
|
:title="props.isActive ? '点击折叠' : '点击展开'"
|
||||||
|
@click="toggleClick"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
:class="['hamburger', props.isActive ? 'is-active' : '']"
|
:class="['hamburger', props.isActive ? 'is-active' : '']"
|
||||||
viewBox="0 0 1024 1024"
|
viewBox="0 0 1024 1024"
|
||||||
|
@ -15,6 +15,7 @@ import { algorithm } from "/@/utils/algorithm";
|
|||||||
import screenfull from "../screenfull/index.vue";
|
import screenfull from "../screenfull/index.vue";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import { storageSession } from "/@/utils/storage";
|
import { storageSession } from "/@/utils/storage";
|
||||||
|
import Icon from "/@/components/ReIcon/src/Icon.vue";
|
||||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||||
import globalization from "/@/assets/svg/globalization.svg";
|
import globalization from "/@/assets/svg/globalization.svg";
|
||||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
||||||
@ -117,7 +118,7 @@ onMounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="horizontal-header">
|
<div class="horizontal-header">
|
||||||
<div class="horizontal-header-left" @click="backHome">
|
<div class="horizontal-header-left" @click="backHome">
|
||||||
<i class="fa fa-optin-monster"></i>
|
<Icon svg :width="35" :height="35" content="team-iconlogo" />
|
||||||
<h4>{{ title }}</h4>
|
<h4>{{ title }}</h4>
|
||||||
</div>
|
</div>
|
||||||
<el-menu
|
<el-menu
|
||||||
@ -150,6 +151,8 @@ onMounted(() => {
|
|||||||
color: locale === 'zh' ? '#f4f4f5' : '#000'
|
color: locale === 'zh' ? '#f4f4f5' : '#000'
|
||||||
}"
|
}"
|
||||||
@click="translationCh"
|
@click="translationCh"
|
||||||
|
><el-icon class="check-zh" v-show="locale === 'zh'"
|
||||||
|
><check /></el-icon
|
||||||
>简体中文</el-dropdown-item
|
>简体中文</el-dropdown-item
|
||||||
>
|
>
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
@ -158,6 +161,8 @@ onMounted(() => {
|
|||||||
color: locale === 'en' ? '#f4f4f5' : '#000'
|
color: locale === 'en' ? '#f4f4f5' : '#000'
|
||||||
}"
|
}"
|
||||||
@click="translationEn"
|
@click="translationEn"
|
||||||
|
><el-icon class="check-en" v-show="locale === 'en'"
|
||||||
|
><check /></el-icon
|
||||||
>English</el-dropdown-item
|
>English</el-dropdown-item
|
||||||
>
|
>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
@ -179,11 +184,13 @@ onMounted(() => {
|
|||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
<i
|
<el-icon
|
||||||
class="el-icon-setting"
|
class="el-icon-setting"
|
||||||
:title="$t('message.hssystemSet')"
|
:title="$t('message.hssystemSet')"
|
||||||
@click="onPanel"
|
@click="onPanel"
|
||||||
></i>
|
>
|
||||||
|
<Setting />
|
||||||
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -199,6 +206,18 @@ onMounted(() => {
|
|||||||
color: #606266;
|
color: #606266;
|
||||||
background: #f0f0f0;
|
background: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.check-zh {
|
||||||
|
position: absolute;
|
||||||
|
left: 20px;
|
||||||
|
top: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-en {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 13px;
|
||||||
|
left: 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.logout {
|
.logout {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getCurrentInstance } from "vue";
|
import { getCurrentInstance } from "vue";
|
||||||
|
import Icon from "/@/components/ReIcon/src/Icon.vue";
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
collapse: Boolean
|
collapse: Boolean
|
||||||
});
|
});
|
||||||
@ -18,8 +19,8 @@ const title =
|
|||||||
class="sidebar-logo-link"
|
class="sidebar-logo-link"
|
||||||
to="/"
|
to="/"
|
||||||
>
|
>
|
||||||
<i class="fa fa-optin-monster"></i>
|
<Icon svg :width="35" :height="35" content="team-iconlogo" />
|
||||||
<h1 class="sidebar-title">{{ title }}</h1>
|
<span class="sidebar-title">{{ title }}</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
<router-link
|
<router-link
|
||||||
v-else
|
v-else
|
||||||
@ -28,8 +29,8 @@ const title =
|
|||||||
class="sidebar-logo-link"
|
class="sidebar-logo-link"
|
||||||
to="/"
|
to="/"
|
||||||
>
|
>
|
||||||
<i class="fa fa-optin-monster"></i>
|
<Icon svg :width="35" :height="35" content="team-iconlogo" />
|
||||||
<h1 class="sidebar-title">{{ title }}</h1>
|
<span class="sidebar-title">{{ title }}</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
@ -39,28 +40,24 @@ const title =
|
|||||||
.sidebar-logo-container {
|
.sidebar-logo-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 50px;
|
height: 48px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
.sidebar-logo-link {
|
.sidebar-logo-link {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
margin-top: 5px;
|
||||||
|
|
||||||
.sidebar-title {
|
.sidebar-title {
|
||||||
display: inline-block;
|
|
||||||
margin: 0;
|
|
||||||
color: #1890ff;
|
color: #1890ff;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
margin-top: 16px;
|
margin-top: 10px;
|
||||||
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
|
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fa-optin-monster {
|
|
||||||
font-size: 30px;
|
|
||||||
color: #1890ff;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapse {
|
.collapse {
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { PropType, ref } from "vue";
|
import { PropType, ref, nextTick, getCurrentInstance } from "vue";
|
||||||
import { childrenType } from "../../types";
|
import { childrenType } from "../../types";
|
||||||
|
import { useAppStoreHook } from "/@/store/modules/app";
|
||||||
import Icon from "/@/components/ReIcon/src/Icon.vue";
|
import Icon from "/@/components/ReIcon/src/Icon.vue";
|
||||||
|
|
||||||
|
const instance = getCurrentInstance().appContext.app.config.globalProperties;
|
||||||
|
const menuMode = instance.$storage.layout?.layout === "vertical";
|
||||||
|
const pureApp = useAppStoreHook();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
item: {
|
item: {
|
||||||
type: Object as PropType<childrenType>
|
type: Object as PropType<childrenType>
|
||||||
@ -19,6 +24,28 @@ const props = defineProps({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const onlyOneChild: childrenType = ref(null);
|
const onlyOneChild: childrenType = ref(null);
|
||||||
|
// 存放菜单是否存在showTooltip属性标识
|
||||||
|
const hoverMenuMap = new WeakMap();
|
||||||
|
// 存储菜单文本dom元素
|
||||||
|
const menuTextRef = ref(null);
|
||||||
|
|
||||||
|
function hoverMenu(key) {
|
||||||
|
// 如果当前菜单showTooltip属性已存在,退出计算
|
||||||
|
if (hoverMenuMap.get(key)) return;
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
// 如果文本内容的整体宽度大于其可视宽度,则文本溢出
|
||||||
|
menuTextRef.value?.scrollWidth > menuTextRef.value?.clientWidth
|
||||||
|
? Object.assign(key, {
|
||||||
|
showTooltip: true
|
||||||
|
})
|
||||||
|
: Object.assign(key, {
|
||||||
|
showTooltip: false
|
||||||
|
});
|
||||||
|
|
||||||
|
hoverMenuMap.set(key, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function hasOneShowingChild(
|
function hasOneShowingChild(
|
||||||
children: childrenType[] = [],
|
children: childrenType[] = [],
|
||||||
@ -55,19 +82,51 @@ function resolvePath(routePath) {
|
|||||||
<el-menu-item
|
<el-menu-item
|
||||||
:index="resolvePath(onlyOneChild.path)"
|
:index="resolvePath(onlyOneChild.path)"
|
||||||
:class="{ 'submenu-title-noDropdown': !isNest }"
|
:class="{ 'submenu-title-noDropdown': !isNest }"
|
||||||
|
style="display: flex; align-items: center"
|
||||||
>
|
>
|
||||||
<i
|
<el-icon v-show="props.item.meta.icon">
|
||||||
:class="
|
<component
|
||||||
onlyOneChild.meta.icon || (props.item.meta && props.item.meta.icon)
|
:is="
|
||||||
"
|
onlyOneChild.meta.icon || (props.item.meta && props.item.meta.icon)
|
||||||
/>
|
"
|
||||||
|
></component>
|
||||||
|
</el-icon>
|
||||||
<template #title>
|
<template #title>
|
||||||
<span>{{ $t(onlyOneChild.meta.title) }}</span>
|
<div
|
||||||
<Icon
|
:style="{
|
||||||
v-if="onlyOneChild.meta.extraIcon"
|
width: pureApp.sidebar.opened ? '' : '100%',
|
||||||
:svg="onlyOneChild.meta.extraIcon.svg ? true : false"
|
display: 'flex',
|
||||||
:content="`${onlyOneChild.meta.extraIcon.name}`"
|
alignItems: 'center',
|
||||||
/>
|
justifyContent: 'space-between',
|
||||||
|
overflow: 'hidden'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<span v-if="!menuMode">{{ $t(onlyOneChild.meta.title) }}</span>
|
||||||
|
<el-tooltip
|
||||||
|
v-else
|
||||||
|
placement="top"
|
||||||
|
:offset="-10"
|
||||||
|
:disabled="!onlyOneChild.showTooltip"
|
||||||
|
>
|
||||||
|
<template #content> {{ $t(onlyOneChild.meta.title) }} </template>
|
||||||
|
<span
|
||||||
|
ref="menuTextRef"
|
||||||
|
:style="{
|
||||||
|
width: pureApp.sidebar.opened ? '125px' : '',
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis'
|
||||||
|
}"
|
||||||
|
@mouseover="hoverMenu(onlyOneChild)"
|
||||||
|
>
|
||||||
|
{{ $t(onlyOneChild.meta.title) }}
|
||||||
|
</span>
|
||||||
|
</el-tooltip>
|
||||||
|
<Icon
|
||||||
|
v-if="onlyOneChild.meta.extraIcon"
|
||||||
|
:svg="onlyOneChild.meta.extraIcon.svg ? true : false"
|
||||||
|
:content="`${onlyOneChild.meta.extraIcon.name}`"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</template>
|
</template>
|
||||||
@ -79,8 +138,32 @@ function resolvePath(routePath) {
|
|||||||
popper-append-to-body
|
popper-append-to-body
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
<i :class="props.item.meta.icon"></i>
|
<el-icon v-show="props.item.meta.icon" :class="props.item.meta.icon">
|
||||||
<span>{{ $t(props.item.meta.title) }}</span>
|
<component :is="props.item.meta && props.item.meta.icon"></component>
|
||||||
|
</el-icon>
|
||||||
|
<span v-if="!menuMode">{{ $t(props.item.meta.title) }}</span>
|
||||||
|
<el-tooltip
|
||||||
|
v-else
|
||||||
|
placement="top"
|
||||||
|
:offset="-10"
|
||||||
|
:disabled="!pureApp.sidebar.opened || !props.item.showTooltip"
|
||||||
|
>
|
||||||
|
<template #content> {{ $t(props.item.meta.title) }} </template>
|
||||||
|
<div
|
||||||
|
ref="menuTextRef"
|
||||||
|
:style="{
|
||||||
|
width: pureApp.sidebar.opened ? '125px' : '',
|
||||||
|
display: 'inline-block',
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis'
|
||||||
|
}"
|
||||||
|
@mouseover="hoverMenu(props.item)"
|
||||||
|
>
|
||||||
|
<span style="overflow: hidden; text-overflow: ellipsis">
|
||||||
|
{{ $t(props.item.meta.title) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</el-tooltip>
|
||||||
<Icon
|
<Icon
|
||||||
v-if="props.item.meta.extraIcon"
|
v-if="props.item.meta.extraIcon"
|
||||||
:svg="props.item.meta.extraIcon.svg ? true : false"
|
:svg="props.item.meta.extraIcon.svg ? true : false"
|
||||||
|
@ -68,12 +68,14 @@ onBeforeMount(() => {
|
|||||||
router
|
router
|
||||||
:collapse-transition="false"
|
:collapse-transition="false"
|
||||||
mode="vertical"
|
mode="vertical"
|
||||||
|
class="outer-most"
|
||||||
@select="menuSelect"
|
@select="menuSelect"
|
||||||
>
|
>
|
||||||
<sidebar-item
|
<sidebar-item
|
||||||
v-for="route in routeStore.wholeRoutes"
|
v-for="route in routeStore.wholeRoutes"
|
||||||
:key="route.path"
|
:key="route.path"
|
||||||
:item="route"
|
:item="route"
|
||||||
|
class="outer-most"
|
||||||
:base-path="route.path"
|
:base-path="route.path"
|
||||||
/>
|
/>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
|
@ -280,6 +280,7 @@ function onClickDrop(key, item, selectRoute?: RouteConfigs) {
|
|||||||
relativeStorage.routesInStorage = routerArrays;
|
relativeStorage.routesInStorage = routerArrays;
|
||||||
usePermissionStoreHook().clearAllCachePage();
|
usePermissionStoreHook().clearAllCachePage();
|
||||||
router.push("/welcome");
|
router.push("/welcome");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -482,14 +483,16 @@ onBeforeMount(() => {
|
|||||||
<router-link :to="item.path" @click="tagOnClick(item)">{{
|
<router-link :to="item.path" @click="tagOnClick(item)">{{
|
||||||
$t(item.meta.title)
|
$t(item.meta.title)
|
||||||
}}</router-link>
|
}}</router-link>
|
||||||
<span
|
<el-icon
|
||||||
v-if="
|
v-if="
|
||||||
($route.path === item.path && index !== 0) ||
|
($route.path === item.path && index !== 0) ||
|
||||||
(index === activeIndex && index !== 0)
|
(index === activeIndex && index !== 0)
|
||||||
"
|
"
|
||||||
class="el-icon-close"
|
class="el-icon-close"
|
||||||
@click="deleteMenu(item)"
|
@click="deleteMenu(item)"
|
||||||
></span>
|
>
|
||||||
|
<CloseBold />
|
||||||
|
</el-icon>
|
||||||
<div
|
<div
|
||||||
:ref="'schedule' + index"
|
:ref="'schedule' + index"
|
||||||
v-if="showModel !== 'card'"
|
v-if="showModel !== 'card'"
|
||||||
@ -520,15 +523,19 @@ onBeforeMount(() => {
|
|||||||
<!-- 右侧功能按钮 -->
|
<!-- 右侧功能按钮 -->
|
||||||
<ul class="right-button">
|
<ul class="right-button">
|
||||||
<li>
|
<li>
|
||||||
<i
|
<el-icon
|
||||||
:title="$t('message.hsrefreshRoute')"
|
:title="$t('message.hsrefreshRoute')"
|
||||||
class="el-icon-refresh-right rotate"
|
class="el-icon-refresh-right rotate"
|
||||||
@click="onFresh"
|
@click="onFresh"
|
||||||
></i>
|
>
|
||||||
|
<RefreshRight />
|
||||||
|
</el-icon>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<el-dropdown trigger="click" placement="bottom-end">
|
<el-dropdown trigger="click" placement="bottom-end">
|
||||||
<i class="el-icon-arrow-down"></i>
|
<el-icon>
|
||||||
|
<ArrowDown />
|
||||||
|
</el-icon>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
@ -628,6 +635,7 @@ onBeforeMount(() => {
|
|||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
color: #1890ff;
|
color: #1890ff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transform: fontsize3s;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
@ -1,32 +1,6 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { routerArrays } from "./types";
|
|
||||||
export default {
|
|
||||||
computed: {
|
|
||||||
layout() {
|
|
||||||
if (!this.$storage.layout) {
|
|
||||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
|
||||||
this.$storage.layout = { layout: "vertical-dark" };
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
!this.$storage.routesInStorage ||
|
|
||||||
this.$storage.routesInStorage.length === 0
|
|
||||||
) {
|
|
||||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
|
||||||
this.$storage.routesInStorage = routerArrays;
|
|
||||||
}
|
|
||||||
if (!this.$storage.locale) {
|
|
||||||
// eslint-disable-next-line
|
|
||||||
this.$storage.locale = { locale: "zh" };
|
|
||||||
useI18n().locale.value = "zh";
|
|
||||||
}
|
|
||||||
return this.$storage?.layout.layout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
|
h,
|
||||||
ref,
|
ref,
|
||||||
unref,
|
unref,
|
||||||
reactive,
|
reactive,
|
||||||
@ -34,13 +8,15 @@ import {
|
|||||||
onMounted,
|
onMounted,
|
||||||
watchEffect,
|
watchEffect,
|
||||||
onBeforeMount,
|
onBeforeMount,
|
||||||
|
defineComponent,
|
||||||
getCurrentInstance
|
getCurrentInstance
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import { setType } from "./types";
|
import { setType } from "./types";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { routerArrays } from "./types";
|
||||||
import { emitter } from "/@/utils/mitt";
|
import { emitter } from "/@/utils/mitt";
|
||||||
import { useEventListener } from "@vueuse/core";
|
import { useEventListener } from "@vueuse/core";
|
||||||
import { storageLocal } from "/@/utils/storage";
|
import backTop from "/@/assets/svg/back_top.svg";
|
||||||
import { useAppStoreHook } from "/@/store/modules/app";
|
import { useAppStoreHook } from "/@/store/modules/app";
|
||||||
import fullScreen from "/@/assets/svg/full_screen.svg";
|
import fullScreen from "/@/assets/svg/full_screen.svg";
|
||||||
import exitScreen from "/@/assets/svg/exit_screen.svg";
|
import exitScreen from "/@/assets/svg/exit_screen.svg";
|
||||||
@ -53,14 +29,45 @@ import setting from "./components/setting/index.vue";
|
|||||||
import Vertical from "./components/sidebar/vertical.vue";
|
import Vertical from "./components/sidebar/vertical.vue";
|
||||||
import Horizontal from "./components/sidebar/horizontal.vue";
|
import Horizontal from "./components/sidebar/horizontal.vue";
|
||||||
|
|
||||||
|
const instance = getCurrentInstance().appContext.app.config.globalProperties;
|
||||||
|
const hiddenSideBar = ref(instance.$config?.HiddenSideBar);
|
||||||
const pureSetting = useSettingStoreHook();
|
const pureSetting = useSettingStoreHook();
|
||||||
|
|
||||||
const instance =
|
// 清空缓存后从serverConfig.json读取默认配置并赋值到storage中
|
||||||
getCurrentInstance().appContext.app.config.globalProperties.$storage;
|
const layout = computed(() => {
|
||||||
|
// 路由
|
||||||
const hiddenSideBar = ref(
|
if (
|
||||||
getCurrentInstance().appContext.config.globalProperties.$config?.HiddenSideBar
|
!instance.$storage.routesInStorage ||
|
||||||
);
|
instance.$storage.routesInStorage.length === 0
|
||||||
|
) {
|
||||||
|
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||||
|
instance.$storage.routesInStorage = routerArrays;
|
||||||
|
}
|
||||||
|
// 国际化
|
||||||
|
if (!instance.$storage.locale) {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
instance.$storage.locale = { locale: instance.$config?.Locale ?? "zh" };
|
||||||
|
useI18n().locale.value = instance.$config?.Locale ?? "zh";
|
||||||
|
}
|
||||||
|
// 导航
|
||||||
|
if (!instance.$storage.layout) {
|
||||||
|
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||||
|
instance.$storage.layout = {
|
||||||
|
layout: instance.$config?.Layout ?? "vertical",
|
||||||
|
theme: instance.$config?.Theme ?? "default"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 灰色模式、色弱模式、隐藏标签页
|
||||||
|
if (!instance.$storage.sets) {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
instance.$storage.sets = {
|
||||||
|
grey: instance.$config?.Grey ?? false,
|
||||||
|
weak: instance.$config?.Weak ?? false,
|
||||||
|
hideTabs: instance.$config?.HideTabs ?? false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return instance.$storage?.layout.layout;
|
||||||
|
});
|
||||||
|
|
||||||
const set: setType = reactive({
|
const set: setType = reactive({
|
||||||
sidebar: computed(() => {
|
sidebar: computed(() => {
|
||||||
@ -82,6 +89,10 @@ const set: setType = reactive({
|
|||||||
withoutAnimation: set.sidebar.withoutAnimation,
|
withoutAnimation: set.sidebar.withoutAnimation,
|
||||||
mobile: set.device === "mobile"
|
mobile: set.device === "mobile"
|
||||||
};
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
hideTabs: computed(() => {
|
||||||
|
return instance.$storage?.sets.hideTabs;
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -90,11 +101,11 @@ const handleClickOutside = (params: boolean) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function setTheme(layoutModel: string) {
|
function setTheme(layoutModel: string) {
|
||||||
let { layout } = storageLocal.getItem("responsive-layout");
|
window.document.body.setAttribute("layout", layoutModel);
|
||||||
let theme = layout.match(/-(.*)/)[1];
|
instance.$storage.layout = {
|
||||||
window.document.body.setAttribute("data-layout", layoutModel);
|
layout: `${layoutModel}`,
|
||||||
window.document.body.setAttribute("data-theme", theme);
|
theme: instance.$storage.layout?.theme
|
||||||
instance.layout = { layout: `${layoutModel}-${theme}` };
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听容器
|
// 监听容器
|
||||||
@ -141,6 +152,49 @@ onMounted(() => {
|
|||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
useEventListener("resize", $_resizeHandler);
|
useEventListener("resize", $_resizeHandler);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const layoutHeader = defineComponent({
|
||||||
|
render() {
|
||||||
|
return h(
|
||||||
|
"div",
|
||||||
|
{
|
||||||
|
class: { "fixed-header": set.fixedHeader },
|
||||||
|
style: [
|
||||||
|
set.hideTabs && layout.value.includes("horizontal")
|
||||||
|
? "box-shadow: 0 1px 4px rgb(0 21 41 / 8%);"
|
||||||
|
: ""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => [
|
||||||
|
!hiddenSideBar.value && layout.value.includes("vertical")
|
||||||
|
? h(navbar)
|
||||||
|
: h("div"),
|
||||||
|
!hiddenSideBar.value && layout.value.includes("horizontal")
|
||||||
|
? h(Horizontal)
|
||||||
|
: h("div"),
|
||||||
|
h(
|
||||||
|
tag,
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
default: () => [
|
||||||
|
h(
|
||||||
|
"span",
|
||||||
|
{ onClick: onFullScreen },
|
||||||
|
{
|
||||||
|
default: () => [
|
||||||
|
!hiddenSideBar.value ? h(fullScreen) : h(exitScreen)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -156,20 +210,21 @@ onBeforeMount(() => {
|
|||||||
/>
|
/>
|
||||||
<Vertical v-show="!hiddenSideBar && layout.includes('vertical')" />
|
<Vertical v-show="!hiddenSideBar && layout.includes('vertical')" />
|
||||||
<div :class="['main-container', hiddenSideBar ? 'main-hidden' : '']">
|
<div :class="['main-container', hiddenSideBar ? 'main-hidden' : '']">
|
||||||
<div :class="{ 'fixed-header': set.fixedHeader }">
|
<div v-if="set.fixedHeader">
|
||||||
<!-- 顶部导航栏 -->
|
<layout-header />
|
||||||
<navbar v-show="!hiddenSideBar && layout.includes('vertical')" />
|
<!-- 主体内容 -->
|
||||||
<!-- tabs标签页 -->
|
<app-main :fixed-header="set.fixedHeader" />
|
||||||
<Horizontal v-show="!hiddenSideBar && layout.includes('horizontal')" />
|
|
||||||
<tag>
|
|
||||||
<span @click="onFullScreen">
|
|
||||||
<fullScreen v-if="!hiddenSideBar" />
|
|
||||||
<exitScreen v-else />
|
|
||||||
</span>
|
|
||||||
</tag>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- 主体内容 -->
|
<el-scrollbar v-else>
|
||||||
<app-main />
|
<el-backtop
|
||||||
|
title="回到顶部"
|
||||||
|
target=".main-container .el-scrollbar__wrap"
|
||||||
|
><backTop />
|
||||||
|
</el-backtop>
|
||||||
|
<layout-header />
|
||||||
|
<!-- 主体内容 -->
|
||||||
|
<app-main :fixed-header="set.fixedHeader" />
|
||||||
|
</el-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
<!-- 系统设置 -->
|
<!-- 系统设置 -->
|
||||||
<setting />
|
<setting />
|
||||||
|
12
src/layout/theme/auroraGreen-vars.scss
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 极光绿
|
||||||
|
|
||||||
|
$subMenuActiveText: #fff;
|
||||||
|
$menuBg: #0b1e15;
|
||||||
|
$menuHover: #60ac80;
|
||||||
|
$subMenuBg: #000;
|
||||||
|
$subMenuActiveBg: #60ac80;
|
||||||
|
$navTextColor: #7a80b4;
|
||||||
|
$menuText: #7a80b4;
|
||||||
|
$sidebarLogo: #112f21;
|
||||||
|
$menuTitleHover: #fff;
|
||||||
|
$menuActiveBefore: #60ac80;
|
24
src/layout/theme/default-vars.scss
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
*此scss变量文件作为multipleScopeVars去编译时,会自动移除!default以达到变量提升
|
||||||
|
*同时此scss变量文件作为默认主题变量文件,被其他.scss通过 @import 时,必需 !default
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 暗雅(默认)
|
||||||
|
|
||||||
|
// 菜单选中后字体样式
|
||||||
|
$subMenuActiveText: #fff !default;
|
||||||
|
//菜单背景
|
||||||
|
$menuBg: #001529 !default;
|
||||||
|
// 鼠标覆盖到菜单时的背景
|
||||||
|
$menuHover: #4091f7 !default;
|
||||||
|
// 子菜单背景
|
||||||
|
$subMenuBg: #0f0303 !default;
|
||||||
|
// 有无子集的激活菜单背景
|
||||||
|
$subMenuActiveBg: #4091f7 !default;
|
||||||
|
$navTextColor: #fff !default;
|
||||||
|
$menuText: rgba(254, 254, 254, 0.65) !default;
|
||||||
|
// logo背景颜色
|
||||||
|
$sidebarLogo: #002140 !default;
|
||||||
|
// 鼠标覆盖到菜单时的字体颜色
|
||||||
|
$menuTitleHover: #fff !default;
|
||||||
|
$menuActiveBefore: #4091f7 !default;
|
12
src/layout/theme/dusk-vars.scss
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 薄暮
|
||||||
|
|
||||||
|
$subMenuActiveText: #fff;
|
||||||
|
$menuBg: #2a0608;
|
||||||
|
$menuHover: #e13c39;
|
||||||
|
$subMenuBg: #000;
|
||||||
|
$subMenuActiveBg: #e13c39;
|
||||||
|
$navTextColor: red;
|
||||||
|
$menuText: rgba(254, 254, 254, 0.651);
|
||||||
|
$sidebarLogo: #42090c;
|
||||||
|
$menuTitleHover: #fff;
|
||||||
|
$menuActiveBefore: #e13c39;
|
11
src/layout/theme/light-vars.scss
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// 明亮
|
||||||
|
$subMenuActiveText: #409eff;
|
||||||
|
$menuBg: #fff;
|
||||||
|
$menuHover: #e0ebf6;
|
||||||
|
$subMenuBg: #fff;
|
||||||
|
$subMenuActiveBg: #e0ebf6;
|
||||||
|
$navTextColor: #7a80b4;
|
||||||
|
$menuText: #7a80b4;
|
||||||
|
$sidebarLogo: #fff;
|
||||||
|
$menuTitleHover: #000;
|
||||||
|
$menuActiveBefore: #4091f7;
|
12
src/layout/theme/mingQing-vars.scss
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 明青
|
||||||
|
|
||||||
|
$subMenuActiveText: #fff;
|
||||||
|
$menuBg: #032121;
|
||||||
|
$menuHover: #59bfc1;
|
||||||
|
$subMenuBg: #000;
|
||||||
|
$subMenuActiveBg: #59bfc1;
|
||||||
|
$navTextColor: #7a80b4;
|
||||||
|
$menuText: #7a80b4;
|
||||||
|
$sidebarLogo: #053434;
|
||||||
|
$menuTitleHover: #fff;
|
||||||
|
$menuActiveBefore: #59bfc1;
|
12
src/layout/theme/pink-vars.scss
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 粉红
|
||||||
|
|
||||||
|
$subMenuActiveText: #fff;
|
||||||
|
$menuBg: #28081a;
|
||||||
|
$menuHover: #d84493;
|
||||||
|
$subMenuBg: #000;
|
||||||
|
$subMenuActiveBg: #d84493;
|
||||||
|
$navTextColor: #7a80b4;
|
||||||
|
$menuText: #7a80b4;
|
||||||
|
$sidebarLogo: #3f0d29;
|
||||||
|
$menuTitleHover: #fff;
|
||||||
|
$menuActiveBefore: #d84493;
|
12
src/layout/theme/saucePurple-vars.scss
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 酱紫
|
||||||
|
|
||||||
|
$subMenuActiveText: #fff;
|
||||||
|
$menuBg: #130824;
|
||||||
|
$menuHover: #693ac9;
|
||||||
|
$subMenuBg: #000;
|
||||||
|
$subMenuActiveBg: #693ac9;
|
||||||
|
$navTextColor: #7a80b4;
|
||||||
|
$menuText: #7a80b4;
|
||||||
|
$sidebarLogo: #1f0c38;
|
||||||
|
$menuTitleHover: #fff;
|
||||||
|
$menuActiveBefore: #693ac9;
|
12
src/layout/theme/volcano-vars.scss
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 火山
|
||||||
|
|
||||||
|
$subMenuActiveText: #fff;
|
||||||
|
$menuBg: #2b0e05;
|
||||||
|
$menuHover: #e85f33;
|
||||||
|
$subMenuBg: #0f0603;
|
||||||
|
$subMenuActiveBg: #e85f33;
|
||||||
|
$navTextColor: #fff;
|
||||||
|
$menuText: rgba(254, 254, 254, 0.65);
|
||||||
|
$sidebarLogo: #441708;
|
||||||
|
$menuTitleHover: #fff;
|
||||||
|
$menuActiveBefore: #e85f33;
|
12
src/layout/theme/yellow-vars.scss
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 黄色
|
||||||
|
|
||||||
|
$subMenuActiveText: #d25f00;
|
||||||
|
$menuBg: #2b2503;
|
||||||
|
$menuHover: #f6da4d;
|
||||||
|
$subMenuBg: #0f0603;
|
||||||
|
$subMenuActiveBg: #f6da4d;
|
||||||
|
$navTextColor: #fff;
|
||||||
|
$menuText: rgba(254, 254, 254, 0.65);
|
||||||
|
$sidebarLogo: #443b05;
|
||||||
|
$menuTitleHover: #fff;
|
||||||
|
$menuActiveBefore: #f6da4d;
|
@ -47,6 +47,7 @@ export interface setType {
|
|||||||
withoutAnimation: boolean;
|
withoutAnimation: boolean;
|
||||||
mobile: boolean;
|
mobile: boolean;
|
||||||
};
|
};
|
||||||
|
hideTabs: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type childrenType = {
|
export type childrenType = {
|
||||||
@ -62,4 +63,10 @@ export type childrenType = {
|
|||||||
name?: string;
|
name?: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
showTooltip?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type themeColorsType = {
|
||||||
|
rgb: string;
|
||||||
|
themeColor: string;
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@ import { setupStore } from "/@/store";
|
|||||||
import { getServerConfig } from "./config";
|
import { getServerConfig } from "./config";
|
||||||
import { createApp, Directive } from "vue";
|
import { createApp, Directive } from "vue";
|
||||||
import { usI18n } from "../src/plugins/i18n";
|
import { usI18n } from "../src/plugins/i18n";
|
||||||
import { useTable } from "../src/plugins/vxe-table";
|
import { MotionPlugin } from "@vueuse/motion";
|
||||||
import { useElementPlus } from "../src/plugins/element-plus";
|
import { useElementPlus } from "../src/plugins/element-plus";
|
||||||
import { injectResponsiveStorage } from "/@/utils/storage/responsive";
|
import { injectResponsiveStorage } from "/@/utils/storage/responsive";
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ Object.keys(directives).forEach(key => {
|
|||||||
getServerConfig(app).then(async config => {
|
getServerConfig(app).then(async config => {
|
||||||
injectResponsiveStorage(app, config);
|
injectResponsiveStorage(app, config);
|
||||||
setupStore(app);
|
setupStore(app);
|
||||||
app.use(router).use(useElementPlus).use(useTable).use(usI18n);
|
app.use(router).use(MotionPlugin).use(useElementPlus).use(usI18n);
|
||||||
await router.isReady();
|
await router.isReady();
|
||||||
app.mount("#app");
|
app.mount("#app");
|
||||||
});
|
});
|
||||||
|
@ -30,12 +30,33 @@ import {
|
|||||||
ElDrawer,
|
ElDrawer,
|
||||||
ElPagination,
|
ElPagination,
|
||||||
ElAlert,
|
ElAlert,
|
||||||
|
ElRadio,
|
||||||
ElRadioButton,
|
ElRadioButton,
|
||||||
ElRadioGroup,
|
ElRadioGroup,
|
||||||
ElDescriptions,
|
ElDescriptions,
|
||||||
ElDescriptionsItem
|
ElDescriptionsItem,
|
||||||
|
ElBacktop,
|
||||||
|
ElSwitch
|
||||||
} from "element-plus";
|
} from "element-plus";
|
||||||
|
|
||||||
|
// https://element-plus.org/zh-CN/component/icon.html
|
||||||
|
import {
|
||||||
|
Check,
|
||||||
|
Menu,
|
||||||
|
HomeFilled,
|
||||||
|
SetUp,
|
||||||
|
Edit,
|
||||||
|
Setting,
|
||||||
|
Lollipop,
|
||||||
|
Link,
|
||||||
|
Position,
|
||||||
|
Histogram,
|
||||||
|
RefreshRight,
|
||||||
|
ArrowDown,
|
||||||
|
Close,
|
||||||
|
CloseBold
|
||||||
|
} from "@element-plus/icons";
|
||||||
|
|
||||||
const components = [
|
const components = [
|
||||||
ElTag,
|
ElTag,
|
||||||
ElAffix,
|
ElAffix,
|
||||||
@ -66,10 +87,29 @@ const components = [
|
|||||||
ElDrawer,
|
ElDrawer,
|
||||||
ElPagination,
|
ElPagination,
|
||||||
ElAlert,
|
ElAlert,
|
||||||
|
ElRadio,
|
||||||
ElRadioButton,
|
ElRadioButton,
|
||||||
ElRadioGroup,
|
ElRadioGroup,
|
||||||
ElDescriptions,
|
ElDescriptions,
|
||||||
ElDescriptionsItem
|
ElDescriptionsItem,
|
||||||
|
ElBacktop,
|
||||||
|
ElSwitch,
|
||||||
|
|
||||||
|
// icon
|
||||||
|
Check,
|
||||||
|
Menu,
|
||||||
|
HomeFilled,
|
||||||
|
SetUp,
|
||||||
|
Edit,
|
||||||
|
Setting,
|
||||||
|
Lollipop,
|
||||||
|
Link,
|
||||||
|
Position,
|
||||||
|
Histogram,
|
||||||
|
RefreshRight,
|
||||||
|
ArrowDown,
|
||||||
|
Close,
|
||||||
|
CloseBold
|
||||||
];
|
];
|
||||||
|
|
||||||
const plugins = [ElLoading];
|
const plugins = [ElLoading];
|
||||||
|
@ -2,39 +2,14 @@
|
|||||||
import enLocale from "element-plus/lib/locale/lang/en";
|
import enLocale from "element-plus/lib/locale/lang/en";
|
||||||
import zhLocale from "element-plus/lib/locale/lang/zh-cn";
|
import zhLocale from "element-plus/lib/locale/lang/zh-cn";
|
||||||
|
|
||||||
// 导航菜单配置
|
|
||||||
// 导航菜单配置
|
// 导航菜单配置
|
||||||
export const menusConfig = {
|
export const menusConfig = {
|
||||||
zh: {
|
zh: {
|
||||||
message: {
|
message: {
|
||||||
hshome: "首页",
|
hshome: "首页",
|
||||||
hssysManagement: "系统管理",
|
|
||||||
hsBaseinfo: "基础信息",
|
|
||||||
hsDict: "字典管理",
|
|
||||||
hseditor: "编辑器",
|
|
||||||
hserror: "错误页面",
|
hserror: "错误页面",
|
||||||
hsfourZeroFour: "404",
|
hsfourZeroFour: "404",
|
||||||
hsfourZeroOne: "401",
|
hsfourZeroOne: "401",
|
||||||
hscomponents: "组件",
|
|
||||||
hsvideo: "视频组件",
|
|
||||||
hsmap: "地图组件",
|
|
||||||
hsdraggable: "拖拽组件",
|
|
||||||
hssplitPane: "切割面板",
|
|
||||||
hsbutton: "按钮组件",
|
|
||||||
hscropping: "图片裁剪",
|
|
||||||
hscountTo: "数字动画",
|
|
||||||
hsselector: "选择器组件",
|
|
||||||
hsflowChart: "流程图",
|
|
||||||
hsseamless: "无缝滚动",
|
|
||||||
hscontextmenu: "右键菜单",
|
|
||||||
hsmenus: "多级菜单",
|
|
||||||
hsmenu1: "菜单1",
|
|
||||||
"hsmenu1-1": "菜单1-1",
|
|
||||||
"hsmenu1-2": "菜单1-2",
|
|
||||||
"hsmenu1-2-1": "菜单1-2-1",
|
|
||||||
"hsmenu1-2-2": "菜单1-2-2",
|
|
||||||
"hsmenu1-3": "菜单1-3",
|
|
||||||
hsmenu2: "菜单2",
|
|
||||||
permission: "权限管理",
|
permission: "权限管理",
|
||||||
permissionPage: "页面权限",
|
permissionPage: "页面权限",
|
||||||
permissionButton: "按钮权限",
|
permissionButton: "按钮权限",
|
||||||
@ -44,33 +19,9 @@ export const menusConfig = {
|
|||||||
en: {
|
en: {
|
||||||
message: {
|
message: {
|
||||||
hshome: "Home",
|
hshome: "Home",
|
||||||
hssysManagement: "System Manage",
|
|
||||||
hsBaseinfo: "Base Info",
|
|
||||||
hsDict: "Dict Manage",
|
|
||||||
hseditor: "Editor",
|
|
||||||
hserror: "Error Page",
|
hserror: "Error Page",
|
||||||
hsfourZeroFour: "404",
|
hsfourZeroFour: "404",
|
||||||
hsfourZeroOne: "401",
|
hsfourZeroOne: "401",
|
||||||
hscomponents: "Components",
|
|
||||||
hsvideo: "Video Components",
|
|
||||||
hsmap: "Map Components",
|
|
||||||
hsdraggable: "Draggable Components",
|
|
||||||
hssplitPane: "Split Pane",
|
|
||||||
hsbutton: "Button Components",
|
|
||||||
hscropping: "Picture Cropping",
|
|
||||||
hscountTo: "Digital Animation",
|
|
||||||
hsselector: "Selector Components",
|
|
||||||
hsflowChart: "Flow Chart",
|
|
||||||
hsseamless: "Seamless Scroll",
|
|
||||||
hscontextmenu: "Context Menu",
|
|
||||||
hsmenus: "MultiLevel Menu",
|
|
||||||
hsmenu1: "Menu1",
|
|
||||||
"hsmenu1-1": "Menu1-1",
|
|
||||||
"hsmenu1-2": "Menu1-2",
|
|
||||||
"hsmenu1-2-1": "Menu1-2-1",
|
|
||||||
"hsmenu1-2-2": "Menu1-2-2",
|
|
||||||
"hsmenu1-3": "Menu1-3",
|
|
||||||
hsmenu2: "Menu2",
|
|
||||||
permission: "Permission Manage",
|
permission: "Permission Manage",
|
||||||
permissionPage: "Page Permission",
|
permissionPage: "Page Permission",
|
||||||
permissionButton: "Button Permission",
|
permissionButton: "Button Permission",
|
||||||
@ -88,10 +39,14 @@ export const buttonConfig = {
|
|||||||
hsexitfullscreen: "退出全屏",
|
hsexitfullscreen: "退出全屏",
|
||||||
hsrefreshRoute: "刷新路由",
|
hsrefreshRoute: "刷新路由",
|
||||||
hslogin: "登陆",
|
hslogin: "登陆",
|
||||||
hsregister: "注册",
|
hsadd: "新增",
|
||||||
|
hsmark: "标记/取消",
|
||||||
|
hssave: "保存",
|
||||||
|
hssearch: "搜索",
|
||||||
hsexpendAll: "全部展开",
|
hsexpendAll: "全部展开",
|
||||||
hscollapseAll: "全部折叠",
|
hscollapseAll: "全部折叠",
|
||||||
hssystemSet: "系统设置",
|
hssystemSet: "打开项目配置",
|
||||||
|
hsdelete: "删除",
|
||||||
hsreload: "重新加载",
|
hsreload: "重新加载",
|
||||||
hscloseCurrentTab: "关闭当前标签页",
|
hscloseCurrentTab: "关闭当前标签页",
|
||||||
hscloseLeftTabs: "关闭左侧标签页",
|
hscloseLeftTabs: "关闭左侧标签页",
|
||||||
@ -107,10 +62,14 @@ export const buttonConfig = {
|
|||||||
hsexitfullscreen: "exitFullscreen",
|
hsexitfullscreen: "exitFullscreen",
|
||||||
hsrefreshRoute: "refreshRoute",
|
hsrefreshRoute: "refreshRoute",
|
||||||
hslogin: "login",
|
hslogin: "login",
|
||||||
hsregister: "register",
|
hsadd: "Add",
|
||||||
|
hsmark: "Mark/Cancel",
|
||||||
|
hssave: "Save",
|
||||||
|
hssearch: "Search",
|
||||||
hsexpendAll: "Expand All",
|
hsexpendAll: "Expand All",
|
||||||
hscollapseAll: "Collapse All",
|
hscollapseAll: "Collapse All",
|
||||||
hssystemSet: "System Set",
|
hssystemSet: "Open ProjectConfig",
|
||||||
|
hsdelete: "Delete",
|
||||||
hsreload: "Reload",
|
hsreload: "Reload",
|
||||||
hscloseCurrentTab: "Close CurrentTab",
|
hscloseCurrentTab: "Close CurrentTab",
|
||||||
hscloseLeftTabs: "Close LeftTabs",
|
hscloseLeftTabs: "Close LeftTabs",
|
||||||
@ -121,6 +80,16 @@ export const buttonConfig = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 配置
|
||||||
|
// export const xxxx = {
|
||||||
|
// zh: {
|
||||||
|
// message: {},
|
||||||
|
// },
|
||||||
|
// en: {
|
||||||
|
// message: {},
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
const localesList = [menusConfig, buttonConfig];
|
const localesList = [menusConfig, buttonConfig];
|
||||||
|
|
||||||
export const localesConfigs = {
|
export const localesConfigs = {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// 多组件库的国际化和本地项目国际化兼容
|
||||||
import { App } from "vue";
|
import { App } from "vue";
|
||||||
import { createI18n } from "vue-i18n";
|
import { createI18n } from "vue-i18n";
|
||||||
import { localesConfigs } from "./config";
|
import { localesConfigs } from "./config";
|
||||||
|
@ -1,119 +0,0 @@
|
|||||||
import "xe-utils";
|
|
||||||
import { App } from "vue";
|
|
||||||
import { i18n } from "../i18n/index";
|
|
||||||
import "font-awesome/css/font-awesome.css";
|
|
||||||
import {
|
|
||||||
// 核心
|
|
||||||
VXETable,
|
|
||||||
|
|
||||||
// 表格功能
|
|
||||||
Header,
|
|
||||||
Footer,
|
|
||||||
Icon,
|
|
||||||
Filter,
|
|
||||||
Edit,
|
|
||||||
Menu,
|
|
||||||
Export,
|
|
||||||
Keyboard,
|
|
||||||
Validator,
|
|
||||||
|
|
||||||
// 可选组件
|
|
||||||
Column,
|
|
||||||
Colgroup,
|
|
||||||
Grid,
|
|
||||||
Tooltip,
|
|
||||||
Toolbar,
|
|
||||||
Pager,
|
|
||||||
Form,
|
|
||||||
FormItem,
|
|
||||||
FormGather,
|
|
||||||
Checkbox,
|
|
||||||
CheckboxGroup,
|
|
||||||
Radio,
|
|
||||||
RadioGroup,
|
|
||||||
RadioButton,
|
|
||||||
Switch,
|
|
||||||
Input,
|
|
||||||
Select,
|
|
||||||
Optgroup,
|
|
||||||
Option,
|
|
||||||
Textarea,
|
|
||||||
Button,
|
|
||||||
Modal,
|
|
||||||
List,
|
|
||||||
Pulldown,
|
|
||||||
|
|
||||||
// 表格
|
|
||||||
Table
|
|
||||||
} from "vxe-table";
|
|
||||||
|
|
||||||
// 全局默认参数
|
|
||||||
VXETable.setup({
|
|
||||||
size: "medium",
|
|
||||||
version: 0,
|
|
||||||
zIndex: 1002,
|
|
||||||
table: {
|
|
||||||
// 自动监听父元素的变化去重新计算表格
|
|
||||||
autoResize: true,
|
|
||||||
// 鼠标移到行是否要高亮显示
|
|
||||||
highlightHoverRow: true
|
|
||||||
},
|
|
||||||
input: {
|
|
||||||
clearable: true
|
|
||||||
},
|
|
||||||
// 对组件内置的提示语进行国际化翻译
|
|
||||||
// @ts-ignore
|
|
||||||
i18n: (key, args) => i18n.global.t(key, args),
|
|
||||||
// 可选,对参数中的列头、校验提示..等进行自动翻译(只对支持国际化的有效)
|
|
||||||
translate(key, args) {
|
|
||||||
// 例如,只翻译 "message." 开头的键值
|
|
||||||
if (key && key.indexOf("message.") > -1) {
|
|
||||||
return i18n.global.t(key, args);
|
|
||||||
}
|
|
||||||
if (key && key.indexOf("el.") > -1) {
|
|
||||||
return i18n.global.t(key, args);
|
|
||||||
}
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export function useTable(app: App) {
|
|
||||||
app
|
|
||||||
.use(Header)
|
|
||||||
.use(Footer)
|
|
||||||
.use(Icon)
|
|
||||||
.use(Filter)
|
|
||||||
.use(Edit)
|
|
||||||
.use(Menu)
|
|
||||||
.use(Export)
|
|
||||||
.use(Keyboard)
|
|
||||||
.use(Validator)
|
|
||||||
|
|
||||||
// 可选组件
|
|
||||||
.use(Column)
|
|
||||||
.use(Colgroup)
|
|
||||||
.use(Grid)
|
|
||||||
.use(Tooltip)
|
|
||||||
.use(Toolbar)
|
|
||||||
.use(Pager)
|
|
||||||
.use(Form)
|
|
||||||
.use(FormItem)
|
|
||||||
.use(FormGather)
|
|
||||||
.use(Checkbox)
|
|
||||||
.use(CheckboxGroup)
|
|
||||||
.use(Radio)
|
|
||||||
.use(RadioGroup)
|
|
||||||
.use(RadioButton)
|
|
||||||
.use(Switch)
|
|
||||||
.use(Input)
|
|
||||||
.use(Select)
|
|
||||||
.use(Optgroup)
|
|
||||||
.use(Option)
|
|
||||||
.use(Textarea)
|
|
||||||
.use(Button)
|
|
||||||
.use(Modal)
|
|
||||||
.use(List)
|
|
||||||
.use(Pulldown)
|
|
||||||
// 安装表格
|
|
||||||
.use(Table);
|
|
||||||
}
|
|
@ -5,12 +5,12 @@ import {
|
|||||||
createWebHashHistory,
|
createWebHashHistory,
|
||||||
RouteRecordNormalized
|
RouteRecordNormalized
|
||||||
} from "vue-router";
|
} from "vue-router";
|
||||||
|
import { RouteConfigs } from "/@/layout/types";
|
||||||
import { split, uniqBy } from "lodash-es";
|
import { split, uniqBy } from "lodash-es";
|
||||||
import { i18n } from "/@/plugins/i18n";
|
import { i18n } from "/@/plugins/i18n";
|
||||||
import { openLink } from "/@/utils/link";
|
import { openLink } from "/@/utils/link";
|
||||||
import NProgress from "/@/utils/progress";
|
import NProgress from "/@/utils/progress";
|
||||||
import { useTimeoutFn } from "@vueuse/core";
|
import { useTimeoutFn } from "@vueuse/core";
|
||||||
import { RouteConfigs } from "/@/layout/types";
|
|
||||||
import { storageSession, storageLocal } from "/@/utils/storage";
|
import { storageSession, storageLocal } from "/@/utils/storage";
|
||||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
||||||
|
|
||||||
@ -18,6 +18,7 @@ import { usePermissionStoreHook } from "/@/store/modules/permission";
|
|||||||
import homeRouter from "./modules/home";
|
import homeRouter from "./modules/home";
|
||||||
import Layout from "/@/layout/index.vue";
|
import Layout from "/@/layout/index.vue";
|
||||||
import errorRouter from "./modules/error";
|
import errorRouter from "./modules/error";
|
||||||
|
import externalLink from "./modules/externalLink";
|
||||||
import remainingRouter from "./modules/remaining";
|
import remainingRouter from "./modules/remaining";
|
||||||
// 动态路由
|
// 动态路由
|
||||||
import { getAsyncRoutes } from "/@/api/routes";
|
import { getAsyncRoutes } from "/@/api/routes";
|
||||||
@ -25,7 +26,11 @@ import { getAsyncRoutes } from "/@/api/routes";
|
|||||||
// https://cn.vitejs.dev/guide/features.html#glob-import
|
// https://cn.vitejs.dev/guide/features.html#glob-import
|
||||||
const modulesRoutes = import.meta.glob("/src/views/*/*/*.vue");
|
const modulesRoutes = import.meta.glob("/src/views/*/*/*.vue");
|
||||||
|
|
||||||
const constantRoutes: Array<RouteComponent> = [homeRouter, errorRouter];
|
const constantRoutes: Array<RouteComponent> = [
|
||||||
|
homeRouter,
|
||||||
|
externalLink,
|
||||||
|
errorRouter
|
||||||
|
];
|
||||||
|
|
||||||
// 按照路由中meta下的rank等级升序来排序路由
|
// 按照路由中meta下的rank等级升序来排序路由
|
||||||
export const ascending = arr => {
|
export const ascending = arr => {
|
||||||
@ -181,7 +186,7 @@ export function resetRouter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 路由白名单
|
// 路由白名单
|
||||||
const whiteList = ["/login", "/register"];
|
const whiteList = ["/login"];
|
||||||
|
|
||||||
router.beforeEach((to, _from, next) => {
|
router.beforeEach((to, _from, next) => {
|
||||||
if (to.meta?.keepAlive) {
|
if (to.meta?.keepAlive) {
|
||||||
|
@ -6,7 +6,7 @@ const errorRouter = {
|
|||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: "/error/401",
|
redirect: "/error/401",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "el-icon-position",
|
icon: "Position",
|
||||||
title: "message.hserror",
|
title: "message.hserror",
|
||||||
showLink: true,
|
showLink: true,
|
||||||
rank: 7
|
rank: 7
|
||||||
|
25
src/router/modules/externalLink.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import Layout from "/@/layout/index.vue";
|
||||||
|
|
||||||
|
const externalLink = {
|
||||||
|
path: "/external",
|
||||||
|
name: "external",
|
||||||
|
component: Layout,
|
||||||
|
meta: {
|
||||||
|
icon: "Link",
|
||||||
|
title: "message.externalLink",
|
||||||
|
showLink: true,
|
||||||
|
rank: 190
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "https://github.com/xiaoxian521/vue-pure-admin",
|
||||||
|
meta: {
|
||||||
|
title: "message.externalLink",
|
||||||
|
showLink: true,
|
||||||
|
rank: 191
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
export default externalLink;
|
@ -6,7 +6,7 @@ const homeRouter = {
|
|||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: "/welcome",
|
redirect: "/welcome",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "el-icon-s-home",
|
icon: "HomeFilled",
|
||||||
showLink: true,
|
showLink: true,
|
||||||
rank: 0
|
rank: 0
|
||||||
},
|
},
|
||||||
|
@ -11,22 +11,12 @@ const remainingRouter = [
|
|||||||
rank: 101
|
rank: 101
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "/register",
|
|
||||||
name: "register",
|
|
||||||
component: () => import("/@/views/register.vue"),
|
|
||||||
meta: {
|
|
||||||
title: "message.hsregister",
|
|
||||||
showLink: false,
|
|
||||||
rank: 102
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/redirect",
|
path: "/redirect",
|
||||||
name: "redirect",
|
name: "redirect",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
meta: {
|
meta: {
|
||||||
icon: "el-icon-s-home",
|
icon: "HomeFilled",
|
||||||
title: "message.hshome",
|
title: "message.hshome",
|
||||||
showLink: false,
|
showLink: false,
|
||||||
rank: 104
|
rank: 104
|
||||||
|
@ -2,6 +2,7 @@ import { storageLocal } from "/@/utils/storage";
|
|||||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { store } from "/@/store";
|
import { store } from "/@/store";
|
||||||
|
import { getConfig } from "/@/config";
|
||||||
|
|
||||||
interface AppState {
|
interface AppState {
|
||||||
sidebar: {
|
sidebar: {
|
||||||
@ -21,9 +22,9 @@ export const useAppStore = defineStore({
|
|||||||
: true,
|
: true,
|
||||||
withoutAnimation: false
|
withoutAnimation: false
|
||||||
},
|
},
|
||||||
|
// 这里的layout用于监听容器拖拉后恢复对应的导航模式
|
||||||
layout:
|
layout:
|
||||||
storageLocal.getItem("responsive-layout")?.layout.match(/(.*)-/)[1] ??
|
storageLocal.getItem("responsive-layout")?.layout ?? getConfig().Layout,
|
||||||
"vertical",
|
|
||||||
device: deviceDetection() ? "mobile" : "desktop"
|
device: deviceDetection() ? "mobile" : "desktop"
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
|
@ -37,10 +37,6 @@
|
|||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-loading-mask {
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// el-tooltip的权重
|
// el-tooltip的权重
|
||||||
.is-dark {
|
.is-dark {
|
||||||
z-index: 99999 !important;
|
z-index: 99999 !important;
|
||||||
|
@ -65,20 +65,6 @@ ul {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// main-container global css
|
|
||||||
.app-container {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login,
|
|
||||||
.register {
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
overflow-x: hidden;
|
|
||||||
background: url("../assets/bg.png") no-repeat center;
|
|
||||||
background-size: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 头部用户信息样式重置 */
|
/* 头部用户信息样式重置 */
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
|
227
src/style/login.css
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
.wave {
|
||||||
|
position: fixed;
|
||||||
|
height: 100%;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
grid-gap: 18rem;
|
||||||
|
padding: 0 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img img {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
width: 360px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 350px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form h2 {
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin: 15px 0;
|
||||||
|
color: #999;
|
||||||
|
font: bold 200% Consolas, Monaco, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group {
|
||||||
|
position: relative;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 7% 93%;
|
||||||
|
margin: 25px 0;
|
||||||
|
padding: 5px 0;
|
||||||
|
border-bottom: 2px solid #d9d9d9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group:nth-child(1) {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group::before,
|
||||||
|
.input-group::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
bottom: -2px;
|
||||||
|
width: 0;
|
||||||
|
height: 2px;
|
||||||
|
background-color: #c5d3f7;
|
||||||
|
transition: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group::after {
|
||||||
|
right: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group::before {
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon i {
|
||||||
|
color: #d9d9d9;
|
||||||
|
transition: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group > div {
|
||||||
|
position: relative;
|
||||||
|
height: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group > div > h5 {
|
||||||
|
position: absolute;
|
||||||
|
left: 10px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
color: #d9d9d9;
|
||||||
|
font-size: 18px;
|
||||||
|
transition: 0.3s;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group.focus .icon i {
|
||||||
|
color: #5392f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group.focus div h5 {
|
||||||
|
top: -5px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group.focus::after,
|
||||||
|
.input-group.focus::before {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
background: none;
|
||||||
|
padding: 0.5rem 0.7rem;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #555;
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: block;
|
||||||
|
text-align: right;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #999;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #5392f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
border-radius: 25px;
|
||||||
|
margin: 1rem 0;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
background-image: linear-gradient(to right, #567dbe, #5392f0, #567dbe);
|
||||||
|
cursor: pointer;
|
||||||
|
color: #fff;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
background-size: 200%;
|
||||||
|
transition: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
background-position: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
bottom: 2px;
|
||||||
|
color: #5392f0;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 18px;
|
||||||
|
font-family: "Roboto", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1080px) {
|
||||||
|
.container {
|
||||||
|
grid-gap: 9rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
.login-form {
|
||||||
|
width: 290px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form h2 {
|
||||||
|
font-size: 2.4rem;
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img img {
|
||||||
|
width: 360px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 280px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.wave {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-box {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
@ -1,26 +1,39 @@
|
|||||||
|
@import "../layout/theme/default-vars.scss";
|
||||||
|
|
||||||
@mixin merge-style(
|
@mixin merge-style(
|
||||||
// 菜单选中后字体样式
|
|
||||||
$subMenuActiveText,
|
|
||||||
//菜单背景
|
|
||||||
$menuBg,
|
|
||||||
// 鼠标覆盖菜单时的背景
|
|
||||||
$menuHover,
|
|
||||||
// 子菜单背景
|
|
||||||
$subMenuBg,
|
|
||||||
// 鼠标覆盖子菜单时的背景
|
|
||||||
$subMenuHover,
|
|
||||||
// vertical模式下主体内容距离网页文档左侧的距离
|
// vertical模式下主体内容距离网页文档左侧的距离
|
||||||
$sideBarWidth,
|
$sideBarWidth
|
||||||
$navTextColor
|
|
||||||
) {
|
) {
|
||||||
$menuText: #7a80b4;
|
|
||||||
$menuActiveText: #7a80b4;
|
$menuActiveText: #7a80b4;
|
||||||
|
|
||||||
|
@media screen and (min-width: 150px) and (max-width: 420px) {
|
||||||
|
.app-main-nofixed-header {
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (min-width: 420px) {
|
||||||
|
.app-main-nofixed-header {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.main-container {
|
.main-container {
|
||||||
|
height: 100vh;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
transition: margin-left 0.28s;
|
transition: margin-left 0.28s;
|
||||||
margin-left: $sideBarWidth;
|
margin-left: $sideBarWidth;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
background: #f0f2f5;
|
||||||
|
@media screen and (min-width: 150px) and (max-width: 420px) {
|
||||||
|
.app-main .el-scrollbar__view:first-child {
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media screen and (min-width: 420px) {
|
||||||
|
.app-main .el-scrollbar__view:first-child {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.fixed-header {
|
.fixed-header {
|
||||||
@ -39,7 +52,7 @@
|
|||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
|
|
||||||
+ .app-main {
|
+ .app-main {
|
||||||
padding-top: 37px;
|
padding-top: 37px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,8 +63,8 @@
|
|||||||
|
|
||||||
.sidebar-container {
|
.sidebar-container {
|
||||||
transition: width 0.28s;
|
transition: width 0.28s;
|
||||||
width: $sideBarWidth;
|
width: $sideBarWidth !important;
|
||||||
background-color: $menuBg;
|
background: $menuBg;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
@ -91,8 +104,10 @@
|
|||||||
|
|
||||||
a {
|
a {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
display: flex;
|
||||||
|
padding-left: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-menu {
|
.el-menu {
|
||||||
@ -104,15 +119,18 @@
|
|||||||
.el-menu-item,
|
.el-menu-item,
|
||||||
.el-sub-menu__title {
|
.el-sub-menu__title {
|
||||||
color: $menuText;
|
color: $menuText;
|
||||||
|
padding: 0 20px 0 40px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $menuTitleHover !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// menu hover
|
// menu hover
|
||||||
.submenu-title-noDropdown,
|
.submenu-title-noDropdown,
|
||||||
.el-sub-menu__title {
|
.el-sub-menu__title {
|
||||||
// background: $menuBg;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $menuHover !important;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,17 +153,23 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
min-width: $sideBarWidth !important;
|
min-width: $sideBarWidth !important;
|
||||||
background-color: $subMenuBg !important;
|
background-color: $subMenuBg !important;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
// 无子集的激活菜单背景
|
||||||
background-color: $subMenuHover !important;
|
.is-active.submenu-title-noDropdown.outer-most {
|
||||||
}
|
background: $subMenuActiveBg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 有子集的激活菜单背景
|
||||||
|
.is-active.nest-menu {
|
||||||
|
background: $subMenuActiveBg !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.horizontal-header {
|
.horizontal-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
background-color: $menuBg;
|
background: $menuBg;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 62px;
|
height: 62px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -160,10 +184,6 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: $menuHover;
|
|
||||||
}
|
|
||||||
|
|
||||||
i {
|
i {
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
color: #1890ff;
|
color: #1890ff;
|
||||||
@ -173,7 +193,7 @@
|
|||||||
h4 {
|
h4 {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: $navTextColor;
|
color: $subMenuActiveText;
|
||||||
transition: all 0.5s;
|
transition: all 0.5s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,7 +209,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
min-width: 280px;
|
min-width: 280px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: $navTextColor;
|
color: $subMenuActiveText;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|
||||||
.screen-full {
|
.screen-full {
|
||||||
@ -205,7 +225,7 @@
|
|||||||
width: 40px;
|
width: 40px;
|
||||||
padding: 11px;
|
padding: 11px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: $navTextColor;
|
color: $subMenuActiveText;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: $menuHover;
|
background: $menuHover;
|
||||||
@ -220,7 +240,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: $navTextColor;
|
color: $subMenuActiveText;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: $menuHover;
|
background: $menuHover;
|
||||||
@ -240,7 +260,7 @@
|
|||||||
.el-icon-setting {
|
.el-icon-setting {
|
||||||
height: 62px;
|
height: 62px;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
padding: 11px;
|
padding: 12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -261,16 +281,16 @@
|
|||||||
.el-menu-item,
|
.el-menu-item,
|
||||||
.el-sub-menu__title {
|
.el-sub-menu__title {
|
||||||
color: $menuText;
|
color: $menuText;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $menuTitleHover !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.submenu-title-noDropdown,
|
.submenu-title-noDropdown,
|
||||||
.el-sub-menu__title {
|
.el-sub-menu__title {
|
||||||
height: 60px;
|
height: 60px;
|
||||||
background: $menuBg;
|
background: $menuBg;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $menuHover !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-active > .el-sub-menu__title,
|
.is-active > .el-sub-menu__title,
|
||||||
@ -296,22 +316,24 @@
|
|||||||
background-color: $subMenuBg !important;
|
background-color: $subMenuBg !important;
|
||||||
|
|
||||||
.el-menu-item {
|
.el-menu-item {
|
||||||
color: $menuText;
|
span {
|
||||||
background-color: $subMenuBg;
|
font-size: 12px;
|
||||||
|
margin-left: 10px;
|
||||||
&:hover {
|
|
||||||
background-color: $subMenuHover;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-sub-menu__title {
|
.el-sub-menu__title {
|
||||||
color: $menuText;
|
color: $menuText;
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .el-menu {
|
& > .el-menu {
|
||||||
i {
|
i {
|
||||||
margin-right: 16px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,9 +351,15 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
min-width: $sideBarWidth !important;
|
min-width: $sideBarWidth !important;
|
||||||
background-color: $subMenuBg !important;
|
background-color: $subMenuBg !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu-item,
|
||||||
|
.el-sub-menu__title {
|
||||||
|
color: $menuText;
|
||||||
|
background-color: $subMenuBg;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $menuHover !important;
|
color: $menuTitleHover !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,11 +368,8 @@
|
|||||||
color: $subMenuActiveText !important;
|
color: $subMenuActiveText !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nest-menu .el-sub-menu > .el-sub-menu__title,
|
.el-menu-item.is-active.nest-menu {
|
||||||
.el-menu-item {
|
background: $subMenuActiveBg !important;
|
||||||
&:hover {
|
|
||||||
background-color: $menuHover !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-menu-item,
|
.el-menu-item,
|
||||||
@ -362,8 +387,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// horizontal菜单折叠
|
// horizontal菜单
|
||||||
.el-menu--horizontal {
|
.el-menu--horizontal {
|
||||||
|
& > .el-sub-menu .el-sub-menu__icon-arrow {
|
||||||
|
position: static !important;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.el-menu--popup {
|
.el-menu--popup {
|
||||||
background-color: $subMenuBg !important;
|
background-color: $subMenuBg !important;
|
||||||
|
|
||||||
@ -371,13 +401,18 @@
|
|||||||
color: $menuText;
|
color: $menuText;
|
||||||
background-color: $subMenuBg;
|
background-color: $subMenuBg;
|
||||||
|
|
||||||
&:hover {
|
span {
|
||||||
background-color: $subMenuHover;
|
font-size: 12px;
|
||||||
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-sub-menu__title {
|
.el-sub-menu__title {
|
||||||
color: $menuText;
|
color: $menuText;
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,7 +429,7 @@
|
|||||||
background-color: $subMenuBg !important;
|
background-color: $subMenuBg !important;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $menuHover !important;
|
color: $menuTitleHover !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,17 +448,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-active {
|
|
||||||
transition: color 0.3s;
|
|
||||||
color: $subMenuActiveText !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nest-menu .el-sub-menu > .el-sub-menu__title,
|
.nest-menu .el-sub-menu > .el-sub-menu__title,
|
||||||
.el-menu-item {
|
.el-menu-item {
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $menuHover !important;
|
color: $menuTitleHover !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 有子集的激活菜单背景
|
||||||
|
.is-active.nest-menu {
|
||||||
|
background: $subMenuActiveBg !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu-item.is-active {
|
||||||
|
transition: color 0.3s;
|
||||||
|
color: $subMenuActiveText !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-scrollbar__wrap {
|
.el-scrollbar__wrap {
|
||||||
@ -435,6 +475,52 @@
|
|||||||
min-width: $sideBarWidth !important;
|
min-width: $sideBarWidth !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 有子菜单
|
||||||
|
.el-menu--collapse
|
||||||
|
.is-active.outer-most.el-sub-menu
|
||||||
|
> .el-sub-menu__title::before {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 5px;
|
||||||
|
width: 3px;
|
||||||
|
height: 100%;
|
||||||
|
background-color: $menuActiveBefore;
|
||||||
|
content: "";
|
||||||
|
clear: both;
|
||||||
|
-webkit-transition: all 0.2s ease-in-out;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
-webkit-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无子菜单
|
||||||
|
.el-menu--collapse .is-active.submenu-title-noDropdown.outer-most::before {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 5px;
|
||||||
|
width: 3px;
|
||||||
|
height: 100%;
|
||||||
|
background-color: $menuActiveBefore;
|
||||||
|
content: "";
|
||||||
|
clear: both;
|
||||||
|
-webkit-transition: all 0.2s ease-in-out;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
-webkit-transform: translateY(0);
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu--collapse .outer-most.el-sub-menu > .el-sub-menu__title::before,
|
||||||
|
.el-menu--collapse .submenu-title-noDropdown.outer-most::before {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
height: 0;
|
||||||
|
width: 3px;
|
||||||
|
-webkit-transform: translateY(-50%);
|
||||||
|
transform: translateY(-50%);
|
||||||
|
top: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
// 手机端
|
// 手机端
|
||||||
.mobile {
|
.mobile {
|
||||||
.fixed-header {
|
.fixed-header {
|
||||||
@ -448,7 +534,7 @@
|
|||||||
|
|
||||||
.sidebar-container {
|
.sidebar-container {
|
||||||
transition: transform 0.28s;
|
transition: transform 0.28s;
|
||||||
width: $sideBarWidth !important;
|
width: $sideBarWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.hideSidebar {
|
&.hideSidebar {
|
||||||
@ -468,14 +554,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-layout="vertical"] {
|
body[layout="vertical"] {
|
||||||
.fixed-header + .app-main {
|
$sideBarWidth: 210px;
|
||||||
padding-top: 85px;
|
@include merge-style($sideBarWidth);
|
||||||
|
|
||||||
|
.sidebar-logo-container {
|
||||||
|
background: $sidebarLogo;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hideSidebar {
|
.hideSidebar {
|
||||||
.fixed-header {
|
.fixed-header {
|
||||||
width: calc(100% - 54px) !important;
|
width: calc(100% - 54px);
|
||||||
transition: width 0.28s;
|
transition: width 0.28s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,7 +573,7 @@ body[data-layout="vertical"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.main-container {
|
.main-container {
|
||||||
margin-left: 54px !important;
|
margin-left: 54px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.submenu-title-noDropdown {
|
.submenu-title-noDropdown {
|
||||||
@ -506,8 +595,10 @@ body[data-layout="vertical"] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 菜单折叠
|
||||||
.el-menu--collapse {
|
.el-menu--collapse {
|
||||||
margin-left: -5px; //需优化的地方
|
margin-left: -5px;
|
||||||
|
|
||||||
.el-sub-menu {
|
.el-sub-menu {
|
||||||
& > .el-sub-menu__title {
|
& > .el-sub-menu__title {
|
||||||
& > span {
|
& > span {
|
||||||
@ -519,101 +610,20 @@ body[data-layout="vertical"] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.submenu-title-noDropdown {
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-layout="horizontal"] {
|
body[layout="horizontal"] {
|
||||||
|
$sideBarWidth: 0;
|
||||||
|
@include merge-style($sideBarWidth);
|
||||||
|
|
||||||
.fixed-header {
|
.fixed-header {
|
||||||
width: 100% !important;
|
width: 100%;
|
||||||
transition: none !important;
|
transition: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fixed-header + .app-main {
|
|
||||||
padding-top: 98px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// vertical模式下暗色主题
|
|
||||||
body[data-layout="vertical"][data-theme="dark"] {
|
|
||||||
$subMenuActiveText: #f4f4f5;
|
|
||||||
$menuBg: #1b2a47;
|
|
||||||
$menuHover: #2a395b;
|
|
||||||
$subMenuBg: #1f2d3d;
|
|
||||||
$subMenuHover: #001528;
|
|
||||||
$sideBarWidth: 210px;
|
|
||||||
$navTextColor: #fff;
|
|
||||||
|
|
||||||
@include merge-style(
|
|
||||||
$subMenuActiveText,
|
|
||||||
$menuBg,
|
|
||||||
$menuHover,
|
|
||||||
$subMenuBg,
|
|
||||||
$subMenuHover,
|
|
||||||
$sideBarWidth,
|
|
||||||
$navTextColor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// vertical模式下亮色主题
|
|
||||||
body[data-layout="vertical"][data-theme="light"] {
|
|
||||||
$subMenuActiveText: #409eff;
|
|
||||||
$menuBg: #fff;
|
|
||||||
$menuHover: #e0ebf6;
|
|
||||||
$subMenuBg: #fff;
|
|
||||||
$subMenuHover: #e0ebf6;
|
|
||||||
$sideBarWidth: 210px;
|
|
||||||
$navTextColor: #7a80b4;
|
|
||||||
|
|
||||||
@include merge-style(
|
|
||||||
$subMenuActiveText,
|
|
||||||
$menuBg,
|
|
||||||
$menuHover,
|
|
||||||
$subMenuBg,
|
|
||||||
$subMenuHover,
|
|
||||||
$sideBarWidth,
|
|
||||||
$navTextColor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// horizontal模式下暗色主题
|
|
||||||
body[data-layout="horizontal"][data-theme="dark"] {
|
|
||||||
$subMenuActiveText: #f4f4f5;
|
|
||||||
$menuBg: #1b2a47;
|
|
||||||
$menuHover: #2a395b;
|
|
||||||
$subMenuBg: #1f2d3d;
|
|
||||||
$subMenuHover: #001528;
|
|
||||||
$sideBarWidth: 0;
|
|
||||||
$navTextColor: #fff;
|
|
||||||
|
|
||||||
@include merge-style(
|
|
||||||
$subMenuActiveText,
|
|
||||||
$menuBg,
|
|
||||||
$menuHover,
|
|
||||||
$subMenuBg,
|
|
||||||
$subMenuHover,
|
|
||||||
$sideBarWidth,
|
|
||||||
$navTextColor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// horizontal模式下亮色主题
|
|
||||||
body[data-layout="horizontal"][data-theme="light"] {
|
|
||||||
$subMenuActiveText: #409eff;
|
|
||||||
$menuBg: #fff;
|
|
||||||
$menuHover: #e0ebf6;
|
|
||||||
$subMenuBg: #fff;
|
|
||||||
$subMenuHover: #e0ebf6;
|
|
||||||
$sideBarWidth: 0;
|
|
||||||
$navTextColor: #7a80b4;
|
|
||||||
|
|
||||||
@include merge-style(
|
|
||||||
$subMenuActiveText,
|
|
||||||
$menuBg,
|
|
||||||
$menuHover,
|
|
||||||
$subMenuBg,
|
|
||||||
$subMenuHover,
|
|
||||||
$sideBarWidth,
|
|
||||||
$navTextColor
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -41,12 +41,6 @@ class EnclosureHttp {
|
|||||||
// 记录当前这一次cancelToken的key
|
// 记录当前这一次cancelToken的key
|
||||||
private currentCancelTokenKey = "";
|
private currentCancelTokenKey = "";
|
||||||
|
|
||||||
private beforeRequestCallback: EnclosureHttpRequestConfig["beforeRequestCallback"] =
|
|
||||||
undefined;
|
|
||||||
|
|
||||||
private beforeResponseCallback: EnclosureHttpRequestConfig["beforeResponseCallback"] =
|
|
||||||
undefined;
|
|
||||||
|
|
||||||
public get cancelTokenList(): Array<cancelTokenType> {
|
public get cancelTokenList(): Array<cancelTokenType> {
|
||||||
return this.sourceTokenList;
|
return this.sourceTokenList;
|
||||||
}
|
}
|
||||||
@ -126,9 +120,8 @@ class EnclosureHttp {
|
|||||||
this.cancelRepeatRequest();
|
this.cancelRepeatRequest();
|
||||||
this.currentCancelTokenKey = cancelKey;
|
this.currentCancelTokenKey = cancelKey;
|
||||||
// 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
|
// 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
|
||||||
if (typeof this.beforeRequestCallback === "function") {
|
if (typeof config.beforeRequestCallback === "function") {
|
||||||
this.beforeRequestCallback($config);
|
config.beforeRequestCallback($config);
|
||||||
this.beforeRequestCallback = undefined;
|
|
||||||
return $config;
|
return $config;
|
||||||
}
|
}
|
||||||
if (EnclosureHttp.initConfig.beforeRequestCallback) {
|
if (EnclosureHttp.initConfig.beforeRequestCallback) {
|
||||||
@ -159,20 +152,21 @@ class EnclosureHttp {
|
|||||||
const instance = EnclosureHttp.axiosInstance;
|
const instance = EnclosureHttp.axiosInstance;
|
||||||
instance.interceptors.response.use(
|
instance.interceptors.response.use(
|
||||||
(response: EnclosureHttpResoponse) => {
|
(response: EnclosureHttpResoponse) => {
|
||||||
|
const $config = response.config;
|
||||||
// 请求每次成功一次就删除当前canceltoken标记
|
// 请求每次成功一次就删除当前canceltoken标记
|
||||||
const cancelKey = EnclosureHttp.genUniqueKey(response.config);
|
const cancelKey = EnclosureHttp.genUniqueKey($config);
|
||||||
this.deleteCancelTokenByCancelKey(cancelKey);
|
this.deleteCancelTokenByCancelKey(cancelKey);
|
||||||
|
|
||||||
|
NProgress.done();
|
||||||
// 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
|
// 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
|
||||||
if (typeof this.beforeResponseCallback === "function") {
|
if (typeof $config.beforeResponseCallback === "function") {
|
||||||
this.beforeResponseCallback(response);
|
$config.beforeResponseCallback(response);
|
||||||
this.beforeResponseCallback = undefined;
|
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
if (EnclosureHttp.initConfig.beforeResponseCallback) {
|
if (EnclosureHttp.initConfig.beforeResponseCallback) {
|
||||||
EnclosureHttp.initConfig.beforeResponseCallback(response);
|
EnclosureHttp.initConfig.beforeResponseCallback(response);
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
NProgress.done();
|
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
(error: EnclosureHttpError) => {
|
(error: EnclosureHttpError) => {
|
||||||
@ -210,12 +204,6 @@ class EnclosureHttp {
|
|||||||
...axiosConfig
|
...axiosConfig
|
||||||
} as EnclosureHttpRequestConfig);
|
} as EnclosureHttpRequestConfig);
|
||||||
// 单独处理自定义请求/响应回掉
|
// 单独处理自定义请求/响应回掉
|
||||||
if (axiosConfig?.beforeRequestCallback) {
|
|
||||||
this.beforeRequestCallback = axiosConfig.beforeRequestCallback;
|
|
||||||
}
|
|
||||||
if (axiosConfig?.beforeResponseCallback) {
|
|
||||||
this.beforeResponseCallback = axiosConfig.beforeResponseCallback;
|
|
||||||
}
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
EnclosureHttp.axiosInstance
|
EnclosureHttp.axiosInstance
|
||||||
.request(config)
|
.request(config)
|
||||||
|
@ -23,14 +23,23 @@ export const injectResponsiveStorage = (app: App, config: ServerConfigs) => {
|
|||||||
locale: {
|
locale: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: Storage.getData(undefined, "locale") ?? {
|
default: Storage.getData(undefined, "locale") ?? {
|
||||||
locale: config.Locale
|
locale: config.Locale ?? "zh"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// layout模式以及主题
|
// layout模式以及主题
|
||||||
layout: {
|
layout: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: Storage.getData(undefined, "layout") ?? {
|
default: Storage.getData(undefined, "layout") ?? {
|
||||||
layout: config.Layout
|
layout: config.Layout ?? "vertical",
|
||||||
|
theme: config.Theme ?? "default"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sets: {
|
||||||
|
type: Object,
|
||||||
|
default: Storage.getData(undefined, "sets") ?? {
|
||||||
|
grey: config.Grey ?? false,
|
||||||
|
weak: config.Weak ?? false,
|
||||||
|
hideTabs: config.HideTabs ?? false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,20 +1,180 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive } from "vue";
|
import { ref, computed } from "vue";
|
||||||
import info, { ContextProps } from "../components/ReInfo/index.vue";
|
import { useRouter } from "vue-router";
|
||||||
|
import { initRouter } from "/@/router";
|
||||||
|
import { storageSession } from "/@/utils/storage";
|
||||||
|
import { addClass, removeClass } from "/@/utils/operate";
|
||||||
|
import bg from "/@/assets/login/bg.png";
|
||||||
|
import avatar from "/@/assets/login/avatar.svg";
|
||||||
|
import illustration0 from "/@/assets/login/illustration0.svg";
|
||||||
|
import illustration1 from "/@/assets/login/illustration1.svg";
|
||||||
|
import illustration2 from "/@/assets/login/illustration2.svg";
|
||||||
|
import illustration3 from "/@/assets/login/illustration3.svg";
|
||||||
|
import illustration4 from "/@/assets/login/illustration4.svg";
|
||||||
|
import illustration5 from "/@/assets/login/illustration5.svg";
|
||||||
|
import illustration6 from "/@/assets/login/illustration6.svg";
|
||||||
|
|
||||||
const contextInfo: ContextProps = reactive({
|
const router = useRouter();
|
||||||
userName: "",
|
|
||||||
passWord: "",
|
// eslint-disable-next-line vue/return-in-computed-property
|
||||||
verify: null,
|
const currentWeek = computed(() => {
|
||||||
svg: null
|
switch (String(new Date().getDay())) {
|
||||||
|
case "0":
|
||||||
|
return illustration0;
|
||||||
|
case "1":
|
||||||
|
return illustration1;
|
||||||
|
case "2":
|
||||||
|
return illustration2;
|
||||||
|
case "3":
|
||||||
|
return illustration3;
|
||||||
|
case "4":
|
||||||
|
return illustration4;
|
||||||
|
case "5":
|
||||||
|
return illustration5;
|
||||||
|
case "6":
|
||||||
|
return illustration6;
|
||||||
|
default:
|
||||||
|
return illustration4;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 登录
|
let user = ref("admin");
|
||||||
const onLogin = () => {};
|
let pwd = ref("123456");
|
||||||
|
|
||||||
|
const onLogin = (): void => {
|
||||||
|
storageSession.setItem("info", {
|
||||||
|
username: "admin",
|
||||||
|
accessToken: "eyJhbGciOiJIUzUxMiJ9.test"
|
||||||
|
});
|
||||||
|
initRouter("admin").then(() => {});
|
||||||
|
router.push("/");
|
||||||
|
};
|
||||||
|
|
||||||
|
function onUserFocus() {
|
||||||
|
addClass(document.querySelector(".user"), "focus");
|
||||||
|
}
|
||||||
|
|
||||||
|
function onUserBlur() {
|
||||||
|
if (user.value.length === 0)
|
||||||
|
removeClass(document.querySelector(".user"), "focus");
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPwdFocus() {
|
||||||
|
addClass(document.querySelector(".pwd"), "focus");
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPwdBlur() {
|
||||||
|
if (pwd.value.length === 0)
|
||||||
|
removeClass(document.querySelector(".pwd"), "focus");
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="login">
|
<img :src="bg" class="wave" />
|
||||||
<info :ruleForm="contextInfo" @on-behavior="onLogin" />
|
<div class="container">
|
||||||
|
<div class="img">
|
||||||
|
<component :is="currentWeek"></component>
|
||||||
|
</div>
|
||||||
|
<div class="login-box">
|
||||||
|
<div class="login-form">
|
||||||
|
<avatar class="avatar" />
|
||||||
|
<h2
|
||||||
|
v-motion
|
||||||
|
:initial="{
|
||||||
|
opacity: 0,
|
||||||
|
y: 100
|
||||||
|
}"
|
||||||
|
:enter="{
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
transition: {
|
||||||
|
delay: 100
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
Pure Admin
|
||||||
|
</h2>
|
||||||
|
<div
|
||||||
|
class="input-group user focus"
|
||||||
|
v-motion
|
||||||
|
:initial="{
|
||||||
|
opacity: 0,
|
||||||
|
y: 100
|
||||||
|
}"
|
||||||
|
:enter="{
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
transition: {
|
||||||
|
delay: 200
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div class="icon">
|
||||||
|
<i class="fa fa-user"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h5>用户名</h5>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="input"
|
||||||
|
v-model="user"
|
||||||
|
@focus="onUserFocus"
|
||||||
|
@blur="onUserBlur"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="input-group pwd focus"
|
||||||
|
v-motion
|
||||||
|
:initial="{
|
||||||
|
opacity: 0,
|
||||||
|
y: 100
|
||||||
|
}"
|
||||||
|
:enter="{
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
transition: {
|
||||||
|
delay: 300
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div class="icon">
|
||||||
|
<i class="fa fa-lock"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h5>密码</h5>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
class="input"
|
||||||
|
v-model="pwd"
|
||||||
|
@focus="onPwdFocus"
|
||||||
|
@blur="onPwdBlur"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
v-motion
|
||||||
|
:initial="{
|
||||||
|
opacity: 0,
|
||||||
|
y: 10
|
||||||
|
}"
|
||||||
|
:enter="{
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
transition: {
|
||||||
|
delay: 400
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
@click="onLogin"
|
||||||
|
>
|
||||||
|
登录
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@import url("/@/style/login.css");
|
||||||
|
</style>
|
||||||
|
@ -14,7 +14,7 @@ function changRole(value) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div>
|
||||||
<el-radio-group v-model="auth" @change="changRole">
|
<el-radio-group v-model="auth" @change="changRole">
|
||||||
<el-radio-button label="admin"></el-radio-button>
|
<el-radio-button label="admin"></el-radio-button>
|
||||||
<el-radio-button label="test"></el-radio-button>
|
<el-radio-button label="test"></el-radio-button>
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, unref } from "vue";
|
import { ref, unref } from "vue";
|
||||||
import { storageSession } from "/@/utils/storage";
|
import { storageSession } from "/@/utils/storage";
|
||||||
|
|
||||||
let purview = ref<string>(storageSession.getItem("info").username);
|
let purview = ref<string>(storageSession.getItem("info").username);
|
||||||
|
|
||||||
function changRole() {
|
function changRole() {
|
||||||
if (unref(purview) === "admin") {
|
if (unref(purview) === "admin") {
|
||||||
storageSession.setItem("info", {
|
storageSession.setItem("info", {
|
||||||
@ -20,7 +22,7 @@ function changRole() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div>
|
||||||
<h4>
|
<h4>
|
||||||
当前角色:
|
当前角色:
|
||||||
<span style="font-size: 26px">{{ purview }}</span>
|
<span style="font-size: 26px">{{ purview }}</span>
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { reactive } from "vue";
|
|
||||||
import info, { ContextProps } from "../components/ReInfo/index.vue";
|
|
||||||
|
|
||||||
const contextInfo: ContextProps = reactive({
|
|
||||||
userName: "",
|
|
||||||
passWord: "",
|
|
||||||
verify: null,
|
|
||||||
svg: null
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="register">
|
|
||||||
<info :ruleForm="contextInfo" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
4
types/global.d.ts
vendored
@ -90,6 +90,10 @@ declare global {
|
|||||||
KeepAlive?: boolean;
|
KeepAlive?: boolean;
|
||||||
Locale?: string;
|
Locale?: string;
|
||||||
Layout?: string;
|
Layout?: string;
|
||||||
|
Theme?: string;
|
||||||
|
Grey?: boolean;
|
||||||
|
Weak?: boolean;
|
||||||
|
HideTabs?: boolean;
|
||||||
MapConfigure?: {
|
MapConfigure?: {
|
||||||
amapKey?: string;
|
amapKey?: string;
|
||||||
baiduKey?: string;
|
baiduKey?: string;
|
||||||
|
@ -6,8 +6,8 @@ import { warpperEnv } from "./build/utils";
|
|||||||
import { createProxy } from "./build/proxy";
|
import { createProxy } from "./build/proxy";
|
||||||
import { viteMockServe } from "vite-plugin-mock";
|
import { viteMockServe } from "vite-plugin-mock";
|
||||||
import svgLoader from "vite-svg-loader";
|
import svgLoader from "vite-svg-loader";
|
||||||
import styleImport from "vite-plugin-style-import";
|
|
||||||
import ElementPlus from "unplugin-element-plus/vite";
|
import ElementPlus from "unplugin-element-plus/vite";
|
||||||
|
import themePreprocessorPlugin from "@zougt/vite-plugin-theme-preprocessor";
|
||||||
|
|
||||||
const pathResolve = (dir: string): string => {
|
const pathResolve = (dir: string): string => {
|
||||||
return resolve(__dirname, ".", dir);
|
return resolve(__dirname, ".", dir);
|
||||||
@ -55,19 +55,63 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
|
|||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
vueJsx(),
|
vueJsx(),
|
||||||
svgLoader(),
|
themePreprocessorPlugin({
|
||||||
styleImport({
|
scss: {
|
||||||
libs: [
|
multipleScopeVars: [
|
||||||
// 按需加载vxe-table
|
{
|
||||||
{
|
scopeName: "layout-theme-default",
|
||||||
libraryName: "vxe-table",
|
path: pathResolve("src/layout/theme/default-vars.scss")
|
||||||
esModule: true,
|
},
|
||||||
ensureStyleFile: true,
|
{
|
||||||
resolveComponent: name => `vxe-table/es/${name}`,
|
scopeName: "layout-theme-light",
|
||||||
resolveStyle: name => `vxe-table/es/${name}/style.css`
|
path: pathResolve("src/layout/theme/light-vars.scss")
|
||||||
}
|
},
|
||||||
]
|
{
|
||||||
|
scopeName: "layout-theme-dusk",
|
||||||
|
path: pathResolve("src/layout/theme/dusk-vars.scss")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scopeName: "layout-theme-volcano",
|
||||||
|
path: pathResolve("src/layout/theme/volcano-vars.scss")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scopeName: "layout-theme-yellow",
|
||||||
|
path: pathResolve("src/layout/theme/yellow-vars.scss")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scopeName: "layout-theme-mingQing",
|
||||||
|
path: pathResolve("src/layout/theme/mingQing-vars.scss")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scopeName: "layout-theme-auroraGreen",
|
||||||
|
path: pathResolve("src/layout/theme/auroraGreen-vars.scss")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scopeName: "layout-theme-pink",
|
||||||
|
path: pathResolve("src/layout/theme/pink-vars.scss")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scopeName: "layout-theme-saucePurple",
|
||||||
|
path: pathResolve("src/layout/theme/saucePurple-vars.scss")
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 默认取 multipleScopeVars[0].scopeName
|
||||||
|
defaultScopeName: "",
|
||||||
|
// 在生产模式是否抽取独立的主题css文件,extract为true以下属性有效
|
||||||
|
extract: true,
|
||||||
|
// 独立主题css文件的输出路径,默认取 viteConfig.build.assetsDir 相对于 (viteConfig.build.outDir)
|
||||||
|
outputDir: "",
|
||||||
|
// 会选取defaultScopeName对应的主题css文件在html添加link
|
||||||
|
themeLinkTagId: "head",
|
||||||
|
// "head"||"head-prepend" || "body" ||"body-prepend"
|
||||||
|
themeLinkTagInjectTo: "head",
|
||||||
|
// 是否对抽取的css文件内对应scopeName的权重类名移除
|
||||||
|
removeCssScopeName: false,
|
||||||
|
// 可以自定义css文件名称的函数
|
||||||
|
customThemeCssFileName: scopeName => scopeName
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
|
svgLoader(),
|
||||||
ElementPlus({}),
|
ElementPlus({}),
|
||||||
viteMockServe({
|
viteMockServe({
|
||||||
mockPath: "mock",
|
mockPath: "mock",
|
||||||
@ -83,17 +127,17 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
|
|||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
include: [
|
include: [
|
||||||
"element-plus/lib/locale/lang/zh-cn",
|
"element-plus/lib/locale/lang/zh-cn",
|
||||||
"element-plus/lib/locale/lang/en",
|
"element-plus/lib/locale/lang/en"
|
||||||
"vxe-table/lib/locale/lang/zh-CN",
|
],
|
||||||
"vxe-table/lib/locale/lang/en-US"
|
exclude: ["@zougt/vite-plugin-theme-preprocessor/dist/browser-utils"]
|
||||||
]
|
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
sourcemap: false,
|
sourcemap: false,
|
||||||
brotliSize: false,
|
brotliSize: false,
|
||||||
// 消除打包大小超过500kb警告
|
// 消除打包大小超过500kb警告
|
||||||
chunkSizeWarningLimit: 2000
|
chunkSizeWarningLimit: 2000,
|
||||||
|
minify: false
|
||||||
},
|
},
|
||||||
define: {
|
define: {
|
||||||
__INTLIFY_PROD_DEVTOOLS__: false
|
__INTLIFY_PROD_DEVTOOLS__: false
|
||||||
|