版本升级到v3:element-plus升级到v2、引入国际化、pinia
This commit is contained in:
parent
4b4b49011e
commit
7cc3274ebc
@ -24,7 +24,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-21 12:51:42
|
||||
* @LastEditTime: 2022-09-24 16:29:19
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -71,5 +71,6 @@ module.exports = {
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/no-unused-components': 'warn',
|
||||
'vue/no-setup-props-destructure': 'off',
|
||||
'vue/script-setup-uses-vars': 'off',
|
||||
},
|
||||
}
|
||||
|
||||
16
mock/menu.js
16
mock/menu.js
@ -24,7 +24,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-07-26 16:43:22
|
||||
* @LastEditTime: 2022-09-27 18:51:22
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -51,10 +51,10 @@ export default [
|
||||
name: 'testEdit',
|
||||
title: '编辑',
|
||||
},
|
||||
{
|
||||
name: 'testAuth',
|
||||
title: '权限测试',
|
||||
},
|
||||
// {
|
||||
// name: 'testAuth',
|
||||
// title: '权限测试',
|
||||
// },
|
||||
{
|
||||
name: 'test-cache',
|
||||
title: '该页面可缓存',
|
||||
@ -83,12 +83,6 @@ export default [
|
||||
},
|
||||
]
|
||||
|
||||
if (query.role === 'admin')
|
||||
childs.push({
|
||||
name: 'testNoAuth',
|
||||
title: '权限页面',
|
||||
})
|
||||
|
||||
return {
|
||||
code: 200,
|
||||
message: '获取菜单成功',
|
||||
|
||||
26
mock/test.js
26
mock/test.js
@ -3,7 +3,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-21 09:39:02
|
||||
* @LastEditTime: 2022-09-25 12:27:50
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -44,4 +44,28 @@ export default [
|
||||
data: null,
|
||||
},
|
||||
},
|
||||
// 请求用户列表
|
||||
{
|
||||
url: '/api/test/users',
|
||||
method: 'post',
|
||||
timeout: 1000,
|
||||
response: () => {
|
||||
// 响应内容
|
||||
return {
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: {
|
||||
'list|10': [
|
||||
{
|
||||
'id|+1': 1,
|
||||
nickName: '@cname()',
|
||||
userEmail: '@email()',
|
||||
'status|1': [0, 1],
|
||||
},
|
||||
],
|
||||
'total|50-1000': 1,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
3686
package-lock.json
generated
3686
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vue3-element-admin",
|
||||
"version": "2.1.0",
|
||||
"version": "3.0.0",
|
||||
"author": {
|
||||
"name": "huzhushan",
|
||||
"email": "huzhushan@126.com",
|
||||
@ -21,19 +21,21 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"axios": "^0.21.1",
|
||||
"vue": "^3.0.5",
|
||||
"vue": "3.2.33",
|
||||
"vue-router": "^4.0.5",
|
||||
"vuex": "^4.0.0"
|
||||
"vuex": "^4.0.0",
|
||||
"pinia": "^2.0.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ehutch79/vite-eslint": "0.0.1",
|
||||
"@vitejs/plugin-vue": "^1.1.5",
|
||||
"@vue/compiler-sfc": "^3.0.5",
|
||||
"@vitejs/plugin-vue": "^1.2.3",
|
||||
"@vue/compiler-sfc": "^3.1.2",
|
||||
"@vue/eslint-config-prettier": "^6.0.0",
|
||||
"autoprefixer": "^10.2.5",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"crypto-js": "^4.0.0",
|
||||
"element-plus": "^1.0.2-beta.71",
|
||||
"element-plus": "^2.2.13",
|
||||
"vue-i18n": "^9.0.0",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"eslint-plugin-vue": "^7.0.0-0",
|
||||
@ -42,7 +44,7 @@
|
||||
"mockjs": "^1.1.0",
|
||||
"prettier": "^1.19.1",
|
||||
"sass": "^1.41.1",
|
||||
"vite": "^2.1.0",
|
||||
"vite": "^2.3.7",
|
||||
"vite-plugin-mock": "^2.3.0",
|
||||
"vite-plugin-svg-icons": "^0.4.0"
|
||||
},
|
||||
|
||||
22
src/App.vue
22
src/App.vue
@ -24,15 +24,14 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-18 13:17:44
|
||||
* @LastEditTime: 2022-09-26 12:14:10
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
-->
|
||||
|
||||
<template>
|
||||
<el-config-provider :locale="locale">
|
||||
<el-config-provider :locale="locales[lang]">
|
||||
<router-view />
|
||||
</el-config-provider>
|
||||
</template>
|
||||
@ -40,16 +39,22 @@
|
||||
<script>
|
||||
import { defineComponent } from 'vue'
|
||||
import { ElConfigProvider } from 'element-plus'
|
||||
|
||||
import zhCn from 'element-plus/lib/locale/lang/zh-cn'
|
||||
import localeZH from 'element-plus/lib/locale/lang/zh-cn'
|
||||
import localeEN from 'element-plus/lib/locale/lang/en'
|
||||
import useLang from '@/i18n/useLang'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
[ElConfigProvider.name]: ElConfigProvider,
|
||||
},
|
||||
data() {
|
||||
setup() {
|
||||
const { lang } = useLang()
|
||||
return {
|
||||
locale: zhCn,
|
||||
lang,
|
||||
locales: {
|
||||
'zh-cn': localeZH,
|
||||
en: localeEN,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
@ -63,5 +68,8 @@ body,
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
* {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 16:35:04
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-21 09:37:00
|
||||
* @LastEditTime: 2022-09-25 11:50:39
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -18,3 +18,12 @@ export const TestError = () => {
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
// 用户列表
|
||||
export const getUsers = data => {
|
||||
return request({
|
||||
url: '/api/test/users',
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
/* 改变主题色变量 */
|
||||
$--colors: (
|
||||
'primary': (
|
||||
'base': $mainColor,
|
||||
/**如果需要修改其它变量,可以在以下文件中查找
|
||||
* https://github.com/element-plus/element-plus/blob/dev/packages/theme-chalk/src/common/var.scss
|
||||
*/
|
||||
|
||||
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
|
||||
$colors: (
|
||||
'primary': (
|
||||
'base': $mainColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
/* 改变 icon 字体路径变量,必需 */
|
||||
$--font-path: 'element-plus/lib/theme-chalk/fonts';
|
||||
@import 'element-plus/packages/theme-chalk/src/reset';
|
||||
@import 'element-plus/packages/theme-chalk/src/index';
|
||||
@use "element-plus/theme-chalk/src/reset.scss" as *;
|
||||
@use "element-plus/theme-chalk/src/index.scss" as *;
|
||||
|
||||
1
src/assets/svg/icon-home.svg
Normal file
1
src/assets/svg/icon-home.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M510.72 41.856l435.2 361.024a32 32 0 0 1-36.16 52.48l-4.736-3.2-41.024-34.048V832c0 48.832-32.64 90.752-76.864 95.552l-8.448 0.448H245.312c-45.696 0-80.96-39.04-84.928-86.912L160 832V407.808l-55.04 44.608a32 32 0 0 1-40.96-0.64l-4.032-4.16a32 32 0 0 1 0.64-40.96l4.096-4.032L510.784 41.856z m-0.512 82.688L223.232 356.672a31.808 31.808 0 0 1 0.256 1.152l0.512 5.76V832c0 16.768 8.64 28.992 17.92 31.552l3.392 0.448h533.376c9.216 0 18.88-10.432 20.928-25.92L800 832V364.992L510.208 124.544z" /></svg>
|
||||
|
After Width: | Height: | Size: 766 B |
1
src/assets/svg/language.svg
Normal file
1
src/assets/svg/language.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1664017268288" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2638" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M848.805886 805.572222c70.998007-81.260745 109.779266-184.217628 109.779266-293.14448 0-119.204939-46.421262-231.277434-130.713041-315.569212C744.876861 113.862257 634.94103 67.61598 517.788843 66.213028c-1.924839-0.599657-10.290367-0.592494-12.227486 0.01535C388.878868 67.945485 279.434224 114.159016 196.73471 196.85853 113.863281 279.730982 67.630307 389.460106 66.095347 506.415818c-0.428765 1.64957-0.436952 8.601912-0.021489 10.226922 1.082658 117.628024 47.364751 228.058113 130.660852 311.354214 84.291778 84.291778 196.36325 130.713041 315.569212 130.713041 119.204939 0 231.277434-46.421262 315.569212-130.713041 6.139837-6.139837 12.054547-12.444427 17.789155-18.871813 0.50756-0.453325 1.001817-0.928139 1.471514-1.440815C847.750857 807.012014 848.295256 806.299793 848.805886 805.572222zM107.447151 532.043499l187.501418 0c1.322112 65.678862 9.253758 127.264499 22.505573 182.112688-61.690014 16.687054-100.819197 38.371936-121.076566 51.906184C144.30971 701.336206 111.676475 620.35687 107.447151 532.043499zM195.881272 259.408121c20.090571 13.556761 59.242266 35.461653 121.340579 52.260248-12.998035 54.127781-20.827351 114.778116-22.243607 179.432649L107.525945 491.101018C112.076588 403.731134 144.437623 323.612399 195.881272 259.408121zM917.081898 491.099994 729.628576 491.099994c-1.415232-64.630996-9.240455-125.260865-22.229281-179.37432 61.95505-16.693194 101.235682-38.444591 121.56673-52.020794C880.270505 323.860039 912.537396 403.866211 917.081898 491.099994zM688.677908 491.099994 532.167319 491.099994 532.167319 335.061149c52.209082-1.094938 97.103572-6.453992 135.272893-14.033621C680.000272 373.163955 687.286212 430.896844 688.677908 491.099994zM532.167319 294.115598 532.167319 109.918435c36.84107 10.398838 72.779583 49.205679 100.926644 110.015649 8.810666 19.035542 16.645099 39.641859 23.464411 61.521169C621.531626 288.227494 580.261687 293.062616 532.167319 294.115598zM491.223814 110.273523l0 183.805236c-47.504944-1.12666-88.378863-6.001691-123.120109-12.802584 6.807033-21.812795 14.623046-42.35976 23.409153-61.344137C419.351903 159.792333 454.809463 121.175827 491.223814 110.273523zM491.223814 335.040682l0 156.059312L335.928912 491.099994c1.391696-60.213383 8.679683-117.955482 21.243837-170.099073C395.008472 328.536548 439.487499 333.887416 491.223814 335.040682zM335.893096 532.043499l155.330718 0 0 158.667719c-51.609425 1.194198-96.019891 6.563486-133.821845 14.103206C344.576873 651.927913 337.193719 593.243349 335.893096 532.043499zM491.223814 731.672118l0 182.909843c-36.415374-10.902304-71.871911-49.51881-99.709933-109.659539-8.679683-18.752086-16.409738-39.034015-23.157419-60.551074C402.9964 737.645157 443.773106 732.820268 491.223814 731.672118zM532.167319 914.937049 532.167319 731.608673c47.904033 1.025353 89.103364 5.862521 124.116809 12.656251-6.755868 21.555945-14.497179 41.87369-23.190165 60.656475C604.946902 865.73137 569.008388 904.538211 532.167319 914.937049zM532.167319 690.660052 532.167319 532.043499l156.546406 0c-1.298576 61.096497-8.66024 119.68487-21.445428 172.502819C629.154233 697.013761 584.319096 691.710988 532.167319 690.660052zM729.659275 532.043499l187.501418 0c-4.221138 88.138386-36.732599 168.973436-88.620363 233.635131-20.469194-13.668301-59.635215-35.298947-121.30374-51.868321C720.43724 659.049101 728.33921 597.585237 729.659275 532.043499zM801.518906 228.742704c-18.329461 11.570523-52.309366 29.355585-104.858186 43.493583-19.295462-63.056128-46.110177-115.004267-78.06189-150.97655C689.00025 140.410913 751.833297 178.097234 801.518906 228.742704zM406.007991 121.259738c-31.905664 35.920094-58.690704 87.768973-77.979002 150.702304-52.40351-14.241352-86.370113-32.099069-104.581893-43.587728C273.076422 177.914062 335.777463 140.364865 406.007991 121.259738zM223.917816 796.963147c18.284435-11.535731 52.098565-29.230742 104.332207-43.335994 19.271926 62.60485 45.976124 114.186645 77.757968 149.968593C335.99952 884.550994 273.472442 847.181899 223.917816 796.963147zM618.59883 903.595746c31.801287-35.803437 58.517765-87.426165 77.792761-150.08218 51.984978 14.023388 85.972047 31.631418 104.533798 43.208081C751.3329 847.061149 688.718841 884.521319 618.59883 903.595746z" p-id="2639"></path></svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@ -17,19 +17,16 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-23 14:56:06
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-23 15:00:31
|
||||
* @LastEditTime: 2022-09-27 16:07:53
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useAccount } from '@/pinia/modules/account'
|
||||
|
||||
export const useUserinfo = () => {
|
||||
const store = useStore()
|
||||
const userinfo = computed(() => store.state.account.userinfo)
|
||||
|
||||
const { userinfo } = storeToRefs(useAccount())
|
||||
return { userinfo }
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-21 09:18:32
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-21 12:45:38
|
||||
* @LastEditTime: 2022-09-27 17:50:59
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -111,18 +111,20 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref, computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { defineComponent, ref } from 'vue'
|
||||
import { useErrorlog } from '@/pinia/modules/errorLog'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ErrorLog',
|
||||
setup() {
|
||||
const dialogTableVisible = ref(false)
|
||||
const store = useStore()
|
||||
const errorLogs = computed(() => store.state.errorLog.logs)
|
||||
const errorStore = useErrorlog()
|
||||
const { logs: errorLogs } = storeToRefs(errorStore)
|
||||
const { clearErrorLog } = errorStore
|
||||
const clearAll = () => {
|
||||
dialogTableVisible.value = false
|
||||
store.dispatch('errorLog/clearErrorLog')
|
||||
clearErrorLog()
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-29 15:04:03
|
||||
* @LastEditTime: 2022-09-25 11:53:47
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -45,7 +45,7 @@
|
||||
<el-form-item
|
||||
v-for="item in search.fields"
|
||||
:key="item.name"
|
||||
:label="item.label"
|
||||
:label="$t(item.label)"
|
||||
:prop="item.name"
|
||||
>
|
||||
<slot v-if="item.type === 'custom'" :name="item.slot" />
|
||||
@ -55,13 +55,13 @@
|
||||
:filterable="!!item.filterable"
|
||||
:multiple="!!item.multiple"
|
||||
clearable
|
||||
:placeholder="`请选择${item.label}`"
|
||||
:placeholder="$t(item.label)"
|
||||
:style="{ width: search.inputWidth, ...item.style }"
|
||||
>
|
||||
<el-option
|
||||
v-for="option of item.options"
|
||||
:key="option.value"
|
||||
:label="option.name"
|
||||
:label="$t(option.name)"
|
||||
:value="option.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
@ -75,7 +75,7 @@
|
||||
:key="option.value"
|
||||
:label="option.value"
|
||||
>
|
||||
{{ option.name }}
|
||||
{{ $t(option.name) }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<el-radio-group
|
||||
@ -88,7 +88,7 @@
|
||||
:key="option.value"
|
||||
:label="option.value"
|
||||
>
|
||||
{{ option.name }}
|
||||
{{ $t(option.name) }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-checkbox-group
|
||||
@ -101,7 +101,7 @@
|
||||
:key="option.value"
|
||||
:label="option.value"
|
||||
>
|
||||
{{ option.name }}
|
||||
{{ $t(option.name) }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<el-checkbox-group
|
||||
@ -114,7 +114,7 @@
|
||||
:key="option.value"
|
||||
:label="option.value"
|
||||
>
|
||||
{{ option.name }}
|
||||
{{ $t(option.name) }}
|
||||
</el-checkbox-button>
|
||||
</el-checkbox-group>
|
||||
<el-date-picker
|
||||
@ -124,7 +124,7 @@
|
||||
format="YYYY-MM-DD"
|
||||
clearable
|
||||
@change="handleDateChange($event, item, 'YYYY-MM-DD')"
|
||||
:placeholder="`请选择${item.label}`"
|
||||
:placeholder="$t(item.label)"
|
||||
:style="{ width: search.inputWidth, ...item.style }"
|
||||
></el-date-picker>
|
||||
<el-date-picker
|
||||
@ -134,7 +134,7 @@
|
||||
clearable
|
||||
@change="handleDateChange($event, item, 'YYYY-MM-DD HH:mm:ss')"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
:placeholder="`请选择${item.label}`"
|
||||
:placeholder="$t(item.label)"
|
||||
:style="{ width: search.inputWidth, ...item.style }"
|
||||
></el-date-picker>
|
||||
<el-date-picker
|
||||
@ -143,11 +143,11 @@
|
||||
type="daterange"
|
||||
format="YYYY-MM-DD"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:start-placeholder="$t('public.startdate')"
|
||||
:end-placeholder="$t('public.enddate')"
|
||||
clearable
|
||||
@change="handleRangeChange($event, item, 'YYYY-MM-DD')"
|
||||
:style="{ width: search.inputWidth, ...item.style }"
|
||||
:style="{ ...item.style }"
|
||||
></el-date-picker>
|
||||
<el-date-picker
|
||||
v-else-if="item.type === 'datetimerange'"
|
||||
@ -155,16 +155,16 @@
|
||||
type="datetimerange"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
range-separator="-"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
:start-placeholder="$t('public.starttime')"
|
||||
:end-placeholder="$t('public.endtime')"
|
||||
clearable
|
||||
@change="handleRangeChange($event, item, 'YYYY-MM-DD HH:mm:ss')"
|
||||
:style="{ width: search.inputWidth, ...item.style }"
|
||||
:style="{ ...item.style }"
|
||||
></el-date-picker>
|
||||
<el-input-number
|
||||
v-else-if="item.type === 'number'"
|
||||
v-model="searchModel[item.name]"
|
||||
:placeholder="`请输入${item.label}`"
|
||||
:placeholder="$t(item.label)"
|
||||
controls-position="right"
|
||||
:min="item.min"
|
||||
:max="item.max"
|
||||
@ -176,7 +176,7 @@
|
||||
type="textarea"
|
||||
clearable
|
||||
v-model="searchModel[item.name]"
|
||||
:placeholder="`请输入${item.label}`"
|
||||
:placeholder="$t(item.label)"
|
||||
:style="{ width: search.inputWidth, ...item.style }"
|
||||
></el-input>
|
||||
<el-input
|
||||
@ -184,16 +184,16 @@
|
||||
:maxlength="item.maxlength"
|
||||
v-model="searchModel[item.name]"
|
||||
clearable
|
||||
:placeholder="`请输入${item.label}`"
|
||||
:placeholder="$t(item.label)"
|
||||
:style="{ width: search.inputWidth, ...item.style }"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item class="search-btn">
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
||||
查询
|
||||
<el-button type="primary" icon="Search" @click="handleSearch">
|
||||
{{ $t('public.search') }}
|
||||
</el-button>
|
||||
<el-button @click="handleReset" icon="el-icon-refresh-right">
|
||||
重置
|
||||
<el-button @click="handleReset" icon="RefreshRight">
|
||||
{{ $t('public.reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@ -224,6 +224,7 @@
|
||||
:filter-method="item.filters && filterHandler"
|
||||
:show-overflow-tooltip="!item.wrap"
|
||||
v-bind="item"
|
||||
:label="item.label ? $t(item.label) : ''"
|
||||
>
|
||||
<template #header="scope" v-if="!!item.labelSlot">
|
||||
<slot :name="item.labelSlot" v-bind="scope"></slot>
|
||||
@ -511,6 +512,9 @@ export default defineComponent({
|
||||
:deep(.el-input-number .el-input__inner) {
|
||||
text-align: left;
|
||||
}
|
||||
:deep(.el-range-editor.el-input__wrapper) {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
.head {
|
||||
@ -530,7 +534,7 @@ export default defineComponent({
|
||||
.pagination {
|
||||
padding: 0 20px 20px;
|
||||
background: #fff;
|
||||
text-align: right;
|
||||
justify-content: flex-end;
|
||||
:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
@ -27,19 +27,19 @@
|
||||
* @version:
|
||||
* @Date: 2021-09-01 13:58:08
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-29 10:10:32
|
||||
* @LastEditTime: 2022-09-27 18:31:22
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
|
||||
import store from '@/store'
|
||||
import { useAccount } from '@/pinia/modules/account'
|
||||
|
||||
export const Permission = app => {
|
||||
app.directive('permission', {
|
||||
mounted: function(el, binding) {
|
||||
const permissionList = store.state.account.permissionList || []
|
||||
const { permissionList } = useAccount()
|
||||
|
||||
if (
|
||||
binding.value &&
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-21 09:18:32
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-21 12:48:49
|
||||
* @LastEditTime: 2022-09-27 15:53:02
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -21,7 +21,8 @@
|
||||
*/
|
||||
|
||||
import { nextTick } from 'vue'
|
||||
import store from '@/store'
|
||||
import { useErrorlog } from './pinia/modules/errorLog'
|
||||
// import store from '@/store'
|
||||
|
||||
// 判断环境,决定是否开启错误监控
|
||||
// - import.meta.env.DEV 布尔值,代表开发环境
|
||||
@ -34,7 +35,7 @@ export default app => {
|
||||
if (flag) {
|
||||
app.config.errorHandler = function(err, vm, info) {
|
||||
nextTick(() => {
|
||||
store.dispatch('errorLog/addErrorLog', {
|
||||
useErrorlog().addErrorLog({
|
||||
err,
|
||||
// vm, // 这里不保存vm,否则渲染错误日志的时候控制台会有警告
|
||||
info,
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-09-18 09:32:01
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-18 17:54:29
|
||||
* @LastEditTime: 2022-09-24 14:43:31
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -23,4 +23,3 @@
|
||||
|
||||
export { default as SvgIcon } from '@/components/SvgIcon/index.vue'
|
||||
export { default as ProTable } from '@/components/ProTable/index.vue'
|
||||
export { default as ElSelectTree } from '@/components/SelectTree/index.vue'
|
||||
|
||||
@ -27,23 +27,23 @@
|
||||
* @version:
|
||||
* @Date: 2021-08-20 11:15:27
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-18 17:25:32
|
||||
* @LastEditTime: 2022-09-27 16:15:56
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
|
||||
import { useTags } from '@/pinia/modules/tags'
|
||||
import { reactive, toRefs, getCurrentInstance } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
// 关闭当前标签
|
||||
export default () => {
|
||||
const instance = getCurrentInstance()
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const { delTag } = useTags()
|
||||
const state = reactive({
|
||||
/**
|
||||
* @param {String} fullPath 要跳转到那个页面的地址
|
||||
@ -52,7 +52,7 @@ export default () => {
|
||||
* @return {*}
|
||||
*/
|
||||
closeTag({ fullPath, reload, f5 } = {}) {
|
||||
store.dispatch('tags/delTag', route)
|
||||
delTag(route)
|
||||
fullPath ? router.push(fullPath) : router.back()
|
||||
reload &&
|
||||
setTimeout(() => {
|
||||
|
||||
19
src/i18n/index.js
Normal file
19
src/i18n/index.js
Normal file
@ -0,0 +1,19 @@
|
||||
import { createI18n } from 'vue-i18n'
|
||||
|
||||
const getMessage = modules => {
|
||||
return Object.entries(modules).reduce((module, [path, mod]) => {
|
||||
const moduleName = path.replace(/^\.\/locales\/[\w-]+\/(.*)\.\w+$/, '$1')
|
||||
module[moduleName] = mod.default
|
||||
return module
|
||||
}, {})
|
||||
}
|
||||
|
||||
export default createI18n({
|
||||
locale: localStorage.getItem('__VEA__lang') || 'zh-cn',
|
||||
messages: {
|
||||
'zh-cn': getMessage(import.meta.globEager('./locales/zh-cn/**/*.js')),
|
||||
en: getMessage(import.meta.globEager('./locales/en/**/*.js')),
|
||||
},
|
||||
legacy: false,
|
||||
globalInjection: true,
|
||||
})
|
||||
6
src/i18n/locales/en/error.js
Normal file
6
src/i18n/locales/en/error.js
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
noauth: 'No access',
|
||||
servererror: 'Server error',
|
||||
notfound: 'Page not found',
|
||||
backhome: 'Back to Home',
|
||||
}
|
||||
10
src/i18n/locales/en/login.js
Normal file
10
src/i18n/locales/en/login.js
Normal file
@ -0,0 +1,10 @@
|
||||
export default {
|
||||
username: 'Username',
|
||||
password: 'Password',
|
||||
login: 'Login',
|
||||
logining: 'Login...',
|
||||
loginsuccess: 'Success',
|
||||
'rules-username': 'Please input username',
|
||||
'rules-password': 'Please input password',
|
||||
'rules-regpassword': '6 to 12 characters in length',
|
||||
}
|
||||
16
src/i18n/locales/en/menu.js
Normal file
16
src/i18n/locales/en/menu.js
Normal file
@ -0,0 +1,16 @@
|
||||
export default {
|
||||
homepage: 'Homepage',
|
||||
dashboard: 'Dashboard',
|
||||
test: 'Test page',
|
||||
testList: 'List',
|
||||
testAdd: 'Add',
|
||||
testEdit: 'Edit',
|
||||
testAuth: 'Auth',
|
||||
testNoAuth: 'No auth',
|
||||
'test-cache': 'Cache',
|
||||
'test-no-cache': 'No Cache',
|
||||
nest: 'Nest page',
|
||||
nestPage1: 'Page1',
|
||||
nestPage2: 'Page2',
|
||||
'test-error-log': 'Error log',
|
||||
}
|
||||
22
src/i18n/locales/en/public.js
Normal file
22
src/i18n/locales/en/public.js
Normal file
@ -0,0 +1,22 @@
|
||||
export default {
|
||||
sure: 'Sure',
|
||||
search: 'Search',
|
||||
reset: 'Reset',
|
||||
edit: 'Edit',
|
||||
add: 'Add',
|
||||
delete: 'Delete',
|
||||
save: 'Save',
|
||||
cancel: 'Cancel',
|
||||
yes: 'Yes',
|
||||
no: 'No',
|
||||
status: 'Status',
|
||||
operate: 'Operate',
|
||||
enabled: 'Enabled',
|
||||
disabled: 'Disabled',
|
||||
male: 'Male',
|
||||
female: 'Female',
|
||||
startdate: 'From',
|
||||
enddate: 'To',
|
||||
starttime: 'From',
|
||||
endtime: 'To',
|
||||
}
|
||||
8
src/i18n/locales/en/tags.js
Normal file
8
src/i18n/locales/en/tags.js
Normal file
@ -0,0 +1,8 @@
|
||||
export default {
|
||||
refresh: 'Refresh',
|
||||
close: 'Close',
|
||||
other: 'Close other',
|
||||
left: 'Close left',
|
||||
right: 'Close right',
|
||||
all: 'Close all',
|
||||
}
|
||||
32
src/i18n/locales/en/test/list.js
Normal file
32
src/i18n/locales/en/test/list.js
Normal file
@ -0,0 +1,32 @@
|
||||
export default {
|
||||
title: 'List',
|
||||
batchDelete: 'Batch delete',
|
||||
add: 'Add one',
|
||||
refresh: 'Refresh',
|
||||
index: 'Index',
|
||||
name: 'Nickname',
|
||||
email: 'Email',
|
||||
desc: 'Description',
|
||||
publish: 'Published',
|
||||
nopublish: 'Unpublished',
|
||||
gender: 'Gender',
|
||||
city: 'City',
|
||||
bj: 'Beijing',
|
||||
sh: 'Shanghai',
|
||||
gz: 'Guangzhou',
|
||||
sz: 'Shenzhen',
|
||||
hobby: 'Hobby',
|
||||
eat: 'Eat',
|
||||
sleep: 'Sleep',
|
||||
bit: 'Beat',
|
||||
fruit: 'Fruit',
|
||||
apple: 'Apple',
|
||||
banana: 'Banana',
|
||||
orange: 'Orange',
|
||||
grape: 'Grape',
|
||||
date: 'Date',
|
||||
daterange: 'Date range',
|
||||
time: 'Time',
|
||||
timerange: 'Time range',
|
||||
num: 'Number',
|
||||
}
|
||||
21
src/i18n/locales/en/topbar.js
Normal file
21
src/i18n/locales/en/topbar.js
Normal file
@ -0,0 +1,21 @@
|
||||
export default {
|
||||
center: 'User center',
|
||||
password: 'Modify password',
|
||||
logout: 'Logout',
|
||||
'lock-title': 'Lock screen',
|
||||
'lock-password': 'Password',
|
||||
'lock-rules-password': 'Please input Screen password',
|
||||
'lock-locked': 'Screen Locked',
|
||||
'lock-lock': 'Unlock',
|
||||
'lock-relogin': 'Re-login',
|
||||
'lock-rules-password2': 'Screen password or User password',
|
||||
'lock-rules-password3': 'Password error',
|
||||
'lock-error': 'Your account has been logged out, please log in directly',
|
||||
'lock-week0': 'Sunday',
|
||||
'lock-week1': 'Monday',
|
||||
'lock-week2': 'Tuesday',
|
||||
'lock-week3': 'Wednesday',
|
||||
'lock-week4': 'Thursday',
|
||||
'lock-week5': 'Friday',
|
||||
'lock-week6': 'Saturday',
|
||||
}
|
||||
6
src/i18n/locales/zh-cn/error.js
Normal file
6
src/i18n/locales/zh-cn/error.js
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
noauth: '您无权访问此页面',
|
||||
servererror: '服务器出错了',
|
||||
notfound: '您访问的页面不存在',
|
||||
backhome: '返回首页',
|
||||
}
|
||||
10
src/i18n/locales/zh-cn/login.js
Normal file
10
src/i18n/locales/zh-cn/login.js
Normal file
@ -0,0 +1,10 @@
|
||||
export default {
|
||||
username: '用户名',
|
||||
password: '密码',
|
||||
login: '登录',
|
||||
logining: '登录中...',
|
||||
loginsuccess: '登录成功',
|
||||
'rules-username': '请输入用户名',
|
||||
'rules-password': '请输入密码',
|
||||
'rules-regpassword': '长度在 6 到 12 个字符',
|
||||
}
|
||||
16
src/i18n/locales/zh-cn/menu.js
Normal file
16
src/i18n/locales/zh-cn/menu.js
Normal file
@ -0,0 +1,16 @@
|
||||
export default {
|
||||
homepage: '首页',
|
||||
dashboard: '工作台',
|
||||
test: '测试页面',
|
||||
testList: '列表',
|
||||
testAdd: '添加',
|
||||
testEdit: '编辑',
|
||||
testAuth: '权限测试',
|
||||
testNoAuth: '权限页面',
|
||||
'test-cache': '该页面可缓存',
|
||||
'test-no-cache': '该页面不缓存',
|
||||
nest: '二级页面',
|
||||
nestPage1: 'Page1',
|
||||
nestPage2: 'Page2',
|
||||
'test-error-log': '测试错误日志',
|
||||
}
|
||||
22
src/i18n/locales/zh-cn/public.js
Normal file
22
src/i18n/locales/zh-cn/public.js
Normal file
@ -0,0 +1,22 @@
|
||||
export default {
|
||||
sure: '确定',
|
||||
search: '搜索',
|
||||
reset: '重置',
|
||||
edit: '编辑',
|
||||
add: '新增',
|
||||
delete: '删除',
|
||||
save: '保存',
|
||||
cancel: '取消',
|
||||
yes: '是',
|
||||
no: '否',
|
||||
status: '状态',
|
||||
operate: '操作',
|
||||
enabled: '启用',
|
||||
disabled: '禁用',
|
||||
male: '男',
|
||||
female: '女',
|
||||
startdate: '开始日期',
|
||||
enddate: '结束日期',
|
||||
starttime: '开始时间',
|
||||
endtime: '结束时间',
|
||||
}
|
||||
8
src/i18n/locales/zh-cn/tags.js
Normal file
8
src/i18n/locales/zh-cn/tags.js
Normal file
@ -0,0 +1,8 @@
|
||||
export default {
|
||||
refresh: '刷新',
|
||||
close: '关闭',
|
||||
other: '关闭其它',
|
||||
left: '关闭左侧',
|
||||
right: '关闭右侧',
|
||||
all: '关闭全部',
|
||||
}
|
||||
32
src/i18n/locales/zh-cn/test/list.js
Normal file
32
src/i18n/locales/zh-cn/test/list.js
Normal file
@ -0,0 +1,32 @@
|
||||
export default {
|
||||
title: '列表',
|
||||
batchDelete: '批量删除',
|
||||
add: '添加一条',
|
||||
refresh: '刷新',
|
||||
index: '序号',
|
||||
name: '昵称',
|
||||
email: '邮箱',
|
||||
desc: '描述',
|
||||
publish: '已发布',
|
||||
nopublish: '未发布',
|
||||
gender: '性别',
|
||||
city: '城市',
|
||||
bj: '北京',
|
||||
sh: '上海',
|
||||
gz: '广州',
|
||||
sz: '深圳',
|
||||
hobby: '爱好',
|
||||
eat: '吃饭',
|
||||
sleep: '睡觉',
|
||||
bit: '打豆豆',
|
||||
fruit: '水果',
|
||||
apple: '苹果',
|
||||
banana: '香蕉',
|
||||
orange: '橘子',
|
||||
grape: '葡萄',
|
||||
date: '日期',
|
||||
daterange: '日期范围',
|
||||
time: '时间',
|
||||
timerange: '时间范围',
|
||||
num: '数量',
|
||||
}
|
||||
21
src/i18n/locales/zh-cn/topbar.js
Normal file
21
src/i18n/locales/zh-cn/topbar.js
Normal file
@ -0,0 +1,21 @@
|
||||
export default {
|
||||
center: '个人中心',
|
||||
password: '修改密码',
|
||||
logout: '退出登录',
|
||||
'lock-title': '锁定屏幕',
|
||||
'lock-password': '锁屏密码',
|
||||
'lock-rules-password': '请输入锁屏密码',
|
||||
'lock-locked': '屏幕已锁定',
|
||||
'lock-lock': '解锁',
|
||||
'lock-relogin': '重新登录',
|
||||
'lock-rules-password2': '请输入锁屏密码或登录密码',
|
||||
'lock-rules-password3': '密码错误',
|
||||
'lock-error': '您的账号已退出,请直接登录',
|
||||
'lock-week0': '星期日',
|
||||
'lock-week1': '星期一',
|
||||
'lock-week2': '星期二',
|
||||
'lock-week3': '星期三',
|
||||
'lock-week4': '星期四',
|
||||
'lock-week5': '星期五',
|
||||
'lock-week6': '星期六',
|
||||
}
|
||||
16
src/i18n/useLang.js
Normal file
16
src/i18n/useLang.js
Normal file
@ -0,0 +1,16 @@
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
export default function useLang() {
|
||||
const i18n = useI18n()
|
||||
const lang = computed(() => i18n.locale.value)
|
||||
const changeLang = value => {
|
||||
i18n.locale.value = value
|
||||
localStorage.setItem('__VEA__lang', value)
|
||||
}
|
||||
return {
|
||||
i18n,
|
||||
lang,
|
||||
changeLang,
|
||||
}
|
||||
}
|
||||
@ -27,7 +27,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-21 12:46:17
|
||||
* @LastEditTime: 2022-09-27 16:27:54
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -42,15 +42,15 @@
|
||||
</router-view>
|
||||
</template>
|
||||
<script>
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { useTags } from '@/pinia/modules/tags'
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const store = useStore()
|
||||
const route = useRoute()
|
||||
const cacheList = computed(() => store.state.tags.cacheList)
|
||||
const { cacheList } = storeToRefs(useTags())
|
||||
const key = computed(() => route.fullPath)
|
||||
|
||||
return {
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-21 12:46:37
|
||||
* @LastEditTime: 2022-09-24 19:33:12
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -32,9 +32,9 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<i v-if="isElementIcon" :class="`icon ${icon}`" />
|
||||
<svg-icon class="icon" v-else-if="!!icon" :name="icon" />
|
||||
<span>{{ title }}</span>
|
||||
<svg-icon class="icon" v-if="isCustomSvg" :name="icon" />
|
||||
<component :is="icon" v-else-if="!!icon" class="icon" />
|
||||
<span>{{ $t(title) }}</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -43,10 +43,10 @@ import { computed, defineComponent } from 'vue'
|
||||
export default defineComponent({
|
||||
props: ['title', 'icon'],
|
||||
setup({ icon }) {
|
||||
const isElementIcon = computed(() => icon && icon.startsWith('el-icon'))
|
||||
const isCustomSvg = computed(() => icon && icon.startsWith('icon-'))
|
||||
|
||||
return {
|
||||
isElementIcon,
|
||||
isCustomSvg,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-07-26 16:02:28
|
||||
* @LastEditTime: 2022-09-27 16:45:42
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -54,9 +54,10 @@
|
||||
<script>
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import Submenu from './Submenu.vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRoute } from 'vue-router'
|
||||
import config from './config/menu.module.scss'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useMenus } from '@/pinia/modules/menu'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -74,10 +75,10 @@ export default defineComponent({
|
||||
},
|
||||
setup() {
|
||||
const route = useRoute()
|
||||
const store = useStore()
|
||||
const { menus } = storeToRefs(useMenus())
|
||||
|
||||
return {
|
||||
menus: computed(() => store.state.menu.menus),
|
||||
menus,
|
||||
activePath: computed(() => route.path),
|
||||
variables: computed(() => config),
|
||||
}
|
||||
@ -87,15 +88,15 @@ export default defineComponent({
|
||||
<style lang="scss">
|
||||
// menu hover
|
||||
.el-menu-item,
|
||||
.el-submenu__title {
|
||||
.el-sub-menu__title {
|
||||
&:hover {
|
||||
background-color: $menuHover !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-submenu {
|
||||
.el-sub-menu {
|
||||
.el-menu-item,
|
||||
.el-submenu .el-submenu__title {
|
||||
.el-sub-menu .el-sub-menu__title {
|
||||
background-color: $subMenuBg !important;
|
||||
|
||||
&:hover {
|
||||
@ -112,7 +113,7 @@ export default defineComponent({
|
||||
|
||||
.el-menu--collapse {
|
||||
.el-menu-item.is-active,
|
||||
.el-submenu.is-active > .el-submenu__title {
|
||||
.el-sub-menu.is-active > .el-sub-menu__title {
|
||||
position: relative;
|
||||
background-color: $collapseMenuActiveBg !important;
|
||||
color: $collapseMenuActiveColor !important;
|
||||
@ -128,19 +129,20 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
.el-submenu__title i {
|
||||
.el-sub-menu__title i {
|
||||
color: $arrowColor;
|
||||
}
|
||||
|
||||
// 水平菜单
|
||||
.el-menu--horizontal {
|
||||
.el-menu-item,
|
||||
.el-submenu .el-submenu__title {
|
||||
.el-sub-menu .el-sub-menu__title {
|
||||
height: $horizontalMenuHeight;
|
||||
line-height: $horizontalMenuHeight;
|
||||
border-bottom: none;
|
||||
}
|
||||
.el-menu-item.is-active,
|
||||
.el-submenu.is-active .el-submenu__title {
|
||||
.el-sub-menu.is-active .el-sub-menu__title {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-21 12:46:55
|
||||
* @LastEditTime: 2022-09-24 16:44:28
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -24,7 +24,7 @@
|
||||
<el-menu-item v-if="!menu.children" :index="menu.url">
|
||||
<item :icon="menu.icon" :title="menu.title" />
|
||||
</el-menu-item>
|
||||
<el-submenu v-else :index="menu.url">
|
||||
<el-sub-menu v-else :index="menu.url">
|
||||
<template #title>
|
||||
<item :icon="menu.icon" :title="menu.title" />
|
||||
</template>
|
||||
@ -34,7 +34,7 @@
|
||||
:is-nest="true"
|
||||
:menu="submenu"
|
||||
/>
|
||||
</el-submenu>
|
||||
</el-sub-menu>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-07-23 09:36:42
|
||||
* @LastEditTime: 2022-09-27 18:45:07
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -44,10 +44,11 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, computed } from 'vue'
|
||||
import { useApp } from '@/pinia/modules/app'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import Logo from './Logo.vue'
|
||||
import Menus from './Menus.vue'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -55,12 +56,13 @@ export default defineComponent({
|
||||
Menus,
|
||||
},
|
||||
setup() {
|
||||
const store = useStore()
|
||||
const collapse = computed(() => !!store.state.app.sidebar.collapse)
|
||||
const device = computed(() => store.state.app.device)
|
||||
const appStore = useApp()
|
||||
const { sidebar, device } = storeToRefs(appStore)
|
||||
const { setCollapse } = appStore
|
||||
const collapse = computed(() => sidebar.value.collapse)
|
||||
|
||||
const closeSidebar = () => {
|
||||
store.commit('app/setCollapse', 1)
|
||||
setCollapse(1)
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@ -26,23 +26,24 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-29 10:52:41
|
||||
* @LastEditTime: 2022-09-27 16:52:30
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
|
||||
import { useTags } from '@/pinia/modules/tags'
|
||||
import { onMounted, onBeforeUnmount, reactive, toRefs, nextTick } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { isAffix } from './useTags'
|
||||
|
||||
export const useContextMenu = tagList => {
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const tagsStore = useTags()
|
||||
|
||||
const state = reactive({
|
||||
visible: false,
|
||||
top: 0,
|
||||
@ -58,7 +59,7 @@ export const useContextMenu = tagList => {
|
||||
state.visible = false
|
||||
},
|
||||
refreshSelectedTag(tag) {
|
||||
store.commit('tags/DEL_CACHE_LIST', tag)
|
||||
tagsStore.deCacheList(tag)
|
||||
const { fullPath } = tag
|
||||
nextTick(() => {
|
||||
router.replace({
|
||||
@ -72,13 +73,13 @@ export const useContextMenu = tagList => {
|
||||
const closedTagIndex = tagList.value.findIndex(
|
||||
item => item.fullPath === tag.fullPath
|
||||
)
|
||||
store.dispatch('tags/delTag', tag)
|
||||
tagsStore.delTag(tag)
|
||||
if (isActive(tag)) {
|
||||
toLastTag(closedTagIndex - 1)
|
||||
}
|
||||
},
|
||||
closeOtherTags() {
|
||||
store.dispatch('tags/delOtherTags', state.selectedTag)
|
||||
tagsStore.delOtherTags(state.selectedTag)
|
||||
router.push(state.selectedTag)
|
||||
},
|
||||
closeLeftTags() {
|
||||
@ -103,11 +104,11 @@ export const useContextMenu = tagList => {
|
||||
direction === 'left'
|
||||
? tagList.value.slice(0, index)
|
||||
: tagList.value.slice(index + 1)
|
||||
store.dispatch('tags/delSomeTags', needToClose)
|
||||
tagsStore.delSomeTags(needToClose)
|
||||
router.push(state.selectedTag)
|
||||
},
|
||||
closeAllTags() {
|
||||
store.dispatch('tags/delAllTags')
|
||||
tagsStore.delAllTags()
|
||||
router.push('/')
|
||||
},
|
||||
})
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-21 12:47:07
|
||||
* @LastEditTime: 2022-08-13 14:50:23
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -35,15 +35,28 @@ import { ref } from 'vue'
|
||||
|
||||
export const useScrollbar = tagsItem => {
|
||||
const scrollContainer = ref(null)
|
||||
const scrollLeft = ref(0)
|
||||
|
||||
const doScroll = val => {
|
||||
scrollLeft.value = val
|
||||
scrollContainer.value.setScrollLeft(scrollLeft.value)
|
||||
}
|
||||
|
||||
const handleScroll = e => {
|
||||
const $wrap = scrollContainer.value.wrap$
|
||||
if ($wrap.offsetWidth + scrollLeft.value > $wrap.children[0].scrollWidth) {
|
||||
doScroll($wrap.children[0].scrollWidth - $wrap.offsetWidth)
|
||||
return
|
||||
} else if (scrollLeft.value < 0) {
|
||||
doScroll(0)
|
||||
return
|
||||
}
|
||||
const eventDelta = e.wheelDelta || -e.deltaY
|
||||
scrollContainer.value.wrap.scrollLeft -= eventDelta / 4
|
||||
doScroll(scrollLeft.value - eventDelta / 4)
|
||||
}
|
||||
|
||||
const moveToTarget = currentTag => {
|
||||
const containerWidth = scrollContainer.value.scrollbar.offsetWidth
|
||||
const scrollWrapper = scrollContainer.value.wrap
|
||||
const $wrap = scrollContainer.value.wrap$
|
||||
const tagList = tagsItem.value
|
||||
|
||||
let firstTag = null
|
||||
@ -54,15 +67,15 @@ export const useScrollbar = tagsItem => {
|
||||
lastTag = tagList[tagList.length - 1]
|
||||
}
|
||||
if (firstTag === currentTag) {
|
||||
scrollWrapper.scrollLeft = 0
|
||||
doScroll(0)
|
||||
} else if (lastTag === currentTag) {
|
||||
scrollWrapper.scrollLeft = scrollWrapper.scrollWidth - containerWidth
|
||||
doScroll($wrap.children[0].scrollWidth - $wrap.offsetWidth)
|
||||
} else {
|
||||
const el = currentTag.$el.nextElementSibling
|
||||
scrollWrapper.scrollLeft =
|
||||
el.offsetLeft + el.offsetWidth > containerWidth
|
||||
? el.offsetLeft - el.offsetWidth
|
||||
: 0
|
||||
|
||||
el.offsetLeft + el.offsetWidth > $wrap.offsetWidth
|
||||
? doScroll(el.offsetLeft - el.offsetWidth)
|
||||
: doScroll(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -24,28 +24,29 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-11-23 10:56:09
|
||||
* @LastEditTime: 2022-09-27 18:28:33
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useTags as useTagsbar } from '@/pinia/modules/tags'
|
||||
import { useScrollbar } from './useScrollbar'
|
||||
import { watch, computed, ref, nextTick, onBeforeMount } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
export const isAffix = tag => {
|
||||
return !!tag.meta && !!tag.meta.affix
|
||||
}
|
||||
|
||||
export const useTags = () => {
|
||||
const store = useStore()
|
||||
const tagStore = useTagsbar()
|
||||
const { tagList } = storeToRefs(tagStore)
|
||||
const { addTag, delTag, saveActivePosition, updateTagList } = tagStore
|
||||
const router = useRouter()
|
||||
const route = router.currentRoute
|
||||
const routes = computed(() => router.getRoutes())
|
||||
const tagList = computed(() => store.state.tags.tagList)
|
||||
|
||||
const tagsItem = ref([])
|
||||
|
||||
@ -71,32 +72,31 @@ export const useTags = () => {
|
||||
|
||||
for (const tag of affixTags) {
|
||||
if (tag.name) {
|
||||
store.dispatch('tags/addTag', tag)
|
||||
addTag(tag)
|
||||
}
|
||||
}
|
||||
|
||||
// 不在路由中的所有标签,需要删除
|
||||
const noUseTags = tagList.value.filter(tag =>
|
||||
routes.value.every(route => route.name !== tag.name)
|
||||
)
|
||||
noUseTags.forEach(tag => {
|
||||
store.dispatch('tags/delTag', tag)
|
||||
delTag(tag)
|
||||
})
|
||||
}
|
||||
|
||||
const addTag = () => {
|
||||
const addTagList = () => {
|
||||
const tag = route.value
|
||||
if (!!tag.name && tag.matched[0].components.default.name === 'layout') {
|
||||
store.dispatch('tags/addTag', tag)
|
||||
addTag(tag)
|
||||
}
|
||||
}
|
||||
|
||||
const saveActivePosition = tag => {
|
||||
const saveTagPosition = tag => {
|
||||
const index = tagList.value.findIndex(
|
||||
item => item.fullPath === tag.fullPath
|
||||
)
|
||||
|
||||
store.dispatch('tags/saveActivePosition', Math.max(0, index))
|
||||
saveActivePosition(Math.max(0, index))
|
||||
}
|
||||
|
||||
const moveToCurrentTag = () => {
|
||||
@ -106,7 +106,7 @@ export const useTags = () => {
|
||||
scrollbar.moveToTarget(tag)
|
||||
|
||||
if (tag.to.fullPath !== route.value.fullPath) {
|
||||
store.dispatch('tags/updateTagList', route.value)
|
||||
updateTagList(route.value)
|
||||
}
|
||||
break
|
||||
}
|
||||
@ -116,13 +116,13 @@ export const useTags = () => {
|
||||
|
||||
onBeforeMount(() => {
|
||||
initTags()
|
||||
addTag()
|
||||
addTagList()
|
||||
moveToCurrentTag()
|
||||
})
|
||||
|
||||
watch(route, (newRoute, oldRoute) => {
|
||||
saveActivePosition(oldRoute) // 保存标签的位置
|
||||
addTag()
|
||||
saveTagPosition(oldRoute) // 保存标签的位置
|
||||
addTagList()
|
||||
moveToCurrentTag()
|
||||
})
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-18 17:50:46
|
||||
* @LastEditTime: 2022-09-24 20:38:36
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -43,12 +43,15 @@
|
||||
@click.middle="closeTag(tag)"
|
||||
@contextmenu.prevent="openMenu(tag, $event)"
|
||||
>
|
||||
<span class="title">{{ tag.title }}</span>
|
||||
<span
|
||||
<span class="title">{{ $t(tag.title) }}</span>
|
||||
|
||||
<el-icon
|
||||
v-if="!isAffix(tag)"
|
||||
class="el-icon-close"
|
||||
@click.prevent.stop="closeTag(tag)"
|
||||
/>
|
||||
>
|
||||
<Close />
|
||||
</el-icon>
|
||||
</div>
|
||||
</router-link>
|
||||
</el-scrollbar>
|
||||
@ -58,12 +61,14 @@
|
||||
:style="{ left: left + 'px', top: top + 'px' }"
|
||||
class="contextmenu"
|
||||
>
|
||||
<li @click="refreshSelectedTag(selectedTag)">刷新</li>
|
||||
<li v-if="!isAffix(selectedTag)" @click="closeTag(selectedTag)">关闭</li>
|
||||
<li @click="closeOtherTags">关闭其他</li>
|
||||
<li @click="closeLeftTags">关闭左侧</li>
|
||||
<li @click="closeRightTags">关闭右侧</li>
|
||||
<li @click="closeAllTags">关闭全部</li>
|
||||
<li @click="refreshSelectedTag(selectedTag)">{{ $t('tags.refresh') }}</li>
|
||||
<li v-if="!isAffix(selectedTag)" @click="closeTag(selectedTag)">
|
||||
{{ $t('tags.close') }}
|
||||
</li>
|
||||
<li @click="closeOtherTags">{{ $t('tags.other') }}</li>
|
||||
<li @click="closeLeftTags">{{ $t('tags.left') }}</li>
|
||||
<li @click="closeRightTags">{{ $t('tags.right') }}</li>
|
||||
<li @click="closeAllTags">{{ $t('tags.all') }}</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
@ -71,7 +76,7 @@
|
||||
import { defineComponent, computed, getCurrentInstance } from 'vue'
|
||||
import { useTags } from './hooks/useTags'
|
||||
import { useContextMenu } from './hooks/useContextMenu'
|
||||
import { useStore } from 'vuex'
|
||||
import { useLayoutsettings } from '@/pinia/modules/layoutSettings'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Tagsbar',
|
||||
@ -80,9 +85,8 @@ export default defineComponent({
|
||||
instance.appContext.config.globalProperties.$tagsbar = this
|
||||
},
|
||||
setup() {
|
||||
const store = useStore()
|
||||
const defaultSettings = computed(() => store.state.layoutSettings)
|
||||
const isTagsbarShow = computed(() => defaultSettings.value.tagsbar.isShow)
|
||||
const defaultSettings = useLayoutsettings()
|
||||
const isTagsbarShow = computed(() => defaultSettings.tagsbar.isShow)
|
||||
|
||||
const tags = useTags()
|
||||
const contextMenu = useContextMenu(tags.tagList)
|
||||
@ -156,7 +160,7 @@ export default defineComponent({
|
||||
margin-left: 8px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: 2px;
|
||||
vertical-align: -2px;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-07-23 17:22:14
|
||||
* @LastEditTime: 2022-09-27 17:38:48
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -50,29 +50,38 @@
|
||||
:class="{ no_link: index === breadcrumbs.length - 1 }"
|
||||
:to="index < breadcrumbs.length - 1 ? item.path : ''"
|
||||
>
|
||||
{{ item.meta.title }}
|
||||
{{ $t(item.meta.title) }}
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, computed, ref, onBeforeMount, watch } from 'vue'
|
||||
import { useApp } from '@/pinia/modules/app'
|
||||
import { useLayoutsettings } from '@/pinia/modules/layoutSettings'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import {
|
||||
defineComponent,
|
||||
computed,
|
||||
ref,
|
||||
onBeforeMount,
|
||||
watch,
|
||||
getCurrentInstance,
|
||||
} from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
export default defineComponent({
|
||||
setup(props, { emit }) {
|
||||
const store = useStore()
|
||||
const device = computed(() => store.state.app.device)
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { device } = storeToRefs(useApp())
|
||||
const router = useRouter()
|
||||
const route = router.currentRoute // 这里不使用useRoute获取当前路由,否则下面watch监听路由的时候会有警告
|
||||
const breadcrumbs = ref([])
|
||||
const defaultSettings = computed(() => store.state.layoutSettings)
|
||||
const defaultSettings = useLayoutsettings()
|
||||
const isHorizontalMenu = computed(
|
||||
() => defaultSettings.value.menus.mode === 'horizontal'
|
||||
() => defaultSettings.menus.mode === 'horizontal'
|
||||
)
|
||||
|
||||
const getBreadcrumbs = route => {
|
||||
const home = [{ path: '/', meta: { title: '首页' } }]
|
||||
const home = [{ path: '/', meta: { title: proxy.$t('menu.homepage') } }]
|
||||
if (route.name === 'home') {
|
||||
return home
|
||||
} else {
|
||||
@ -91,6 +100,7 @@ export default defineComponent({
|
||||
watch(
|
||||
route,
|
||||
newRoute => {
|
||||
route.value.meta.truetitle = proxy.$t(route.value.meta.title)
|
||||
breadcrumbs.value = getBreadcrumbs(newRoute)
|
||||
emit('on-breadcrumbs-change', breadcrumbs.value.length > 1)
|
||||
},
|
||||
@ -118,9 +128,9 @@ export default defineComponent({
|
||||
::v-deep(.is-link) {
|
||||
font-weight: normal;
|
||||
}
|
||||
::v-deep(.el-breadcrumb__item) {
|
||||
float: none;
|
||||
}
|
||||
// ::v-deep(.el-breadcrumb__item) {
|
||||
// float: none;
|
||||
// }
|
||||
.no_link {
|
||||
::v-deep(.el-breadcrumb__inner) {
|
||||
color: #97a8be !important;
|
||||
|
||||
94
src/layout/components/Topbar/ChangeLang.vue
Normal file
94
src/layout/components/Topbar/ChangeLang.vue
Normal file
@ -0,0 +1,94 @@
|
||||
<!--
|
||||
* _oo0oo_
|
||||
* o8888888o
|
||||
* 88" . "88
|
||||
* (| -_- |)
|
||||
* 0\ = /0
|
||||
* ___/`---'\___
|
||||
* .' \\| |// '.
|
||||
* / \\||| : |||// \
|
||||
* / _||||| -:- |||||- \
|
||||
* | | \\\ - /// | |
|
||||
* | \_| ''\---/'' |_/ |
|
||||
* \ .-\__ '-' ___/-. /
|
||||
* ___'. .' /--.--\ `. .'___
|
||||
* ."" '< `.___\_<|>_/___.' >' "".
|
||||
* | | : `- \`.;`\ _ /`;.`/ - ` : | |
|
||||
* \ \ `_. \_ __\ /__ _/ .-` / /
|
||||
* =====`-.____`.___ \_____/___.-`___.-'=====
|
||||
* `=---='
|
||||
*
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* 佛祖保佑 永不宕机 永无BUG
|
||||
*
|
||||
* 佛曰:
|
||||
* 写字楼里写字间,写字间里程序员;
|
||||
* 程序人员写程序,又拿程序换酒钱。
|
||||
* 酒醒只在网上坐,酒醉还来网下眠;
|
||||
* 酒醉酒醒日复日,网上网下年复年。
|
||||
* 但愿老死电脑间,不愿鞠躬老板前;
|
||||
* 奔驰宝马贵者趣,公交自行程序员。
|
||||
* 别人笑我忒疯癫,我笑自己命太贱;
|
||||
* 不见满街漂亮妹,哪个归得程序员?
|
||||
*
|
||||
* @Descripttion:
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2022-09-26 11:53:15
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
-->
|
||||
|
||||
<template>
|
||||
<el-dropdown trigger="hover">
|
||||
<div class="change-lang">
|
||||
<svg-icon name="language" class="icon"></svg-icon>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
@click="changeLang(item.value)"
|
||||
v-for="item in langlist"
|
||||
:key="item.value"
|
||||
>
|
||||
{{ item.name }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
<script setup>
|
||||
import useLang from '@/i18n/useLang'
|
||||
const langlist = [
|
||||
{
|
||||
name: '简体中文',
|
||||
value: 'zh-cn',
|
||||
},
|
||||
{
|
||||
name: 'English',
|
||||
value: 'en',
|
||||
},
|
||||
]
|
||||
const { changeLang } = useLang()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.change-lang {
|
||||
padding: 0 16px;
|
||||
height: 48px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -18,7 +18,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-21 12:47:40
|
||||
* @LastEditTime: 2022-09-27 18:43:44
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -26,25 +26,30 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<i
|
||||
class="fold-btn el-icon-s-fold"
|
||||
<el-icon
|
||||
:size="20"
|
||||
class="fold-btn"
|
||||
:class="{ collapse: collapse }"
|
||||
@click="handleToggleMenu"
|
||||
></i>
|
||||
>
|
||||
<Fold />
|
||||
</el-icon>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useApp } from '@/pinia/modules/app'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed, defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const store = useStore()
|
||||
const collapse = computed(() => !!store.state.app.sidebar.collapse)
|
||||
const appStore = useApp()
|
||||
const { sidebar } = storeToRefs(appStore)
|
||||
const { setCollapse } = appStore
|
||||
const handleToggleMenu = () => {
|
||||
store.commit('app/setCollapse', +!collapse.value)
|
||||
setCollapse(+!sidebar.value.collapse)
|
||||
}
|
||||
return {
|
||||
collapse,
|
||||
collapse: computed(() => sidebar.value.collapse),
|
||||
handleToggleMenu,
|
||||
}
|
||||
},
|
||||
@ -54,11 +59,7 @@ export default defineComponent({
|
||||
.fold-btn {
|
||||
line-height: 48px;
|
||||
padding: 0 10px;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
&.collapse {
|
||||
transform: scale(-1, 1);
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-23 14:15:50
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-28 09:23:23
|
||||
* @LastEditTime: 2022-09-27 17:55:16
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -52,17 +52,24 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<el-dropdown-item @click="dialogVisible = true">锁定屏幕</el-dropdown-item>
|
||||
<el-dropdown-item @click="dialogVisible = true">
|
||||
{{ $t('topbar.lock-title') }}
|
||||
</el-dropdown-item>
|
||||
<el-dialog
|
||||
title="锁定屏幕"
|
||||
:title="$t('topbar.lock-title')"
|
||||
v-model="dialogVisible"
|
||||
width="640px"
|
||||
custom-class="lock-modal"
|
||||
append-to-body
|
||||
>
|
||||
<Avatar />
|
||||
<el-form :model="lockModel" :rules="lockRules" ref="lockForm">
|
||||
<el-form-item label="锁屏密码" prop="password">
|
||||
<el-form
|
||||
:model="lockModel"
|
||||
:rules="lockRules"
|
||||
ref="lockForm"
|
||||
label-width="90px"
|
||||
>
|
||||
<el-form-item :label="$t('topbar.lock-password')" prop="password">
|
||||
<el-input
|
||||
type="password"
|
||||
v-model.trim="lockModel.password"
|
||||
@ -71,13 +78,8 @@
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
size="small"
|
||||
class="submit-btn"
|
||||
type="primary"
|
||||
@click="submitForm"
|
||||
>
|
||||
锁定屏幕
|
||||
<el-button class="submit-btn" type="primary" @click="submitForm">
|
||||
{{ $t('topbar.lock-title') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@ -85,25 +87,27 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, reactive, ref } from 'vue'
|
||||
import { defineComponent, getCurrentInstance, reactive, ref } from 'vue'
|
||||
import Avatar from '@/components/Avatar/index.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { useApp } from '@/pinia/modules/app'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Avatar,
|
||||
},
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const dialogVisible = ref(false)
|
||||
const lockForm = ref(null)
|
||||
const lockModel = reactive({
|
||||
password: '',
|
||||
})
|
||||
const lockRules = reactive({
|
||||
password: [{ required: true, message: '请输入锁屏密码' }],
|
||||
password: [
|
||||
{ required: true, message: proxy.$t('topbar.lock-rules-password') },
|
||||
],
|
||||
})
|
||||
const submitForm = () => {
|
||||
lockForm.value.validate(valid => {
|
||||
@ -112,7 +116,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
// 对密码加密并跟token保存在一起
|
||||
store.dispatch('app/setScreenCode', lockModel.password)
|
||||
useApp().setScreenCode(lockModel.password)
|
||||
|
||||
// 跳转到锁屏页面
|
||||
router.push('/lock?redirect=' + router.currentRoute.value.fullPath)
|
||||
@ -135,8 +139,3 @@ export default defineComponent({
|
||||
max-width: 90%;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-18 15:39:30
|
||||
* @LastEditTime: 2022-09-27 17:56:21
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -45,7 +45,7 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<el-dropdown trigger="click">
|
||||
<el-dropdown trigger="hover">
|
||||
<div class="userinfo">
|
||||
<template v-if="!userinfo">
|
||||
<i class="el-icon-user" />
|
||||
@ -58,27 +58,28 @@
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item>个人中心</el-dropdown-item>
|
||||
<el-dropdown-item>修改密码</el-dropdown-item>
|
||||
<el-dropdown-item>{{ $t('topbar.center') }}</el-dropdown-item>
|
||||
<el-dropdown-item>{{ $t('topbar.password') }}</el-dropdown-item>
|
||||
<lock-modal />
|
||||
<el-dropdown-item @click="logout">退出登录</el-dropdown-item>
|
||||
<el-dropdown-item @click="logout">
|
||||
{{ $t('topbar.logout') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useUserinfo } from '@/components/Avatar/hooks/useUserinfo'
|
||||
import LockModal from './LockModal.vue'
|
||||
import { useApp } from '@/pinia/modules/app'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
LockModal,
|
||||
},
|
||||
setup() {
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
|
||||
const { userinfo } = useUserinfo()
|
||||
@ -86,7 +87,7 @@ export default defineComponent({
|
||||
// 退出
|
||||
const logout = () => {
|
||||
// 清除token
|
||||
store.dispatch('app/clearToken')
|
||||
useApp().clearToken()
|
||||
router.push('/login')
|
||||
}
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-21 09:18:32
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-07-23 16:49:39
|
||||
* @LastEditTime: 2022-09-27 18:36:16
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -58,6 +58,7 @@
|
||||
<div class="action">
|
||||
<error-log />
|
||||
<userinfo />
|
||||
<change-lang />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -67,8 +68,11 @@ import Logo from '@/layout/components/Sidebar/Logo.vue'
|
||||
import Hamburger from './Hamburger.vue'
|
||||
import Breadcrumbs from './Breadcrumbs.vue'
|
||||
import Userinfo from './Userinfo.vue'
|
||||
import ChangeLang from './ChangeLang.vue'
|
||||
import ErrorLog from '@/components/ErrorLog/index.vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useLayoutsettings } from '@/pinia/modules/layoutSettings'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useApp } from '@/pinia/modules/app'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -76,16 +80,16 @@ export default defineComponent({
|
||||
Hamburger,
|
||||
Breadcrumbs,
|
||||
Userinfo,
|
||||
ChangeLang,
|
||||
ErrorLog,
|
||||
},
|
||||
setup() {
|
||||
const store = useStore()
|
||||
const defaultSettings = computed(() => store.state.layoutSettings)
|
||||
const defaultSettings = useLayoutsettings()
|
||||
|
||||
const device = computed(() => store.state.app.device)
|
||||
const { device } = storeToRefs(useApp())
|
||||
|
||||
const isHorizontalMenu = computed(
|
||||
() => defaultSettings.value.menus.mode === 'horizontal'
|
||||
() => defaultSettings.menus.mode === 'horizontal'
|
||||
)
|
||||
|
||||
const isShowLogo = computed(
|
||||
@ -95,7 +99,7 @@ export default defineComponent({
|
||||
const isShowHamburger = computed(() => !isHorizontalMenu.value)
|
||||
|
||||
const isShowBreadcrumbs = computed(
|
||||
() => defaultSettings.value.breadcrumbs.isShow && !isHorizontalMenu.value
|
||||
() => defaultSettings.breadcrumbs.isShow && !isHorizontalMenu.value
|
||||
)
|
||||
|
||||
return {
|
||||
|
||||
@ -24,22 +24,23 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-29 11:31:50
|
||||
* @LastEditTime: 2022-09-27 19:02:14
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
|
||||
import { onBeforeMount, onBeforeUnmount /*watch*/ } from 'vue'
|
||||
// import { useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useApp } from '@/pinia/modules/app'
|
||||
import { onBeforeMount, onBeforeUnmount, computed } from 'vue'
|
||||
|
||||
const WIDTH = 768
|
||||
export const useResizeHandler = () => {
|
||||
const store = useStore()
|
||||
// const router = useRouter();
|
||||
// const route = router.currentRoute;
|
||||
const appStore = useApp()
|
||||
const { sidebar } = storeToRefs(appStore)
|
||||
const { setDevice, setCollapse } = appStore
|
||||
const collapse = computed(() => sidebar.value.collapse)
|
||||
|
||||
const isMobile = () => {
|
||||
return window.innerWidth < WIDTH
|
||||
@ -47,11 +48,11 @@ export const useResizeHandler = () => {
|
||||
|
||||
const resizeHandler = () => {
|
||||
if (isMobile()) {
|
||||
store.commit('app/setDevice', 'mobile')
|
||||
store.commit('app/setCollapse', 1)
|
||||
setDevice('mobile')
|
||||
setCollapse(1)
|
||||
} else {
|
||||
store.commit('app/setDevice', 'desktop')
|
||||
store.commit('app/setCollapse', 0)
|
||||
setDevice('desktop')
|
||||
setCollapse(collapse.value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,11 +64,4 @@ export const useResizeHandler = () => {
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', resizeHandler)
|
||||
})
|
||||
|
||||
// // 监听路由的时候不能使用useRoute获取路由,否则会有警告
|
||||
// watch(route, () => {
|
||||
// if (store.state.app.device === 'mobile' && !store.state.app.sidebar.collapse) {
|
||||
// store.commit('app/setCollapse', 1)
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-18 14:58:53
|
||||
* @LastEditTime: 2022-09-27 18:31:47
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -62,7 +62,8 @@ import Tagsbar from './components/Tagsbar/index.vue'
|
||||
import Breadcrumbs from './components/Topbar/Breadcrumbs.vue'
|
||||
import Content from './components/Content/index.vue'
|
||||
import { useResizeHandler } from './hooks/useResizeHandler'
|
||||
import { useStore } from 'vuex'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useLayoutsettings } from '@/pinia/modules/layoutSettings'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'layout',
|
||||
@ -76,16 +77,13 @@ export default defineComponent({
|
||||
},
|
||||
setup() {
|
||||
useResizeHandler()
|
||||
const store = useStore()
|
||||
const defaultSettings = computed(() => store.state.layoutSettings)
|
||||
const isFluid = computed(() => defaultSettings.value.layout.isFluid)
|
||||
const isTopbarFixed = computed(() => defaultSettings.value.topbar.isFixed)
|
||||
const isMenusShow = computed(() => defaultSettings.value.menus.isShow)
|
||||
const isHorizontalMenu = computed(
|
||||
() => defaultSettings.value.menus.mode === 'horizontal'
|
||||
)
|
||||
const defaultSettings = useLayoutsettings()
|
||||
const isFluid = defaultSettings.layout.isFluid
|
||||
const isTopbarFixed = defaultSettings.topbar.isFixed
|
||||
const isMenusShow = defaultSettings.menus.isShow
|
||||
const isHorizontalMenu = defaultSettings.menus.mode === 'horizontal'
|
||||
const isBreadcrumbsShow = computed(
|
||||
() => isHorizontalMenu.value && defaultSettings.value.breadcrumbs.isShow
|
||||
() => isHorizontalMenu && defaultSettings.breadcrumbs.isShow
|
||||
)
|
||||
const paddingFlag = ref(true)
|
||||
const handleBreadcrumbsChange = boo => {
|
||||
|
||||
26
src/main.js
26
src/main.js
@ -27,7 +27,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-29 10:08:00
|
||||
* @LastEditTime: 2022-09-27 19:04:15
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -42,15 +42,22 @@ const app = createApp(App)
|
||||
// 引入element-plus
|
||||
import ElementPlus from 'element-plus'
|
||||
import './assets/style/element-variables.scss'
|
||||
// 引入中文语言包
|
||||
import 'dayjs/locale/zh-cn'
|
||||
import locale from 'element-plus/lib/locale/lang/zh-cn'
|
||||
|
||||
// 国际化
|
||||
import i18n from '@/i18n'
|
||||
|
||||
// 全局注册element-plus/icons-vue
|
||||
import * as ICONS from '@element-plus/icons-vue'
|
||||
Object.entries(ICONS).forEach(([key, component]) => {
|
||||
// app.component(key === 'PieChart' ? 'PieChartIcon' : key, component)
|
||||
app.component(key, component)
|
||||
})
|
||||
|
||||
// 引入路由
|
||||
import router from './router'
|
||||
|
||||
// 引入store
|
||||
import store from './store'
|
||||
// 引入pinia
|
||||
import pinia from './pinia'
|
||||
|
||||
// 权限控制
|
||||
import './permission'
|
||||
@ -73,9 +80,8 @@ import useErrorHandler from './error-log'
|
||||
useErrorHandler(app)
|
||||
|
||||
app
|
||||
.use(ElementPlus, {
|
||||
locale,
|
||||
})
|
||||
.use(store)
|
||||
.use(i18n)
|
||||
.use(ElementPlus)
|
||||
.use(pinia)
|
||||
.use(router)
|
||||
.mount('#app')
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-29 09:47:46
|
||||
* @LastEditTime: 2022-09-27 16:35:06
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -34,12 +34,16 @@
|
||||
*/
|
||||
|
||||
import { ElLoading } from 'element-plus'
|
||||
import router, { asyncRoutes } from '@/router'
|
||||
import store from '@/store'
|
||||
import router from '@/router'
|
||||
// import store from '@/store'
|
||||
import { TOKEN } from '@/store/modules/app' // TOKEN变量名
|
||||
import { nextTick } from 'vue'
|
||||
import { useApp } from './pinia/modules/app'
|
||||
import { useAccount } from './pinia/modules/account'
|
||||
import { useMenus } from './pinia/modules/menu'
|
||||
|
||||
const getPageTitle = title => {
|
||||
const appTitle = store.state.app.title
|
||||
const { title: appTitle } = useApp()
|
||||
if (title) {
|
||||
return `${title} - ${appTitle}`
|
||||
}
|
||||
@ -49,9 +53,15 @@ const getPageTitle = title => {
|
||||
// 白名单,里面是路由对象的name
|
||||
const WhiteList = ['login', 'lock']
|
||||
|
||||
let loadingInstance = null
|
||||
|
||||
// vue-router4的路由守卫不再是通过next放行,而是通过return返回true或false或者一个路由地址
|
||||
router.beforeEach(async to => {
|
||||
document.title = getPageTitle(!!to.meta && to.meta.title)
|
||||
loadingInstance = ElLoading.service({
|
||||
lock: true,
|
||||
// text: '正在加载数据,请稍候~',
|
||||
background: 'rgba(0, 0, 0, 0.7)',
|
||||
})
|
||||
|
||||
if (WhiteList.includes(to.name)) {
|
||||
return true
|
||||
@ -65,40 +75,25 @@ router.beforeEach(async to => {
|
||||
replace: true,
|
||||
}
|
||||
} else {
|
||||
const { userinfo, getUserinfo } = useAccount()
|
||||
// 获取用户角色信息,根据角色判断权限
|
||||
let userinfo = store.state.account.userinfo
|
||||
if (!userinfo) {
|
||||
const loadingInstance = ElLoading.service({
|
||||
lock: true,
|
||||
text: '正在加载数据,请稍候~',
|
||||
background: 'rgba(0, 0, 0, 0.7)',
|
||||
})
|
||||
try {
|
||||
// 获取用户信息
|
||||
userinfo = await store.dispatch('account/getUserinfo')
|
||||
loadingInstance.close()
|
||||
await getUserinfo()
|
||||
} catch (err) {
|
||||
loadingInstance.close()
|
||||
return false
|
||||
}
|
||||
|
||||
// 删除所有动态路由
|
||||
asyncRoutes.forEach(item => {
|
||||
router.removeRoute(item.name)
|
||||
})
|
||||
return to.fullPath
|
||||
}
|
||||
|
||||
// 生成菜单(如果你的项目有动态菜单,在此处会添加动态路由)
|
||||
if (store.state.menu.menus.length <= 0) {
|
||||
const loadingInstance = ElLoading.service({
|
||||
lock: true,
|
||||
text: '正在加载数据,请稍候~',
|
||||
background: 'rgba(0, 0, 0, 0.7)',
|
||||
})
|
||||
const { menus, generateMenus } = useMenus()
|
||||
if (menus.length <= 0) {
|
||||
try {
|
||||
await store.dispatch('menu/generateMenus', userinfo)
|
||||
loadingInstance.close()
|
||||
await generateMenus()
|
||||
return to.fullPath // 添加动态路由后,必须加这一句触发重定向,否则会404
|
||||
} catch (err) {
|
||||
loadingInstance.close()
|
||||
@ -108,7 +103,7 @@ router.beforeEach(async to => {
|
||||
|
||||
// 判断是否处于锁屏状态
|
||||
if (to.name !== 'lock') {
|
||||
const { authorization } = store.state.app
|
||||
const { authorization } = useApp()
|
||||
if (!!authorization && !!authorization.screenCode) {
|
||||
return {
|
||||
name: 'lock',
|
||||
@ -121,3 +116,12 @@ router.beforeEach(async to => {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
router.afterEach(to => {
|
||||
loadingInstance.close()
|
||||
if (router.currentRoute.value.name === to.name) {
|
||||
nextTick(() => {
|
||||
document.title = getPageTitle(!!to.meta && to.meta.truetitle)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@ -14,22 +14,15 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-21 12:48:11
|
||||
* @LastEditTime: 2022-09-27 14:52:09
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
|
||||
import { createStore } from 'vuex'
|
||||
import { createPinia } from 'pinia'
|
||||
|
||||
const modulesFiles = import.meta.globEager('./modules/*.js')
|
||||
const modules = Object.entries(modulesFiles).reduce((modules, [path, mod]) => {
|
||||
const moduleName = path.replace(/^\.\/modules\/(.*)\.\w+$/, '$1')
|
||||
modules[moduleName] = mod.default
|
||||
return modules
|
||||
}, {})
|
||||
const pinia = createPinia()
|
||||
|
||||
export default createStore({
|
||||
modules,
|
||||
})
|
||||
export default pinia
|
||||
@ -3,38 +3,32 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-29 10:10:14
|
||||
* @LastEditTime: 2022-09-27 14:57:06
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
import { defineStore } from 'pinia'
|
||||
import { GetUserinfo } from '@/api/login'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
export const useAccount = defineStore('account', {
|
||||
state: () => ({
|
||||
userinfo: null,
|
||||
permissionList: [],
|
||||
},
|
||||
mutations: {
|
||||
// 保存用户信息
|
||||
setUserinfo(state, data) {
|
||||
state.userinfo = data
|
||||
},
|
||||
// 清除用户信息
|
||||
clearUserinfo(state) {
|
||||
state.userinfo = null
|
||||
},
|
||||
},
|
||||
}),
|
||||
actions: {
|
||||
// 清除用户信息
|
||||
clearUserinfo() {
|
||||
this.userinfo = null
|
||||
},
|
||||
// 获取用户信息
|
||||
async getUserinfo({ commit }) {
|
||||
async getUserinfo() {
|
||||
const { code, data } = await GetUserinfo()
|
||||
if (+code === 200) {
|
||||
commit('setUserinfo', data)
|
||||
this.userinfo = data
|
||||
return Promise.resolve(data)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
@ -3,70 +3,67 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-11-15 09:51:45
|
||||
* @LastEditTime: 2022-09-27 15:42:35
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
|
||||
import { defineStore } from 'pinia'
|
||||
import { getItem, setItem, removeItem } from '@/utils/storage' //getItem和setItem是封装的操作localStorage的方法
|
||||
import { AesEncryption } from '@/utils/encrypt'
|
||||
import { toRaw } from 'vue'
|
||||
import { useAccount } from './account'
|
||||
import { useTags } from './tags'
|
||||
import { useMenus } from './menu'
|
||||
export const TOKEN = 'VEA-TOKEN'
|
||||
const COLLAPSE = 'VEA-COLLAPSE'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
export const useApp = defineStore('app', {
|
||||
state: () => ({
|
||||
title: 'Vue3 Element Admin',
|
||||
authorization: getItem(TOKEN),
|
||||
sidebar: {
|
||||
collapse: getItem(COLLAPSE),
|
||||
},
|
||||
device: 'desktop',
|
||||
},
|
||||
mutations: {
|
||||
setToken(state, data) {
|
||||
state.authorization = data
|
||||
// 保存到localStorage
|
||||
setItem(TOKEN, data)
|
||||
},
|
||||
clearToken(state) {
|
||||
state.authorization = ''
|
||||
|
||||
removeItem(TOKEN)
|
||||
},
|
||||
setCollapse(state, data) {
|
||||
state.sidebar.collapse = data
|
||||
}),
|
||||
actions: {
|
||||
setCollapse(data) {
|
||||
this.sidebar.collapse = data
|
||||
// 保存到localStorage
|
||||
setItem(COLLAPSE, data)
|
||||
},
|
||||
clearCollapse(state) {
|
||||
state.sidebar.collapse = ''
|
||||
|
||||
clearCollapse() {
|
||||
this.sidebar.collapse = ''
|
||||
removeItem(COLLAPSE)
|
||||
},
|
||||
setDevice(state, device) {
|
||||
state.device = device
|
||||
setDevice(device) {
|
||||
this.device = device
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setToken({ commit, dispatch }, payload) {
|
||||
dispatch('clearToken')
|
||||
commit('setToken', payload)
|
||||
setToken(data) {
|
||||
this.authorization = data
|
||||
// 保存到localStorage
|
||||
setItem(TOKEN, data)
|
||||
},
|
||||
clearToken({ commit }) {
|
||||
initToken(data) {
|
||||
this.clearToken()
|
||||
this.setToken(data)
|
||||
},
|
||||
clearToken() {
|
||||
// 清除token
|
||||
commit('clearToken')
|
||||
this.authorization = ''
|
||||
removeItem(TOKEN)
|
||||
// 清除用户信息
|
||||
commit('account/clearUserinfo', '', { root: true })
|
||||
useAccount().clearUserinfo()
|
||||
// 清除标签栏
|
||||
commit('tags/CLEAR_ALL_TAGS', '', { root: true })
|
||||
useTags().clearAllTags()
|
||||
// 清空menus
|
||||
commit('menu/SET_MENUS', [], { root: true })
|
||||
useMenus().setMenus([])
|
||||
},
|
||||
setScreenCode({ commit, state }, password) {
|
||||
const authorization = toRaw(state.authorization)
|
||||
setScreenCode(password) {
|
||||
const authorization = toRaw(this.authorization)
|
||||
|
||||
if (!password) {
|
||||
try {
|
||||
@ -74,7 +71,10 @@ export default {
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
commit('setToken', authorization)
|
||||
|
||||
this.authorization = authorization
|
||||
// 保存到localStorage
|
||||
setItem(TOKEN, authorization)
|
||||
|
||||
return
|
||||
}
|
||||
@ -82,10 +82,13 @@ export default {
|
||||
// 对密码加密
|
||||
const screenCode = new AesEncryption().encryptByAES(password)
|
||||
|
||||
commit('setToken', {
|
||||
const res = {
|
||||
...authorization,
|
||||
screenCode,
|
||||
})
|
||||
}
|
||||
this.authorization = res
|
||||
// 保存到localStorage
|
||||
setItem(TOKEN, res)
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
29
src/pinia/modules/errorLog.js
Normal file
29
src/pinia/modules/errorLog.js
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* @Descripttion:
|
||||
* @version:
|
||||
* @Date: 2021-04-21 09:18:32
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2022-09-27 15:45:36
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useErrorlog = defineStore('errorLog', {
|
||||
state: () => ({
|
||||
logs: [],
|
||||
}),
|
||||
actions: {
|
||||
addErrorLog(log) {
|
||||
// 可以根据需要将错误上报给服务器
|
||||
// ....code.......
|
||||
|
||||
this.logs.push(log)
|
||||
},
|
||||
clearErrorLog() {
|
||||
this.logs.splice(0)
|
||||
},
|
||||
},
|
||||
})
|
||||
@ -27,24 +27,24 @@
|
||||
* @version:
|
||||
* @Date: 2021-07-23 16:10:49
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-18 15:03:26
|
||||
* @LastEditTime: 2022-09-27 15:47:50
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
|
||||
import { defineStore } from 'pinia'
|
||||
import { getItem, setItem } from '@/utils/storage' //getItem和setItem是封装的操作localStorage的方法
|
||||
import defaultSettings from '@/default-settings'
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: getItem('defaultSettings') || defaultSettings,
|
||||
mutations: {
|
||||
SAVE_SETTINGS(state, data) {
|
||||
|
||||
export const useLayoutsettings = defineStore('layoutSettings', {
|
||||
state: () => getItem('defaultSettings') || defaultSettings,
|
||||
actions: {
|
||||
saveSettings(data) {
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
state[key] = value
|
||||
this[key] = value
|
||||
})
|
||||
setItem('defaultSettings', data)
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
106
src/pinia/modules/menu.js
Normal file
106
src/pinia/modules/menu.js
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* @Descripttion:
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2022-09-27 16:41:46
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
import { defineStore } from 'pinia'
|
||||
import { fixedRoutes, asyncRoutes } from '@/router'
|
||||
import { GetMenus } from '@/api/menu'
|
||||
import router from '@/router'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export const useMenus = defineStore('menu', () => {
|
||||
const generateUrl = (path, parentPath) => {
|
||||
return path.startsWith('/')
|
||||
? path
|
||||
: path
|
||||
? `${parentPath}/${path}`
|
||||
: parentPath
|
||||
}
|
||||
|
||||
const getFilterRoutes = (targetRoutes, ajaxRoutes) => {
|
||||
const filterRoutes = []
|
||||
|
||||
ajaxRoutes.forEach(item => {
|
||||
const target = targetRoutes.find(target => target.name === item.name)
|
||||
|
||||
if (target) {
|
||||
const { children: targetChildren, ...rest } = target
|
||||
const route = {
|
||||
...rest,
|
||||
}
|
||||
|
||||
if (item.children) {
|
||||
route.children = getFilterRoutes(targetChildren, item.children)
|
||||
}
|
||||
|
||||
filterRoutes.push(route)
|
||||
}
|
||||
})
|
||||
|
||||
return filterRoutes
|
||||
}
|
||||
|
||||
const getFilterMenus = (arr, parentPath = '') => {
|
||||
const menus = []
|
||||
|
||||
arr.forEach(item => {
|
||||
if (!item.hidden) {
|
||||
const menu = {
|
||||
url: generateUrl(item.path, parentPath),
|
||||
title: item.meta.title,
|
||||
icon: item.icon,
|
||||
}
|
||||
if (item.children) {
|
||||
if (item.children.filter(child => !child.hidden).length <= 1) {
|
||||
menu.url = generateUrl(item.children[0].path, menu.url)
|
||||
} else {
|
||||
menu.children = getFilterMenus(item.children, menu.url)
|
||||
}
|
||||
}
|
||||
menus.push(menu)
|
||||
}
|
||||
})
|
||||
|
||||
return menus
|
||||
}
|
||||
|
||||
const menus = ref([])
|
||||
const setMenus = data => {
|
||||
menus.value = data
|
||||
}
|
||||
const generateMenus = async () => {
|
||||
// // 方式一:只有固定菜单
|
||||
// const menus = getFilterMenus(fixedRoutes)
|
||||
// commit('SET_MENUS', menus)
|
||||
|
||||
// 方式二:有动态菜单
|
||||
// 从后台获取菜单
|
||||
const { code, data } = await GetMenus()
|
||||
|
||||
if (+code === 200) {
|
||||
// 添加路由之前先删除所有动态路由
|
||||
asyncRoutes.forEach(item => {
|
||||
router.removeRoute(item.name)
|
||||
})
|
||||
// 过滤出需要添加的动态路由
|
||||
const filterRoutes = getFilterRoutes(asyncRoutes, data)
|
||||
filterRoutes.forEach(route => router.addRoute(route))
|
||||
|
||||
// 生成菜单
|
||||
const menus = getFilterMenus([...fixedRoutes, ...filterRoutes])
|
||||
setMenus(menus)
|
||||
}
|
||||
}
|
||||
return {
|
||||
menus,
|
||||
setMenus,
|
||||
generateMenus,
|
||||
}
|
||||
})
|
||||
113
src/pinia/modules/tags.js
Normal file
113
src/pinia/modules/tags.js
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* @Descripttion:
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2022-09-27 16:49:31
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
import { defineStore } from 'pinia'
|
||||
import { getItem, setItem, removeItem } from '@/utils/storage' //getItem和setItem是封装的操作localStorage的方法
|
||||
const TAGLIST = 'VEA-TAGLIST'
|
||||
|
||||
export const useTags = defineStore('tags', {
|
||||
state: () => ({
|
||||
tagList: getItem(TAGLIST) || [],
|
||||
cacheList: [],
|
||||
activePosition: -1,
|
||||
}),
|
||||
actions: {
|
||||
saveActivePosition(index) {
|
||||
this.activePosition = index
|
||||
},
|
||||
addTag({ path, fullPath, name, meta, params, query }) {
|
||||
if (this.tagList.some(v => v.path === path)) return false
|
||||
// 添加tagList
|
||||
const target = Object.assign(
|
||||
{},
|
||||
{ path, fullPath, name, meta, params, query },
|
||||
{
|
||||
title: meta.title || '未命名',
|
||||
fullPath: fullPath || path,
|
||||
}
|
||||
)
|
||||
if (this.activePosition === -1) {
|
||||
if (name === 'home') {
|
||||
this.tagList.unshift(target)
|
||||
} else {
|
||||
this.tagList.push(target)
|
||||
}
|
||||
} else {
|
||||
this.tagList.splice(this.activePosition + 1, 0, target)
|
||||
}
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, this.tagList)
|
||||
|
||||
// 添加cacheList
|
||||
if (this.cacheList.includes(name)) return
|
||||
if (!meta.noCache) {
|
||||
this.cacheList.push(name)
|
||||
}
|
||||
},
|
||||
deTagList(tag) {
|
||||
// 删除tagList
|
||||
this.tagList = this.tagList.filter(v => v.path !== tag.path)
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, this.tagList)
|
||||
},
|
||||
deCacheList(tag) {
|
||||
// 删除cacheList
|
||||
this.cacheList = this.cacheList.filter(v => v !== tag.name)
|
||||
},
|
||||
delTag(tag) {
|
||||
// 删除tagList
|
||||
this.deTagList(tag)
|
||||
|
||||
// 删除cacheList
|
||||
this.deCacheList(tag)
|
||||
},
|
||||
delOtherTags(tag) {
|
||||
this.tagList = this.tagList.filter(
|
||||
v => !!v.meta.affix || v.path === tag.path
|
||||
)
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, this.tagList)
|
||||
|
||||
this.cacheList = this.cacheList.filter(v => v === tag.name)
|
||||
},
|
||||
delSomeTags(tags) {
|
||||
this.tagList = this.tagList.filter(
|
||||
v => !!v.meta.affix || tags.every(tag => tag.path !== v.path)
|
||||
)
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, this.tagList)
|
||||
|
||||
this.cacheList = this.cacheList.filter(v =>
|
||||
tags.every(tag => tag.name !== v)
|
||||
)
|
||||
},
|
||||
delAllTags() {
|
||||
this.tagList = this.tagList.filter(v => !!v.meta.affix)
|
||||
// 保存到localStorage
|
||||
removeItem(TAGLIST)
|
||||
this.cacheList = []
|
||||
},
|
||||
updateTagList(tag) {
|
||||
const index = this.tagList.findIndex(v => v.path === tag.path)
|
||||
if (index > -1) {
|
||||
this.tagList[index] = Object.assign({}, this.tagList[index], tag)
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, this.tagList)
|
||||
}
|
||||
},
|
||||
clearAllTags() {
|
||||
this.cacheList = []
|
||||
this.tagList = []
|
||||
// 保存到localStorage
|
||||
removeItem(TAGLIST)
|
||||
},
|
||||
},
|
||||
})
|
||||
@ -3,16 +3,17 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-18 16:23:58
|
||||
* @LastEditTime: 2022-09-27 18:14:03
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
import store from '@/store'
|
||||
|
||||
import { useAccount } from '@/pinia/modules/account'
|
||||
|
||||
const checkUserinfo = (code, fullPath) => {
|
||||
const userinfo = store.state.account.userinfo
|
||||
const { userinfo } = useAccount()
|
||||
if (userinfo) {
|
||||
return `/error/${code === '404' ? fullPath : code}`
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-07-26 14:37:08
|
||||
* @LastEditTime: 2022-09-24 19:27:21
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -19,16 +19,16 @@ export default [
|
||||
component: Layout,
|
||||
name: 'Dashboard',
|
||||
meta: {
|
||||
title: '工作台',
|
||||
title: 'menu.dashboard',
|
||||
},
|
||||
icon: 'home',
|
||||
icon: 'icon-home',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'home',
|
||||
component: Home,
|
||||
meta: {
|
||||
title: '首页',
|
||||
title: 'menu.homepage',
|
||||
affix: true,
|
||||
},
|
||||
},
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-21 09:18:32
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-07-26 16:30:58
|
||||
* @LastEditTime: 2022-09-27 18:51:35
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -28,16 +28,16 @@ export default [
|
||||
component: Layout,
|
||||
name: 'test',
|
||||
meta: {
|
||||
title: '测试页面',
|
||||
title: 'menu.test',
|
||||
},
|
||||
icon: 'el-icon-location',
|
||||
icon: 'Location',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'testList',
|
||||
component: List,
|
||||
meta: {
|
||||
title: '列表',
|
||||
title: 'menu.testList',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -45,7 +45,7 @@ export default [
|
||||
name: 'testAdd',
|
||||
component: Add,
|
||||
meta: {
|
||||
title: '添加',
|
||||
title: 'menu.testAdd',
|
||||
},
|
||||
hidden: true, // 不在菜单中显示
|
||||
},
|
||||
@ -54,33 +54,33 @@ export default [
|
||||
name: 'testEdit',
|
||||
component: Edit,
|
||||
meta: {
|
||||
title: '编辑',
|
||||
title: 'menu.testEdit',
|
||||
},
|
||||
hidden: true, // 不在菜单中显示
|
||||
},
|
||||
{
|
||||
path: 'auth',
|
||||
name: 'testAuth',
|
||||
component: Auth,
|
||||
meta: {
|
||||
title: '权限测试',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'noauth',
|
||||
name: 'testNoAuth',
|
||||
component: NoAuth,
|
||||
meta: {
|
||||
title: '权限页面',
|
||||
},
|
||||
hidden: true,
|
||||
},
|
||||
// {
|
||||
// path: 'auth',
|
||||
// name: 'testAuth',
|
||||
// component: Auth,
|
||||
// meta: {
|
||||
// title: 'menu.testAuth',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// path: 'noauth',
|
||||
// name: 'testNoAuth',
|
||||
// component: NoAuth,
|
||||
// meta: {
|
||||
// title: 'menu.testNoAuth',
|
||||
// },
|
||||
// hidden: true,
|
||||
// },
|
||||
{
|
||||
path: 'cache',
|
||||
name: 'test-cache',
|
||||
component: Iscache,
|
||||
meta: {
|
||||
title: '该页面可缓存',
|
||||
title: 'menu.test-cache',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -88,7 +88,7 @@ export default [
|
||||
name: 'test-no-cache',
|
||||
component: Nocache,
|
||||
meta: {
|
||||
title: '该页面不缓存',
|
||||
title: 'menu.test-no-cache',
|
||||
noCache: true, // 不缓存页面
|
||||
},
|
||||
},
|
||||
@ -98,7 +98,7 @@ export default [
|
||||
component: Nest,
|
||||
redirect: '/test/nest/page1',
|
||||
meta: {
|
||||
title: '二级菜单',
|
||||
title: 'menu.nest',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
@ -106,7 +106,7 @@ export default [
|
||||
name: 'nestPage1',
|
||||
component: NestPage1,
|
||||
meta: {
|
||||
title: 'page1',
|
||||
title: 'menu.nestPage1',
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -114,7 +114,7 @@ export default [
|
||||
name: 'nestPage2',
|
||||
component: NestPage2,
|
||||
meta: {
|
||||
title: 'page2',
|
||||
title: 'menu.nestPage2',
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -124,7 +124,7 @@ export default [
|
||||
name: 'test-error-log',
|
||||
component: ErrorLog,
|
||||
meta: {
|
||||
title: '测试错误日志',
|
||||
title: 'menu.test-error-log',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* @Descripttion:
|
||||
* @version:
|
||||
* @Date: 2021-04-21 09:18:32
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-21 09:34:13
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
const state = {
|
||||
logs: [],
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
ADD_ERROR_LOG: (state, log) => {
|
||||
state.logs.push(log)
|
||||
},
|
||||
CLEAR_ERROR_LOG: state => {
|
||||
state.logs.splice(0)
|
||||
},
|
||||
}
|
||||
|
||||
const actions = {
|
||||
addErrorLog({ commit }, log) {
|
||||
// 可以根据需要将错误上报给服务器
|
||||
// ....code.......
|
||||
|
||||
// 触发mutations
|
||||
commit('ADD_ERROR_LOG', log)
|
||||
},
|
||||
clearErrorLog({ commit }) {
|
||||
commit('CLEAR_ERROR_LOG')
|
||||
},
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions,
|
||||
}
|
||||
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* @Descripttion:
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-07-26 18:22:01
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
import { fixedRoutes, asyncRoutes } from '@/router'
|
||||
import { GetMenus } from '@/api/menu'
|
||||
import router from '@/router'
|
||||
|
||||
// const hasPermission = (role, route) => {
|
||||
// if (!!route.meta && !!route.meta.roles && !route.meta.roles.includes(role)) {
|
||||
// return false
|
||||
// }
|
||||
// return true
|
||||
// }
|
||||
|
||||
const generateUrl = (path, parentPath) => {
|
||||
return path.startsWith('/')
|
||||
? path
|
||||
: path
|
||||
? `${parentPath}/${path}`
|
||||
: parentPath
|
||||
}
|
||||
|
||||
const getFilterRoutes = (targetRoutes, ajaxRoutes) => {
|
||||
const filterRoutes = []
|
||||
|
||||
ajaxRoutes.forEach(item => {
|
||||
const target = targetRoutes.find(target => target.name === item.name)
|
||||
|
||||
if (target) {
|
||||
const { children: targetChildren, ...rest } = target
|
||||
const route = {
|
||||
...rest,
|
||||
}
|
||||
|
||||
if (item.children) {
|
||||
route.children = getFilterRoutes(targetChildren, item.children)
|
||||
}
|
||||
|
||||
filterRoutes.push(route)
|
||||
}
|
||||
})
|
||||
|
||||
return filterRoutes
|
||||
}
|
||||
|
||||
const getFilterMenus = (arr, parentPath = '') => {
|
||||
const menus = []
|
||||
|
||||
arr.forEach(item => {
|
||||
if (!item.hidden) {
|
||||
const menu = {
|
||||
url: generateUrl(item.path, parentPath),
|
||||
title: item.meta.title,
|
||||
icon: item.icon,
|
||||
}
|
||||
if (item.children) {
|
||||
if (item.children.filter(child => !child.hidden).length <= 1) {
|
||||
menu.url = generateUrl(item.children[0].path, menu.url)
|
||||
} else {
|
||||
menu.children = getFilterMenus(item.children, menu.url)
|
||||
}
|
||||
}
|
||||
menus.push(menu)
|
||||
}
|
||||
})
|
||||
|
||||
return menus
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
menus: [],
|
||||
},
|
||||
mutations: {
|
||||
SET_MENUS(state, data) {
|
||||
state.menus = data
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async generateMenus({ commit }, userinfo) {
|
||||
// // 方式一:只有固定菜单
|
||||
// const menus = getFilterMenus(fixedRoutes)
|
||||
// commit('SET_MENUS', menus)
|
||||
|
||||
// 方式二:有动态菜单
|
||||
// 从后台获取菜单
|
||||
const { code, data } = await GetMenus({ role: userinfo.role })
|
||||
|
||||
if (+code === 200) {
|
||||
// 过滤出需要添加的动态路由
|
||||
const filterRoutes = getFilterRoutes(asyncRoutes, data)
|
||||
filterRoutes.forEach(route => router.addRoute(route))
|
||||
|
||||
// 生成菜单
|
||||
const menus = getFilterMenus([...fixedRoutes, ...filterRoutes])
|
||||
commit('SET_MENUS', menus)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -1,150 +0,0 @@
|
||||
/*
|
||||
* @Descripttion:
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-18 15:36:04
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
*/
|
||||
import { getItem, setItem, removeItem } from '@/utils/storage' //getItem和setItem是封装的操作localStorage的方法
|
||||
|
||||
const TAGLIST = 'VEA-TAGLIST'
|
||||
|
||||
const state = {
|
||||
tagList: getItem(TAGLIST) || [],
|
||||
cacheList: [],
|
||||
activePosition: -1,
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
ADD_TAG_LIST: (state, { path, fullPath, name, meta, params, query }) => {
|
||||
if (state.tagList.some(v => v.path === path)) return false
|
||||
|
||||
const target = Object.assign(
|
||||
{},
|
||||
{ path, fullPath, name, meta, params, query },
|
||||
{
|
||||
title: meta.title || '未命名',
|
||||
fullPath: fullPath || path,
|
||||
}
|
||||
)
|
||||
if (state.activePosition === -1) {
|
||||
if (name === 'home') {
|
||||
state.tagList.unshift(target)
|
||||
} else {
|
||||
state.tagList.push(target)
|
||||
}
|
||||
} else {
|
||||
state.tagList.splice(state.activePosition + 1, 0, target)
|
||||
}
|
||||
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList)
|
||||
},
|
||||
ADD_CACHE_LIST: (state, tag) => {
|
||||
if (state.cacheList.includes(tag.name)) return
|
||||
if (!tag.meta.noCache) {
|
||||
state.cacheList.push(tag.name)
|
||||
}
|
||||
},
|
||||
|
||||
DEL_TAG_LIST: (state, tag) => {
|
||||
state.tagList = state.tagList.filter(v => v.path !== tag.path)
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList)
|
||||
},
|
||||
DEL_CACHE_LIST: (state, tag) => {
|
||||
state.cacheList = state.cacheList.filter(v => v !== tag.name)
|
||||
},
|
||||
|
||||
DEL_OTHER_TAG_LIST: (state, tag) => {
|
||||
state.tagList = state.tagList.filter(
|
||||
v => !!v.meta.affix || v.path === tag.path
|
||||
)
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList)
|
||||
},
|
||||
DEL_OTHER_CACHE_LIST: (state, tag) => {
|
||||
state.cacheList = state.cacheList.filter(v => v === tag.name)
|
||||
},
|
||||
|
||||
DEL_SOME_TAG_LIST: (state, tags) => {
|
||||
state.tagList = state.tagList.filter(
|
||||
v => !!v.meta.affix || tags.every(tag => tag.path !== v.path)
|
||||
)
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList)
|
||||
},
|
||||
|
||||
DEL_SOME_CACHE_LIST: (state, tags) => {
|
||||
state.cacheList = state.cacheList.filter(v =>
|
||||
tags.every(tag => tag.name !== v)
|
||||
)
|
||||
},
|
||||
|
||||
DEL_ALL_TAG_LIST: state => {
|
||||
state.tagList = state.tagList.filter(v => !!v.meta.affix)
|
||||
// 保存到localStorage
|
||||
removeItem(TAGLIST)
|
||||
},
|
||||
DEL_ALL_CACHE_LIST: state => {
|
||||
state.cacheList = []
|
||||
},
|
||||
CLEAR_ALL_TAGS: state => {
|
||||
state.cacheList = []
|
||||
state.tagList = []
|
||||
// 保存到localStorage
|
||||
removeItem(TAGLIST)
|
||||
},
|
||||
UPDATE_TAG_LIST: (state, tag) => {
|
||||
const index = state.tagList.findIndex(v => v.path === tag.path)
|
||||
if (index > -1) {
|
||||
state.tagList[index] = Object.assign({}, state.tagList[index], tag)
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList)
|
||||
}
|
||||
},
|
||||
|
||||
SAVE_ACTIVE_POSITION: (state, index) => {
|
||||
state.activePosition = index
|
||||
},
|
||||
}
|
||||
|
||||
const actions = {
|
||||
saveActivePosition({ commit }, index) {
|
||||
commit('SAVE_ACTIVE_POSITION', index)
|
||||
},
|
||||
addTag({ commit }, tag) {
|
||||
commit('ADD_TAG_LIST', tag)
|
||||
commit('ADD_CACHE_LIST', tag)
|
||||
},
|
||||
delTag({ commit }, tag) {
|
||||
commit('DEL_TAG_LIST', tag)
|
||||
commit('DEL_CACHE_LIST', tag)
|
||||
},
|
||||
delOtherTags({ commit }, tag) {
|
||||
commit('DEL_OTHER_TAG_LIST', tag)
|
||||
commit('DEL_OTHER_CACHE_LIST', tag)
|
||||
},
|
||||
delSomeTags({ commit }, tags) {
|
||||
commit('DEL_SOME_TAG_LIST', tags)
|
||||
commit('DEL_SOME_CACHE_LIST', tags)
|
||||
},
|
||||
delAllTags({ commit }) {
|
||||
commit('DEL_ALL_TAG_LIST')
|
||||
commit('DEL_ALL_CACHE_LIST')
|
||||
},
|
||||
updateTagList({ commit }, { path, fullPath, name, meta, params, query }) {
|
||||
commit('UPDATE_TAG_LIST', { path, fullPath, name, meta, params, query })
|
||||
},
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions,
|
||||
}
|
||||
@ -22,7 +22,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-18 15:44:39
|
||||
* @LastEditTime: 2022-09-27 18:17:20
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -31,8 +31,8 @@
|
||||
|
||||
import axios from 'axios'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import store from '@/store'
|
||||
import router from '@/router'
|
||||
import { useApp } from '@/pinia/modules/app'
|
||||
|
||||
const service = axios.create({
|
||||
baseURL: '/',
|
||||
@ -43,7 +43,7 @@ const service = axios.create({
|
||||
// 拦截请求
|
||||
service.interceptors.request.use(
|
||||
config => {
|
||||
const { authorization } = store.state.app
|
||||
const { authorization } = useApp()
|
||||
if (authorization) {
|
||||
config.headers.Authorization = `Bearer ${authorization.token}`
|
||||
}
|
||||
@ -67,7 +67,7 @@ service.interceptors.response.use(
|
||||
// 响应拦截器中的 error 就是那个响应的错误对象
|
||||
if (error.response && error.response.status === 401) {
|
||||
// 校验是否有 refresh_token
|
||||
const { authorization } = store.state.app
|
||||
const { authorization, clearToken, setToken } = useApp()
|
||||
if (!authorization || !authorization.refresh_token) {
|
||||
if (router.currentRoute.value.name === 'login') {
|
||||
return Promise.reject(error)
|
||||
@ -75,7 +75,7 @@ service.interceptors.response.use(
|
||||
const redirect = encodeURIComponent(window.location.href)
|
||||
router.push(`/login?redirect=${redirect}`)
|
||||
// 清除token
|
||||
store.dispatch('app/clearToken')
|
||||
clearToken()
|
||||
setTimeout(() => {
|
||||
ElMessage.closeAll()
|
||||
try {
|
||||
@ -99,7 +99,7 @@ service.interceptors.response.use(
|
||||
})
|
||||
// 如果获取成功,则把新的 token 更新到容器中
|
||||
// console.log('刷新 token 成功', res)
|
||||
store.commit('app/setToken', {
|
||||
setToken({
|
||||
token: res.data.data.token, // 最新获取的可用 token
|
||||
refresh_token: authorization.refresh_token, // 还是原来的 refresh_token
|
||||
})
|
||||
@ -113,7 +113,7 @@ service.interceptors.response.use(
|
||||
const redirect = encodeURIComponent(window.location.href)
|
||||
router.push(`/login?redirect=${redirect}`)
|
||||
// 清除token
|
||||
store.dispatch('app/clearToken')
|
||||
clearToken()
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-21 09:33:01
|
||||
* @LastEditTime: 2022-09-24 21:52:50
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -14,19 +14,19 @@
|
||||
<template v-if="error === '403'">
|
||||
<span class="code-403">403</span>
|
||||
<svg-icon name="error-icons-403" class="error-img" />
|
||||
<h2 class="title">您无权访问此页面</h2>
|
||||
<h2 class="title">{{ $t('error.noauth') }}</h2>
|
||||
</template>
|
||||
<template v-else-if="error === '500'">
|
||||
<svg-icon name="error-icons-500" class="error-img" />
|
||||
<h2 class="title">服务器出错了</h2>
|
||||
<h2 class="title">{{ $t('error.servererror') }}</h2>
|
||||
</template>
|
||||
<template v-else-if="error === '404'">
|
||||
<svg-icon name="error-icons-404" class="error-img" />
|
||||
<h2 class="title">您访问的页面不存在</h2>
|
||||
<h2 class="title">{{ $t('error.notfound') }}</h2>
|
||||
</template>
|
||||
|
||||
<router-link to="/">
|
||||
<el-button type="primary">返回首页</el-button>
|
||||
<el-button type="primary">{{ $t('error.backhome') }}</el-button>
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -3,27 +3,12 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-23 15:16:12
|
||||
* @LastEditTime: 2022-09-24 18:18:43
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
|
||||
-->
|
||||
<template>
|
||||
<div class="home">home</div>
|
||||
home
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'home',
|
||||
setup() {},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.home {
|
||||
color: $mainColor;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-23 16:21:00
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-04-23 16:50:50
|
||||
* @LastEditTime: 2022-09-25 11:10:49
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -34,7 +34,13 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="current-time" v-html="currentTime"></div>
|
||||
<div class="current-time">
|
||||
<div class="time">{{ currentTime }}</div>
|
||||
<div class="date">
|
||||
{{ currentDate }}
|
||||
<span style="margin-left: 16px">{{ $t(week) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -45,10 +51,7 @@ export default defineComponent({
|
||||
setup() {
|
||||
const currentTime = ref(null)
|
||||
const getTime = () => {
|
||||
currentTime.value = parseTime(
|
||||
new Date(),
|
||||
'<div class="time">{h}:{i}:{s}</div><div class="date">{y}-{m}-{d} 周{a}</div>'
|
||||
)
|
||||
currentTime.value = parseTime(new Date(), '{h}:{i}:{s}')
|
||||
requestAnimationFrame(getTime)
|
||||
}
|
||||
|
||||
@ -58,6 +61,8 @@ export default defineComponent({
|
||||
|
||||
return {
|
||||
currentTime,
|
||||
currentDate: parseTime(new Date(), '{y}-{m}-{d}'),
|
||||
week: `topbar.lock-week${new Date().getDay()}`,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-23 19:17:20
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-07-19 10:04:01
|
||||
* @LastEditTime: 2022-09-27 18:37:28
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -46,10 +46,10 @@
|
||||
|
||||
<template>
|
||||
<h1 class="title">
|
||||
⚡ 屏幕已锁定
|
||||
⚡ {{ $t('topbar.lock-locked') }}
|
||||
<div class="unlock-btn" @click="handleUnlock">
|
||||
<i class="el-icon-unlock"></i>
|
||||
解锁
|
||||
{{ $t('topbar.lock-lock') }}
|
||||
</div>
|
||||
</h1>
|
||||
<div class="unlock-modal" v-show="showModal">
|
||||
@ -60,14 +60,15 @@
|
||||
type="password"
|
||||
v-model.trim="lockModel.password"
|
||||
autocomplete="off"
|
||||
placeholder="请输入锁屏密码或登录密码"
|
||||
:placeholder="$t('topbar.lock-rules-password2')"
|
||||
@keyup.enter="submitForm"
|
||||
style="width:320px"
|
||||
>
|
||||
<template #append>
|
||||
<el-button
|
||||
type="primary"
|
||||
class="btn-unlock"
|
||||
icon="el-icon-right"
|
||||
icon="Right"
|
||||
:loading="loading"
|
||||
@click="submitForm"
|
||||
></el-button>
|
||||
@ -75,8 +76,12 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="cancel" type="text">取消</el-button>
|
||||
<el-button @click="reLogin" type="text">重新登录</el-button>
|
||||
<el-button @click="cancel" type="text">
|
||||
{{ $t('public.cancel') }}
|
||||
</el-button>
|
||||
<el-button @click="reLogin" type="text">
|
||||
{{ $t('topbar.lock-relogin') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
@ -86,8 +91,10 @@ import { defineComponent, ref, reactive, getCurrentInstance } from 'vue'
|
||||
import Avatar from '@/components/Avatar/index.vue'
|
||||
import { AesEncryption } from '@/utils/encrypt'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { Login } from '@/api/login'
|
||||
import { useApp } from '@/pinia/modules/app'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useAccount } from '@/pinia/modules/account'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -95,7 +102,6 @@ export default defineComponent({
|
||||
},
|
||||
setup() {
|
||||
const { proxy: ctx } = getCurrentInstance()
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const showModal = ref(false)
|
||||
@ -105,9 +111,15 @@ export default defineComponent({
|
||||
})
|
||||
const loading = ref(false)
|
||||
|
||||
const appStore = useApp()
|
||||
const { authorization } = storeToRefs(appStore)
|
||||
const { clearToken, setScreenCode } = appStore
|
||||
const accountStore = useAccount()
|
||||
const { userinfo } = storeToRefs(accountStore)
|
||||
const { getUserinfo } = accountStore
|
||||
|
||||
const checkPwd = async (rule, value, callback) => {
|
||||
const { authorization } = store.state.app
|
||||
const cipher = authorization && authorization.screenCode
|
||||
const cipher = authorization.value && authorization.value.screenCode
|
||||
if (!cipher) {
|
||||
return callback()
|
||||
}
|
||||
@ -118,7 +130,7 @@ export default defineComponent({
|
||||
// 尝试登录
|
||||
loading.value = true
|
||||
const { code } = await Login({
|
||||
username: store.state.account.userinfo.name,
|
||||
username: userinfo.value.name,
|
||||
password: value,
|
||||
})
|
||||
loading.value = false
|
||||
@ -131,10 +143,10 @@ export default defineComponent({
|
||||
|
||||
const lockRules = reactive({
|
||||
password: [
|
||||
{ required: true, message: '请输入密码' },
|
||||
{ required: true, message: ctx.$t('topbar.lock-rules-password2') },
|
||||
{
|
||||
validator: checkPwd,
|
||||
message: '密码错误',
|
||||
message: ctx.$t('topbar.lock-rules-password3'),
|
||||
trigger: 'none',
|
||||
},
|
||||
],
|
||||
@ -142,13 +154,14 @@ export default defineComponent({
|
||||
|
||||
const handleUnlock = () => {
|
||||
// 判断当前是否登录
|
||||
const { authorization } = store.state.app
|
||||
if (authorization) {
|
||||
if (authorization.value) {
|
||||
showModal.value = true
|
||||
// 尝试获取用户信息
|
||||
!store.state.account.userinfo && store.dispatch('account/getUserinfo')
|
||||
if (!userinfo.value) {
|
||||
getUserinfo()
|
||||
}
|
||||
} else {
|
||||
ctx.$message('您的账号已退出,请直接登录')
|
||||
ctx.$message(ctx.$t('topbar.lock-error'))
|
||||
reLogin()
|
||||
}
|
||||
}
|
||||
@ -162,7 +175,7 @@ export default defineComponent({
|
||||
// 返回锁屏前的页面
|
||||
router.push({ path: route.query.redirect || '/', replace: true })
|
||||
// 清除锁屏密码
|
||||
store.dispatch('app/setScreenCode', '')
|
||||
setScreenCode('')
|
||||
})
|
||||
}
|
||||
|
||||
@ -174,7 +187,7 @@ export default defineComponent({
|
||||
const reLogin = () => {
|
||||
router.push('/login?redirect=' + (route.query.redirect || '/'))
|
||||
// 清除token
|
||||
store.dispatch('app/clearToken')
|
||||
clearToken()
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-11-15 09:48:29
|
||||
* @LastEditTime: 2022-09-27 18:24:27
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -17,19 +17,19 @@
|
||||
<el-input
|
||||
class="text"
|
||||
v-model="model.userName"
|
||||
prefix-icon="el-icon-user-solid"
|
||||
prefix-icon="User"
|
||||
clearable
|
||||
placeholder="用户名"
|
||||
:placeholder="$t('login.username')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
class="text"
|
||||
v-model="model.password"
|
||||
prefix-icon="el-icon-lock"
|
||||
prefix-icon="Lock"
|
||||
show-password
|
||||
clearable
|
||||
placeholder="密码"
|
||||
:placeholder="$t('login.password')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
@ -37,6 +37,7 @@
|
||||
:loading="loading"
|
||||
type="primary"
|
||||
class="btn"
|
||||
size="large"
|
||||
@click="submit"
|
||||
>
|
||||
{{ btnText }}
|
||||
@ -44,6 +45,9 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="change-lang">
|
||||
<change-lang />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -54,39 +58,57 @@ import {
|
||||
toRefs,
|
||||
ref,
|
||||
computed,
|
||||
watch,
|
||||
} from 'vue'
|
||||
import { Login } from '@/api/login'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import ChangeLang from '@/layout/components/Topbar/ChangeLang.vue'
|
||||
import useLang from '@/i18n/useLang'
|
||||
import { useApp } from '@/pinia/modules/app'
|
||||
|
||||
export default defineComponent({
|
||||
components: { ChangeLang },
|
||||
name: 'login',
|
||||
setup() {
|
||||
const { proxy: ctx } = getCurrentInstance() // 可以把ctx当成vue2中的this
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const { lang } = useLang()
|
||||
watch(lang, () => {
|
||||
state.rules = getRules()
|
||||
})
|
||||
const getRules = () => ({
|
||||
userName: [
|
||||
{
|
||||
required: true,
|
||||
message: ctx.$t('login.rules-username'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: ctx.$t('login.rules-password'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
min: 6,
|
||||
max: 12,
|
||||
message: ctx.$t('login.rules-regpassword'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
})
|
||||
const state = reactive({
|
||||
model: {
|
||||
userName: 'admin',
|
||||
password: '123456',
|
||||
},
|
||||
rules: {
|
||||
userName: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{
|
||||
min: 6,
|
||||
max: 12,
|
||||
message: '长度在 6 到 12 个字符',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
},
|
||||
rules: getRules(),
|
||||
loading: false,
|
||||
btnText: computed(() => (state.loading ? '登录中...' : '登录')),
|
||||
btnText: computed(() =>
|
||||
state.loading ? ctx.$t('login.logining') : ctx.$t('login.login')
|
||||
),
|
||||
loginForm: ref(null),
|
||||
submit: () => {
|
||||
if (state.loading) {
|
||||
@ -98,7 +120,7 @@ export default defineComponent({
|
||||
const { code, data, message } = await Login(state.model)
|
||||
if (+code === 200) {
|
||||
ctx.$message.success({
|
||||
message: '登录成功',
|
||||
message: ctx.$t('login.loginsuccess'),
|
||||
duration: 1000,
|
||||
})
|
||||
|
||||
@ -112,8 +134,7 @@ export default defineComponent({
|
||||
} else {
|
||||
router.push('/')
|
||||
}
|
||||
|
||||
store.dispatch('app/setToken', data)
|
||||
useApp().initToken(data)
|
||||
} else {
|
||||
ctx.$message.error(message)
|
||||
}
|
||||
@ -144,6 +165,20 @@ export default defineComponent({
|
||||
padding: 0 24px;
|
||||
box-sizing: border-box;
|
||||
margin: 160px auto 0;
|
||||
:deep {
|
||||
.el-input__wrapper {
|
||||
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1) inset;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.el-input-group--append > .el-input__wrapper {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
.el-input-group--prepend > .el-input__wrapper {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
@ -153,8 +188,6 @@ export default defineComponent({
|
||||
.text {
|
||||
font-size: 16px;
|
||||
:deep(.el-input__inner) {
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
color: #fff;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
@ -168,4 +201,20 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
}
|
||||
.change-lang {
|
||||
position: fixed;
|
||||
right: 20px;
|
||||
top: 20px;
|
||||
:deep {
|
||||
.change-lang {
|
||||
height: 24px;
|
||||
&:hover {
|
||||
background: none;
|
||||
}
|
||||
.icon {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-18 18:10:39
|
||||
* @LastEditTime: 2022-09-24 18:16:03
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -16,111 +16,4 @@
|
||||
<br />
|
||||
需要配置路由增加属性hidden: true,注意不是在meta中增加该属性,而是跟meta同级
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div style="width: 400px">
|
||||
<el-select-tree
|
||||
placeholder="请选择角色"
|
||||
v-model="roles"
|
||||
:multiple="true"
|
||||
:data="treeData"
|
||||
:tree-props="treeProps"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, reactive, toRefs } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const state = reactive({
|
||||
roles: ['11', '311'],
|
||||
treeData: [
|
||||
{
|
||||
id: '1',
|
||||
label: '一级 1',
|
||||
children: [
|
||||
{
|
||||
id: '11',
|
||||
label: '二级 1-1',
|
||||
children: [
|
||||
{
|
||||
id: '111',
|
||||
label: '三级 1-1-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
label: '一级 2',
|
||||
children: [
|
||||
{
|
||||
id: '21',
|
||||
label: '二级 2-1',
|
||||
children: [
|
||||
{
|
||||
id: '211',
|
||||
label: '三级 2-1-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '22',
|
||||
label: '二级 2-2',
|
||||
children: [
|
||||
{
|
||||
id: '221',
|
||||
label: '三级 2-2-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
label: '一级 3',
|
||||
children: [
|
||||
{
|
||||
id: '31',
|
||||
label: '二级 3-1',
|
||||
children: [
|
||||
{
|
||||
id: '311',
|
||||
label: '三级 3-1-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '32',
|
||||
label: '二级 3-2',
|
||||
children: [
|
||||
{
|
||||
id: '321',
|
||||
label: '三级 3-2-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
treeProps: {
|
||||
props: {
|
||||
children: 'children',
|
||||
label: 'label',
|
||||
},
|
||||
},
|
||||
handleChange(v) {
|
||||
console.log('你选择了:', v)
|
||||
},
|
||||
})
|
||||
return {
|
||||
...toRefs(state),
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
<template>
|
||||
<h2>
|
||||
当前用户角色:{{
|
||||
$store.state.account.userinfo && $store.state.account.userinfo.role
|
||||
}}
|
||||
</h2>
|
||||
<h2>当前用户角色:{{ userinfo && userinfo.role }}</h2>
|
||||
<h4><mark>刷新页面可切换随机角色</mark></h4>
|
||||
<router-link to="/test/noauth">点击进入只有admin才能访问的页面</router-link>
|
||||
</template>
|
||||
<script setup>
|
||||
import { useAccount } from '@/pinia/modules/account'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const { userinfo } = storeToRefs(useAccount())
|
||||
</script>
|
||||
|
||||
@ -1,57 +1,75 @@
|
||||
<template>
|
||||
<pro-table
|
||||
ref="table"
|
||||
title="列表"
|
||||
:title="$t('test/list.title')"
|
||||
:request="getList"
|
||||
:columns="columns"
|
||||
:search="searchConfig"
|
||||
:pagination="paginationConfig"
|
||||
@selectionChange="handleSelectionChange"
|
||||
>
|
||||
<!-- 工具栏 -->
|
||||
<template #toolbar>
|
||||
<el-button type="primary" icon="el-icon-delete" @click="batchDelete">
|
||||
批量删除
|
||||
<el-button type="primary" icon="Delete" @click="batchDelete">
|
||||
{{ $t('test/list.batchDelete') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
@click="$router.push('/test/add')"
|
||||
>
|
||||
添加一条
|
||||
<el-button type="primary" icon="Plus" @click="$router.push('/test/add')">
|
||||
{{ $t('test/list.add') }}
|
||||
</el-button>
|
||||
<el-button type="primary" icon="el-icon-refresh" @click="refresh">
|
||||
刷新
|
||||
<el-button type="primary" icon="Refresh" @click="refresh">
|
||||
{{ $t('test/list.refresh') }}
|
||||
</el-button>
|
||||
</template>
|
||||
<template #status="{row}">
|
||||
<el-tag :type="row.status === 1 ? 'success' : 'error'">
|
||||
{{ row.status === 1 ? $t('public.enabled') : $t('public.disabled') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
<template #operate="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="$router.push(`/test/edit/${scope.row.id}`)"
|
||||
>
|
||||
编辑
|
||||
{{ $t('public.edit') }}
|
||||
</el-button>
|
||||
<el-button size="small" type="danger">
|
||||
{{ $t('public.delete') }}
|
||||
</el-button>
|
||||
<el-button size="mini" type="danger">删除</el-button>
|
||||
</template>
|
||||
</pro-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, reactive, ref, toRefs } from 'vue'
|
||||
|
||||
import { getUsers } from '@/api/test'
|
||||
export default defineComponent({
|
||||
name: 'testList',
|
||||
setup() {
|
||||
// const { proxy } = getCurrentInstance()
|
||||
|
||||
const state = reactive({
|
||||
// 表格列配置,大部分属性跟el-table-column配置一样
|
||||
columns: [
|
||||
{ type: 'selection' },
|
||||
{ label: '序号', type: 'index' },
|
||||
{ label: '名称', prop: 'nickName', sortable: true, width: 180 },
|
||||
{ label: '邮箱', prop: 'userEmail' },
|
||||
{ type: 'selection', width: 56 },
|
||||
{ label: 'test/list.index', type: 'index', width: 80 },
|
||||
{
|
||||
label: '操作',
|
||||
label: 'test/list.name',
|
||||
prop: 'nickName',
|
||||
sortable: true,
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
label: 'test/list.email',
|
||||
prop: 'userEmail',
|
||||
minWidth: 200,
|
||||
},
|
||||
{
|
||||
label: 'public.status',
|
||||
tdSlot: 'status',
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
label: 'public.operate',
|
||||
width: 180,
|
||||
align: 'center',
|
||||
tdSlot: 'operate', // 自定义单元格内容的插槽名称
|
||||
@ -60,145 +78,141 @@ export default defineComponent({
|
||||
// 搜索配置
|
||||
searchConfig: {
|
||||
labelWidth: '90px', // 必须带上单位
|
||||
inputWidth: '360px', // 必须带上单位
|
||||
inputWidth: '400px', // 必须带上单位
|
||||
fields: [
|
||||
{
|
||||
type: 'text',
|
||||
label: '账户名称',
|
||||
label: 'test/list.name',
|
||||
name: 'nickName',
|
||||
defaultValue: 'abc',
|
||||
},
|
||||
{
|
||||
type: 'textarea',
|
||||
label: '描述',
|
||||
name: 'description',
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
label: 'public.status',
|
||||
name: 'status',
|
||||
type: 'select',
|
||||
defaultValue: 1,
|
||||
options: [
|
||||
{
|
||||
name: '已发布',
|
||||
name: 'test/list.publish',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: '未发布',
|
||||
name: 'test/list.nopublish',
|
||||
value: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '性别',
|
||||
label: 'test/list.gender',
|
||||
name: 'sex',
|
||||
type: 'radio',
|
||||
options: [
|
||||
{
|
||||
name: '男',
|
||||
name: 'public.male',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: '女',
|
||||
name: 'public.female',
|
||||
value: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '城市',
|
||||
label: 'test/list.city',
|
||||
name: 'city',
|
||||
type: 'radio-button',
|
||||
options: [
|
||||
{
|
||||
name: '北京',
|
||||
name: 'test/list.bj',
|
||||
value: 'bj',
|
||||
},
|
||||
{
|
||||
name: '上海',
|
||||
name: 'test/list.sh',
|
||||
value: 'sh',
|
||||
},
|
||||
{
|
||||
name: '广州',
|
||||
name: 'test/list.gz',
|
||||
value: 'gz',
|
||||
},
|
||||
{
|
||||
name: '深圳',
|
||||
name: 'test/list.sz',
|
||||
value: 'sz',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '爱好',
|
||||
label: 'test/list.hobby',
|
||||
name: 'hobby',
|
||||
type: 'checkbox',
|
||||
defaultValue: ['吃饭'],
|
||||
defaultValue: ['eat'],
|
||||
options: [
|
||||
{
|
||||
name: '吃饭',
|
||||
value: '吃饭',
|
||||
name: 'test/list.eat',
|
||||
value: 'eat',
|
||||
},
|
||||
{
|
||||
name: '睡觉',
|
||||
value: '睡觉',
|
||||
name: 'test/list.sleep',
|
||||
value: 'sleep',
|
||||
},
|
||||
{
|
||||
name: '打豆豆',
|
||||
value: '打豆豆',
|
||||
name: 'test/list.bit',
|
||||
value: 'bit',
|
||||
},
|
||||
],
|
||||
// transform: (val) => val.join(","),
|
||||
},
|
||||
{
|
||||
label: '水果',
|
||||
label: 'test/list.fruit',
|
||||
name: 'fruit',
|
||||
type: 'checkbox-button',
|
||||
options: [
|
||||
{
|
||||
name: '苹果',
|
||||
value: '苹果',
|
||||
name: 'test/list.apple',
|
||||
value: 'apple',
|
||||
},
|
||||
{
|
||||
name: '香蕉',
|
||||
value: '香蕉',
|
||||
name: 'test/list.banana',
|
||||
value: 'banana',
|
||||
},
|
||||
{
|
||||
name: '橘子',
|
||||
value: '橘子',
|
||||
name: 'test/list.orange',
|
||||
value: 'orange',
|
||||
},
|
||||
{
|
||||
name: '葡萄',
|
||||
value: '葡萄',
|
||||
name: 'test/list.grape',
|
||||
value: 'grape',
|
||||
},
|
||||
],
|
||||
transform: val => val.join(','),
|
||||
},
|
||||
{
|
||||
label: '日期',
|
||||
label: 'test/list.date',
|
||||
name: 'date',
|
||||
type: 'date',
|
||||
},
|
||||
{
|
||||
label: '时间',
|
||||
label: 'test/list.time',
|
||||
name: 'datetime',
|
||||
type: 'datetime',
|
||||
defaultValue: '2020-10-10 8:00:00',
|
||||
},
|
||||
{
|
||||
label: '日期范围',
|
||||
label: 'test/list.daterange',
|
||||
name: 'daterange',
|
||||
type: 'daterange',
|
||||
trueNames: ['startDate', 'endDate'],
|
||||
style: { width: '400px' },
|
||||
},
|
||||
{
|
||||
label: '时间范围',
|
||||
label: 'test/list.timerange',
|
||||
name: 'datetimerange',
|
||||
type: 'datetimerange',
|
||||
trueNames: ['startTime', 'endTime'],
|
||||
style: { width: '360px' },
|
||||
style: { width: '400px' },
|
||||
defaultValue: ['2020-10-10 9:00:00', '2020-10-11 18:30:00'],
|
||||
},
|
||||
{
|
||||
label: '数量',
|
||||
label: 'test/list.num',
|
||||
name: 'num',
|
||||
type: 'number',
|
||||
min: 0,
|
||||
@ -207,12 +221,12 @@ export default defineComponent({
|
||||
],
|
||||
},
|
||||
// 分页配置
|
||||
paginationConfig: {
|
||||
layout: 'total, prev, pager, next, sizes', // 分页组件显示哪些功能
|
||||
pageSize: 5, // 每页条数
|
||||
pageSizes: [5, 10, 20, 50],
|
||||
style: { textAlign: 'left' },
|
||||
},
|
||||
// paginationConfig: {
|
||||
// layout: 'total, prev, pager, next, sizes', // 分页组件显示哪些功能
|
||||
// pageSize: 10, // 每页条数
|
||||
// pageSizes: [5, 10, 20, 50],
|
||||
// style: { 'justify-content': 'flex-end' },
|
||||
// },
|
||||
selectedItems: [],
|
||||
batchDelete() {
|
||||
console.log(state.selectedItems)
|
||||
@ -225,28 +239,7 @@ export default defineComponent({
|
||||
async getList(params) {
|
||||
console.log(params)
|
||||
// params是从组件接收的,包含分页和搜索字段。
|
||||
const { data } = await new Promise(rs => {
|
||||
setTimeout(() => {
|
||||
rs({
|
||||
code: 200,
|
||||
data: {
|
||||
list: [
|
||||
{
|
||||
id: 1,
|
||||
nickName: 'zhangsan',
|
||||
userEmail: 'zhangsan@xx.com',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
nickName: 'lisi',
|
||||
userEmail: 'lisi@xx.com',
|
||||
},
|
||||
],
|
||||
total: 100,
|
||||
},
|
||||
})
|
||||
}, 3000)
|
||||
})
|
||||
const { data } = await getUsers(params)
|
||||
|
||||
// 必须要返回一个对象,包含data数组和total总数
|
||||
return {
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
* @version:
|
||||
* @Date: 2021-04-20 11:06:21
|
||||
* @LastEditors: huzhushan@126.com
|
||||
* @LastEditTime: 2021-09-18 15:09:15
|
||||
* @LastEditTime: 2022-09-24 14:33:17
|
||||
* @Author: huzhushan@126.com
|
||||
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
|
||||
* @Github: https://github.com/huzhushan/vue3-element-admin
|
||||
@ -61,7 +61,9 @@ export default env => {
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
// 全局变量
|
||||
additionalData: '@import "./src/assets/style/global-variables.scss";',
|
||||
// additionalData: '@import "./src/assets/style/global-variables.scss";',
|
||||
// element-plus升级到v2需要改成以下写法
|
||||
additionalData: `@use "./src/assets/style/global-variables.scss" as *;`,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -71,6 +73,7 @@ export default env => {
|
||||
},
|
||||
},
|
||||
server: {
|
||||
port: 3001,
|
||||
open: true,
|
||||
proxy: {
|
||||
'/api': {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user