mirror of
https://gitee.com/lyt-top/vue-next-admin
synced 2026-07-04 13:02:39 +08:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1cbc0f1b4e | |||
| bf9fce206a | |||
| 9195d8367f | |||
| 1b3600f394 | |||
| 16823b2ef7 | |||
| 9d794f2309 | |||
| bd8ac2cc94 | |||
| 2b9506845c | |||
| d2d83fd70b | |||
| 56139e72a7 | |||
| 07e0f742d8 | |||
| c09b154a3f | |||
| 6e59014357 | |||
| 02e7c49750 | |||
| 7b26cb21dd | |||
| bfecc6f6d2 | |||
| 14981044b9 | |||
| 8ed7986a96 | |||
| 852075ccfb | |||
| ba80b9bc76 | |||
| 4f8f13a722 |
@ -1,5 +1,5 @@
|
|||||||
# 本地环境
|
# 本地环境
|
||||||
ENV = 'development'
|
ENV = development
|
||||||
|
|
||||||
# 本地环境接口地址
|
# 本地环境接口地址
|
||||||
VITE_API_URL = 'http://localhost:8888/'
|
VITE_API_URL = http://localhost:8888/
|
||||||
@ -1,5 +1,5 @@
|
|||||||
# 线上环境
|
# 线上环境
|
||||||
ENV = 'production'
|
ENV = production
|
||||||
|
|
||||||
# 线上环境接口地址
|
# 线上环境接口地址
|
||||||
VITE_API_URL = 'https://lyt-top.gitee.io/vue-next-admin-preview/'
|
VITE_API_URL = https://lyt-top.gitee.io/vue-next-admin-preview/
|
||||||
49
CHANGELOG.md
49
CHANGELOG.md
@ -2,6 +2,55 @@
|
|||||||
|
|
||||||
🎉🎉🔥 `vue-next-admin` 基于 vue3.x 、Typescript、vite、Element plus 等,适配手机、平板、pc 的后台开源免费模板库(vue2.x 请切换 vue-prev-admin 分支)
|
🎉🎉🔥 `vue-next-admin` 基于 vue3.x 、Typescript、vite、Element plus 等,适配手机、平板、pc 的后台开源免费模板库(vue2.x 请切换 vue-prev-admin 分支)
|
||||||
|
|
||||||
|
## 2.4.3
|
||||||
|
|
||||||
|
`2023.02.22`
|
||||||
|
|
||||||
|
🚩🚩🚩 感谢 [驰骋工作流引擎-表单引擎-低代码开发平台](http://www.ccflow.org/) 赞助商的赞助。驰骋公司为社会提供流程引擎+表单引擎+低代码开发平台一体的开源软件解决方案,欢迎广大开发者前去体验!
|
||||||
|
|
||||||
|
- 🌟 更新 依赖更新最新版本
|
||||||
|
- 🎉 新增 赞助商组件(`/src/layout/sponsors`),[项目目录结构查看](https://lyt-top.gitee.io/vue-next-admin-doc-preview/config/)
|
||||||
|
- 🐞 修复 [过滤筛选组件展开点击不了](https://gitee.com/lyt-top/vue-next-admin/issues/I688WG)
|
||||||
|
- 🐞 修复 [设置锁屏时间时直接白屏了不能恢复,除非删除主题配置才会重新加载](https://gitee.com/lyt-top/vue-next-admin/issues/I6AF8P),感谢[@baizunxian](https://gitee.com/xb_xiaobai)
|
||||||
|
- 🐞 修复 `分栏布局` 地址栏输入不存在的路由报错问题
|
||||||
|
- 🎨 合并 [!44 tagsViewName 正则匹配错误,匹配到含 en 单词](https://gitee.com/lyt-top/vue-next-admin/pulls/44/files),感谢[@tony 星](https://gitee.com/tony_tong_xin)
|
||||||
|
- 🎨 合并 [!45 fix 地址栏出现 false 问题](https://gitee.com/lyt-top/vue-next-admin/pulls/45),感谢[@随心](https://gitee.com/jiangqiang1996)
|
||||||
|
- 🎯 优化 `/src/utils/storage` 下 `key` 编写成 `${__NEXT_NAME__}:${key}`,防止部署多套系统到同一域名不同目录时,变量共用的问题(`__NEXT_NAME__`为 `package.json` 中的 `name`)
|
||||||
|
- 🎯 优化 watermark 单词拼写错误
|
||||||
|
|
||||||
|
## 2.4.21
|
||||||
|
|
||||||
|
`2022.12.12`
|
||||||
|
|
||||||
|
- 🌟 更新 依赖更新最新版本
|
||||||
|
- 🎉 新增 菜单背景高亮颜色可自定义,通过 `布局配置 -> 菜单设置 -> 菜单高亮背景色` 进行设置
|
||||||
|
- 🐞 修复 `分栏布局` 二级导航菜单内容多时,无法滚动问题,感谢群友@静雨轩主人
|
||||||
|
- 🐞 修复 [!42 修复 工作流无法添加新节点问题](https://gitee.com/lyt-top/vue-next-admin/pulls/42),感谢[@beta](https://gitee.com/beta_dz)
|
||||||
|
- 🎯 优化 `/make/tableDemo` 表头很多时,无法滚动问题,感谢群友@糊涂涂涂
|
||||||
|
|
||||||
|
## 2.4.2
|
||||||
|
|
||||||
|
`2022.12.09`
|
||||||
|
|
||||||
|
- 🌟 更新 依赖更新最新版本
|
||||||
|
- 🎉 新增 国际化自动导入文件功能,只需在 `/src/i18n/pages` 下新建文件夹定义即可
|
||||||
|
- 🎉 新增 `/make/tableDemo` 中 [搜索框展开,收缩功能,高级筛选组件 有计划做吗](https://gitee.com/lyt-top/vue-next-admin/issues/I6511L)
|
||||||
|
- 🐞 修复 [!40 开启 TagsView 缓存后,刷新后所有的路由都变成组件缓存了](https://gitee.com/lyt-top/vue-next-admin/pulls/40),感谢[@mrjimin](https://gitee.com/mrjimin)
|
||||||
|
- 🐞 修复 [!41 修复 get 请求传递嵌套对象或数组时无法正常编码问题](https://gitee.com/lyt-top/vue-next-admin/pulls/41),感谢[@随心](https://gitee.com/jiangqiang1996)
|
||||||
|
- 🐞 修复 组件 wangEditor 回显值的问题
|
||||||
|
- 🐞 修复 `/fun/echartsMap`(地理坐标/地图)、`visualizingDemo2`(数据可视化演示 2) 演示报错问题
|
||||||
|
- 🎯 优化 版本升级提示
|
||||||
|
- 🎯 优化 无权限登录时增加提示信息,[BUG:因前端加载路由(initFrontEndControlRoutes)中当前用户角色为一个陌生角色, 导致 router.beforeEach 会死循环 浏览器崩溃](https://gitee.com/lyt-top/vue-next-admin/issues/I64HVO),感谢[@canroc](https://gitee.com/canroc)、[@随心](https://gitee.com/jiangqiang1996)
|
||||||
|
- 🌈 重构 `/views/system` 新增修改组件合并。[可以把新增修改组件合并成一个吧](https://gitee.com/lyt-top/vue-next-admin/issues/I64WES)
|
||||||
|
- 🌈 重构 图标选择器,[图标选择器没办法筛选,只能筛选 ali 的](https://gitee.com/lyt-top/vue-next-admin/issues/I64HZD),感谢[@随心](https://gitee.com/jiangqiang1996)
|
||||||
|
|
||||||
|
## 2.4.1
|
||||||
|
|
||||||
|
`2022.11.30`
|
||||||
|
|
||||||
|
- 🎉 新增 版本升级提示
|
||||||
|
- 🐞 修复 [先打开 F12 再登录进去,然后改变浏览器大小 js 报错](https://gitee.com/lyt-top/vue-next-admin/issues/I63ZZT),感谢[@Quber](https://gitee.com/quber)
|
||||||
|
|
||||||
## 2.4.0
|
## 2.4.0
|
||||||
|
|
||||||
`2022.11.29`
|
`2022.11.29`
|
||||||
|
|||||||
32
README.md
32
README.md
@ -1,25 +1,31 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
<img src="https://img-blog.csdnimg.cn/9efd5420327a46b7bd6d93524a97229d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAbHl0LXRvcA==,size_14,color_FFFFFF,t_70,g_se,x_16">
|
<img src="https://img-blog.csdnimg.cn/9efd5420327a46b7bd6d93524a97229d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAbHl0LXRvcA==,size_14,color_FFFFFF,t_70,g_se,x_16">
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://v3.vuejs.org/" target="_blank">
|
<a href="https://v3.vuejs.org/" target="_blank">
|
||||||
<img src="https://img.shields.io/badge/vue.js-vue3.x-green" alt="vue">
|
<img src="https://img.shields.io/badge/vue.js-vue3.x-green" alt="vue">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://element-plus.gitee.io/#/zh-CN/component/changelog" target="_blank">
|
<a href="https://element-plus.gitee.io/#/zh-CN/component/changelog" target="_blank">
|
||||||
<img src="https://img.shields.io/badge/element--plus-%3E1.0.0-blue" alt="element plus">
|
<img src="https://img.shields.io/badge/element--plus-%3E1.0.0-blue" alt="element plus">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://www.tslang.cn/" target="_blank">
|
<a href="https://www.tslang.cn/" target="_blank">
|
||||||
<img src="https://img.shields.io/badge/typescript-%3E4.0.0-blue" alt="typescript">
|
<img src="https://img.shields.io/badge/typescript-%3E4.0.0-blue" alt="typescript">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://vitejs.dev/" target="_blank">
|
<a href="https://vitejs.dev/" target="_blank">
|
||||||
<img src="https://img.shields.io/badge/vite-%3E2.0.0-yellow" alt="vite">
|
<img src="https://img.shields.io/badge/vite-%3E2.0.0-yellow" alt="vite">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://gitee.com/lyt-top/vue-next-admin/blob/master/LICENSE" target="_blank">
|
<a href="https://gitee.com/lyt-top/vue-next-admin/blob/master/LICENSE" target="_blank">
|
||||||
<img src="https://img.shields.io/badge/license-MIT-success" alt="license">
|
<img src="https://img.shields.io/badge/license-MIT-success" alt="license">
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p> </p>
|
<p> </p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
#### 💝 长期赞助商
|
||||||
|
|
||||||
|
<a href="http://www.ccflow.org/" target="_blank">
|
||||||
|
<img src="./src/assets/ccflowRightNextAdmin.png" width="50%" height="70px">
|
||||||
|
</a>
|
||||||
|
|
||||||
#### 🌈 介绍
|
#### 🌈 介绍
|
||||||
|
|
||||||
基于 vue3.x + CompositionAPI setup 语法糖 + typescript + vite + element plus + vue-router-next + pinia 技术,适配手机、平板、pc 的后台开源免费模板,希望减少工作量,帮助大家实现快速开发。
|
基于 vue3.x + CompositionAPI setup 语法糖 + typescript + vite + element plus + vue-router-next + pinia 技术,适配手机、平板、pc 的后台开源免费模板,希望减少工作量,帮助大家实现快速开发。
|
||||||
@ -43,13 +49,15 @@
|
|||||||
|
|
||||||
| Edge | Firefox | Chrome | Safari |
|
| Edge | Firefox | Chrome | Safari |
|
||||||
| --------- | ------------ | ----------- | ----------- |
|
| --------- | ------------ | ----------- | ----------- |
|
||||||
| Edge ≥ 79 | Firefox ≥ 78 | Chrome ≥ 72 | Safari ≥ 12 |
|
| Edge ≥ 88 | Firefox ≥ 78 | Chrome ≥ 87 | Safari ≥ 13 |
|
||||||
|
|
||||||
> 由于 Vue3 不再支持 IE11,故而 ElementPlus 也不支持 IE11 及之前版本。
|
> 由于 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 版本 > 14.18+/16+</a>
|
||||||
|
|
||||||
|
> Vite 不再支持 Node 12 / 13 / 15,因为上述版本已经进入了 EOL 阶段。现在你必须使用 Node 14.18+ / 16+ 版本。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 克隆项目
|
# 克隆项目
|
||||||
|
|||||||
3490
package-lock.json
generated
3490
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
43
package.json
43
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vue-next-admin",
|
"name": "vue-next-admin",
|
||||||
"version": "2.4.0",
|
"version": "2.4.3",
|
||||||
"description": "vue3 vite next admin template",
|
"description": "vue3 vite next admin template",
|
||||||
"author": "lyt_20201208",
|
"author": "lyt_20201208",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -13,46 +13,45 @@
|
|||||||
"@element-plus/icons-vue": "^2.0.10",
|
"@element-plus/icons-vue": "^2.0.10",
|
||||||
"@wangeditor/editor": "^5.1.23",
|
"@wangeditor/editor": "^5.1.23",
|
||||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||||
"axios": "^1.2.0",
|
"axios": "^1.3.3",
|
||||||
"countup.js": "^2.3.2",
|
"countup.js": "^2.4.2",
|
||||||
"cropperjs": "^1.5.13",
|
"cropperjs": "^1.5.13",
|
||||||
"echarts": "^5.4.0",
|
"echarts": "^5.4.1",
|
||||||
"echarts-gl": "^2.0.9",
|
"echarts-gl": "^2.0.9",
|
||||||
"echarts-wordcloud": "^2.1.0",
|
"echarts-wordcloud": "^2.1.0",
|
||||||
"element-plus": "^2.2.25",
|
"element-plus": "^2.2.32",
|
||||||
"js-cookie": "^3.0.1",
|
"js-cookie": "^3.0.1",
|
||||||
"js-table2excel": "^1.0.3",
|
"js-table2excel": "^1.0.3",
|
||||||
"jsplumb": "^2.15.6",
|
"jsplumb": "^2.15.6",
|
||||||
"mitt": "^3.0.0",
|
"mitt": "^3.0.0",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"pinia": "^2.0.27",
|
"pinia": "^2.0.32",
|
||||||
"print-js": "^1.6.0",
|
"print-js": "^1.6.0",
|
||||||
"qrcodejs2-fixes": "^0.0.2",
|
"qrcodejs2-fixes": "^0.0.2",
|
||||||
|
"qs": "^6.11.0",
|
||||||
"screenfull": "^6.0.2",
|
"screenfull": "^6.0.2",
|
||||||
"sortablejs": "^1.15.0",
|
"sortablejs": "^1.15.0",
|
||||||
"splitpanes": "^3.1.5",
|
"splitpanes": "^3.1.5",
|
||||||
"vue": "^3.2.45",
|
"vue": "^3.2.47",
|
||||||
"vue-clipboard3": "^2.0.0",
|
"vue-clipboard3": "^2.0.0",
|
||||||
"vue-grid-layout": "^3.0.0-beta1",
|
"vue-grid-layout": "^3.0.0-beta1",
|
||||||
"vue-i18n": "^9.2.2",
|
"vue-i18n": "^9.2.2",
|
||||||
"vue-router": "^4.1.6"
|
"vue-router": "^4.1.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^18.11.9",
|
"@types/node": "^18.14.0",
|
||||||
"@types/nprogress": "^0.2.0",
|
"@types/nprogress": "^0.2.0",
|
||||||
"@types/sortablejs": "^1.15.0",
|
"@types/sortablejs": "^1.15.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
"@typescript-eslint/eslint-plugin": "^5.53.0",
|
||||||
"@typescript-eslint/parser": "^5.45.0",
|
"@typescript-eslint/parser": "^5.53.0",
|
||||||
"@vitejs/plugin-vue": "^3.2.0",
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
"@vue/compiler-sfc": "^3.2.45",
|
"@vue/compiler-sfc": "^3.2.47",
|
||||||
"dotenv": "^16.0.3",
|
"eslint": "^8.34.0",
|
||||||
"eslint": "^8.28.0",
|
"eslint-plugin-vue": "^9.9.0",
|
||||||
"eslint-plugin-vue": "^9.8.0",
|
"prettier": "^2.8.4",
|
||||||
"prettier": "^2.8.0",
|
"sass": "^1.58.3",
|
||||||
"sass": "^1.56.1",
|
"typescript": "^4.9.5",
|
||||||
"sass-loader": "^13.2.0",
|
"vite": "^4.1.4",
|
||||||
"typescript": "^4.9.3",
|
|
||||||
"vite": "^3.2.4",
|
|
||||||
"vite-plugin-vue-setup-extend": "^0.4.0",
|
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||||
"vue-eslint-parser": "^9.1.0"
|
"vue-eslint-parser": "^9.1.0"
|
||||||
},
|
},
|
||||||
@ -65,8 +64,8 @@
|
|||||||
"url": "https://gitee.com/lyt-top/vue-next-admin/issues"
|
"url": "https://gitee.com/lyt-top/vue-next-admin/issues"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.0.0",
|
"node": ">=16.0.0",
|
||||||
"npm": ">= 6.0.0"
|
"npm": ">= 7.0.0"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"vue",
|
"vue",
|
||||||
|
|||||||
23
src/App.vue
23
src/App.vue
@ -1,9 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-config-provider :size="getGlobalComponentSize" :locale="getGlobalI18n">
|
<el-config-provider :size="getGlobalComponentSize" :locale="getGlobalI18n">
|
||||||
<router-view v-show="themeConfig.lockScreenTime > 1" />
|
<router-view v-show="setLockScreen" />
|
||||||
<LockScreen v-if="themeConfig.isLockScreen" />
|
<LockScreen v-if="themeConfig.isLockScreen" />
|
||||||
<Setings ref="setingsRef" v-show="themeConfig.lockScreenTime > 1" />
|
<Setings ref="setingsRef" v-show="setLockScreen" />
|
||||||
<CloseFull v-if="!themeConfig.isLockScreen" />
|
<CloseFull v-if="!themeConfig.isLockScreen" />
|
||||||
|
<Upgrade v-if="getVersion" />
|
||||||
|
<Sponsors />
|
||||||
</el-config-provider>
|
</el-config-provider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -23,6 +25,8 @@ import setIntroduction from '/@/utils/setIconfont';
|
|||||||
const LockScreen = defineAsyncComponent(() => import('/@/layout/lockScreen/index.vue'));
|
const LockScreen = defineAsyncComponent(() => import('/@/layout/lockScreen/index.vue'));
|
||||||
const Setings = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/setings.vue'));
|
const Setings = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/setings.vue'));
|
||||||
const CloseFull = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/closeFull.vue'));
|
const CloseFull = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/closeFull.vue'));
|
||||||
|
const Upgrade = defineAsyncComponent(() => import('/@/layout/upgrade/index.vue'));
|
||||||
|
const Sponsors = defineAsyncComponent(() => import('/@/layout/sponsors/index.vue'));
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const { messages, locale } = useI18n();
|
const { messages, locale } = useI18n();
|
||||||
@ -32,6 +36,21 @@ const stores = useTagsViewRoutes();
|
|||||||
const storesThemeConfig = useThemeConfig();
|
const storesThemeConfig = useThemeConfig();
|
||||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||||
|
|
||||||
|
// 设置锁屏时组件显示隐藏
|
||||||
|
const setLockScreen = computed(() => {
|
||||||
|
// 防止锁屏后,刷新出现不相关界面
|
||||||
|
// https://gitee.com/lyt-top/vue-next-admin/issues/I6AF8P
|
||||||
|
return themeConfig.value.isLockScreen ? themeConfig.value.lockScreenTime > 1 : themeConfig.value.lockScreenTime >= 0;
|
||||||
|
});
|
||||||
|
// 获取版本号
|
||||||
|
const getVersion = computed(() => {
|
||||||
|
let isVersion = false;
|
||||||
|
if (route.path !== '/login') {
|
||||||
|
// @ts-ignore
|
||||||
|
if ((Local.get('version') && Local.get('version') !== __NEXT_VERSION__) || !Local.get('version')) isVersion = true;
|
||||||
|
}
|
||||||
|
return isVersion;
|
||||||
|
});
|
||||||
// 获取全局组件大小
|
// 获取全局组件大小
|
||||||
const getGlobalComponentSize = computed(() => {
|
const getGlobalComponentSize = computed(() => {
|
||||||
return other.globalComponentSize();
|
return other.globalComponentSize();
|
||||||
|
|||||||
@ -1,17 +1,27 @@
|
|||||||
import request from '/@/utils/request';
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* (不建议写成 request.post(xxx),因为这样 post 时,无法 params 与 data 同时传参)
|
||||||
|
*
|
||||||
* 登录api接口集合
|
* 登录api接口集合
|
||||||
* @method signIn 用户登录
|
* @method signIn 用户登录
|
||||||
* @method signOut 用户退出登录
|
* @method signOut 用户退出登录
|
||||||
*/
|
*/
|
||||||
export function useLoginApi() {
|
export function useLoginApi() {
|
||||||
return {
|
return {
|
||||||
signIn: (params: object) => {
|
signIn: (data: object) => {
|
||||||
return request.post('/user/signIn', params);
|
return request({
|
||||||
|
url: '/user/signIn',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
signOut: (params: object) => {
|
signOut: (data: object) => {
|
||||||
return request.post('/user/signOut', params);
|
return request({
|
||||||
|
url: '/user/signOut',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import request from '/@/utils/request';
|
|||||||
/**
|
/**
|
||||||
* 以下为模拟接口地址,gitee 的不通,就换自己的真实接口地址
|
* 以下为模拟接口地址,gitee 的不通,就换自己的真实接口地址
|
||||||
*
|
*
|
||||||
|
* (不建议写成 request.post(xxx),因为这样 post 时,无法 params 与 data 同时传参)
|
||||||
|
*
|
||||||
* 后端控制菜单模拟json,路径在 https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu
|
* 后端控制菜单模拟json,路径在 https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu
|
||||||
* 后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
|
* 后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
|
||||||
* @method getAdminMenu 获取后端动态路由菜单(admin)
|
* @method getAdminMenu 获取后端动态路由菜单(admin)
|
||||||
@ -11,10 +13,18 @@ import request from '/@/utils/request';
|
|||||||
export function useMenuApi() {
|
export function useMenuApi() {
|
||||||
return {
|
return {
|
||||||
getAdminMenu: (params?: object) => {
|
getAdminMenu: (params?: object) => {
|
||||||
return request.get('/gitee/lyt-top/vue-next-admin-images/raw/master/menu/adminMenu.json', params);
|
return request({
|
||||||
|
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/adminMenu.json',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
getTestMenu: (params?: object) => {
|
getTestMenu: (params?: object) => {
|
||||||
return request.get('/gitee/lyt-top/vue-next-admin-images/raw/master/menu/testMenu.json', params);
|
return request({
|
||||||
|
url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/testMenu.json',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
src/assets/ccflowRightNextAdmin.png
Normal file
BIN
src/assets/ccflowRightNextAdmin.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 153 KiB |
@ -88,4 +88,14 @@ watch(
|
|||||||
deep: true,
|
deep: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
// 监听双向绑定值改变,用于回显
|
||||||
|
watch(
|
||||||
|
() => props.getHtml,
|
||||||
|
(val) => {
|
||||||
|
state.editorVal = val;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deep: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,67 +1,48 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="icon-selector w100 h100">
|
<div class="icon-selector w100 h100">
|
||||||
|
<el-input
|
||||||
|
v-model="state.fontIconSearch"
|
||||||
|
:placeholder="state.fontIconPlaceholder"
|
||||||
|
:clearable="clearable"
|
||||||
|
:disabled="disabled"
|
||||||
|
:size="size"
|
||||||
|
ref="inputWidthRef"
|
||||||
|
@clear="onClearFontIcon"
|
||||||
|
@focus="onIconFocus"
|
||||||
|
@blur="onIconBlur"
|
||||||
|
>
|
||||||
|
<template #prepend>
|
||||||
|
<SvgIcon
|
||||||
|
:name="state.fontIconPrefix === '' ? prepend : state.fontIconPrefix"
|
||||||
|
class="font14"
|
||||||
|
v-if="state.fontIconPrefix === '' ? prepend?.indexOf('ele-') > -1 : state.fontIconPrefix?.indexOf('ele-') > -1"
|
||||||
|
/>
|
||||||
|
<i v-else :class="state.fontIconPrefix === '' ? prepend : state.fontIconPrefix" class="font14"></i>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
<el-popover
|
<el-popover
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
:width="state.fontIconWidth"
|
:width="state.fontIconWidth"
|
||||||
trigger="click"
|
|
||||||
transition="el-zoom-in-top"
|
transition="el-zoom-in-top"
|
||||||
popper-class="icon-selector-popper"
|
popper-class="icon-selector-popper"
|
||||||
@show="onPopoverShow"
|
trigger="click"
|
||||||
|
:virtual-ref="inputWidthRef"
|
||||||
|
virtual-triggering
|
||||||
>
|
>
|
||||||
<template #reference>
|
|
||||||
<el-input
|
|
||||||
v-model="state.fontIconSearch"
|
|
||||||
:placeholder="state.fontIconPlaceholder"
|
|
||||||
:clearable="clearable"
|
|
||||||
:disabled="disabled"
|
|
||||||
:size="size"
|
|
||||||
ref="inputWidthRef"
|
|
||||||
@clear="onClearFontIcon"
|
|
||||||
@focus="onIconFocus"
|
|
||||||
@blur="onIconBlur"
|
|
||||||
>
|
|
||||||
<template #prepend>
|
|
||||||
<SvgIcon
|
|
||||||
:name="state.fontIconPrefix === '' ? prepend : state.fontIconPrefix"
|
|
||||||
class="font14"
|
|
||||||
v-if="state.fontIconPrefix === '' ? prepend?.indexOf('ele-') > -1 : state.fontIconPrefix?.indexOf('ele-') > -1"
|
|
||||||
/>
|
|
||||||
<i v-else :class="state.fontIconPrefix === '' ? prepend : state.fontIconPrefix" class="font14"></i>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</template>
|
|
||||||
<template #default>
|
<template #default>
|
||||||
<div class="icon-selector-warp">
|
<div class="icon-selector-warp">
|
||||||
<div class="icon-selector-warp-title flex">
|
<div class="icon-selector-warp-title">{{ title }}</div>
|
||||||
<div class="flex-auto">{{ title }}</div>
|
<el-tabs v-model="state.fontIconTabActive" @tab-click="onIconClick">
|
||||||
<div class="icon-selector-warp-title-tab" v-if="type === 'all'">
|
<el-tab-pane lazy label="ali" name="ali">
|
||||||
<span :class="{ 'span-active': state.fontIconType === 'ali' }" @click="onIconChange('ali')" class="ml10" title="iconfont 图标">
|
<IconList :list="fontIconSheetsFilterList" :empty="emptyDescription" :prefix="state.fontIconPrefix" @get-icon="onColClick" />
|
||||||
ali
|
</el-tab-pane>
|
||||||
</span>
|
<el-tab-pane lazy label="ele" name="ele">
|
||||||
<span :class="{ 'span-active': state.fontIconType === 'ele' }" @click="onIconChange('ele')" class="ml10" title="elementPlus 图标">
|
<IconList :list="fontIconSheetsFilterList" :empty="emptyDescription" :prefix="state.fontIconPrefix" @get-icon="onColClick" />
|
||||||
ele
|
</el-tab-pane>
|
||||||
</span>
|
<el-tab-pane lazy label="awe" name="awe">
|
||||||
<span :class="{ 'span-active': state.fontIconType === 'awe' }" @click="onIconChange('awe')" class="ml10" title="fontawesome 图标">
|
<IconList :list="fontIconSheetsFilterList" :empty="emptyDescription" :prefix="state.fontIconPrefix" @get-icon="onColClick" />
|
||||||
awe
|
</el-tab-pane>
|
||||||
</span>
|
</el-tabs>
|
||||||
</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': state.fontIconPrefix === v }">
|
|
||||||
<div class="flex-margin">
|
|
||||||
<div class="icon-selector-warp-item-value">
|
|
||||||
<SvgIcon :name="v" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-empty :image-size="100" v-if="fontIconSheetsFilterList.length <= 0" :description="emptyDescription"></el-empty>
|
|
||||||
</el-scrollbar>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
@ -69,8 +50,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="iconSelector">
|
<script setup lang="ts" name="iconSelector">
|
||||||
import { ref, reactive, onMounted, nextTick, computed, watch } from 'vue';
|
import { defineAsyncComponent, ref, reactive, onMounted, nextTick, computed, watch } from 'vue';
|
||||||
|
import type { TabsPaneContext } from 'element-plus';
|
||||||
import initIconfont from '/@/utils/getStyleSheets';
|
import initIconfont from '/@/utils/getStyleSheets';
|
||||||
|
import '/@/theme/iconSelector.scss';
|
||||||
|
|
||||||
// 定义父组件传过来的值
|
// 定义父组件传过来的值
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -94,11 +77,6 @@ const props = defineProps({
|
|||||||
type: String,
|
type: String,
|
||||||
default: () => '请选择图标',
|
default: () => '请选择图标',
|
||||||
},
|
},
|
||||||
// icon 图标类型
|
|
||||||
type: {
|
|
||||||
type: String,
|
|
||||||
default: () => 'ele',
|
|
||||||
},
|
|
||||||
// 禁用
|
// 禁用
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -123,18 +101,22 @@ const props = defineProps({
|
|||||||
// 定义子组件向父组件传值/事件
|
// 定义子组件向父组件传值/事件
|
||||||
const emit = defineEmits(['update:modelValue', 'get', 'clear']);
|
const emit = defineEmits(['update:modelValue', 'get', 'clear']);
|
||||||
|
|
||||||
|
// 引入组件
|
||||||
|
const IconList = defineAsyncComponent(() => import('/@/components/iconSelector/list.vue'));
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const inputWidthRef = ref();
|
const inputWidthRef = ref();
|
||||||
const selectorScrollbarRef = ref();
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
fontIconPrefix: '',
|
fontIconPrefix: '',
|
||||||
fontIconWidth: 0,
|
fontIconWidth: 0,
|
||||||
fontIconSearch: '',
|
fontIconSearch: '',
|
||||||
fontIconTabsIndex: 0,
|
|
||||||
fontIconSheetsList: [],
|
|
||||||
fontIconPlaceholder: '',
|
fontIconPlaceholder: '',
|
||||||
fontIconType: 'ali',
|
fontIconTabActive: 'ali',
|
||||||
fontIconShow: true,
|
fontIconList: {
|
||||||
|
ali: [],
|
||||||
|
ele: [],
|
||||||
|
awe: [],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 处理 input 获取焦点时,modelValue 有值时,改变 input 的 placeholder 值
|
// 处理 input 获取焦点时,modelValue 有值时,改变 input 的 placeholder 值
|
||||||
@ -145,32 +127,91 @@ const onIconFocus = () => {
|
|||||||
};
|
};
|
||||||
// 处理 input 失去焦点时,为空将清空 input 值,为点击选中图标时,将取原先值
|
// 处理 input 失去焦点时,为空将清空 input 值,为点击选中图标时,将取原先值
|
||||||
const onIconBlur = () => {
|
const onIconBlur = () => {
|
||||||
|
const list = fontIconTabNameList();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const icon = state.fontIconSheetsList.filter((icon: string) => icon === state.fontIconSearch);
|
const icon = list.filter((icon: string) => icon === state.fontIconSearch);
|
||||||
if (icon.length <= 0) state.fontIconSearch = '';
|
if (icon.length <= 0) state.fontIconSearch = '';
|
||||||
}, 300);
|
}, 300);
|
||||||
};
|
};
|
||||||
|
// 图标搜索及图标数据显示
|
||||||
|
const fontIconSheetsFilterList = computed(() => {
|
||||||
|
const list = fontIconTabNameList();
|
||||||
|
if (!state.fontIconSearch) return list;
|
||||||
|
let search = state.fontIconSearch.trim().toLowerCase();
|
||||||
|
return list.filter((item: string) => {
|
||||||
|
if (item.toLowerCase().indexOf(search) !== -1) return item;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// 根据 tab name 类型设置图标
|
||||||
|
const fontIconTabNameList = () => {
|
||||||
|
let iconList: any = [];
|
||||||
|
if (state.fontIconTabActive === 'ali') iconList = state.fontIconList.ali;
|
||||||
|
else if (state.fontIconTabActive === 'ele') iconList = state.fontIconList.ele;
|
||||||
|
else if (state.fontIconTabActive === 'awe') iconList = state.fontIconList.awe;
|
||||||
|
return iconList;
|
||||||
|
};
|
||||||
// 处理 icon 双向绑定数值回显
|
// 处理 icon 双向绑定数值回显
|
||||||
const initModeValueEcho = () => {
|
const initModeValueEcho = () => {
|
||||||
if (props.modelValue === '') return ((<string | undefined>state.fontIconPlaceholder) = props.placeholder);
|
if (props.modelValue === '') return ((<string | undefined>state.fontIconPlaceholder) = props.placeholder);
|
||||||
(<string | undefined>state.fontIconPlaceholder) = props.modelValue;
|
(<string | undefined>state.fontIconPlaceholder) = props.modelValue;
|
||||||
(<string | undefined>state.fontIconPrefix) = props.modelValue;
|
(<string | undefined>state.fontIconPrefix) = props.modelValue;
|
||||||
};
|
};
|
||||||
// 处理 icon type 类型为 all 时,类型 ali、ele、awe 回显问题
|
// 处理 icon 类型,用于回显时,tab 高亮与初始化数据
|
||||||
const initFontIconTypeEcho = () => {
|
const initFontIconName = () => {
|
||||||
if (props.modelValue!.indexOf('iconfont') > -1) onIconChange('ali');
|
let name = 'ali';
|
||||||
else if (props.modelValue!.indexOf('ele-') > -1) onIconChange('ele');
|
if (props.modelValue!.indexOf('iconfont') > -1) name = 'ali';
|
||||||
else if (props.modelValue!.indexOf('fa') > -1) onIconChange('awe');
|
else if (props.modelValue!.indexOf('ele-') > -1) name = 'ele';
|
||||||
else onIconChange('ali');
|
else if (props.modelValue!.indexOf('fa') > -1) name = 'awe';
|
||||||
|
// 初始化 tab 高亮回显
|
||||||
|
state.fontIconTabActive = name;
|
||||||
|
return name;
|
||||||
|
};
|
||||||
|
// 初始化数据
|
||||||
|
const initFontIconData = async (name: string) => {
|
||||||
|
if (name === 'ali') {
|
||||||
|
// 阿里字体图标使用 `iconfont xxx`
|
||||||
|
if (state.fontIconList.ali.length > 0) return;
|
||||||
|
await initIconfont.ali().then((res: any) => {
|
||||||
|
state.fontIconList.ali = res.map((i: string) => `iconfont ${i}`);
|
||||||
|
});
|
||||||
|
} else if (name === 'ele') {
|
||||||
|
// element plus 图标
|
||||||
|
if (state.fontIconList.ele.length > 0) return;
|
||||||
|
await initIconfont.ele().then((res: any) => {
|
||||||
|
state.fontIconList.ele = res;
|
||||||
|
});
|
||||||
|
} else if (name === 'awe') {
|
||||||
|
// fontawesome字体图标使用 `fa xxx`
|
||||||
|
if (state.fontIconList.awe.length > 0) return;
|
||||||
|
await initIconfont.awe().then((res: any) => {
|
||||||
|
state.fontIconList.awe = res.map((i: string) => `fa ${i}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 初始化 input 的 placeholder
|
||||||
|
// 参考(单项数据流):https://cn.vuejs.org/v2/guide/components-props.html?#%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE%E6%B5%81
|
||||||
|
state.fontIconPlaceholder = props.placeholder;
|
||||||
|
// 初始化双向绑定回显
|
||||||
|
initModeValueEcho();
|
||||||
|
};
|
||||||
|
// 图标点击切换
|
||||||
|
const onIconClick = (pane: TabsPaneContext) => {
|
||||||
|
initFontIconData(pane.paneName as string);
|
||||||
|
inputWidthRef.value.focus();
|
||||||
|
};
|
||||||
|
// 获取当前点击的 icon 图标
|
||||||
|
const onColClick = (v: string) => {
|
||||||
|
state.fontIconPlaceholder = v;
|
||||||
|
state.fontIconPrefix = v;
|
||||||
|
emit('get', state.fontIconPrefix);
|
||||||
|
emit('update:modelValue', state.fontIconPrefix);
|
||||||
|
inputWidthRef.value.focus();
|
||||||
|
};
|
||||||
|
// 清空当前点击的 icon 图标
|
||||||
|
const onClearFontIcon = () => {
|
||||||
|
state.fontIconPrefix = '';
|
||||||
|
emit('clear', state.fontIconPrefix);
|
||||||
|
emit('update:modelValue', state.fontIconPrefix);
|
||||||
};
|
};
|
||||||
// 图标搜索及图标数据显示
|
|
||||||
const fontIconSheetsFilterList = computed(() => {
|
|
||||||
if (!state.fontIconSearch) return state.fontIconSheetsList;
|
|
||||||
let search = state.fontIconSearch.trim().toLowerCase();
|
|
||||||
return state.fontIconSheetsList.filter((item: string) => {
|
|
||||||
if (item.toLowerCase().indexOf(search) !== -1) return item;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// 获取 input 的宽度
|
// 获取 input 的宽度
|
||||||
const getInputWidth = () => {
|
const getInputWidth = () => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@ -183,56 +224,9 @@ const initResize = () => {
|
|||||||
getInputWidth();
|
getInputWidth();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// 初始化数据
|
|
||||||
const initFontIconData = async (type: string) => {
|
|
||||||
state.fontIconSheetsList = [];
|
|
||||||
if (type === 'ali') {
|
|
||||||
await initIconfont.ali().then((res: any) => {
|
|
||||||
// 阿里字体图标使用 `iconfont xxx`
|
|
||||||
state.fontIconSheetsList = res.map((i: string) => `iconfont ${i}`);
|
|
||||||
});
|
|
||||||
} else if (type === 'ele') {
|
|
||||||
await initIconfont.ele().then((res: any) => {
|
|
||||||
state.fontIconSheetsList = res;
|
|
||||||
});
|
|
||||||
} else if (type === 'awe') {
|
|
||||||
await initIconfont.awe().then((res: any) => {
|
|
||||||
// fontawesome字体图标使用 `fa xxx`
|
|
||||||
state.fontIconSheetsList = res.map((i: string) => `fa ${i}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// 初始化 input 的 placeholder
|
|
||||||
// 参考(单项数据流):https://cn.vuejs.org/v2/guide/components-props.html?#%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE%E6%B5%81
|
|
||||||
state.fontIconPlaceholder = props.placeholder;
|
|
||||||
// 初始化双向绑定回显
|
|
||||||
initModeValueEcho();
|
|
||||||
};
|
|
||||||
// 图标点击切换
|
|
||||||
const onIconChange = (type: string) => {
|
|
||||||
state.fontIconType = type;
|
|
||||||
initFontIconData(type);
|
|
||||||
};
|
|
||||||
// 获取当前点击的 icon 图标
|
|
||||||
const onColClick = (v: string) => {
|
|
||||||
state.fontIconPlaceholder = v;
|
|
||||||
state.fontIconPrefix = v;
|
|
||||||
emit('get', state.fontIconPrefix);
|
|
||||||
emit('update:modelValue', state.fontIconPrefix);
|
|
||||||
};
|
|
||||||
// 清空当前点击的 icon 图标
|
|
||||||
const onClearFontIcon = () => {
|
|
||||||
state.fontIconPrefix = '';
|
|
||||||
emit('clear', state.fontIconPrefix);
|
|
||||||
emit('update:modelValue', state.fontIconPrefix);
|
|
||||||
};
|
|
||||||
// 监听 Popover 打开,用于双向绑定值回显
|
|
||||||
const onPopoverShow = () => {
|
|
||||||
initModeValueEcho();
|
|
||||||
initFontIconTypeEcho();
|
|
||||||
};
|
|
||||||
// 页面加载时
|
// 页面加载时
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initModeValueEcho();
|
initFontIconData(initFontIconName());
|
||||||
initResize();
|
initResize();
|
||||||
getInputWidth();
|
getInputWidth();
|
||||||
});
|
});
|
||||||
@ -241,6 +235,7 @@ watch(
|
|||||||
() => props.modelValue,
|
() => props.modelValue,
|
||||||
() => {
|
() => {
|
||||||
initModeValueEcho();
|
initModeValueEcho();
|
||||||
|
initFontIconName();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
84
src/components/iconSelector/list.vue
Normal file
84
src/components/iconSelector/list.vue
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<template>
|
||||||
|
<div class="icon-selector-warp-row">
|
||||||
|
<el-scrollbar ref="selectorScrollbarRef">
|
||||||
|
<el-row :gutter="10" v-if="props.list.length > 0">
|
||||||
|
<el-col :xs="6" :sm="4" :md="4" :lg="4" :xl="4" v-for="(v, k) in list" :key="k" @click="onColClick(v)">
|
||||||
|
<div class="icon-selector-warp-item" :class="{ 'icon-selector-active': prefix === v }">
|
||||||
|
<SvgIcon :name="v" />
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-empty :image-size="100" v-if="list.length <= 0" :description="empty"></el-empty>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="iconSelectorList">
|
||||||
|
// 定义父组件传过来的值
|
||||||
|
const props = defineProps({
|
||||||
|
// 图标列表数据
|
||||||
|
list: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
// 自定义空状态描述文字
|
||||||
|
empty: {
|
||||||
|
type: String,
|
||||||
|
default: () => '无相关图标',
|
||||||
|
},
|
||||||
|
// 高亮当前选中图标
|
||||||
|
prefix: {
|
||||||
|
type: String,
|
||||||
|
default: () => '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 定义子组件向父组件传值/事件
|
||||||
|
const emit = defineEmits(['get-icon']);
|
||||||
|
|
||||||
|
// 当前 icon 图标点击时
|
||||||
|
const onColClick = (v: unknown | string) => {
|
||||||
|
emit('get-icon', v);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.icon-selector-warp-row {
|
||||||
|
height: 230px;
|
||||||
|
overflow: hidden;
|
||||||
|
.el-row {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
.el-scrollbar__bar.is-horizontal {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.icon-selector-warp-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid var(--el-border-color);
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
height: 30px;
|
||||||
|
i {
|
||||||
|
font-size: 20px;
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: var(--el-color-primary-light-9);
|
||||||
|
border: 1px solid var(--el-color-primary-light-5);
|
||||||
|
i {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.icon-selector-active {
|
||||||
|
background-color: var(--el-color-primary-light-9);
|
||||||
|
border: 1px solid var(--el-color-primary-light-5);
|
||||||
|
i {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -21,7 +21,7 @@
|
|||||||
:label="item.title"
|
:label="item.title"
|
||||||
>
|
>
|
||||||
<template v-slot="scope">
|
<template v-slot="scope">
|
||||||
<template v-if="item.key === 'image'">
|
<template v-if="item.type === 'image'">
|
||||||
<img :src="scope.row[item.key]" :width="item.width" :height="item.height" />
|
<img :src="scope.row[item.key]" :width="item.width" :height="item.height" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@ -71,26 +71,28 @@
|
|||||||
<SvgIcon name="iconfont icon-quanjushezhi_o" :size="22" title="设置" />
|
<SvgIcon name="iconfont icon-quanjushezhi_o" :size="22" title="设置" />
|
||||||
</template>
|
</template>
|
||||||
<template #default>
|
<template #default>
|
||||||
<div ref="toolSetRef">
|
<div class="tool-box">
|
||||||
<div class="tool-box">
|
<el-tooltip content="拖动进行排序" placement="top-start">
|
||||||
<el-tooltip content="拖动进行排序" placement="top-start">
|
<SvgIcon name="fa fa-question-circle-o" :size="17" class="ml11" color="#909399" />
|
||||||
<SvgIcon name="fa fa-question-circle-o" :size="17" class="ml11" color="#909399" />
|
</el-tooltip>
|
||||||
</el-tooltip>
|
<el-checkbox
|
||||||
<el-checkbox
|
v-model="state.checkListAll"
|
||||||
v-model="state.checkListAll"
|
:indeterminate="state.checkListIndeterminate"
|
||||||
:indeterminate="state.checkListIndeterminate"
|
class="ml10 mr1"
|
||||||
class="ml10 mr1"
|
label="列显示"
|
||||||
label="列显示"
|
@change="onCheckAllChange"
|
||||||
@change="onCheckAllChange"
|
/>
|
||||||
/>
|
<el-checkbox v-model="getConfig.isSerialNo" class="ml12 mr1" label="序号" />
|
||||||
<el-checkbox v-model="getConfig.isSerialNo" class="ml12 mr1" label="序号" />
|
<el-checkbox v-model="getConfig.isSelection" class="ml12 mr1" label="多选" />
|
||||||
<el-checkbox v-model="getConfig.isSelection" class="ml12 mr1" label="多选" />
|
|
||||||
</div>
|
|
||||||
<div class="tool-item" v-for="v in header" :key="v.key" :data-key="v.key">
|
|
||||||
<i class="fa fa-arrows-alt handle cursor-pointer"></i>
|
|
||||||
<el-checkbox v-model="v.isCheck" class="ml12 mr8" :label="v.title" @change="onCheckChange" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<el-scrollbar>
|
||||||
|
<div ref="toolSetRef" class="tool-sortable">
|
||||||
|
<div class="tool-sortable-item" v-for="v in header" :key="v.key" :data-key="v.key">
|
||||||
|
<i class="fa fa-arrows-alt handle cursor-pointer"></i>
|
||||||
|
<el-checkbox v-model="v.isCheck" size="default" class="ml12 mr8" :label="v.title" @change="onCheckChange" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-scrollbar>
|
||||||
</template>
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
@ -119,11 +121,6 @@ const props = defineProps({
|
|||||||
type: Array<EmptyObjectType>,
|
type: Array<EmptyObjectType>,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
// 搜索参数
|
|
||||||
param: {
|
|
||||||
type: Object,
|
|
||||||
default: () => {},
|
|
||||||
},
|
|
||||||
// 配置项
|
// 配置项
|
||||||
config: {
|
config: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -161,7 +158,7 @@ const setHeader = computed(() => {
|
|||||||
return props.header.filter((v) => v.isCheck);
|
return props.header.filter((v) => v.isCheck);
|
||||||
});
|
});
|
||||||
// tool 列显示全选改变时
|
// tool 列显示全选改变时
|
||||||
const onCheckAllChange = (val: boolean) => {
|
const onCheckAllChange = <T>(val: T) => {
|
||||||
if (val) props.header.forEach((v) => (v.isCheck = true));
|
if (val) props.header.forEach((v) => (v.isCheck = true));
|
||||||
else props.header.forEach((v) => (v.isCheck = false));
|
else props.header.forEach((v) => (v.isCheck = false));
|
||||||
state.checkListIndeterminate = false;
|
state.checkListIndeterminate = false;
|
||||||
|
|||||||
@ -2,53 +2,53 @@ import { createI18n } from 'vue-i18n';
|
|||||||
import pinia from '/@/stores/index';
|
import pinia from '/@/stores/index';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||||
import zhcnLocale from 'element-plus/lib/locale/lang/zh-cn';
|
|
||||||
import enLocale from 'element-plus/lib/locale/lang/en';
|
|
||||||
import zhtwLocale from 'element-plus/lib/locale/lang/zh-tw';
|
|
||||||
|
|
||||||
import nextZhcn from '/@/i18n/lang/zh-cn';
|
|
||||||
import nextEn from '/@/i18n/lang/en';
|
|
||||||
import nextZhtw from '/@/i18n/lang/zh-tw';
|
|
||||||
|
|
||||||
import pagesLoginZhcn from '/@/i18n/pages/login/zh-cn';
|
|
||||||
import pagesLoginEn from '/@/i18n/pages/login/en';
|
|
||||||
import pagesLoginZhtw from '/@/i18n/pages/login/zh-tw';
|
|
||||||
import pagesFormI18nZhcn from '/@/i18n/pages/formI18n/zh-cn';
|
|
||||||
import pagesFormI18nEn from '/@/i18n/pages/formI18n/en';
|
|
||||||
import pagesFormI18nZhtw from '/@/i18n/pages/formI18n/zh-tw';
|
|
||||||
|
|
||||||
// 定义语言国际化内容
|
// 定义语言国际化内容
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 说明:
|
* 说明:
|
||||||
* /src/i18n/lang 下的 ts 为框架的国际化内容
|
* 须在 pages 下新建文件夹(建议 `要国际化界面目录` 与 `i18n 目录` 相同,方便查找),
|
||||||
* /src/i18n/pages 下的 ts 为各界面的国际化内容
|
* 注意国际化定义的字段,不要与原有的定义字段相同。
|
||||||
|
* 1、/src/i18n/lang 下的 ts 为框架的国际化内容
|
||||||
|
* 2、/src/i18n/pages 下的 ts 为各界面的国际化内容
|
||||||
*/
|
*/
|
||||||
const messages = {
|
|
||||||
[zhcnLocale.name]: {
|
// element plus 自带国际化
|
||||||
...zhcnLocale,
|
import enLocale from 'element-plus/lib/locale/lang/en';
|
||||||
message: {
|
import zhcnLocale from 'element-plus/lib/locale/lang/zh-cn';
|
||||||
...nextZhcn,
|
import zhtwLocale from 'element-plus/lib/locale/lang/zh-tw';
|
||||||
...pagesLoginZhcn,
|
|
||||||
...pagesFormI18nZhcn,
|
// 定义变量内容
|
||||||
},
|
const messages = {};
|
||||||
},
|
const element = { en: enLocale, 'zh-cn': zhcnLocale, 'zh-tw': zhtwLocale };
|
||||||
[enLocale.name]: {
|
const itemize = { en: [], 'zh-cn': [], 'zh-tw': [] };
|
||||||
...enLocale,
|
const modules: Record<string, any> = import.meta.glob('./**/*.ts', { eager: true });
|
||||||
message: {
|
|
||||||
...nextEn,
|
// 对自动引入的 modules 进行分类 en、zh-cn、zh-tw
|
||||||
...pagesLoginEn,
|
// https://vitejs.cn/vite3-cn/guide/features.html#glob-import
|
||||||
...pagesFormI18nEn,
|
for (const path in modules) {
|
||||||
},
|
const key = path.match(/(\S+)\/(\S+).ts/);
|
||||||
},
|
if (itemize[key![2]]) itemize[key![2]].push(modules[path].default);
|
||||||
[zhtwLocale.name]: {
|
else itemize[key![2]] = modules[path];
|
||||||
...zhtwLocale,
|
}
|
||||||
message: {
|
|
||||||
...nextZhtw,
|
// 合并数组对象(非标准数组对象,数组中对象的每项 key、value 都不同)
|
||||||
...pagesLoginZhtw,
|
function mergeArrObj<T>(list: T, key: string) {
|
||||||
...pagesFormI18nZhtw,
|
let obj = {};
|
||||||
},
|
list[key].forEach((i: EmptyObjectType) => {
|
||||||
},
|
obj = Object.assign({}, obj, i);
|
||||||
};
|
});
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理最终格式
|
||||||
|
for (const key in itemize) {
|
||||||
|
messages[key] = {
|
||||||
|
name: key,
|
||||||
|
el: element[key].el,
|
||||||
|
message: mergeArrObj(itemize, key),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// 读取 pinia 默认语言
|
// 读取 pinia 默认语言
|
||||||
const stores = useThemeConfig(pinia);
|
const stores = useThemeConfig(pinia);
|
||||||
|
|||||||
@ -137,6 +137,7 @@ export default {
|
|||||||
twoIsTopBarColorGradual: 'Top bar gradient',
|
twoIsTopBarColorGradual: 'Top bar gradient',
|
||||||
twoMenuBar: 'Menu background',
|
twoMenuBar: 'Menu background',
|
||||||
twoMenuBarColor: 'Menu default font color',
|
twoMenuBarColor: 'Menu default font color',
|
||||||
|
twoMenuBarActiveColor: 'Menu Highlight Color',
|
||||||
twoIsMenuBarColorGradual: 'Menu gradient',
|
twoIsMenuBarColorGradual: 'Menu gradient',
|
||||||
twoColumnsMenuBar: 'Column menu background',
|
twoColumnsMenuBar: 'Column menu background',
|
||||||
twoColumnsMenuBarColor: 'Default font color bar menu',
|
twoColumnsMenuBarColor: 'Default font color bar menu',
|
||||||
@ -180,4 +181,12 @@ export default {
|
|||||||
copyTextSuccess: 'Copy succeeded!',
|
copyTextSuccess: 'Copy succeeded!',
|
||||||
copyTextError: 'Copy failed!',
|
copyTextError: 'Copy failed!',
|
||||||
},
|
},
|
||||||
|
upgrade: {
|
||||||
|
title: 'New version',
|
||||||
|
msg: 'The new version is available, please update it now! Dont worry, the update is fast!',
|
||||||
|
desc: 'Prompt: Update will restore the default configuration',
|
||||||
|
btnOne: 'Cruel refusal',
|
||||||
|
btnTwo: 'Update now',
|
||||||
|
btnTwoLoading: 'Updating',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -137,6 +137,7 @@ export default {
|
|||||||
twoIsTopBarColorGradual: '顶栏背景渐变',
|
twoIsTopBarColorGradual: '顶栏背景渐变',
|
||||||
twoMenuBar: '菜单背景',
|
twoMenuBar: '菜单背景',
|
||||||
twoMenuBarColor: '菜单默认字体颜色',
|
twoMenuBarColor: '菜单默认字体颜色',
|
||||||
|
twoMenuBarActiveColor: '菜单高亮背景色',
|
||||||
twoIsMenuBarColorGradual: '菜单背景渐变',
|
twoIsMenuBarColorGradual: '菜单背景渐变',
|
||||||
twoColumnsMenuBar: '分栏菜单背景',
|
twoColumnsMenuBar: '分栏菜单背景',
|
||||||
twoColumnsMenuBarColor: '分栏菜单默认字体颜色',
|
twoColumnsMenuBarColor: '分栏菜单默认字体颜色',
|
||||||
@ -180,4 +181,12 @@ export default {
|
|||||||
copyTextSuccess: '复制成功!',
|
copyTextSuccess: '复制成功!',
|
||||||
copyTextError: '复制失败!',
|
copyTextError: '复制失败!',
|
||||||
},
|
},
|
||||||
|
upgrade: {
|
||||||
|
title: '新版本升级',
|
||||||
|
msg: '新版本来啦,马上更新尝鲜吧!不用担心,更新很快的哦!',
|
||||||
|
desc: '提示:更新会还原默认配置',
|
||||||
|
btnOne: '残忍拒绝',
|
||||||
|
btnTwo: '马上更新',
|
||||||
|
btnTwoLoading: '更新中',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -137,6 +137,7 @@ export default {
|
|||||||
twoIsTopBarColorGradual: '頂欄背景漸變',
|
twoIsTopBarColorGradual: '頂欄背景漸變',
|
||||||
twoMenuBar: '選單背景',
|
twoMenuBar: '選單背景',
|
||||||
twoMenuBarColor: '選單默認字體顏色',
|
twoMenuBarColor: '選單默認字體顏色',
|
||||||
|
twoMenuBarActiveColor: '選單高亮背景色',
|
||||||
twoIsMenuBarColorGradual: '選單背景漸變',
|
twoIsMenuBarColorGradual: '選單背景漸變',
|
||||||
twoColumnsMenuBar: '分欄選單背景',
|
twoColumnsMenuBar: '分欄選單背景',
|
||||||
twoColumnsMenuBarColor: '分欄選單默認字體顏色',
|
twoColumnsMenuBarColor: '分欄選單默認字體顏色',
|
||||||
@ -180,4 +181,12 @@ export default {
|
|||||||
copyTextSuccess: '複製成功!',
|
copyTextSuccess: '複製成功!',
|
||||||
copyTextError: '複製失敗!',
|
copyTextError: '複製失敗!',
|
||||||
},
|
},
|
||||||
|
upgrade: {
|
||||||
|
title: '新版本陞級',
|
||||||
|
msg: '新版本來啦,馬上更新嘗鮮吧! 不用擔心,更新很快的哦!',
|
||||||
|
desc: '提示:更新會還原默認配寘',
|
||||||
|
btnOne: '殘忍拒絕',
|
||||||
|
btnTwo: '馬上更新',
|
||||||
|
btnTwoLoading: '更新中',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -74,6 +74,7 @@ const state = reactive<ColumnsAsideState>({
|
|||||||
|
|
||||||
// 设置菜单高亮位置移动
|
// 设置菜单高亮位置移动
|
||||||
const setColumnsAsideMove = (k: number) => {
|
const setColumnsAsideMove = (k: number) => {
|
||||||
|
if (k === undefined) return false;
|
||||||
state.liIndex = k;
|
state.liIndex = k;
|
||||||
columnsAsideActiveRef.value.style.top = `${columnsAsideOffsetTopRefs.value[k].offsetTop + state.difference}px`;
|
columnsAsideActiveRef.value.style.top = `${columnsAsideOffsetTopRefs.value[k].offsetTop + state.difference}px`;
|
||||||
};
|
};
|
||||||
@ -198,7 +199,8 @@ watch(
|
|||||||
background: var(--next-bg-columnsMenuBar);
|
background: var(--next-bg-columnsMenuBar);
|
||||||
ul {
|
ul {
|
||||||
position: relative;
|
position: relative;
|
||||||
.layout-columns-active {
|
.layout-columns-active,
|
||||||
|
.layout-columns-active a {
|
||||||
color: var(--next-bg-columnsMenuBarColor) !important;
|
color: var(--next-bg-columnsMenuBarColor) !important;
|
||||||
transition: 0.3s ease-in-out;
|
transition: 0.3s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,6 +59,17 @@
|
|||||||
<el-color-picker v-model="getThemeConfig.menuBarColor" size="default" @change="onBgColorPickerChange('menuBarColor')"> </el-color-picker>
|
<el-color-picker v-model="getThemeConfig.menuBarColor" size="default" @change="onBgColorPickerChange('menuBarColor')"> </el-color-picker>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex">
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoMenuBarActiveColor') }}</div>
|
||||||
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
|
<el-color-picker
|
||||||
|
v-model="getThemeConfig.menuBarActiveColor"
|
||||||
|
size="default"
|
||||||
|
show-alpha
|
||||||
|
@change="onBgColorPickerChange('menuBarActiveColor')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex mt14">
|
<div class="layout-breadcrumb-seting-bar-flex mt14">
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoIsMenuBarColorGradual') }}</div>
|
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoIsMenuBarColorGradual') }}</div>
|
||||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||||
@ -427,7 +438,7 @@ import { useThemeConfig } from '/@/stores/themeConfig';
|
|||||||
import { useChangeColor } from '/@/utils/theme';
|
import { useChangeColor } from '/@/utils/theme';
|
||||||
import { verifyAndSpace } from '/@/utils/toolsValidate';
|
import { verifyAndSpace } from '/@/utils/toolsValidate';
|
||||||
import { Local } from '/@/utils/storage';
|
import { Local } from '/@/utils/storage';
|
||||||
import Watermark from '/@/utils/wartermark';
|
import Watermark from '/@/utils/watermark';
|
||||||
import commonFunction from '/@/utils/commonFunction';
|
import commonFunction from '/@/utils/commonFunction';
|
||||||
import other from '/@/utils/other';
|
import other from '/@/utils/other';
|
||||||
import mittBus from '/@/utils/mitt';
|
import mittBus from '/@/utils/mitt';
|
||||||
@ -577,6 +588,7 @@ const onSetLayout = (layout: string) => {
|
|||||||
const initLayoutChangeFun = () => {
|
const initLayoutChangeFun = () => {
|
||||||
onBgColorPickerChange('menuBar');
|
onBgColorPickerChange('menuBar');
|
||||||
onBgColorPickerChange('menuBarColor');
|
onBgColorPickerChange('menuBarColor');
|
||||||
|
onBgColorPickerChange('menuBarActiveColor');
|
||||||
onBgColorPickerChange('topBar');
|
onBgColorPickerChange('topBar');
|
||||||
onBgColorPickerChange('topBarColor');
|
onBgColorPickerChange('topBarColor');
|
||||||
onBgColorPickerChange('columnsMenuBar');
|
onBgColorPickerChange('columnsMenuBar');
|
||||||
@ -619,6 +631,8 @@ const onCopyConfigClick = () => {
|
|||||||
const onResetConfigClick = () => {
|
const onResetConfigClick = () => {
|
||||||
Local.clear();
|
Local.clear();
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
|
// @ts-ignore
|
||||||
|
Local.set('version', __NEXT_VERSION__);
|
||||||
};
|
};
|
||||||
// 初始化菜单样式等
|
// 初始化菜单样式等
|
||||||
const initSetStyle = () => {
|
const initSetStyle = () => {
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
<div class="layout-padding layout-padding-unset layout-iframe">
|
<div class="layout-padding layout-padding-unset layout-iframe">
|
||||||
<div class="layout-padding-auto layout-padding-view">
|
<div class="layout-padding-auto layout-padding-view">
|
||||||
<div class="w100" v-for="v in setIframeList" :key="v.path" v-loading="v.meta.loading" element-loading-background="white">
|
<div class="w100" v-for="v in setIframeList" :key="v.path" v-loading="v.meta.loading" element-loading-background="white">
|
||||||
<transition-group :name="name" mode="out-in">
|
<transition-group :name="name">
|
||||||
<iframe
|
<iframe
|
||||||
:src="v.meta.isLink"
|
:src="v.meta.isLink"
|
||||||
:key="v.path"
|
:key="v.path"
|
||||||
|
|||||||
@ -80,9 +80,13 @@ onMounted(() => {
|
|||||||
getIframeListRoutes();
|
getIframeListRoutes();
|
||||||
// https://gitee.com/lyt-top/vue-next-admin/issues/I58U75
|
// https://gitee.com/lyt-top/vue-next-admin/issues/I58U75
|
||||||
// https://gitee.com/lyt-top/vue-next-admin/issues/I59RXK
|
// https://gitee.com/lyt-top/vue-next-admin/issues/I59RXK
|
||||||
|
// https://gitee.com/lyt-top/vue-next-admin/pulls/40
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (themeConfig.value.isCacheTagsView) cachedViews.value = Session.get('tagsViewList')?.map((item: RouteItem) => item.name);
|
if (themeConfig.value.isCacheTagsView) {
|
||||||
|
let tagsViewArr: RouteItem[] = Session.get('tagsViewList') || [];
|
||||||
|
cachedViews.value = tagsViewArr.filter((item) => item.meta?.isKeepAlive).map((item) => item.name as string);
|
||||||
|
}
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
108
src/layout/sponsors/index.vue
Normal file
108
src/layout/sponsors/index.vue
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<template>
|
||||||
|
<div class="sponsors-container" title="点击前往体验" v-show="state.sponsors.isShow" @click="onSponsorsClick">
|
||||||
|
<el-carousel height="240px" indicator-position="none" :arrow="setCarouselShow" @change="onCarouselChange">
|
||||||
|
<el-carousel-item v-for="(v, k) in state.sponsors.list" :key="k">
|
||||||
|
<img :src="v.url" class="sponsors-img" />
|
||||||
|
<div class="sponsors-text" v-html="v.text"></div>
|
||||||
|
</el-carousel-item>
|
||||||
|
</el-carousel>
|
||||||
|
<div class="sponsors-close">
|
||||||
|
<SvgIcon name="ele-Close" :size="12" title="关闭赞助商" @click.stop="onCloseSponsors" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="layoutSponsors">
|
||||||
|
import { reactive, computed, onMounted } from 'vue';
|
||||||
|
import sponsorsOne from '/@/assets/ccflowRightNextAdmin.png';
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const state = reactive({
|
||||||
|
sponsors: {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
url: sponsorsOne,
|
||||||
|
text: `驰骋BPM系统包含表单引擎+流程引擎+权限控制,方便集成,配置灵活,功能强大,适合中国国情的工作流引擎.演示:http://demo.ccflow.org。右上角点star方可加群: 1060674395`,
|
||||||
|
link: 'http://www.ccflow.org/',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
isShow: false,
|
||||||
|
index: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 设置轮播图箭头显示
|
||||||
|
const setCarouselShow = computed(() => {
|
||||||
|
return state.sponsors.list.length <= 1 ? 'never' : 'hover';
|
||||||
|
});
|
||||||
|
// 关闭赞助商
|
||||||
|
const onCloseSponsors = () => {
|
||||||
|
state.sponsors.isShow = false;
|
||||||
|
};
|
||||||
|
// 轮播图改变时
|
||||||
|
const onCarouselChange = (e: number) => {
|
||||||
|
state.sponsors.index = e;
|
||||||
|
};
|
||||||
|
// 当前项内容点击
|
||||||
|
const onSponsorsClick = () => {
|
||||||
|
window.open(state.sponsors.list[state.sponsors.index].link);
|
||||||
|
};
|
||||||
|
// 延迟显示,防止影响其它界面加载
|
||||||
|
const delayShow = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
state.sponsors.isShow = true;
|
||||||
|
}, 3000);
|
||||||
|
};
|
||||||
|
// 页面加载时
|
||||||
|
onMounted(() => {
|
||||||
|
delayShow();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.sponsors-container {
|
||||||
|
position: fixed;
|
||||||
|
right: 15px;
|
||||||
|
bottom: 15px;
|
||||||
|
z-index: 3;
|
||||||
|
width: 200px;
|
||||||
|
background-color: var(--next-bg-main-color);
|
||||||
|
box-shadow: var(--el-box-shadow-lighter);
|
||||||
|
border-radius: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
.sponsors-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
.sponsors-text {
|
||||||
|
padding: 10px;
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
font-size: var(--el-dialog-content-font-size);
|
||||||
|
}
|
||||||
|
.sponsors-close {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.05);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: absolute;
|
||||||
|
right: -35px;
|
||||||
|
bottom: -35px;
|
||||||
|
:deep(i) {
|
||||||
|
position: absolute;
|
||||||
|
left: 9px;
|
||||||
|
top: 9px;
|
||||||
|
color: #afafaf;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
:deep(i) {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
151
src/layout/upgrade/index.vue
Normal file
151
src/layout/upgrade/index.vue
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
<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">{{ $t('message.upgrade.title') }}</span>
|
||||||
|
<span class="upgrade-title-warp-version">v{{ state.version }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="upgrade-content">
|
||||||
|
{{ getThemeConfig.globalTitle }} {{ $t('message.upgrade.msg') }}
|
||||||
|
<div class="mt5">
|
||||||
|
<el-link type="primary" class="font12" href="https://gitee.com/lyt-top/vue-next-admin/blob/master/CHANGELOG.md" target="_black">
|
||||||
|
CHANGELOG.md
|
||||||
|
</el-link>
|
||||||
|
</div>
|
||||||
|
<div class="upgrade-content-desc mt5">{{ $t('message.upgrade.desc') }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="upgrade-btn">
|
||||||
|
<el-button round size="default" type="info" text @click="onCancel">{{ $t('message.upgrade.btnOne') }}</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 lang="ts" name="layoutUpgrade">
|
||||||
|
import { reactive, computed, onMounted } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||||
|
import { Local } from '/@/utils/storage';
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const { t } = useI18n();
|
||||||
|
const storesThemeConfig = useThemeConfig();
|
||||||
|
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||||
|
const state = reactive({
|
||||||
|
isUpgrade: false,
|
||||||
|
// @ts-ignore
|
||||||
|
version: __NEXT_VERSION__,
|
||||||
|
isLoading: false,
|
||||||
|
btnTxt: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取布局配置信息
|
||||||
|
const getThemeConfig = computed(() => {
|
||||||
|
return themeConfig.value;
|
||||||
|
});
|
||||||
|
// 残忍拒绝
|
||||||
|
const onCancel = () => {
|
||||||
|
state.isUpgrade = false;
|
||||||
|
};
|
||||||
|
// 马上更新
|
||||||
|
const onUpgrade = () => {
|
||||||
|
state.isLoading = true;
|
||||||
|
state.btnTxt = t('message.upgrade.btnTwoLoading');
|
||||||
|
setTimeout(() => {
|
||||||
|
Local.clear();
|
||||||
|
window.location.reload();
|
||||||
|
Local.set('version', state.version);
|
||||||
|
}, 2000);
|
||||||
|
};
|
||||||
|
// 延迟显示,防止刷新时界面显示太快
|
||||||
|
const delayShow = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
state.isUpgrade = true;
|
||||||
|
}, 2000);
|
||||||
|
};
|
||||||
|
// 页面加载时
|
||||||
|
onMounted(() => {
|
||||||
|
delayShow();
|
||||||
|
setTimeout(() => {
|
||||||
|
state.btnTxt = t('message.upgrade.btnTwo');
|
||||||
|
}, 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-light-1);
|
||||||
|
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 {
|
||||||
|
color: var(--next-color-white);
|
||||||
|
background-color: var(--el-color-primary-light-4);
|
||||||
|
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>
|
||||||
@ -43,6 +43,9 @@ export async function initBackEndControlRoutes() {
|
|||||||
await useUserInfo().setUserInfos();
|
await useUserInfo().setUserInfos();
|
||||||
// 获取路由菜单数据
|
// 获取路由菜单数据
|
||||||
const res = await getBackEndControlRoutes();
|
const res = await getBackEndControlRoutes();
|
||||||
|
// 无登录权限时,添加判断
|
||||||
|
// https://gitee.com/lyt-top/vue-next-admin/issues/I64HVO
|
||||||
|
if (res.data.length <= 0) return Promise.resolve(true);
|
||||||
// 存储接口原始路由(未处理component),根据需求选择使用
|
// 存储接口原始路由(未处理component),根据需求选择使用
|
||||||
useRequestOldRoutes().setRequestOldRoutes(JSON.parse(JSON.stringify(res.data)));
|
useRequestOldRoutes().setRequestOldRoutes(JSON.parse(JSON.stringify(res.data)));
|
||||||
// 处理路由(component),替换 dynamicRoutes(/@/router/route)第一个顶级 children 的路由
|
// 处理路由(component),替换 dynamicRoutes(/@/router/route)第一个顶级 children 的路由
|
||||||
@ -58,7 +61,7 @@ export async function initBackEndControlRoutes() {
|
|||||||
* @description 用于左侧菜单、横向菜单的显示
|
* @description 用于左侧菜单、横向菜单的显示
|
||||||
* @description 用于 tagsView、菜单搜索中:未过滤隐藏的(isHide)
|
* @description 用于 tagsView、菜单搜索中:未过滤隐藏的(isHide)
|
||||||
*/
|
*/
|
||||||
export function setFilterMenuAndCacheTagsViewRoutes() {
|
export async function setFilterMenuAndCacheTagsViewRoutes() {
|
||||||
const storesRoutesList = useRoutesList(pinia);
|
const storesRoutesList = useRoutesList(pinia);
|
||||||
storesRoutesList.setRoutesList(dynamicRoutes[0].children as any);
|
storesRoutesList.setRoutesList(dynamicRoutes[0].children as any);
|
||||||
setCacheTagsViewRoutes();
|
setCacheTagsViewRoutes();
|
||||||
@ -119,8 +122,8 @@ export function getBackEndControlRoutes() {
|
|||||||
* @description 用于菜单管理界面刷新菜单(未进行测试)
|
* @description 用于菜单管理界面刷新菜单(未进行测试)
|
||||||
* @description 路径:/src/views/system/menu/component/addMenu.vue
|
* @description 路径:/src/views/system/menu/component/addMenu.vue
|
||||||
*/
|
*/
|
||||||
export function setBackEndControlRefreshRoutes() {
|
export async function setBackEndControlRefreshRoutes() {
|
||||||
getBackEndControlRoutes();
|
await getBackEndControlRoutes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -26,6 +26,9 @@ export async function initFrontEndControlRoutes() {
|
|||||||
// 触发初始化用户信息 pinia
|
// 触发初始化用户信息 pinia
|
||||||
// https://gitee.com/lyt-top/vue-next-admin/issues/I5F1HP
|
// https://gitee.com/lyt-top/vue-next-admin/issues/I5F1HP
|
||||||
await useUserInfo(pinia).setUserInfos();
|
await useUserInfo(pinia).setUserInfos();
|
||||||
|
// 无登录权限时,添加判断
|
||||||
|
// https://gitee.com/lyt-top/vue-next-admin/issues/I64HVO
|
||||||
|
if (useUserInfo().userInfos.roles.length <= 0) return Promise.resolve(true);
|
||||||
// 添加动态路由
|
// 添加动态路由
|
||||||
await setAddRoute();
|
await setAddRoute();
|
||||||
// 设置递归过滤有权限的路由到 pinia routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
// 设置递归过滤有权限的路由到 pinia routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||||
|
|||||||
@ -856,7 +856,7 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
|
|||||||
isAffix: false,
|
isAffix: false,
|
||||||
isIframe: false,
|
isIframe: false,
|
||||||
roles: ['admin'],
|
roles: ['admin'],
|
||||||
icon: 'iconfont icon-diannao',
|
icon: 'iconfont icon-wenducanshu-05',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -23,10 +23,7 @@ export const useThemeConfig = defineStore('themeConfig', {
|
|||||||
isIsDark: false,
|
isIsDark: false,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 菜单 / 顶栏
|
* 顶栏设置
|
||||||
* 注意:v1.0.17 版本去除设置布局切换,重置主题样式(initSetLayoutChange),
|
|
||||||
* 切换布局需手动设置样式,设置的样式自动同步各布局,
|
|
||||||
* 代码位置:/@/layout/navBars/breadcrumb/setings.vue
|
|
||||||
*/
|
*/
|
||||||
// 默认顶栏导航背景颜色
|
// 默认顶栏导航背景颜色
|
||||||
topBar: '#ffffff',
|
topBar: '#ffffff',
|
||||||
@ -34,12 +31,22 @@ export const useThemeConfig = defineStore('themeConfig', {
|
|||||||
topBarColor: '#606266',
|
topBarColor: '#606266',
|
||||||
// 是否开启顶栏背景颜色渐变
|
// 是否开启顶栏背景颜色渐变
|
||||||
isTopBarColorGradual: false,
|
isTopBarColorGradual: false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 菜单设置
|
||||||
|
*/
|
||||||
// 默认菜单导航背景颜色
|
// 默认菜单导航背景颜色
|
||||||
menuBar: '#545c64',
|
menuBar: '#545c64',
|
||||||
// 默认菜单导航字体颜色
|
// 默认菜单导航字体颜色
|
||||||
menuBarColor: '#eaeaea',
|
menuBarColor: '#eaeaea',
|
||||||
|
// 默认菜单高亮背景色
|
||||||
|
menuBarActiveColor: 'rgba(0, 0, 0, 0.2)',
|
||||||
// 是否开启菜单背景颜色渐变
|
// 是否开启菜单背景颜色渐变
|
||||||
isMenuBarColorGradual: false,
|
isMenuBarColorGradual: false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分栏设置
|
||||||
|
*/
|
||||||
// 默认分栏菜单背景颜色
|
// 默认分栏菜单背景颜色
|
||||||
columnsMenuBar: '#545c64',
|
columnsMenuBar: '#545c64',
|
||||||
// 默认分栏菜单字体颜色
|
// 默认分栏菜单字体颜色
|
||||||
@ -89,7 +96,7 @@ export const useThemeConfig = defineStore('themeConfig', {
|
|||||||
// 是否开启 TagsView 共用
|
// 是否开启 TagsView 共用
|
||||||
isShareTagsView: false,
|
isShareTagsView: false,
|
||||||
// 是否开启 Footer 底部版权信息
|
// 是否开启 Footer 底部版权信息
|
||||||
isFooter: true,
|
isFooter: false,
|
||||||
// 是否开启灰色模式
|
// 是否开启灰色模式
|
||||||
isGrayscale: false,
|
isGrayscale: false,
|
||||||
// 是否开启色弱模式
|
// 是否开启色弱模式
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
--next-bg-topBarColor: var(--next-color-bar) !important;
|
--next-bg-topBarColor: var(--next-color-bar) !important;
|
||||||
--next-bg-menuBar: var(--next-color-disabled) !important;
|
--next-bg-menuBar: var(--next-color-disabled) !important;
|
||||||
--next-bg-menuBarColor: var(--next-color-bar) !important;
|
--next-bg-menuBarColor: var(--next-color-bar) !important;
|
||||||
|
--next-bg-menuBarActiveColor: var(--next-color-hover-rgba) !important;
|
||||||
--next-bg-columnsMenuBar: var(--next-color-disabled) !important;
|
--next-bg-columnsMenuBar: var(--next-color-disabled) !important;
|
||||||
--next-bg-columnsMenuBarColor: var(--next-color-bar) !important;
|
--next-bg-columnsMenuBarColor: var(--next-color-bar) !important;
|
||||||
--next-border-color-light: var(--next-border-black) !important;
|
--next-border-color-light: var(--next-border-black) !important;
|
||||||
|
|||||||
@ -19,9 +19,6 @@
|
|||||||
|
|
||||||
/* Input 输入框、InputNumber 计数器
|
/* Input 输入框、InputNumber 计数器
|
||||||
------------------------------- */
|
------------------------------- */
|
||||||
.el-input {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
// 菜单搜索
|
// 菜单搜索
|
||||||
.el-autocomplete-suggestion__wrap {
|
.el-autocomplete-suggestion__wrap {
|
||||||
max-height: 280px !important;
|
max-height: 280px !important;
|
||||||
@ -71,7 +68,7 @@
|
|||||||
------------------------------- */
|
------------------------------- */
|
||||||
// 鼠标 hover 时颜色
|
// 鼠标 hover 时颜色
|
||||||
.el-menu-hover-bg-color {
|
.el-menu-hover-bg-color {
|
||||||
background-color: var(--next-color-menu-hover) !important;
|
background-color: var(--next-bg-menuBarActiveColor) !important;
|
||||||
}
|
}
|
||||||
// 默认样式修改
|
// 默认样式修改
|
||||||
.el-menu {
|
.el-menu {
|
||||||
@ -111,6 +108,9 @@
|
|||||||
.el-sub-menu:not(.is-opened):hover .el-sub-menu__title {
|
.el-sub-menu:not(.is-opened):hover .el-sub-menu__title {
|
||||||
@extend .el-menu-hover-bg-color;
|
@extend .el-menu-hover-bg-color;
|
||||||
}
|
}
|
||||||
|
.el-menu-item:hover {
|
||||||
|
@extend .el-menu-hover-bg-color;
|
||||||
|
}
|
||||||
.el-sub-menu.is-active.is-opened .el-sub-menu__title {
|
.el-sub-menu.is-active.is-opened .el-sub-menu__title {
|
||||||
background-color: unset !important;
|
background-color: unset !important;
|
||||||
}
|
}
|
||||||
@ -282,6 +282,10 @@
|
|||||||
.layout-container-view .el-scrollbar__view {
|
.layout-container-view .el-scrollbar__view {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
/*防止分栏布局二级菜单很多时,滚动条消失问题*/
|
||||||
|
.layout-columns-warp .layout-aside .el-scrollbar__view {
|
||||||
|
height: unset !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Pagination 分页
|
/* Pagination 分页
|
||||||
------------------------------- */
|
------------------------------- */
|
||||||
|
|||||||
@ -5,64 +5,25 @@
|
|||||||
.icon-selector-warp {
|
.icon-selector-warp {
|
||||||
height: 260px;
|
height: 260px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
.icon-selector-warp-title {
|
.icon-selector-warp-title {
|
||||||
|
position: absolute;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
padding: 0 15px;
|
left: 15px;
|
||||||
.icon-selector-warp-title-tab {
|
|
||||||
span {
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
color: var(--el-color-primary);
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.span-active {
|
|
||||||
color: var(--el-color-primary);
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.icon-selector-warp-row {
|
.el-tabs__header {
|
||||||
height: 230px;
|
display: flex;
|
||||||
overflow: hidden;
|
justify-content: flex-end;
|
||||||
border-top: 1px solid var(--el-border-color);
|
padding: 0 15px;
|
||||||
.el-row {
|
border-bottom: 1px solid var(--el-border-color-light);
|
||||||
padding: 15px;
|
margin: 0 !important;
|
||||||
}
|
.el-tabs__nav-wrap {
|
||||||
.el-scrollbar__bar.is-horizontal {
|
&::after {
|
||||||
display: none;
|
height: 0 !important;
|
||||||
}
|
|
||||||
.icon-selector-warp-item {
|
|
||||||
display: flex;
|
|
||||||
border: 1px solid var(--el-border-color);
|
|
||||||
padding: 5px;
|
|
||||||
border-radius: 5px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
.icon-selector-warp-item-value {
|
|
||||||
i {
|
|
||||||
font-size: 20px;
|
|
||||||
color: var(--el-text-color-regular);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
&:hover {
|
.el-tabs__item {
|
||||||
cursor: pointer;
|
padding: 0 5px !important;
|
||||||
background-color: var(--el-color-primary-light-9);
|
|
||||||
border: 1px solid var(--el-color-primary-light-5);
|
|
||||||
.icon-selector-warp-item-value {
|
|
||||||
i {
|
|
||||||
color: var(--el-color-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.icon-selector-active {
|
|
||||||
background-color: var(--el-color-primary-light-9);
|
|
||||||
border: 1px solid var(--el-color-primary-light-5);
|
|
||||||
.icon-selector-warp-item-value {
|
|
||||||
i {
|
|
||||||
color: var(--el-color-primary);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
@import 'common/transition.scss';
|
@import 'common/transition.scss';
|
||||||
@import './other.scss';
|
@import './other.scss';
|
||||||
@import './element.scss';
|
@import './element.scss';
|
||||||
@import './iconSelector.scss';
|
|
||||||
@import './media/media.scss';
|
@import './media/media.scss';
|
||||||
@import './waves.scss';
|
@import './waves.scss';
|
||||||
@import './dark.scss';
|
@import './dark.scss';
|
||||||
|
|||||||
@ -16,4 +16,16 @@
|
|||||||
// 响应式表单时,登录页需要重新处理
|
// 响应式表单时,登录页需要重新处理
|
||||||
display: unset !important;
|
display: unset !important;
|
||||||
}
|
}
|
||||||
|
// 表格演示中的表单筛选
|
||||||
|
.table-form-btn {
|
||||||
|
display: flex !important;
|
||||||
|
.el-form-item__label {
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 表格演示中的表单筛选最大高度,适配移动端
|
||||||
|
.table-search-container {
|
||||||
|
max-height: 160px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,18 +8,20 @@
|
|||||||
height: 40px;
|
height: 40px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.tool-item {
|
.tool-sortable {
|
||||||
display: flex;
|
max-height: 303px;
|
||||||
box-sizing: border-box;
|
.tool-sortable-item {
|
||||||
color: var(--el-text-color-primary);
|
display: flex;
|
||||||
height: 35px;
|
box-sizing: border-box;
|
||||||
align-items: center;
|
color: var(--el-text-color-primary);
|
||||||
padding: var(--el-popover-padding);
|
align-items: center;
|
||||||
&:hover {
|
padding: 0 12px;
|
||||||
background: var(--el-fill-color-lighter);
|
&:hover {
|
||||||
}
|
background: var(--el-fill-color-lighter);
|
||||||
i {
|
}
|
||||||
opacity: 0.7;
|
i {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/types/global.d.ts
vendored
1
src/types/global.d.ts
vendored
@ -5,6 +5,7 @@ declare module 'splitpanes';
|
|||||||
declare module 'js-cookie';
|
declare module 'js-cookie';
|
||||||
declare module '@wangeditor/editor-for-vue';
|
declare module '@wangeditor/editor-for-vue';
|
||||||
declare module 'js-table2excel';
|
declare module 'js-table2excel';
|
||||||
|
declare module 'qs';
|
||||||
|
|
||||||
// 声明一个模块,防止引入文件时报错
|
// 声明一个模块,防止引入文件时报错
|
||||||
declare module '*.json';
|
declare module '*.json';
|
||||||
|
|||||||
1
src/types/pinia.d.ts
vendored
1
src/types/pinia.d.ts
vendored
@ -48,6 +48,7 @@ declare interface ThemeConfigState {
|
|||||||
isTopBarColorGradual: boolean;
|
isTopBarColorGradual: boolean;
|
||||||
menuBar: string;
|
menuBar: string;
|
||||||
menuBarColor: string;
|
menuBarColor: string;
|
||||||
|
menuBarActiveColor: string;
|
||||||
isMenuBarColorGradual: boolean;
|
isMenuBarColorGradual: boolean;
|
||||||
columnsMenuBar: string;
|
columnsMenuBar: string;
|
||||||
columnsMenuBarColor: string;
|
columnsMenuBarColor: string;
|
||||||
|
|||||||
15
src/types/views.d.ts
vendored
15
src/types/views.d.ts
vendored
@ -43,7 +43,6 @@ declare type Demo2State<T = any> = {
|
|||||||
earth3DBtnList: T[];
|
earth3DBtnList: T[];
|
||||||
chartData4List: T[];
|
chartData4List: T[];
|
||||||
myCharts: T[];
|
myCharts: T[];
|
||||||
the3DEarth: HTMLDivElement | null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -243,8 +242,6 @@ declare type XyState = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
declare type WorkflowState<T = any> = {
|
declare type WorkflowState<T = any> = {
|
||||||
workflowRightRef: HTMLDivElement | null;
|
|
||||||
leftNavRefs: HTMLElement[];
|
|
||||||
leftNavList: T[];
|
leftNavList: T[];
|
||||||
dropdownNode: XyState;
|
dropdownNode: XyState;
|
||||||
dropdownLine: XyState;
|
dropdownLine: XyState;
|
||||||
@ -305,11 +302,19 @@ declare type TableHeaderType = {
|
|||||||
isCheck: boolean;
|
isCheck: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
declare type TableSearchType = {
|
||||||
|
label: string;
|
||||||
|
prop: string;
|
||||||
|
placeholder: string;
|
||||||
|
required: boolean;
|
||||||
|
type: string;
|
||||||
|
options?: SelectOptionType[];
|
||||||
|
};
|
||||||
|
|
||||||
declare type TableDemoState = {
|
declare type TableDemoState = {
|
||||||
tableData: {
|
tableData: {
|
||||||
data: EmptyObjectType[];
|
data: EmptyObjectType[];
|
||||||
header: TableHeaderType[];
|
header: TableHeaderType[];
|
||||||
param: EmptyObjectType;
|
|
||||||
config: {
|
config: {
|
||||||
total: number;
|
total: number;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
@ -318,5 +323,7 @@ declare type TableDemoState = {
|
|||||||
isSerialNo: boolean;
|
isSerialNo: boolean;
|
||||||
isOperate: boolean;
|
isOperate: boolean;
|
||||||
};
|
};
|
||||||
|
search: TableSearchType[];
|
||||||
|
param: EmptyObjectType;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -53,8 +53,11 @@ export function useTitle() {
|
|||||||
export function setTagsViewNameI18n(item: any) {
|
export function setTagsViewNameI18n(item: any) {
|
||||||
let tagsViewName: string = '';
|
let tagsViewName: string = '';
|
||||||
const { query, params, meta } = item;
|
const { query, params, meta } = item;
|
||||||
|
// 修复tagsViewName匹配到其他含下列单词的路由
|
||||||
|
// https://gitee.com/lyt-top/vue-next-admin/pulls/44/files
|
||||||
|
const pattern = /^\{("(zh-cn|en|zh-tw)":"[^,]+",?){1,3}}$/;
|
||||||
if (query?.tagsViewName || params?.tagsViewName) {
|
if (query?.tagsViewName || params?.tagsViewName) {
|
||||||
if (/\/zh-cn|en|zh-tw\//.test(query?.tagsViewName) || /\/zh-cn|en|zh-tw\//.test(params?.tagsViewName)) {
|
if (pattern.test(query?.tagsViewName) || pattern.test(params?.tagsViewName)) {
|
||||||
// 国际化
|
// 国际化
|
||||||
const urlTagsParams = (query?.tagsViewName && JSON.parse(query?.tagsViewName)) || (params?.tagsViewName && JSON.parse(params?.tagsViewName));
|
const urlTagsParams = (query?.tagsViewName && JSON.parse(query?.tagsViewName)) || (params?.tagsViewName && JSON.parse(params?.tagsViewName));
|
||||||
tagsViewName = urlTagsParams[i18n.global.locale.value];
|
tagsViewName = urlTagsParams[i18n.global.locale.value];
|
||||||
|
|||||||
@ -1,17 +1,23 @@
|
|||||||
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
|
import axios, { AxiosInstance } from 'axios';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
import { Session } from '/@/utils/storage';
|
import { Session } from '/@/utils/storage';
|
||||||
|
import qs from 'qs';
|
||||||
|
|
||||||
// 配置新建一个 axios 实例
|
// 配置新建一个 axios 实例
|
||||||
const service: AxiosInstance = axios.create({
|
const service: AxiosInstance = axios.create({
|
||||||
baseURL: import.meta.env.VITE_API_URL,
|
baseURL: import.meta.env.VITE_API_URL,
|
||||||
timeout: 50000,
|
timeout: 50000,
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
paramsSerializer: {
|
||||||
|
serialize(params) {
|
||||||
|
return qs.stringify(params, { allowDots: true });
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 添加请求拦截器
|
// 添加请求拦截器
|
||||||
service.interceptors.request.use(
|
service.interceptors.request.use(
|
||||||
(config: AxiosRequestConfig) => {
|
(config) => {
|
||||||
// 在发送请求之前做些什么 token
|
// 在发送请求之前做些什么 token
|
||||||
if (Session.get('token')) {
|
if (Session.get('token')) {
|
||||||
config.headers!['Authorization'] = `${Session.get('token')}`;
|
config.headers!['Authorization'] = `${Session.get('token')}`;
|
||||||
|
|||||||
@ -8,18 +8,23 @@ import Cookies from 'js-cookie';
|
|||||||
* @method clear 移除全部永久缓存
|
* @method clear 移除全部永久缓存
|
||||||
*/
|
*/
|
||||||
export const Local = {
|
export const Local = {
|
||||||
|
// 查看 v2.4.3版本更新日志
|
||||||
|
setKey(key: string) {
|
||||||
|
// @ts-ignore
|
||||||
|
return `${__NEXT_NAME__}:${key}`;
|
||||||
|
},
|
||||||
// 设置永久缓存
|
// 设置永久缓存
|
||||||
set(key: string, val: any) {
|
set<T>(key: string, val: T) {
|
||||||
window.localStorage.setItem(key, JSON.stringify(val));
|
window.localStorage.setItem(Local.setKey(key), JSON.stringify(val));
|
||||||
},
|
},
|
||||||
// 获取永久缓存
|
// 获取永久缓存
|
||||||
get(key: string) {
|
get(key: string) {
|
||||||
let json = <string>window.localStorage.getItem(key);
|
let json = <string>window.localStorage.getItem(Local.setKey(key));
|
||||||
return JSON.parse(json);
|
return JSON.parse(json);
|
||||||
},
|
},
|
||||||
// 移除永久缓存
|
// 移除永久缓存
|
||||||
remove(key: string) {
|
remove(key: string) {
|
||||||
window.localStorage.removeItem(key);
|
window.localStorage.removeItem(Local.setKey(key));
|
||||||
},
|
},
|
||||||
// 移除全部永久缓存
|
// 移除全部永久缓存
|
||||||
clear() {
|
clear() {
|
||||||
@ -36,20 +41,20 @@ export const Local = {
|
|||||||
*/
|
*/
|
||||||
export const Session = {
|
export const Session = {
|
||||||
// 设置临时缓存
|
// 设置临时缓存
|
||||||
set(key: string, val: any) {
|
set<T>(key: string, val: T) {
|
||||||
if (key === 'token') return Cookies.set(key, val);
|
if (key === 'token') return Cookies.set(key, val);
|
||||||
window.sessionStorage.setItem(key, JSON.stringify(val));
|
window.sessionStorage.setItem(Local.setKey(key), JSON.stringify(val));
|
||||||
},
|
},
|
||||||
// 获取临时缓存
|
// 获取临时缓存
|
||||||
get(key: string) {
|
get(key: string) {
|
||||||
if (key === 'token') return Cookies.get(key);
|
if (key === 'token') return Cookies.get(key);
|
||||||
let json = <string>window.sessionStorage.getItem(key);
|
let json = <string>window.sessionStorage.getItem(Local.setKey(key));
|
||||||
return JSON.parse(json);
|
return JSON.parse(json);
|
||||||
},
|
},
|
||||||
// 移除临时缓存
|
// 移除临时缓存
|
||||||
remove(key: string) {
|
remove(key: string) {
|
||||||
if (key === 'token') return Cookies.remove(key);
|
if (key === 'token') return Cookies.remove(key);
|
||||||
window.sessionStorage.removeItem(key);
|
window.sessionStorage.removeItem(Local.setKey(key));
|
||||||
},
|
},
|
||||||
// 移除全部临时缓存
|
// 移除全部临时缓存
|
||||||
clear() {
|
clear() {
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import { useRouter } from 'vue-router';
|
|||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
// 返回首页
|
||||||
const onGoHome = () => {
|
const onGoHome = () => {
|
||||||
router.push('/');
|
router.push('/');
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,18 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="layout-padding">
|
<div class="layout-padding">
|
||||||
<div class="layout-padding-auto layout-padding-view">
|
<div class="layout-padding-auto layout-padding-view">
|
||||||
<div ref="echartsMap" style="height: 100%"></div>
|
<div ref="echartsMapRef" style="height: 100%"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="funEchartsMap">
|
<script setup lang="ts" name="funEchartsMap">
|
||||||
import { reactive, onMounted } from 'vue';
|
import { reactive, onMounted, ref } from 'vue';
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import 'echarts/extension/bmap/bmap';
|
import 'echarts/extension/bmap/bmap';
|
||||||
import { echartsMapList, echartsMapData } from './mock';
|
import { echartsMapList, echartsMapData } from './mock';
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
|
const echartsMapRef = ref<RefType>('');
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
echartsMap: '' as unknown,
|
echartsMap: '' as unknown,
|
||||||
echartsMapList,
|
echartsMapList,
|
||||||
@ -35,7 +36,7 @@ const convertData = (data: EmptyObjectType[]) => {
|
|||||||
};
|
};
|
||||||
// 初始化 echartsMap
|
// 初始化 echartsMap
|
||||||
const initEchartsMap = () => {
|
const initEchartsMap = () => {
|
||||||
const myChart = echarts.init(<HTMLElement>state.echartsMap);
|
const myChart = echarts.init(echartsMapRef.value);
|
||||||
const option = {
|
const option = {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'item',
|
trigger: 'item',
|
||||||
|
|||||||
@ -66,7 +66,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="home">
|
<script setup lang="ts" name="home">
|
||||||
import { reactive, onMounted, ref, watch, nextTick, onActivated } from 'vue';
|
import { reactive, onMounted, ref, watch, nextTick, onActivated, markRaw } from 'vue';
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||||
@ -192,7 +192,7 @@ const state = reactive({
|
|||||||
// 折线图
|
// 折线图
|
||||||
const initLineChart = () => {
|
const initLineChart = () => {
|
||||||
if (!state.global.dispose.some((b: any) => b === state.global.homeChartOne)) state.global.homeChartOne.dispose();
|
if (!state.global.dispose.some((b: any) => b === state.global.homeChartOne)) state.global.homeChartOne.dispose();
|
||||||
state.global.homeChartOne = echarts.init(homeLineRef.value, state.charts.theme);
|
state.global.homeChartOne = markRaw(echarts.init(homeLineRef.value, state.charts.theme));
|
||||||
const option = {
|
const option = {
|
||||||
backgroundColor: state.charts.bgColor,
|
backgroundColor: state.charts.bgColor,
|
||||||
title: {
|
title: {
|
||||||
@ -274,7 +274,7 @@ const initLineChart = () => {
|
|||||||
// 饼图
|
// 饼图
|
||||||
const initPieChart = () => {
|
const initPieChart = () => {
|
||||||
if (!state.global.dispose.some((b: any) => b === state.global.homeChartTwo)) state.global.homeChartTwo.dispose();
|
if (!state.global.dispose.some((b: any) => b === state.global.homeChartTwo)) state.global.homeChartTwo.dispose();
|
||||||
state.global.homeChartTwo = echarts.init(homePieRef.value, state.charts.theme);
|
state.global.homeChartTwo = markRaw(echarts.init(homePieRef.value, state.charts.theme));
|
||||||
var getname = ['房屋及结构物', '专用设备', '通用设备', '文物和陈列品', '图书、档案'];
|
var getname = ['房屋及结构物', '专用设备', '通用设备', '文物和陈列品', '图书、档案'];
|
||||||
var getvalue = [34.2, 38.87, 17.88, 9.05, 2.05];
|
var getvalue = [34.2, 38.87, 17.88, 9.05, 2.05];
|
||||||
var data = [];
|
var data = [];
|
||||||
@ -359,7 +359,7 @@ const initPieChart = () => {
|
|||||||
// 柱状图
|
// 柱状图
|
||||||
const initBarChart = () => {
|
const initBarChart = () => {
|
||||||
if (!state.global.dispose.some((b: any) => b === state.global.homeCharThree)) state.global.homeCharThree.dispose();
|
if (!state.global.dispose.some((b: any) => b === state.global.homeCharThree)) state.global.homeCharThree.dispose();
|
||||||
state.global.homeCharThree = echarts.init(homeBarRef.value, state.charts.theme);
|
state.global.homeCharThree = markRaw(echarts.init(homeBarRef.value, state.charts.theme));
|
||||||
const option = {
|
const option = {
|
||||||
backgroundColor: state.charts.bgColor,
|
backgroundColor: state.charts.bgColor,
|
||||||
title: {
|
title: {
|
||||||
|
|||||||
@ -100,37 +100,41 @@ const onSignIn = async () => {
|
|||||||
Cookies.set('userName', state.ruleForm.userName);
|
Cookies.set('userName', state.ruleForm.userName);
|
||||||
if (!themeConfig.value.isRequestRoutes) {
|
if (!themeConfig.value.isRequestRoutes) {
|
||||||
// 前端控制路由,2、请注意执行顺序
|
// 前端控制路由,2、请注意执行顺序
|
||||||
await initFrontEndControlRoutes();
|
const isNoPower = await initFrontEndControlRoutes();
|
||||||
signInSuccess();
|
signInSuccess(isNoPower);
|
||||||
} else {
|
} else {
|
||||||
// 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
|
// 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
|
||||||
// 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/"
|
// 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/"
|
||||||
await initBackEndControlRoutes();
|
const isNoPower = await initBackEndControlRoutes();
|
||||||
// 执行完 initBackEndControlRoutes,再执行 signInSuccess
|
// 执行完 initBackEndControlRoutes,再执行 signInSuccess
|
||||||
signInSuccess();
|
signInSuccess(isNoPower);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// 登录成功后的跳转
|
// 登录成功后的跳转
|
||||||
const signInSuccess = () => {
|
const signInSuccess = (isNoPower: boolean | undefined) => {
|
||||||
// 初始化登录成功时间问候语
|
if (isNoPower) {
|
||||||
let currentTimeInfo = currentTime.value;
|
ElMessage.warning('抱歉,您没有登录权限');
|
||||||
// 登录成功,跳到转首页
|
Session.clear();
|
||||||
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
|
|
||||||
if (route.query?.redirect) {
|
|
||||||
router.push({
|
|
||||||
path: <string>route.query?.redirect,
|
|
||||||
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
router.push('/');
|
// 初始化登录成功时间问候语
|
||||||
|
let currentTimeInfo = currentTime.value;
|
||||||
|
// 登录成功,跳到转首页
|
||||||
|
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
|
||||||
|
if (route.query?.redirect) {
|
||||||
|
router.push({
|
||||||
|
path: <string>route.query?.redirect,
|
||||||
|
query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
router.push('/');
|
||||||
|
}
|
||||||
|
// 登录成功提示
|
||||||
|
const signInText = t('message.signInText');
|
||||||
|
ElMessage.success(`${currentTimeInfo},${signInText}`);
|
||||||
|
// 添加 loading,防止第一次进入界面时出现短暂空白
|
||||||
|
NextLoading.start();
|
||||||
}
|
}
|
||||||
// 登录成功提示
|
state.loading.signIn = false;
|
||||||
// 关闭 loading
|
|
||||||
state.loading.signIn = true;
|
|
||||||
const signInText = t('message.signInText');
|
|
||||||
ElMessage.success(`${currentTimeInfo},${signInText}`);
|
|
||||||
// 添加 loading,防止第一次进入界面时出现短暂空白
|
|
||||||
NextLoading.start();
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -35,6 +35,13 @@ const IconSelector = defineAsyncComponent(() => import('/@/components/iconSelect
|
|||||||
const state = reactive({
|
const state = reactive({
|
||||||
modelIcon: '',
|
modelIcon: '',
|
||||||
tableData: [
|
tableData: [
|
||||||
|
{
|
||||||
|
a1: 'v-model',
|
||||||
|
a2: '双向绑定值',
|
||||||
|
a3: 'string',
|
||||||
|
a4: '',
|
||||||
|
a5: '',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
a1: 'prepend',
|
a1: 'prepend',
|
||||||
a2: '输入框前置内容,只能字体图标',
|
a2: '输入框前置内容,只能字体图标',
|
||||||
@ -63,13 +70,6 @@ const state = reactive({
|
|||||||
a4: '',
|
a4: '',
|
||||||
a5: '请选择图标',
|
a5: '请选择图标',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
a1: 'type',
|
|
||||||
a2: 'icon 图标类型',
|
|
||||||
a3: 'string',
|
|
||||||
a4: 'ali / ele / awe / all',
|
|
||||||
a5: 'ele',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
a1: 'disabled',
|
a1: 'disabled',
|
||||||
a2: '禁用',
|
a2: '禁用',
|
||||||
|
|||||||
@ -1,15 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="table-demo-container layout-padding">
|
<div class="table-demo-container layout-padding">
|
||||||
<div class="table-demo-padding layout-padding-view layout-padding-auto">
|
<div class="table-demo-padding layout-padding-view layout-padding-auto">
|
||||||
<div class="system-user-search mb15">
|
<TableSearch :search="state.tableData.search" @search="onSearch" />
|
||||||
<el-input v-model="state.tableData.param.search" size="default" placeholder="请输入核酸采样点名称" style="max-width: 180px" />
|
|
||||||
<el-button size="default" type="primary" class="ml10" @click="onSearch">
|
|
||||||
<el-icon>
|
|
||||||
<ele-Search />
|
|
||||||
</el-icon>
|
|
||||||
查询
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
<Table
|
<Table
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
v-bind="state.tableData"
|
v-bind="state.tableData"
|
||||||
@ -28,6 +20,7 @@ import { ElMessage } from 'element-plus';
|
|||||||
|
|
||||||
// 引入组件
|
// 引入组件
|
||||||
const Table = defineAsyncComponent(() => import('/@/components/table/index.vue'));
|
const Table = defineAsyncComponent(() => import('/@/components/table/index.vue'));
|
||||||
|
const TableSearch = defineAsyncComponent(() => import('/@/views/make/tableDemo/search.vue'));
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const tableRef = ref<RefType>();
|
const tableRef = ref<RefType>();
|
||||||
@ -44,10 +37,6 @@ const state = reactive<TableDemoState>({
|
|||||||
{ key: 'isSupport', colWidth: '', title: '是否支持24小时核酸检测', type: 'text', isCheck: true },
|
{ key: 'isSupport', colWidth: '', title: '是否支持24小时核酸检测', type: 'text', isCheck: true },
|
||||||
{ key: 'image', colWidth: '', width: '70', height: '40', title: '图片描述', type: 'image', isCheck: true },
|
{ key: 'image', colWidth: '', width: '70', height: '40', title: '图片描述', type: 'image', isCheck: true },
|
||||||
],
|
],
|
||||||
// 搜索参数(可选)
|
|
||||||
param: {
|
|
||||||
search: '',
|
|
||||||
},
|
|
||||||
// 配置项(必传)
|
// 配置项(必传)
|
||||||
config: {
|
config: {
|
||||||
total: 0, // 列表总数
|
total: 0, // 列表总数
|
||||||
@ -57,6 +46,31 @@ const state = reactive<TableDemoState>({
|
|||||||
isSelection: true, // 是否显示表格多选
|
isSelection: true, // 是否显示表格多选
|
||||||
isOperate: true, // 是否显示表格操作栏
|
isOperate: true, // 是否显示表格操作栏
|
||||||
},
|
},
|
||||||
|
// 搜索表单,动态生成(传空数组时,将不显示搜索,注意格式)
|
||||||
|
search: [
|
||||||
|
{ label: '采样点名称', prop: 'name', placeholder: '请输入应检尽检核酸采样点名称', required: true, type: 'input' },
|
||||||
|
{ label: '详细地址', prop: 'address', placeholder: '请输入详细地址', required: false, type: 'input' },
|
||||||
|
{ label: '联系电话', prop: 'phone', placeholder: '请输入采样点联系电话', required: false, type: 'input' },
|
||||||
|
{ label: '开放时间', prop: 'time', placeholder: '请选择', required: false, type: 'date' },
|
||||||
|
{
|
||||||
|
label: '支持24小时',
|
||||||
|
prop: 'isSupport',
|
||||||
|
placeholder: '请选择',
|
||||||
|
required: false,
|
||||||
|
type: 'select',
|
||||||
|
options: [
|
||||||
|
{ label: '是', value: 1 },
|
||||||
|
{ label: '否', value: 0 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ label: '图片描述', prop: 'image', placeholder: '请输入图片描述', required: false, type: 'input' },
|
||||||
|
{ label: '核酸机构', prop: 'mechanism', placeholder: '请输入核酸机构', required: false, type: 'input' },
|
||||||
|
],
|
||||||
|
// 搜索参数(不用传,用于分页、搜索时传给后台的值,`getTableData` 中使用)
|
||||||
|
param: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -81,8 +95,9 @@ const getTableData = () => {
|
|||||||
state.tableData.config.loading = false;
|
state.tableData.config.loading = false;
|
||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
// 搜索
|
// 搜索点击时表单回调
|
||||||
const onSearch = () => {
|
const onSearch = (data: EmptyObjectType) => {
|
||||||
|
state.tableData.param = Object.assign({}, state.tableData.param, { ...data });
|
||||||
tableRef.value.pageReset();
|
tableRef.value.pageReset();
|
||||||
};
|
};
|
||||||
// 删除当前项回调
|
// 删除当前项回调
|
||||||
@ -100,7 +115,6 @@ const onTablePageChange = (page: TableDemoPageType) => {
|
|||||||
const onSortHeader = (data: TableHeaderType[]) => {
|
const onSortHeader = (data: TableHeaderType[]) => {
|
||||||
state.tableData.header = data;
|
state.tableData.header = data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 页面加载时
|
// 页面加载时
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getTableData();
|
getTableData();
|
||||||
|
|||||||
110
src/views/make/tableDemo/search.vue
Normal file
110
src/views/make/tableDemo/search.vue
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
<template>
|
||||||
|
<div class="table-search-container" v-if="props.search.length > 0">
|
||||||
|
<el-form ref="tableSearchRef" :model="state.form" size="default" label-width="100px" class="table-form">
|
||||||
|
<el-row>
|
||||||
|
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20" v-for="(val, key) in search" :key="key" v-show="key === 0 || state.isToggle">
|
||||||
|
<template v-if="val.type !== ''">
|
||||||
|
<el-form-item
|
||||||
|
:label="val.label"
|
||||||
|
:prop="val.prop"
|
||||||
|
:rules="[{ required: val.required, message: `${val.label}不能为空`, trigger: val.type === 'input' ? 'blur' : 'change' }]"
|
||||||
|
>
|
||||||
|
<el-input v-model="state.form[val.prop]" :placeholder="val.placeholder" clearable v-if="val.type === 'input'" style="width: 100%" />
|
||||||
|
<el-date-picker
|
||||||
|
v-model="state.form[val.prop]"
|
||||||
|
type="date"
|
||||||
|
:placeholder="val.placeholder"
|
||||||
|
v-else-if="val.type === 'date'"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
<el-select v-model="state.form[val.prop]" :placeholder="val.placeholder" v-else-if="val.type === 'select'" style="width: 100%">
|
||||||
|
<el-option v-for="item in val.options" :key="item.value" :label="item.label" :value="item.value"> </el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
||||||
|
<el-form-item class="table-form-btn" :label-width="search.length <= 1 ? '10px' : '100px'">
|
||||||
|
<template #label v-if="search.length > 1">
|
||||||
|
<div class="table-form-btn-toggle ml10" @click="state.isToggle = !state.isToggle">
|
||||||
|
<span>{{ state.isToggle ? '收筛选' : '展筛选' }}</span>
|
||||||
|
<SvgIcon :name="state.isToggle ? 'ele-ArrowUp' : 'ele-ArrowDown'" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div>
|
||||||
|
<el-button size="default" type="primary" @click="onSearch(tableSearchRef)">查询 </el-button>
|
||||||
|
<el-button size="default" type="info" class="ml10" @click="onReset(tableSearchRef)"> 重置 </el-button>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="makeTableDemoSearch">
|
||||||
|
import { reactive, ref, onMounted } from 'vue';
|
||||||
|
import type { FormInstance } from 'element-plus';
|
||||||
|
|
||||||
|
// 定义父组件传过来的值
|
||||||
|
const props = defineProps({
|
||||||
|
// 搜索表单
|
||||||
|
search: {
|
||||||
|
type: Array<TableSearchType>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 定义子组件向父组件传值/事件
|
||||||
|
const emit = defineEmits(['search']);
|
||||||
|
|
||||||
|
// 定义变量内容
|
||||||
|
const tableSearchRef = ref<FormInstance>();
|
||||||
|
const state = reactive({
|
||||||
|
form: {},
|
||||||
|
isToggle: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const onSearch = (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
formEl.validate((valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
emit('search', state.form);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 重置
|
||||||
|
const onReset = (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
formEl.resetFields();
|
||||||
|
emit('search', state.form);
|
||||||
|
};
|
||||||
|
// 初始化 form 字段,取自父组件 search.prop
|
||||||
|
const initFormField = () => {
|
||||||
|
if (props.search.length <= 0) return false;
|
||||||
|
props.search.forEach((v) => (state.form[v.prop] = ''));
|
||||||
|
};
|
||||||
|
// 页面加载时
|
||||||
|
onMounted(() => {
|
||||||
|
initFormField();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.table-search-container {
|
||||||
|
display: flex;
|
||||||
|
.table-form {
|
||||||
|
flex: 1;
|
||||||
|
.table-form-btn-toggle {
|
||||||
|
white-space: nowrap;
|
||||||
|
user-select: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -8,21 +8,12 @@
|
|||||||
element-loading-background="rgba(255, 255, 255, 0.1)"
|
element-loading-background="rgba(255, 255, 255, 0.1)"
|
||||||
:class="{ 'min-h-360': state.tableData.data.length <= 0 }"
|
:class="{ 'min-h-360': state.tableData.data.length <= 0 }"
|
||||||
>
|
>
|
||||||
<div
|
<div v-for="(val, key) in state.filtering" :key="key" ref="dlRefs" class="filtering-list-flex">
|
||||||
v-for="(val, key) in filtering"
|
|
||||||
:key="key"
|
|
||||||
:ref="
|
|
||||||
(el) => {
|
|
||||||
if (el) dlRefs[key] = el;
|
|
||||||
}
|
|
||||||
"
|
|
||||||
class="filtering-list-flex"
|
|
||||||
>
|
|
||||||
<div class="filtering-list-title">{{ val.title }}</div>
|
<div class="filtering-list-title">{{ val.title }}</div>
|
||||||
<div class="filtering-list-item" :style="{ height: val.isMore ? 'auto' : '50px' }">
|
<div class="filtering-list-item" :style="{ height: val.isMore ? 'auto' : '50px' }">
|
||||||
<span class="span" :class="v.active ? 'dd-active' : ''" v-for="(v, k) in val.children" :key="k" @click="onSelItem(val, v)">{{
|
<span class="span" :class="v.active ? 'dd-active' : ''" v-for="(v, k) in val.children" :key="k" @click="onSelItem(val, v)">
|
||||||
v.label
|
{{ v.label }}
|
||||||
}}</span>
|
</span>
|
||||||
<div class="dd-more" v-if="val.isShowMore" @click="val.isMore = !val.isMore">
|
<div class="dd-more" v-if="val.isShowMore" @click="val.isMore = !val.isMore">
|
||||||
<span>{{ val.isMore ? '收起' : '展开' }}</span>
|
<span>{{ val.isMore ? '收起' : '展开' }}</span>
|
||||||
<i :class="val.isMore ? 'el-icon-arrow-down' : 'el-icon-arrow-right'"></i>
|
<i :class="val.isMore ? 'el-icon-arrow-down' : 'el-icon-arrow-right'"></i>
|
||||||
|
|||||||
@ -15,8 +15,8 @@
|
|||||||
<span class="tree-custom-node">
|
<span class="tree-custom-node">
|
||||||
<span style="flex: 1">{{ node.label }}</span>
|
<span style="flex: 1">{{ node.label }}</span>
|
||||||
<span v-if="data.isShow" style="flex: 1; display: flex">
|
<span v-if="data.isShow" style="flex: 1; display: flex">
|
||||||
<span type="text" size="default" style="flex: 1">{{ data.label1 }}</span>
|
<span style="flex: 1">{{ data.label1 }}</span>
|
||||||
<span type="text" size="default" style="flex: 1">{{ data.label2 }}</span>
|
<span style="flex: 1">{{ data.label2 }}</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
<div
|
<div
|
||||||
ref="leftNavRefs"
|
ref="leftNavRefs"
|
||||||
v-for="val in leftNavList"
|
v-for="val in state.leftNavList"
|
||||||
:key="val.id"
|
:key="val.id"
|
||||||
:style="{ height: val.isOpen ? 'auto' : '50px', overflow: 'hidden' }"
|
:style="{ height: val.isOpen ? 'auto' : '50px', overflow: 'hidden' }"
|
||||||
class="workflow-left-id"
|
class="workflow-left-id"
|
||||||
@ -86,6 +86,8 @@ const Drawer = defineAsyncComponent(() => import('./component/drawer/index.vue')
|
|||||||
const Help = defineAsyncComponent(() => import('./component/tool/help.vue'));
|
const Help = defineAsyncComponent(() => import('./component/tool/help.vue'));
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
|
const leftNavRefs = ref([]);
|
||||||
|
const workflowRightRef = ref();
|
||||||
const contextmenuNodeRef = ref();
|
const contextmenuNodeRef = ref();
|
||||||
const contextmenuLineRef = ref();
|
const contextmenuLineRef = ref();
|
||||||
const drawerRef = ref();
|
const drawerRef = ref();
|
||||||
@ -95,8 +97,6 @@ const storesThemeConfig = useThemeConfig();
|
|||||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||||
const { copyText } = commonFunction();
|
const { copyText } = commonFunction();
|
||||||
const state = reactive<WorkflowState>({
|
const state = reactive<WorkflowState>({
|
||||||
workflowRightRef: null,
|
|
||||||
leftNavRefs: [],
|
|
||||||
leftNavList: [],
|
leftNavList: [],
|
||||||
dropdownNode: { x: '', y: '' },
|
dropdownNode: { x: '', y: '' },
|
||||||
dropdownLine: { x: '', y: '' },
|
dropdownLine: { x: '', y: '' },
|
||||||
@ -151,7 +151,7 @@ const initLeftNavList = () => {
|
|||||||
};
|
};
|
||||||
// 左侧导航-初始化拖动
|
// 左侧导航-初始化拖动
|
||||||
const initSortable = () => {
|
const initSortable = () => {
|
||||||
state.leftNavRefs.forEach((v) => {
|
leftNavRefs.value.forEach((v) => {
|
||||||
Sortable.create(v as HTMLDivElement, {
|
Sortable.create(v as HTMLDivElement, {
|
||||||
group: {
|
group: {
|
||||||
name: 'vue-next-admin-1',
|
name: 'vue-next-admin-1',
|
||||||
@ -165,7 +165,7 @@ const initSortable = () => {
|
|||||||
onEnd: function (evt: any) {
|
onEnd: function (evt: any) {
|
||||||
const { name, icon, id } = evt.clone.dataset;
|
const { name, icon, id } = evt.clone.dataset;
|
||||||
const { layerX, layerY, clientX, clientY } = evt.originalEvent;
|
const { layerX, layerY, clientX, clientY } = evt.originalEvent;
|
||||||
const el = state.workflowRightRef!;
|
const el = workflowRightRef.value!;
|
||||||
const { x, y, width, height } = el.getBoundingClientRect();
|
const { x, y, width, height } = el.getBoundingClientRect();
|
||||||
if (clientX < x || clientX > width + x || clientY < y || y > y + height) {
|
if (clientX < x || clientX > width + x || clientY < y || y > y + height) {
|
||||||
ElMessage.warning('请把节点拖入到画布中');
|
ElMessage.warning('请把节点拖入到画布中');
|
||||||
|
|||||||
@ -1,143 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="system-add-dept-container">
|
|
||||||
<el-dialog title="新增部门" v-model="state.isShowDialog" width="769px">
|
|
||||||
<el-form :model="state.ruleForm" size="default" label-width="90px">
|
|
||||||
<el-row :gutter="35">
|
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
|
||||||
<el-form-item label="上级部门">
|
|
||||||
<el-cascader
|
|
||||||
:options="state.deptData"
|
|
||||||
:props="{ checkStrictly: true, value: 'deptName', label: 'deptName' }"
|
|
||||||
placeholder="请选择部门"
|
|
||||||
clearable
|
|
||||||
class="w100"
|
|
||||||
v-model="state.ruleForm.deptLevel"
|
|
||||||
>
|
|
||||||
<template #default="{ node, data }">
|
|
||||||
<span>{{ data.deptName }}</span>
|
|
||||||
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
|
|
||||||
</template>
|
|
||||||
</el-cascader>
|
|
||||||
</el-form-item>
|
|
||||||
</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.deptName" placeholder="请输入部门名称" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</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.person" placeholder="请输入负责人" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</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.phone" placeholder="请输入手机号" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</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.email" placeholder="请输入" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="排序">
|
|
||||||
<el-input-number v-model="state.ruleForm.sort" :min="0" :max="999" controls-position="right" placeholder="请输入排序" class="w100" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="部门状态">
|
|
||||||
<el-switch v-model="state.ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
|
||||||
<el-form-item label="部门描述">
|
|
||||||
<el-input v-model="state.ruleForm.describe" type="textarea" placeholder="请输入部门描述" maxlength="150"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="onSubmit" size="default">新 增</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts" name="systemAddDept">
|
|
||||||
import { reactive, onMounted } from 'vue';
|
|
||||||
|
|
||||||
// 定义变量内容
|
|
||||||
const state = reactive({
|
|
||||||
isShowDialog: false,
|
|
||||||
ruleForm: {
|
|
||||||
deptLevel: [], // 上级部门
|
|
||||||
deptName: '', // 部门名称
|
|
||||||
person: '', // 负责人
|
|
||||||
phone: '', // 手机号
|
|
||||||
email: '', // 邮箱
|
|
||||||
sort: 0, // 排序
|
|
||||||
status: true, // 部门状态
|
|
||||||
describe: '', // 部门描述
|
|
||||||
},
|
|
||||||
deptData: [] as DeptTreeType[], // 部门数据
|
|
||||||
});
|
|
||||||
|
|
||||||
// 打开弹窗
|
|
||||||
const openDialog = () => {
|
|
||||||
state.isShowDialog = true;
|
|
||||||
};
|
|
||||||
// 关闭弹窗
|
|
||||||
const closeDialog = () => {
|
|
||||||
state.isShowDialog = false;
|
|
||||||
};
|
|
||||||
// 取消
|
|
||||||
const onCancel = () => {
|
|
||||||
closeDialog();
|
|
||||||
};
|
|
||||||
// 新增
|
|
||||||
const onSubmit = () => {
|
|
||||||
closeDialog();
|
|
||||||
};
|
|
||||||
// 初始化部门数据
|
|
||||||
const initTableData = () => {
|
|
||||||
state.deptData.push({
|
|
||||||
deptName: 'vueNextAdmin',
|
|
||||||
createTime: new Date().toLocaleString(),
|
|
||||||
status: true,
|
|
||||||
sort: Math.random(),
|
|
||||||
describe: '顶级部门',
|
|
||||||
id: Math.random(),
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
deptName: 'IT外包服务',
|
|
||||||
createTime: new Date().toLocaleString(),
|
|
||||||
status: true,
|
|
||||||
sort: Math.random(),
|
|
||||||
describe: '总部',
|
|
||||||
id: Math.random(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
deptName: '资本控股',
|
|
||||||
createTime: new Date().toLocaleString(),
|
|
||||||
status: true,
|
|
||||||
sort: Math.random(),
|
|
||||||
describe: '分部',
|
|
||||||
id: Math.random(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// 页面加载时
|
|
||||||
onMounted(() => {
|
|
||||||
initTableData();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 暴露变量
|
|
||||||
defineExpose({
|
|
||||||
openDialog,
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="system-edit-dept-container">
|
<div class="system-dept-dialog-container">
|
||||||
<el-dialog title="修改部门" v-model="state.isShowDialog" width="769px">
|
<el-dialog :title="state.dialog.title" v-model="state.dialog.isShowDialog" width="769px">
|
||||||
<el-form :model="state.ruleForm" size="default" label-width="90px">
|
<el-form ref="deptDialogFormRef" :model="state.ruleForm" size="default" label-width="90px">
|
||||||
<el-row :gutter="35">
|
<el-row :gutter="35">
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||||
<el-form-item label="上级部门">
|
<el-form-item label="上级部门">
|
||||||
@ -60,19 +60,22 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||||
<el-button type="primary" @click="onSubmit" size="default">修 改</el-button>
|
<el-button type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="systemEditDept">
|
<script setup lang="ts" name="systemDeptDialog">
|
||||||
import { reactive, onMounted } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
// 定义子组件向父组件传值/事件
|
||||||
|
const emit = defineEmits(['refresh']);
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
|
const deptDialogFormRef = ref();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
isShowDialog: false,
|
|
||||||
ruleForm: {
|
ruleForm: {
|
||||||
deptLevel: [] as string[], // 上级部门
|
deptLevel: [] as string[], // 上级部门
|
||||||
deptName: '', // 部门名称
|
deptName: '', // 部门名称
|
||||||
@ -84,31 +87,51 @@ const state = reactive({
|
|||||||
describe: '', // 部门描述
|
describe: '', // 部门描述
|
||||||
},
|
},
|
||||||
deptData: [] as DeptTreeType[], // 部门数据
|
deptData: [] as DeptTreeType[], // 部门数据
|
||||||
|
dialog: {
|
||||||
|
isShowDialog: false,
|
||||||
|
type: '',
|
||||||
|
title: '',
|
||||||
|
submitTxt: '',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 打开弹窗
|
// 打开弹窗
|
||||||
const openDialog = (row: RowDeptType) => {
|
const openDialog = (type: string, row: RowDeptType) => {
|
||||||
row.deptLevel = ['vueNextAdmin'];
|
if (type === 'edit') {
|
||||||
row.person = 'lyt';
|
row.deptLevel = ['vueNextAdmin'];
|
||||||
row.phone = '12345678910';
|
row.person = 'lyt';
|
||||||
row.email = 'vueNextAdmin@123.com';
|
row.phone = '12345678910';
|
||||||
state.ruleForm = row;
|
row.email = 'vueNextAdmin@123.com';
|
||||||
state.isShowDialog = true;
|
state.ruleForm = row;
|
||||||
|
state.dialog.title = '修改部门';
|
||||||
|
state.dialog.submitTxt = '修 改';
|
||||||
|
} else {
|
||||||
|
state.dialog.title = '新增部门';
|
||||||
|
state.dialog.submitTxt = '新 增';
|
||||||
|
// 清空表单,此项需加表单验证才能使用
|
||||||
|
// nextTick(() => {
|
||||||
|
// deptDialogFormRef.value.resetFields();
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
state.dialog.isShowDialog = true;
|
||||||
|
getMenuData();
|
||||||
};
|
};
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
const closeDialog = () => {
|
const closeDialog = () => {
|
||||||
state.isShowDialog = false;
|
state.dialog.isShowDialog = false;
|
||||||
};
|
};
|
||||||
// 取消
|
// 取消
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
closeDialog();
|
closeDialog();
|
||||||
};
|
};
|
||||||
// 新增
|
// 提交
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
closeDialog();
|
closeDialog();
|
||||||
|
emit('refresh');
|
||||||
|
// if (state.dialog.type === 'add') { }
|
||||||
};
|
};
|
||||||
// 初始化部门数据
|
// 初始化部门数据
|
||||||
const initTableData = () => {
|
const getMenuData = () => {
|
||||||
state.deptData.push({
|
state.deptData.push({
|
||||||
deptName: 'vueNextAdmin',
|
deptName: 'vueNextAdmin',
|
||||||
createTime: new Date().toLocaleString(),
|
createTime: new Date().toLocaleString(),
|
||||||
@ -136,10 +159,6 @@ const initTableData = () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// 页面加载时
|
|
||||||
onMounted(() => {
|
|
||||||
initTableData();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 暴露变量
|
// 暴露变量
|
||||||
defineExpose({
|
defineExpose({
|
||||||
@ -9,7 +9,7 @@
|
|||||||
</el-icon>
|
</el-icon>
|
||||||
查询
|
查询
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button size="default" type="success" class="ml10" @click="onOpenAddDept">
|
<el-button size="default" type="success" class="ml10" @click="onOpenAddDept('add')">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<ele-FolderAdd />
|
<ele-FolderAdd />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
@ -18,6 +18,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<el-table
|
<el-table
|
||||||
:data="state.tableData.data"
|
:data="state.tableData.data"
|
||||||
|
v-loading="state.tableData.loading"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
default-expand-all
|
default-expand-all
|
||||||
@ -39,15 +40,14 @@
|
|||||||
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
|
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="操作" show-overflow-tooltip width="140">
|
<el-table-column label="操作" show-overflow-tooltip width="140">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button size="small" text type="primary" @click="onOpenAddDept">新增</el-button>
|
<el-button size="small" text type="primary" @click="onOpenAddDept('add')">新增</el-button>
|
||||||
<el-button size="small" text type="primary" @click="onOpenEditDept(scope.row)">修改</el-button>
|
<el-button size="small" text type="primary" @click="onOpenEditDept('edit', scope.row)">修改</el-button>
|
||||||
<el-button size="small" text type="primary" @click="onTabelRowDel(scope.row)">删除</el-button>
|
<el-button size="small" text type="primary" @click="onTabelRowDel(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-card>
|
</el-card>
|
||||||
<AddDept ref="addDeptRef" />
|
<DeptDialog ref="deptDialogRef" @refresh="getTableData()" />
|
||||||
<EditDept ref="editDeptRef" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -56,12 +56,10 @@ import { defineAsyncComponent, ref, reactive, onMounted } from 'vue';
|
|||||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||||
|
|
||||||
// 引入组件
|
// 引入组件
|
||||||
const AddDept = defineAsyncComponent(() => import('/@/views/system/dept/component/addDept.vue'));
|
const DeptDialog = defineAsyncComponent(() => import('/@/views/system/dept/dialog.vue'));
|
||||||
const EditDept = defineAsyncComponent(() => import('/@/views/system/dept/component/editDept.vue'));
|
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const addDeptRef = ref();
|
const deptDialogRef = ref();
|
||||||
const editDeptRef = ref();
|
|
||||||
const state = reactive<SysDeptState>({
|
const state = reactive<SysDeptState>({
|
||||||
tableData: {
|
tableData: {
|
||||||
data: [],
|
data: [],
|
||||||
@ -75,7 +73,9 @@ const state = reactive<SysDeptState>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 初始化表格数据
|
// 初始化表格数据
|
||||||
const initTableData = () => {
|
const getTableData = () => {
|
||||||
|
state.tableData.loading = true;
|
||||||
|
state.tableData.data = [];
|
||||||
state.tableData.data.push({
|
state.tableData.data.push({
|
||||||
deptName: 'vueNextAdmin',
|
deptName: 'vueNextAdmin',
|
||||||
createTime: new Date().toLocaleString(),
|
createTime: new Date().toLocaleString(),
|
||||||
@ -103,14 +103,17 @@ const initTableData = () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
state.tableData.total = state.tableData.data.length;
|
state.tableData.total = state.tableData.data.length;
|
||||||
|
setTimeout(() => {
|
||||||
|
state.tableData.loading = false;
|
||||||
|
}, 500);
|
||||||
};
|
};
|
||||||
// 打开新增菜单弹窗
|
// 打开新增菜单弹窗
|
||||||
const onOpenAddDept = () => {
|
const onOpenAddDept = (type: string) => {
|
||||||
addDeptRef.value.openDialog();
|
deptDialogRef.value.openDialog(type);
|
||||||
};
|
};
|
||||||
// 打开编辑菜单弹窗
|
// 打开编辑菜单弹窗
|
||||||
const onOpenEditDept = (row: DeptTreeType) => {
|
const onOpenEditDept = (type: string, row: DeptTreeType) => {
|
||||||
editDeptRef.value.openDialog(row);
|
deptDialogRef.value.openDialog(type, row);
|
||||||
};
|
};
|
||||||
// 删除当前行
|
// 删除当前行
|
||||||
const onTabelRowDel = (row: DeptTreeType) => {
|
const onTabelRowDel = (row: DeptTreeType) => {
|
||||||
@ -120,12 +123,13 @@ const onTabelRowDel = (row: DeptTreeType) => {
|
|||||||
type: 'warning',
|
type: 'warning',
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
getTableData();
|
||||||
ElMessage.success('删除成功');
|
ElMessage.success('删除成功');
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
};
|
};
|
||||||
// 页面加载时
|
// 页面加载时
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initTableData();
|
getTableData();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,114 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="system-add-dic-container">
|
|
||||||
<el-dialog title="新增字典" v-model="state.isShowDialog" width="769px">
|
|
||||||
<el-alert title="半成品,交互过于复杂,请自行扩展!" type="warning" :closable="false" class="mb20"> </el-alert>
|
|
||||||
<el-form :model="state.ruleForm" size="default" label-width="90px">
|
|
||||||
<el-row :gutter="35">
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="字典名称">
|
|
||||||
<el-input v-model="state.ruleForm.dicName" placeholder="请输入字典名称" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</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="请输入字段名,拼接 ruleForm.list" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
|
||||||
<el-form-item label="字典状态">
|
|
||||||
<el-switch v-model="state.ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
|
||||||
<el-row :gutter="35" v-for="(v, k) in state.ruleForm.list" :key="k">
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item :prop="`list[${k}].label`">
|
|
||||||
<template #label>
|
|
||||||
<el-button type="primary" circle size="small" @click="onAddRow" v-if="k === 0">
|
|
||||||
<el-icon>
|
|
||||||
<ele-Plus />
|
|
||||||
</el-icon>
|
|
||||||
</el-button>
|
|
||||||
<el-button type="danger" circle size="small" @click="onDelRow(k)" v-else>
|
|
||||||
<el-icon>
|
|
||||||
<ele-Delete />
|
|
||||||
</el-icon>
|
|
||||||
</el-button>
|
|
||||||
<span class="ml10">字段</span>
|
|
||||||
</template>
|
|
||||||
<el-input v-model="v.label" style="width: 100%" placeholder="请输入字段名"> </el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="属性" :prop="`list[${k}].value`">
|
|
||||||
<el-input v-model="v.value" style="width: 100%" placeholder="请输入属性值"> </el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
|
||||||
<el-form-item label="字典描述">
|
|
||||||
<el-input v-model="state.ruleForm.describe" type="textarea" placeholder="请输入字典描述" maxlength="150"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="onSubmit" size="default">新 增</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts" name="systemAddDic">
|
|
||||||
import { reactive } from 'vue';
|
|
||||||
|
|
||||||
// 定义变量内容
|
|
||||||
const state = reactive({
|
|
||||||
isShowDialog: false,
|
|
||||||
ruleForm: {
|
|
||||||
dicName: '', // 字典名称
|
|
||||||
fieldName: '', // 字段名
|
|
||||||
status: true, // 字典状态
|
|
||||||
list: [] as ListType[], // 子集字段 + 属性值
|
|
||||||
describe: '', // 字典描述
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// 打开弹窗
|
|
||||||
const openDialog = () => {
|
|
||||||
state.isShowDialog = true;
|
|
||||||
};
|
|
||||||
// 关闭弹窗
|
|
||||||
const closeDialog = () => {
|
|
||||||
state.isShowDialog = false;
|
|
||||||
};
|
|
||||||
// 取消
|
|
||||||
const onCancel = () => {
|
|
||||||
closeDialog();
|
|
||||||
};
|
|
||||||
// 新增
|
|
||||||
const onSubmit = () => {
|
|
||||||
closeDialog();
|
|
||||||
};
|
|
||||||
// 新增行
|
|
||||||
const onAddRow = () => {
|
|
||||||
state.ruleForm.list.push({
|
|
||||||
id: Math.random(),
|
|
||||||
label: '',
|
|
||||||
value: '',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// 删除行
|
|
||||||
const onDelRow = (k: number) => {
|
|
||||||
state.ruleForm.list.splice(k, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 暴露变量
|
|
||||||
defineExpose({
|
|
||||||
openDialog,
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="system-edit-dic-container">
|
<div class="system-dic-dialog-container">
|
||||||
<el-dialog title="修改字典" v-model="state.isShowDialog" width="769px">
|
<el-dialog :title="state.dialog.title" v-model="state.dialog.isShowDialog" width="769px">
|
||||||
<el-alert title="半成品,交互过于复杂,请自行扩展!" type="warning" :closable="false" class="mb20"> </el-alert>
|
<el-alert title="半成品,交互过于复杂,请自行扩展!" type="warning" :closable="false" class="mb20"> </el-alert>
|
||||||
<el-form :model="state.ruleForm" size="default" label-width="90px">
|
<el-form ref="dicDialogFormRef" :model="state.ruleForm" size="default" label-width="90px">
|
||||||
<el-row :gutter="35">
|
<el-row :gutter="35">
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||||
<el-form-item label="字典名称">
|
<el-form-item label="字典名称">
|
||||||
@ -56,19 +56,22 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||||
<el-button type="primary" @click="onSubmit" size="default">修 改</el-button>
|
<el-button type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="systemEditDic">
|
<script setup lang="ts" name="systemDicDialog">
|
||||||
import { reactive } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
// 定义子组件向父组件传值/事件
|
||||||
|
const emit = defineEmits(['refresh']);
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
|
const dicDialogFormRef = ref();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
isShowDialog: false,
|
|
||||||
ruleForm: {
|
ruleForm: {
|
||||||
dicName: '', // 字典名称
|
dicName: '', // 字典名称
|
||||||
fieldName: '', // 字段名
|
fieldName: '', // 字段名
|
||||||
@ -76,37 +79,56 @@ const state = reactive({
|
|||||||
list: [] as ListType[], // 子集字段 + 属性值
|
list: [] as ListType[], // 子集字段 + 属性值
|
||||||
describe: '', // 字典描述
|
describe: '', // 字典描述
|
||||||
},
|
},
|
||||||
|
dialog: {
|
||||||
|
isShowDialog: false,
|
||||||
|
type: '',
|
||||||
|
title: '',
|
||||||
|
submitTxt: '',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 打开弹窗
|
// 打开弹窗
|
||||||
const openDialog = (row: RowDicType) => {
|
const openDialog = (type: string, row: RowDicType) => {
|
||||||
if (row.fieldName === 'SYS_UERINFO') {
|
if (type === 'edit') {
|
||||||
row.list = [
|
if (row.fieldName === 'SYS_UERINFO') {
|
||||||
{ id: Math.random(), label: 'sex', value: '1' },
|
row.list = [
|
||||||
{ id: Math.random(), label: 'sex', value: '0' },
|
{ id: Math.random(), label: 'sex', value: '1' },
|
||||||
];
|
{ id: Math.random(), label: 'sex', value: '0' },
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
row.list = [
|
||||||
|
{ id: Math.random(), label: 'role', value: 'admin' },
|
||||||
|
{ id: Math.random(), label: 'role', value: 'common' },
|
||||||
|
{ id: Math.random(), label: 'roleName', value: '超级管理员' },
|
||||||
|
{ id: Math.random(), label: 'roleName', value: '普通用户' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
state.ruleForm = row;
|
||||||
|
state.dialog.title = '修改字典';
|
||||||
|
state.dialog.submitTxt = '修 改';
|
||||||
} else {
|
} else {
|
||||||
row.list = [
|
state.dialog.title = '新增字典';
|
||||||
{ id: Math.random(), label: 'role', value: 'admin' },
|
state.dialog.submitTxt = '新 增';
|
||||||
{ id: Math.random(), label: 'role', value: 'common' },
|
// 清空表单,此项需加表单验证才能使用
|
||||||
{ id: Math.random(), label: 'roleName', value: '超级管理员' },
|
// nextTick(() => {
|
||||||
{ id: Math.random(), label: 'roleName', value: '普通用户' },
|
// dicDialogFormRef.value.resetFields();
|
||||||
];
|
// });
|
||||||
}
|
}
|
||||||
state.ruleForm = row;
|
state.dialog.isShowDialog = true;
|
||||||
state.isShowDialog = true;
|
|
||||||
};
|
};
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
const closeDialog = () => {
|
const closeDialog = () => {
|
||||||
state.isShowDialog = false;
|
state.dialog.isShowDialog = false;
|
||||||
};
|
};
|
||||||
// 取消
|
// 取消
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
closeDialog();
|
closeDialog();
|
||||||
};
|
};
|
||||||
// 新增
|
// 提交
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
closeDialog();
|
closeDialog();
|
||||||
|
emit('refresh');
|
||||||
|
// if (state.dialog.type === 'add') { }
|
||||||
};
|
};
|
||||||
// 新增行
|
// 新增行
|
||||||
const onAddRow = () => {
|
const onAddRow = () => {
|
||||||
@ -9,14 +9,14 @@
|
|||||||
</el-icon>
|
</el-icon>
|
||||||
查询
|
查询
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button size="default" type="success" class="ml10" @click="onOpenAddDic">
|
<el-button size="default" type="success" class="ml10" @click="onOpenAddDic('add')">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<ele-FolderAdd />
|
<ele-FolderAdd />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
新增字典
|
新增字典
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="state.tableData.data" style="width: 100%">
|
<el-table :data="state.tableData.data" v-loading="state.tableData.loading" style="width: 100%">
|
||||||
<el-table-column type="index" label="序号" width="50" />
|
<el-table-column type="index" label="序号" width="50" />
|
||||||
<el-table-column prop="dicName" label="字典名称" show-overflow-tooltip></el-table-column>
|
<el-table-column prop="dicName" label="字典名称" show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column prop="fieldName" label="字段名" show-overflow-tooltip></el-table-column>
|
<el-table-column prop="fieldName" label="字段名" show-overflow-tooltip></el-table-column>
|
||||||
@ -30,7 +30,7 @@
|
|||||||
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
|
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="操作" width="100">
|
<el-table-column label="操作" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button size="small" text type="primary" @click="onOpenEditDic(scope.row)">修改</el-button>
|
<el-button size="small" text type="primary" @click="onOpenEditDic('edit', scope.row)">修改</el-button>
|
||||||
<el-button size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button>
|
<el-button size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -49,8 +49,7 @@
|
|||||||
>
|
>
|
||||||
</el-pagination>
|
</el-pagination>
|
||||||
</el-card>
|
</el-card>
|
||||||
<AddDic ref="addDicRef" />
|
<DicDialog ref="dicDialogRef" @refresh="getTableData()" />
|
||||||
<EditDic ref="editDicRef" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -59,12 +58,10 @@ import { defineAsyncComponent, reactive, onMounted, ref } from 'vue';
|
|||||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||||
|
|
||||||
// 引入组件
|
// 引入组件
|
||||||
const AddDic = defineAsyncComponent(() => import('/@/views/system/dic/component/addDic.vue'));
|
const DicDialog = defineAsyncComponent(() => import('/@/views/system/dic/dialog.vue'));
|
||||||
const EditDic = defineAsyncComponent(() => import('/@/views/system/dic/component/editDic.vue'));
|
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const addDicRef = ref();
|
const dicDialogRef = ref();
|
||||||
const editDicRef = ref();
|
|
||||||
const state = reactive<SysDicState>({
|
const state = reactive<SysDicState>({
|
||||||
tableData: {
|
tableData: {
|
||||||
data: [],
|
data: [],
|
||||||
@ -78,7 +75,8 @@ const state = reactive<SysDicState>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 初始化表格数据
|
// 初始化表格数据
|
||||||
const initTableData = () => {
|
const getTableData = () => {
|
||||||
|
state.tableData.loading = true;
|
||||||
const data = [];
|
const data = [];
|
||||||
for (let i = 0; i < 2; i++) {
|
for (let i = 0; i < 2; i++) {
|
||||||
data.push({
|
data.push({
|
||||||
@ -92,14 +90,17 @@ const initTableData = () => {
|
|||||||
}
|
}
|
||||||
state.tableData.data = data;
|
state.tableData.data = data;
|
||||||
state.tableData.total = state.tableData.data.length;
|
state.tableData.total = state.tableData.data.length;
|
||||||
|
setTimeout(() => {
|
||||||
|
state.tableData.loading = false;
|
||||||
|
}, 500);
|
||||||
};
|
};
|
||||||
// 打开新增字典弹窗
|
// 打开新增字典弹窗
|
||||||
const onOpenAddDic = () => {
|
const onOpenAddDic = (type: string) => {
|
||||||
addDicRef.value.openDialog();
|
dicDialogRef.value.openDialog(type);
|
||||||
};
|
};
|
||||||
// 打开修改字典弹窗
|
// 打开修改字典弹窗
|
||||||
const onOpenEditDic = (row: RowDicType) => {
|
const onOpenEditDic = (type: string, row: RowDicType) => {
|
||||||
editDicRef.value.openDialog(row);
|
dicDialogRef.value.openDialog(type, row);
|
||||||
};
|
};
|
||||||
// 删除字典
|
// 删除字典
|
||||||
const onRowDel = (row: RowDicType) => {
|
const onRowDel = (row: RowDicType) => {
|
||||||
@ -109,6 +110,7 @@ const onRowDel = (row: RowDicType) => {
|
|||||||
type: 'warning',
|
type: 'warning',
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
getTableData();
|
||||||
ElMessage.success('删除成功');
|
ElMessage.success('删除成功');
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
@ -116,13 +118,15 @@ const onRowDel = (row: RowDicType) => {
|
|||||||
// 分页改变
|
// 分页改变
|
||||||
const onHandleSizeChange = (val: number) => {
|
const onHandleSizeChange = (val: number) => {
|
||||||
state.tableData.param.pageSize = val;
|
state.tableData.param.pageSize = val;
|
||||||
|
getTableData();
|
||||||
};
|
};
|
||||||
// 分页改变
|
// 分页改变
|
||||||
const onHandleCurrentChange = (val: number) => {
|
const onHandleCurrentChange = (val: number) => {
|
||||||
state.tableData.param.pageNum = val;
|
state.tableData.param.pageNum = val;
|
||||||
|
getTableData();
|
||||||
};
|
};
|
||||||
// 页面加载时
|
// 页面加载时
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initTableData();
|
getTableData();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,237 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="system-edit-menu-container">
|
|
||||||
<el-dialog title="修改菜单" v-model="state.isShowDialog" width="769px">
|
|
||||||
<el-form :model="state.ruleForm" size="default" label-width="80px">
|
|
||||||
<el-row :gutter="35">
|
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
|
||||||
<el-form-item label="上级菜单">
|
|
||||||
<el-cascader
|
|
||||||
:options="state.menuData"
|
|
||||||
:props="{ checkStrictly: true, value: 'path', label: 'title' }"
|
|
||||||
placeholder="请选择上级菜单"
|
|
||||||
clearable
|
|
||||||
class="w100"
|
|
||||||
v-model="state.ruleForm.menuSuperior"
|
|
||||||
>
|
|
||||||
<template #default="{ node, data }">
|
|
||||||
<span>{{ data.title }}</span>
|
|
||||||
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
|
|
||||||
</template>
|
|
||||||
</el-cascader>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
|
||||||
<el-form-item label="菜单类型">
|
|
||||||
<el-radio-group v-model="state.ruleForm.menuType">
|
|
||||||
<el-radio label="menu">菜单</el-radio>
|
|
||||||
<el-radio label="btn">按钮</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
</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.meta.title" placeholder="格式:message.router.xxx" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<template v-if="state.ruleForm.menuType === 'menu'">
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="路由名称">
|
|
||||||
<el-input v-model="state.ruleForm.name" placeholder="路由中的 name 值" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</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.path" placeholder="路由中的 path 值" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</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.redirect" placeholder="请输入路由重定向" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="菜单图标">
|
|
||||||
<IconSelector placeholder="请输入菜单图标" v-model="state.ruleForm.meta.icon" type="all" />
|
|
||||||
</el-form-item>
|
|
||||||
</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.component" placeholder="组件路径" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</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.meta.isLink"
|
|
||||||
placeholder="外链/内嵌时链接地址(http:xxx.com)"
|
|
||||||
clearable
|
|
||||||
:disabled="!state.ruleForm.isLink"
|
|
||||||
>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="权限标识">
|
|
||||||
<el-select v-model="state.ruleForm.meta.roles" multiple placeholder="取角色管理" clearable class="w100">
|
|
||||||
<el-option label="admin" value="admin"></el-option>
|
|
||||||
<el-option label="common" value="common"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</template>
|
|
||||||
<template v-if="state.ruleForm.menuType === 'btn'">
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="权限标识">
|
|
||||||
<el-input v-model="state.ruleForm.btnPower" placeholder="请输入权限标识" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</template>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="菜单排序">
|
|
||||||
<el-input-number v-model="state.ruleForm.menuSort" controls-position="right" placeholder="请输入排序" class="w100" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<template v-if="state.ruleForm.menuType === 'menu'">
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="是否隐藏">
|
|
||||||
<el-radio-group v-model="state.ruleForm.meta.isHide">
|
|
||||||
<el-radio :label="true">隐藏</el-radio>
|
|
||||||
<el-radio :label="false">不隐藏</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="页面缓存">
|
|
||||||
<el-radio-group v-model="state.ruleForm.meta.isKeepAlive">
|
|
||||||
<el-radio :label="true">缓存</el-radio>
|
|
||||||
<el-radio :label="false">不缓存</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="是否固定">
|
|
||||||
<el-radio-group v-model="state.ruleForm.meta.isAffix">
|
|
||||||
<el-radio :label="true">固定</el-radio>
|
|
||||||
<el-radio :label="false">不固定</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="是否外链">
|
|
||||||
<el-radio-group v-model="state.ruleForm.isLink" :disabled="state.ruleForm.meta.isIframe">
|
|
||||||
<el-radio :label="true">是</el-radio>
|
|
||||||
<el-radio :label="false">否</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="是否内嵌">
|
|
||||||
<el-radio-group v-model="state.ruleForm.meta.isIframe" @change="onSelectIframeChange">
|
|
||||||
<el-radio :label="true">是</el-radio>
|
|
||||||
<el-radio :label="false">否</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</template>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="onSubmit" size="default">修 改</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts" name="systemEditMenu">
|
|
||||||
import { defineAsyncComponent, reactive, onMounted } from 'vue';
|
|
||||||
import { storeToRefs } from 'pinia';
|
|
||||||
import { useRoutesList } from '/@/stores/routesList';
|
|
||||||
import { i18n } from '/@/i18n/index';
|
|
||||||
// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd";
|
|
||||||
|
|
||||||
// 引入组件
|
|
||||||
const IconSelector = defineAsyncComponent(() => import('/@/components/iconSelector/index.vue'));
|
|
||||||
|
|
||||||
// 定义变量内容
|
|
||||||
const stores = useRoutesList();
|
|
||||||
const { routesList } = storeToRefs(stores);
|
|
||||||
const state = reactive({
|
|
||||||
isShowDialog: false,
|
|
||||||
// 参数请参考 `/src/router/route.ts` 中的 `dynamicRoutes` 路由菜单格式
|
|
||||||
ruleForm: {
|
|
||||||
menuSuperior: [], // 上级菜单
|
|
||||||
menuType: 'menu', // 菜单类型
|
|
||||||
name: '', // 路由名称
|
|
||||||
component: '', // 组件路径
|
|
||||||
isLink: false, // 是否外链
|
|
||||||
menuSort: 0, // 菜单排序
|
|
||||||
path: '', // 路由路径
|
|
||||||
redirect: '', // 路由重定向,有子集 children 时
|
|
||||||
meta: {
|
|
||||||
title: '', // 菜单名称
|
|
||||||
icon: '', // 菜单图标
|
|
||||||
isHide: false, // 是否隐藏
|
|
||||||
isKeepAlive: true, // 是否缓存
|
|
||||||
isAffix: false, // 是否固定
|
|
||||||
isLink: '', // 外链/内嵌时链接地址(http:xxx.com),开启外链条件,`1、isLink: 链接地址不为空`
|
|
||||||
isIframe: false, // 是否内嵌,开启条件,`1、isIframe:true 2、isLink:链接地址不为空`
|
|
||||||
roles: '', // 权限标识,取角色管理
|
|
||||||
},
|
|
||||||
btnPower: '', // 菜单类型为按钮时,权限标识
|
|
||||||
},
|
|
||||||
menuData: [] as RouteItems, // 上级菜单数据
|
|
||||||
});
|
|
||||||
|
|
||||||
// 获取 pinia 中的路由
|
|
||||||
const getMenuData = (routes: RouteItems) => {
|
|
||||||
const arr: RouteItems = [];
|
|
||||||
routes.map((val: RouteItem) => {
|
|
||||||
val['title'] = i18n.global.t(val.meta?.title as string);
|
|
||||||
arr.push({ ...val });
|
|
||||||
if (val.children) getMenuData(val.children);
|
|
||||||
});
|
|
||||||
return arr;
|
|
||||||
};
|
|
||||||
// 打开弹窗
|
|
||||||
const openDialog = (row: any) => {
|
|
||||||
// 模拟数据,实际请走接口
|
|
||||||
row.menuType = 'menu';
|
|
||||||
row.menuSort = Math.random();
|
|
||||||
row.component = `${row.component} `
|
|
||||||
.match(/\'(.+)\'/g)
|
|
||||||
?.join('')
|
|
||||||
.replace(/\'/g, '');
|
|
||||||
state.ruleForm = row;
|
|
||||||
state.isShowDialog = true;
|
|
||||||
};
|
|
||||||
// 关闭弹窗
|
|
||||||
const closeDialog = () => {
|
|
||||||
state.isShowDialog = false;
|
|
||||||
};
|
|
||||||
// 是否内嵌下拉改变
|
|
||||||
const onSelectIframeChange = () => {
|
|
||||||
if (state.ruleForm.meta.isIframe) state.ruleForm.isLink = true;
|
|
||||||
else state.ruleForm.isLink = false;
|
|
||||||
};
|
|
||||||
// 取消
|
|
||||||
const onCancel = () => {
|
|
||||||
closeDialog();
|
|
||||||
};
|
|
||||||
// 新增
|
|
||||||
const onSubmit = () => {
|
|
||||||
closeDialog(); // 关闭弹窗
|
|
||||||
// setBackEndControlRefreshRoutes() // 刷新菜单,未进行后端接口测试
|
|
||||||
};
|
|
||||||
// 页面加载时
|
|
||||||
onMounted(() => {
|
|
||||||
state.menuData = getMenuData(routesList.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 暴露变量
|
|
||||||
defineExpose({
|
|
||||||
openDialog,
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="system-add-menu-container">
|
<div class="system-menu-dialog-container">
|
||||||
<el-dialog title="新增菜单" v-model="state.isShowDialog" width="769px">
|
<el-dialog :title="state.dialog.title" v-model="state.dialog.isShowDialog" width="769px">
|
||||||
<el-form :model="state.ruleForm" size="default" label-width="80px">
|
<el-form ref="menuDialogFormRef" :model="state.ruleForm" size="default" label-width="80px">
|
||||||
<el-row :gutter="35">
|
<el-row :gutter="35">
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
||||||
<el-form-item label="上级菜单">
|
<el-form-item label="上级菜单">
|
||||||
@ -51,7 +51,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||||
<el-form-item label="菜单图标">
|
<el-form-item label="菜单图标">
|
||||||
<IconSelector placeholder="请输入菜单图标" v-model="state.ruleForm.meta.icon" type="all" />
|
<IconSelector placeholder="请输入菜单图标" v-model="state.ruleForm.meta.icon" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||||
@ -138,28 +138,31 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||||
<el-button type="primary" @click="onSubmit" size="default">新 增</el-button>
|
<el-button type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="systemAddMenu">
|
<script setup lang="ts" name="systemMenuDialog">
|
||||||
import { defineAsyncComponent, reactive, onMounted } from 'vue';
|
import { defineAsyncComponent, reactive, onMounted, ref } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useRoutesList } from '/@/stores/routesList';
|
import { useRoutesList } from '/@/stores/routesList';
|
||||||
import { i18n } from '/@/i18n/index';
|
import { i18n } from '/@/i18n/index';
|
||||||
// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd";
|
// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd";
|
||||||
|
|
||||||
|
// 定义子组件向父组件传值/事件
|
||||||
|
const emit = defineEmits(['refresh']);
|
||||||
|
|
||||||
// 引入组件
|
// 引入组件
|
||||||
const IconSelector = defineAsyncComponent(() => import('/@/components/iconSelector/index.vue'));
|
const IconSelector = defineAsyncComponent(() => import('/@/components/iconSelector/index.vue'));
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
|
const menuDialogFormRef = ref();
|
||||||
const stores = useRoutesList();
|
const stores = useRoutesList();
|
||||||
const { routesList } = storeToRefs(stores);
|
const { routesList } = storeToRefs(stores);
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
isShowDialog: false,
|
|
||||||
// 参数请参考 `/src/router/route.ts` 中的 `dynamicRoutes` 路由菜单格式
|
// 参数请参考 `/src/router/route.ts` 中的 `dynamicRoutes` 路由菜单格式
|
||||||
ruleForm: {
|
ruleForm: {
|
||||||
menuSuperior: [], // 上级菜单
|
menuSuperior: [], // 上级菜单
|
||||||
@ -183,6 +186,12 @@ const state = reactive({
|
|||||||
btnPower: '', // 菜单类型为按钮时,权限标识
|
btnPower: '', // 菜单类型为按钮时,权限标识
|
||||||
},
|
},
|
||||||
menuData: [] as RouteItems, // 上级菜单数据
|
menuData: [] as RouteItems, // 上级菜单数据
|
||||||
|
dialog: {
|
||||||
|
isShowDialog: false,
|
||||||
|
type: '',
|
||||||
|
title: '',
|
||||||
|
submitTxt: '',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取 pinia 中的路由
|
// 获取 pinia 中的路由
|
||||||
@ -196,12 +205,32 @@ const getMenuData = (routes: RouteItems) => {
|
|||||||
return arr;
|
return arr;
|
||||||
};
|
};
|
||||||
// 打开弹窗
|
// 打开弹窗
|
||||||
const openDialog = () => {
|
const openDialog = (type: string, row?: any) => {
|
||||||
state.isShowDialog = true;
|
if (type === 'edit') {
|
||||||
|
// 模拟数据,实际请走接口
|
||||||
|
row.menuType = 'menu';
|
||||||
|
row.menuSort = Math.random();
|
||||||
|
row.component = `${row.component} `
|
||||||
|
.match(/\'(.+)\'/g)
|
||||||
|
?.join('')
|
||||||
|
.replace(/\'/g, '');
|
||||||
|
state.ruleForm = row;
|
||||||
|
state.dialog.title = '修改菜单';
|
||||||
|
state.dialog.submitTxt = '修 改';
|
||||||
|
} else {
|
||||||
|
state.dialog.title = '新增菜单';
|
||||||
|
state.dialog.submitTxt = '新 增';
|
||||||
|
// 清空表单,此项需加表单验证才能使用
|
||||||
|
// nextTick(() => {
|
||||||
|
// menuDialogFormRef.value.resetFields();
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
state.dialog.type = type;
|
||||||
|
state.dialog.isShowDialog = true;
|
||||||
};
|
};
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
const closeDialog = () => {
|
const closeDialog = () => {
|
||||||
state.isShowDialog = false;
|
state.dialog.isShowDialog = false;
|
||||||
};
|
};
|
||||||
// 是否内嵌下拉改变
|
// 是否内嵌下拉改变
|
||||||
const onSelectIframeChange = () => {
|
const onSelectIframeChange = () => {
|
||||||
@ -212,9 +241,11 @@ const onSelectIframeChange = () => {
|
|||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
closeDialog();
|
closeDialog();
|
||||||
};
|
};
|
||||||
// 新增
|
// 提交
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
closeDialog(); // 关闭弹窗
|
closeDialog(); // 关闭弹窗
|
||||||
|
emit('refresh');
|
||||||
|
// if (state.dialog.type === 'add') { }
|
||||||
// setBackEndControlRefreshRoutes() // 刷新菜单,未进行后端接口测试
|
// setBackEndControlRefreshRoutes() // 刷新菜单,未进行后端接口测试
|
||||||
};
|
};
|
||||||
// 页面加载时
|
// 页面加载时
|
||||||
@ -16,7 +16,13 @@
|
|||||||
新增菜单
|
新增菜单
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="menuTableData" style="width: 100%" row-key="path" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
|
<el-table
|
||||||
|
:data="state.tableData.data"
|
||||||
|
v-loading="state.tableData.loading"
|
||||||
|
style="width: 100%"
|
||||||
|
row-key="path"
|
||||||
|
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||||
|
>
|
||||||
<el-table-column label="菜单名称" show-overflow-tooltip>
|
<el-table-column label="菜单名称" show-overflow-tooltip>
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<SvgIcon :name="scope.row.meta.icon" />
|
<SvgIcon :name="scope.row.meta.icon" />
|
||||||
@ -46,46 +52,54 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" show-overflow-tooltip width="140">
|
<el-table-column label="操作" show-overflow-tooltip width="140">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button size="small" text type="primary" @click="onOpenAddMenu">新增</el-button>
|
<el-button size="small" text type="primary" @click="onOpenAddMenu('add')">新增</el-button>
|
||||||
<el-button size="small" text type="primary" @click="onOpenEditMenu(scope.row)">修改</el-button>
|
<el-button size="small" text type="primary" @click="onOpenEditMenu('edit', scope.row)">修改</el-button>
|
||||||
<el-button size="small" text type="primary" @click="onTabelRowDel(scope.row)">删除</el-button>
|
<el-button size="small" text type="primary" @click="onTabelRowDel(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-card>
|
</el-card>
|
||||||
<AddMenu ref="addMenuRef" />
|
<MenuDialog ref="menuDialogRef" @refresh="getTableData()" />
|
||||||
<EditMenu ref="editMenuRef" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="systemMenu">
|
<script setup lang="ts" name="systemMenu">
|
||||||
import { defineAsyncComponent, ref, computed } from 'vue';
|
import { defineAsyncComponent, ref, onMounted, reactive } from 'vue';
|
||||||
import { RouteRecordRaw } from 'vue-router';
|
import { RouteRecordRaw } from 'vue-router';
|
||||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useRoutesList } from '/@/stores/routesList';
|
import { useRoutesList } from '/@/stores/routesList';
|
||||||
|
// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd";
|
||||||
|
|
||||||
// 引入组件
|
// 引入组件
|
||||||
const AddMenu = defineAsyncComponent(() => import('/@/views/system/menu/component/addMenu.vue'));
|
const MenuDialog = defineAsyncComponent(() => import('/@/views/system/menu/dialog.vue'));
|
||||||
const EditMenu = defineAsyncComponent(() => import('/@/views/system/menu/component/editMenu.vue'));
|
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const stores = useRoutesList();
|
const stores = useRoutesList();
|
||||||
const { routesList } = storeToRefs(stores);
|
const { routesList } = storeToRefs(stores);
|
||||||
const addMenuRef = ref();
|
const menuDialogRef = ref();
|
||||||
const editMenuRef = ref();
|
const state = reactive({
|
||||||
|
tableData: {
|
||||||
// 获取 pinia 中的路由
|
data: [] as RouteRecordRaw[],
|
||||||
const menuTableData = computed(() => {
|
loading: true,
|
||||||
return routesList.value;
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 获取路由数据,真实请从接口获取
|
||||||
|
const getTableData = () => {
|
||||||
|
state.tableData.loading = true;
|
||||||
|
state.tableData.data = routesList.value;
|
||||||
|
setTimeout(() => {
|
||||||
|
state.tableData.loading = false;
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
// 打开新增菜单弹窗
|
// 打开新增菜单弹窗
|
||||||
const onOpenAddMenu = () => {
|
const onOpenAddMenu = (type: string) => {
|
||||||
addMenuRef.value.openDialog();
|
menuDialogRef.value.openDialog(type);
|
||||||
};
|
};
|
||||||
// 打开编辑菜单弹窗
|
// 打开编辑菜单弹窗
|
||||||
const onOpenEditMenu = (row: RouteRecordRaw) => {
|
const onOpenEditMenu = (type: string, row: RouteRecordRaw) => {
|
||||||
editMenuRef.value.openDialog(row);
|
menuDialogRef.value.openDialog(type, row);
|
||||||
};
|
};
|
||||||
// 删除当前行
|
// 删除当前行
|
||||||
const onTabelRowDel = (row: RouteRecordRaw) => {
|
const onTabelRowDel = (row: RouteRecordRaw) => {
|
||||||
@ -96,7 +110,13 @@ const onTabelRowDel = (row: RouteRecordRaw) => {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ElMessage.success('删除成功');
|
ElMessage.success('删除成功');
|
||||||
|
getTableData();
|
||||||
|
//await setBackEndControlRefreshRoutes() // 刷新菜单,未进行后端接口测试
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
};
|
};
|
||||||
|
// 页面加载时
|
||||||
|
onMounted(() => {
|
||||||
|
getTableData();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,221 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="system-edit-role-container">
|
|
||||||
<el-dialog title="修改角色" v-model="state.isShowDialog" width="769px">
|
|
||||||
<el-form :model="state.ruleForm" size="default" label-width="90px">
|
|
||||||
<el-row :gutter="35">
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="角色名称">
|
|
||||||
<el-input v-model="state.ruleForm.roleName" placeholder="请输入角色名称" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="角色标识">
|
|
||||||
<template #label>
|
|
||||||
<el-tooltip effect="dark" content="用于 `router/route.ts` meta.roles" placement="top-start">
|
|
||||||
<span>角色标识</span>
|
|
||||||
</el-tooltip>
|
|
||||||
</template>
|
|
||||||
<el-input v-model="state.ruleForm.roleSign" placeholder="请输入角色标识" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="排序">
|
|
||||||
<el-input-number v-model="state.ruleForm.sort" :min="0" :max="999" controls-position="right" placeholder="请输入排序" class="w100" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="角色状态">
|
|
||||||
<el-switch v-model="state.ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
|
||||||
<el-form-item label="角色描述">
|
|
||||||
<el-input v-model="state.ruleForm.describe" type="textarea" placeholder="请输入角色描述" maxlength="150"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
|
||||||
<el-form-item label="菜单权限">
|
|
||||||
<el-tree
|
|
||||||
:data="state.menuData"
|
|
||||||
:props="state.menuProps"
|
|
||||||
:default-checked-keys="[112, 113]"
|
|
||||||
node-key="id"
|
|
||||||
show-checkbox
|
|
||||||
class="menu-data-tree"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="onSubmit" size="default">修 改</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts" name="systemEditRole">
|
|
||||||
import { reactive } from 'vue';
|
|
||||||
|
|
||||||
// 定义变量内容
|
|
||||||
const state = reactive({
|
|
||||||
isShowDialog: false,
|
|
||||||
ruleForm: {
|
|
||||||
roleName: '', // 角色名称
|
|
||||||
roleSign: '', // 角色标识
|
|
||||||
sort: 0, // 排序
|
|
||||||
status: true, // 角色状态
|
|
||||||
describe: '', // 角色描述
|
|
||||||
},
|
|
||||||
menuData: [] as TreeType[],
|
|
||||||
menuProps: {
|
|
||||||
children: 'children',
|
|
||||||
label: 'label',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// 打开弹窗
|
|
||||||
const openDialog = (row: RowRoleType) => {
|
|
||||||
state.ruleForm = row;
|
|
||||||
state.isShowDialog = true;
|
|
||||||
getMenuData();
|
|
||||||
};
|
|
||||||
// 关闭弹窗
|
|
||||||
const closeDialog = () => {
|
|
||||||
state.isShowDialog = false;
|
|
||||||
};
|
|
||||||
// 取消
|
|
||||||
const onCancel = () => {
|
|
||||||
closeDialog();
|
|
||||||
};
|
|
||||||
// 新增
|
|
||||||
const onSubmit = () => {
|
|
||||||
closeDialog();
|
|
||||||
};
|
|
||||||
// 获取菜单结构数据
|
|
||||||
const getMenuData = () => {
|
|
||||||
state.menuData = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
label: '系统管理',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: 11,
|
|
||||||
label: '菜单管理',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: 111,
|
|
||||||
label: '菜单新增',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 112,
|
|
||||||
label: '菜单修改',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 113,
|
|
||||||
label: '菜单删除',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 114,
|
|
||||||
label: '菜单查询',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 12,
|
|
||||||
label: '角色管理',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: 121,
|
|
||||||
label: '角色新增',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 122,
|
|
||||||
label: '角色修改',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 123,
|
|
||||||
label: '角色删除',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 124,
|
|
||||||
label: '角色查询',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 13,
|
|
||||||
label: '用户管理',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: 131,
|
|
||||||
label: '用户新增',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 132,
|
|
||||||
label: '用户修改',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 133,
|
|
||||||
label: '用户删除',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 134,
|
|
||||||
label: '用户查询',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
label: '权限管理',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: 21,
|
|
||||||
label: '前端控制',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: 211,
|
|
||||||
label: '页面权限',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 212,
|
|
||||||
label: '页面权限',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 22,
|
|
||||||
label: '后端控制',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: 221,
|
|
||||||
label: '页面权限',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
// 暴露变量
|
|
||||||
defineExpose({
|
|
||||||
openDialog,
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.system-edit-role-container {
|
|
||||||
.menu-data-tree {
|
|
||||||
width: 100%;
|
|
||||||
border: 1px solid var(--el-border-color);
|
|
||||||
border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="system-add-role-container">
|
<div class="system-role-dialog-container">
|
||||||
<el-dialog title="新增角色" v-model="state.isShowDialog" width="769px">
|
<el-dialog :title="state.dialog.title" v-model="state.dialog.isShowDialog" width="769px">
|
||||||
<el-form :model="state.ruleForm" size="default" label-width="90px">
|
<el-form ref="roleDialogFormRef" :model="state.ruleForm" size="default" label-width="90px">
|
||||||
<el-row :gutter="35">
|
<el-row :gutter="35">
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||||
<el-form-item label="角色名称">
|
<el-form-item label="角色名称">
|
||||||
@ -43,19 +43,22 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||||
<el-button type="primary" @click="onSubmit" size="default">新 增</el-button>
|
<el-button type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="systemAddRole">
|
<script setup lang="ts" name="systemRoleDialog">
|
||||||
import { reactive } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
// 定义子组件向父组件传值/事件
|
||||||
|
const emit = defineEmits(['refresh']);
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
|
const roleDialogFormRef = ref();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
isShowDialog: false,
|
|
||||||
ruleForm: {
|
ruleForm: {
|
||||||
roleName: '', // 角色名称
|
roleName: '', // 角色名称
|
||||||
roleSign: '', // 角色标识
|
roleSign: '', // 角色标识
|
||||||
@ -68,24 +71,44 @@ const state = reactive({
|
|||||||
children: 'children',
|
children: 'children',
|
||||||
label: 'label',
|
label: 'label',
|
||||||
},
|
},
|
||||||
|
dialog: {
|
||||||
|
isShowDialog: false,
|
||||||
|
type: '',
|
||||||
|
title: '',
|
||||||
|
submitTxt: '',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 打开弹窗
|
// 打开弹窗
|
||||||
const openDialog = () => {
|
const openDialog = (type: string, row: RowRoleType) => {
|
||||||
state.isShowDialog = true;
|
if (type === 'edit') {
|
||||||
|
state.ruleForm = row;
|
||||||
|
state.dialog.title = '修改角色';
|
||||||
|
state.dialog.submitTxt = '修 改';
|
||||||
|
} else {
|
||||||
|
state.dialog.title = '新增角色';
|
||||||
|
state.dialog.submitTxt = '新 增';
|
||||||
|
// 清空表单,此项需加表单验证才能使用
|
||||||
|
// nextTick(() => {
|
||||||
|
// roleDialogFormRef.value.resetFields();
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
state.dialog.isShowDialog = true;
|
||||||
getMenuData();
|
getMenuData();
|
||||||
};
|
};
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
const closeDialog = () => {
|
const closeDialog = () => {
|
||||||
state.isShowDialog = false;
|
state.dialog.isShowDialog = false;
|
||||||
};
|
};
|
||||||
// 取消
|
// 取消
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
closeDialog();
|
closeDialog();
|
||||||
};
|
};
|
||||||
// 新增
|
// 提交
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
closeDialog();
|
closeDialog();
|
||||||
|
emit('refresh');
|
||||||
|
// if (state.dialog.type === 'add') { }
|
||||||
};
|
};
|
||||||
// 获取菜单结构数据
|
// 获取菜单结构数据
|
||||||
const getMenuData = () => {
|
const getMenuData = () => {
|
||||||
@ -202,7 +225,7 @@ defineExpose({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.system-add-role-container {
|
.system-role-dialog-container {
|
||||||
.menu-data-tree {
|
.menu-data-tree {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid var(--el-border-color);
|
border: 1px solid var(--el-border-color);
|
||||||
@ -9,14 +9,14 @@
|
|||||||
</el-icon>
|
</el-icon>
|
||||||
查询
|
查询
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button size="default" type="success" class="ml10" @click="onOpenAddRole">
|
<el-button size="default" type="success" class="ml10" @click="onOpenAddRole('add')">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<ele-FolderAdd />
|
<ele-FolderAdd />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
新增角色
|
新增角色
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="state.tableData.data" style="width: 100%">
|
<el-table :data="state.tableData.data" v-loading="state.tableData.loading" style="width: 100%">
|
||||||
<el-table-column type="index" label="序号" width="60" />
|
<el-table-column type="index" label="序号" width="60" />
|
||||||
<el-table-column prop="roleName" label="角色名称" show-overflow-tooltip></el-table-column>
|
<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="roleSign" label="角色标识" show-overflow-tooltip></el-table-column>
|
||||||
@ -31,7 +31,7 @@
|
|||||||
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
|
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="操作" width="100">
|
<el-table-column label="操作" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button :disabled="scope.row.roleName === '超级管理员'" size="small" text type="primary" @click="onOpenEditRole(scope.row)"
|
<el-button :disabled="scope.row.roleName === '超级管理员'" size="small" text type="primary" @click="onOpenEditRole('edit', scope.row)"
|
||||||
>修改</el-button
|
>修改</el-button
|
||||||
>
|
>
|
||||||
<el-button :disabled="scope.row.roleName === '超级管理员'" size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button>
|
<el-button :disabled="scope.row.roleName === '超级管理员'" size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button>
|
||||||
@ -52,8 +52,7 @@
|
|||||||
>
|
>
|
||||||
</el-pagination>
|
</el-pagination>
|
||||||
</div>
|
</div>
|
||||||
<AddRole ref="addRoleRef" />
|
<RoleDialog ref="roleDialogRef" @refresh="getTableData()" />
|
||||||
<EditRole ref="editRoleRef" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -62,12 +61,10 @@ import { defineAsyncComponent, reactive, onMounted, ref } from 'vue';
|
|||||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||||
|
|
||||||
// 引入组件
|
// 引入组件
|
||||||
const AddRole = defineAsyncComponent(() => import('/@/views/system/role/component/addRole.vue'));
|
const RoleDialog = defineAsyncComponent(() => import('/@/views/system/role/dialog.vue'));
|
||||||
const EditRole = defineAsyncComponent(() => import('/@/views/system/role/component/editRole.vue'));
|
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const addRoleRef = ref();
|
const roleDialogRef = ref();
|
||||||
const editRoleRef = ref();
|
|
||||||
const state = reactive<SysRoleState>({
|
const state = reactive<SysRoleState>({
|
||||||
tableData: {
|
tableData: {
|
||||||
data: [],
|
data: [],
|
||||||
@ -81,7 +78,8 @@ const state = reactive<SysRoleState>({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
// 初始化表格数据
|
// 初始化表格数据
|
||||||
const initTableData = () => {
|
const getTableData = () => {
|
||||||
|
state.tableData.loading = true;
|
||||||
const data = [];
|
const data = [];
|
||||||
for (let i = 0; i < 20; i++) {
|
for (let i = 0; i < 20; i++) {
|
||||||
data.push({
|
data.push({
|
||||||
@ -95,14 +93,17 @@ const initTableData = () => {
|
|||||||
}
|
}
|
||||||
state.tableData.data = data;
|
state.tableData.data = data;
|
||||||
state.tableData.total = state.tableData.data.length;
|
state.tableData.total = state.tableData.data.length;
|
||||||
|
setTimeout(() => {
|
||||||
|
state.tableData.loading = false;
|
||||||
|
}, 500);
|
||||||
};
|
};
|
||||||
// 打开新增角色弹窗
|
// 打开新增角色弹窗
|
||||||
const onOpenAddRole = () => {
|
const onOpenAddRole = (type: string) => {
|
||||||
addRoleRef.value.openDialog();
|
roleDialogRef.value.openDialog(type);
|
||||||
};
|
};
|
||||||
// 打开修改角色弹窗
|
// 打开修改角色弹窗
|
||||||
const onOpenEditRole = (row: Object) => {
|
const onOpenEditRole = (type: string, row: Object) => {
|
||||||
editRoleRef.value.openDialog(row);
|
roleDialogRef.value.openDialog(type, row);
|
||||||
};
|
};
|
||||||
// 删除角色
|
// 删除角色
|
||||||
const onRowDel = (row: RowRoleType) => {
|
const onRowDel = (row: RowRoleType) => {
|
||||||
@ -112,6 +113,7 @@ const onRowDel = (row: RowRoleType) => {
|
|||||||
type: 'warning',
|
type: 'warning',
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
getTableData();
|
||||||
ElMessage.success('删除成功');
|
ElMessage.success('删除成功');
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
@ -119,14 +121,16 @@ const onRowDel = (row: RowRoleType) => {
|
|||||||
// 分页改变
|
// 分页改变
|
||||||
const onHandleSizeChange = (val: number) => {
|
const onHandleSizeChange = (val: number) => {
|
||||||
state.tableData.param.pageSize = val;
|
state.tableData.param.pageSize = val;
|
||||||
|
getTableData();
|
||||||
};
|
};
|
||||||
// 分页改变
|
// 分页改变
|
||||||
const onHandleCurrentChange = (val: number) => {
|
const onHandleCurrentChange = (val: number) => {
|
||||||
state.tableData.param.pageNum = val;
|
state.tableData.param.pageNum = val;
|
||||||
|
getTableData();
|
||||||
};
|
};
|
||||||
// 页面加载时
|
// 页面加载时
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initTableData();
|
getTableData();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,167 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="system-add-user-container">
|
|
||||||
<el-dialog title="新增用户" v-model="state.isShowDialog" width="769px">
|
|
||||||
<el-form :model="state.ruleForm" size="default" label-width="90px">
|
|
||||||
<el-row :gutter="35">
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="账户名称">
|
|
||||||
<el-input v-model="state.ruleForm.userName" placeholder="请输入账户名称" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</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.userNickname" placeholder="请输入用户昵称" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="关联角色">
|
|
||||||
<el-select v-model="state.ruleForm.roleSign" placeholder="请选择" clearable class="w100">
|
|
||||||
<el-option label="超级管理员" value="admin"></el-option>
|
|
||||||
<el-option label="普通用户" value="common"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="部门">
|
|
||||||
<el-cascader
|
|
||||||
:options="state.deptData"
|
|
||||||
:props="{ checkStrictly: true, value: 'deptName', label: 'deptName' }"
|
|
||||||
placeholder="请选择部门"
|
|
||||||
clearable
|
|
||||||
class="w100"
|
|
||||||
v-model="state.ruleForm.department"
|
|
||||||
>
|
|
||||||
<template #default="{ node, data }">
|
|
||||||
<span>{{ data.deptName }}</span>
|
|
||||||
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
|
|
||||||
</template>
|
|
||||||
</el-cascader>
|
|
||||||
</el-form-item>
|
|
||||||
</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.phone" placeholder="请输入手机号" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</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.email" placeholder="请输入" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="性别">
|
|
||||||
<el-select v-model="state.ruleForm.sex" placeholder="请选择" clearable class="w100">
|
|
||||||
<el-option label="男" value="男"></el-option>
|
|
||||||
<el-option label="女" value="女"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</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.password" placeholder="请输入" type="password" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="账户过期">
|
|
||||||
<el-date-picker v-model="state.ruleForm.overdueTime" type="date" placeholder="请选择" class="w100"> </el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
|
||||||
<el-form-item label="用户状态">
|
|
||||||
<el-switch v-model="state.ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
|
||||||
<el-form-item label="用户描述">
|
|
||||||
<el-input v-model="state.ruleForm.describe" type="textarea" placeholder="请输入用户描述" maxlength="150"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="onSubmit" size="default">新 增</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts" name="systemAddUser">
|
|
||||||
import { reactive, onMounted } from 'vue';
|
|
||||||
|
|
||||||
// 定义变量内容
|
|
||||||
const state = reactive({
|
|
||||||
isShowDialog: false,
|
|
||||||
ruleForm: {
|
|
||||||
userName: '', // 账户名称
|
|
||||||
userNickname: '', // 用户昵称
|
|
||||||
roleSign: '', // 关联角色
|
|
||||||
department: [], // 部门
|
|
||||||
phone: '', // 手机号
|
|
||||||
email: '', // 邮箱
|
|
||||||
sex: '', // 性别
|
|
||||||
password: '', // 账户密码
|
|
||||||
overdueTime: '', // 账户过期
|
|
||||||
status: true, // 用户状态
|
|
||||||
describe: '', // 用户描述
|
|
||||||
},
|
|
||||||
deptData: [] as DeptTreeType[], // 部门数据
|
|
||||||
});
|
|
||||||
|
|
||||||
// 打开弹窗
|
|
||||||
const openDialog = () => {
|
|
||||||
state.isShowDialog = true;
|
|
||||||
};
|
|
||||||
// 关闭弹窗
|
|
||||||
const closeDialog = () => {
|
|
||||||
state.isShowDialog = false;
|
|
||||||
};
|
|
||||||
// 取消
|
|
||||||
const onCancel = () => {
|
|
||||||
closeDialog();
|
|
||||||
};
|
|
||||||
// 新增
|
|
||||||
const onSubmit = () => {
|
|
||||||
closeDialog();
|
|
||||||
};
|
|
||||||
// 初始化部门数据
|
|
||||||
const initTableData = () => {
|
|
||||||
state.deptData.push({
|
|
||||||
deptName: 'vueNextAdmin',
|
|
||||||
createTime: new Date().toLocaleString(),
|
|
||||||
status: true,
|
|
||||||
sort: Math.random(),
|
|
||||||
describe: '顶级部门',
|
|
||||||
id: Math.random(),
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
deptName: 'IT外包服务',
|
|
||||||
createTime: new Date().toLocaleString(),
|
|
||||||
status: true,
|
|
||||||
sort: Math.random(),
|
|
||||||
describe: '总部',
|
|
||||||
id: Math.random(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
deptName: '资本控股',
|
|
||||||
createTime: new Date().toLocaleString(),
|
|
||||||
status: true,
|
|
||||||
sort: Math.random(),
|
|
||||||
describe: '分部',
|
|
||||||
id: Math.random(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// 页面加载时
|
|
||||||
onMounted(() => {
|
|
||||||
initTableData();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 暴露变量
|
|
||||||
defineExpose({
|
|
||||||
openDialog,
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="system-edit-user-container">
|
<div class="system-user-dialog-container">
|
||||||
<el-dialog title="修改用户" v-model="state.isShowDialog" width="769px">
|
<el-dialog :title="state.dialog.title" v-model="state.dialog.isShowDialog" width="769px">
|
||||||
<el-form :model="state.ruleForm" size="default" label-width="90px">
|
<el-form ref="userDialogFormRef" :model="state.ruleForm" size="default" label-width="90px">
|
||||||
<el-row :gutter="35">
|
<el-row :gutter="35">
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
|
||||||
<el-form-item label="账户名称">
|
<el-form-item label="账户名称">
|
||||||
@ -81,19 +81,22 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button @click="onCancel" size="default">取 消</el-button>
|
<el-button @click="onCancel" size="default">取 消</el-button>
|
||||||
<el-button type="primary" @click="onSubmit" size="default">修 改</el-button>
|
<el-button type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="systemEditUser">
|
<script setup lang="ts" name="systemUserDialog">
|
||||||
import { reactive, onMounted } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
// 定义子组件向父组件传值/事件
|
||||||
|
const emit = defineEmits(['refresh']);
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
|
const userDialogFormRef = ref();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
isShowDialog: false,
|
|
||||||
ruleForm: {
|
ruleForm: {
|
||||||
userName: '', // 账户名称
|
userName: '', // 账户名称
|
||||||
userNickname: '', // 用户昵称
|
userNickname: '', // 用户昵称
|
||||||
@ -108,27 +111,47 @@ const state = reactive({
|
|||||||
describe: '', // 用户描述
|
describe: '', // 用户描述
|
||||||
},
|
},
|
||||||
deptData: [] as DeptTreeType[], // 部门数据
|
deptData: [] as DeptTreeType[], // 部门数据
|
||||||
|
dialog: {
|
||||||
|
isShowDialog: false,
|
||||||
|
type: '',
|
||||||
|
title: '',
|
||||||
|
submitTxt: '',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 打开弹窗
|
// 打开弹窗
|
||||||
const openDialog = (row: RowUserType) => {
|
const openDialog = (type: string, row: RowUserType) => {
|
||||||
state.ruleForm = row;
|
if (type === 'edit') {
|
||||||
state.isShowDialog = true;
|
state.ruleForm = row;
|
||||||
|
state.dialog.title = '修改用户';
|
||||||
|
state.dialog.submitTxt = '修 改';
|
||||||
|
} else {
|
||||||
|
state.dialog.title = '新增用户';
|
||||||
|
state.dialog.submitTxt = '新 增';
|
||||||
|
// 清空表单,此项需加表单验证才能使用
|
||||||
|
// nextTick(() => {
|
||||||
|
// userDialogFormRef.value.resetFields();
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
state.dialog.isShowDialog = true;
|
||||||
|
getMenuData();
|
||||||
};
|
};
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
const closeDialog = () => {
|
const closeDialog = () => {
|
||||||
state.isShowDialog = false;
|
state.dialog.isShowDialog = false;
|
||||||
};
|
};
|
||||||
// 取消
|
// 取消
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
closeDialog();
|
closeDialog();
|
||||||
};
|
};
|
||||||
// 新增
|
// 提交
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
closeDialog();
|
closeDialog();
|
||||||
|
emit('refresh');
|
||||||
|
// if (state.dialog.type === 'add') { }
|
||||||
};
|
};
|
||||||
// 初始化部门数据
|
// 初始化部门数据
|
||||||
const initTableData = () => {
|
const getMenuData = () => {
|
||||||
state.deptData.push({
|
state.deptData.push({
|
||||||
deptName: 'vueNextAdmin',
|
deptName: 'vueNextAdmin',
|
||||||
createTime: new Date().toLocaleString(),
|
createTime: new Date().toLocaleString(),
|
||||||
@ -156,10 +179,6 @@ const initTableData = () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// 页面加载时
|
|
||||||
onMounted(() => {
|
|
||||||
initTableData();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 暴露变量
|
// 暴露变量
|
||||||
defineExpose({
|
defineExpose({
|
||||||
@ -9,14 +9,14 @@
|
|||||||
</el-icon>
|
</el-icon>
|
||||||
查询
|
查询
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button size="default" type="success" class="ml10" @click="onOpenAddUser">
|
<el-button size="default" type="success" class="ml10" @click="onOpenAddUser('add')">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<ele-FolderAdd />
|
<ele-FolderAdd />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
新增用户
|
新增用户
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="state.tableData.data" style="width: 100%">
|
<el-table :data="state.tableData.data" v-loading="state.tableData.loading" style="width: 100%">
|
||||||
<el-table-column type="index" label="序号" width="60" />
|
<el-table-column type="index" label="序号" width="60" />
|
||||||
<el-table-column prop="userName" label="账户名称" show-overflow-tooltip></el-table-column>
|
<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="userNickname" label="用户昵称" show-overflow-tooltip></el-table-column>
|
||||||
@ -34,7 +34,9 @@
|
|||||||
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
|
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column label="操作" width="100">
|
<el-table-column label="操作" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="onOpenEditUser(scope.row)">修改</el-button>
|
<el-button :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="onOpenEditUser('edit', scope.row)"
|
||||||
|
>修改</el-button
|
||||||
|
>
|
||||||
<el-button :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button>
|
<el-button :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -53,8 +55,7 @@
|
|||||||
>
|
>
|
||||||
</el-pagination>
|
</el-pagination>
|
||||||
</el-card>
|
</el-card>
|
||||||
<AddUer ref="addUserRef" />
|
<UserDialog ref="userDialogRef" @refresh="getTableData()" />
|
||||||
<EditUser ref="editUserRef" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -63,12 +64,10 @@ import { defineAsyncComponent, reactive, onMounted, ref } from 'vue';
|
|||||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||||
|
|
||||||
// 引入组件
|
// 引入组件
|
||||||
const AddUer = defineAsyncComponent(() => import('/@/views/system/user/component/addUser.vue'));
|
const UserDialog = defineAsyncComponent(() => import('/@/views/system/user/dialog.vue'));
|
||||||
const EditUser = defineAsyncComponent(() => import('/@/views/system/user/component/editUser.vue'));
|
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const addUserRef = ref();
|
const userDialogRef = ref();
|
||||||
const editUserRef = ref();
|
|
||||||
const state = reactive<SysUserState>({
|
const state = reactive<SysUserState>({
|
||||||
tableData: {
|
tableData: {
|
||||||
data: [],
|
data: [],
|
||||||
@ -82,7 +81,8 @@ const state = reactive<SysUserState>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 初始化表格数据
|
// 初始化表格数据
|
||||||
const initTableData = () => {
|
const getTableData = () => {
|
||||||
|
state.tableData.loading = true;
|
||||||
const data = [];
|
const data = [];
|
||||||
for (let i = 0; i < 2; i++) {
|
for (let i = 0; i < 2; i++) {
|
||||||
data.push({
|
data.push({
|
||||||
@ -102,14 +102,17 @@ const initTableData = () => {
|
|||||||
}
|
}
|
||||||
state.tableData.data = data;
|
state.tableData.data = data;
|
||||||
state.tableData.total = state.tableData.data.length;
|
state.tableData.total = state.tableData.data.length;
|
||||||
|
setTimeout(() => {
|
||||||
|
state.tableData.loading = false;
|
||||||
|
}, 500);
|
||||||
};
|
};
|
||||||
// 打开新增用户弹窗
|
// 打开新增用户弹窗
|
||||||
const onOpenAddUser = () => {
|
const onOpenAddUser = (type: string) => {
|
||||||
addUserRef.value.openDialog();
|
userDialogRef.value.openDialog(type);
|
||||||
};
|
};
|
||||||
// 打开修改用户弹窗
|
// 打开修改用户弹窗
|
||||||
const onOpenEditUser = (row: RowUserType) => {
|
const onOpenEditUser = (type: string, row: RowUserType) => {
|
||||||
editUserRef.value.openDialog(row);
|
userDialogRef.value.openDialog(type, row);
|
||||||
};
|
};
|
||||||
// 删除用户
|
// 删除用户
|
||||||
const onRowDel = (row: RowUserType) => {
|
const onRowDel = (row: RowUserType) => {
|
||||||
@ -119,6 +122,7 @@ const onRowDel = (row: RowUserType) => {
|
|||||||
type: 'warning',
|
type: 'warning',
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
getTableData();
|
||||||
ElMessage.success('删除成功');
|
ElMessage.success('删除成功');
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
@ -126,14 +130,16 @@ const onRowDel = (row: RowUserType) => {
|
|||||||
// 分页改变
|
// 分页改变
|
||||||
const onHandleSizeChange = (val: number) => {
|
const onHandleSizeChange = (val: number) => {
|
||||||
state.tableData.param.pageSize = val;
|
state.tableData.param.pageSize = val;
|
||||||
|
getTableData();
|
||||||
};
|
};
|
||||||
// 分页改变
|
// 分页改变
|
||||||
const onHandleCurrentChange = (val: number) => {
|
const onHandleCurrentChange = (val: number) => {
|
||||||
state.tableData.param.pageNum = val;
|
state.tableData.param.pageNum = val;
|
||||||
|
getTableData();
|
||||||
};
|
};
|
||||||
// 页面加载时
|
// 页面加载时
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initTableData();
|
getTableData();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -127,7 +127,7 @@
|
|||||||
<div class="big-data-down-center">
|
<div class="big-data-down-center">
|
||||||
<div class="big-data-down-center-one">
|
<div class="big-data-down-center-one">
|
||||||
<div class="big-data-down-center-one-content" ref="rightChartData5">
|
<div class="big-data-down-center-one-content" ref="rightChartData5">
|
||||||
<div ref="the3DEarth"></div>
|
<div id="3DEarth"></div>
|
||||||
<div :class="v.topLevelClass" v-for="(v, k) in state.earth3DBtnList" :key="k">
|
<div :class="v.topLevelClass" v-for="(v, k) in state.earth3DBtnList" :key="k">
|
||||||
<div class="circle" v-for="i in 4" :key="i"></div>
|
<div class="circle" v-for="i in 4" :key="i"></div>
|
||||||
<div class="text-box">
|
<div class="text-box">
|
||||||
@ -259,7 +259,6 @@ const state = reactive<Demo2State>({
|
|||||||
earth3DBtnList,
|
earth3DBtnList,
|
||||||
chartData4List,
|
chartData4List,
|
||||||
myCharts: [],
|
myCharts: [],
|
||||||
the3DEarth: null,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 初始化时间
|
// 初始化时间
|
||||||
@ -690,7 +689,7 @@ const initRightChartData2 = () => {
|
|||||||
};
|
};
|
||||||
// 3DEarth 地图
|
// 3DEarth 地图
|
||||||
const init3DEarth = (globeRadius: any) => {
|
const init3DEarth = (globeRadius: any) => {
|
||||||
let el = state.the3DEarth!;
|
let el = <HTMLElement>document.getElementById('3DEarth');
|
||||||
el.style.height = `${rightChartData5.value.offsetHeight}px`;
|
el.style.height = `${rightChartData5.value.offsetHeight}px`;
|
||||||
const myChart = echarts.init(el);
|
const myChart = echarts.init(el);
|
||||||
const option = {
|
const option = {
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { resolve } from 'path';
|
|||||||
import { defineConfig, loadEnv, ConfigEnv } from 'vite';
|
import { defineConfig, loadEnv, ConfigEnv } from 'vite';
|
||||||
import vueSetupExtend from 'vite-plugin-vue-setup-extend';
|
import vueSetupExtend from 'vite-plugin-vue-setup-extend';
|
||||||
|
|
||||||
const pathResolve = (dir: string): any => {
|
const pathResolve = (dir: string) => {
|
||||||
return resolve(__dirname, '.', dir);
|
return resolve(__dirname, '.', dir);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -19,14 +19,14 @@ const viteConfig = defineConfig((mode: ConfigEnv) => {
|
|||||||
root: process.cwd(),
|
root: process.cwd(),
|
||||||
resolve: { alias },
|
resolve: { alias },
|
||||||
base: mode.command === 'serve' ? './' : env.VITE_PUBLIC_PATH,
|
base: mode.command === 'serve' ? './' : env.VITE_PUBLIC_PATH,
|
||||||
hmr: true,
|
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
include: ['element-plus/lib/locale/lang/zh-cn', 'element-plus/lib/locale/lang/en', 'element-plus/lib/locale/lang/zh-tw'],
|
include: ['element-plus/lib/locale/lang/zh-cn', 'element-plus/lib/locale/lang/en', 'element-plus/lib/locale/lang/zh-tw'],
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
port: env.VITE_PORT as unknown as number,
|
port: env.VITE_PORT as unknown as number,
|
||||||
open: env.VITE_OPEN,
|
open: JSON.parse(env.VITE_OPEN),
|
||||||
|
hmr: true,
|
||||||
proxy: {
|
proxy: {
|
||||||
'/gitee': {
|
'/gitee': {
|
||||||
target: 'https://gitee.com',
|
target: 'https://gitee.com',
|
||||||
@ -38,7 +38,6 @@ const viteConfig = defineConfig((mode: ConfigEnv) => {
|
|||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
outDir: 'dist',
|
outDir: 'dist',
|
||||||
sourcemap: false,
|
|
||||||
chunkSizeWarningLimit: 1500,
|
chunkSizeWarningLimit: 1500,
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
output: {
|
output: {
|
||||||
@ -58,6 +57,8 @@ const viteConfig = defineConfig((mode: ConfigEnv) => {
|
|||||||
__VUE_I18N_LEGACY_API__: JSON.stringify(false),
|
__VUE_I18N_LEGACY_API__: JSON.stringify(false),
|
||||||
__VUE_I18N_FULL_INSTALL__: JSON.stringify(false),
|
__VUE_I18N_FULL_INSTALL__: JSON.stringify(false),
|
||||||
__INTLIFY_PROD_DEVTOOLS__: JSON.stringify(false),
|
__INTLIFY_PROD_DEVTOOLS__: JSON.stringify(false),
|
||||||
|
__NEXT_VERSION__: JSON.stringify(process.env.npm_package_version),
|
||||||
|
__NEXT_NAME__: JSON.stringify(process.env.npm_package_name),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user