'admin-22.12.01:同步vue-next-admin-template分支v2.4.1版本内容'
This commit is contained in:
parent
57c5394d6f
commit
83ef1dc51e
41
.eslintrc.js
41
.eslintrc.js
|
|
@ -6,21 +6,38 @@ module.exports = {
|
|||
node: true,
|
||||
},
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 12,
|
||||
parser: '@typescript-eslint/parser',
|
||||
sourceType: 'module',
|
||||
},
|
||||
extends: ['plugin:vue/vue3-essential', 'plugin:vue/essential', 'eslint:recommended'],
|
||||
plugins: ['vue'],
|
||||
plugins: ['vue', '@typescript-eslint'],
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts', '*.tsx', '*.vue'],
|
||||
rules: {
|
||||
'no-undef': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
// http://eslint.cn/docs/rules/
|
||||
// https://eslint.vuejs.org/rules/
|
||||
'@type-eslint/ban-ts-ignore': 'off',
|
||||
'@type-eslint/explicit-function-return-type': 'off',
|
||||
'@type-eslint/no-explicit-any': 'off',
|
||||
'@type-eslint/no-var-requires': 'off',
|
||||
'@type-eslint/no-empty-function': 'off',
|
||||
'@type-eslint/no-use-before-define': 'off',
|
||||
'@type-eslint/ban-ts-comment': 'off',
|
||||
'@type-eslint/ban-types': 'off',
|
||||
'@type-eslint/no-non-null-assertion': 'off',
|
||||
'@type-eslint/explicit-module-boundary-types': 'off',
|
||||
// https://typescript-eslint.io/rules/no-unused-vars/
|
||||
'@typescript-eslint/ban-ts-ignore': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-redeclare': 'error',
|
||||
'@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [2],
|
||||
'vue/custom-event-name-casing': 'off',
|
||||
'vue/attributes-order': 'off',
|
||||
'vue/one-component-per-file': 'off',
|
||||
|
|
@ -54,6 +71,6 @@ module.exports = {
|
|||
'no-v-model-argument': 'off',
|
||||
'no-case-declarations': 'off',
|
||||
'no-console': 'error',
|
||||
'no-undef': 'off',
|
||||
'no-redeclare': 'off',
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
# <a href="https://gitee.com/lyt-top/vue-next-admin" target="_blank">vue-next-admin-template-js(不带国际化) 更新日志</a>
|
||||
|
||||
🎉🎉🔥 `vue-next-admin-template-js` 基于 (vue-next-admin-template v2.3.0 版本) vue3.x 、vite、Element plus 等,适配手机、平板、pc 的后台开源免费模板库(vue2.x 请切换 vue-prev-admin 分支)
|
||||
🎉🎉🔥 `vue-next-admin-template-js` 基于 (vue-next-admin-template v2.4.1 版本) vue3.x 、vite、Element plus 等,适配手机、平板、pc 的后台开源免费模板库(vue2.x 请切换 vue-prev-admin 分支)
|
||||
|
||||
## 2.4.1
|
||||
|
||||
`2022.12.01`
|
||||
|
||||
- 🎉 同步 vue-next-admin-template 基础版本(不带国际化) 分支 v2.4.1 版本内容,具体查看 master 分支 CHANGELOG.md
|
||||
|
||||
## 2.3.0
|
||||
|
||||
|
|
|
|||
16
README.md
16
README.md
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#### 🌈 介绍 基础版 js(不带国际化,基于 vue-next-admin-template V2.3.0 版,setup 语法糖)
|
||||
|
||||
基于 vue3.x + CompositionAPI + vite + element plus + vue-router-next,适配手机、平板、pc 的后台开源免费模板,希望减少工作量,帮助大家实现快速开发。
|
||||
基于 vue3.x + CompositionAPI setup 语法糖 + typescript + vite + element plus + vue-router-next + pinia 技术,适配手机、平板、pc 的后台开源免费模板,希望减少工作量,帮助大家实现快速开发。
|
||||
|
||||
#### ⛱️ 线上预览
|
||||
|
||||
|
|
@ -43,13 +43,13 @@
|
|||
|
||||
| Edge | Firefox | Chrome | Safari |
|
||||
| --------- | ------------ | ----------- | ----------- |
|
||||
| Edge ≥ 79 | Firefox ≥ 78 | Chrome ≥ 64 | Safari ≥ 12 |
|
||||
| Edge ≥ 79 | Firefox ≥ 78 | Chrome ≥ 76 | Safari ≥ 12 |
|
||||
|
||||
> 由于 Vue3 不再支持 IE11,故而 ElementPlus 也不支持 IE11 及之前版本。
|
||||
|
||||
#### ⚡ 使用说明
|
||||
|
||||
建议使用 cnpm,因为 yarn 有时会报错。<a href="http://nodejs.cn/" target="_blank">node 版本 > 12xx.xx.x</a>
|
||||
建议使用 cnpm,因为 yarn 有时会报错。<a href="http://nodejs.cn/" target="_blank">node 版本 > 14xx.xx.x</a>
|
||||
|
||||
```bash
|
||||
# 克隆项目
|
||||
|
|
@ -78,11 +78,11 @@ cnpm run build
|
|||
#### 💯 学习交流加 QQ 群
|
||||
|
||||
- 若加群了没同意(一般秒过),那就是群满了(500 人群),请换一个群试试。群会定期清理半年(6 个月)未发言的群友,资源有限,请谅解。建议勿加多群,可能会误伤!微信群由于只有 `7天有效` 就不放这里了。
|
||||
- 群号码:
|
||||
1 群:<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=RdUY97Vx0T0vZ_1OOu-X1yFNkWgDwbjC&jump_from=webapi">665452019</a>
|
||||
2 群:<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=zVfy3gNy7pNWVK3kMduDzwU369PZg2fw&jump_from=webapi">766356862</a>
|
||||
3 群:<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=02EWb5P2JkP-8iwzaDadgFdxA0HSHPpn&jump_from=webapi">795345435</a>
|
||||
4 群:<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=0gTFO04WwkeZZ6R4lju6gucbeXHK-wNd&jump_from=webapi">736626228</a>
|
||||
|
||||
- 1 群:<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=RdUY97Vx0T0vZ_1OOu-X1yFNkWgDwbjC&jump_from=webapi">665452019</a>
|
||||
- 2 群:<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=zVfy3gNy7pNWVK3kMduDzwU369PZg2fw&jump_from=webapi">766356862</a>
|
||||
- 3 群:<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=02EWb5P2JkP-8iwzaDadgFdxA0HSHPpn&jump_from=webapi">795345435</a>
|
||||
- 4 群:<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=0gTFO04WwkeZZ6R4lju6gucbeXHK-wNd&jump_from=webapi">736626228</a>
|
||||
|
||||
<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=RdUY97Vx0T0vZ_1OOu-X1yFNkWgDwbjC&jump_from=webapi">
|
||||
<img src="https://img-blog.csdnimg.cn/35e00f12a3fe4820892ec630ca72f15f.png" width="220" height="220" alt="vue-next-admin 讨论群1" title="vue-next-admin 讨论群1"/>
|
||||
|
|
|
|||
|
|
@ -4,17 +4,18 @@
|
|||
"module": "esnext",
|
||||
"lib": ["esnext", "dom", "dom.iterable", "scripthost"],
|
||||
"jsx": "preserve",
|
||||
"isolatedModules": true,
|
||||
"strict": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"moduleResolution": "node",
|
||||
"baseUrl": ".",
|
||||
"types": ["vite/client"],
|
||||
"paths": {
|
||||
"/@/*": ["src/*"]
|
||||
},
|
||||
"moduleResolution": "node",
|
||||
"strict": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
22
package.json
22
package.json
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "vue-next-admin-template-js",
|
||||
"version": "2.3.0",
|
||||
"version": "2.4.1",
|
||||
"description": "vue3 vite next admin template js setup",
|
||||
"author": "lyt_20201208",
|
||||
"license": "MIT",
|
||||
|
|
@ -11,13 +11,13 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.0.10",
|
||||
"axios": "^1.1.3",
|
||||
"axios": "^1.2.0",
|
||||
"echarts": "^5.4.0",
|
||||
"element-plus": "^2.2.21",
|
||||
"element-plus": "^2.2.25",
|
||||
"js-cookie": "^3.0.1",
|
||||
"mitt": "^3.0.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.0.23",
|
||||
"pinia": "^2.0.27",
|
||||
"qrcodejs2-fixes": "^0.0.2",
|
||||
"screenfull": "^6.0.2",
|
||||
"sortablejs": "^1.15.0",
|
||||
|
|
@ -28,13 +28,11 @@
|
|||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^3.2.0",
|
||||
"@vue/compiler-sfc": "^3.2.45",
|
||||
"dotenv": "^16.0.3",
|
||||
"eslint": "^8.27.0",
|
||||
"eslint-plugin-vue": "^9.7.0",
|
||||
"prettier": "^2.7.1",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-plugin-vue": "^9.8.0",
|
||||
"prettier": "^2.8.0",
|
||||
"sass": "^1.56.1",
|
||||
"sass-loader": "^13.2.0",
|
||||
"unplugin-auto-import": "^0.11.4",
|
||||
"unplugin-auto-import": "^0.12.0",
|
||||
"vite": "^3.2.4",
|
||||
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||
"vue-eslint-parser": "^9.1.0"
|
||||
|
|
@ -48,8 +46,8 @@
|
|||
"url": "https://gitee.com/lyt-top/vue-next-admin/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0",
|
||||
"npm": ">= 6.0.0"
|
||||
"node": ">=14.0.0",
|
||||
"npm": ">= 7.0.0"
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
|
|
|
|||
15
src/App.vue
15
src/App.vue
|
|
@ -4,6 +4,7 @@
|
|||
<LockScreen v-if="themeConfig.isLockScreen" />
|
||||
<Setings ref="setingsRef" v-show="themeConfig.lockScreenTime > 1" />
|
||||
<CloseFull v-if="!themeConfig.isLockScreen" />
|
||||
<Upgrade v-if="getVersion" />
|
||||
</el-config-provider>
|
||||
</template>
|
||||
|
||||
|
|
@ -17,15 +18,27 @@ import { Local, Session } from '/@/utils/storage';
|
|||
import setIntroduction from '/@/utils/setIconfont';
|
||||
import mittBus from './utils/mitt';
|
||||
|
||||
// 引入组件
|
||||
const LockScreen = defineAsyncComponent(() => import('/@/layout/lockScreen/index.vue'));
|
||||
const Setings = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/setings.vue'));
|
||||
const CloseFull = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/closeFull.vue'));
|
||||
const Upgrade = defineAsyncComponent(() => import('/@/layout/upgrade/index.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const setingsRef = ref();
|
||||
const route = useRoute();
|
||||
const stores = useTagsViewRoutes();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
|
||||
// 获取版本号
|
||||
const getVersion = computed(() => {
|
||||
let isVersion = false;
|
||||
if (route.path !== '/login') {
|
||||
if ((Local.get('version') && Local.get('version') !== __VERSION__) || !Local.get('version')) isVersion = true;
|
||||
}
|
||||
return isVersion;
|
||||
});
|
||||
// 获取全局组件大小
|
||||
const getGlobalComponentSize = computed(() => {
|
||||
return other.globalComponentSize();
|
||||
|
|
@ -46,7 +59,7 @@ onMounted(() => {
|
|||
});
|
||||
// 获取缓存中的布局配置
|
||||
if (Local.get('themeConfig')) {
|
||||
storesThemeConfig.setThemeConfig(Local.get('themeConfig'));
|
||||
storesThemeConfig.setThemeConfig({ themeConfig: Local.get('themeConfig') });
|
||||
document.documentElement.style.cssText = Local.get('themeConfigStyle');
|
||||
}
|
||||
// 获取缓存中的全屏配置
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
import request from '/@/utils/request';
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
* @param params 要传的参数值
|
||||
* @returns 返回接口数据
|
||||
* 登录api接口集合
|
||||
* @method signIn 用户登录
|
||||
* @method signOut 用户退出登录
|
||||
|
|
@ -11,18 +8,10 @@ import request from '/@/utils/request';
|
|||
export function useLoginApi() {
|
||||
return {
|
||||
signIn: (params) => {
|
||||
return request({
|
||||
url: '/user/signIn',
|
||||
method: 'post',
|
||||
data: params,
|
||||
});
|
||||
return request.post('/user/signIn', params);
|
||||
},
|
||||
signOut: (params) => {
|
||||
return request({
|
||||
url: '/user/signOut',
|
||||
method: 'post',
|
||||
data: params,
|
||||
});
|
||||
return request.post('/user/signOut', params);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,20 @@
|
|||
import request from '/@/utils/request';
|
||||
|
||||
/**
|
||||
* 以下为模拟接口地址,gitee 的不通,就换自己的真实接口地址
|
||||
*
|
||||
* 后端控制菜单模拟json,路径在 https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu
|
||||
* 后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
|
||||
* @method getMenuAdmin 获取后端动态路由菜单(admin)
|
||||
* @method getMenuTest 获取后端动态路由菜单(test)
|
||||
* @method getAdminMenu 获取后端动态路由菜单(admin)
|
||||
* @method getTestMenu 获取后端动态路由菜单(test)
|
||||
*/
|
||||
export function useMenuApi() {
|
||||
return {
|
||||
getMenuAdmin: (params) => {
|
||||
return request({
|
||||
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/adminMenu.json',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
getAdminMenu: (params) => {
|
||||
return request.get('/gitee/lyt-top/vue-next-admin-images/raw/master/menu/adminMenu.json', params);
|
||||
},
|
||||
getMenuTest: (params) => {
|
||||
return request({
|
||||
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/testMenu.json',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
getTestMenu: (params) => {
|
||||
return request.get('/gitee/lyt-top/vue-next-admin-images/raw/master/menu/testMenu.json', params);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<div class="icon-selector w100 h100">
|
||||
<el-popover
|
||||
placement="bottom"
|
||||
:width="fontIconWidth"
|
||||
:width="state.fontIconWidth"
|
||||
trigger="click"
|
||||
transition="el-zoom-in-top"
|
||||
popper-class="icon-selector-popper"
|
||||
|
|
@ -10,8 +10,8 @@
|
|||
>
|
||||
<template #reference>
|
||||
<el-input
|
||||
v-model="fontIconSearch"
|
||||
:placeholder="fontIconPlaceholder"
|
||||
v-model="state.fontIconSearch"
|
||||
:placeholder="state.fontIconPlaceholder"
|
||||
:clearable="clearable"
|
||||
:disabled="disabled"
|
||||
:size="size"
|
||||
|
|
@ -22,11 +22,11 @@
|
|||
>
|
||||
<template #prepend>
|
||||
<SvgIcon
|
||||
:name="fontIconPrefix === '' ? prepend : fontIconPrefix"
|
||||
:name="state.fontIconPrefix === '' ? prepend : state.fontIconPrefix"
|
||||
class="font14"
|
||||
v-if="fontIconPrefix === '' ? prepend?.indexOf('ele-') > -1 : fontIconPrefix?.indexOf('ele-') > -1"
|
||||
v-if="state.fontIconPrefix === '' ? prepend?.indexOf('ele-') > -1 : state.fontIconPrefix?.indexOf('ele-') > -1"
|
||||
/>
|
||||
<i v-else :class="fontIconPrefix === '' ? prepend : fontIconPrefix" class="font14"></i>
|
||||
<i v-else :class="state.fontIconPrefix === '' ? prepend : state.fontIconPrefix" class="font14"></i>
|
||||
</template>
|
||||
</el-input>
|
||||
</template>
|
||||
|
|
@ -35,16 +35,22 @@
|
|||
<div class="icon-selector-warp-title flex">
|
||||
<div class="flex-auto">{{ title }}</div>
|
||||
<div class="icon-selector-warp-title-tab" v-if="type === 'all'">
|
||||
<span :class="{ 'span-active': fontIconType === 'ali' }" @click="onIconChange('ali')" class="ml10" title="iconfont 图标">ali</span>
|
||||
<span :class="{ 'span-active': fontIconType === 'ele' }" @click="onIconChange('ele')" class="ml10" title="elementPlus 图标">ele</span>
|
||||
<span :class="{ 'span-active': fontIconType === 'awe' }" @click="onIconChange('awe')" class="ml10" title="fontawesome 图标">awe</span>
|
||||
<span :class="{ 'span-active': state.fontIconType === 'ali' }" @click="onIconChange('ali')" class="ml10" title="iconfont 图标">
|
||||
ali
|
||||
</span>
|
||||
<span :class="{ 'span-active': state.fontIconType === 'ele' }" @click="onIconChange('ele')" class="ml10" title="elementPlus 图标">
|
||||
ele
|
||||
</span>
|
||||
<span :class="{ 'span-active': state.fontIconType === 'awe' }" @click="onIconChange('awe')" class="ml10" title="fontawesome 图标">
|
||||
awe
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="icon-selector-warp-row">
|
||||
<el-scrollbar ref="selectorScrollbarRef">
|
||||
<el-row :gutter="10" v-if="fontIconSheetsFilterList.length > 0">
|
||||
<el-col :xs="6" :sm="4" :md="4" :lg="4" :xl="4" @click="onColClick(v)" v-for="(v, k) in fontIconSheetsFilterList" :key="k">
|
||||
<div class="icon-selector-warp-item" :class="{ 'icon-selector-active': fontIconPrefix === v }">
|
||||
<div class="icon-selector-warp-item" :class="{ 'icon-selector-active': state.fontIconPrefix === v }">
|
||||
<div class="flex-margin">
|
||||
<div class="icon-selector-warp-item-value">
|
||||
<SvgIcon :name="v" />
|
||||
|
|
@ -62,37 +68,35 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, toRefs, reactive, onMounted, nextTick, computed, watch, defineComponent } from 'vue';
|
||||
<script setup name="iconSelector">
|
||||
import initIconfont from '/@/utils/getStyleSheets';
|
||||
import '/@/theme/iconSelector.scss';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'iconSelector',
|
||||
emits: ['update:modelValue', 'get', 'clear'],
|
||||
props: {
|
||||
// 定义父组件传过来的值
|
||||
const props = defineProps({
|
||||
// 输入框前置内容
|
||||
prepend: {
|
||||
type: String,
|
||||
type,
|
||||
default: () => 'ele-Pointer',
|
||||
},
|
||||
// 输入框占位文本
|
||||
placeholder: {
|
||||
type: String,
|
||||
type,
|
||||
default: () => '请输入内容搜索图标或者选择图标',
|
||||
},
|
||||
// 输入框占位文本
|
||||
size: {
|
||||
type: String,
|
||||
type,
|
||||
default: () => 'default',
|
||||
},
|
||||
// 弹窗标题
|
||||
title: {
|
||||
type: String,
|
||||
type,
|
||||
default: () => '请选择图标',
|
||||
},
|
||||
// icon 图标类型
|
||||
type: {
|
||||
type: String,
|
||||
type,
|
||||
default: () => 'ele',
|
||||
},
|
||||
// 禁用
|
||||
|
|
@ -107,15 +111,19 @@ export default defineComponent({
|
|||
},
|
||||
// 自定义空状态描述文字
|
||||
emptyDescription: {
|
||||
type: String,
|
||||
type,
|
||||
default: () => '无相关图标',
|
||||
},
|
||||
// 双向绑定值,默认为 modelValue,
|
||||
// 参考:https://v3.cn.vuejs.org/guide/migration/v-model.html#%E8%BF%81%E7%A7%BB%E7%AD%96%E7%95%A5
|
||||
// 参考:https://v3.cn.vuejs.org/guide/component-custom-events.html#%E5%A4%9A%E4%B8%AA-v-model-%E7%BB%91%E5%AE%9A
|
||||
modelValue: String,
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
modelValue,
|
||||
});
|
||||
|
||||
// 定义子组件向父组件传值/事件
|
||||
const emit = defineEmits(['update:modelValue', 'get', 'clear']);
|
||||
|
||||
// 定义变量内容
|
||||
const inputWidthRef = ref();
|
||||
const selectorScrollbarRef = ref();
|
||||
const state = reactive({
|
||||
|
|
@ -128,6 +136,7 @@ export default defineComponent({
|
|||
fontIconType: 'ali',
|
||||
fontIconShow: true,
|
||||
});
|
||||
|
||||
// 处理 input 获取焦点时,modelValue 有值时,改变 input 的 placeholder 值
|
||||
const onIconFocus = () => {
|
||||
if (!props.modelValue) return false;
|
||||
|
|
@ -149,9 +158,9 @@ export default defineComponent({
|
|||
};
|
||||
// 处理 icon type 类型为 all 时,类型 ali、ele、awe 回显问题
|
||||
const initFontIconTypeEcho = () => {
|
||||
if (props.modelValue?.indexOf('iconfont') > -1) onIconChange('ali');
|
||||
else if (props.modelValue?.indexOf('ele-') > -1) onIconChange('ele');
|
||||
else if (props.modelValue?.indexOf('fa') > -1) onIconChange('awe');
|
||||
if (props.modelValue.indexOf('iconfont') > -1) onIconChange('ali');
|
||||
else if (props.modelValue.indexOf('ele-') > -1) onIconChange('ele');
|
||||
else if (props.modelValue.indexOf('fa') > -1) onIconChange('awe');
|
||||
else onIconChange('ali');
|
||||
};
|
||||
// 图标搜索及图标数据显示
|
||||
|
|
@ -234,18 +243,4 @@ export default defineComponent({
|
|||
initModeValueEcho();
|
||||
}
|
||||
);
|
||||
return {
|
||||
inputWidthRef,
|
||||
selectorScrollbarRef,
|
||||
fontIconSheetsFilterList,
|
||||
onColClick,
|
||||
onIconChange,
|
||||
onClearFontIcon,
|
||||
onIconFocus,
|
||||
onIconBlur,
|
||||
onPopoverShow,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -8,12 +8,9 @@
|
|||
<i v-else :class="getIconName" :style="setIconSvgStyle" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { computed, defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'svgIcon',
|
||||
props: {
|
||||
<script setup name="svgIcon">
|
||||
// 定义父组件传过来的值
|
||||
const props = defineProps({
|
||||
// svg 图标组件名字
|
||||
name: {
|
||||
type: String,
|
||||
|
|
@ -27,10 +24,11 @@ export default defineComponent({
|
|||
color: {
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
});
|
||||
|
||||
// 在线链接、本地引入地址前缀
|
||||
const linesString = ['https', 'http', '/src', '/assets', import.meta.env.VITE_PUBLIC_PATH];
|
||||
// https://gitee.com/lyt-top/vue-next-admin/issues/I62OVL
|
||||
const linesString = ['https', 'http', '/src', '/assets', 'data:image', import.meta.env.VITE_PUBLIC_PATH];
|
||||
|
||||
// 获取 icon 图标名称
|
||||
const getIconName = computed(() => {
|
||||
|
|
@ -60,14 +58,4 @@ export default defineComponent({
|
|||
compatibles.forEach((j) => filterStyle.push(`${j}-filter: drop-shadow(${props.color} 30px 0);`));
|
||||
return `width: ${props.size}px;height: ${props.size}px;position: relative;left: -${props.size}px;${filterStyle.join('')}`;
|
||||
});
|
||||
return {
|
||||
getIconName,
|
||||
isShowIconSvg,
|
||||
isShowIconImg,
|
||||
setIconSvgStyle,
|
||||
setIconImgOutStyle,
|
||||
setIconSvgInsStyle,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { authDirective } from '/@/utils/authDirective';
|
||||
import { wavesDirective, dragDirective } from '/@/utils/customDirective';
|
||||
import { authDirective } from './authDirective';
|
||||
import { wavesDirective, dragDirective } from '/@/directive/customDirective';
|
||||
|
||||
/**
|
||||
* 导出指令方法:v-xxx
|
||||
|
|
@ -17,9 +17,11 @@ import { useThemeConfig } from '/@/stores/themeConfig';
|
|||
import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
|
||||
import mittBus from '/@/utils/mitt';
|
||||
|
||||
// 引入组件
|
||||
const Logo = defineAsyncComponent(() => import('/@/layout/logo/index.vue'));
|
||||
const Vertical = defineAsyncComponent(() => import('/@/layout/navMenu/vertical.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const layoutAsideScrollbarRef = ref();
|
||||
const stores = useRoutesList();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
|
|
@ -29,8 +31,9 @@ const { themeConfig } = storeToRefs(storesThemeConfig);
|
|||
const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes);
|
||||
const state = reactive({
|
||||
menuList: [],
|
||||
clientWidth: '',
|
||||
clientWidth: 0,
|
||||
});
|
||||
|
||||
// 设置菜单展开/收起时的宽度
|
||||
const setCollapseStyle = computed(() => {
|
||||
const { layout, isCollapse, menuBar } = themeConfig.value;
|
||||
|
|
@ -63,19 +66,22 @@ const setCollapseStyle = computed(() => {
|
|||
}
|
||||
}
|
||||
});
|
||||
// 关闭移动端蒙版
|
||||
const closeLayoutAsideMobileMode = () => {
|
||||
const el = document.querySelector('.layout-aside-mobile-mode');
|
||||
el && el.parentNode?.removeChild(el);
|
||||
const clientWidth = document.body.clientWidth;
|
||||
if (clientWidth < 1000) themeConfig.value.isCollapse = false;
|
||||
document.body.setAttribute('class', '');
|
||||
};
|
||||
// 设置显示/隐藏 logo
|
||||
const setShowLogo = computed(() => {
|
||||
let { layout, isShowLogo } = themeConfig.value;
|
||||
return (isShowLogo && layout === 'defaults') || (isShowLogo && layout === 'columns');
|
||||
});
|
||||
// 关闭移动端蒙版
|
||||
const closeLayoutAsideMobileMode = () => {
|
||||
const el = document.querySelector('.layout-aside-mobile-mode');
|
||||
el?.setAttribute('style', 'animation: error-img-two 0.3s');
|
||||
setTimeout(() => {
|
||||
el?.parentNode?.removeChild(el);
|
||||
}, 300);
|
||||
const clientWidth = document.body.clientWidth;
|
||||
if (clientWidth < 1000) themeConfig.value.isCollapse = false;
|
||||
document.body.setAttribute('class', '');
|
||||
};
|
||||
// 设置/过滤路由(非静态路由/是否显示在菜单中)
|
||||
const setFilterRoutes = () => {
|
||||
if (themeConfig.value.layout === 'columns') return false;
|
||||
|
|
@ -84,7 +90,7 @@ const setFilterRoutes = () => {
|
|||
// 路由过滤递归函数
|
||||
const filterRoutesFun = (arr) => {
|
||||
return arr
|
||||
.filter((item) => !item.meta.isHide)
|
||||
.filter((item) => !item.meta?.isHide)
|
||||
.map((item) => {
|
||||
item = Object.assign({}, item);
|
||||
if (item.children) item.children = filterRoutesFun(item.children);
|
||||
|
|
@ -102,24 +108,6 @@ const onAsideEnterLeave = (bool) => {
|
|||
if (!bool) mittBus.emit('restoreDefault');
|
||||
stores.setColumnsMenuHover(bool);
|
||||
};
|
||||
// 监听 themeConfig 配置文件的变化,更新菜单 el-scrollbar 的高度
|
||||
watch(themeConfig.value, (val) => {
|
||||
if (val.isShowLogoChange !== val.isShowLogo) {
|
||||
if (layoutAsideScrollbarRef.value) layoutAsideScrollbarRef.value.update();
|
||||
}
|
||||
});
|
||||
// 监听vuex值的变化,动态赋值给菜单中
|
||||
watch(
|
||||
pinia.state,
|
||||
(val) => {
|
||||
let { layout, isClassicSplitMenu } = val.themeConfig.themeConfig;
|
||||
if (layout === 'classic' && isClassicSplitMenu) return false;
|
||||
setFilterRoutes();
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
// 页面加载前
|
||||
onBeforeMount(() => {
|
||||
initMenuFixed(document.body.clientWidth);
|
||||
|
|
@ -144,4 +132,22 @@ onBeforeMount(() => {
|
|||
closeLayoutAsideMobileMode();
|
||||
});
|
||||
});
|
||||
// 监听 themeConfig 配置文件的变化,更新菜单 el-scrollbar 的高度
|
||||
watch(themeConfig.value, (val) => {
|
||||
if (val.isShowLogoChange !== val.isShowLogo) {
|
||||
if (layoutAsideScrollbarRef.value) layoutAsideScrollbarRef.value.update();
|
||||
}
|
||||
});
|
||||
// 监听 pinia 值的变化,动态赋值给菜单中
|
||||
watch(
|
||||
pinia.state,
|
||||
(val) => {
|
||||
let { layout, isClassicSplitMenu } = val.themeConfig.themeConfig;
|
||||
if (layout === 'classic' && isClassicSplitMenu) return false;
|
||||
setFilterRoutes();
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ import { useRoutesList } from '/@/stores/routesList';
|
|||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import mittBus from '/@/utils/mitt';
|
||||
|
||||
// 定义变量内容
|
||||
const columnsAsideOffsetTopRefs = ref([]);
|
||||
const columnsAsideActiveRef = ref();
|
||||
const stores = useRoutesList();
|
||||
|
|
@ -69,6 +70,7 @@ const state = reactive({
|
|||
difference: 0,
|
||||
routeSplit: [],
|
||||
});
|
||||
|
||||
// 设置菜单高亮位置移动
|
||||
const setColumnsAsideMove = (k) => {
|
||||
state.liIndex = k;
|
||||
|
|
@ -111,17 +113,17 @@ const setFilterRoutes = () => {
|
|||
state.columnsAsideList = filterRoutesFun(routesList.value);
|
||||
const resData = setSendChildren(route.path);
|
||||
if (Object.keys(resData).length <= 0) return false;
|
||||
onColumnsAsideDown(resData.item[0].k);
|
||||
onColumnsAsideDown(resData.item?.k);
|
||||
mittBus.emit('setSendColumnsChildren', resData);
|
||||
};
|
||||
// 传送当前子级数据到菜单中
|
||||
const setSendChildren = (path) => {
|
||||
const currentPathSplit = path.split('/');
|
||||
let currentData = {};
|
||||
let currentData = { children: [] };
|
||||
state.columnsAsideList.map((v, k) => {
|
||||
if (v.path === `/${currentPathSplit[1]}`) {
|
||||
v['k'] = k;
|
||||
currentData['item'] = [{ ...v }];
|
||||
currentData['item'] = { ...v };
|
||||
currentData['children'] = [{ ...v }];
|
||||
if (v.children) currentData['children'] = v.children;
|
||||
}
|
||||
|
|
@ -131,7 +133,7 @@ const setSendChildren = (path) => {
|
|||
// 路由过滤递归函数
|
||||
const filterRoutesFun = (arr) => {
|
||||
return arr
|
||||
.filter((item) => !item.meta.isHide)
|
||||
.filter((item) => !item.meta?.isHide)
|
||||
.map((item) => {
|
||||
item = Object.assign({}, item);
|
||||
if (item.children) item.children = filterRoutesFun(item.children);
|
||||
|
|
@ -150,24 +152,6 @@ const setColumnsMenuHighlight = (path) => {
|
|||
onColumnsAsideDown(currentSplitRoute.k);
|
||||
}, 0);
|
||||
};
|
||||
// 监听布局配置信息的变化,动态增加菜单高亮位置移动像素
|
||||
watch(
|
||||
pinia.state,
|
||||
(val) => {
|
||||
val.themeConfig.themeConfig.columnsAsideStyle === 'columnsRound' ? (state.difference = 3) : (state.difference = 0);
|
||||
if (!val.routesList.isColumnsMenuHover && !val.routesList.isColumnsNavHover) {
|
||||
state.liHoverIndex = null;
|
||||
mittBus.emit('setSendColumnsChildren', setSendChildren(route.path));
|
||||
} else {
|
||||
state.liHoverIndex = state.liOldIndex;
|
||||
if (!state.liOldPath) return false;
|
||||
mittBus.emit('setSendColumnsChildren', setSendChildren(state.liOldPath));
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
setFilterRoutes();
|
||||
|
|
@ -186,6 +170,24 @@ onBeforeRouteUpdate((to) => {
|
|||
setColumnsMenuHighlight(to.path);
|
||||
mittBus.emit('setSendColumnsChildren', setSendChildren(to.path));
|
||||
});
|
||||
// 监听布局配置信息的变化,动态增加菜单高亮位置移动像素
|
||||
watch(
|
||||
pinia.state,
|
||||
(val) => {
|
||||
val.themeConfig.themeConfig.columnsAsideStyle === 'columnsRound' ? (state.difference = 3) : (state.difference = 0);
|
||||
if (!val.routesList.isColumnsMenuHover && !val.routesList.isColumnsNavHover) {
|
||||
state.liHoverIndex = null;
|
||||
mittBus.emit('setSendColumnsChildren', setSendChildren(route.path));
|
||||
} else {
|
||||
state.liHoverIndex = state.liOldIndex;
|
||||
if (!state.liOldPath) return false;
|
||||
mittBus.emit('setSendColumnsChildren', setSendChildren(state.liOldPath));
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@
|
|||
import { storeToRefs } from 'pinia';
|
||||
import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
|
||||
|
||||
// 引入组件
|
||||
const NavBarsIndex = defineAsyncComponent(() => import('/@/layout/navBars/index.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const storesTagsViewRoutes = useTagsViewRoutes();
|
||||
const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes);
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
<template>
|
||||
<el-main class="layout-main" :style="isFixedHeader ? `height: calc(100% - ${setMainHeight})` : `minHeight: calc(100% - ${setMainHeight})`">
|
||||
<el-scrollbar ref="layoutMainScrollbarRef" class="layout-main-scroll" wrap-class="layout-main-scroll" view-class="layout-main-scroll">
|
||||
<el-scrollbar
|
||||
ref="layoutMainScrollbarRef"
|
||||
class="layout-main-scroll layout-backtop-header-fixed"
|
||||
wrap-class="layout-main-scroll"
|
||||
view-class="layout-main-scroll"
|
||||
>
|
||||
<LayoutParentView />
|
||||
<LayoutFooter v-if="isFooter" />
|
||||
</el-scrollbar>
|
||||
<el-backtop target=".layout-backtop .el-scrollbar__wrap" />
|
||||
<el-backtop :target="setBacktopClass" />
|
||||
</el-main>
|
||||
</template>
|
||||
|
||||
|
|
@ -14,15 +19,18 @@ import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
|
|||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import { NextLoading } from '/@/utils/loading';
|
||||
|
||||
// 引入组件
|
||||
const LayoutParentView = defineAsyncComponent(() => import('/@/layout/routerView/parent.vue'));
|
||||
const LayoutFooter = defineAsyncComponent(() => import('/@/layout/footer/index.vue'));
|
||||
|
||||
const layoutMainScrollbarRef = ref('');
|
||||
// 定义变量内容
|
||||
const layoutMainScrollbarRef = ref();
|
||||
const route = useRoute();
|
||||
const storesTagsViewRoutes = useTagsViewRoutes();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes);
|
||||
|
||||
// 设置 footer 显示/隐藏
|
||||
const isFooter = computed(() => {
|
||||
return themeConfig.value.isFooter && !route.meta.isIframe;
|
||||
|
|
@ -31,6 +39,11 @@ const isFooter = computed(() => {
|
|||
const isFixedHeader = computed(() => {
|
||||
return themeConfig.value.isFixedHeader;
|
||||
});
|
||||
// 设置 Backtop 回到顶部
|
||||
const setBacktopClass = computed(() => {
|
||||
if (themeConfig.value.isFixedHeader) return `.layout-backtop-header-fixed .el-scrollbar__wrap`;
|
||||
else return `.layout-backtop .el-scrollbar__wrap`;
|
||||
});
|
||||
// 设置主内容区的高度
|
||||
const setMainHeight = computed(() => {
|
||||
if (isTagsViewCurrenFull.value) return '0px';
|
||||
|
|
@ -38,9 +51,9 @@ const setMainHeight = computed(() => {
|
|||
if (isTagsview && layout !== 'classic') return '85px';
|
||||
else return '51px';
|
||||
});
|
||||
// 页面加载时
|
||||
onMounted(async () => {
|
||||
NextLoading.done();
|
||||
// 页面加载前
|
||||
onMounted(() => {
|
||||
NextLoading.done(600);
|
||||
});
|
||||
|
||||
// 暴露变量
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@
|
|||
<div class="layout-footer pb15">
|
||||
<div class="layout-footer-warp">
|
||||
<div>vue-next-admin,Made by lyt with ❤️</div>
|
||||
<div class="mt5">版权所有:深圳市xxx软件科技有限公司</div>
|
||||
<div class="mt5">深圳市 xxx 公司版权所有</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="layoutFooter"></script>
|
||||
<script setup name="layoutFooter">
|
||||
// 此处需有内容(注释也得),否则缓存将失败
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.layout-footer {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<component :is="layouts[themeConfig.layout]"></component>
|
||||
<component :is="layouts[themeConfig.layout]" />
|
||||
</template>
|
||||
|
||||
<script setup name="layout">
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import { Local } from '/@/utils/storage';
|
||||
import mittBus from '/@/utils/mitt';
|
||||
|
||||
// 引入组件
|
||||
const layouts = {
|
||||
defaults: defineAsyncComponent(() => import('/@/layout/main/defaults.vue')),
|
||||
classic: defineAsyncComponent(() => import('/@/layout/main/classic.vue')),
|
||||
|
|
@ -16,8 +16,10 @@ const layouts = {
|
|||
columns: defineAsyncComponent(() => import('/@/layout/main/columns.vue')),
|
||||
};
|
||||
|
||||
// 定义变量内容
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
|
||||
// 窗口大小改变时(适配移动端)
|
||||
const onLayoutResize = () => {
|
||||
if (!Local.get('oldLayout')) Local.set('oldLayout', themeConfig.value.layout);
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
<template>
|
||||
<div v-show="isShowLockScreen">
|
||||
<div v-show="state.isShowLockScreen">
|
||||
<div class="layout-lock-screen-mask"></div>
|
||||
<div class="layout-lock-screen-img" :class="{ 'layout-lock-screen-filter': state.isShowLoockLogin }"></div>
|
||||
<div class="layout-lock-screen">
|
||||
<div
|
||||
class="layout-lock-screen-date"
|
||||
ref="layoutLockScreenDateRef"
|
||||
@mousedown="onDown"
|
||||
@mousemove="onMove"
|
||||
@mousedown="onDownPc"
|
||||
@mousemove="onMovePc"
|
||||
@mouseup="onEnd"
|
||||
@touchstart.stop="onDown"
|
||||
@touchmove.stop="onMove"
|
||||
@touchstart.stop="onDownApp"
|
||||
@touchmove.stop="onMoveApp"
|
||||
@touchend.stop="onEnd"
|
||||
>
|
||||
<div class="layout-lock-screen-date-box">
|
||||
|
|
@ -60,14 +60,16 @@
|
|||
</template>
|
||||
|
||||
<script setup name="layoutLockScreen">
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import { formatDate } from '/@/utils/formatTime';
|
||||
import { Local } from '/@/utils/storage';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
|
||||
// 定义变量内容
|
||||
const layoutLockScreenDateRef = ref();
|
||||
const layoutLockScreenInputRef = ref();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
const layoutLockScreenInputRef = ref();
|
||||
const state = reactive({
|
||||
transparency: 1,
|
||||
downClientY: 0,
|
||||
|
|
@ -85,21 +87,32 @@ const state = reactive({
|
|||
isShowLockScreenIntervalTime: 0,
|
||||
lockScreenPassword: '',
|
||||
});
|
||||
// 鼠标按下
|
||||
const onDown = (down) => {
|
||||
|
||||
// 鼠标按下 pc
|
||||
const onDownPc = (down) => {
|
||||
state.isFlags = true;
|
||||
state.downClientY = down.touches ? down.touches[0].clientY : down.clientY;
|
||||
state.downClientY = down.clientY;
|
||||
};
|
||||
// 鼠标移动
|
||||
const onMove = (move) => {
|
||||
// 鼠标按下 app
|
||||
const onDownApp = (down) => {
|
||||
state.isFlags = true;
|
||||
state.downClientY = down.touches[0].clientY;
|
||||
};
|
||||
// 鼠标移动 pc
|
||||
const onMovePc = (move) => {
|
||||
state.moveDifference = move.clientY - state.downClientY;
|
||||
onMove();
|
||||
};
|
||||
// 鼠标移动 app
|
||||
const onMoveApp = (move) => {
|
||||
state.moveDifference = move.touches[0].clientY - state.downClientY;
|
||||
onMove();
|
||||
};
|
||||
// 鼠标移动事件
|
||||
const onMove = () => {
|
||||
if (state.isFlags) {
|
||||
const el = state.querySelectorEl;
|
||||
const opacitys = (state.transparency -= 1 / 200);
|
||||
if (move.touches) {
|
||||
state.moveDifference = move.touches[0].clientY - state.downClientY;
|
||||
} else {
|
||||
state.moveDifference = move.clientY - state.downClientY;
|
||||
}
|
||||
if (state.moveDifference >= 0) return false;
|
||||
el.setAttribute('style', `top:${state.moveDifference}px;cursor:pointer;opacity:${opacitys};`);
|
||||
if (state.moveDifference < -400) {
|
||||
|
|
|
|||
|
|
@ -9,12 +9,14 @@
|
|||
</template>
|
||||
|
||||
<script setup name="layoutLogo">
|
||||
import logoMini from '/@/assets/logo-mini.svg';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import logoMini from '/@/assets/logo-mini.svg';
|
||||
|
||||
// 定义变量内容
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
|
||||
// 设置 logo 的显示。classic 经典布局默认显示 logo
|
||||
const setShowLogo = computed(() => {
|
||||
let { isCollapse, layout } = themeConfig.value;
|
||||
|
|
|
|||
|
|
@ -15,32 +15,40 @@
|
|||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
|
||||
// 引入组件
|
||||
const LayoutAside = defineAsyncComponent(() => import('/@/layout/component/aside.vue'));
|
||||
const LayoutHeader = defineAsyncComponent(() => import('/@/layout/component/header.vue'));
|
||||
const LayoutMain = defineAsyncComponent(() => import('/@/layout/component/main.vue'));
|
||||
const LayoutTagsView = defineAsyncComponent(() => import('/@/layout/navBars/tagsView/tagsView.vue'));
|
||||
|
||||
const layoutMainRef = ref('');
|
||||
// 定义变量内容
|
||||
const layoutMainRef = ref();
|
||||
const route = useRoute();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
|
||||
// 判断是否显示 tasgview
|
||||
const isTagsview = computed(() => {
|
||||
return themeConfig.value.isTagsview;
|
||||
});
|
||||
// 重置滚动条高度,更新子级 scrollbar
|
||||
const updateScrollbar = () => {
|
||||
layoutMainRef.value.layoutMainScrollbarRef.update();
|
||||
layoutMainRef.value?.layoutMainScrollbarRef.update();
|
||||
};
|
||||
// 重置滚动条高度,由于组件是异步引入的
|
||||
const initScrollBarHeight = () => {
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
updateScrollbar();
|
||||
layoutMainRef.value.layoutMainScrollbarRef.wrap$.scrollTop = 0;
|
||||
// '!' not null 断言操作符,不执行运行时检查
|
||||
layoutMainRef.value.layoutMainScrollbarRef.wrapRef.scrollTop = 0;
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initScrollBarHeight();
|
||||
});
|
||||
// 监听路由的变化,切换界面时,滚动条置顶
|
||||
watch(
|
||||
() => route.path,
|
||||
|
|
@ -58,8 +66,4 @@ watch(
|
|||
deep: true,
|
||||
}
|
||||
);
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initScrollBarHeight();
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -15,16 +15,19 @@
|
|||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
|
||||
// 引入组件
|
||||
const LayoutAside = defineAsyncComponent(() => import('/@/layout/component/aside.vue'));
|
||||
const LayoutHeader = defineAsyncComponent(() => import('/@/layout/component/header.vue'));
|
||||
const LayoutMain = defineAsyncComponent(() => import('/@/layout/component/main.vue'));
|
||||
const ColumnsAside = defineAsyncComponent(() => import('/@/layout/component/columnsAside.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const layoutScrollbarRef = ref('');
|
||||
const layoutMainRef = ref('');
|
||||
const layoutMainRef = ref();
|
||||
const route = useRoute();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
|
||||
// 重置滚动条高度
|
||||
const updateScrollbar = () => {
|
||||
// 更新父级 scrollbar
|
||||
|
|
@ -37,11 +40,15 @@ const initScrollBarHeight = () => {
|
|||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
updateScrollbar();
|
||||
layoutScrollbarRef.value.wrap$.scrollTop = 0;
|
||||
layoutMainRef.value.layoutMainScrollbarRef.wrap$.scrollTop = 0;
|
||||
layoutScrollbarRef.value.wrapRef.scrollTop = 0;
|
||||
layoutMainRef.value.layoutMainScrollbarRef.wrapRef.scrollTop = 0;
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initScrollBarHeight();
|
||||
});
|
||||
// 监听路由的变化,切换界面时,滚动条置顶
|
||||
watch(
|
||||
() => route.path,
|
||||
|
|
@ -59,8 +66,4 @@ watch(
|
|||
deep: true,
|
||||
}
|
||||
);
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initScrollBarHeight();
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -15,15 +15,18 @@ import { storeToRefs } from 'pinia';
|
|||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import { NextLoading } from '/@/utils/loading';
|
||||
|
||||
// 引入组件
|
||||
const LayoutAside = defineAsyncComponent(() => import('/@/layout/component/aside.vue'));
|
||||
const LayoutHeader = defineAsyncComponent(() => import('/@/layout/component/header.vue'));
|
||||
const LayoutMain = defineAsyncComponent(() => import('/@/layout/component/main.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const layoutScrollbarRef = ref('');
|
||||
const layoutMainRef = ref('');
|
||||
const layoutMainRef = ref();
|
||||
const route = useRoute();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
|
||||
// 重置滚动条高度
|
||||
const updateScrollbar = () => {
|
||||
// 更新父级 scrollbar
|
||||
|
|
@ -36,11 +39,16 @@ const initScrollBarHeight = () => {
|
|||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
updateScrollbar();
|
||||
layoutScrollbarRef.value.wrap$.scrollTop = 0;
|
||||
layoutMainRef.value.layoutMainScrollbarRef.wrap$.scrollTop = 0;
|
||||
layoutScrollbarRef.value.wrapRef.scrollTop = 0;
|
||||
layoutMainRef.value.layoutMainScrollbarRef.wrapRef.scrollTop = 0;
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initScrollBarHeight();
|
||||
NextLoading.done(600);
|
||||
});
|
||||
// 监听路由的变化,切换界面时,滚动条置顶
|
||||
watch(
|
||||
() => route.path,
|
||||
|
|
@ -58,9 +66,4 @@ watch(
|
|||
deep: true,
|
||||
}
|
||||
);
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initScrollBarHeight();
|
||||
NextLoading.done(600);
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -9,13 +9,16 @@
|
|||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
|
||||
// 引入组件
|
||||
const LayoutHeader = defineAsyncComponent(() => import('/@/layout/component/header.vue'));
|
||||
const LayoutMain = defineAsyncComponent(() => import('/@/layout/component/main.vue'));
|
||||
|
||||
const layoutMainRef = ref('');
|
||||
// 定义变量内容
|
||||
const layoutMainRef = ref();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
const route = useRoute();
|
||||
|
||||
// 重置滚动条高度,更新子级 scrollbar
|
||||
const updateScrollbar = () => {
|
||||
layoutMainRef.value.layoutMainScrollbarRef.update();
|
||||
|
|
@ -25,10 +28,14 @@ const initScrollBarHeight = () => {
|
|||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
updateScrollbar();
|
||||
layoutMainRef.value.layoutMainScrollbarRef.wrap$.scrollTop = 0;
|
||||
layoutMainRef.value.layoutMainScrollbarRef.wrapRef.scrollTop = 0;
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initScrollBarHeight();
|
||||
});
|
||||
// 监听路由的变化,切换界面时,滚动条置顶
|
||||
watch(
|
||||
() => route.path,
|
||||
|
|
@ -46,8 +53,4 @@ watch(
|
|||
deep: true,
|
||||
}
|
||||
);
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initScrollBarHeight();
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
@click="onThemeConfigChange"
|
||||
/>
|
||||
<el-breadcrumb class="layout-navbars-breadcrumb-hide">
|
||||
<transition-group name="breadcrumb" mode="out-in">
|
||||
<transition-group name="breadcrumb">
|
||||
<el-breadcrumb-item v-for="(v, k) in state.breadcrumbList" :key="!v.meta.tagsViewName ? v.meta.title : v.meta.tagsViewName">
|
||||
<span v-if="k === state.breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span">
|
||||
<SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />
|
||||
|
|
@ -30,8 +30,8 @@ import other from '/@/utils/other';
|
|||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import { useRoutesList } from '/@/stores/routesList';
|
||||
Local;
|
||||
|
||||
// 定义变量内容
|
||||
const stores = useRoutesList();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
|
|
@ -44,6 +44,7 @@ const state = reactive({
|
|||
routeSplitFirst: '',
|
||||
routeSplitIndex: 1,
|
||||
});
|
||||
|
||||
// 动态设置经典、横向布局不显示
|
||||
const isShowBreadcrumb = computed(() => {
|
||||
initRouteSplit(route.path);
|
||||
|
|
@ -111,7 +112,6 @@ onBeforeRouteUpdate((to) => {
|
|||
.layout-navbars-breadcrumb-icon {
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
margin-right: 15px;
|
||||
color: var(--next-bg-topBarColor);
|
||||
height: 100%;
|
||||
width: 40px;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
import { storeToRefs } from 'pinia';
|
||||
import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
|
||||
|
||||
// 定义变量内容
|
||||
const stores = useTagsViewRoutes();
|
||||
const { isTagsViewCurrenFull } = storeToRefs(stores);
|
||||
|
||||
|
|
@ -29,7 +30,6 @@ const onCloseFullscreen = () => {
|
|||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 100%;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
|
|
@ -41,6 +41,7 @@ const onCloseFullscreen = () => {
|
|||
color: #333333;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
transition: all 0.3s ease;
|
||||
:deep(i) {
|
||||
|
|
@ -49,5 +50,4 @@ const onCloseFullscreen = () => {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -13,11 +13,13 @@ import { useRoutesList } from '/@/stores/routesList';
|
|||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import mittBus from '/@/utils/mitt';
|
||||
|
||||
// 引入组件
|
||||
const Breadcrumb = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/breadcrumb.vue'));
|
||||
const User = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/user.vue'));
|
||||
const Logo = defineAsyncComponent(() => import('/@/layout/logo/index.vue'));
|
||||
const Horizontal = defineAsyncComponent(() => import('/@/layout/navMenu/horizontal.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const stores = useRoutesList();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
|
|
@ -26,6 +28,7 @@ const route = useRoute();
|
|||
const state = reactive({
|
||||
menuList: [],
|
||||
});
|
||||
|
||||
// 设置 logo 显示/隐藏
|
||||
const setIsShowLogo = computed(() => {
|
||||
let { isShowLogo, layout } = themeConfig.value;
|
||||
|
|
@ -57,7 +60,7 @@ const delClassicChildren = (arr) => {
|
|||
// 路由过滤递归函数
|
||||
const filterRoutesFun = (arr) => {
|
||||
return arr
|
||||
.filter((item) => !item.meta.isHide)
|
||||
.filter((item) => !item.meta?.isHide)
|
||||
.map((item) => {
|
||||
item = Object.assign({}, item);
|
||||
if (item.children) item.children = filterRoutesFun(item.children);
|
||||
|
|
@ -67,11 +70,11 @@ const filterRoutesFun = (arr) => {
|
|||
// 传送当前子级数据到菜单中
|
||||
const setSendClassicChildren = (path) => {
|
||||
const currentPathSplit = path.split('/');
|
||||
let currentData = {};
|
||||
let currentData = { children: [] };
|
||||
filterRoutesFun(routesList.value).map((v, k) => {
|
||||
if (v.path === `/${currentPathSplit[1]}`) {
|
||||
v['k'] = k;
|
||||
currentData['item'] = [{ ...v }];
|
||||
currentData['item'] = { ...v };
|
||||
currentData['children'] = [{ ...v }];
|
||||
if (v.children) currentData['children'] = v.children;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
import { storeToRefs } from 'pinia';
|
||||
import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
|
||||
|
||||
// 定义变量内容
|
||||
const storesTagsViewRoutes = useTagsViewRoutes();
|
||||
const { tagsViewRoutes } = storeToRefs(storesTagsViewRoutes);
|
||||
const layoutMenuAutocompleteRef = ref();
|
||||
|
|
@ -40,6 +41,7 @@ const state = reactive({
|
|||
menuQuery: '',
|
||||
tagsViewList: [],
|
||||
});
|
||||
|
||||
// 搜索弹窗打开
|
||||
const openSearch = () => {
|
||||
state.menuQuery = '';
|
||||
|
|
@ -74,13 +76,13 @@ const createFilter = (queryString) => {
|
|||
const initTageView = () => {
|
||||
if (state.tagsViewList.length > 0) return false;
|
||||
tagsViewRoutes.value.map((v) => {
|
||||
if (!v.meta.isHide) state.tagsViewList.push({ ...v });
|
||||
if (!v.meta?.isHide) state.tagsViewList.push({ ...v });
|
||||
});
|
||||
};
|
||||
// 当前菜单选中时
|
||||
const onHandleSelect = (item) => {
|
||||
let { path, redirect } = item;
|
||||
if (item.meta.isLink && !item.meta.isIframe) window.open(item.meta.isLink);
|
||||
if (item.meta?.isLink && !item.meta?.isIframe) window.open(item.meta?.isLink);
|
||||
else if (redirect) router.push(redirect);
|
||||
else router.push(path);
|
||||
closeSearch();
|
||||
|
|
@ -94,6 +96,7 @@ defineExpose({
|
|||
|
||||
<style scoped lang="scss">
|
||||
.layout-search-dialog {
|
||||
position: relative;
|
||||
:deep(.el-dialog) {
|
||||
.el-dialog__header,
|
||||
.el-dialog__body {
|
||||
|
|
|
|||
|
|
@ -413,7 +413,7 @@
|
|||
import { ElMessage } from 'element-plus';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import { getLightColor, getDarkColor } from '/@/utils/theme';
|
||||
import { useChangeColor } from '/@/utils/theme';
|
||||
import { verifyAndSpace } from '/@/utils/toolsValidate';
|
||||
import { Local } from '/@/utils/storage';
|
||||
import Watermark from '/@/utils/wartermark';
|
||||
|
|
@ -421,12 +421,15 @@ import commonFunction from '/@/utils/commonFunction';
|
|||
import other from '/@/utils/other';
|
||||
import mittBus from '/@/utils/mitt';
|
||||
|
||||
// 定义变量内容
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
const { copyText } = commonFunction();
|
||||
const { getLightColor, getDarkColor } = useChangeColor();
|
||||
const state = reactive({
|
||||
isMobile: false,
|
||||
});
|
||||
|
||||
// 获取布局配置信息
|
||||
const getThemeConfig = computed(() => {
|
||||
return themeConfig.value;
|
||||
|
|
@ -445,7 +448,7 @@ const onColorPickerChange = () => {
|
|||
};
|
||||
// 2、菜单 / 顶栏
|
||||
const onBgColorPickerChange = (bg) => {
|
||||
document.documentElement.style.setProperty(`--next-bg-${bg}`, getThemeConfig.value[bg]);
|
||||
document.documentElement.style.setProperty(`--next-bg-${bg}`, themeConfig.value[bg]);
|
||||
if (bg === 'menuBar') {
|
||||
document.documentElement.style.setProperty(`--next-bg-menuBar-light-1`, getLightColor(getThemeConfig.value.menuBar, 0.05));
|
||||
}
|
||||
|
|
@ -552,6 +555,7 @@ const onWartermarkTextInput = (val) => {
|
|||
// 5、布局切换
|
||||
const onSetLayout = (layout) => {
|
||||
Local.set('oldLayout', layout);
|
||||
if (getThemeConfig.value.layout === layout) return false;
|
||||
if (layout === 'transverse') getThemeConfig.value.isCollapse = false;
|
||||
getThemeConfig.value.layout = layout;
|
||||
getThemeConfig.value.isDrawer = false;
|
||||
|
|
@ -566,7 +570,7 @@ const initLayoutChangeFun = () => {
|
|||
onBgColorPickerChange('columnsMenuBar');
|
||||
onBgColorPickerChange('columnsMenuBarColor');
|
||||
};
|
||||
// 关闭弹窗时,初始化变量。变量用于处理 layoutScrollbarRef.value.update()
|
||||
// 关闭弹窗时,初始化变量。变量用于处理 layoutScrollbarRef.value.update() 更新滚动条高度
|
||||
const onDrawerClose = () => {
|
||||
getThemeConfig.value.isFixedHeaderChange = false;
|
||||
getThemeConfig.value.isShowLogoChange = false;
|
||||
|
|
@ -603,6 +607,8 @@ const onCopyConfigClick = () => {
|
|||
const onResetConfigClick = () => {
|
||||
Local.clear();
|
||||
window.location.reload();
|
||||
// @ts-ignore
|
||||
Local.set('version', __VERSION__);
|
||||
};
|
||||
// 初始化菜单样式等
|
||||
const initSetStyle = () => {
|
||||
|
|
@ -732,7 +738,7 @@ defineExpose({
|
|||
line-height: 1;
|
||||
letter-spacing: 2px;
|
||||
white-space: nowrap;
|
||||
color: var(--el-color-primary-light-4);
|
||||
color: var(--el-color-primary-light-5);
|
||||
text-align: center;
|
||||
transform: rotate(30deg);
|
||||
left: -1px;
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="medium" :disabled="state.disabledSize === 'large'">大型</el-dropdown-item>
|
||||
<el-dropdown-item command="small" :disabled="state.disabledSize === 'default'">默认</el-dropdown-item>
|
||||
<el-dropdown-item command="mini" :disabled="state.disabledSize === 'small'">小型</el-dropdown-item>
|
||||
<el-dropdown-item command="large" :disabled="state.disabledSize === 'large'">大型</el-dropdown-item>
|
||||
<el-dropdown-item command="default" :disabled="state.disabledSize === 'default'">默认</el-dropdown-item>
|
||||
<el-dropdown-item command="small" :disabled="state.disabledSize === 'small'">小型</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
|
|
@ -66,15 +66,17 @@
|
|||
<script setup name="layoutBreadcrumbUser">
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import screenfull from 'screenfull';
|
||||
import { Session, Local } from '/@/utils/storage';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useUserInfo } from '/@/stores/userInfo';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import mittBus from '/@/utils/mitt';
|
||||
import { Session, Local } from '/@/utils/storage';
|
||||
|
||||
// 引入组件
|
||||
const UserNews = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/userNews.vue'));
|
||||
const Search = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/search.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const router = useRouter();
|
||||
const stores = useUserInfo();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
|
|
@ -83,9 +85,9 @@ const { themeConfig } = storeToRefs(storesThemeConfig);
|
|||
const searchRef = ref();
|
||||
const state = reactive({
|
||||
isScreenfull: false,
|
||||
isShowUserNewsPopover: false,
|
||||
disabledSize: '',
|
||||
disabledSize: 'large',
|
||||
});
|
||||
|
||||
// 设置分割样式
|
||||
const layoutUserFlexNum = computed(() => {
|
||||
let num = '';
|
||||
|
|
@ -163,7 +165,6 @@ const onComponentSizeChange = (size) => {
|
|||
initI18nOrSize('globalComponentSize', 'disabledSize');
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
// 初始化组件大小/i18n
|
||||
const initI18nOrSize = (value, attr) => {
|
||||
state[attr] = Local.get('themeConfig')[value];
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
</template>
|
||||
|
||||
<script setup name="layoutBreadcrumbUserNews">
|
||||
// 定义变量内容
|
||||
const state = reactive({
|
||||
newsList: [
|
||||
{
|
||||
|
|
@ -35,6 +36,7 @@ const state = reactive({
|
|||
},
|
||||
],
|
||||
});
|
||||
|
||||
// 全部已读点击
|
||||
const onAllReadClick = () => {
|
||||
state.newsList = [];
|
||||
|
|
@ -73,9 +75,9 @@ const onGoToGiteeClick = () => {
|
|||
padding-bottom: 12px;
|
||||
}
|
||||
.content-box-msg {
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
.content-box-time {
|
||||
color: var(--el-text-color-secondary);
|
||||
|
|
|
|||
|
|
@ -9,11 +9,14 @@
|
|||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
|
||||
// 引入组件
|
||||
const BreadcrumbIndex = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/index.vue'));
|
||||
const TagsView = defineAsyncComponent(() => import('/@/layout/navBars/tagsView/tagsView.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
|
||||
// 是否显示 tagsView
|
||||
const setShowTagsView = computed(() => {
|
||||
let { layout, isTagsview } = themeConfig.value;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
</template>
|
||||
|
||||
<script setup name="layoutTagsViewContextmenu">
|
||||
// 定义父组件传过来的值
|
||||
const props = defineProps({
|
||||
dropdown: {
|
||||
type: Object,
|
||||
|
|
@ -41,7 +42,11 @@ const props = defineProps({
|
|||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 定义子组件向父组件传值/事件
|
||||
const emit = defineEmits(['currentContextmenuClick']);
|
||||
|
||||
// 定义变量内容
|
||||
const state = reactive({
|
||||
isShow: false,
|
||||
dropdownList: [
|
||||
|
|
@ -54,6 +59,7 @@ const state = reactive({
|
|||
item: {},
|
||||
arrowLeft: 10,
|
||||
});
|
||||
|
||||
// 父级传过来的坐标 x,y 值
|
||||
const dropdowns = computed(() => {
|
||||
// 117 为 `Dropdown 下拉菜单` 的宽度
|
||||
|
|
@ -73,7 +79,7 @@ const onCurrentContextmenuClick = (contextMenuClickId) => {
|
|||
// 打开右键菜单:判断是否固定,固定则不显示关闭按钮
|
||||
const openContextmenu = (item) => {
|
||||
state.item = item;
|
||||
item.meta.isAffix ? (state.dropdownList[1].affix = true) : (state.dropdownList[1].affix = false);
|
||||
item.meta?.isAffix ? (state.dropdownList[1].affix = true) : (state.dropdownList[1].affix = false);
|
||||
closeContextmenu();
|
||||
setTimeout(() => {
|
||||
state.isShow = true;
|
||||
|
|
|
|||
|
|
@ -60,29 +60,32 @@ import { isObjectValueEqual } from '/@/utils/arrayOperation';
|
|||
import other from '/@/utils/other';
|
||||
import mittBus from '/@/utils/mitt';
|
||||
|
||||
// 引入组件
|
||||
const Contextmenu = defineAsyncComponent(() => import('/@/layout/navBars/tagsView/contextmenu.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const tagsRefs = ref([]);
|
||||
const scrollbarRef = ref();
|
||||
const contextmenuRef = ref();
|
||||
const tagsUlRef = ref();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const stores = useTagsViewRoutes();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const storesTagsViewRoutes = useTagsViewRoutes();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
const { tagsViewRoutes } = storeToRefs(storesTagsViewRoutes);
|
||||
const storesKeepALiveNames = useKeepALiveNames();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
routeActive: '',
|
||||
routePath: route.path,
|
||||
dropdown: { x: '', y: '' },
|
||||
sortable: '',
|
||||
tagsRefsIndex: 0,
|
||||
tagsViewList: [],
|
||||
sortable: '',
|
||||
tagsViewRoutesList: [],
|
||||
});
|
||||
|
||||
// 动态设置 tagsView 风格样式
|
||||
const setTagsStyle = computed(() => {
|
||||
return themeConfig.value.tagsStyle;
|
||||
|
|
@ -116,7 +119,7 @@ const isActive = (v) => {
|
|||
const addBrowserSetSession = (tagsViewList) => {
|
||||
Session.set('tagsViewList', tagsViewList);
|
||||
};
|
||||
// 获取 vuex 中的 tagsViewRoutes 列表
|
||||
// 获取 pinia 中的 tagsViewRoutes 列表
|
||||
const getTagsViewRoutes = async () => {
|
||||
state.routeActive = await setTagsViewHighlight(route);
|
||||
state.routePath = (await route.meta.isDynamic) ? route.meta.isDynamicPath : route.path;
|
||||
|
|
@ -124,13 +127,13 @@ const getTagsViewRoutes = async () => {
|
|||
state.tagsViewRoutesList = tagsViewRoutes.value;
|
||||
initTagsView();
|
||||
};
|
||||
// vuex 中获取路由信息:如果是设置了固定的(isAffix),进行初始化显示
|
||||
// pinia 中获取路由信息:如果是设置了固定的(isAffix),进行初始化显示
|
||||
const initTagsView = async () => {
|
||||
if (Session.get('tagsViewList') && getThemeConfig.value.isCacheTagsView) {
|
||||
state.tagsViewList = await Session.get('tagsViewList');
|
||||
} else {
|
||||
await state.tagsViewRoutesList.map((v) => {
|
||||
if (v.meta.isAffix && !v.meta.isHide) {
|
||||
if (v.meta?.isAffix && !v.meta.isHide) {
|
||||
v.url = setTagsViewHighlight(v);
|
||||
state.tagsViewList.push({ ...v });
|
||||
storesKeepALiveNames.addCachedView(v);
|
||||
|
|
@ -143,20 +146,22 @@ const initTagsView = async () => {
|
|||
};
|
||||
// 处理可开启多标签详情,单标签详情(动态路由(xxx/:id/:name"),普通路由处理)
|
||||
const solveAddTagsView = async (path, to) => {
|
||||
let isDynamicPath = to.meta.isDynamic ? to.meta.isDynamicPath : path;
|
||||
let isDynamicPath = to?.meta?.isDynamic ? to.meta.isDynamicPath : path;
|
||||
let current = state.tagsViewList.filter(
|
||||
(v) =>
|
||||
v.path === isDynamicPath &&
|
||||
isObjectValueEqual(
|
||||
to.meta.isDynamic ? (v.params ? v.params : null) : v.query ? v.query : null,
|
||||
to.meta.isDynamic ? (to?.params ? to?.params : null) : to?.query ? to?.query : null
|
||||
to?.meta?.isDynamic ? (v.params ? v.params : null) : v.query ? v.query : null,
|
||||
to?.meta?.isDynamic ? (to?.params ? to?.params : null) : to?.query ? to?.query : null
|
||||
)
|
||||
);
|
||||
if (current.length <= 0) {
|
||||
// 防止:Avoid app logic that relies on enumerating keys on a component instance. The keys will be empty in production mode to avoid performance overhead.
|
||||
let findItem = state.tagsViewRoutesList.find((v) => v.path === isDynamicPath);
|
||||
if (!findItem || findItem.meta.isAffix || (findItem.meta.isLink && !findItem.meta.isIframe)) return false;
|
||||
to.meta.isDynamic ? (findItem.params = to.params) : (findItem.query = to.query);
|
||||
if (!findItem) return false;
|
||||
if (findItem.meta.isAffix) return false;
|
||||
if (findItem.meta.isLink && !findItem.meta.isIframe) return false;
|
||||
to?.meta?.isDynamic ? (findItem.params = to.params) : (findItem.query = to?.query);
|
||||
findItem.url = setTagsViewHighlight(findItem);
|
||||
state.tagsViewList.push({ ...findItem });
|
||||
await storesKeepALiveNames.addCachedView(findItem);
|
||||
|
|
@ -165,16 +170,16 @@ const solveAddTagsView = async (path, to) => {
|
|||
};
|
||||
// 处理单标签时,第二次的值未覆盖第一次的 tagsViewList 值(Session Storage)
|
||||
const singleAddTagsView = (path, to) => {
|
||||
let isDynamicPath = to.meta.isDynamic ? to.meta.isDynamicPath : path;
|
||||
let isDynamicPath = to?.meta?.isDynamic ? to.meta.isDynamicPath : path;
|
||||
state.tagsViewList.forEach((v) => {
|
||||
if (
|
||||
v.path === isDynamicPath &&
|
||||
!isObjectValueEqual(
|
||||
to.meta.isDynamic ? (v.params ? v.params : null) : v.query ? v.query : null,
|
||||
to.meta.isDynamic ? (to?.params ? to?.params : null) : to?.query ? to?.query : null
|
||||
to?.meta?.isDynamic ? (v.params ? v.params : null) : v.query ? v.query : null,
|
||||
to?.meta?.isDynamic ? (to?.params ? to?.params : null) : to?.query ? to?.query : null
|
||||
)
|
||||
) {
|
||||
to.meta.isDynamic ? (v.params = to.params) : (v.query = to.query);
|
||||
to?.meta?.isDynamic ? (v.params = to.params) : (v.query = to?.query);
|
||||
v.url = setTagsViewHighlight(v);
|
||||
addBrowserSetSession(state.tagsViewList);
|
||||
}
|
||||
|
|
@ -185,17 +190,17 @@ const addTagsView = (path, to) => {
|
|||
// 防止拿取不到路由信息
|
||||
nextTick(async () => {
|
||||
// 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G
|
||||
let item = '';
|
||||
if (to && to.meta.isDynamic) {
|
||||
let item;
|
||||
if (to?.meta?.isDynamic) {
|
||||
// 动态路由(xxx/:id/:name"):参数不同,开启多个 tagsview
|
||||
if (!getThemeConfig.value.isShareTagsView) await solveAddTagsView(path, to);
|
||||
else await singleAddTagsView(path, to);
|
||||
if (state.tagsViewList.some((v) => v.path === to.meta.isDynamicPath)) {
|
||||
if (state.tagsViewList.some((v) => v.path === to?.meta?.isDynamicPath)) {
|
||||
// 防止首次进入界面时(登录进入) tagsViewList 不存浏览器中
|
||||
addBrowserSetSession(state.tagsViewList);
|
||||
return false;
|
||||
}
|
||||
item = state.tagsViewRoutesList.find((v) => v.path === to.meta.isDynamicPath);
|
||||
item = state.tagsViewRoutesList.find((v) => v.path === to?.meta?.isDynamicPath);
|
||||
} else {
|
||||
// 普通路由:参数不同,开启多个 tagsview
|
||||
if (!getThemeConfig.value.isShareTagsView) await solveAddTagsView(path, to);
|
||||
|
|
@ -207,8 +212,9 @@ const addTagsView = (path, to) => {
|
|||
}
|
||||
item = state.tagsViewRoutesList.find((v) => v.path === path);
|
||||
}
|
||||
if (!item || (item.meta.isLink && !item.meta.isIframe)) return false;
|
||||
if (to && to.meta.isDynamic) item.params = to?.params ? to?.params : route.params;
|
||||
if (!item) return false;
|
||||
if (item?.meta?.isLink && !item.meta.isIframe) return false;
|
||||
if (to?.meta?.isDynamic) item.params = to?.params ? to?.params : route.params;
|
||||
else item.query = to?.query ? to?.query : route.query;
|
||||
item.url = setTagsViewHighlight(item);
|
||||
await storesKeepALiveNames.addCachedView(item);
|
||||
|
|
@ -231,12 +237,12 @@ const refreshCurrentTagsView = async (fullPath) => {
|
|||
if (!item) return false;
|
||||
await storesKeepALiveNames.delCachedView(item);
|
||||
mittBus.emit('onTagsViewRefreshRouterView', fullPath);
|
||||
if (item.meta.isKeepAlive) storesKeepALiveNames.addCachedView(item);
|
||||
if (item.meta?.isKeepAlive) storesKeepALiveNames.addCachedView(item);
|
||||
};
|
||||
// 3、关闭当前 tagsView:如果是设置了固定的(isAffix),不可以关闭
|
||||
const closeCurrentTagsView = (path) => {
|
||||
state.tagsViewList.map((v, k, arr) => {
|
||||
if (!v.meta.isAffix) {
|
||||
state.tagsViewList.map((v, k, arrs) => {
|
||||
if (!v.meta?.isAffix) {
|
||||
if (getThemeConfig.value.isShareTagsView ? v.path === path : v.url === path) {
|
||||
storesKeepALiveNames.delCachedView(v);
|
||||
state.tagsViewList.splice(k, 1);
|
||||
|
|
@ -275,7 +281,7 @@ const closeOtherTagsView = (path) => {
|
|||
if (Session.get('tagsViewList')) {
|
||||
state.tagsViewList = [];
|
||||
Session.get('tagsViewList').map((v) => {
|
||||
if (v.meta.isAffix && !v.meta.isHide) {
|
||||
if (v.meta?.isAffix && !v.meta.isHide) {
|
||||
v.url = setTagsViewHighlight(v);
|
||||
storesKeepALiveNames.delOthersCachedViews(v);
|
||||
state.tagsViewList.push({ ...v });
|
||||
|
|
@ -291,7 +297,7 @@ const closeAllTagsView = () => {
|
|||
storesKeepALiveNames.delAllCachedViews();
|
||||
state.tagsViewList = [];
|
||||
Session.get('tagsViewList').map((v) => {
|
||||
if (v.meta.isAffix && !v.meta.isHide) {
|
||||
if (v.meta?.isAffix && !v.meta.isHide) {
|
||||
v.url = setTagsViewHighlight(v);
|
||||
state.tagsViewList.push({ ...v });
|
||||
router.push({ path: state.tagsViewList[state.tagsViewList.length - 1].path });
|
||||
|
|
@ -315,13 +321,8 @@ const getCurrentRouteItem = (item) => {
|
|||
state.tagsViewList.forEach((v) => {
|
||||
v.transUrl = transUrlParams(v);
|
||||
if (v.transUrl) {
|
||||
if (v.meta.isDynamic) {
|
||||
// 路由带参数:动态路由(xxx/:id/:name")isDynamic
|
||||
if (v.transUrl === transUrlParams(v) && v.transUrl === decodeURI(item.path)) resItem = v;
|
||||
} else {
|
||||
// 路由带参数:普通路由,因为有 tagsView 共用/不共用
|
||||
// 动态路由、普通路由带参数
|
||||
if (v.transUrl === transUrlParams(v) && v.transUrl === item.commonUrl) resItem = v;
|
||||
}
|
||||
} else {
|
||||
// 路由不带参数
|
||||
if (v.path === decodeURI(item.path)) resItem = v;
|
||||
|
|
@ -371,7 +372,7 @@ const onContextmenu = (v, e) => {
|
|||
};
|
||||
// 鼠标按下时,判断是鼠标中键就关闭当前 tasgview
|
||||
const onMousedownMenu = (v, e) => {
|
||||
if (!v.meta.isAffix && e.which === 2) {
|
||||
if (!v.meta?.isAffix && e.button === 1) {
|
||||
const item = Object.assign({}, { contextMenuClickId: 1, ...v });
|
||||
onCurrentContextmenuClick(item);
|
||||
}
|
||||
|
|
@ -381,18 +382,32 @@ const onTagsClick = (v, k) => {
|
|||
state.tagsRefsIndex = k;
|
||||
router.push(v);
|
||||
};
|
||||
// 处理 url,地址栏链接有参数时,tagsview 右键菜单刷新功能失效问题
|
||||
// 处理 url,地址栏链接有参数时,tagsview 右键菜单刷新功能失效问题,感谢 @ZzZz-RIPPER、@dejavuuuuu
|
||||
// https://gitee.com/lyt-top/vue-next-admin/issues/I5K3YO
|
||||
// https://gitee.com/lyt-top/vue-next-admin/issues/I61VS9
|
||||
const transUrlParams = (v) => {
|
||||
let params = v.query && Object.keys(v.query).length > 0 ? v.query : v.params;
|
||||
if (!params) return '';
|
||||
let path = '';
|
||||
for (let [key, value] of Object.entries(params)) {
|
||||
if (v.meta.isDynamic) path += `/${value}`;
|
||||
if (v.meta?.isDynamic) path += `/${value}`;
|
||||
else path += `&${key}=${value}`;
|
||||
}
|
||||
// 判断是否是动态路由(xxx/:id/:name")isDynamic
|
||||
return v.meta.isDynamic ? `${v.path.split(':')[0]}${path.replace(/^\//, '')}` : `${v.path}${path.replace(/^&/, '?')}`;
|
||||
if (v.meta?.isDynamic) {
|
||||
/**
|
||||
*
|
||||
* isFnClick 用于判断是通过方法调用,还是直接右键菜单点击(此处只针对动态路由)
|
||||
* 原因:
|
||||
* 1、右键菜单点击时,路由的 path 还是原始定义的路由格式,如:/params/dynamic/details/:t/:id/:tagsViewName
|
||||
* 2、通过事件调用时,路由的 path 不是原始定义的路由格式,如:/params/dynamic/details/vue-next-admin/111/我是动态路由测试tagsViewName(非国际化)
|
||||
*
|
||||
* 所以右侧菜单点击时,需要处理路径拼接 v.path.split(':')[0],得到路径 + 参数的完整路径
|
||||
*/
|
||||
return v.isFnClick ? decodeURI(v.path) : `${v.path.split(':')[0]}${path.replace(/^\//, '')}`;
|
||||
} else {
|
||||
return `${v.path}${path.replace(/^&/, '?')}`;
|
||||
}
|
||||
};
|
||||
// 处理 tagsView 高亮(多标签详情时使用,单标签详情未使用)
|
||||
const setTagsViewHighlight = (v) => {
|
||||
|
|
@ -403,11 +418,11 @@ const setTagsViewHighlight = (v) => {
|
|||
path += params[i];
|
||||
}
|
||||
// 判断是否是动态路由(xxx/:id/:name")
|
||||
return `${v.meta.isDynamic ? v.meta.isDynamicPath : v.path}-${path}`;
|
||||
return `${v.meta?.isDynamic ? v.meta.isDynamicPath : v.path}-${path}`;
|
||||
};
|
||||
// 鼠标滚轮滚动
|
||||
const onHandleScroll = (e) => {
|
||||
scrollbarRef.value.$refs.scrollbarRef.$refs.wrap$.scrollLeft += e.wheelDelta / 4;
|
||||
scrollbarRef.value.$refs.wrapRef.scrollLeft += e.wheelDelta / 4;
|
||||
};
|
||||
// tagsView 横向滚动
|
||||
const tagsViewmoveToCurrentTag = () => {
|
||||
|
|
@ -424,7 +439,7 @@ const tagsViewmoveToCurrentTag = () => {
|
|||
// 最后 li
|
||||
let liLast = tagsRefs.value[tagsRefs.value.length - 1];
|
||||
// 当前滚动条的值
|
||||
let scrollRefs = scrollbarRef.value.$refs.wrap$;
|
||||
let scrollRefs = scrollbarRef.value.$refs.wrapRef;
|
||||
// 当前滚动条滚动宽度
|
||||
let scrollS = scrollRefs.scrollWidth;
|
||||
// 当前滚动条偏移宽度
|
||||
|
|
@ -436,9 +451,9 @@ const tagsViewmoveToCurrentTag = () => {
|
|||
// 下一个 tags li dom
|
||||
let liNextTag = tagsRefs.value[state.tagsRefsIndex + 1];
|
||||
// 上一个 tags li dom 的偏移距离
|
||||
let beforePrevL = '';
|
||||
let beforePrevL = 0;
|
||||
// 下一个 tags li dom 的偏移距离
|
||||
let afterNextL = '';
|
||||
let afterNextL = 0;
|
||||
if (liDom === liFirst) {
|
||||
// 头部
|
||||
scrollRefs.scrollLeft = 0;
|
||||
|
|
@ -510,6 +525,8 @@ onBeforeMount(() => {
|
|||
window.addEventListener('resize', onSortableResize);
|
||||
// 监听非本页面调用 0 刷新当前,1 关闭当前,2 关闭其它,3 关闭全部 4 当前页全屏
|
||||
mittBus.on('onCurrentContextmenuClick', (data) => {
|
||||
// 通过方法点击关闭 tagsView
|
||||
data.isFnClick = true;
|
||||
onCurrentContextmenuClick(data);
|
||||
});
|
||||
// 监听布局配置界面开启/关闭拖拽
|
||||
|
|
@ -522,7 +539,7 @@ onBeforeMount(() => {
|
|||
router.push('/home');
|
||||
state.tagsViewList = [];
|
||||
state.tagsViewRoutesList.map((v) => {
|
||||
if (v.meta.isAffix && !v.meta.isHide) {
|
||||
if (v.meta?.isAffix && !v.meta.isHide) {
|
||||
v.url = setTagsViewHighlight(v);
|
||||
state.tagsViewList.push({ ...v });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,31 +31,36 @@
|
|||
</template>
|
||||
|
||||
<script setup name="navMenuHorizontal">
|
||||
import { onBeforeRouteUpdate } from 'vue-router';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useRoutesList } from '/@/stores/routesList';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import { onBeforeRouteUpdate } from 'vue-router';
|
||||
import { verifyUrl } from '/@/utils/toolsValidate';
|
||||
import other from '/@/utils/other';
|
||||
import mittBus from '/@/utils/mitt';
|
||||
|
||||
// 引入组件
|
||||
const SubItem = defineAsyncComponent(() => import('/@/layout/navMenu/subItem.vue'));
|
||||
|
||||
// 定义父组件传过来的值
|
||||
const props = defineProps({
|
||||
// 菜单列表
|
||||
menuList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
// 定义变量内容
|
||||
const elMenuHorizontalScrollRef = ref();
|
||||
const stores = useRoutesList();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { routesList } = storeToRefs(stores);
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
defaultActive: null,
|
||||
defaultActive: '',
|
||||
});
|
||||
|
||||
// 获取父级菜单数据
|
||||
const menuLists = computed(() => {
|
||||
return props.menuList;
|
||||
|
|
@ -63,20 +68,20 @@ const menuLists = computed(() => {
|
|||
// 设置横向滚动条可以鼠标滚轮滚动
|
||||
const onElMenuHorizontalScroll = (e) => {
|
||||
const eventDelta = e.wheelDelta || -e.deltaY * 40;
|
||||
elMenuHorizontalScrollRef.value.$refs.wrap$.scrollLeft = elMenuHorizontalScrollRef.value.$refs.wrap$.scrollLeft + eventDelta / 4;
|
||||
elMenuHorizontalScrollRef.value.$refs.wrapRef.scrollLeft = elMenuHorizontalScrollRef.value.$refs.wrapRef.scrollLeft + eventDelta / 4;
|
||||
};
|
||||
// 初始化数据,页面刷新时,滚动条滚动到对应位置
|
||||
const initElMenuOffsetLeft = () => {
|
||||
nextTick(() => {
|
||||
let els = document.querySelector('.el-menu.el-menu--horizontal li.is-active');
|
||||
if (!els) return false;
|
||||
elMenuHorizontalScrollRef.value.$refs.wrap$.scrollLeft = els.offsetLeft;
|
||||
elMenuHorizontalScrollRef.value.$refs.wrapRef.scrollLeft = els.offsetLeft;
|
||||
});
|
||||
};
|
||||
// 路由过滤递归函数
|
||||
const filterRoutesFun = (arr) => {
|
||||
return arr
|
||||
.filter((item) => !item.meta.isHide)
|
||||
.filter((item) => !item.meta?.isHide)
|
||||
.map((item) => {
|
||||
item = Object.assign({}, item);
|
||||
if (item.children) item.children = filterRoutesFun(item.children);
|
||||
|
|
@ -86,11 +91,11 @@ const filterRoutesFun = (arr) => {
|
|||
// 传送当前子级数据到菜单中
|
||||
const setSendClassicChildren = (path) => {
|
||||
const currentPathSplit = path.split('/');
|
||||
let currentData = {};
|
||||
let currentData = { children: [] };
|
||||
filterRoutesFun(routesList.value).map((v, k) => {
|
||||
if (v.path === `/${currentPathSplit[1]}`) {
|
||||
v['k'] = k;
|
||||
currentData['item'] = [{ ...v }];
|
||||
currentData['item'] = { ...v };
|
||||
currentData['children'] = [{ ...v }];
|
||||
if (v.children) currentData['children'] = v.children;
|
||||
}
|
||||
|
|
@ -101,19 +106,16 @@ const setSendClassicChildren = (path) => {
|
|||
const setCurrentRouterHighlight = (currentRoute) => {
|
||||
const { path, meta } = currentRoute;
|
||||
if (themeConfig.value.layout === 'classic') {
|
||||
state.defaultActive = `/${path.split('/')[1]}`;
|
||||
state.defaultActive = `/${path?.split('/')[1]}`;
|
||||
} else {
|
||||
const pathSplit = meta.isDynamic ? meta.isDynamicPath.split('/') : path.split('/');
|
||||
if (pathSplit.length >= 4 && meta.isHide) state.defaultActive = pathSplit.splice(0, 3).join('/');
|
||||
const pathSplit = meta?.isDynamic ? meta.isDynamicPath.split('/') : path.split('/');
|
||||
if (pathSplit.length >= 4 && meta?.isHide) state.defaultActive = pathSplit.splice(0, 3).join('/');
|
||||
else state.defaultActive = path;
|
||||
}
|
||||
};
|
||||
// 打开外部链接
|
||||
const onALinkClick = (val) => {
|
||||
const { origin, pathname } = window.location;
|
||||
router.push(val.path);
|
||||
if (verifyUrl(val.meta.isLink)) window.open(val.meta.isLink);
|
||||
else window.open(`${origin}${pathname}#${val.meta.isLink}`);
|
||||
other.handleOpenLink(val);
|
||||
};
|
||||
// 页面加载前
|
||||
onBeforeMount(() => {
|
||||
|
|
|
|||
|
|
@ -25,25 +25,23 @@
|
|||
</template>
|
||||
|
||||
<script setup name="navMenuSubItem">
|
||||
import { useRouter } from 'vue-router';
|
||||
import { verifyUrl } from '/@/utils/toolsValidate';
|
||||
import other from '/@/utils/other';
|
||||
|
||||
// 定义父组件传过来的值
|
||||
const props = defineProps({
|
||||
// 菜单列表
|
||||
chil: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
const router = useRouter();
|
||||
|
||||
// 获取父级菜单数据
|
||||
const chils = computed(() => {
|
||||
return props.chil;
|
||||
});
|
||||
// 打开外部链接
|
||||
const onALinkClick = (val) => {
|
||||
const { origin, pathname } = window.location;
|
||||
router.push(val.path);
|
||||
if (verifyUrl(val.meta.isLink)) window.open(val.meta.isLink);
|
||||
else window.open(`${origin}${pathname}#${val.meta.isLink}`);
|
||||
other.handleOpenLink(val);
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -31,28 +31,33 @@
|
|||
</template>
|
||||
|
||||
<script setup name="navMenuVertical">
|
||||
import { onBeforeRouteUpdate } from 'vue-router';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import { onBeforeRouteUpdate } from 'vue-router';
|
||||
import { verifyUrl } from '/@/utils/toolsValidate';
|
||||
import other from '/@/utils/other';
|
||||
|
||||
// 引入组件
|
||||
const SubItem = defineAsyncComponent(() => import('/@/layout/navMenu/subItem.vue'));
|
||||
|
||||
// 定义父组件传过来的值
|
||||
const props = defineProps({
|
||||
// 菜单列表
|
||||
menuList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
// 定义变量内容
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const state = reactive({
|
||||
// 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G
|
||||
defaultActive: route.meta.isDynamic ? route.meta.isDynamicPath : route.path,
|
||||
isCollapse: false,
|
||||
});
|
||||
|
||||
// 获取父级菜单数据
|
||||
const menuLists = computed(() => {
|
||||
return props.menuList;
|
||||
|
|
@ -64,26 +69,13 @@ const getThemeConfig = computed(() => {
|
|||
// 菜单高亮(详情时,父级高亮)
|
||||
const setParentHighlight = (currentRoute) => {
|
||||
const { path, meta } = currentRoute;
|
||||
const pathSplit = meta.isDynamic ? meta.isDynamicPath.split('/') : path.split('/');
|
||||
if (pathSplit.length >= 4 && meta.isHide) return pathSplit.splice(0, 3).join('/');
|
||||
const pathSplit = meta?.isDynamic ? meta.isDynamicPath.split('/') : path.split('/');
|
||||
if (pathSplit.length >= 4 && meta?.isHide) return pathSplit.splice(0, 3).join('/');
|
||||
else return path;
|
||||
};
|
||||
// 设置菜单的收起/展开
|
||||
watch(
|
||||
themeConfig.value,
|
||||
() => {
|
||||
document.body.clientWidth <= 1000 ? (state.isCollapse = false) : (state.isCollapse = themeConfig.value.isCollapse);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
// 打开外部链接
|
||||
const onALinkClick = (val) => {
|
||||
const { origin, pathname } = window.location;
|
||||
router.push(val.path);
|
||||
if (verifyUrl(val.meta.isLink)) window.open(val.meta.isLink);
|
||||
else window.open(`${origin}${pathname}#${val.meta.isLink}`);
|
||||
other.handleOpenLink(val);
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
|
|
@ -96,4 +88,14 @@ onBeforeRouteUpdate((to) => {
|
|||
const clientWidth = document.body.clientWidth;
|
||||
if (clientWidth < 1000) themeConfig.value.isCollapse = false;
|
||||
});
|
||||
// 设置菜单的收起/展开
|
||||
watch(
|
||||
themeConfig.value,
|
||||
() => {
|
||||
document.body.clientWidth <= 1000 ? (state.isCollapse = false) : (state.isCollapse = themeConfig.value.isCollapse);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -20,26 +20,33 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="layoutIfameView">
|
||||
<script setup name="layoutIframeView">
|
||||
// 定义父组件传过来的值
|
||||
const props = defineProps({
|
||||
// 刷新 iframe
|
||||
refreshKey: {
|
||||
type: String,
|
||||
default: () => '',
|
||||
},
|
||||
// 过渡动画 name
|
||||
name: {
|
||||
type: String,
|
||||
default: () => 'slide-right',
|
||||
},
|
||||
// iframe 列表
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
// 定义变量内容
|
||||
const iframeRef = ref();
|
||||
const route = useRoute();
|
||||
|
||||
// 处理 list 列表,当打开时,才进行加载
|
||||
const setIframeList = computed(() => {
|
||||
return props.list.filter((v) => v.meta.isIframeOpen);
|
||||
return props.list.filter((v) => v.meta?.isIframeOpen);
|
||||
});
|
||||
// 获取 iframe 当前路由 path
|
||||
const getRoutePath = computed(() => {
|
||||
|
|
@ -52,7 +59,7 @@ const closeIframeLoading = (val, item) => {
|
|||
iframeRef.value.forEach((v) => {
|
||||
if (v.dataset.url === val) {
|
||||
v.onload = () => {
|
||||
if (item.meta.isIframeOpen && item.meta.loading) item.meta.loading = false;
|
||||
if (item.meta?.isIframeOpen && item.meta.loading) item.meta.loading = false;
|
||||
};
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<div class="layout-padding-auto layout-padding-view">
|
||||
<div class="layout-link-warp">
|
||||
<i class="layout-link-icon iconfont icon-xingqiu"></i>
|
||||
<div class="layout-link-msg">页面 "{{ state.currentRouteMeta.title }}" 已在新窗口中打开</div>
|
||||
<div class="layout-link-msg">页面 {{ state.title }} 已在新窗口中打开</div>
|
||||
<el-button class="mt30" round size="default" @click="onGotoFullPage">
|
||||
<i class="iconfont icon-lianjie"></i>
|
||||
<span>立即前往体验</span>
|
||||
|
|
@ -16,24 +16,25 @@
|
|||
<script setup name="layoutLinkView">
|
||||
import { verifyUrl } from '/@/utils/toolsValidate';
|
||||
|
||||
// 定义变量内容
|
||||
const route = useRoute();
|
||||
const state = reactive({
|
||||
currentRouteMeta: {
|
||||
isLink: '',
|
||||
title: '',
|
||||
},
|
||||
isLink: '',
|
||||
});
|
||||
|
||||
// 立即前往
|
||||
const onGotoFullPage = () => {
|
||||
const { origin, pathname } = window.location;
|
||||
if (verifyUrl(state.currentRouteMeta.isLink)) window.open(state.currentRouteMeta.isLink);
|
||||
else window.open(`${origin}${pathname}#${state.currentRouteMeta.isLink}`);
|
||||
if (verifyUrl(state.isLink)) window.open(state.isLink);
|
||||
else window.open(`${origin}${pathname}#${state.isLink}`);
|
||||
};
|
||||
// 监听路由的变化,设置内容
|
||||
watch(
|
||||
() => route.path,
|
||||
() => {
|
||||
state.currentRouteMeta = route.meta;
|
||||
state.title = route.meta.title;
|
||||
state.isLink = route.meta.isLink;
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
|
|
|
|||
|
|
@ -20,8 +20,10 @@ import { useThemeConfig } from '/@/stores/themeConfig';
|
|||
import { Session } from '/@/utils/storage';
|
||||
import mittBus from '/@/utils/mitt';
|
||||
|
||||
// 引入组件
|
||||
const Iframes = defineAsyncComponent(() => import('/@/layout/routerView/iframes.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const storesKeepAliveNames = useKeepALiveNames();
|
||||
|
|
@ -34,6 +36,7 @@ const state = reactive({
|
|||
keepAliveNameList: [],
|
||||
iframeList: [],
|
||||
});
|
||||
|
||||
// 设置主界面切换动画
|
||||
const setTransitionName = computed(() => {
|
||||
return themeConfig.value.animation;
|
||||
|
|
@ -69,7 +72,8 @@ onBeforeMount(() => {
|
|||
state.keepAliveNameList = keepAliveNames.value;
|
||||
});
|
||||
});
|
||||
}); // 页面加载时
|
||||
});
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
getIframeListRoutes();
|
||||
// https://gitee.com/lyt-top/vue-next-admin/issues/I58U75
|
||||
|
|
@ -82,7 +86,7 @@ onMounted(() => {
|
|||
});
|
||||
// 页面卸载时
|
||||
onUnmounted(() => {
|
||||
mittBus.off('onTagsViewRefreshRouterView');
|
||||
mittBus.off('onTagsViewRefreshRouterView', () => {});
|
||||
});
|
||||
// 监听路由变化,防止 tagsView 多标签时,切换动画消失
|
||||
// https://toscode.gitee.com/lyt-top/vue-next-admin/pulls/38/files
|
||||
|
|
|
|||
|
|
@ -0,0 +1,134 @@
|
|||
<template>
|
||||
<div class="upgrade-dialog">
|
||||
<el-dialog
|
||||
v-model="state.isUpgrade"
|
||||
width="300px"
|
||||
destroy-on-close
|
||||
:show-close="false"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
>
|
||||
<div class="upgrade-title">
|
||||
<div class="upgrade-title-warp">
|
||||
<span class="upgrade-title-warp-txt">新版本升级</span>
|
||||
<span class="upgrade-title-warp-version">v{{ state.version }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upgrade-content">
|
||||
{{ getThemeConfig.globalTitle }} 新版本来啦,马上更新尝鲜吧!不用担心,更新很快的哦!
|
||||
<div class="upgrade-content-desc mt5">提示:更新会还原默认配置</div>
|
||||
</div>
|
||||
<div class="upgrade-btn">
|
||||
<el-button round size="default" type="info" text @click="onCancel">残忍拒绝</el-button>
|
||||
<el-button type="primary" round size="default" @click="onUpgrade" :loading="state.isLoading">{{ state.btnTxt }}</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="layoutUpgrade">
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import { Local } from '/@/utils/storage';
|
||||
|
||||
// 定义变量内容
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
const state = reactive({
|
||||
isUpgrade: true,
|
||||
version: __VERSION__,
|
||||
isLoading: false,
|
||||
btnTxt: '',
|
||||
});
|
||||
|
||||
// 获取布局配置信息
|
||||
const getThemeConfig = computed(() => {
|
||||
return themeConfig.value;
|
||||
});
|
||||
// 残忍拒绝
|
||||
const onCancel = () => {
|
||||
state.isUpgrade = false;
|
||||
};
|
||||
// 马上更新
|
||||
const onUpgrade = () => {
|
||||
state.isLoading = true;
|
||||
state.btnTxt = '更新中';
|
||||
setTimeout(() => {
|
||||
Local.clear();
|
||||
window.location.reload();
|
||||
Local.set('version', state.version);
|
||||
}, 2000);
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
state.btnTxt = '马上更新';
|
||||
}, 200);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.upgrade-dialog {
|
||||
:deep(.el-dialog) {
|
||||
.el-dialog__body {
|
||||
padding: 0 !important;
|
||||
}
|
||||
.el-dialog__header {
|
||||
display: none !important;
|
||||
}
|
||||
.upgrade-title {
|
||||
text-align: center;
|
||||
height: 130px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: var(--el-color-primary);
|
||||
width: 130%;
|
||||
height: 130px;
|
||||
border-bottom-left-radius: 100%;
|
||||
border-bottom-right-radius: 100%;
|
||||
}
|
||||
.upgrade-title-warp {
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
.upgrade-title-warp-txt {
|
||||
color: var(--next-color-white);
|
||||
font-size: 22px;
|
||||
letter-spacing: 3px;
|
||||
}
|
||||
.upgrade-title-warp-version {
|
||||
background-color: var(--next-color-white);
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
top: -2px;
|
||||
right: -50px;
|
||||
padding: 2px 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.upgrade-content {
|
||||
padding: 20px;
|
||||
line-height: 22px;
|
||||
.upgrade-content-desc {
|
||||
color: var(--el-color-info-light-5);
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
.upgrade-btn {
|
||||
border-top: 1px solid var(--el-border-color-lighter, #ebeef5);
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 15px 20px;
|
||||
.el-button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -2,7 +2,7 @@ import { createApp } from 'vue';
|
|||
import pinia from './stores/index';
|
||||
import App from './App.vue';
|
||||
import router from './router';
|
||||
import { directive } from '/@/utils/directive';
|
||||
import { directive } from '/@/directive/index';
|
||||
import other from '/@/utils/other';
|
||||
|
||||
import ElementPlus from 'element-plus';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { storeToRefs } from 'pinia';
|
||||
import pinia from '../stores/index';
|
||||
import pinia from '/@/stores/index';
|
||||
import { useUserInfo } from '/@/stores/userInfo';
|
||||
import { useRequestOldRoutes } from '/@/stores/requestOldRoutes';
|
||||
import { Session } from '/@/utils/storage';
|
||||
|
|
@ -10,18 +10,18 @@ import { useRoutesList } from '/@/stores/routesList';
|
|||
import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
|
||||
import { useMenuApi } from '/@/api/menu/index';
|
||||
|
||||
const menuApi = useMenuApi();
|
||||
|
||||
const layouModules = import.meta.glob('../layout/routerView/*.{vue,tsx}');
|
||||
const viewsModules = import.meta.glob('../views/**/*.{vue,tsx}');
|
||||
|
||||
// 后端控制路由
|
||||
|
||||
// 引入 api 请求接口
|
||||
const menuApi = useMenuApi();
|
||||
|
||||
/**
|
||||
* 获取目录下的 .vue、.tsx 全部文件
|
||||
* @method import.meta.glob
|
||||
* @link 参考:https://cn.vitejs.dev/guide/features.html#json
|
||||
*/
|
||||
const layouModules = import.meta.glob('../layout/routerView/*.{vue,tsx}');
|
||||
const viewsModules = import.meta.glob('../views/**/*.{vue,tsx}');
|
||||
const dynamicViewsModules = Object.assign({}, { ...layouModules }, { ...viewsModules });
|
||||
|
||||
/**
|
||||
|
|
@ -30,9 +30,8 @@ const dynamicViewsModules = Object.assign({}, { ...layouModules }, { ...viewsMod
|
|||
* @method useUserInfo().setUserInfos() 触发初始化用户信息 pinia
|
||||
* @method useRequestOldRoutes().setRequestOldRoutes() 存储接口原始路由(未处理component),根据需求选择使用
|
||||
* @method setAddRoute 添加动态路由
|
||||
* @method setFilterMenuAndCacheTagsViewRoutes 设置路由到 vuex routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||
* @method setFilterMenuAndCacheTagsViewRoutes 设置路由到 pinia routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||
*/
|
||||
|
||||
export async function initBackEndControlRoutes() {
|
||||
// 界面 loading 动画开始执行
|
||||
if (window.nextLoading === undefined) NextLoading.start();
|
||||
|
|
@ -49,12 +48,12 @@ export async function initBackEndControlRoutes() {
|
|||
dynamicRoutes[0].children = await backEndComponent(res.data);
|
||||
// 添加动态路由
|
||||
await setAddRoute();
|
||||
// 设置路由到 vuex routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||
// 设置路由到 pinia routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||
await setFilterMenuAndCacheTagsViewRoutes();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置路由到 vuex routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||
* 设置路由到 pinia routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||
* @description 用于左侧菜单、横向菜单的显示
|
||||
* @description 用于 tagsView、菜单搜索中:未过滤隐藏的(isHide)
|
||||
*/
|
||||
|
|
@ -109,9 +108,9 @@ export function getBackEndControlRoutes() {
|
|||
const { userInfos } = storeToRefs(stores);
|
||||
const auth = userInfos.value.roles[0];
|
||||
// 管理员 admin
|
||||
if (auth === 'admin') return menuApi.getMenuAdmin();
|
||||
if (auth === 'admin') return menuApi.getAdminMenu();
|
||||
// 其它用户 test
|
||||
else return menuApi.getMenuTest();
|
||||
else return menuApi.getTestMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { storeToRefs } from 'pinia';
|
||||
import { formatTwoStageRoutes, formatFlatteningRoutes, router } from '/@/router/index';
|
||||
import { dynamicRoutes, notFoundAndNoPower } from '/@/router/route';
|
||||
import pinia from '../stores/index';
|
||||
import pinia from '/@/stores/index';
|
||||
import { Session } from '/@/utils/storage';
|
||||
import { useUserInfo } from '/@/stores/userInfo';
|
||||
import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
|
||||
|
|
@ -15,7 +15,7 @@ import { NextLoading } from '/@/utils/loading';
|
|||
* @method NextLoading 界面 loading 动画开始执行
|
||||
* @method useUserInfo(pinia).setUserInfos() 触发初始化用户信息 pinia
|
||||
* @method setAddRoute 添加动态路由
|
||||
* @method setFilterMenuAndCacheTagsViewRoutes 设置递归过滤有权限的路由到 vuex routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||
* @method setFilterMenuAndCacheTagsViewRoutes 设置递归过滤有权限的路由到 pinia routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||
*/
|
||||
export async function initFrontEndControlRoutes() {
|
||||
// 界面 loading 动画开始执行
|
||||
|
|
@ -27,7 +27,7 @@ export async function initFrontEndControlRoutes() {
|
|||
await useUserInfo(pinia).setUserInfos();
|
||||
// 添加动态路由
|
||||
await setAddRoute();
|
||||
// 设置递归过滤有权限的路由到 vuex routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||
// 设置递归过滤有权限的路由到 pinia routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||
await setFilterMenuAndCacheTagsViewRoutes();
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ export function setCacheTagsViewRoutes() {
|
|||
}
|
||||
|
||||
/**
|
||||
* 设置递归过滤有权限的路由到 vuex routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||
* 设置递归过滤有权限的路由到 pinia routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||
* @description 用于左侧菜单、横向菜单的显示
|
||||
* @description 用于 tagsView、菜单搜索中:未过滤隐藏的(isHide)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -91,11 +91,11 @@ export const useThemeConfig = defineStore('themeConfig', {
|
|||
// 是否开启 Footer 底部版权信息
|
||||
isFooter: true,
|
||||
// 是否开启灰色模式
|
||||
isGrayscale: false,
|
||||
isGrayscale: true,
|
||||
// 是否开启色弱模式
|
||||
isInvert: false,
|
||||
// 是否开启水印
|
||||
isWartermark: true,
|
||||
isWartermark: false,
|
||||
// 水印文案
|
||||
wartermarkText: 'vue-next-admin',
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ export const useThemeConfig = defineStore('themeConfig', {
|
|||
}),
|
||||
actions: {
|
||||
setThemeConfig(data) {
|
||||
this.themeConfig = data;
|
||||
this.themeConfig = data.themeConfig;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export const useUserInfo = defineStore('userInfo', {
|
|||
}),
|
||||
actions: {
|
||||
async setUserInfos() {
|
||||
// 存储用户信息到浏览器缓存
|
||||
if (Session.get('userInfo')) {
|
||||
this.userInfos = Session.get('userInfo');
|
||||
} else {
|
||||
|
|
@ -62,8 +63,6 @@ export const useUserInfo = defineStore('userInfo', {
|
|||
roles: defaultRoles,
|
||||
authBtnList: defaultAuthBtnList,
|
||||
};
|
||||
// 存储用户信息到浏览器缓存
|
||||
Session.set('userInfo', userInfos);
|
||||
resolve(userInfos);
|
||||
}, 0);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@
|
|||
--el-fill-color-light: var(--next-color-hover-rgba) !important;
|
||||
--el-bg-color-overlay: var(--el-color-primary-light-9) !important;
|
||||
--el-mask-color: rgb(42 42 42 / 80%);
|
||||
--el-fill-color-lighter: var(--next-color-hover-rgba) !important;
|
||||
|
||||
// button
|
||||
.el-button {
|
||||
|
|
@ -167,6 +168,12 @@
|
|||
.el-pagination.is-background .el-pager li {
|
||||
background-color: var(--next-bg-color);
|
||||
}
|
||||
/*深色模式时分页高亮问题*/
|
||||
.el-pagination.is-background .btn-next.is-active,
|
||||
.el-pagination.is-background .btn-prev.is-active,
|
||||
.el-pagination.is-background .el-pager li.is-active {
|
||||
color: var(--next-color-white) !important;
|
||||
}
|
||||
|
||||
// radio
|
||||
.el-radio-button:not(.is-active) .el-radio-button__inner {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
/* Button 按钮
|
||||
------------------------------- */
|
||||
// 第三方字体图标大小
|
||||
.el-button i.el-icon,
|
||||
.el-button:not(.is-circle) i.el-icon,
|
||||
.el-button i.iconfont,
|
||||
.el-button i.fa,
|
||||
.el-button--default i.iconfont,
|
||||
|
|
@ -283,6 +283,19 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
/* Pagination 分页
|
||||
------------------------------- */
|
||||
.el-pagination__editor {
|
||||
margin-right: 8px;
|
||||
}
|
||||
/*深色模式时分页高亮问题*/
|
||||
.el-pagination.is-background .btn-next.is-active,
|
||||
.el-pagination.is-background .btn-prev.is-active,
|
||||
.el-pagination.is-background .el-pager li.is-active {
|
||||
background-color: var(--el-color-primary) !important;
|
||||
color: var(--el-color-white) !important;
|
||||
}
|
||||
|
||||
/* Drawer 抽屉
|
||||
------------------------------- */
|
||||
.el-drawer {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
@import 'common/transition.scss';
|
||||
@import './other.scss';
|
||||
@import './element.scss';
|
||||
@import './iconSelector.scss';
|
||||
@import './media/media.scss';
|
||||
@import './waves.scss';
|
||||
@import './dark.scss';
|
||||
|
|
|
|||
|
|
@ -52,4 +52,8 @@
|
|||
color: #666666;
|
||||
}
|
||||
}
|
||||
// pagination 分页中的工具栏
|
||||
.table-footer-tool {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
.el-pagination__jump {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 默认居中对齐
|
||||
.el-pagination {
|
||||
text-align: center !important;
|
||||
.el-pagination,
|
||||
.table-footer {
|
||||
justify-content: center !important;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
.table-tool-popper {
|
||||
padding: 0 !important;
|
||||
.tool-box {
|
||||
display: flex;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
box-sizing: border-box;
|
||||
color: var(--el-text-color-primary);
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
}
|
||||
.tool-item {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
color: var(--el-text-color-primary);
|
||||
height: 35px;
|
||||
align-items: center;
|
||||
padding: var(--el-popover-padding);
|
||||
&:hover {
|
||||
background: var(--el-fill-color-lighter);
|
||||
}
|
||||
i {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import { formatDate } from '/@/utils/formatTime';
|
|||
|
||||
export default function () {
|
||||
const { toClipboard } = useClipboard();
|
||||
|
||||
// 百分比格式化
|
||||
const percentFormat = (row, column, cellValue) => {
|
||||
return cellValue ? `${cellValue}%` : '-';
|
||||
|
|
@ -42,11 +43,11 @@ export default function () {
|
|||
// 复制
|
||||
toClipboard(text);
|
||||
// 下面可以设置复制成功的提示框等操作
|
||||
ElMessage.success('复制成功!');
|
||||
ElMessage.success('复制成功!');
|
||||
resolve(text);
|
||||
} catch (e) {
|
||||
// 复制失败
|
||||
ElMessage.error('复制失败!');
|
||||
ElMessage.error('复制失败!');
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import { nextTick } from 'vue';
|
||||
import { nextTick, defineAsyncComponent } from 'vue';
|
||||
import * as svg from '@element-plus/icons-vue';
|
||||
import router from '/@/router/index';
|
||||
import pinia from '../stores/index';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import { Local } from '/@/utils/storage';
|
||||
import SvgIcon from '/@/components/svgIcon/index.vue';
|
||||
|
||||
// 引入组件
|
||||
const SvgIcon = defineAsyncComponent(() => import('/@/components/svgIcon/index.vue'));
|
||||
|
||||
/**
|
||||
* 导出全局注册 element plus svg 图标
|
||||
|
|
@ -150,6 +152,17 @@ export function handleEmpty(list) {
|
|||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开外部链接
|
||||
* @param val 当前点击项菜单
|
||||
*/
|
||||
export function handleOpenLink(val) {
|
||||
const { origin, pathname } = window.location;
|
||||
router.push(val.path);
|
||||
if (verifyUrl(val.meta?.isLink)) window.open(val.meta?.isLink);
|
||||
else window.open(`${origin}${pathname}#${val.meta?.isLink}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一批量导出
|
||||
* @method elSvg 导出全局注册 element plus svg 图标
|
||||
|
|
@ -160,6 +173,7 @@ export function handleEmpty(list) {
|
|||
* @method deepClone 对象深克隆
|
||||
* @method isMobile 判断是否是移动端
|
||||
* @method handleEmpty 判断数组对象中所有属性是否为空,为空则删除当前行对象
|
||||
* @method handleOpenLink 打开外部链接
|
||||
*/
|
||||
const other = {
|
||||
elSvg: (app) => {
|
||||
|
|
@ -186,6 +200,9 @@ const other = {
|
|||
handleEmpty: (list) => {
|
||||
return handleEmpty(list);
|
||||
},
|
||||
handleOpenLink: (val) => {
|
||||
handleOpenLink(val);
|
||||
},
|
||||
};
|
||||
|
||||
// 统一批量导出
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ service.interceptors.request.use(
|
|||
(config) => {
|
||||
// 在发送请求之前做些什么 token
|
||||
if (Session.get('token')) {
|
||||
config.headers.common['Authorization'] = `${Session.get('token')}`;
|
||||
config.headers['Authorization'] = `${Session.get('token')}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// 字体图标 url
|
||||
const cssCdnUrlList = ['//at.alicdn.com/t/font_2298093_y6u00apwst.css', '//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css'];
|
||||
const cssCdnUrlList = ['//at.alicdn.com/t/c/font_2298093_rnp72ifj3ba.css', '//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css'];
|
||||
// 第三方 js url
|
||||
const jsCdnUrlList = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,59 +1,63 @@
|
|||
import { ElMessage } from 'element-plus';
|
||||
|
||||
/**
|
||||
* hex颜色转rgb颜色
|
||||
* @param str 颜色值字符串
|
||||
* @returns 返回处理后的颜色值
|
||||
* 颜色转换函数
|
||||
* @method hexToRgb hex 颜色转 rgb 颜色
|
||||
* @method rgbToHex rgb 颜色转 Hex 颜色
|
||||
* @method getDarkColor 加深颜色值
|
||||
* @method getLightColor 变浅颜色值
|
||||
*/
|
||||
export function hexToRgb(str) {
|
||||
export function useChangeColor() {
|
||||
// str 颜色值字符串
|
||||
const hexToRgb = (str) => {
|
||||
let hexs = '';
|
||||
let reg = /^\#?[0-9A-Fa-f]{6}$/;
|
||||
if (!reg.test(str)) return ElMessage.warning('输入错误的hex');
|
||||
if (!reg.test(str)) {
|
||||
ElMessage.warning('输入错误的hex');
|
||||
return '';
|
||||
}
|
||||
str = str.replace('#', '');
|
||||
hexs = str.match(/../g);
|
||||
for (let i = 0; i < 3; i++) hexs[i] = parseInt(hexs[i], 16);
|
||||
return hexs;
|
||||
}
|
||||
|
||||
/**
|
||||
* rgb颜色转Hex颜色
|
||||
* @param r 代表红色
|
||||
* @param g 代表绿色
|
||||
* @param b 代表蓝色
|
||||
* @returns 返回处理后的颜色值
|
||||
*/
|
||||
export function rgbToHex(r, g, b) {
|
||||
};
|
||||
// r 代表红色 | g 代表绿色 | b 代表蓝色
|
||||
const rgbToHex = (r, g, b) => {
|
||||
let reg = /^\d{1,3}$/;
|
||||
if (!reg.test(r) || !reg.test(g) || !reg.test(b)) return ElMessage.warning('输入错误的rgb颜色值');
|
||||
if (!reg.test(r) || !reg.test(g) || !reg.test(b)) {
|
||||
ElMessage.warning('输入错误的rgb颜色值');
|
||||
return '';
|
||||
}
|
||||
let hexs = [r.toString(16), g.toString(16), b.toString(16)];
|
||||
for (let i = 0; i < 3; i++) if (hexs[i].length == 1) hexs[i] = `0${hexs[i]}`;
|
||||
return `#${hexs.join('')}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加深颜色值
|
||||
* @param color 颜色值字符串
|
||||
* @param level 加深的程度,限0-1之间
|
||||
* @returns 返回处理后的颜色值
|
||||
*/
|
||||
export function getDarkColor(color, level) {
|
||||
};
|
||||
// color 颜色值字符串 | level 变浅的程度,限0-1之间
|
||||
const getDarkColor = (color, level) => {
|
||||
let reg = /^\#?[0-9A-Fa-f]{6}$/;
|
||||
if (!reg.test(color)) return ElMessage.warning('输入错误的hex颜色值');
|
||||
let rgb = hexToRgb(color);
|
||||
if (!reg.test(color)) {
|
||||
ElMessage.warning('输入错误的hex颜色值');
|
||||
return '';
|
||||
}
|
||||
let rgb = useChangeColor().hexToRgb(color);
|
||||
for (let i = 0; i < 3; i++) rgb[i] = Math.floor(rgb[i] * (1 - level));
|
||||
return rgbToHex(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 变浅颜色值
|
||||
* @param color 颜色值字符串
|
||||
* @param level 加深的程度,限0-1之间
|
||||
* @returns 返回处理后的颜色值
|
||||
*/
|
||||
export function getLightColor(color, level) {
|
||||
return useChangeColor().rgbToHex(rgb[0], rgb[1], rgb[2]);
|
||||
};
|
||||
// color 颜色值字符串 | level 加深的程度,限0-1之间
|
||||
const getLightColor = (color, level) => {
|
||||
let reg = /^\#?[0-9A-Fa-f]{6}$/;
|
||||
if (!reg.test(color)) return ElMessage.warning('输入错误的hex颜色值');
|
||||
let rgb = hexToRgb(color);
|
||||
for (let i = 0; i < 3; i++) rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i]);
|
||||
return rgbToHex(rgb[0], rgb[1], rgb[2]);
|
||||
if (!reg.test(color)) {
|
||||
ElMessage.warning('输入错误的hex颜色值');
|
||||
return '';
|
||||
}
|
||||
let rgb = useChangeColor().hexToRgb(color);
|
||||
for (let i = 0; i < 3; i++) rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i]);
|
||||
return useChangeColor().rgbToHex(rgb[0], rgb[1], rgb[2]);
|
||||
};
|
||||
return {
|
||||
hexToRgb,
|
||||
rgbToHex,
|
||||
getDarkColor,
|
||||
getLightColor,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="401">
|
||||
<script setup name="noPower">
|
||||
import { Session } from '/@/utils/storage';
|
||||
|
||||
// 重新授权
|
||||
|
|
|
|||
|
|
@ -22,8 +22,10 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="404">
|
||||
<script setup name="notFound">
|
||||
// 定义变量内容
|
||||
const router = useRouter();
|
||||
|
||||
// 返回首页
|
||||
const onGoHome = () => {
|
||||
router.push('/');
|
||||
|
|
|
|||
|
|
@ -71,13 +71,7 @@ import { storeToRefs } from 'pinia';
|
|||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
|
||||
|
||||
const globalHome = {
|
||||
homeChartOne: null,
|
||||
homeChartTwo: null,
|
||||
homeCharThree: null,
|
||||
dispose: [null, '', undefined],
|
||||
};
|
||||
|
||||
// 定义变量内容
|
||||
const homeLineRef = ref();
|
||||
const homePieRef = ref();
|
||||
const homeBarRef = ref();
|
||||
|
|
@ -86,6 +80,12 @@ const storesThemeConfig = useThemeConfig();
|
|||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes);
|
||||
const state = reactive({
|
||||
global: {
|
||||
homeChartOne: null,
|
||||
homeChartTwo: null,
|
||||
homeCharThree: null,
|
||||
dispose: [null, '', undefined],
|
||||
},
|
||||
homeOne: [
|
||||
{
|
||||
num1: '125,12',
|
||||
|
|
@ -190,8 +190,8 @@ const state = reactive({
|
|||
|
||||
// 折线图
|
||||
const initLineChart = () => {
|
||||
if (!globalHome.dispose.some((b) => b === globalHome.homeChartOne)) globalHome.homeChartOne.dispose();
|
||||
globalHome.homeChartOne = echarts.init(homeLineRef.value, state.charts.theme);
|
||||
if (!state.global.dispose.some((b) => b === state.global.homeChartOne)) state.global.homeChartOne.dispose();
|
||||
state.global.homeChartOne = markRaw(echarts.init(homeLineRef.value, state.charts.theme));
|
||||
const option = {
|
||||
backgroundColor: state.charts.bgColor,
|
||||
title: {
|
||||
|
|
@ -267,13 +267,13 @@ const initLineChart = () => {
|
|||
},
|
||||
],
|
||||
};
|
||||
globalHome.homeChartOne.setOption(option);
|
||||
state.myCharts.push(globalHome.homeChartOne);
|
||||
state.global.homeChartOne.setOption(option);
|
||||
state.myCharts.push(state.global.homeChartOne);
|
||||
};
|
||||
// 饼图
|
||||
const initPieChart = () => {
|
||||
if (!globalHome.dispose.some((b) => b === globalHome.homeChartTwo)) globalHome.homeChartTwo.dispose();
|
||||
globalHome.homeChartTwo = echarts.init(homePieRef.value, state.charts.theme);
|
||||
if (!state.global.dispose.some((b) => b === state.global.homeChartTwo)) state.global.homeChartTwo.dispose();
|
||||
state.global.homeChartTwo = markRaw(echarts.init(homePieRef.value, state.charts.theme));
|
||||
var getname = ['房屋及结构物', '专用设备', '通用设备', '文物和陈列品', '图书、档案'];
|
||||
var getvalue = [34.2, 38.87, 17.88, 9.05, 2.05];
|
||||
var data = [];
|
||||
|
|
@ -352,13 +352,13 @@ const initPieChart = () => {
|
|||
},
|
||||
],
|
||||
};
|
||||
globalHome.homeChartTwo.setOption(option);
|
||||
state.myCharts.push(globalHome.homeChartTwo);
|
||||
state.global.homeChartTwo.setOption(option);
|
||||
state.myCharts.push(state.global.homeChartTwo);
|
||||
};
|
||||
// 柱状图
|
||||
const initBarChart = () => {
|
||||
if (!globalHome.dispose.some((b) => b === globalHome.homeCharThree)) globalHome.homeCharThree.dispose();
|
||||
globalHome.homeCharThree = echarts.init(homeBarRef.value, state.charts.theme);
|
||||
if (!state.global.dispose.some((b) => b === state.global.homeCharThree)) state.global.homeCharThree.dispose();
|
||||
state.global.homeCharThree = markRaw(echarts.init(homeBarRef.value, state.charts.theme));
|
||||
const option = {
|
||||
backgroundColor: state.charts.bgColor,
|
||||
title: {
|
||||
|
|
@ -483,8 +483,8 @@ const initBarChart = () => {
|
|||
},
|
||||
],
|
||||
};
|
||||
globalHome.homeCharThree.setOption(option);
|
||||
state.myCharts.push(globalHome.homeCharThree);
|
||||
state.global.homeCharThree.setOption(option);
|
||||
state.myCharts.push(state.global.homeCharThree);
|
||||
};
|
||||
// 批量设置 echarts resize
|
||||
const initEchartsResizeFun = () => {
|
||||
|
|
@ -508,14 +508,14 @@ onMounted(() => {
|
|||
onActivated(() => {
|
||||
initEchartsResizeFun();
|
||||
});
|
||||
// 监听 vuex 中的 tagsview 开启全屏变化,重新 resize 图表,防止不出现/大小不变等
|
||||
// 监听 pinia 中的 tagsview 开启全屏变化,重新 resize 图表,防止不出现/大小不变等
|
||||
watch(
|
||||
() => isTagsViewCurrenFull.value,
|
||||
() => {
|
||||
initEchartsResizeFun();
|
||||
}
|
||||
);
|
||||
// 监听 vuex 中是否开启深色主题
|
||||
// 监听 pinia 中是否开启深色主题
|
||||
watch(
|
||||
() => themeConfig.value.isIsDark,
|
||||
(isIsDark) => {
|
||||
|
|
@ -585,7 +585,7 @@ $homeNavLengh: 8;
|
|||
animation-name: error-num;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: calc($i/10) + s;
|
||||
animation-delay: calc($i/4) + s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ import { Session } from '/@/utils/storage';
|
|||
import { formatAxis } from '/@/utils/formatTime';
|
||||
import { NextLoading } from '/@/utils/loading';
|
||||
|
||||
// 定义变量内容
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
const route = useRoute();
|
||||
|
|
@ -69,6 +70,7 @@ const state = reactive({
|
|||
signIn: false,
|
||||
},
|
||||
});
|
||||
|
||||
// 时间获取
|
||||
const currentTime = computed(() => {
|
||||
return formatAxis(new Date());
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
</template>
|
||||
|
||||
<script setup name="loginMobile">
|
||||
// 定义变量内容
|
||||
const state = reactive({
|
||||
ruleForm: {
|
||||
userName: '',
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@
|
|||
<script setup name="loginScan">
|
||||
import QRCode from 'qrcodejs2-fixes';
|
||||
|
||||
// 定义变量内容
|
||||
const qrcodeRef = ref(null);
|
||||
|
||||
// 初始化生成二维码
|
||||
const initQrcode = () => {
|
||||
nextTick(() => {
|
||||
|
|
|
|||
|
|
@ -50,16 +50,19 @@ import logoMini from '/@/assets/logo-mini.svg';
|
|||
import loginMain from '/@/assets/login-main.svg';
|
||||
import loginBg from '/@/assets/login-bg.svg';
|
||||
|
||||
// 引入组件
|
||||
const Account = defineAsyncComponent(() => import('/@/views/login/component/account.vue'));
|
||||
const Mobile = defineAsyncComponent(() => import('/@/views/login/component/mobile.vue'));
|
||||
const Scan = defineAsyncComponent(() => import('/@/views/login/component/scan.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
const state = reactive({
|
||||
tabsActiveName: 'account',
|
||||
isScan: false,
|
||||
});
|
||||
|
||||
// 获取布局配置信息
|
||||
const getThemeConfig = computed(() => {
|
||||
return themeConfig.value;
|
||||
|
|
@ -202,6 +205,7 @@ onMounted(() => {
|
|||
letter-spacing: 3px;
|
||||
animation: logoAnimation 0.3s ease;
|
||||
animation-delay: 0.3s;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
.login-right-warp-main-form {
|
||||
flex: 1;
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@
|
|||
</template>
|
||||
|
||||
<script setup name="systemAddDept">
|
||||
// 定义变量内容
|
||||
const state = reactive({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
|
|
@ -82,6 +83,7 @@ const state = reactive({
|
|||
},
|
||||
deptData: [], // 部门数据
|
||||
});
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = () => {
|
||||
state.isShowDialog = true;
|
||||
|
|
@ -104,7 +106,7 @@ const initTableData = () => {
|
|||
deptName: 'vueNextAdmin',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '顶级部门',
|
||||
id: Math.random(),
|
||||
children: [
|
||||
|
|
@ -112,7 +114,7 @@ const initTableData = () => {
|
|||
deptName: 'IT外包服务',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '总部',
|
||||
id: Math.random(),
|
||||
},
|
||||
|
|
@ -120,7 +122,7 @@ const initTableData = () => {
|
|||
deptName: '资本控股',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '分部',
|
||||
id: Math.random(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -67,7 +67,8 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="logsystemEditDeptin">
|
||||
<script setup name="systemEditDept">
|
||||
// 定义变量内容
|
||||
const state = reactive({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
|
|
@ -82,6 +83,7 @@ const state = reactive({
|
|||
},
|
||||
deptData: [], // 部门数据
|
||||
});
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = (row) => {
|
||||
row.deptLevel = ['vueNextAdmin'];
|
||||
|
|
@ -109,7 +111,7 @@ const initTableData = () => {
|
|||
deptName: 'vueNextAdmin',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '顶级部门',
|
||||
id: Math.random(),
|
||||
children: [
|
||||
|
|
@ -117,7 +119,7 @@ const initTableData = () => {
|
|||
deptName: 'IT外包服务',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '总部',
|
||||
id: Math.random(),
|
||||
},
|
||||
|
|
@ -125,7 +127,7 @@ const initTableData = () => {
|
|||
deptName: '资本控股',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '分部',
|
||||
id: Math.random(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -54,9 +54,11 @@
|
|||
<script setup name="systemDept">
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
|
||||
// 引入组件
|
||||
const AddDept = defineAsyncComponent(() => import('/@/views/system/dept/component/addDept.vue'));
|
||||
const EditDept = defineAsyncComponent(() => import('/@/views/system/dept/component/editDept.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const addDeptRef = ref();
|
||||
const editDeptRef = ref();
|
||||
const state = reactive({
|
||||
|
|
@ -70,13 +72,14 @@ const state = reactive({
|
|||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
state.tableData.data.push({
|
||||
deptName: 'vueNextAdmin',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '顶级部门',
|
||||
id: Math.random(),
|
||||
children: [
|
||||
|
|
@ -84,7 +87,7 @@ const initTableData = () => {
|
|||
deptName: 'IT外包服务',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '总部',
|
||||
id: Math.random(),
|
||||
},
|
||||
|
|
@ -92,7 +95,7 @@ const initTableData = () => {
|
|||
deptName: '资本控股',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '分部',
|
||||
id: Math.random(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="字段名">
|
||||
<el-input v-model="state.ruleForm.fieldName" placeholder="请输入字段名,拼接 state.ruleForm.list" clearable></el-input>
|
||||
<el-input v-model="state.ruleForm.fieldName" placeholder="请输入字段名,拼接 ruleForm.list" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
|
|
@ -64,24 +64,18 @@
|
|||
</template>
|
||||
|
||||
<script setup name="systemAddDic">
|
||||
// 定义变量内容
|
||||
const state = reactive({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
dicName: '', // 字典名称
|
||||
fieldName: '', // 字段名
|
||||
status: true, // 字典状态
|
||||
list: [
|
||||
// 子集字段 + 属性值
|
||||
{
|
||||
id: Math.random(),
|
||||
label: '',
|
||||
value: '',
|
||||
},
|
||||
],
|
||||
list: [], // 子集字段 + 属性值
|
||||
describe: '', // 字典描述
|
||||
fieldNameList: [], // 字段名: [{子集字段 + 属性值}]
|
||||
},
|
||||
});
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = () => {
|
||||
state.isShowDialog = true;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||
<el-form-item label="字段名">
|
||||
<el-input v-model="state.ruleForm.fieldName" placeholder="请输入字段名,拼接 state.ruleForm.list" clearable></el-input>
|
||||
<el-input v-model="state.ruleForm.fieldName" placeholder="请输入字段名,拼接 ruleForm.list" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||
|
|
@ -64,24 +64,18 @@
|
|||
</template>
|
||||
|
||||
<script setup name="systemEditDic">
|
||||
// 定义变量内容
|
||||
const state = reactive({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
dicName: '', // 字典名称
|
||||
fieldName: '', // 字段名
|
||||
status: true, // 字典状态
|
||||
list: [
|
||||
// 子集字段 + 属性值
|
||||
{
|
||||
id: Math.random(),
|
||||
label: '',
|
||||
value: '',
|
||||
},
|
||||
],
|
||||
list: [], // 子集字段 + 属性值
|
||||
describe: '', // 字典描述
|
||||
fieldNameList: [], // 字段名: [{子集字段 + 属性值}]
|
||||
},
|
||||
});
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = (row) => {
|
||||
if (row.fieldName === 'SYS_UERINFO') {
|
||||
|
|
|
|||
|
|
@ -57,9 +57,11 @@
|
|||
<script setup name="systemDic">
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
|
||||
// 引入组件
|
||||
const AddDic = defineAsyncComponent(() => import('/@/views/system/dic/component/addDic.vue'));
|
||||
const EditDic = defineAsyncComponent(() => import('/@/views/system/dic/component/editDic.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const addDicRef = ref();
|
||||
const editDicRef = ref();
|
||||
const state = reactive({
|
||||
|
|
@ -73,6 +75,7 @@ const state = reactive({
|
|||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
const data = [];
|
||||
|
|
@ -83,6 +86,7 @@ const initTableData = () => {
|
|||
describe: i === 0 ? '这是角色字典' : '这是用户性别字典',
|
||||
status: true,
|
||||
createTime: new Date().toLocaleString(),
|
||||
list: [],
|
||||
});
|
||||
}
|
||||
state.tableData.data = data;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
v-model="state.ruleForm.meta.isLink"
|
||||
placeholder="外链/内嵌时链接地址(http:xxx.com)"
|
||||
clearable
|
||||
:disabled="state.ruleForm.isLink === '' || !state.ruleForm.isLink"
|
||||
:disabled="!state.ruleForm.isLink"
|
||||
>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
|
@ -148,9 +148,12 @@
|
|||
<script setup name="systemAddMenu">
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useRoutesList } from '/@/stores/routesList';
|
||||
import IconSelector from '/@/components/iconSelector/index.vue';
|
||||
// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd";
|
||||
|
||||
// 引入组件
|
||||
const IconSelector = defineAsyncComponent(() => import('/@/components/iconSelector/index.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const stores = useRoutesList();
|
||||
const { routesList } = storeToRefs(stores);
|
||||
const state = reactive({
|
||||
|
|
@ -173,17 +176,18 @@ const state = reactive({
|
|||
isAffix: false, // 是否固定
|
||||
isLink: '', // 外链/内嵌时链接地址(http:xxx.com),开启外链条件,`1、isLink: 链接地址不为空`
|
||||
isIframe: false, // 是否内嵌,开启条件,`1、isIframe:true 2、isLink:链接地址不为空`
|
||||
roles: '', // 权限标识,取角色管理
|
||||
},
|
||||
btnPower: '', // 菜单类型为按钮时,权限标识
|
||||
},
|
||||
menuData: [], // 上级菜单数据
|
||||
});
|
||||
// 获取 vuex 中的路由
|
||||
|
||||
// 获取 pinia 中的路由
|
||||
const getMenuData = (routes) => {
|
||||
const arr = [];
|
||||
routes.map((val) => {
|
||||
val['title'] = val.meta.title;
|
||||
val['id'] = Math.random();
|
||||
val['title'] = val.meta?.title;
|
||||
arr.push({ ...val });
|
||||
if (val.children) getMenuData(val.children);
|
||||
});
|
||||
|
|
@ -199,11 +203,8 @@ const closeDialog = () => {
|
|||
};
|
||||
// 是否内嵌下拉改变
|
||||
const onSelectIframeChange = () => {
|
||||
if (state.ruleForm.meta.isIframe) {
|
||||
state.ruleForm.isLink = true;
|
||||
} else {
|
||||
state.ruleForm.isLink = '';
|
||||
}
|
||||
if (state.ruleForm.meta.isIframe) state.ruleForm.isLink = true;
|
||||
else state.ruleForm.isLink = false;
|
||||
};
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
v-model="state.ruleForm.meta.isLink"
|
||||
placeholder="外链/内嵌时链接地址(http:xxx.com)"
|
||||
clearable
|
||||
:disabled="state.ruleForm.isLink === '' || !state.ruleForm.isLink"
|
||||
:disabled="!state.ruleForm.isLink"
|
||||
>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
|
@ -148,9 +148,12 @@
|
|||
<script setup name="systemEditMenu">
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useRoutesList } from '/@/stores/routesList';
|
||||
import IconSelector from '/@/components/iconSelector/index.vue';
|
||||
// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd";
|
||||
|
||||
// 引入组件
|
||||
const IconSelector = defineAsyncComponent(() => import('/@/components/iconSelector/index.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const stores = useRoutesList();
|
||||
const { routesList } = storeToRefs(stores);
|
||||
const state = reactive({
|
||||
|
|
@ -179,12 +182,12 @@ const state = reactive({
|
|||
},
|
||||
menuData: [], // 上级菜单数据
|
||||
});
|
||||
// 获取 vuex 中的路由
|
||||
|
||||
// 获取 pinia 中的路由
|
||||
const getMenuData = (routes) => {
|
||||
const arr = [];
|
||||
routes.map((val) => {
|
||||
val['title'] = val.meta.title;
|
||||
val['id'] = Math.random();
|
||||
val['title'] = val.meta?.title;
|
||||
arr.push({ ...val });
|
||||
if (val.children) getMenuData(val.children);
|
||||
});
|
||||
|
|
@ -208,11 +211,8 @@ const closeDialog = () => {
|
|||
};
|
||||
// 是否内嵌下拉改变
|
||||
const onSelectIframeChange = () => {
|
||||
if (state.ruleForm.meta.isIframe) {
|
||||
state.ruleForm.isLink = true;
|
||||
} else {
|
||||
state.ruleForm.isLink = '';
|
||||
}
|
||||
if (state.ruleForm.meta.isIframe) state.ruleForm.isLink = true;
|
||||
else state.ruleForm.isLink = false;
|
||||
};
|
||||
// 取消
|
||||
const onCancel = () => {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
</el-table-column>
|
||||
<el-table-column label="操作" show-overflow-tooltip width="140">
|
||||
<template #default="scope">
|
||||
<el-button size="small" text type="primary" @click="onOpenAddMenu(scope.row)">新增</el-button>
|
||||
<el-button size="small" text type="primary" @click="onOpenAddMenu">新增</el-button>
|
||||
<el-button size="small" text type="primary" @click="onOpenEditMenu(scope.row)">修改</el-button>
|
||||
<el-button size="small" text type="primary" @click="onTabelRowDel(scope.row)">删除</el-button>
|
||||
</template>
|
||||
|
|
@ -59,17 +59,20 @@
|
|||
</template>
|
||||
|
||||
<script setup name="systemMenu">
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useRoutesList } from '/@/stores/routesList';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
|
||||
// 引入组件
|
||||
const AddMenu = defineAsyncComponent(() => import('/@/views/system/menu/component/addMenu.vue'));
|
||||
const EditMenu = defineAsyncComponent(() => import('/@/views/system/menu/component/editMenu.vue'));
|
||||
|
||||
const addMenuRef = ref();
|
||||
const editMenuRef = ref();
|
||||
// 定义变量内容
|
||||
const stores = useRoutesList();
|
||||
const { routesList } = storeToRefs(stores);
|
||||
const addMenuRef = ref();
|
||||
const editMenuRef = ref();
|
||||
|
||||
// 获取 pinia 中的路由
|
||||
const menuTableData = computed(() => {
|
||||
return routesList.value;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
</template>
|
||||
|
||||
<script setup name="systemAddRole">
|
||||
// 定义变量内容
|
||||
const state = reactive({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
|
|
@ -66,6 +67,7 @@ const state = reactive({
|
|||
label: 'label',
|
||||
},
|
||||
});
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = () => {
|
||||
state.isShowDialog = true;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@
|
|||
</template>
|
||||
|
||||
<script setup name="systemEditRole">
|
||||
// 定义变量内容
|
||||
const state = reactive({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
|
|
@ -73,6 +74,7 @@ const state = reactive({
|
|||
label: 'label',
|
||||
},
|
||||
});
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = (row) => {
|
||||
state.ruleForm = row;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<div class="system-role-container layout-padding">
|
||||
<div class="system-role-padding layout-padding-auto layout-padding-view">
|
||||
<div class="system-user-search mb15">
|
||||
<el-input size="default" placeholder="请输入角色名称" style="max-width: 180px"> </el-input>
|
||||
<el-input v-model="state.tableData.param.search" size="default" placeholder="请输入角色名称" style="max-width: 180px"> </el-input>
|
||||
<el-button size="default" type="primary" class="ml10">
|
||||
<el-icon>
|
||||
<ele-Search />
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
</el-button>
|
||||
</div>
|
||||
<el-table :data="state.tableData.data" style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="50" />
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column prop="roleName" label="角色名称" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="roleSign" label="角色标识" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="sort" label="排序" show-overflow-tooltip></el-table-column>
|
||||
|
|
@ -51,18 +51,20 @@
|
|||
:total="state.tableData.total"
|
||||
>
|
||||
</el-pagination>
|
||||
</div>
|
||||
<AddRole ref="addRoleRef" />
|
||||
<EditRole ref="editRoleRef" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="systemRole">
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
|
||||
// 引入组件
|
||||
const AddRole = defineAsyncComponent(() => import('/@/views/system/role/component/addRole.vue'));
|
||||
const EditRole = defineAsyncComponent(() => import('/@/views/system/role/component/editRole.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const addRoleRef = ref();
|
||||
const editRoleRef = ref();
|
||||
const state = reactive({
|
||||
|
|
@ -71,19 +73,17 @@ const state = reactive({
|
|||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
search: '',
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
},
|
||||
formInline: {
|
||||
user: '',
|
||||
region: '',
|
||||
},
|
||||
});
|
||||
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
const data = [];
|
||||
for (let i = 0; i < 2; i++) {
|
||||
for (let i = 0; i < 20; i++) {
|
||||
data.push({
|
||||
roleName: i === 0 ? '超级管理员' : '普通用户',
|
||||
roleSign: i === 0 ? 'admin' : 'common',
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@
|
|||
</template>
|
||||
|
||||
<script setup name="systemAddUser">
|
||||
// 定义变量内容
|
||||
const state = reactive({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
|
|
@ -106,6 +107,7 @@ const state = reactive({
|
|||
},
|
||||
deptData: [], // 部门数据
|
||||
});
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = () => {
|
||||
state.isShowDialog = true;
|
||||
|
|
@ -128,7 +130,7 @@ const initTableData = () => {
|
|||
deptName: 'vueNextAdmin',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '顶级部门',
|
||||
id: Math.random(),
|
||||
children: [
|
||||
|
|
@ -136,7 +138,7 @@ const initTableData = () => {
|
|||
deptName: 'IT外包服务',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '总部',
|
||||
id: Math.random(),
|
||||
},
|
||||
|
|
@ -144,7 +146,7 @@ const initTableData = () => {
|
|||
deptName: '资本控股',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '分部',
|
||||
id: Math.random(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@
|
|||
</template>
|
||||
|
||||
<script setup name="systemEditUser">
|
||||
// 定义变量内容
|
||||
const state = reactive({
|
||||
isShowDialog: false,
|
||||
ruleForm: {
|
||||
|
|
@ -106,6 +107,7 @@ const state = reactive({
|
|||
},
|
||||
deptData: [], // 部门数据
|
||||
});
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = (row) => {
|
||||
state.ruleForm = row;
|
||||
|
|
@ -129,7 +131,7 @@ const initTableData = () => {
|
|||
deptName: 'vueNextAdmin',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '顶级部门',
|
||||
id: Math.random(),
|
||||
children: [
|
||||
|
|
@ -137,7 +139,7 @@ const initTableData = () => {
|
|||
deptName: 'IT外包服务',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '总部',
|
||||
id: Math.random(),
|
||||
},
|
||||
|
|
@ -145,7 +147,7 @@ const initTableData = () => {
|
|||
deptName: '资本控股',
|
||||
createTime: new Date().toLocaleString(),
|
||||
status: true,
|
||||
sort: Number.parseInt(Math.random()),
|
||||
sort: Math.random(),
|
||||
describe: '分部',
|
||||
id: Math.random(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
</el-button>
|
||||
</div>
|
||||
<el-table :data="state.tableData.data" style="width: 100%">
|
||||
<el-table-column type="index" label="序号" width="50" />
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column prop="userName" label="账户名称" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="userNickname" label="用户昵称" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="roleSign" label="关联角色" show-overflow-tooltip></el-table-column>
|
||||
|
|
@ -61,9 +61,11 @@
|
|||
<script setup name="systemUser">
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
|
||||
// 引入组件
|
||||
const AddUer = defineAsyncComponent(() => import('/@/views/system/user/component/addUser.vue'));
|
||||
const EditUser = defineAsyncComponent(() => import('/@/views/system/user/component/editUser.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const addUserRef = ref();
|
||||
const editUserRef = ref();
|
||||
const state = reactive({
|
||||
|
|
@ -77,6 +79,7 @@ const state = reactive({
|
|||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
const data = [];
|
||||
|
|
@ -132,3 +135,17 @@ onMounted(() => {
|
|||
initTableData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.system-user-container {
|
||||
:deep(.el-card__body) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
.el-table {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ const viteConfig = defineConfig((mode) => {
|
|||
},
|
||||
},
|
||||
css: { preprocessorOptions: { css: { charset: false } } },
|
||||
define: {
|
||||
__VERSION__: JSON.stringify(process.env.npm_package_version),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue