mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-11-03 13:44:47 +08:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa845fc3f5 | ||
|
|
079a455181 | ||
|
|
07794d000c | ||
|
|
e787f46414 | ||
|
|
e61d6109d7 | ||
|
|
34eda14473 | ||
|
|
0eb0b7395e | ||
|
|
73705eb0e4 | ||
|
|
d94fb0ef06 | ||
|
|
17470ecce2 | ||
|
|
12db6966fb | ||
|
|
5070568b89 | ||
|
|
ef91f113ee | ||
|
|
c875d20e83 | ||
|
|
c86aae7b8b | ||
|
|
ee30cba471 | ||
|
|
7bcd8a800a | ||
|
|
903e298951 | ||
|
|
955b76f30a | ||
|
|
1b052023b6 | ||
|
|
3af52cf6c4 | ||
|
|
660b6f4be8 |
11
.vscode/extensions.json
vendored
Normal file
11
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"stylelint.vscode-stylelint",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"johnsoncodehk.volar",
|
||||
"lokalise.i18n-ally",
|
||||
"mikestead.dotenv",
|
||||
"antfu.iconify"
|
||||
]
|
||||
}
|
||||
27
.vscode/settings.json
vendored
27
.vscode/settings.json
vendored
@@ -1,11 +1,14 @@
|
||||
{
|
||||
// You should install these plugins:
|
||||
// ESLint
|
||||
// Prettier - Code formatter
|
||||
// stylelint
|
||||
// vscode-icons
|
||||
// TypeScript Vue Plugin (Volar)
|
||||
// Vue Language Features (Volar)
|
||||
/** 你需要安装这些插件,以便带来更好的提示体验
|
||||
* ESLint
|
||||
* Prettier - Code formatter
|
||||
* stylelint
|
||||
* vscode-icons
|
||||
* i18n Ally
|
||||
* Iconify IntelliSense
|
||||
* TypeScript Vue Plugin (Volar)
|
||||
* Vue Language Features (Volar)
|
||||
*/
|
||||
"terminal.integrated.rendererType": "dom",
|
||||
"editor.formatOnType": true,
|
||||
"editor.formatOnSave": true,
|
||||
@@ -45,5 +48,13 @@
|
||||
},
|
||||
"volar.tsPlugin": true,
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"i18n-ally.localesPaths": ["src/plugins/i18n"]
|
||||
"i18n-ally.localesPaths": ["src/plugins/i18n"],
|
||||
"i18n-ally.keystyle": "nested",
|
||||
"i18n-ally.sortKeys": true,
|
||||
"i18n-ally.namespace": true,
|
||||
"i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
|
||||
"i18n-ally.enabledParsers": ["ts"],
|
||||
"i18n-ally.sourceLanguage": "en",
|
||||
"i18n-ally.displayLanguage": "zh-CN",
|
||||
"i18n-ally.enabledFrameworks": ["vue", "react"]
|
||||
}
|
||||
|
||||
17
.vscode/vue3.2+.setup-snippets.json
vendored
Normal file
17
.vscode/vue3.2+.setup-snippets.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"Vue3.2+快速生成模板": {
|
||||
"prefix": "Vue3.2+",
|
||||
"body": [
|
||||
"<script setup lang='ts'>",
|
||||
"</script>\n",
|
||||
"<template>",
|
||||
"\t<div>\n",
|
||||
"\t</div>",
|
||||
"</template>\n",
|
||||
"<style scoped>\n",
|
||||
"</style>",
|
||||
"$2"
|
||||
],
|
||||
"description": "Vue3.2+"
|
||||
}
|
||||
}
|
||||
20
.vscode/vue3.2.setup-snippets
vendored
20
.vscode/vue3.2.setup-snippets
vendored
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"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,3 +1,17 @@
|
||||
# 2.8.0(2022-1-4)
|
||||
|
||||
### 🎫 Feat
|
||||
|
||||
-Added dark theme
|
||||
-Add element-plus custom theme
|
||||
-Add guide page
|
||||
|
||||
### 🍏 Perf
|
||||
|
||||
-Optimize internationalization, compatible with the vscode plug-in i18n Ally smart reminder
|
||||
-Optimize the back-end return routing structure
|
||||
-Optimize local storage, with four built-in buttons `responsive-configure`, `responsive-locale`, `responsive-layout`, `responsive-tags`, which are basic configuration, international configuration, layout configuration, and tab persistent configuration
|
||||
|
||||
# 2.7.0(2021-12-18)
|
||||
|
||||
### 🎫 Feat
|
||||
|
||||
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,3 +1,17 @@
|
||||
# 2.8.0(2022-1-4)
|
||||
|
||||
### 🎫 Feat
|
||||
|
||||
-Added dark theme
|
||||
-Add element-plus custom theme
|
||||
-Add guide page
|
||||
|
||||
### 🍏 Perf
|
||||
|
||||
-Optimize internationalization, compatible with the vscode plug-in i18n Ally smart reminder
|
||||
-Optimize the back-end return routing structure
|
||||
-Optimize local storage, with four built-in buttons `responsive-configure`, `responsive-locale`, `responsive-layout`, `responsive-tags`, which are basic configuration, international configuration, layout configuration, and tab persistent configuration
|
||||
|
||||
# 2.7.0(2021-12-18)
|
||||
|
||||
### 🎫 Feat
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
# 2.8.0(2022-1-4)
|
||||
|
||||
### 🎫 Feat
|
||||
|
||||
- 添加暗黑主题
|
||||
- 添加 element-plus 自定义主题
|
||||
- 添加引导页
|
||||
|
||||
### 🍏 Perf
|
||||
|
||||
- 优化国际化,兼容 vscode 插件 i18n Ally 智能提醒
|
||||
- 优化后端返回路由结构
|
||||
- 优化本地存储,内置四个键`responsive-configure`、`responsive-locale`、`responsive-layout`、`responsive-tags`,分别为基本配置、国际化配置、布局配置、标签页持久化配置
|
||||
|
||||
# 2.7.0(2021-12-18)
|
||||
|
||||
### 🎫 Feat
|
||||
|
||||
@@ -28,6 +28,7 @@ Github Address: <https://github.com/xiaoxian521/pure-admin-thin>
|
||||
<p align="center">
|
||||
<img alt="PureAdmin Logo" width="100%" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b4857fc7eb7d4c0f8deeefc644c1f7dd~tplv-k3u1fbpfcp-watermark.awebp?">
|
||||
<img alt="PureAdmin Logo" width="100%" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/549c3184697f4d268a78c9833e5ec2ea~tplv-k3u1fbpfcp-watermark.awebp?">
|
||||
<img alt="PureAdmin Logo" width="100%" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/381fc957fac143db9f06efdd389d88a3~tplv-k3u1fbpfcp-watermark.awebp?">
|
||||
</p>
|
||||
|
||||
### Use Gitpod
|
||||
@@ -117,9 +118,15 @@ Support modern browsers, not IE
|
||||
|
||||
## Donate
|
||||
|
||||
If you think this project is helpful to you, you can help the author buy a cup of coffee to show your support!
|
||||
If you think this project is helpful to you, you can help the author buy a cup of coffee to show your support
|
||||
|
||||
<img src="http://yiming_chang.gitee.io/manages/pay.png" width="360px" height="480px" />
|
||||
<img src="http://yiming_chang.gitee.io/manages/pay.jpg" width="150px" height="150px" />
|
||||
|
||||
## WeChat Exchange Group
|
||||
|
||||
For the better development of the project, you can choose to donate 10 yuan and add the following WeChat to pull you into the group. After adding, please consciously send a screenshot of the donation
|
||||
|
||||
<img src="http://yiming_chang.gitee.io/manages/kf.jpg" width="150px" height="195px" />
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ UI 设计:<https://www.bilibili.com/video/BV17g411T7rq/>
|
||||
<p align="center">
|
||||
<img alt="PureAdmin Logo" width="100%" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b4857fc7eb7d4c0f8deeefc644c1f7dd~tplv-k3u1fbpfcp-watermark.awebp?">
|
||||
<img alt="PureAdmin Logo" width="100%" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/549c3184697f4d268a78c9833e5ec2ea~tplv-k3u1fbpfcp-watermark.awebp?">
|
||||
<img alt="PureAdmin Logo" width="100%" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/381fc957fac143db9f06efdd389d88a3~tplv-k3u1fbpfcp-watermark.awebp?">
|
||||
</p>
|
||||
|
||||
### 使用 Gitpod
|
||||
@@ -121,11 +122,11 @@ pnpm build
|
||||
|
||||
<img src="http://yiming_chang.gitee.io/manages/pay.jpg" width="150px" height="150px" />
|
||||
|
||||
## 付费咨询、需求定制
|
||||
## 微信交流群
|
||||
|
||||
作者精力有限,需要提供技术服务的可扫下面的二维码加微信,添加请备注来意
|
||||
为了项目更好的发展,你可选择捐赠 10 元后添加下图微信拉你进群,添加后请自觉发捐赠截图
|
||||
|
||||
<img src="http://yiming_chang.gitee.io/manages/wechat.jpg" width="150px" height="150px" />
|
||||
<img src="http://yiming_chang.gitee.io/manages/kf.jpg" width="150px" height="195px" />
|
||||
|
||||
## 许可证
|
||||
|
||||
|
||||
@@ -5,29 +5,29 @@ import { MockMethod } from "vite-plugin-mock";
|
||||
const systemRouter = {
|
||||
path: "/system",
|
||||
name: "system",
|
||||
redirect: "/system/user",
|
||||
redirect: "/system/user/index",
|
||||
meta: {
|
||||
icon: "Setting",
|
||||
title: "message.hssysManagement",
|
||||
title: "menus.hssysManagement",
|
||||
i18n: true,
|
||||
showLink: true,
|
||||
rank: 6
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "/system/user",
|
||||
path: "/system/user/index",
|
||||
name: "user",
|
||||
meta: {
|
||||
title: "message.hsBaseinfo",
|
||||
title: "menus.hsBaseinfo",
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "/system/dict",
|
||||
path: "/system/dict/index",
|
||||
name: "dict",
|
||||
meta: {
|
||||
title: "message.hsDict",
|
||||
title: "menus.hsDict",
|
||||
i18n: true,
|
||||
showLink: true,
|
||||
keepAlive: true
|
||||
@@ -39,9 +39,9 @@ const systemRouter = {
|
||||
const permissionRouter = {
|
||||
path: "/permission",
|
||||
name: "permission",
|
||||
redirect: "/permission/page",
|
||||
redirect: "/permission/page/index",
|
||||
meta: {
|
||||
title: "message.permission",
|
||||
title: "menus.permission",
|
||||
icon: "Lollipop",
|
||||
i18n: true,
|
||||
showLink: true,
|
||||
@@ -49,19 +49,19 @@ const permissionRouter = {
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "/permission/page",
|
||||
path: "/permission/page/index",
|
||||
name: "permissionPage",
|
||||
meta: {
|
||||
title: "message.permissionPage",
|
||||
title: "menus.permissionPage",
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "/permission/button",
|
||||
path: "/permission/button/index",
|
||||
name: "permissionButton",
|
||||
meta: {
|
||||
title: "message.permissionButton",
|
||||
title: "menus.permissionButton",
|
||||
i18n: true,
|
||||
showLink: true,
|
||||
authority: []
|
||||
@@ -76,7 +76,7 @@ const tabsRouter = {
|
||||
redirect: "/tabs/index",
|
||||
meta: {
|
||||
icon: "IF-team-icontabs",
|
||||
title: "message.hstabs",
|
||||
title: "menus.hstabs",
|
||||
i18n: true,
|
||||
showLink: true,
|
||||
rank: 8
|
||||
@@ -86,7 +86,7 @@ const tabsRouter = {
|
||||
path: "/tabs/index",
|
||||
name: "reTabs",
|
||||
meta: {
|
||||
title: "message.hstabs",
|
||||
title: "menus.hstabs",
|
||||
showLink: true,
|
||||
i18n: true
|
||||
}
|
||||
@@ -99,7 +99,6 @@ const tabsRouter = {
|
||||
showLink: false,
|
||||
i18n: false,
|
||||
dynamicLevel: 3,
|
||||
realPath: "/tabs/detail",
|
||||
refreshRedirect: "/tabs/index"
|
||||
}
|
||||
}
|
||||
|
||||
19
package.json
19
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vue-pure-admin",
|
||||
"version": "2.7.0",
|
||||
"version": "2.8.0",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">= 16",
|
||||
@@ -29,6 +29,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@amap/amap-jsapi-loader": "^1.0.1",
|
||||
"@ctrl/tinycolor": "^3.4.0",
|
||||
"@element-plus/icons-vue": "^0.2.4",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.36",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.4",
|
||||
@@ -38,29 +39,27 @@
|
||||
"@vueuse/core": "^6.7.1",
|
||||
"@vueuse/motion": "^2.0.0-beta.4",
|
||||
"animate.css": "^4.1.1",
|
||||
"await-to-js": "^3.0.0",
|
||||
"axios": "^0.21.1",
|
||||
"cropperjs": "^1.5.11",
|
||||
"css-color-function": "^1.3.3",
|
||||
"dayjs": "^1.10.7",
|
||||
"driver.js": "^0.9.8",
|
||||
"echarts": "^5.2.1",
|
||||
"element-plus": "1.2.0-beta.6",
|
||||
"element-plus": "1.3.0-beta.1",
|
||||
"element-resize-detector": "^1.2.3",
|
||||
"font-awesome": "^4.7.0",
|
||||
"js-cookie": "^3.0.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lowdb": "^3.0.0",
|
||||
"mitt": "^3.0.0",
|
||||
"mockjs": "^1.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"path": "^0.12.7",
|
||||
"path-to-regexp": "^6.2.0",
|
||||
"pinia": "^2.0.0-rc.14",
|
||||
"qs": "^6.10.1",
|
||||
"remixicon": "^2.5.0",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"responsive-storage": "^1.0.11",
|
||||
"sortablejs": "1.13.0",
|
||||
"typescript-cookie": "^1.0.0",
|
||||
"rgb-hex": "^4.0.0",
|
||||
"v-contextmenu": "3.0.0",
|
||||
"vue": "^3.2.24",
|
||||
"vue-i18n": "^9.2.0-beta.3",
|
||||
@@ -68,10 +67,9 @@
|
||||
"vue-router": "^4.0.12",
|
||||
"vue-types": "^4.1.0",
|
||||
"vuedraggable": "4.1.0",
|
||||
"vxe-table": "4.0.30",
|
||||
"vxe-table": "^4.1.18",
|
||||
"wangeditor": "^4.7.9",
|
||||
"xe-ajax": "4.0.5",
|
||||
"xe-utils": "3.4.0",
|
||||
"xe-utils": "^3.5.2",
|
||||
"xgplayer": "2.28.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -94,7 +92,6 @@
|
||||
"@zougt/vite-plugin-theme-preprocessor": "^1.4.0",
|
||||
"autoprefixer": "10.2.4",
|
||||
"babel-plugin-transform-remove-console": "6.9.4",
|
||||
"chalk": "2.4.2",
|
||||
"cross-env": "7.0.3",
|
||||
"eslint": "7.30.0",
|
||||
"eslint-plugin-prettier": "3.4.0",
|
||||
|
||||
183
pnpm-lock.yaml
generated
183
pnpm-lock.yaml
generated
@@ -4,6 +4,7 @@ specifiers:
|
||||
"@amap/amap-jsapi-loader": ^1.0.1
|
||||
"@commitlint/cli": 13.1.0
|
||||
"@commitlint/config-conventional": 13.1.0
|
||||
"@ctrl/tinycolor": ^3.4.0
|
||||
"@element-plus/icons-vue": ^0.2.4
|
||||
"@fortawesome/fontawesome-svg-core": ^1.2.36
|
||||
"@fortawesome/free-solid-svg-icons": ^5.15.4
|
||||
@@ -29,15 +30,15 @@ specifiers:
|
||||
"@zougt/vite-plugin-theme-preprocessor": ^1.4.0
|
||||
animate.css: ^4.1.1
|
||||
autoprefixer: 10.2.4
|
||||
await-to-js: ^3.0.0
|
||||
axios: ^0.21.1
|
||||
babel-plugin-transform-remove-console: 6.9.4
|
||||
chalk: 2.4.2
|
||||
cropperjs: ^1.5.11
|
||||
cross-env: 7.0.3
|
||||
css-color-function: ^1.3.3
|
||||
dayjs: ^1.10.7
|
||||
driver.js: ^0.9.8
|
||||
echarts: ^5.2.1
|
||||
element-plus: 1.2.0-beta.6
|
||||
element-plus: 1.3.0-beta.1
|
||||
element-resize-detector: ^1.2.3
|
||||
eslint: 7.30.0
|
||||
eslint-plugin-prettier: 3.4.0
|
||||
@@ -47,12 +48,10 @@ specifiers:
|
||||
js-cookie: ^3.0.1
|
||||
lint-staged: 11.1.2
|
||||
lodash-es: ^4.17.21
|
||||
lowdb: ^3.0.0
|
||||
mitt: ^3.0.0
|
||||
mockjs: ^1.1.0
|
||||
nprogress: ^0.2.0
|
||||
path: ^0.12.7
|
||||
path-to-regexp: ^6.2.0
|
||||
pinia: ^2.0.0-rc.14
|
||||
postcss: 8.2.6
|
||||
postcss-import: 14.0.0
|
||||
@@ -62,16 +61,15 @@ specifiers:
|
||||
remixicon: ^2.5.0
|
||||
resize-observer-polyfill: ^1.5.1
|
||||
responsive-storage: ^1.0.11
|
||||
rgb-hex: ^4.0.0
|
||||
rimraf: 3.0.2
|
||||
sass: ^1.45.0
|
||||
sass-loader: ^12.3.0
|
||||
sortablejs: 1.13.0
|
||||
stylelint: 13.13.1
|
||||
stylelint-config-prettier: 8.0.2
|
||||
stylelint-config-standard: 22.0.0
|
||||
stylelint-order: 4.1.0
|
||||
typescript: 4.4.2
|
||||
typescript-cookie: ^1.0.0
|
||||
unplugin-element-plus: ^0.1.3
|
||||
v-contextmenu: 3.0.0
|
||||
vite: 2.6.14
|
||||
@@ -85,14 +83,14 @@ specifiers:
|
||||
vue-router: ^4.0.12
|
||||
vue-types: ^4.1.0
|
||||
vuedraggable: 4.1.0
|
||||
vxe-table: 4.0.30
|
||||
vxe-table: ^4.1.18
|
||||
wangeditor: ^4.7.9
|
||||
xe-ajax: 4.0.5
|
||||
xe-utils: 3.4.0
|
||||
xe-utils: ^3.5.2
|
||||
xgplayer: 2.28.0
|
||||
|
||||
dependencies:
|
||||
"@amap/amap-jsapi-loader": 1.0.1
|
||||
"@ctrl/tinycolor": 3.4.0
|
||||
"@element-plus/icons-vue": 0.2.4_vue@3.2.24
|
||||
"@fortawesome/fontawesome-svg-core": 1.2.36
|
||||
"@fortawesome/free-solid-svg-icons": 5.15.4
|
||||
@@ -102,29 +100,27 @@ dependencies:
|
||||
"@vueuse/core": 6.7.5_vue@3.2.24
|
||||
"@vueuse/motion": 2.0.0-beta.4_vue@3.2.24
|
||||
animate.css: 4.1.1
|
||||
await-to-js: 3.0.0
|
||||
axios: 0.21.4
|
||||
cropperjs: 1.5.12
|
||||
css-color-function: 1.3.3
|
||||
dayjs: 1.10.7
|
||||
driver.js: 0.9.8
|
||||
echarts: 5.2.2
|
||||
element-plus: 1.2.0-beta.6_vue@3.2.24
|
||||
element-plus: 1.3.0-beta.1_vue@3.2.24
|
||||
element-resize-detector: 1.2.3
|
||||
font-awesome: 4.7.0
|
||||
js-cookie: 3.0.1
|
||||
lodash-es: 4.17.21
|
||||
lowdb: 3.0.0
|
||||
mitt: 3.0.0
|
||||
mockjs: 1.1.0
|
||||
nprogress: 0.2.0
|
||||
path: 0.12.7
|
||||
path-to-regexp: 6.2.0
|
||||
pinia: 2.0.2_typescript@4.4.2+vue@3.2.24
|
||||
qs: 6.10.1
|
||||
remixicon: 2.5.0
|
||||
resize-observer-polyfill: 1.5.1
|
||||
responsive-storage: 1.0.11_vue@3.2.24
|
||||
sortablejs: 1.13.0
|
||||
typescript-cookie: 1.0.0
|
||||
rgb-hex: 4.0.0
|
||||
v-contextmenu: 3.0.0_vue@3.2.24
|
||||
vue: 3.2.24
|
||||
vue-i18n: 9.2.0-beta.17_vue@3.2.24
|
||||
@@ -132,10 +128,9 @@ dependencies:
|
||||
vue-router: 4.0.12_vue@3.2.24
|
||||
vue-types: 4.1.1_vue@3.2.24
|
||||
vuedraggable: 4.1.0_vue@3.2.24
|
||||
vxe-table: 4.0.30_vue@3.2.24+xe-utils@3.4.0
|
||||
vxe-table: 4.1.18_vue@3.2.24+xe-utils@3.5.2
|
||||
wangeditor: 4.7.9
|
||||
xe-ajax: 4.0.5
|
||||
xe-utils: 3.4.0
|
||||
xe-utils: 3.5.2
|
||||
xgplayer: 2.28.0
|
||||
|
||||
devDependencies:
|
||||
@@ -158,7 +153,6 @@ devDependencies:
|
||||
"@zougt/vite-plugin-theme-preprocessor": 1.4.0_sass@1.45.0
|
||||
autoprefixer: 10.2.4_postcss@8.2.6
|
||||
babel-plugin-transform-remove-console: 6.9.4
|
||||
chalk: 2.4.2
|
||||
cross-env: 7.0.3
|
||||
eslint: 7.30.0
|
||||
eslint-plugin-prettier: 3.4.0_eslint@7.30.0+prettier@2.3.2
|
||||
@@ -793,6 +787,14 @@ packages:
|
||||
chalk: 4.1.2
|
||||
dev: true
|
||||
|
||||
/@ctrl/tinycolor/3.4.0:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-JZButFdZ1+/xAfpguQHoabIXkcqRRKpMrWKBkpEZZyxfY9C1DpADFB8PEqGSTeFr135SaTRfKqGKx5xSCLI7ZQ==
|
||||
}
|
||||
engines: { node: ">=10" }
|
||||
dev: false
|
||||
|
||||
/@element-plus/icons-vue/0.2.4_vue@3.2.24:
|
||||
resolution:
|
||||
{
|
||||
@@ -1594,10 +1596,10 @@ packages:
|
||||
vue-demi: 0.12.1_vue@3.2.24
|
||||
dev: false
|
||||
|
||||
/@vueuse/core/7.2.2_vue@3.2.24:
|
||||
/@vueuse/core/7.4.3_vue@3.2.24:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-T9oksrPflNhsgG/Y/7IeCSmITPZ0VKDnTpK8y7SQl4ZIdLIL8L7fJyhJEgSMWyo497j/XK3RKFkOTh4GFTVeIQ==
|
||||
integrity: sha512-OflPLlQ7eqaDJgKYw9DpRCbtfpkFkg1EqHFq7CFrbIEElB39wIfB9ccNypCar8e5KRDrAbOJLIOOvDZO6aC2Gg==
|
||||
}
|
||||
peerDependencies:
|
||||
"@vue/composition-api": ^1.1.0
|
||||
@@ -1608,7 +1610,7 @@ packages:
|
||||
vue:
|
||||
optional: true
|
||||
dependencies:
|
||||
"@vueuse/shared": 7.2.2_vue@3.2.24
|
||||
"@vueuse/shared": 7.4.3_vue@3.2.24
|
||||
vue: 3.2.24
|
||||
vue-demi: 0.12.1_vue@3.2.24
|
||||
dev: false
|
||||
@@ -1649,10 +1651,10 @@ packages:
|
||||
vue-demi: 0.12.1_vue@3.2.24
|
||||
dev: false
|
||||
|
||||
/@vueuse/shared/7.2.2_vue@3.2.24:
|
||||
/@vueuse/shared/7.4.3_vue@3.2.24:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-9vevEvvQgx4snSrDfZ5BFd7FmlIl9rwTtr8ySzPZhZQslx6lbcsXK3Q97I06Fv8S2TedR//X9fn2QbNtbFmdog==
|
||||
integrity: sha512-tNOCbpD3uZyzxNuw2GX5LTVkMB//IZ7GS452F7TwlY07aIoGjPgixi2Yfk/xSR4CcC9iU56zprZW33aEGj1O1Q==
|
||||
}
|
||||
peerDependencies:
|
||||
"@vue/composition-api": ^1.1.0
|
||||
@@ -1943,14 +1945,6 @@ packages:
|
||||
postcss-value-parser: 4.1.0
|
||||
dev: true
|
||||
|
||||
/await-to-js/3.0.0:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==
|
||||
}
|
||||
engines: { node: ">=6.0.0" }
|
||||
dev: false
|
||||
|
||||
/axios/0.21.4:
|
||||
resolution:
|
||||
{
|
||||
@@ -1973,6 +1967,10 @@ packages:
|
||||
}
|
||||
dev: true
|
||||
|
||||
/balanced-match/0.1.0:
|
||||
resolution: { integrity: sha1-tQS9BYabOSWd0MXvw12EMXbczEo= }
|
||||
dev: false
|
||||
|
||||
/balanced-match/1.0.2:
|
||||
resolution:
|
||||
{
|
||||
@@ -2297,6 +2295,11 @@ packages:
|
||||
is-regexp: 2.1.0
|
||||
dev: true
|
||||
|
||||
/clone/1.0.4:
|
||||
resolution: { integrity: sha1-2jCcwmPfFZlMaIypAheco8fNfH4= }
|
||||
engines: { node: ">=0.8" }
|
||||
dev: false
|
||||
|
||||
/clone/2.1.2:
|
||||
resolution: { integrity: sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= }
|
||||
engines: { node: ">=0.8" }
|
||||
@@ -2328,7 +2331,12 @@ packages:
|
||||
{
|
||||
integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
}
|
||||
dev: true
|
||||
|
||||
/color-string/0.3.0:
|
||||
resolution: { integrity: sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE= }
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
dev: false
|
||||
|
||||
/color-string/1.9.0:
|
||||
resolution:
|
||||
@@ -2340,6 +2348,14 @@ packages:
|
||||
simple-swizzle: 0.2.2
|
||||
dev: true
|
||||
|
||||
/color/0.11.4:
|
||||
resolution: { integrity: sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q= }
|
||||
dependencies:
|
||||
clone: 1.0.4
|
||||
color-convert: 1.9.3
|
||||
color-string: 0.3.0
|
||||
dev: false
|
||||
|
||||
/color/4.1.0:
|
||||
resolution:
|
||||
{
|
||||
@@ -2547,6 +2563,15 @@ packages:
|
||||
which: 2.0.2
|
||||
dev: true
|
||||
|
||||
/css-color-function/1.3.3:
|
||||
resolution: { integrity: sha1-jtJMLAIFBzM5+voAS8jBQfzLKC4= }
|
||||
dependencies:
|
||||
balanced-match: 0.1.0
|
||||
color: 0.11.4
|
||||
debug: 3.2.7
|
||||
rgb: 0.1.0
|
||||
dev: false
|
||||
|
||||
/css-declaration-sorter/6.1.3_postcss@8.3.11:
|
||||
resolution:
|
||||
{
|
||||
@@ -2746,6 +2771,15 @@ packages:
|
||||
ms: 2.0.0
|
||||
dev: true
|
||||
|
||||
/debug/3.2.7:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
|
||||
}
|
||||
dependencies:
|
||||
ms: 2.1.2
|
||||
dev: false
|
||||
|
||||
/debug/4.3.2:
|
||||
resolution:
|
||||
{
|
||||
@@ -2926,6 +2960,13 @@ packages:
|
||||
unidragger: 2.3.1
|
||||
dev: false
|
||||
|
||||
/driver.js/0.9.8:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-bczjyKdX6XmFyCDkwtRmlaORDwfBk1xXmRO0CAe5VwNQTM98aWaG2LAIiIdTe53iV/B7W5lXlIy2xYtf0JRb7Q==
|
||||
}
|
||||
dev: false
|
||||
|
||||
/echarts/5.2.2:
|
||||
resolution:
|
||||
{
|
||||
@@ -2947,17 +2988,18 @@ packages:
|
||||
}
|
||||
dev: true
|
||||
|
||||
/element-plus/1.2.0-beta.6_vue@3.2.24:
|
||||
/element-plus/1.3.0-beta.1_vue@3.2.24:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-8EdSIR/5/FHcSB8w1diAh+gJMHgxIvxuZoayY99k6taAR1QyEFHuPTgFccZLopJ1+iP4UEsZFz49l57qS08Utw==
|
||||
integrity: sha512-q3vMaKElPpuSTeIF7kuDmMOE+N1YVCCIG3fshXpz6qgjnxPbgZumVM0qGfhr8DTu9JxRbBoDok49dqtX/BWn3w==
|
||||
}
|
||||
peerDependencies:
|
||||
vue: ^3.2.0
|
||||
dependencies:
|
||||
"@ctrl/tinycolor": 3.4.0
|
||||
"@element-plus/icons-vue": 0.2.4_vue@3.2.24
|
||||
"@popperjs/core": 2.11.0
|
||||
"@vueuse/core": 7.2.2_vue@3.2.24
|
||||
"@vueuse/core": 7.4.3_vue@3.2.24
|
||||
async-validator: 4.0.7
|
||||
dayjs: 1.10.7
|
||||
lodash: 4.17.21
|
||||
@@ -4738,16 +4780,6 @@ packages:
|
||||
}
|
||||
dev: true
|
||||
|
||||
/lowdb/3.0.0:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-9KZRulmIcU8fZuWiaM0d5e2/nPnrFyXkeXVpqT+MJS+vgbgOf1EbtvgQmba8HwUFgDl1oeZR6XqEJnkJmQdKmg==
|
||||
}
|
||||
engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 }
|
||||
dependencies:
|
||||
steno: 2.1.0
|
||||
dev: false
|
||||
|
||||
/lower-case/2.0.2:
|
||||
resolution:
|
||||
{
|
||||
@@ -5016,7 +5048,6 @@ packages:
|
||||
{
|
||||
integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
}
|
||||
dev: true
|
||||
|
||||
/multimatch/4.0.0:
|
||||
resolution:
|
||||
@@ -5367,6 +5398,7 @@ packages:
|
||||
{
|
||||
integrity: sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==
|
||||
}
|
||||
dev: true
|
||||
|
||||
/path-type/4.0.0:
|
||||
resolution:
|
||||
@@ -6310,6 +6342,19 @@ packages:
|
||||
engines: { iojs: ">=1.0.0", node: ">=0.10.0" }
|
||||
dev: true
|
||||
|
||||
/rgb-hex/4.0.0:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-Eg2ev5CiMBnQ9Gpflmqbwbso0CCdISqtVIow7OpYSLN1ULUv2jTB9YieS1DSSn/17AD7KkPWDPzSFzI4GSuu/Q==
|
||||
}
|
||||
engines: { node: ">=12" }
|
||||
dev: false
|
||||
|
||||
/rgb/0.1.0:
|
||||
resolution: { integrity: sha1-vieykej+/+rBvZlylyG/pA/AN7U= }
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/rimraf/3.0.2:
|
||||
resolution:
|
||||
{
|
||||
@@ -6526,13 +6571,6 @@ packages:
|
||||
tslib: 2.3.1
|
||||
dev: true
|
||||
|
||||
/sortablejs/1.13.0:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-RBJirPY0spWCrU5yCmWM1eFs/XgX2J5c6b275/YyxFRgnzPhKl/TDeU2hNR8Dt7ITq66NRPM4UlOt+e5O4CFHg==
|
||||
}
|
||||
dev: false
|
||||
|
||||
/sortablejs/1.14.0:
|
||||
resolution:
|
||||
{
|
||||
@@ -6649,14 +6687,6 @@ packages:
|
||||
engines: { node: ">= 0.6" }
|
||||
dev: true
|
||||
|
||||
/steno/2.1.0:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-mauOsiaqTNGFkWqIfwcm3y/fq+qKKaIWf1vf3ocOuTdco9XoHCO2AGF1gFYXuZFSWuP38Q8LBHBGJv2KnJSXyA==
|
||||
}
|
||||
engines: { node: ^14.13.1 || >=16.0.0 }
|
||||
dev: false
|
||||
|
||||
/string-argv/0.3.1:
|
||||
resolution:
|
||||
{
|
||||
@@ -7138,14 +7168,6 @@ packages:
|
||||
is-typedarray: 1.0.0
|
||||
dev: true
|
||||
|
||||
/typescript-cookie/1.0.0:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-oYHAgQWDqheZXiq1ODzVwwl+8lGzK/ApsxAu1a4uyl+Yd9BuF0M5I3bowgb5oAlU3Qyqejcj5kDyOZe+y+W4SA==
|
||||
}
|
||||
engines: { node: ">=14" }
|
||||
dev: false
|
||||
|
||||
/typescript/4.4.2:
|
||||
resolution:
|
||||
{
|
||||
@@ -7585,17 +7607,17 @@ packages:
|
||||
vue: 3.2.24
|
||||
dev: false
|
||||
|
||||
/vxe-table/4.0.30_vue@3.2.24+xe-utils@3.4.0:
|
||||
/vxe-table/4.1.18_vue@3.2.24+xe-utils@3.5.2:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-sHUJL+XazADSTJlAZDwIAVeOMB3hBSj+5IeAUKHH+eKmSYju+l31og7NbgYsgRVTpG959F9EpUOnMMXvWptq/w==
|
||||
integrity: sha512-hiaJv45rl8swU8YrtZVM7UhVMCrlkhxnZKuyjM1zcFhSNhuQWIy7KkewZctk83foAxlTBjEzwGNsXDuWjBW3vQ==
|
||||
}
|
||||
peerDependencies:
|
||||
vue: ^3.2.2
|
||||
xe-utils: ^3.2.0
|
||||
xe-utils: ^3.5.0
|
||||
dependencies:
|
||||
vue: 3.2.24
|
||||
xe-utils: 3.4.0
|
||||
xe-utils: 3.5.2
|
||||
dev: false
|
||||
|
||||
/wangeditor/4.7.9:
|
||||
@@ -7685,17 +7707,10 @@ packages:
|
||||
typedarray-to-buffer: 3.1.5
|
||||
dev: true
|
||||
|
||||
/xe-ajax/4.0.5:
|
||||
/xe-utils/3.5.2:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-SlVaSfOyBH2Dy51zevNbTIY1EcRlIjoP25YXcN+l9gYfl1rsQ68EsVPD6gw47sM/zzQhiPvqmzM4RzOUggbgaw==
|
||||
}
|
||||
dev: false
|
||||
|
||||
/xe-utils/3.4.0:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-V2o/Ew/iXBduWbj0ixqA7atUe4HFxo0HcpBsxnrLHbKVspfZ2O/7+m325AHcN2xxPZtBZGQVg1w/cQ5Q8WmcTA==
|
||||
integrity: sha512-TIQct9Ed43O5J0YYRMmD15KHKUzGIW+Hetv9/diEMHT5YQVr0csC0FCFOfSgsIcuamziPVAWNFLl1QKYJE2oxA==
|
||||
}
|
||||
dev: false
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"Version": "2.7.0",
|
||||
"Version": "2.8.0",
|
||||
"Title": "PureAdmin",
|
||||
"FixedHeader": true,
|
||||
"HiddenSideBar": false,
|
||||
@@ -8,9 +8,14 @@
|
||||
"Locale": "zh",
|
||||
"Layout": "vertical",
|
||||
"Theme": "default",
|
||||
"DarkMode": false,
|
||||
"Grey": false,
|
||||
"Weak": false,
|
||||
"HideTabs": false,
|
||||
"SidebarStatus": true,
|
||||
"EpThemeColor": "#409EFF",
|
||||
"ShowLogo": true,
|
||||
"ShowModel": "smart",
|
||||
"MapConfigure": {
|
||||
"amapKey": "97b3248d1553172e81f168cf94ea667e",
|
||||
"options": {
|
||||
|
||||
1
src/assets/svg/dark.svg
Normal file
1
src/assets/svg/dark.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.38 2.019a7.5 7.5 0 1 0 10.6 10.6C21.662 17.854 17.316 22 12.001 22 6.477 22 2 17.523 2 12c0-5.315 4.146-9.661 9.38-9.981z"/></svg>
|
||||
|
After Width: | Height: | Size: 263 B |
1
src/assets/svg/day.svg
Normal file
1
src/assets/svg/day.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></svg>
|
||||
|
After Width: | Height: | Size: 480 B |
@@ -12,8 +12,15 @@ import { useEventListener, tryOnUnmounted, useTimeoutFn } from "@vueuse/core";
|
||||
|
||||
let echartInstance: ECharts;
|
||||
|
||||
const props = defineProps({
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
});
|
||||
|
||||
function initechartInstance() {
|
||||
const echartDom = document.querySelector(".bar");
|
||||
const echartDom = document.querySelector(".bar" + props.index);
|
||||
if (!echartDom) return;
|
||||
// @ts-ignore
|
||||
echartInstance = echarts.init(echartDom);
|
||||
@@ -85,12 +92,5 @@ tryOnUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bar"></div>
|
||||
<div :class="'bar' + props.index" style="width: 100%; height: 35vh"></div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.bar {
|
||||
width: 100%;
|
||||
height: 35vh;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -10,52 +10,40 @@ const lists = ref([
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-descriptions
|
||||
class="margin-top"
|
||||
direction="vertical"
|
||||
:column="3"
|
||||
size="medium"
|
||||
border
|
||||
>
|
||||
<el-descriptions class="margin-top" direction="vertical" :column="3" border>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<i class="el-icon-user"></i>
|
||||
<el-icon><user /></el-icon>
|
||||
用户名
|
||||
</template>
|
||||
xiaoxian
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<i class="el-icon-mobile-phone"></i>
|
||||
<el-icon><iphone /></el-icon>
|
||||
手机号
|
||||
</template>
|
||||
123456789
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<i class="el-icon-location-outline"></i>
|
||||
<el-icon><location /></el-icon>
|
||||
居住地
|
||||
</template>
|
||||
上海
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions
|
||||
class="margin-top"
|
||||
direction="vertical"
|
||||
:column="2"
|
||||
size="medium"
|
||||
border
|
||||
>
|
||||
<el-descriptions class="margin-top" direction="vertical" :column="2" border>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<i class="el-icon-tickets"></i>
|
||||
<el-icon><tickets /></el-icon>
|
||||
标签
|
||||
</template>
|
||||
<el-tag
|
||||
v-for="item in lists"
|
||||
:key="item.label"
|
||||
:type="item.type"
|
||||
size="mini"
|
||||
size="small"
|
||||
effect="dark"
|
||||
>
|
||||
{{ item.label }}
|
||||
@@ -63,22 +51,16 @@ const lists = ref([
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<i class="el-icon-office-building"></i>
|
||||
<el-icon><office-building /></el-icon>
|
||||
联系地址
|
||||
</template>
|
||||
上海市徐汇区
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions
|
||||
class="margin-top"
|
||||
direction="vertical"
|
||||
:column="1"
|
||||
size="medium"
|
||||
border
|
||||
>
|
||||
<el-descriptions class="margin-top" direction="vertical" :column="1" border>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<i class="el-icon-notebook-1"></i>
|
||||
<el-icon><notebook /></el-icon>
|
||||
留言
|
||||
</template>
|
||||
好好学习,天天向上
|
||||
@@ -87,7 +69,7 @@ const lists = ref([
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.el-tag--mini {
|
||||
.el-tag {
|
||||
margin-right: 10px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -12,8 +12,15 @@ import { useEventListener, tryOnUnmounted, useTimeoutFn } from "@vueuse/core";
|
||||
|
||||
let echartInstance: ECharts;
|
||||
|
||||
const props = defineProps({
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
});
|
||||
|
||||
function initechartInstance() {
|
||||
const echartDom = document.querySelector(".line");
|
||||
const echartDom = document.querySelector(".line" + props.index);
|
||||
if (!echartDom) return;
|
||||
// @ts-ignore
|
||||
echartInstance = echarts.init(echartDom);
|
||||
@@ -73,12 +80,5 @@ tryOnUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="line"></div>
|
||||
<div :class="'line' + props.index" style="width: 100%; height: 35vh"></div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.line {
|
||||
width: 100%;
|
||||
height: 35vh;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -12,8 +12,15 @@ import { useEventListener, tryOnUnmounted, useTimeoutFn } from "@vueuse/core";
|
||||
|
||||
let echartInstance: ECharts;
|
||||
|
||||
const props = defineProps({
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
});
|
||||
|
||||
function initechartInstance() {
|
||||
const echartDom = document.querySelector(".pie");
|
||||
const echartDom = document.querySelector(".pie" + props.index);
|
||||
if (!echartDom) return;
|
||||
// @ts-ignore
|
||||
echartInstance = echarts.init(echartDom);
|
||||
@@ -76,12 +83,5 @@ tryOnUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="pie"></div>
|
||||
<div :class="'pie' + props.index" style="width: 100%; height: 35vh"></div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.pie {
|
||||
width: 100%;
|
||||
height: 35vh;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -9,20 +9,24 @@ import { iconComponents } from "/@/plugins/element-plus";
|
||||
* @returns component
|
||||
*/
|
||||
export function findIconReg(icon: string) {
|
||||
// fontawesome
|
||||
const faReg = /^FA-/;
|
||||
// fontawesome4
|
||||
const fa4Reg = /^fa-/;
|
||||
// fontawesome5+
|
||||
const fa5Reg = /^FA-/;
|
||||
// iconfont
|
||||
const iFReg = /^IF-/;
|
||||
// remixicon
|
||||
const riReg = /^RI-/;
|
||||
// typeof icon === "function" 属于SVG
|
||||
if (faReg.test(icon)) {
|
||||
const text = icon.split(faReg)[1];
|
||||
if (fa5Reg.test(icon)) {
|
||||
const text = icon.split(fa5Reg)[1];
|
||||
return findIcon(
|
||||
text.slice(0, text.indexOf(" ")),
|
||||
text.slice(0, text.indexOf(" ") == -1 ? text.length : text.indexOf(" ")),
|
||||
"FA",
|
||||
text.slice(text.indexOf(" ") + 1, text.length)
|
||||
);
|
||||
} else if (fa4Reg.test(icon)) {
|
||||
return findIcon(icon.split(fa4Reg)[1], "fa");
|
||||
} else if (iFReg.test(icon)) {
|
||||
return findIcon(icon.split(iFReg)[1], "IF");
|
||||
} else if (typeof icon === "function") {
|
||||
@@ -45,6 +49,14 @@ export function findIcon(icon: String, type = "EL", property?: string) {
|
||||
components: { FontAwesomeIcon },
|
||||
template: `<font-awesome-icon :icon="icon" v-bind:[property]="true" />`
|
||||
});
|
||||
} else if (type === "fa") {
|
||||
return defineComponent({
|
||||
name: "faIcon",
|
||||
data() {
|
||||
return { icon: `fa ${icon}` };
|
||||
},
|
||||
template: `<i :class="icon" />`
|
||||
});
|
||||
} else if (type === "IF") {
|
||||
return defineComponent({
|
||||
name: "IfIcon",
|
||||
|
||||
@@ -27,12 +27,23 @@ const transitions = computed(() => {
|
||||
});
|
||||
|
||||
const hideTabs = computed(() => {
|
||||
return instance?.sets.hideTabs;
|
||||
return instance?.configure.hideTabs;
|
||||
});
|
||||
|
||||
const layout = computed(() => {
|
||||
return instance?.layout.layout === "vertical";
|
||||
});
|
||||
|
||||
const getSectionStyle = computed(() => {
|
||||
return [
|
||||
hideTabs.value && layout ? "padding-top: 48px;" : "",
|
||||
!hideTabs.value && layout ? "padding-top: 85px;" : "",
|
||||
hideTabs.value && !layout.value ? "padding-top: 48px" : "",
|
||||
!hideTabs.value && !layout.value ? "padding-top: 85px;" : "",
|
||||
props.fixedHeader ? "" : "padding-top: 0;"
|
||||
];
|
||||
});
|
||||
|
||||
const transitionMain = defineComponent({
|
||||
render() {
|
||||
return h(
|
||||
@@ -71,12 +82,7 @@ const transitionMain = defineComponent({
|
||||
<template>
|
||||
<section
|
||||
:class="[props.fixedHeader ? 'app-main' : 'app-main-nofixed-header']"
|
||||
:style="[
|
||||
hideTabs && layout ? 'padding-top: 48px;' : '',
|
||||
!hideTabs && layout ? 'padding-top: 85px;' : '',
|
||||
hideTabs && !layout ? 'padding-top: 48px' : '',
|
||||
!hideTabs && !layout ? 'padding-top: 85px;' : ''
|
||||
]"
|
||||
:style="getSectionStyle"
|
||||
>
|
||||
<router-view>
|
||||
<template #default="{ Component, route }">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { emitter } from "/@/utils/mitt";
|
||||
import Notice from "./notice/index.vue";
|
||||
@@ -22,6 +23,15 @@ const route = useRoute();
|
||||
let usename = storageSession.getItem("info")?.username;
|
||||
const { locale } = useI18n();
|
||||
|
||||
const getDropdownItemStyle = computed(() => {
|
||||
return t => {
|
||||
return {
|
||||
background: locale.value === t ? "#1b2a47" : "",
|
||||
color: locale.value === t ? "#f4f4f5" : "#000"
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
watch(
|
||||
() => locale.value,
|
||||
() => {
|
||||
@@ -73,29 +83,23 @@ function translationEn() {
|
||||
|
||||
<div class="vertical-header-right">
|
||||
<!-- 通知 -->
|
||||
<Notice />
|
||||
<Notice id="header-notice" />
|
||||
<!-- 全屏 -->
|
||||
<screenfull v-show="!deviceDetection()" />
|
||||
<screenfull id="header-screenfull" v-show="!deviceDetection()" />
|
||||
<!-- 国际化 -->
|
||||
<el-dropdown trigger="click">
|
||||
<el-dropdown id="header-translation" trigger="click">
|
||||
<globalization />
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu class="translation">
|
||||
<el-dropdown-item
|
||||
:style="{
|
||||
background: locale === 'zh' ? '#1b2a47' : '',
|
||||
color: locale === 'zh' ? '#f4f4f5' : '#000'
|
||||
}"
|
||||
:style="getDropdownItemStyle('zh')"
|
||||
@click="translationCh"
|
||||
><el-icon class="check-zh" v-show="locale === 'zh'"
|
||||
><check /></el-icon
|
||||
>简体中文</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item
|
||||
:style="{
|
||||
background: locale === 'en' ? '#1b2a47' : '',
|
||||
color: locale === 'en' ? '#f4f4f5' : '#000'
|
||||
}"
|
||||
:style="getDropdownItemStyle('en')"
|
||||
@click="translationEn"
|
||||
><el-icon class="check-en" v-show="locale === 'en'"
|
||||
><check /></el-icon
|
||||
@@ -114,14 +118,14 @@ function translationEn() {
|
||||
<el-dropdown-menu class="logout">
|
||||
<el-dropdown-item @click="logout">
|
||||
<i class="ri-logout-circle-r-line"></i
|
||||
>{{ $t("message.hsLoginOut") }}</el-dropdown-item
|
||||
>{{ $t("buttons.hsLoginOut") }}</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<el-icon
|
||||
class="el-icon-setting"
|
||||
:title="$t('message.hssystemSet')"
|
||||
:title="$t('buttons.hssystemSet')"
|
||||
@click="onPanel"
|
||||
>
|
||||
<Setting />
|
||||
@@ -230,7 +234,7 @@ function translationEn() {
|
||||
|
||||
.translation {
|
||||
.el-dropdown-menu__item {
|
||||
padding: 0 40px !important;
|
||||
padding: 5px 40px !important;
|
||||
}
|
||||
|
||||
.el-dropdown-menu__item:focus,
|
||||
@@ -242,12 +246,10 @@ function translationEn() {
|
||||
.check-zh {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 13px;
|
||||
}
|
||||
|
||||
.check-en {
|
||||
position: absolute;
|
||||
bottom: 13px;
|
||||
left: 20px;
|
||||
}
|
||||
}
|
||||
@@ -259,7 +261,6 @@ function translationEn() {
|
||||
min-width: 100%;
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 18px !important;
|
||||
}
|
||||
|
||||
.el-dropdown-menu__item:focus,
|
||||
|
||||
@@ -8,8 +8,8 @@ const { isFullscreen, toggle } = useFullscreen();
|
||||
<i
|
||||
:title="
|
||||
isFullscreen
|
||||
? $t('message.hsexitfullscreen')
|
||||
: $t('message.hsfullscreen')
|
||||
? $t('buttons.hsexitfullscreen')
|
||||
: $t('buttons.hsfullscreen')
|
||||
"
|
||||
:class="
|
||||
isFullscreen
|
||||
|
||||
@@ -9,20 +9,28 @@ import {
|
||||
useCssModule,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
import panel from "../panel/index.vue";
|
||||
import rgbHex from "rgb-hex";
|
||||
import { find } from "lodash-es";
|
||||
import { getConfig } from "/@/config";
|
||||
import { useRouter } from "vue-router";
|
||||
import panel from "../panel/index.vue";
|
||||
import { emitter } from "/@/utils/mitt";
|
||||
import { templateRef } from "@vueuse/core";
|
||||
import dayIcon from "/@/assets/svg/day.svg";
|
||||
import { debounce } from "/@/utils/debounce";
|
||||
import darkIcon from "/@/assets/svg/dark.svg";
|
||||
import { themeColorsType } from "../../types";
|
||||
import { useAppStoreHook } from "/@/store/modules/app";
|
||||
import { shadeBgColor } from "../../theme/element-plus";
|
||||
import { useEpThemeStoreHook } from "/@/store/modules/epTheme";
|
||||
import { storageLocal, storageSession } from "/@/utils/storage";
|
||||
import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
|
||||
import { createNewStyle, writeNewStyle } from "../../theme/element-plus";
|
||||
import { toggleTheme } from "@zougt/vite-plugin-theme-preprocessor/dist/browser-utils";
|
||||
|
||||
const router = useRouter();
|
||||
const { isSelect } = useCssModule();
|
||||
const body = document.documentElement as HTMLElement;
|
||||
const instance =
|
||||
getCurrentInstance().appContext.app.config.globalProperties.$storage;
|
||||
|
||||
@@ -71,17 +79,33 @@ if (unref(layoutTheme)) {
|
||||
}
|
||||
|
||||
// 默认灵动模式
|
||||
const markValue = ref(storageLocal.getItem("showModel") || "smart");
|
||||
const markValue = ref(instance.configure?.showModel ?? "smart");
|
||||
|
||||
const logoVal = ref(storageLocal.getItem("logoVal") || "1");
|
||||
const logoVal = ref(instance.configure?.showLogo ?? true);
|
||||
|
||||
const epThemeColor = ref(useEpThemeStoreHook().getEpThemeColor);
|
||||
|
||||
const settings = reactive({
|
||||
greyVal: instance.sets.grey,
|
||||
weakVal: instance.sets.weak,
|
||||
tabsVal: instance.sets.hideTabs,
|
||||
multiTagsCache: instance.sets.multiTagsCache
|
||||
greyVal: instance.configure.grey,
|
||||
weakVal: instance.configure.weak,
|
||||
tabsVal: instance.configure.hideTabs,
|
||||
showLogo: instance.configure.showLogo,
|
||||
showModel: instance.configure.showModel,
|
||||
multiTagsCache: instance.configure.multiTagsCache
|
||||
});
|
||||
|
||||
const getThemeColorStyle = computed(() => {
|
||||
return rgb => {
|
||||
return { background: `rgb(${rgb})` };
|
||||
};
|
||||
});
|
||||
|
||||
function changeStorageConfigure(key, val) {
|
||||
const storageConfigure = instance.configure;
|
||||
storageConfigure[key] = val;
|
||||
instance.configure = storageConfigure;
|
||||
}
|
||||
|
||||
function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
|
||||
const targetEl = target || document.body;
|
||||
let { className } = targetEl;
|
||||
@@ -92,12 +116,7 @@ function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
|
||||
// 灰色模式设置
|
||||
const greyChange = (value): void => {
|
||||
toggleClass(settings.greyVal, "html-grey", document.querySelector("html"));
|
||||
instance.sets = {
|
||||
grey: value,
|
||||
weak: instance.sets.weak,
|
||||
hideTabs: instance.sets.hideTabs,
|
||||
multiTagsCache: instance.sets.multiTagsCache
|
||||
};
|
||||
changeStorageConfigure("grey", value);
|
||||
};
|
||||
|
||||
// 色弱模式设置
|
||||
@@ -107,77 +126,58 @@ const weekChange = (value): void => {
|
||||
"html-weakness",
|
||||
document.querySelector("html")
|
||||
);
|
||||
instance.sets = {
|
||||
grey: instance.sets.grey,
|
||||
weak: value,
|
||||
hideTabs: instance.sets.hideTabs,
|
||||
multiTagsCache: instance.sets.multiTagsCache
|
||||
};
|
||||
changeStorageConfigure("weak", value);
|
||||
};
|
||||
|
||||
const tagsChange = () => {
|
||||
let showVal = settings.tabsVal;
|
||||
instance.sets = {
|
||||
grey: instance.sets.grey,
|
||||
weak: instance.sets.weak,
|
||||
hideTabs: showVal,
|
||||
multiTagsCache: instance.sets.multiTagsCache
|
||||
};
|
||||
changeStorageConfigure("hideTabs", showVal);
|
||||
emitter.emit("tagViewsChange", showVal);
|
||||
};
|
||||
|
||||
const multiTagsCacheChange = () => {
|
||||
let multiTagsCache = settings.multiTagsCache;
|
||||
instance.sets = {
|
||||
grey: instance.sets.grey,
|
||||
weak: instance.sets.weak,
|
||||
hideTabs: instance.sets.hideTabs,
|
||||
multiTagsCache: multiTagsCache
|
||||
};
|
||||
changeStorageConfigure("multiTagsCache", multiTagsCache);
|
||||
useMultiTagsStoreHook().multiTagsCacheChange(multiTagsCache);
|
||||
};
|
||||
|
||||
//初始化项目配置
|
||||
nextTick(() => {
|
||||
settings.greyVal &&
|
||||
document.querySelector("html")?.setAttribute("class", "html-grey");
|
||||
settings.weakVal &&
|
||||
document.querySelector("html")?.setAttribute("class", "html-weakness");
|
||||
settings.tabsVal && tagsChange();
|
||||
});
|
||||
|
||||
// 清空缓存并返回登录页
|
||||
function onReset() {
|
||||
storageLocal.clear();
|
||||
storageSession.clear();
|
||||
toggleClass(false, "html-grey", document.querySelector("html"));
|
||||
toggleClass(false, "html-weakness", document.querySelector("html"));
|
||||
toggleClass(getConfig().Grey, "html-grey", document.querySelector("html"));
|
||||
toggleClass(
|
||||
getConfig().Weak,
|
||||
"html-weakness",
|
||||
document.querySelector("html")
|
||||
);
|
||||
useMultiTagsStoreHook().handleTags("equal", [
|
||||
{
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
icon: "el-icon-s-home",
|
||||
title: "menus.hshome",
|
||||
icon: "HomeFilled",
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
}
|
||||
]);
|
||||
useMultiTagsStoreHook().multiTagsCacheChange(getConfig().MultiTagsCache);
|
||||
useEpThemeStoreHook().setEpThemeColor(getConfig().EpThemeColor);
|
||||
storageLocal.clear();
|
||||
storageSession.clear();
|
||||
router.push("/login");
|
||||
}
|
||||
|
||||
function onChange(label) {
|
||||
storageLocal.setItem("showModel", label);
|
||||
changeStorageConfigure("showModel", label);
|
||||
emitter.emit("tagViewsShowModel", label);
|
||||
}
|
||||
|
||||
// 侧边栏Logo
|
||||
function logoChange() {
|
||||
unref(logoVal) === "1"
|
||||
? storageLocal.setItem("logoVal", "1")
|
||||
: storageLocal.setItem("logoVal", "-1");
|
||||
unref(logoVal)
|
||||
? changeStorageConfigure("showLogo", true)
|
||||
: changeStorageConfigure("showLogo", false);
|
||||
emitter.emit("logoChange", unref(logoVal));
|
||||
}
|
||||
|
||||
@@ -223,23 +223,97 @@ const getThemeColor = computed(() => {
|
||||
function setLayoutModel(layout: string) {
|
||||
layoutTheme.value.layout = layout;
|
||||
window.document.body.setAttribute("layout", layout);
|
||||
instance.layout = { layout, theme: layoutTheme.value.theme };
|
||||
instance.layout = {
|
||||
layout,
|
||||
theme: layoutTheme.value.theme,
|
||||
darkMode: instance.layout.darkMode,
|
||||
sidebarStatus: instance.layout.sidebarStatus,
|
||||
epThemeColor: instance.layout.epThemeColor
|
||||
};
|
||||
useAppStoreHook().setLayout(layout);
|
||||
}
|
||||
|
||||
// 存放夜间主题切换前的导航主题色
|
||||
let tempLayoutThemeColor;
|
||||
|
||||
// 设置导航主题色
|
||||
function setLayoutThemeColor(theme: string) {
|
||||
tempLayoutThemeColor = instance.layout.theme;
|
||||
layoutTheme.value.theme = theme;
|
||||
toggleTheme({
|
||||
scopeName: `layout-theme-${theme}`
|
||||
});
|
||||
instance.layout = { layout: useAppStoreHook().layout, theme };
|
||||
instance.layout = {
|
||||
layout: useAppStoreHook().layout,
|
||||
theme,
|
||||
darkMode: dataTheme.value,
|
||||
sidebarStatus: instance.layout.sidebarStatus,
|
||||
epThemeColor: instance.layout.epThemeColor
|
||||
};
|
||||
|
||||
if (theme === "default" || theme === "light") {
|
||||
setEpThemeColor(getConfig().EpThemeColor);
|
||||
} else {
|
||||
const colors = find(themeColors.value, { themeColor: theme });
|
||||
const color = "#" + rgbHex(colors.rgb);
|
||||
setEpThemeColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置ep主题色
|
||||
const setEpThemeColor = (color: string) => {
|
||||
writeNewStyle(createNewStyle(color));
|
||||
useEpThemeStoreHook().setEpThemeColor(color);
|
||||
body.style.setProperty("--el-color-primary-active", shadeBgColor(color));
|
||||
};
|
||||
|
||||
let dataTheme = ref<boolean>(instance.layout.darkMode);
|
||||
|
||||
// 日间、夜间主题切换
|
||||
function dataThemeChange() {
|
||||
if (dataTheme.value) {
|
||||
body.setAttribute("data-theme", "dark");
|
||||
setLayoutThemeColor("light");
|
||||
} else {
|
||||
body.setAttribute("data-theme", "");
|
||||
tempLayoutThemeColor && setLayoutThemeColor(tempLayoutThemeColor);
|
||||
instance.layout = {
|
||||
layout: useAppStoreHook().layout,
|
||||
theme: instance.layout.theme,
|
||||
darkMode: dataTheme.value,
|
||||
sidebarStatus: instance.layout.sidebarStatus,
|
||||
epThemeColor: instance.layout.epThemeColor
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//初始化项目配置
|
||||
nextTick(() => {
|
||||
settings.greyVal &&
|
||||
document.querySelector("html")?.setAttribute("class", "html-grey");
|
||||
settings.weakVal &&
|
||||
document.querySelector("html")?.setAttribute("class", "html-weakness");
|
||||
settings.tabsVal && tagsChange();
|
||||
|
||||
writeNewStyle(createNewStyle(epThemeColor.value));
|
||||
dataThemeChange();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<panel>
|
||||
<el-divider>主题风格</el-divider>
|
||||
<el-divider>主题</el-divider>
|
||||
<el-switch
|
||||
v-model="dataTheme"
|
||||
inline-prompt
|
||||
class="pure-datatheme"
|
||||
:active-icon="dayIcon"
|
||||
:inactive-icon="darkIcon"
|
||||
@change="dataThemeChange"
|
||||
>
|
||||
</el-switch>
|
||||
|
||||
<el-divider>导航栏模式</el-divider>
|
||||
<ul class="pure-theme">
|
||||
<el-tooltip class="item" content="左侧菜单模式" placement="bottom">
|
||||
<li
|
||||
@@ -264,12 +338,12 @@ function setLayoutThemeColor(theme: string) {
|
||||
</el-tooltip>
|
||||
</ul>
|
||||
|
||||
<el-divider>主题色</el-divider>
|
||||
<ul class="theme-color">
|
||||
<el-divider v-show="!dataTheme">主题色</el-divider>
|
||||
<ul class="theme-color" v-show="!dataTheme">
|
||||
<li
|
||||
v-for="(item, index) in themeColors"
|
||||
:key="index"
|
||||
:style="{ background: `rgb(${item.rgb})` }"
|
||||
:style="getThemeColorStyle(item.rgb)"
|
||||
@click="setLayoutThemeColor(item.themeColor)"
|
||||
>
|
||||
<el-icon
|
||||
@@ -284,7 +358,7 @@ function setLayoutThemeColor(theme: string) {
|
||||
|
||||
<el-divider>界面显示</el-divider>
|
||||
<ul class="setting">
|
||||
<li>
|
||||
<li v-show="!dataTheme">
|
||||
<span>灰色模式</span>
|
||||
<el-switch
|
||||
v-model="settings.greyVal"
|
||||
@@ -296,7 +370,7 @@ function setLayoutThemeColor(theme: string) {
|
||||
>
|
||||
</el-switch>
|
||||
</li>
|
||||
<li>
|
||||
<li v-show="!dataTheme">
|
||||
<span>色弱模式</span>
|
||||
<el-switch
|
||||
v-model="settings.weakVal"
|
||||
@@ -325,8 +399,8 @@ function setLayoutThemeColor(theme: string) {
|
||||
<el-switch
|
||||
v-model="logoVal"
|
||||
inline-prompt
|
||||
active-value="1"
|
||||
inactive-value="-1"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
inactive-color="#a6a6a6"
|
||||
active-text="开"
|
||||
inactive-text="关"
|
||||
@@ -391,6 +465,14 @@ function setLayoutThemeColor(theme: string) {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.pure-datatheme {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
text-align: center;
|
||||
display: block;
|
||||
padding-top: 25px;
|
||||
}
|
||||
|
||||
.pure-theme {
|
||||
margin-top: 25px;
|
||||
width: 100%;
|
||||
|
||||
@@ -65,7 +65,7 @@ const getBreadcrumb = (): void => {
|
||||
{
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: { title: "message.hshome", i18n: true }
|
||||
meta: { title: "menus.hshome", i18n: true }
|
||||
} as unknown as RouteLocationMatched
|
||||
].concat(matched);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,15 @@ const routers = useRouter().options.routes;
|
||||
let usename = storageSession.getItem("info")?.username;
|
||||
const { locale, t } = useI18n();
|
||||
|
||||
const getDropdownItemStyle = computed(() => {
|
||||
return t => {
|
||||
return {
|
||||
background: locale.value === t ? "#1b2a47" : "",
|
||||
color: locale.value === t ? "#f4f4f5" : "#000"
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
watch(
|
||||
() => locale.value,
|
||||
() => {
|
||||
@@ -140,29 +149,23 @@ onMounted(() => {
|
||||
</el-menu>
|
||||
<div class="horizontal-header-right">
|
||||
<!-- 通知 -->
|
||||
<Notice />
|
||||
<Notice id="header-notice" />
|
||||
<!-- 全屏 -->
|
||||
<screenfull v-show="!deviceDetection()" />
|
||||
<screenfull id="header-screenfull" v-show="!deviceDetection()" />
|
||||
<!-- 国际化 -->
|
||||
<el-dropdown trigger="click">
|
||||
<el-dropdown id="header-translation" trigger="click">
|
||||
<globalization />
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu class="translation">
|
||||
<el-dropdown-item
|
||||
:style="{
|
||||
background: locale === 'zh' ? '#1b2a47' : '',
|
||||
color: locale === 'zh' ? '#f4f4f5' : '#000'
|
||||
}"
|
||||
:style="getDropdownItemStyle('zh')"
|
||||
@click="translationCh"
|
||||
><el-icon class="check-zh" v-show="locale === 'zh'"
|
||||
><check /></el-icon
|
||||
>简体中文</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item
|
||||
:style="{
|
||||
background: locale === 'en' ? '#1b2a47' : '',
|
||||
color: locale === 'en' ? '#f4f4f5' : '#000'
|
||||
}"
|
||||
:style="getDropdownItemStyle('en')"
|
||||
@click="translationEn"
|
||||
><el-icon class="check-en" v-show="locale === 'en'"
|
||||
><check /></el-icon
|
||||
@@ -181,14 +184,14 @@ onMounted(() => {
|
||||
<el-dropdown-menu class="logout">
|
||||
<el-dropdown-item @click="logout">
|
||||
<i class="ri-logout-circle-r-line"></i
|
||||
>{{ $t("message.hsLoginOut") }}</el-dropdown-item
|
||||
>{{ $t("buttons.hsLoginOut") }}</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<el-icon
|
||||
class="el-icon-setting"
|
||||
:title="$t('message.hssystemSet')"
|
||||
:title="$t('buttons.hssystemSet')"
|
||||
@click="onPanel"
|
||||
>
|
||||
<Setting />
|
||||
@@ -200,7 +203,7 @@ onMounted(() => {
|
||||
<style lang="scss" scoped>
|
||||
.translation {
|
||||
.el-dropdown-menu__item {
|
||||
padding: 0 40px !important;
|
||||
padding: 5px 40px !important;
|
||||
}
|
||||
|
||||
.el-dropdown-menu__item:focus,
|
||||
@@ -212,12 +215,10 @@ onMounted(() => {
|
||||
.check-zh {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 13px;
|
||||
}
|
||||
|
||||
.check-en {
|
||||
position: absolute;
|
||||
bottom: 13px;
|
||||
left: 20px;
|
||||
}
|
||||
}
|
||||
@@ -229,7 +230,6 @@ onMounted(() => {
|
||||
min-width: 100%;
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 18px !important;
|
||||
}
|
||||
|
||||
.el-dropdown-menu__item:focus,
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
ref,
|
||||
PropType,
|
||||
nextTick,
|
||||
computed,
|
||||
CSSProperties,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
import path from "path";
|
||||
import { PropType, ref, nextTick, getCurrentInstance } from "vue";
|
||||
import { childrenType } from "../../types";
|
||||
import { useAppStoreHook } from "/@/store/modules/app";
|
||||
import Icon from "/@/components/ReIcon/src/Icon.vue";
|
||||
import { transformI18n } from "/@/plugins/i18n";
|
||||
import { findIconReg } from "/@/components/ReIcon";
|
||||
import Icon from "/@/components/ReIcon/src/Icon.vue";
|
||||
import { useAppStoreHook } from "/@/store/modules/app";
|
||||
|
||||
const instance = getCurrentInstance().appContext.app.config.globalProperties;
|
||||
const menuMode = instance.$storage.layout?.layout === "vertical";
|
||||
const pureApp = useAppStoreHook();
|
||||
@@ -24,6 +32,48 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
|
||||
const getNoDropdownStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
display: "flex",
|
||||
alignItems: "center"
|
||||
};
|
||||
});
|
||||
|
||||
const getDivStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
width: pureApp.sidebar.opened ? "" : "100%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
overflow: "hidden"
|
||||
};
|
||||
});
|
||||
|
||||
const getMenuTextStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
width: pureApp.sidebar.opened ? "125px" : "",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
outline: "none"
|
||||
};
|
||||
});
|
||||
|
||||
const getSubTextStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
width: pureApp.sidebar.opened ? "125px" : "",
|
||||
display: "inline-block",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis"
|
||||
};
|
||||
});
|
||||
|
||||
const getSpanStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis"
|
||||
};
|
||||
});
|
||||
|
||||
const onlyOneChild: childrenType = ref(null);
|
||||
// 存放菜单是否存在showTooltip属性标识
|
||||
const hoverMenuMap = new WeakMap();
|
||||
@@ -88,7 +138,7 @@ function resolvePath(routePath) {
|
||||
<el-menu-item
|
||||
:index="resolvePath(onlyOneChild.path)"
|
||||
:class="{ 'submenu-title-noDropdown': !isNest }"
|
||||
style="display: flex; align-items: center"
|
||||
:style="getNoDropdownStyle"
|
||||
>
|
||||
<el-icon v-show="props.item.meta.icon">
|
||||
<component
|
||||
@@ -101,15 +151,7 @@ function resolvePath(routePath) {
|
||||
></component>
|
||||
</el-icon>
|
||||
<template #title>
|
||||
<div
|
||||
:style="{
|
||||
width: pureApp.sidebar.opened ? '' : '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
overflow: 'hidden'
|
||||
}"
|
||||
>
|
||||
<div :style="getDivStyle">
|
||||
<span v-if="!menuMode">{{
|
||||
transformI18n(onlyOneChild.meta.title, onlyOneChild.meta.i18n)
|
||||
}}</span>
|
||||
@@ -126,12 +168,7 @@ function resolvePath(routePath) {
|
||||
</template>
|
||||
<span
|
||||
ref="menuTextRef"
|
||||
:style="{
|
||||
width: pureApp.sidebar.opened ? '125px' : '',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
outline: 'none'
|
||||
}"
|
||||
:style="getMenuTextStyle"
|
||||
@mouseover="hoverMenu(onlyOneChild)"
|
||||
>
|
||||
{{
|
||||
@@ -175,15 +212,10 @@ function resolvePath(routePath) {
|
||||
</template>
|
||||
<div
|
||||
ref="menuTextRef"
|
||||
:style="{
|
||||
width: pureApp.sidebar.opened ? '125px' : '',
|
||||
display: 'inline-block',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis'
|
||||
}"
|
||||
:style="getSubTextStyle"
|
||||
@mouseover="hoverMenu(props.item)"
|
||||
>
|
||||
<span style="overflow: hidden; text-overflow: ellipsis">
|
||||
<span :style="getSpanStyle">
|
||||
{{ transformI18n(props.item.meta.title, props.item.meta.i18n) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,9 @@ import { usePermissionStoreHook } from "/@/store/modules/permission";
|
||||
const route = useRoute();
|
||||
const pureApp = useAppStoreHook();
|
||||
const router = useRouter().options.routes;
|
||||
const showLogo = ref(storageLocal.getItem("logoVal") || "1");
|
||||
const showLogo = ref(
|
||||
storageLocal.getItem("responsive-configure")?.showLogo ?? true
|
||||
);
|
||||
const isCollapse = computed(() => {
|
||||
return !pureApp.getSidebarStatus;
|
||||
});
|
||||
@@ -58,7 +60,7 @@ onBeforeMount(() => {
|
||||
|
||||
<template>
|
||||
<div :class="['sidebar-container', showLogo ? 'has-logo' : '']">
|
||||
<Logo v-if="showLogo === '1'" :collapse="isCollapse" />
|
||||
<Logo v-if="showLogo" :collapse="isCollapse" />
|
||||
<el-scrollbar wrap-class="scrollbar-wrapper">
|
||||
<el-menu
|
||||
:default-active="activeMenu"
|
||||
|
||||
@@ -207,7 +207,6 @@
|
||||
li {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0 12px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
import {
|
||||
ref,
|
||||
watch,
|
||||
onBeforeMount,
|
||||
unref,
|
||||
nextTick,
|
||||
computed,
|
||||
getCurrentInstance,
|
||||
ComputedRef
|
||||
ComputedRef,
|
||||
CSSProperties,
|
||||
onBeforeMount,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
|
||||
import close from "/@/assets/svg/close.svg";
|
||||
@@ -17,6 +18,7 @@ import closeLeft from "/@/assets/svg/close_left.svg";
|
||||
import closeOther from "/@/assets/svg/close_other.svg";
|
||||
import closeRight from "/@/assets/svg/close_right.svg";
|
||||
|
||||
import { $t as t } from "/@/plugins/i18n";
|
||||
import { emitter } from "/@/utils/mitt";
|
||||
import { isEqual, isEmpty } from "lodash-es";
|
||||
import { transformI18n } from "/@/plugins/i18n";
|
||||
@@ -187,42 +189,42 @@ const handleScroll = (offset: number): void => {
|
||||
const tagsViews = ref<Array<tagsViewsType>>([
|
||||
{
|
||||
icon: refresh,
|
||||
text: "message.hsreload",
|
||||
text: t("buttons.hsreload"),
|
||||
divided: false,
|
||||
disabled: false,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: close,
|
||||
text: "message.hscloseCurrentTab",
|
||||
text: t("buttons.hscloseCurrentTab"),
|
||||
divided: false,
|
||||
disabled: multiTags.value.length > 1 ? false : true,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: closeLeft,
|
||||
text: "message.hscloseLeftTabs",
|
||||
text: t("buttons.hscloseLeftTabs"),
|
||||
divided: true,
|
||||
disabled: multiTags.value.length > 1 ? false : true,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: closeRight,
|
||||
text: "message.hscloseRightTabs",
|
||||
text: t("buttons.hscloseRightTabs"),
|
||||
divided: false,
|
||||
disabled: multiTags.value.length > 1 ? false : true,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: closeOther,
|
||||
text: "message.hscloseOtherTabs",
|
||||
text: t("buttons.hscloseOtherTabs"),
|
||||
divided: true,
|
||||
disabled: multiTags.value.length > 2 ? false : true,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: closeAll,
|
||||
text: "message.hscloseAllTabs",
|
||||
text: t("buttons.hscloseAllTabs"),
|
||||
divided: false,
|
||||
disabled: multiTags.value.length > 1 ? false : true,
|
||||
show: true
|
||||
@@ -230,9 +232,13 @@ const tagsViews = ref<Array<tagsViewsType>>([
|
||||
]);
|
||||
|
||||
// 显示模式,默认灵动模式显示
|
||||
const showModel = ref(storageLocal.getItem("showModel") || "smart");
|
||||
const showModel = ref(
|
||||
storageLocal.getItem("responsive-configure")?.showModel || "smart"
|
||||
);
|
||||
if (!showModel.value) {
|
||||
storageLocal.setItem("showModel", "card");
|
||||
const configure = storageLocal.getItem("responsive-configure");
|
||||
configure.showModel = "card";
|
||||
storageLocal.setItem("responsive-configure", configure);
|
||||
}
|
||||
|
||||
let visible = ref(false);
|
||||
@@ -306,7 +312,7 @@ function deleteDynamicTag(obj: any, current: any, tag?: string) {
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
title: "menus.hshome",
|
||||
i18n: true,
|
||||
icon: "el-icon-s-home",
|
||||
showLink: true
|
||||
@@ -609,17 +615,23 @@ onBeforeMount(() => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const getTabStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
transform: `translateX(${translateX.value}px)`
|
||||
};
|
||||
});
|
||||
|
||||
const getContextMenuStyle = computed((): CSSProperties => {
|
||||
return { left: buttonLeft.value + "px", top: buttonTop.value + "px" };
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="containerDom" class="tags-view" v-if="!showTags">
|
||||
<i class="ri-arrow-left-s-line" @click="handleScroll(200)"></i>
|
||||
<div ref="scrollbarDom" class="scroll-container">
|
||||
<div
|
||||
class="tab"
|
||||
ref="tabDom"
|
||||
:style="{ transform: `translateX(${translateX}px)` }"
|
||||
>
|
||||
<div class="tab" ref="tabDom" :style="getTabStyle">
|
||||
<div
|
||||
:ref="'dynamic' + index"
|
||||
v-for="(item, index) in multiTags"
|
||||
@@ -663,7 +675,7 @@ onBeforeMount(() => {
|
||||
<ul
|
||||
v-show="visible"
|
||||
:key="Math.random()"
|
||||
:style="{ left: buttonLeft + 'px', top: buttonTop + 'px' }"
|
||||
:style="getContextMenuStyle"
|
||||
class="contextmenu"
|
||||
>
|
||||
<div
|
||||
@@ -682,7 +694,7 @@ onBeforeMount(() => {
|
||||
<ul class="right-button">
|
||||
<li>
|
||||
<el-icon
|
||||
:title="$t('message.hsrefreshRoute')"
|
||||
:title="$t('buttons.hsrefreshRoute')"
|
||||
class="el-icon-refresh-right rotate"
|
||||
@click="onFresh"
|
||||
>
|
||||
|
||||
@@ -16,8 +16,8 @@ import { useAppStoreHook } from "/@/store/modules/app";
|
||||
import fullScreen from "/@/assets/svg/full_screen.svg";
|
||||
import exitScreen from "/@/assets/svg/exit_screen.svg";
|
||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||
import { useSettingStoreHook } from "/@/store/modules/settings";
|
||||
import { useMultiTagsStore } from "/@/store/modules/multiTags";
|
||||
import { useSettingStoreHook } from "/@/store/modules/settings";
|
||||
|
||||
import navbar from "./components/navbar.vue";
|
||||
import tag from "./components/tag/index.vue";
|
||||
@@ -51,16 +51,21 @@ const layout = computed(() => {
|
||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||
instance.$storage.layout = {
|
||||
layout: instance.$config?.Layout ?? "vertical",
|
||||
theme: instance.$config?.Theme ?? "default"
|
||||
theme: instance.$config?.Theme ?? "default",
|
||||
darkMode: instance.$config?.DarkMode ?? false,
|
||||
sidebarStatus: instance.$config?.SidebarStatus ?? true,
|
||||
epThemeColor: instance.$config?.EpThemeColor ?? "#409EFF"
|
||||
};
|
||||
}
|
||||
// 灰色模式、色弱模式、隐藏标签页
|
||||
if (!instance.$storage.sets) {
|
||||
if (!instance.$storage.configure) {
|
||||
// eslint-disable-next-line
|
||||
instance.$storage.sets = {
|
||||
instance.$storage.configure = {
|
||||
grey: instance.$config?.Grey ?? false,
|
||||
weak: instance.$config?.Weak ?? false,
|
||||
hideTabs: instance.$config?.HideTabs ?? false,
|
||||
showLogo: instance.$config?.ShowLogo ?? true,
|
||||
showModel: instance.$config?.ShowModel ?? "smart",
|
||||
multiTagsCache: instance.$config?.MultiTagsCache ?? false
|
||||
};
|
||||
}
|
||||
@@ -90,7 +95,7 @@ const set: setType = reactive({
|
||||
}),
|
||||
|
||||
hideTabs: computed(() => {
|
||||
return instance.$storage?.sets.hideTabs;
|
||||
return instance.$storage?.configure.hideTabs;
|
||||
})
|
||||
});
|
||||
|
||||
@@ -98,7 +103,10 @@ function setTheme(layoutModel: string) {
|
||||
window.document.body.setAttribute("layout", layoutModel);
|
||||
instance.$storage.layout = {
|
||||
layout: `${layoutModel}`,
|
||||
theme: instance.$storage.layout?.theme
|
||||
theme: instance.$storage.layout?.theme,
|
||||
darkMode: instance.$storage.layout?.darkMode,
|
||||
sidebarStatus: instance.$storage.layout?.sidebarStatus,
|
||||
epThemeColor: instance.$storage.layout?.epThemeColor
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
80
src/layout/theme/element-plus.ts
Normal file
80
src/layout/theme/element-plus.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
/* 动态改变element-plus主题色 */
|
||||
import rgbHex from "rgb-hex";
|
||||
import color from "css-color-function";
|
||||
import { TinyColor } from "@ctrl/tinycolor";
|
||||
import epCss from "element-plus/dist/index.css";
|
||||
|
||||
// 色值表
|
||||
const formula = {
|
||||
"shade-1": "color(primary shade(10%))",
|
||||
"light-1": "color(primary tint(10%))",
|
||||
"light-2": "color(primary tint(20%))",
|
||||
"light-3": "color(primary tint(30%))",
|
||||
"light-4": "color(primary tint(40%))",
|
||||
"light-5": "color(primary tint(50%))",
|
||||
"light-6": "color(primary tint(60%))",
|
||||
"light-7": "color(primary tint(70%))",
|
||||
"light-8": "color(primary tint(80%))",
|
||||
"light-9": "color(primary tint(90%))"
|
||||
};
|
||||
|
||||
// 把生成的样式表写入到style中
|
||||
export const writeNewStyle = (newStyle: string): void => {
|
||||
const style = window.document.createElement("style");
|
||||
style.innerText = newStyle;
|
||||
window.document.head.appendChild(style);
|
||||
};
|
||||
|
||||
// 根据主题色,生成最新的样式表
|
||||
export const createNewStyle = (primaryStyle: string): string => {
|
||||
// 根据主色生成色值表
|
||||
const colors = createColors(primaryStyle);
|
||||
// 在当前ep的默认样式表中标记需要替换的色值
|
||||
let cssText = getStyleTemplate(epCss);
|
||||
// 遍历生成的色值表,在 默认样式表 进行全局替换
|
||||
Object.keys(colors).forEach(key => {
|
||||
cssText = cssText.replace(
|
||||
new RegExp("(:|\\s+)" + key, "g"),
|
||||
"$1" + colors[key]
|
||||
);
|
||||
});
|
||||
return cssText;
|
||||
};
|
||||
|
||||
export const createColors = (primary: string) => {
|
||||
if (!primary) return;
|
||||
const colors = {
|
||||
primary
|
||||
};
|
||||
Object.keys(formula).forEach(key => {
|
||||
const value = formula[key].replace(/primary/, primary);
|
||||
colors[key] = "#" + rgbHex(color.convert(value));
|
||||
});
|
||||
return colors;
|
||||
};
|
||||
|
||||
const getStyleTemplate = (data: string): string => {
|
||||
const colorMap = {
|
||||
"#3a8ee6": "shade-1",
|
||||
"#409eff": "primary",
|
||||
"#53a8ff": "light-1",
|
||||
"#66b1ff": "light-2",
|
||||
"#79bbff": "light-3",
|
||||
"#8cc5ff": "light-4",
|
||||
"#a0cfff": "light-5",
|
||||
"#b3d8ff": "light-6",
|
||||
"#c6e2ff": "light-7",
|
||||
"#d9ecff": "light-8",
|
||||
"#ecf5ff": "light-9"
|
||||
};
|
||||
Object.keys(colorMap).forEach(key => {
|
||||
const value = colorMap[key];
|
||||
data = data.replace(new RegExp(key, "ig"), value);
|
||||
});
|
||||
return data;
|
||||
};
|
||||
|
||||
// 自动计算hover和active颜色 https://element-plus.gitee.io/zh-CN/component/button.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E9%A2%9C%E8%89%B2-%E6%B5%8B%E8%AF%95%E7%89%88
|
||||
export const shadeBgColor = (color: string): string => {
|
||||
return new TinyColor(color).shade(10).toString();
|
||||
};
|
||||
@@ -3,9 +3,9 @@ export const routerArrays: Array<RouteConfigs> = [
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
title: "menus.hshome",
|
||||
i18n: true,
|
||||
icon: "el-icon-s-home",
|
||||
icon: "HomeFilled",
|
||||
showLink: true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +115,14 @@ import {
|
||||
ArrowDown,
|
||||
Close,
|
||||
CloseBold,
|
||||
Bell
|
||||
Bell,
|
||||
Guide,
|
||||
User,
|
||||
Iphone,
|
||||
Location,
|
||||
Tickets,
|
||||
OfficeBuilding,
|
||||
Notebook
|
||||
} from "@element-plus/icons-vue";
|
||||
|
||||
// Icon
|
||||
@@ -134,7 +141,14 @@ export const iconComponents = [
|
||||
ArrowDown,
|
||||
Close,
|
||||
CloseBold,
|
||||
Bell
|
||||
Bell,
|
||||
Guide,
|
||||
User,
|
||||
Iphone,
|
||||
Location,
|
||||
Tickets,
|
||||
OfficeBuilding,
|
||||
Notebook
|
||||
];
|
||||
|
||||
export function useElementPlus(app: App) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// 菜单国际化配置
|
||||
import { siphonI18n } from "./index";
|
||||
// vxe-table组件国际化
|
||||
import zhVxeTable from "vxe-table/lib/locale/lang/zh-CN";
|
||||
import enVxeTable from "vxe-table/lib/locale/lang/en-US";
|
||||
@@ -7,156 +7,18 @@ import enVxeTable from "vxe-table/lib/locale/lang/en-US";
|
||||
import enLocale from "element-plus/lib/locale/lang/en";
|
||||
import zhLocale from "element-plus/lib/locale/lang/zh-cn";
|
||||
|
||||
// 导航菜单配置
|
||||
export const menusConfig = {
|
||||
zh: {
|
||||
message: {
|
||||
hshome: "首页",
|
||||
hssysManagement: "系统管理",
|
||||
hsBaseinfo: "基础信息",
|
||||
hsDict: "字典管理",
|
||||
hseditor: "编辑器",
|
||||
hserror: "错误页面",
|
||||
hsfourZeroFour: "404",
|
||||
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: "权限管理",
|
||||
permissionPage: "页面权限",
|
||||
permissionButton: "按钮权限",
|
||||
hstabs: "标签页操作",
|
||||
hsMenuTree: "菜单树结构",
|
||||
externalLink: "外链"
|
||||
}
|
||||
},
|
||||
en: {
|
||||
message: {
|
||||
hshome: "Home",
|
||||
hssysManagement: "System Manage",
|
||||
hsBaseinfo: "Base Info",
|
||||
hsDict: "Dict Manage",
|
||||
hseditor: "Editor",
|
||||
hserror: "Error Page",
|
||||
hsfourZeroFour: "404",
|
||||
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",
|
||||
permissionPage: "Page Permission",
|
||||
permissionButton: "Button Permission",
|
||||
hstabs: "Tabs Operate",
|
||||
hsMenuTree: "Menu Tree",
|
||||
externalLink: "External Link"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 按钮配置
|
||||
export const buttonConfig = {
|
||||
zh: {
|
||||
message: {
|
||||
hsLoginOut: "退出系统",
|
||||
hsfullscreen: "全屏",
|
||||
hsexitfullscreen: "退出全屏",
|
||||
hsrefreshRoute: "刷新路由",
|
||||
hslogin: "登陆",
|
||||
hsadd: "新增",
|
||||
hsmark: "标记/取消",
|
||||
hssave: "保存",
|
||||
hssearch: "搜索",
|
||||
hsexpendAll: "全部展开",
|
||||
hscollapseAll: "全部折叠",
|
||||
hssystemSet: "打开项目配置",
|
||||
hsdelete: "删除",
|
||||
hsreload: "重新加载",
|
||||
hscloseCurrentTab: "关闭当前标签页",
|
||||
hscloseLeftTabs: "关闭左侧标签页",
|
||||
hscloseRightTabs: "关闭右侧标签页",
|
||||
hscloseOtherTabs: "关闭其他标签页",
|
||||
hscloseAllTabs: "关闭全部标签页"
|
||||
}
|
||||
},
|
||||
en: {
|
||||
message: {
|
||||
hsLoginOut: "loginOut",
|
||||
hsfullscreen: "fullScreen",
|
||||
hsexitfullscreen: "exitFullscreen",
|
||||
hsrefreshRoute: "refreshRoute",
|
||||
hslogin: "login",
|
||||
hsadd: "Add",
|
||||
hsmark: "Mark/Cancel",
|
||||
hssave: "Save",
|
||||
hssearch: "Search",
|
||||
hsexpendAll: "Expand All",
|
||||
hscollapseAll: "Collapse All",
|
||||
hssystemSet: "Open ProjectConfig",
|
||||
hsdelete: "Delete",
|
||||
hsreload: "Reload",
|
||||
hscloseCurrentTab: "Close CurrentTab",
|
||||
hscloseLeftTabs: "Close LeftTabs",
|
||||
hscloseRightTabs: "Close RightTabs",
|
||||
hscloseOtherTabs: "Close OtherTabs",
|
||||
hscloseAllTabs: "Close AllTabs"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 配置
|
||||
// export const xxxx = {
|
||||
// zh: {
|
||||
// message: {},
|
||||
// },
|
||||
// en: {
|
||||
// message: {},
|
||||
// },
|
||||
// };
|
||||
|
||||
const localesList = [menusConfig, buttonConfig];
|
||||
// 项目内自定义国际化
|
||||
const zhModules = import.meta.globEager("./zh-CN/**/*.ts");
|
||||
const enModules = import.meta.globEager("./en/**/*.ts");
|
||||
|
||||
export const localesConfigs = {
|
||||
zh: {
|
||||
message: Object.assign({}, ...localesList.map(v => v.zh.message)),
|
||||
...siphonI18n(zhModules, "zh-CN"),
|
||||
...zhVxeTable,
|
||||
...zhLocale
|
||||
},
|
||||
en: {
|
||||
message: Object.assign({}, ...localesList.map(v => v.en.message)),
|
||||
...siphonI18n(enModules, "en"),
|
||||
...enVxeTable,
|
||||
...enLocale
|
||||
}
|
||||
|
||||
21
src/plugins/i18n/en/buttons.ts
Normal file
21
src/plugins/i18n/en/buttons.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export default {
|
||||
hsLoginOut: "LoginOut",
|
||||
hsfullscreen: "FullScreen",
|
||||
hsexitfullscreen: "ExitFullscreen",
|
||||
hsrefreshRoute: "RefreshRoute",
|
||||
hslogin: "Login",
|
||||
hsadd: "Add",
|
||||
hsmark: "Mark/Cancel",
|
||||
hssave: "Save",
|
||||
hssearch: "Search",
|
||||
hsexpendAll: "Expand All",
|
||||
hscollapseAll: "Collapse All",
|
||||
hssystemSet: "Open ProjectConfig",
|
||||
hsdelete: "Delete",
|
||||
hsreload: "Reload",
|
||||
hscloseCurrentTab: "Close CurrentTab",
|
||||
hscloseLeftTabs: "Close LeftTabs",
|
||||
hscloseRightTabs: "Close RightTabs",
|
||||
hscloseOtherTabs: "Close OtherTabs",
|
||||
hscloseAllTabs: "Close AllTabs"
|
||||
};
|
||||
38
src/plugins/i18n/en/menus.ts
Normal file
38
src/plugins/i18n/en/menus.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
export default {
|
||||
hshome: "Home",
|
||||
hslogin: "Login",
|
||||
hssysManagement: "System Manage",
|
||||
hsBaseinfo: "Base Info",
|
||||
hsDict: "Dict Manage",
|
||||
hseditor: "Editor",
|
||||
hserror: "Error Page",
|
||||
hsfourZeroFour: "404",
|
||||
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",
|
||||
permissionPage: "Page Permission",
|
||||
permissionButton: "Button Permission",
|
||||
hstabs: "Tabs Operate",
|
||||
hsMenuTree: "Menu Tree",
|
||||
hsguide: "Guide",
|
||||
externalLink: "External Link"
|
||||
};
|
||||
@@ -1,19 +1,10 @@
|
||||
// 多组件库的国际化和本地项目国际化兼容
|
||||
import { App } from "vue";
|
||||
import { set } from "lodash-es";
|
||||
import { createI18n } from "vue-i18n";
|
||||
import { localesConfigs } from "./config";
|
||||
import { storageLocal } from "/@/utils/storage";
|
||||
|
||||
export const i18n = createI18n({
|
||||
locale: storageLocal.getItem("responsive-locale")?.locale ?? "zh",
|
||||
fallbackLocale: "en",
|
||||
messages: localesConfigs
|
||||
});
|
||||
|
||||
export function usI18n(app: App) {
|
||||
app.use(i18n);
|
||||
}
|
||||
|
||||
/**
|
||||
* 国际化转换工具函数
|
||||
* @param message message
|
||||
@@ -37,3 +28,47 @@ export function transformI18n(message: string | object = "", isI18n = false) {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从模块中抽取国际化
|
||||
* @param langs 存放国际化模块
|
||||
* @param prefix 语言 默认 zh-CN
|
||||
* @returns obj 格式:{模块名.**}
|
||||
*/
|
||||
export function siphonI18n(
|
||||
langs: Record<string, Record<string, any>>,
|
||||
prefix = "zh-CN"
|
||||
) {
|
||||
const langsObj: Recordable = {};
|
||||
Object.keys(langs).forEach((key: string) => {
|
||||
let fileName = key.replace(`./${prefix}/`, "").replace(/^\.\//, "");
|
||||
fileName = fileName.substring(0, fileName.lastIndexOf("."));
|
||||
const keyList = fileName.split("/");
|
||||
const moduleName = keyList.shift();
|
||||
const objKey = keyList.join(".");
|
||||
const langFileModule = langs[key].default;
|
||||
|
||||
if (moduleName) {
|
||||
if (objKey) {
|
||||
set(langsObj, moduleName, langsObj[moduleName] || {});
|
||||
set(langsObj[moduleName], objKey, langFileModule);
|
||||
} else {
|
||||
set(langsObj, moduleName, langFileModule || {});
|
||||
}
|
||||
}
|
||||
});
|
||||
return langsObj;
|
||||
}
|
||||
|
||||
// 此函数只是配合i18n Ally插件来进行国际化智能提示,并无实际意义(只对提示起作用),如果不需要国际化可删除
|
||||
export const $t = (key: string) => key;
|
||||
|
||||
export const i18n = createI18n({
|
||||
locale: storageLocal.getItem("responsive-locale")?.locale ?? "zh",
|
||||
fallbackLocale: "en",
|
||||
messages: localesConfigs
|
||||
});
|
||||
|
||||
export function usI18n(app: App) {
|
||||
app.use(i18n);
|
||||
}
|
||||
|
||||
21
src/plugins/i18n/zh-CN/buttons.ts
Normal file
21
src/plugins/i18n/zh-CN/buttons.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export default {
|
||||
hsLoginOut: "退出系统",
|
||||
hsfullscreen: "全屏",
|
||||
hsexitfullscreen: "退出全屏",
|
||||
hsrefreshRoute: "刷新路由",
|
||||
hslogin: "登陆",
|
||||
hsadd: "新增",
|
||||
hsmark: "标记/取消",
|
||||
hssave: "保存",
|
||||
hssearch: "搜索",
|
||||
hsexpendAll: "全部展开",
|
||||
hscollapseAll: "全部折叠",
|
||||
hssystemSet: "打开项目配置",
|
||||
hsdelete: "删除",
|
||||
hsreload: "重新加载",
|
||||
hscloseCurrentTab: "关闭当前标签页",
|
||||
hscloseLeftTabs: "关闭左侧标签页",
|
||||
hscloseRightTabs: "关闭右侧标签页",
|
||||
hscloseOtherTabs: "关闭其他标签页",
|
||||
hscloseAllTabs: "关闭全部标签页"
|
||||
};
|
||||
38
src/plugins/i18n/zh-CN/menus.ts
Normal file
38
src/plugins/i18n/zh-CN/menus.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
export default {
|
||||
hshome: "首页",
|
||||
hslogin: "登陆",
|
||||
hssysManagement: "系统管理",
|
||||
hsBaseinfo: "基础信息",
|
||||
hsDict: "字典管理",
|
||||
hseditor: "编辑器",
|
||||
hserror: "错误页面",
|
||||
hsfourZeroFour: "404",
|
||||
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: "权限管理",
|
||||
permissionPage: "页面权限",
|
||||
permissionButton: "按钮权限",
|
||||
hstabs: "标签页操作",
|
||||
hsMenuTree: "菜单树结构",
|
||||
hsguide: "引导页",
|
||||
externalLink: "外链"
|
||||
};
|
||||
@@ -65,8 +65,8 @@ VXETable.setup({
|
||||
i18n: (key, args) => i18n.global.t(key, args),
|
||||
// 可选,对参数中的列头、校验提示..等进行自动翻译(只对支持国际化的有效)
|
||||
translate(key, args) {
|
||||
// 例如,只翻译 "message." 开头的键值
|
||||
if (key && key.indexOf("message.") > -1) {
|
||||
// 例如,只翻译 "buttons." 开头的键值
|
||||
if (key && key.indexOf("buttons.") > -1) {
|
||||
return i18n.global.t(key, args);
|
||||
}
|
||||
if (key && key.indexOf("el.") > -1) {
|
||||
|
||||
@@ -89,7 +89,7 @@ router.beforeEach((to: toRouteType, _from, next) => {
|
||||
});
|
||||
};
|
||||
// 未开启标签页缓存,刷新页面重定向到顶级路由(参考标签页操作例子,只针对静态路由)
|
||||
if (to.meta?.realPath) {
|
||||
if (to.meta?.refreshRedirect) {
|
||||
const routes = router.options.routes;
|
||||
const { refreshRedirect } = to.meta;
|
||||
const { name, meta } = findRouteByPath(refreshRedirect, routes);
|
||||
@@ -117,8 +117,9 @@ router.beforeEach((to: toRouteType, _from, next) => {
|
||||
route?.meta?.rank !== 0 &&
|
||||
routePartent.length === 0
|
||||
) {
|
||||
if (!route?.meta?.refreshRedirect) return;
|
||||
const { name, meta } = findRouteByPath(
|
||||
route?.meta?.refreshRedirect,
|
||||
route.meta.refreshRedirect,
|
||||
routes
|
||||
);
|
||||
handTag(
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const componentsRouter = {
|
||||
@@ -7,7 +8,7 @@ const componentsRouter = {
|
||||
redirect: "/components/video",
|
||||
meta: {
|
||||
icon: "Menu",
|
||||
title: "message.hscomponents",
|
||||
title: $t("menus.hscomponents"),
|
||||
i18n: true,
|
||||
showLink: true,
|
||||
rank: 4
|
||||
@@ -18,7 +19,7 @@ const componentsRouter = {
|
||||
name: "video",
|
||||
component: () => import("/@/views/components/video/index.vue"),
|
||||
meta: {
|
||||
title: "message.hsvideo",
|
||||
title: $t("menus.hsvideo"),
|
||||
showLink: true,
|
||||
i18n: true
|
||||
}
|
||||
@@ -28,7 +29,7 @@ const componentsRouter = {
|
||||
name: "map",
|
||||
component: () => import("/@/views/components/map/index.vue"),
|
||||
meta: {
|
||||
title: "message.hsmap",
|
||||
title: $t("menus.hsmap"),
|
||||
showLink: true,
|
||||
keepAlive: true,
|
||||
i18n: true,
|
||||
@@ -42,7 +43,7 @@ const componentsRouter = {
|
||||
name: "draggable",
|
||||
component: () => import("/@/views/components/draggable/index.vue"),
|
||||
meta: {
|
||||
title: "message.hsdraggable",
|
||||
title: $t("menus.hsdraggable"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
transition: {
|
||||
@@ -57,7 +58,7 @@ const componentsRouter = {
|
||||
name: "splitPane",
|
||||
component: () => import("/@/views/components/split-pane/index.vue"),
|
||||
meta: {
|
||||
title: "message.hssplitPane",
|
||||
title: $t("menus.hssplitPane"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
extraIcon: {
|
||||
@@ -71,7 +72,7 @@ const componentsRouter = {
|
||||
name: "button",
|
||||
component: () => import("/@/views/components/button/index.vue"),
|
||||
meta: {
|
||||
title: "message.hsbutton",
|
||||
title: $t("menus.hsbutton"),
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
@@ -81,7 +82,7 @@ const componentsRouter = {
|
||||
name: "cropping",
|
||||
component: () => import("/@/views/components/cropping/index.vue"),
|
||||
meta: {
|
||||
title: "message.hscropping",
|
||||
title: $t("menus.hscropping"),
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
@@ -91,7 +92,7 @@ const componentsRouter = {
|
||||
name: "countTo",
|
||||
component: () => import("/@/views/components/count-to/index.vue"),
|
||||
meta: {
|
||||
title: "message.hscountTo",
|
||||
title: $t("menus.hscountTo"),
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
@@ -101,7 +102,7 @@ const componentsRouter = {
|
||||
name: "selector",
|
||||
component: () => import("/@/views/components/selector/index.vue"),
|
||||
meta: {
|
||||
title: "message.hsselector",
|
||||
title: $t("menus.hsselector"),
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
@@ -111,7 +112,7 @@ const componentsRouter = {
|
||||
name: "seamlessScroll",
|
||||
component: () => import("/@/views/components/seamless-scroll/index.vue"),
|
||||
meta: {
|
||||
title: "message.hsseamless",
|
||||
title: $t("menus.hsseamless"),
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
@@ -121,7 +122,7 @@ const componentsRouter = {
|
||||
name: "contextmenu",
|
||||
component: () => import("/@/views/components/contextmenu/index.vue"),
|
||||
meta: {
|
||||
title: "message.hscontextmenu",
|
||||
title: $t("menus.hscontextmenu"),
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const editorRouter = {
|
||||
@@ -7,7 +8,7 @@ const editorRouter = {
|
||||
redirect: "/editor/index",
|
||||
meta: {
|
||||
icon: "Edit",
|
||||
title: "message.hseditor",
|
||||
title: $t("menus.hseditor"),
|
||||
i18n: true,
|
||||
showLink: true,
|
||||
rank: 2
|
||||
@@ -18,7 +19,7 @@ const editorRouter = {
|
||||
name: "reEditor",
|
||||
component: () => import("/@/views/editor/index.vue"),
|
||||
meta: {
|
||||
title: "message.hseditor",
|
||||
title: $t("menus.hseditor"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
keepAlive: true,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const errorRouter = {
|
||||
@@ -7,7 +8,7 @@ const errorRouter = {
|
||||
redirect: "/error/401",
|
||||
meta: {
|
||||
icon: "Position",
|
||||
title: "message.hserror",
|
||||
title: $t("menus.hserror"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
rank: 7
|
||||
@@ -18,7 +19,7 @@ const errorRouter = {
|
||||
name: "401",
|
||||
component: () => import("/@/views/error/401.vue"),
|
||||
meta: {
|
||||
title: "message.hsfourZeroOne",
|
||||
title: $t("menus.hsfourZeroOne"),
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
@@ -28,7 +29,7 @@ const errorRouter = {
|
||||
name: "404",
|
||||
component: () => import("/@/views/error/404.vue"),
|
||||
meta: {
|
||||
title: "message.hsfourZeroFour",
|
||||
title: $t("menus.hsfourZeroFour"),
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const externalLink = {
|
||||
@@ -6,7 +7,7 @@ const externalLink = {
|
||||
component: Layout,
|
||||
meta: {
|
||||
icon: "Link",
|
||||
title: "message.externalLink",
|
||||
title: $t("menus.externalLink"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
rank: 190
|
||||
@@ -15,7 +16,7 @@ const externalLink = {
|
||||
{
|
||||
path: "https://github.com/xiaoxian521/vue-pure-admin",
|
||||
meta: {
|
||||
title: "message.externalLink",
|
||||
title: $t("menus.externalLink"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
rank: 191
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const flowChartRouter = {
|
||||
@@ -7,7 +8,7 @@ const flowChartRouter = {
|
||||
redirect: "/flowChart/index",
|
||||
meta: {
|
||||
icon: "SetUp",
|
||||
title: "message.hsflowChart",
|
||||
title: $t("menus.hsflowChart"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
rank: 1
|
||||
@@ -18,7 +19,7 @@ const flowChartRouter = {
|
||||
name: "flowChart",
|
||||
component: () => import("/@/views/flow-chart/index.vue"),
|
||||
meta: {
|
||||
title: "message.hsflowChart",
|
||||
title: $t("menus.hsflowChart"),
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
|
||||
30
src/router/modules/guide.ts
Normal file
30
src/router/modules/guide.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const guideRouter = {
|
||||
path: "/guide",
|
||||
name: "reGuide",
|
||||
component: Layout,
|
||||
redirect: "/guide/index",
|
||||
meta: {
|
||||
icon: "Guide",
|
||||
title: $t("menus.hsguide"),
|
||||
i18n: true,
|
||||
showLink: true,
|
||||
rank: 10
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "/guide/index",
|
||||
name: "reGuide",
|
||||
component: () => import("/@/views/guide/index.vue"),
|
||||
meta: {
|
||||
title: $t("menus.hsguide"),
|
||||
showLink: true,
|
||||
i18n: true
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export default guideRouter;
|
||||
@@ -1,3 +1,4 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const homeRouter = {
|
||||
@@ -7,7 +8,7 @@ const homeRouter = {
|
||||
redirect: "/welcome",
|
||||
meta: {
|
||||
icon: "HomeFilled",
|
||||
title: "message.hshome",
|
||||
title: $t("menus.hshome"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
rank: 0
|
||||
@@ -18,7 +19,7 @@ const homeRouter = {
|
||||
name: "welcome",
|
||||
component: () => import("/@/views/welcome.vue"),
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
title: $t("menus.hshome"),
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// 静态路由
|
||||
import homeRouter from "./home";
|
||||
import errorRouter from "./error";
|
||||
import guideRouter from "./guide";
|
||||
import editorRouter from "./editor";
|
||||
import nestedRouter from "./nested";
|
||||
import menuTreeRouter from "./menuTree";
|
||||
@@ -20,6 +21,7 @@ import {
|
||||
const routes = [
|
||||
homeRouter,
|
||||
errorRouter,
|
||||
guideRouter,
|
||||
nestedRouter,
|
||||
externalLink,
|
||||
editorRouter,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const menuTreeRouter = {
|
||||
@@ -7,7 +8,7 @@ const menuTreeRouter = {
|
||||
redirect: "/menuTree/index",
|
||||
meta: {
|
||||
icon: "RI-node-tree",
|
||||
title: "message.hsMenuTree",
|
||||
title: $t("menus.hsMenuTree"),
|
||||
i18n: true,
|
||||
showLink: true,
|
||||
rank: 9
|
||||
@@ -18,7 +19,7 @@ const menuTreeRouter = {
|
||||
name: "reMenuTree",
|
||||
component: () => import("/@/views/menu-tree/index.vue"),
|
||||
meta: {
|
||||
title: "message.hsMenuTree",
|
||||
title: $t("menus.hsMenuTree"),
|
||||
showLink: true,
|
||||
i18n: true
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const nestedRouter = {
|
||||
@@ -6,7 +7,7 @@ const nestedRouter = {
|
||||
redirect: "/nested/menu1/menu1-1",
|
||||
name: "Nested",
|
||||
meta: {
|
||||
title: "message.hsmenus",
|
||||
title: $t("menus.hsmenus"),
|
||||
icon: "Histogram",
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
@@ -18,7 +19,7 @@ const nestedRouter = {
|
||||
component: () => import("/@/layout/routerView/parent.vue"),
|
||||
name: "Menu1",
|
||||
meta: {
|
||||
title: "message.hsmenu1",
|
||||
title: $t("menus.hsmenu1"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
keepAlive: true
|
||||
@@ -30,7 +31,7 @@ const nestedRouter = {
|
||||
component: () => import("/@/views/nested/menu1/menu1-1/index.vue"),
|
||||
name: "Menu1-1",
|
||||
meta: {
|
||||
title: "message.hsmenu1-1",
|
||||
title: $t("menus.hsmenu1-1"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
keepAlive: true
|
||||
@@ -42,7 +43,7 @@ const nestedRouter = {
|
||||
name: "Menu1-2",
|
||||
redirect: "/nested/menu1/menu1-2/menu1-2-1",
|
||||
meta: {
|
||||
title: "message.hsmenu1-2",
|
||||
title: $t("menus.hsmenu1-2"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
keepAlive: true
|
||||
@@ -54,7 +55,7 @@ const nestedRouter = {
|
||||
import("/@/views/nested/menu1/menu1-2/menu1-2-1/index.vue"),
|
||||
name: "Menu1-2-1",
|
||||
meta: {
|
||||
title: "message.hsmenu1-2-1",
|
||||
title: $t("menus.hsmenu1-2-1"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
keepAlive: true
|
||||
@@ -66,7 +67,7 @@ const nestedRouter = {
|
||||
import("/@/views/nested/menu1/menu1-2/menu1-2-2/index.vue"),
|
||||
name: "Menu1-2-2",
|
||||
meta: {
|
||||
title: "message.hsmenu1-2-2",
|
||||
title: $t("menus.hsmenu1-2-2"),
|
||||
showLink: true,
|
||||
keepAlive: true,
|
||||
i18n: true,
|
||||
@@ -83,7 +84,7 @@ const nestedRouter = {
|
||||
component: () => import("/@/views/nested/menu1/menu1-3/index.vue"),
|
||||
name: "Menu1-3",
|
||||
meta: {
|
||||
title: "message.hsmenu1-3",
|
||||
title: $t("menus.hsmenu1-3"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
keepAlive: true
|
||||
@@ -96,7 +97,7 @@ const nestedRouter = {
|
||||
name: "Menu2",
|
||||
component: () => import("/@/views/nested/menu2/index.vue"),
|
||||
meta: {
|
||||
title: "message.hsmenu2",
|
||||
title: $t("menus.hsmenu2"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
keepAlive: true
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const remainingRouter = [
|
||||
@@ -6,7 +7,7 @@ const remainingRouter = [
|
||||
name: "login",
|
||||
component: () => import("/@/views/login.vue"),
|
||||
meta: {
|
||||
title: "message.hslogin",
|
||||
title: $t("menus.hslogin"),
|
||||
showLink: false,
|
||||
i18n: true,
|
||||
rank: 101
|
||||
@@ -18,7 +19,7 @@ const remainingRouter = [
|
||||
component: Layout,
|
||||
meta: {
|
||||
icon: "HomeFilled",
|
||||
title: "message.hshome",
|
||||
title: $t("menus.hshome"),
|
||||
i18n: true,
|
||||
showLink: false,
|
||||
rank: 104
|
||||
|
||||
@@ -2,8 +2,8 @@ import { RouteLocationNormalized } from "vue-router";
|
||||
|
||||
export interface toRouteType extends RouteLocationNormalized {
|
||||
meta: {
|
||||
keepAlive: boolean;
|
||||
keepAlive?: boolean;
|
||||
refreshRedirect: string;
|
||||
realPath: string;
|
||||
dynamicLevel?: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { useTimeoutFn } from "@vueuse/core";
|
||||
import { RouteConfigs } from "/@/layout/types";
|
||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
||||
// 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,tsx}");
|
||||
|
||||
// 动态路由
|
||||
import { getAsyncRoutes } from "/@/api/routes";
|
||||
@@ -212,15 +212,13 @@ const handleAliveRoute = (matched: RouteRecordNormalized[], mode?: string) => {
|
||||
// 过滤后端传来的动态路由 重新生成规范路由
|
||||
const addAsyncRoutes = (arrRoutes: Array<RouteRecordRaw>) => {
|
||||
if (!arrRoutes || !arrRoutes.length) return;
|
||||
const modulesRoutesKeys = Object.keys(modulesRoutes);
|
||||
arrRoutes.forEach((v: RouteRecordRaw) => {
|
||||
if (v.redirect) {
|
||||
v.component = Layout;
|
||||
} else {
|
||||
if (v.meta.realPath) {
|
||||
v.component = modulesRoutes[`/src/views${v.meta.realPath}/index.vue`];
|
||||
} else {
|
||||
v.component = modulesRoutes[`/src/views${v.path}/index.vue`];
|
||||
}
|
||||
const index = modulesRoutesKeys.findIndex(ev => ev.includes(v.path));
|
||||
v.component = modulesRoutes[modulesRoutesKeys[index]];
|
||||
}
|
||||
if (v.children) {
|
||||
addAsyncRoutes(v.children);
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { storageLocal } from "/@/utils/storage";
|
||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||
import { store } from "/@/store";
|
||||
import { appType } from "./types";
|
||||
import { defineStore } from "pinia";
|
||||
import { getConfig } from "/@/config";
|
||||
import { storageLocal } from "/@/utils/storage";
|
||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||
|
||||
export const useAppStore = defineStore({
|
||||
id: "pure-app",
|
||||
state: (): appType => ({
|
||||
sidebar: {
|
||||
opened: storageLocal.getItem("sidebarStatus")
|
||||
? !!+storageLocal.getItem("sidebarStatus")
|
||||
: true,
|
||||
opened:
|
||||
storageLocal.getItem("responsive-layout")?.sidebarStatus ??
|
||||
getConfig().SidebarStatus,
|
||||
withoutAnimation: false,
|
||||
isClickHamburger: false
|
||||
},
|
||||
@@ -30,20 +30,22 @@ export const useAppStore = defineStore({
|
||||
},
|
||||
actions: {
|
||||
TOGGLE_SIDEBAR(opened?: boolean, resize?: string) {
|
||||
const layout = storageLocal.getItem("responsive-layout");
|
||||
if (opened && resize) {
|
||||
this.sidebar.withoutAnimation = true;
|
||||
this.sidebar.opened = true;
|
||||
storageLocal.setItem("sidebarStatus", true);
|
||||
layout.sidebarStatus = true;
|
||||
} else if (!opened && resize) {
|
||||
this.sidebar.withoutAnimation = true;
|
||||
this.sidebar.opened = false;
|
||||
storageLocal.setItem("sidebarStatus", false);
|
||||
layout.sidebarStatus = false;
|
||||
} else if (!opened && !resize) {
|
||||
this.sidebar.withoutAnimation = false;
|
||||
this.sidebar.opened = !this.sidebar.opened;
|
||||
this.sidebar.isClickHamburger = !this.sidebar.opened;
|
||||
storageLocal.setItem("sidebarStatus", this.sidebar.opened);
|
||||
layout.sidebarStatus = this.sidebar.opened;
|
||||
}
|
||||
storageLocal.setItem("responsive-layout", layout);
|
||||
},
|
||||
TOGGLE_DEVICE(device: string) {
|
||||
this.device = device;
|
||||
|
||||
30
src/store/modules/epTheme.ts
Normal file
30
src/store/modules/epTheme.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { store } from "/@/store";
|
||||
import { defineStore } from "pinia";
|
||||
import { getConfig } from "/@/config";
|
||||
import { storageLocal } from "/@/utils/storage";
|
||||
|
||||
export const useEpThemeStore = defineStore({
|
||||
id: "pure-epTheme",
|
||||
state: () => ({
|
||||
epThemeColor:
|
||||
storageLocal.getItem("responsive-layout")?.epThemeColor ??
|
||||
getConfig().EpThemeColor
|
||||
}),
|
||||
getters: {
|
||||
getEpThemeColor() {
|
||||
return this.epThemeColor;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setEpThemeColor(newColor) {
|
||||
const layout = storageLocal.getItem("responsive-layout");
|
||||
this.epThemeColor = newColor;
|
||||
layout.epThemeColor = newColor;
|
||||
storageLocal.setItem("responsive-layout", layout);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export function useEpThemeStoreHook() {
|
||||
return useEpThemeStore(store);
|
||||
}
|
||||
@@ -8,21 +8,21 @@ export const useMultiTagsStore = defineStore({
|
||||
id: "pure-multiTags",
|
||||
state: () => ({
|
||||
// 存储标签页信息(路由信息)
|
||||
multiTags: storageLocal.getItem("responsive-sets").multiTagsCache
|
||||
multiTags: storageLocal.getItem("responsive-configure").multiTagsCache
|
||||
? storageLocal.getItem("responsive-tags")
|
||||
: [
|
||||
{
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
icon: "el-icon-s-home",
|
||||
title: "menus.hshome",
|
||||
icon: "HomeFilled",
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
}
|
||||
],
|
||||
multiTagsCache: storageLocal.getItem("responsive-sets").multiTagsCache
|
||||
multiTagsCache: storageLocal.getItem("responsive-configure").multiTagsCache
|
||||
}),
|
||||
getters: {
|
||||
getMultiTagsCache() {
|
||||
@@ -55,31 +55,30 @@ export const useMultiTagsStore = defineStore({
|
||||
case "push":
|
||||
{
|
||||
const tagVal = value as multiType;
|
||||
const tagPath = tagVal?.path;
|
||||
// 判断tag是否已存在
|
||||
const tagHasExits = this.multiTags.some(tag => {
|
||||
return tag.path === tagVal?.path;
|
||||
return tag.path === tagPath;
|
||||
});
|
||||
|
||||
// 判断tag中的query键值是否相等
|
||||
const tagQueryHasExits = this.multiTags.some(tag => {
|
||||
return isEqual(tag.query, tagVal.query);
|
||||
return isEqual(tag.query, tagVal?.query);
|
||||
});
|
||||
|
||||
if (tagHasExits && tagQueryHasExits) return;
|
||||
|
||||
const meta = tagVal?.meta;
|
||||
const dynamicLevel = meta?.dynamicLevel ?? -1;
|
||||
const dynamicLevel = tagVal?.meta?.dynamicLevel ?? -1;
|
||||
if (dynamicLevel > 0) {
|
||||
// dynamicLevel动态路由可打开的数量
|
||||
const realPath = meta?.realPath ?? "";
|
||||
// 获取到已经打开的动态路由数, 判断是否大于dynamicLevel
|
||||
if (
|
||||
this.multiTags.filter(e => e.meta?.realPath ?? "" === realPath)
|
||||
.length >= dynamicLevel
|
||||
this.multiTags.filter(e => e?.path === tagPath).length >=
|
||||
dynamicLevel
|
||||
) {
|
||||
// 关闭第一个
|
||||
const index = this.multiTags.findIndex(
|
||||
item => item.meta?.realPath === realPath
|
||||
item => item?.path === tagPath
|
||||
);
|
||||
index !== -1 && this.multiTags.splice(index, 1);
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ export type multiType = {
|
||||
path: string;
|
||||
parentPath: string;
|
||||
name: string;
|
||||
query: object;
|
||||
meta: any;
|
||||
query?: object;
|
||||
};
|
||||
|
||||
export type setType = {
|
||||
|
||||
@@ -58,8 +58,8 @@ export const useUserStore = defineStore({
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
icon: "el-icon-s-home",
|
||||
title: "menus.hshome",
|
||||
icon: "HomeFilled",
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
|
||||
29
src/style/dark.scss
Normal file
29
src/style/dark.scss
Normal file
@@ -0,0 +1,29 @@
|
||||
/* 暗黑模式 */
|
||||
[data-theme="dark"] {
|
||||
filter: invert(0.9) hue-rotate(180deg);
|
||||
|
||||
#mse,
|
||||
img,
|
||||
.icon-svg,
|
||||
.login-container {
|
||||
filter: invert(1) hue-rotate(180deg);
|
||||
}
|
||||
|
||||
// element plus
|
||||
.el-radio-button__original-radio:checked + .el-radio-button__inner,
|
||||
.el-image-viewer__close,
|
||||
.el-image-viewer__actions__inner,
|
||||
.el-image-viewer__next,
|
||||
.el-image-viewer__prev {
|
||||
color: #000 !important;
|
||||
}
|
||||
|
||||
.el-overlay {
|
||||
background-color: rgba(0, 0, 0, 0.05) !important;
|
||||
}
|
||||
|
||||
.el-drawer {
|
||||
box-shadow: 0 8px 10px -5px rgb(0 0 0 / 1%), 0 16px 24px 2px rgb(0 0 0 / 2%),
|
||||
0 6px 30px 5px rgb(0 0 0 / 1%);
|
||||
}
|
||||
}
|
||||
@@ -35,3 +35,30 @@
|
||||
.is-dark {
|
||||
z-index: 99999 !important;
|
||||
}
|
||||
|
||||
/* 动态改变cssvar 用于主题切换 https://github.com/element-plus/element-plus/issues/4856#issuecomment-1000174357 */
|
||||
.el-button--primary {
|
||||
--el-button-bg-color: var(--el-color-primary) !important;
|
||||
--el-button-border-color: var(--el-color-primary) !important;
|
||||
--el-button-hover-bg-color: var(--el-color-primary-light-2) !important;
|
||||
--el-button-hover-border-color: var(--el-color-primary-light-2) !important;
|
||||
--el-button-active-bg-color: var(--el-color-primary-active) !important;
|
||||
--el-button-active-border-color: var(--el-color-primary-active) !important;
|
||||
}
|
||||
|
||||
/* nprogress适配ep的primary */
|
||||
#nprogress {
|
||||
& .bar {
|
||||
background-color: var(--el-color-primary) !important;
|
||||
}
|
||||
|
||||
& .peg {
|
||||
box-shadow: 0 0 10px var(--el-color-primary),
|
||||
0 0 5px var(--el-color-primary) !important;
|
||||
}
|
||||
|
||||
& .spinner-icon {
|
||||
border-top-color: var(--el-color-primary);
|
||||
border-left-color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
@import "./transition.scss";
|
||||
@import "./element-plus.scss";
|
||||
@import "./sidebar.scss";
|
||||
@import "./dark.scss";
|
||||
|
||||
body {
|
||||
width: 100%;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.container {
|
||||
.login-container {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: grid;
|
||||
@@ -183,7 +183,7 @@ a:hover {
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1080px) {
|
||||
.container {
|
||||
.login-container {
|
||||
grid-gap: 9rem;
|
||||
}
|
||||
}
|
||||
@@ -217,7 +217,7 @@ a:hover {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.container {
|
||||
.login-container {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
|
||||
@@ -568,6 +568,7 @@
|
||||
body[layout="vertical"] {
|
||||
$sideBarWidth: 210px;
|
||||
@include merge-style($sideBarWidth);
|
||||
|
||||
.el-menu--collapse {
|
||||
width: 54px;
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ http.request('get', '/xxx?message=' + msg);
|
||||
import { http } from "/@/utils/http";
|
||||
|
||||
// params传参
|
||||
http.request('get', '/xxx', { params: param });
|
||||
http.request('post', '/xxx', { params: param });
|
||||
|
||||
// data传参
|
||||
http.request('get', '/xxx', { data: param });
|
||||
http.request('post', '/xxx', { data: param });
|
||||
```
|
||||
|
||||
@@ -17,15 +17,20 @@ export const injectResponsiveStorage = (app: App, config: ServerConfigs) => {
|
||||
type: Object,
|
||||
default: Storage.getData(undefined, "layout") ?? {
|
||||
layout: config.Layout ?? "vertical",
|
||||
theme: config.Theme ?? "default"
|
||||
theme: config.Theme ?? "default",
|
||||
darkMode: config.DarkMode ?? false,
|
||||
sidebarStatus: config.SidebarStatus ?? true,
|
||||
epThemeColor: config.EpThemeColor ?? "409EFF"
|
||||
}
|
||||
},
|
||||
sets: {
|
||||
configure: {
|
||||
type: Object,
|
||||
default: Storage.getData(undefined, "sets") ?? {
|
||||
default: Storage.getData(undefined, "configure") ?? {
|
||||
grey: config.Grey ?? false,
|
||||
weak: config.Weak ?? false,
|
||||
hideTabs: config.HideTabs ?? false,
|
||||
showLogo: config.ShowLogo ?? true,
|
||||
showModel: config.ShowModel ?? "smart",
|
||||
multiTagsCache: config.MultiTagsCache ?? false
|
||||
}
|
||||
}
|
||||
@@ -40,7 +45,7 @@ export const injectResponsiveStorage = (app: App, config: ServerConfigs) => {
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
title: "menus.hshome",
|
||||
i18n: true,
|
||||
icon: "HomeFilled",
|
||||
showLink: true
|
||||
|
||||
93
src/views/guide/index.vue
Normal file
93
src/views/guide/index.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "reGuide"
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Driver from "driver.js";
|
||||
import "driver.js/dist/driver.min.css";
|
||||
|
||||
// 步骤
|
||||
const steps = [
|
||||
{
|
||||
element: "#header-notice",
|
||||
popover: {
|
||||
title: "消息通知",
|
||||
description: "你可以在这里查看管理员发送的消息",
|
||||
position: "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
element: "#header-screenfull",
|
||||
popover: {
|
||||
title: "全屏",
|
||||
description: "你可以在这里进行全屏切换",
|
||||
position: "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
element: "#header-translation",
|
||||
popover: {
|
||||
title: "国际化",
|
||||
description: "你可以在这里进行语言切换",
|
||||
position: "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
element: ".el-icon-setting",
|
||||
popover: {
|
||||
title: "项目配置",
|
||||
description: "你可以在这里查看项目配置",
|
||||
position: "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
element: ".tags-view",
|
||||
popover: {
|
||||
title: "多标签页",
|
||||
description: "这里是你访问过的页面的历史",
|
||||
position: "buttom"
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const driver = new Driver({
|
||||
className: "scoped-class",
|
||||
animate: true,
|
||||
opacity: 0.75,
|
||||
padding: 0,
|
||||
allowClose: true,
|
||||
overlayClickNext: false,
|
||||
doneBtnText: "完成",
|
||||
closeBtnText: "关闭",
|
||||
nextBtnText: "下一步",
|
||||
prevBtnText: "上一步"
|
||||
});
|
||||
|
||||
const guide = () => {
|
||||
driver.defineSteps(steps);
|
||||
driver.start();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<p>引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能</p>
|
||||
<el-button
|
||||
type="primary"
|
||||
style="margin-top: 10px"
|
||||
@click.prevent.stop="guide"
|
||||
>
|
||||
打开引导页
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
div#driver-highlighted-element-stage,
|
||||
div#driver-page-overlay {
|
||||
background: transparent !important;
|
||||
outline: 5000px solid rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
</style>
|
||||
@@ -71,7 +71,7 @@ function onPwdBlur() {
|
||||
|
||||
<template>
|
||||
<img :src="bg" class="wave" />
|
||||
<div class="container">
|
||||
<div class="login-container">
|
||||
<div class="img">
|
||||
<component :is="currentWeek"></component>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<p>{{ $t("message.hsmenu1") }}</p>
|
||||
<p style="text-indent: 2em">{{ $t("message.hsmenu1-1") }}</p>
|
||||
<p>{{ $t("menus.hsmenu1") }}</p>
|
||||
<p style="text-indent: 2em">{{ $t("menus.hsmenu1-1") }}</p>
|
||||
<el-input v-model="input" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<p>{{ $t("message.hsmenu1") }}</p>
|
||||
<p style="text-indent: 2em">{{ $t("message.hsmenu1-2") }}</p>
|
||||
<p style="text-indent: 4em">{{ $t("message.hsmenu1-2-1") }}</p>
|
||||
<p>{{ $t("menus.hsmenu1") }}</p>
|
||||
<p style="text-indent: 2em">{{ $t("menus.hsmenu1-2") }}</p>
|
||||
<p style="text-indent: 4em">{{ $t("menus.hsmenu1-2-1") }}</p>
|
||||
<el-input v-model="input" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<p>{{ $t("message.hsmenu1") }}</p>
|
||||
<p style="text-indent: 2em">{{ $t("message.hsmenu1-2") }}</p>
|
||||
<p style="text-indent: 4em">{{ $t("message.hsmenu1-2-2") }}</p>
|
||||
<p>{{ $t("menus.hsmenu1") }}</p>
|
||||
<p style="text-indent: 2em">{{ $t("menus.hsmenu1-2") }}</p>
|
||||
<p style="text-indent: 4em">{{ $t("menus.hsmenu1-2-2") }}</p>
|
||||
<el-input v-model="input" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<p>{{ $t("message.hsmenu1") }}</p>
|
||||
<p style="text-indent: 2em">{{ $t("message.hsmenu1-3") }}</p>
|
||||
<p>{{ $t("menus.hsmenu1") }}</p>
|
||||
<p style="text-indent: 2em">{{ $t("menus.hsmenu1-3") }}</p>
|
||||
<el-input v-model="input" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<p>{{ $t("message.hsmenu2") }}</p>
|
||||
<p>{{ $t("menus.hsmenu2") }}</p>
|
||||
<el-input v-model="input" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -101,13 +101,13 @@ const checkboxChangeEvent: VxeTableEvents.CheckboxChange = ({ records }) => {
|
||||
<template #default="{ row }">
|
||||
<vxe-button
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
icon="fa fa-pencil-square-o"
|
||||
@click="editConfig(row)"
|
||||
>编辑</vxe-button
|
||||
>
|
||||
<vxe-button
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
icon="fa fa-trash-o"
|
||||
@click="delConfig(row)"
|
||||
>删除</vxe-button
|
||||
>
|
||||
@@ -140,7 +140,7 @@ const checkboxChangeEvent: VxeTableEvents.CheckboxChange = ({ records }) => {
|
||||
<span class="select-count"
|
||||
>已选中{{ configData.selectRecords.length }}条</span
|
||||
>
|
||||
<vxe-button size="small">{{ $t("message.hsdelete") }}</vxe-button>
|
||||
<vxe-button size="small">{{ $t("buttons.hsdelete") }}</vxe-button>
|
||||
</span>
|
||||
</template>
|
||||
</vxe-pager>
|
||||
@@ -179,10 +179,4 @@ const checkboxChangeEvent: VxeTableEvents.CheckboxChange = ({ records }) => {
|
||||
:deep(.el-divider--horizontal) {
|
||||
margin: 13px 0;
|
||||
}
|
||||
|
||||
:deep(.el-icon-close) {
|
||||
&:hover {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -209,28 +209,28 @@ function handleClose() {
|
||||
<template #buttons>
|
||||
<vxe-input
|
||||
v-model="dictData.filterName"
|
||||
:placeholder="$t('message.hssearch')"
|
||||
:placeholder="$t('buttons.hssearch')"
|
||||
@keyup="searchEvent"
|
||||
></vxe-input>
|
||||
</template>
|
||||
<template #tools>
|
||||
<vxe-button
|
||||
icon="el-icon-circle-plus-outline"
|
||||
icon="fa fa-plus-square-o"
|
||||
status="primary"
|
||||
@click="onAdd"
|
||||
>{{ $t("message.hsadd") }}</vxe-button
|
||||
>{{ $t("buttons.hsadd") }}</vxe-button
|
||||
>
|
||||
<vxe-button
|
||||
icon="el-icon-folder-opened"
|
||||
icon="fa fa-folder-open-o"
|
||||
status="primary"
|
||||
@click="$refs.xTree.setAllTreeExpand(true)"
|
||||
>{{ $t("message.hsexpendAll") }}</vxe-button
|
||||
>{{ $t("buttons.hsexpendAll") }}</vxe-button
|
||||
>
|
||||
<vxe-button
|
||||
icon="el-icon-folder"
|
||||
icon="fa fa-folder-o"
|
||||
status="primary"
|
||||
@click="$refs.xTree.clearTreeExpand()"
|
||||
>{{ $t("message.hscollapseAll") }}</vxe-button
|
||||
>{{ $t("buttons.hscollapseAll") }}</vxe-button
|
||||
>
|
||||
</template>
|
||||
</vxe-toolbar>
|
||||
@@ -266,23 +266,26 @@ function handleClose() {
|
||||
</vxe-table-column>
|
||||
<vxe-table-column title="操作" width="330" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<vxe-button type="text" icon="el-icon-edit" @click="onEdit(row)"
|
||||
<vxe-button
|
||||
type="text"
|
||||
icon="fa fa-pencil-square-o"
|
||||
@click="onEdit(row)"
|
||||
>编辑</vxe-button
|
||||
>
|
||||
<vxe-button
|
||||
type="text"
|
||||
icon="el-icon-circle-plus-outline"
|
||||
icon="fa fa-plus-square-o"
|
||||
@click="onAddChild(row)"
|
||||
>新增子类型</vxe-button
|
||||
>
|
||||
<vxe-button
|
||||
v-show="row.model"
|
||||
type="text"
|
||||
icon="el-icon-setting"
|
||||
icon="fa fa-cog"
|
||||
@click="onDeploy(row)"
|
||||
>字典配置</vxe-button
|
||||
>
|
||||
<vxe-button type="text" icon="el-icon-delete" @click="confirmEvent"
|
||||
<vxe-button type="text" icon="fa fa-trash-o" @click="confirmEvent"
|
||||
>删除</vxe-button
|
||||
>
|
||||
</template>
|
||||
|
||||
@@ -6,6 +6,7 @@ export default {
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive } from "vue";
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import { VxeGridProps } from "vxe-table";
|
||||
|
||||
const gridOptions = reactive({
|
||||
@@ -29,19 +30,19 @@ const gridOptions = reactive({
|
||||
buttons: [
|
||||
{
|
||||
code: "insert_actived",
|
||||
name: "message.hsadd",
|
||||
name: $t("buttons.hsadd"),
|
||||
status: "perfect",
|
||||
icon: "fa fa-plus"
|
||||
},
|
||||
{
|
||||
code: "mark_cancel",
|
||||
name: "message.hsmark",
|
||||
name: $t("buttons.hsmark"),
|
||||
status: "perfect",
|
||||
icon: "fa fa-trash-o"
|
||||
},
|
||||
{
|
||||
code: "save",
|
||||
name: "message.hssave",
|
||||
name: $t("buttons.hssave"),
|
||||
status: "perfect",
|
||||
icon: "fa fa-save"
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@ function toDetail(index: number) {
|
||||
title: { zh: `No.${index} - 详情信息`, en: `No.${index} - DetailInfo` },
|
||||
showLink: false,
|
||||
i18n: false,
|
||||
dynamicLevel: 3,
|
||||
realPath: "/tabs/detail"
|
||||
dynamicLevel: 3
|
||||
}
|
||||
});
|
||||
router.push({ name: "tabDetail", query: { id: String(index) } });
|
||||
@@ -31,12 +30,7 @@ function toDetail(index: number) {
|
||||
title="标签页复用超出限制自动关闭(使用场景: 动态路由)"
|
||||
name="tag"
|
||||
>
|
||||
<el-button
|
||||
v-for="index in 6"
|
||||
:key="index"
|
||||
size="medium"
|
||||
@click="toDetail(index)"
|
||||
>
|
||||
<el-button v-for="index in 6" :key="index" @click="toDetail(index)">
|
||||
打开{{ index }}详情页
|
||||
</el-button>
|
||||
</el-collapse-item>
|
||||
@@ -63,9 +63,7 @@ const openDepot = (): void => {
|
||||
>
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div>
|
||||
<span>GitHub信息</span>
|
||||
</div>
|
||||
<span style="font-size: 16px; font-weight: 500">GitHub信息</span>
|
||||
</template>
|
||||
<el-skeleton animated :rows="7" :loading="loading">
|
||||
<template #default>
|
||||
@@ -97,9 +95,9 @@ const openDepot = (): void => {
|
||||
>
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div>
|
||||
<span>GitHub滚动信息</span>
|
||||
</div>
|
||||
<span style="font-size: 16px; font-weight: 500"
|
||||
>GitHub滚动信息</span
|
||||
>
|
||||
</template>
|
||||
<el-skeleton animated :rows="7" :loading="loading">
|
||||
<template #default>
|
||||
@@ -131,9 +129,9 @@ const openDepot = (): void => {
|
||||
>
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div>
|
||||
<span>GitHub饼图信息</span>
|
||||
</div>
|
||||
<span style="font-size: 16px; font-weight: 500"
|
||||
>GitHub饼图信息</span
|
||||
>
|
||||
</template>
|
||||
<el-skeleton animated :rows="7" :loading="loading">
|
||||
<template #default>
|
||||
@@ -165,9 +163,9 @@ const openDepot = (): void => {
|
||||
>
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div>
|
||||
<span>GitHub折线图信息</span>
|
||||
</div>
|
||||
<span style="font-size: 16px; font-weight: 500"
|
||||
>GitHub折线图信息</span
|
||||
>
|
||||
</template>
|
||||
<el-skeleton animated :rows="7" :loading="loading">
|
||||
<template #default>
|
||||
@@ -199,9 +197,9 @@ const openDepot = (): void => {
|
||||
>
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div>
|
||||
<span>GitHub柱状图信息</span>
|
||||
</div>
|
||||
<span style="font-size: 16px; font-weight: 500"
|
||||
>GitHub柱状图信息</span
|
||||
>
|
||||
</template>
|
||||
<el-skeleton animated :rows="7" :loading="loading">
|
||||
<template #default>
|
||||
|
||||
5
types/global.d.ts
vendored
5
types/global.d.ts
vendored
@@ -82,9 +82,14 @@ declare global {
|
||||
Locale?: string;
|
||||
Layout?: string;
|
||||
Theme?: string;
|
||||
DarkMode?: boolean;
|
||||
Grey?: boolean;
|
||||
Weak?: boolean;
|
||||
HideTabs?: boolean;
|
||||
SidebarStatus?: boolean;
|
||||
EpThemeColor?: string;
|
||||
ShowLogo?: boolean;
|
||||
ShowModel?: string;
|
||||
MapConfigure?: {
|
||||
amapKey?: string;
|
||||
options: {
|
||||
|
||||
Reference in New Issue
Block a user