Compare commits
376 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
39d745536c | ||
|
2335f1f34b | ||
|
aa8cbb847d | ||
|
3e28c838ee | ||
|
18ee9d4ec8 | ||
|
1943c3985f | ||
|
4155d160cb | ||
|
95c86975ac | ||
|
85a96962e0 | ||
|
308d08b81f | ||
|
5a46563a47 | ||
|
e5d7a8aef4 | ||
|
a050e25025 | ||
|
5b64dd0a07 | ||
|
1521fcc529 | ||
|
a4cfc69126 | ||
|
f24bb37e96 | ||
|
f5f84b1469 | ||
|
ffeb363126 | ||
|
8d43c83eef | ||
|
21decad50c | ||
|
0dc2d9dcf6 | ||
|
89ae5eff78 | ||
|
b845a0c253 | ||
|
9195f0ea36 | ||
|
40d10734a2 | ||
|
ac59260a49 | ||
|
9b5f2502f8 | ||
|
cc06c12f8c | ||
|
183ea32be6 | ||
|
a2b7d7b713 | ||
|
991fba682f | ||
|
99d66df3dc | ||
|
8e8e59ae47 | ||
|
fa6a10e7cd | ||
|
c2041c2782 | ||
|
65fe9fce81 | ||
|
c4df5d65e2 | ||
|
283e42f0d2 | ||
|
c016c136ae | ||
|
fa91de42b9 | ||
|
7384ed0ce3 | ||
|
23d0791e4e | ||
|
0ba4a8c4d0 | ||
|
e5c7326a38 | ||
|
96fa681a91 | ||
|
48736f6519 | ||
|
1cdd40be28 | ||
|
9f66eb52a3 | ||
|
60049933ae | ||
|
50ff1b8f9f | ||
|
ae73f1bb14 | ||
|
cc8c7b1e07 | ||
|
6a74374f71 | ||
|
3aefc5fd8b | ||
|
1a4ec87b69 | ||
|
3cc44e4ec1 | ||
|
a29da7fac0 | ||
|
9884e6bb1e | ||
|
a085116ae9 | ||
|
516e5f9566 | ||
|
4c1a31661e | ||
|
3005f8e7a5 | ||
|
2c4c321590 | ||
|
d67f24ef5c | ||
|
5c43c869aa | ||
|
9db45c2297 | ||
|
363c9b7b2b | ||
|
7daf8b05de | ||
|
9d0c481f85 | ||
|
ea0ffa53ef | ||
|
2b80d75327 | ||
|
51fe3e9a2d | ||
|
da4f5f1dd3 | ||
|
40a0dafb4e | ||
|
6913945e1b | ||
|
1ea621bf5a | ||
|
2c6ec39122 | ||
|
df11702b38 | ||
|
2e87918730 | ||
|
8f2fa66647 | ||
|
3febc21536 | ||
|
d1e8ca972f | ||
|
6f702b6e55 | ||
|
2b33da9e9c | ||
|
7387f4d1d3 | ||
|
360f1bb233 | ||
|
e97ea6b731 | ||
|
09c4fb24b5 | ||
|
e42c4ddc3a | ||
|
df8482e4a7 | ||
|
f1e4e44d7e | ||
|
5352269b09 | ||
|
65e48f847f | ||
|
5345501700 | ||
|
b81d122b95 | ||
|
747b6973be | ||
|
d18eb01292 | ||
|
f8d7ced955 | ||
|
bba662ed6c | ||
|
bbb634e9f4 | ||
|
4181fd0aca | ||
|
e33c566eaa | ||
|
a5f94ec488 | ||
|
282019598e | ||
|
41a9ce41a6 | ||
|
bdce56a803 | ||
|
16b2263ae5 | ||
|
b47192516a | ||
|
25e3b339c1 | ||
|
4f71fd1006 | ||
|
5fe157b672 | ||
|
f395391f4c | ||
|
c7e615c7b4 | ||
|
98d3c87bac | ||
|
dece5567ba | ||
|
cd3b44e6ba | ||
|
b546184f3f | ||
|
3ed834204b | ||
|
1613273835 | ||
|
cb4f0a4680 | ||
|
41d8a234a3 | ||
|
aea1fac10b | ||
|
46890f08c8 | ||
|
47ff13c198 | ||
|
e34944a950 | ||
|
d13dfb0043 | ||
|
0b0d7e7cfd | ||
|
b51180bfbf | ||
|
87f43b5f17 | ||
|
d552d86dd2 | ||
|
b87a7f5d65 | ||
|
e4a6b7aad0 | ||
|
700232952f | ||
|
0c1e0952f1 | ||
|
77098b3173 | ||
|
11f6938623 | ||
|
b98663ab7c | ||
|
33bbcd810a | ||
|
c71badd0d5 | ||
|
41f9e174c7 | ||
|
55a02c6053 | ||
|
2056089ed9 | ||
|
20c238f9cd | ||
|
78ae075519 | ||
|
c49c7b5e3a | ||
|
a49fb8a807 | ||
|
db9393b182 | ||
|
0ccaf15f40 | ||
|
2f566b2d1a | ||
|
eb7b68e2e5 | ||
|
de22c060cb | ||
|
445c7b1a5e | ||
|
515c072e59 | ||
|
567127f2b2 | ||
|
755e70e2c5 | ||
|
fcc65450fc | ||
|
1cf1e1765e | ||
|
029c4cfba8 | ||
|
e4b4c782e3 | ||
|
2801b730c5 | ||
|
b04c7510e5 | ||
|
16ff5dcb3c | ||
|
11c9145eaf | ||
|
ed32848708 | ||
|
635ecb60d6 | ||
|
f06b637e47 | ||
|
ce403d8528 | ||
|
08eada130b | ||
|
042c678328 | ||
|
c7e5c4472f | ||
|
f7e4c82b2e | ||
|
3f3b4a6023 | ||
|
620369c4da | ||
|
e680edf65d | ||
|
ad0f7a8811 | ||
|
6ce2afadf7 | ||
|
286e5add86 | ||
|
5ac312af12 | ||
|
308243b16b | ||
|
a1e78d1d1e | ||
|
437b0b069d | ||
|
8de2c3a838 | ||
|
d823d3aa1a | ||
|
a7890763fe | ||
|
e11abd1f9a | ||
|
08e70171bc | ||
|
6cf3425f13 | ||
|
d36efcb3d9 | ||
|
3aee08136b | ||
|
4926efe662 | ||
|
8d17ec38ba | ||
|
6fee6f09de | ||
|
f577bae164 | ||
|
a901e2a4ff | ||
|
b34c427a5d | ||
|
bb0a54c5d8 | ||
|
45e2f2528f | ||
|
fdd7d4e29e | ||
|
ccd951ee61 | ||
|
0c67454008 | ||
|
ba0ed7978f | ||
|
e288a19078 | ||
|
fed5dc8bbf | ||
|
a2ac82a1e8 | ||
|
b5f005613b | ||
|
660b1e91a9 | ||
|
b61371b722 | ||
|
61b969b2f1 | ||
|
647e7de72b | ||
|
07b5481aea | ||
|
fb27a50192 | ||
|
03bf8a1b2e | ||
|
0ed84ae1d2 | ||
|
fdd5d9285e | ||
|
539cec483f | ||
|
668b3851c5 | ||
|
99182cd929 | ||
|
879b3fa74f | ||
|
4dd22edc8d | ||
|
9e480b08e3 | ||
|
6cb9de9a56 | ||
|
ed6419d2d9 | ||
|
311b8f7f38 | ||
|
f00a8786c4 | ||
|
d053263f4b | ||
|
426ae0eb03 | ||
|
937a9d306b | ||
|
8291fd8293 | ||
|
e533167710 | ||
|
2696a626c3 | ||
|
dc2cdd6488 | ||
|
f7610dad14 | ||
|
682e9a96fb | ||
|
bfae72401d | ||
|
10ffbe6be1 | ||
|
db2ef88c5f | ||
|
405bf92794 | ||
|
52a61577b8 | ||
|
2275380e00 | ||
|
1f7c06b777 | ||
|
999e725a3f | ||
|
87216deed1 | ||
|
46b35d8232 | ||
|
8ff7310075 | ||
|
86ed69f161 | ||
|
518c971c88 | ||
|
2f940b0cd1 | ||
|
18e74e0243 | ||
|
35364c44bf | ||
|
0511e9f877 | ||
|
0c91118e09 | ||
|
304fa3e315 | ||
|
a64f6e4c6e | ||
|
f38c2bc0b8 | ||
|
892ae19176 | ||
|
14808f7597 | ||
|
631541083e | ||
|
087a369fbf | ||
|
6da4e83140 | ||
|
edb713ae48 | ||
|
ef07a18847 | ||
|
1e00b2a38b | ||
|
330cd62dcc | ||
|
bc37ff08d7 | ||
|
61c23ff794 | ||
|
09af5dac2c | ||
|
653fd3f15c | ||
|
e835101242 | ||
|
6f6a6c45c3 | ||
|
283e0d6ab4 | ||
|
35bb3b1244 | ||
|
7e9ccac572 | ||
|
24bd54b0ef | ||
|
35849994a8 | ||
|
e62387d684 | ||
|
cf578f4ee3 | ||
|
a80fcbbde6 | ||
|
61b7d639cc | ||
|
f79e813b69 | ||
|
13b25bd0c7 | ||
|
79ceea9b6f | ||
|
fc7160e074 | ||
|
45ff7b8931 | ||
|
124bc3ec22 | ||
|
3088dd53f0 | ||
|
65626b59b6 | ||
|
90ce0c92b3 | ||
|
dc93da7f81 | ||
|
6634bdf0e6 | ||
|
84888ca6da | ||
|
e1780efdfd | ||
|
05bb1d2f9d | ||
|
c5e9ad95f1 | ||
|
44a68be040 | ||
|
3817434d74 | ||
|
07f5caf73b | ||
|
56337192ae | ||
|
f5cad22740 | ||
|
6cdbca8f38 | ||
|
e1efbab2dc | ||
|
362b538bae | ||
|
887fa9d735 | ||
|
d8d760aa0d | ||
|
fdda070a88 | ||
|
9a83b2f251 | ||
|
8437c686be | ||
|
b60e86540a | ||
|
f094c30e46 | ||
|
db0fabb069 | ||
|
0ba8579cab | ||
|
620edee09f | ||
|
82344e240b | ||
|
ab2e3e6573 | ||
|
32cf2ec404 | ||
|
db9e29a2d1 | ||
|
1a49935026 | ||
|
d7df6ff222 | ||
|
cbacecb81e | ||
|
dcd1c3481a | ||
|
78d6521e6a | ||
|
94de8785b6 | ||
|
630d473efb | ||
|
01aa06ed98 | ||
|
10983218d9 | ||
|
b3d5757f86 | ||
|
98ab709793 | ||
|
5dbebba20b | ||
|
2404e96e5d | ||
|
a06b36482c | ||
|
27c88c020c | ||
|
f820bec8eb | ||
|
b4cb7e1fb4 | ||
|
214a1995fb | ||
|
29475e8a43 | ||
|
de0ee7eb69 | ||
|
f458156d80 | ||
|
32f3f23916 | ||
|
6cc720cfe2 | ||
|
e7a4834d6d | ||
|
4e78ba3143 | ||
|
c28185ee78 | ||
|
a04382c0c3 | ||
|
4ded451f88 | ||
|
2a585e3a5c | ||
|
7094edbd2b | ||
|
6300e29cd3 | ||
|
17bdad85bc | ||
|
410013a669 | ||
|
6fef9486e2 | ||
|
9746ac4b98 | ||
|
8d503f2fa5 | ||
|
823eb59a5c | ||
|
6f5939e555 | ||
|
9fecd72f4c | ||
|
ea670e7d22 | ||
|
9c0a63b9fd | ||
|
2573c7a1ed | ||
|
0b58e4ee1f | ||
|
6ed1b6004b | ||
|
5182d9d7fa | ||
|
65b49420c3 | ||
|
62d6c38113 | ||
|
99e8ff82cc | ||
|
1dcc3d799f | ||
|
ab9ee3ce70 | ||
|
02a9c117d0 | ||
|
6f67b0f433 | ||
|
959dea0f8c | ||
|
cee8097690 | ||
|
c0959b8aed | ||
|
2deeedc024 | ||
|
6671d2bbcc | ||
|
1d9934bd48 | ||
|
0d8b7a6834 | ||
|
2711435494 |
13
.gitee/ISSUE_TEMPLATE.zh-CN.md
Normal file
13
.gitee/ISSUE_TEMPLATE.zh-CN.md
Normal file
@ -0,0 +1,13 @@
|
||||
### 当前使用版本、分支(必填,否则不予处理)
|
||||
|
||||
|
||||
|
||||
### 该问题是如何引起的?(确定最新版也有问题再提!!!)
|
||||
|
||||
|
||||
|
||||
### 重现步骤(如果有就写完整)
|
||||
|
||||
|
||||
|
||||
### 报错信息
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,6 +15,7 @@ logs/
|
||||
# idea
|
||||
.idea/
|
||||
*.iml
|
||||
.murphy.yml
|
||||
|
||||
*velocity.log*
|
||||
|
||||
|
107
README.md
107
README.md
@ -6,18 +6,15 @@
|
||||
|
||||
## 框架介绍
|
||||
|
||||
Snowy(SnowyAdmin)是国内首个国产化前后端分离快速开发平台,集成国密加解密插件,
|
||||
Snowy(SnowyAdmin)是国内首个国密前后端分离快速开发平台,集成国密加解密插件,
|
||||
软件层面完全符合等保测评要求,同时实现国产化机型、中间件、数据库适配,是您的不二之选!
|
||||
技术框架与密码结合,让更多的人认识密码,使用密码;更是让前后分离“密”不可分。
|
||||
|
||||
|
||||
采用SpringBoot+MybatisPlus+AntDesignVue+Vite 等更多优秀组件及前沿技术开发,注释丰富,代码简洁,开箱即用!
|
||||
|
||||
|
||||
Snowy谐音“小诺”,恰应小诺团队名称;意思为”下雪的、纯洁的“,寓意框架追求简洁至上,大道至简。
|
||||
|
||||
欢迎加入QQ技术群互相解决问题:732230670
|
||||
|
||||
<p align="center">
|
||||
<p align="center">
|
||||
<a href="https://gitee.com/xiaonuobase/snowy">
|
||||
@ -44,16 +41,23 @@ Snowy谐音“小诺”,恰应小诺团队名称;意思为”下雪的、纯
|
||||
<a href="./LICENSE">
|
||||
<img src="https://img.shields.io/badge/license-Apache%202-red" alt="license Apache 2.0">
|
||||
</a>
|
||||
<a href="https://old.murphysec.com/dr/mQ1xAybeOLMLOxH8pU" alt="OSCS Status">
|
||||
<img src="https://www.oscs1024.com/platform/badge//xiaonuobase/snowy.git.svg?size=small"/>
|
||||
</a>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
## 快速链接
|
||||
|
||||
下载地址:https://gitee.com/xiaonuobase/snowy
|
||||
gitee下载地址:[https://gitee.com/xiaonuobase/snowy](https://gitee.com/xiaonuobase/snowy)
|
||||
|
||||
演示地址:https://snowy.xiaonuo.vip
|
||||
github下载地址(镜像):[https://github.com/xiaonuobase/Snowy](https://github.com/xiaonuobase/Snowy)
|
||||
|
||||
## 支撑组件及启动
|
||||
演示地址:[https://snowy.xiaonuo.vip](https://snowy.xiaonuo.vip)
|
||||
|
||||
文档地址:[https://xiaonuo.vip/doc](https://xiaonuo.vip/doc)
|
||||
|
||||
## 快速启动
|
||||
|
||||
全栈工程师推荐idea
|
||||
|
||||
@ -62,7 +66,7 @@ Snowy谐音“小诺”,恰应小诺团队名称;意思为”下雪的、纯
|
||||
|--- | ----- | ----- |
|
||||
| node.js | 最新版 | JavaScript运行环境 |
|
||||
|
||||
#### 启动前端
|
||||
### 启动前端
|
||||
|
||||
```
|
||||
npm install
|
||||
@ -74,15 +78,78 @@ npm run dev
|
||||
| 插件 | 版本 | 用途 |
|
||||
| --- | ----- | ----- |
|
||||
| jdk | 11 / 1.8 |java环境 |
|
||||
| lombok | idea内 |代码简化插件 |
|
||||
| maven | 最新版 |包管理工具 |
|
||||
| redis | 最新版 | 缓存库 |
|
||||
| mysql | 8.0 / 5.7 | 数据库 |
|
||||
|
||||
#### 启动后端
|
||||
### 启动后端
|
||||
开发工具内配置好maven并在代码中配置数据库即可启动
|
||||
|
||||
## 代码结构
|
||||
|
||||
Snowy2.0框架对代码以插件化的模式进行分包,使得包层级结构更加清晰合理,同时降低了耦合度,关于插件模块化开发的规范请查阅文档【SNOWY开源文档——前端手册or后端手册——开发规范】板块。
|
||||
|
||||
```
|
||||
snowy
|
||||
|-snowy-admin-web == 前端
|
||||
|-public == 基础静态文件
|
||||
|-src == 前端源代码
|
||||
|-api == API接口转发
|
||||
|-assets == 静态文件
|
||||
|-components == VUE组件
|
||||
|-config == 基础配置
|
||||
|-layout == 基础布局
|
||||
|-locales == 多语言配置
|
||||
|-router == 基础路由配置
|
||||
|-store == Pinia缓存配置
|
||||
|-style == 样式风格配置
|
||||
|-utils == 工具类
|
||||
|-views == 所有视图界面
|
||||
|-snowy-common == 基础通用模块
|
||||
|-snowy-plugin == 插件包
|
||||
|-snowy-plugin-auth == 登录鉴权插件
|
||||
|-snowy-plugin-biz == 业务功能插件
|
||||
|-snowy-plugin-client == C端功能插件
|
||||
|-snowy-plugin-dev == 开发工具插件
|
||||
|-snowy-plugin-gen == 代码生成插件
|
||||
|-snowy-plugin-mobile == 移动端管理插件
|
||||
|-snowy-plugin-sys == 系统功能插件
|
||||
|-snowy-plugin-api == 插件api包
|
||||
|-snowy-plugin-auth-api == 登录鉴权插件api接口
|
||||
|-snowy-plugin-biz-api == 业务功能插件api接口
|
||||
|-snowy-plugin-client-api == C端功能插件api接口
|
||||
|-snowy-plugin-dev-api == 开发工具插件api接口
|
||||
|-snowy-plugin-gen == 代码生成插件api接口
|
||||
|-snowy-plugin-mobile == 移动端管理插件api接口
|
||||
|-snowy-plugin-sys-api == 系统功能插件api接口
|
||||
|-snowy-web-app == 主启动模块
|
||||
```
|
||||
|
||||
|
||||
## 分支说明
|
||||
|
||||
- master
|
||||
|
||||
正式稳定版本,具体版本升级内容看更新标签
|
||||
|
||||
- dev
|
||||
|
||||
团队开发的分支(代码可能随时会推,不保证运行和使用)
|
||||
|
||||
- snowy1.8
|
||||
|
||||
1.x分支,目前已停止新增功能,只限于bug的维护,推荐使用2x版本
|
||||
|
||||
## 视频教程
|
||||
|
||||
教程地址(免费开放):[https://space.bilibili.com/50101698/channel/collectiondetail?sid=739071](https://space.bilibili.com/50101698/channel/collectiondetail?sid=739071)
|
||||
|
||||
<img src="https://pan.xiaonuo.vip/?explorer/share/fileOut&shareID=8nOccuKg&path=%7BshareItemLink%3A8nOccuKg%7D%2F"/>
|
||||
|
||||
作者也在上班工作,所以在利用休息时间为大家创作,录制视频的目的也是为各位小伙伴提供文档跟技术交流群聊之外的上手学习资料
|
||||
|
||||
> 视频由小诺开源技术团队王同学(每天一点)进行录制
|
||||
|
||||
## 效果图:fire:
|
||||
|
||||
@ -116,9 +183,12 @@ npm run dev
|
||||
| 用户密码 | SM3完整性保护存储,登录时做完整性校验 |
|
||||
| 用户手机号 | SM4(cbc模式)加解密使用字段脱敏 |
|
||||
|
||||
## 官方微信群
|
||||
## 官方技术群
|
||||
|
||||
因群达到200人以上,需加微信拉群
|
||||
|
||||
QQ技术群:732230670(已满)、685395081
|
||||
|
||||
微信技术群:因群达到200人以上,需加微信拉群
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
@ -127,7 +197,17 @@ npm run dev
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## 原理图解
|
||||
## 代码贡献
|
||||
|
||||
近期有很多热心开源的小伙伴陆续为咱们Snowy框架提交PR或者提出好的建议,基本合格的PR我们都接受,这样您的头像就列入到咱们Snowy仓库的贡献者列表啦!
|
||||
|
||||
如何贡献:
|
||||
|
||||
1、fork一份代码至自己的账号下,本地修改您要提的代码,提交至您fork的仓库
|
||||
|
||||
2、登录gitee后到Snowy仓库下创建Pull Requests,选择您的仓库到Snowy的dev分支,提交即可
|
||||
|
||||
因为dev分支是团队开发分支,并不是统一发版本的测试过的,所以我们建议提代码至dev即可
|
||||
|
||||
## 团队成员
|
||||
|
||||
@ -136,11 +216,12 @@ npm run dev
|
||||
| 俞宝山 | 全栈 | 俞宝山 |
|
||||
| 徐玉祥 | 全栈 | 就是那个锅 |
|
||||
| 董夏雨 | 全栈 | 阿董 |
|
||||
| 王鹏 | 全栈 | 每天一点 |
|
||||
|
||||
## 曾获荣誉
|
||||
|
||||
<p align="center">
|
||||
<img src="https://pan.xiaonuo.vip/?explorer/share/fileOut&shareID=7xtGQLOA&path=%7BshareItemLink%3A7xtGQLOA%7D%2F"/>
|
||||
<img src="https://pan.xiaonuo.vip/?explorer/share/file&hash=ec54DtG4v8DfcUEPF0ACAHWW-urCcymI_0fSSaqMmMXKLsTWdHpQqH0e&name=/%E8%8D%A3%E8%AA%892021%E4%B8%8E2022.jpg"/>
|
||||
</p>
|
||||
|
||||
## 版权说明
|
||||
|
617
pom.xml
617
pom.xml
@ -13,13 +13,74 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.5.4</version>
|
||||
<version>2.5.12</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<snowy.version>2.0.0</snowy.version>
|
||||
<spring-framework.version>5.3.26</spring-framework.version>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<!-- 锁定依赖版本号 -->
|
||||
<ali.oss.version>3.14.0</ali.oss.version>
|
||||
<aliyun.sdk.dm.version>3.3.1</aliyun.sdk.dm.version>
|
||||
<aliyun.sdk.dysmsapi.version>2.0.9</aliyun.sdk.dysmsapi.version>
|
||||
<aliyun.sdk.ecs.version>3.1.0</aliyun.sdk.ecs.version>
|
||||
<bcprov.jdk15on.version>1.70</bcprov.jdk15on.version>
|
||||
<beetl.version>1.2.40.Beetl.RELEASE</beetl.version>
|
||||
<checker.qual.version>3.31.0</checker.qual.version>
|
||||
<commons.beanutils.version>1.9.4</commons.beanutils.version>
|
||||
<commons.compress.version>1.22</commons.compress.version>
|
||||
<commons.pool2.version>2.11.1</commons.pool2.version>
|
||||
<druid.version>1.2.9</druid.version>
|
||||
<dynamic.datasource.version>3.5.1</dynamic.datasource.version>
|
||||
<easy.trans.version>2.1.7</easy.trans.version>
|
||||
<easyexcel.version>3.2.1</easyexcel.version>
|
||||
<easypoi.version>4.3.0</easypoi.version>
|
||||
<fastjson.version>2.0.24</fastjson.version>
|
||||
<gson.version>2.8.9</gson.version>
|
||||
<guava.version>31.1-jre</guava.version>
|
||||
<hutool.version>5.8.12</hutool.version>
|
||||
<ip2region.version>2.6.3</ip2region.version>
|
||||
<jackson.annotations.version>2.14.2</jackson.annotations.version>
|
||||
<jackson.core.version>2.14.2</jackson.core.version>
|
||||
<jackson.databind.version>2.14.2</jackson.databind.version>
|
||||
<jackson.datatype.jdk8.version>2.14.2</jackson.datatype.jdk8.version>
|
||||
<jackson.datatype.jsr310.version>2.14.2</jackson.datatype.jsr310.version>
|
||||
<jackson.module.parameter.names.version>2.14.2</jackson.module.parameter.names.version>
|
||||
<javax.mail.version>1.6.2</javax.mail.version>
|
||||
<jettison.version>1.5.3</jettison.version>
|
||||
<junit.version>4.13.2</junit.version>
|
||||
<just.auth.version>1.16.5</just.auth.version>
|
||||
<knife4j.version>2.0.9</knife4j.version>
|
||||
<logback.classic.version>1.2.0</logback.classic.version>
|
||||
<lombok.versin>1.18.22</lombok.versin>
|
||||
<minio.version>8.5.2</minio.version>
|
||||
<mssql.connector.java.version>9.2.1.jre8</mssql.connector.java.version>
|
||||
<mybatis.plus.version>3.5.3.1</mybatis.plus.version>
|
||||
<mybatis.version>3.5.10</mybatis.version>
|
||||
<mysql.connector.java.version>8.0.28</mysql.connector.java.version>
|
||||
<netty.common.version>4.1.89.Final</netty.common.version>
|
||||
<netty.handler.version>4.1.89.Final</netty.handler.version>
|
||||
<okhttp3.version>4.10.0</okhttp3.version>
|
||||
<okio.version>3.3.0</okio.version>
|
||||
<oracle.connector.java.version>21.5.0.0</oracle.connector.java.version>
|
||||
<oracle.nls.orai18n.version>19.7.0.0</oracle.nls.orai18n.version>
|
||||
<oshi.core.version>6.2.2</oshi.core.version>
|
||||
<pinyin.version>2.5.1</pinyin.version>
|
||||
<postgres.connector.java.version>42.2.25</postgres.connector.java.version>
|
||||
<protobuf.java.version>3.21.12</protobuf.java.version>
|
||||
<sa.token.version>1.31.0</sa.token.version>
|
||||
<smcrypto.version>0.3.2</smcrypto.version>
|
||||
<snakeyaml.version>2.0</snakeyaml.version>
|
||||
<spring.context.version>5.3.19</spring.context.version>
|
||||
<spring.security.crypto.version>6.0.2</spring.security.crypto.version>
|
||||
<springfox.swagger2.version>2.10.5</springfox.swagger2.version>
|
||||
<ten.cos.version>5.6.68</ten.cos.version>
|
||||
<ten.sdk.ses.version>3.1.455</ten.sdk.ses.version>
|
||||
<ten.sdk.sms.version>3.1.455</ten.sdk.sms.version>
|
||||
<tomcat.embed.core.version>9.0.72</tomcat.embed.core.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
@ -36,6 +97,556 @@
|
||||
<module>snowy-web-app</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
<!-- snowy-common -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-common</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-auth-api -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-auth-api</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-biz-api -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-biz-api</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-client-api -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-client-api</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-dev-api -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-dev-api</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-gen-api -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-gen-api</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-mobile-api -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-mobile-api</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-sys-api -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-sys-api</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-auth -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-auth</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-biz -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-biz</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-client -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-client</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-dev -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-dev</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-gen -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-gen</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-mobile -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-mobile</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snowy-plugin-sys -->
|
||||
<dependency>
|
||||
<groupId>vip.xiaonuo</groupId>
|
||||
<artifactId>snowy-plugin-sys</artifactId>
|
||||
<version>${snowy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.versin}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- druid -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>${druid.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- mybatis -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
<version>${mybatis.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- mybatis-plus-core -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-core</artifactId>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- mybatis-plus -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- easy-trans -->
|
||||
<dependency>
|
||||
<groupId>com.fhs-opensource</groupId>
|
||||
<artifactId>easy-trans-spring-boot-starter</artifactId>
|
||||
<version>${easy.trans.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- easy-trans-mybatis-plus-extend -->
|
||||
<dependency>
|
||||
<groupId>com.fhs-opensource</groupId>
|
||||
<artifactId>easy-trans-mybatis-plus-extend</artifactId>
|
||||
<version>${easy.trans.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- redis -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
<version>${commons.pool2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- okhttp -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${okhttp3.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- okio -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okio</groupId>
|
||||
<artifactId>okio</artifactId>
|
||||
<version>${okio.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- hutool -->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- pinyin4j -->
|
||||
<dependency>
|
||||
<groupId>com.belerweb</groupId>
|
||||
<artifactId>pinyin4j</artifactId>
|
||||
<version>${pinyin.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- ip2region -->
|
||||
<dependency>
|
||||
<groupId>org.lionsoul</groupId>
|
||||
<artifactId>ip2region</artifactId>
|
||||
<version>${ip2region.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- knife4j -->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||
<version>${knife4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- easy-poi -->
|
||||
<dependency>
|
||||
<groupId>cn.afterturn</groupId>
|
||||
<artifactId>easypoi-spring-boot-starter</artifactId>
|
||||
<version>${easypoi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- sm-crypto -->
|
||||
<dependency>
|
||||
<groupId>com.antherd</groupId>
|
||||
<artifactId>sm-crypto</artifactId>
|
||||
<version>${smcrypto.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- easyexcel -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel</artifactId>
|
||||
<version>${easyexcel.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token-core -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-core</artifactId>
|
||||
<version>${sa.token.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||
<version>${sa.token.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token 整合 redis (使用jackson序列化方式) -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-dao-redis-jackson</artifactId>
|
||||
<version>${sa.token.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token插件:权限缓存与业务缓存分离 -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-alone-redis</artifactId>
|
||||
<version>${sa.token.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token 插件:整合SSO -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-sso</artifactId>
|
||||
<version>${sa.token.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JustAuth 第三方登录 -->
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>${just.auth.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- beetl模板引擎 -->
|
||||
<dependency>
|
||||
<groupId>com.ibeetl</groupId>
|
||||
<artifactId>beetl-framework-starter</artifactId>
|
||||
<version>${beetl.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--腾讯云上传文件客户端-->
|
||||
<dependency>
|
||||
<groupId>com.qcloud</groupId>
|
||||
<artifactId>cos_api</artifactId>
|
||||
<version>${ten.cos.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--阿里云上传文件客户端-->
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
<version>${ali.oss.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--minio上传文件客户端-->
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<version>${minio.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--java邮件发送-->
|
||||
<dependency>
|
||||
<groupId>com.sun.mail</groupId>
|
||||
<artifactId>javax.mail</artifactId>
|
||||
<version>${javax.mail.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--阿里云邮件发送-->
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-dm</artifactId>
|
||||
<version>${aliyun.sdk.dm.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 腾讯云邮件发送 -->
|
||||
<dependency>
|
||||
<groupId>com.tencentcloudapi</groupId>
|
||||
<artifactId>tencentcloud-sdk-java-ses</artifactId>
|
||||
<version>${ten.sdk.ses.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--阿里云短信发送-->
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>dysmsapi20170525</artifactId>
|
||||
<version>${aliyun.sdk.dysmsapi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--腾讯云短信发送-->
|
||||
<dependency>
|
||||
<groupId>com.tencentcloudapi</groupId>
|
||||
<artifactId>tencentcloud-sdk-java-sms</artifactId>
|
||||
<version>${ten.sdk.sms.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--系统硬件信息-->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>${oshi.core.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- junit -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- logback-classic -->
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback.classic.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- gson -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>${gson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- guava -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- netty-common -->
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-common</artifactId>
|
||||
<version>${netty.common.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- netty-common -->
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-handler</artifactId>
|
||||
<version>${netty.handler.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- jettison -->
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jettison</groupId>
|
||||
<artifactId>jettison</artifactId>
|
||||
<version>${jettison.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- snakeyaml -->
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>${snakeyaml.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- spring-context -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.context.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- spring-security-crypto -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-crypto</artifactId>
|
||||
<version>${spring.security.crypto.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- springfox-swagger2 -->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>${springfox.swagger2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- tomcat-embed-core -->
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
<version>${tomcat.embed.core.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- fastjson -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- jackson-annotations -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>${jackson.annotations.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- jackson-core -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson.core.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- jackson-databind -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.databind.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- jackson-datatype -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jdk8</artifactId>
|
||||
<version>${jackson.datatype.jdk8.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- jackson-jsr310 -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>${jackson.datatype.jsr310.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- jackson-module-parameter-names -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.module</groupId>
|
||||
<artifactId>jackson-module-parameter-names</artifactId>
|
||||
<version>${jackson.module.parameter.names.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- commons-beanutils -->
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>${commons.beanutils.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- commons-compress -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>${commons.compress.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- protobuf-java -->
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
<version>${protobuf.java.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- checker-qual -->
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<version>${checker.qual.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- bcprov-jdk15on -->
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<version>${bcprov.jdk15on.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- dynamic-datasource -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
<version>${dynamic.datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- mysql -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql.connector.java.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- postgresql -->
|
||||
<!--<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>${postgres.connector.java.version}</version>
|
||||
</dependency>-->
|
||||
|
||||
<!-- oracle -->
|
||||
<!--<dependency>
|
||||
<groupId>com.oracle.database.jdbc</groupId>
|
||||
<artifactId>ojdbc8</artifactId>
|
||||
<version>${oracle.connector.java.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.oracle.database.nls</groupId>
|
||||
<artifactId>orai18n</artifactId>
|
||||
<version>${oracle.nls.orai18n.version}</version>
|
||||
</dependency>-->
|
||||
|
||||
<!-- mssql -->
|
||||
<!--<dependency>
|
||||
<groupId>com.microsoft.sqlserver</groupId>
|
||||
<artifactId>mssql-jdbc</artifactId>
|
||||
<version>${mssql.connector.java.version}</version>
|
||||
</dependency>-->
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@ -67,10 +678,6 @@
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>false</filtering>
|
||||
<includes>
|
||||
<include>*.xdb</include>
|
||||
</includes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
|
@ -9,3 +9,6 @@ VITE_API_BASEURL = http://127.0.0.1:82
|
||||
|
||||
# 本地端口
|
||||
VITE_PORT = 81
|
||||
|
||||
# 开启设置抽屉
|
||||
VITE_SET_DRAWER = true
|
||||
|
@ -9,3 +9,6 @@ VITE_API_BASEURL = http://127.0.0.1:82
|
||||
|
||||
# 本地端口
|
||||
VITE_PORT = 81
|
||||
|
||||
# 开启设置抽屉
|
||||
VITE_SET_DRAWER = false
|
||||
|
@ -33,6 +33,7 @@ module.exports = {
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/html-self-closing': 'off',
|
||||
'vue/v-on-event-hyphenation': 'off',
|
||||
'vue/multi-word-component-names': 'off'
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'prettier/prettier': ['error', { endOfLine: 'auto' }]
|
||||
}
|
||||
}
|
||||
|
6
snowy-admin-web/.gitignore
vendored
6
snowy-admin-web/.gitignore
vendored
@ -1,6 +1,8 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
*.lock
|
||||
package-lock.json
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
@ -12,7 +14,9 @@ yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
package-lock.json
|
||||
# other files
|
||||
stats.html
|
||||
auto-imports.d.ts
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
|
@ -10,69 +10,73 @@
|
||||
"license": "Apache-2.0",
|
||||
"author": "yubaoshan",
|
||||
"scripts": {
|
||||
"serve": "vite",
|
||||
"dev": "vite --mode development",
|
||||
"serve": "vite --host 0.0.0.0",
|
||||
"dev": "vite --mode development --host 0.0.0.0",
|
||||
"preview": "vite preview",
|
||||
"build": "vite build --mode production",
|
||||
"prod": "vite --mode production"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "4.0.1",
|
||||
"@ant-design/icons-vue": "^6.0.1",
|
||||
"@antv/g2plot": "^2.4.10",
|
||||
"@chenfengyuan/vue-qrcode": "2",
|
||||
"@highlightjs/vue-plugin": "^2.1.0",
|
||||
"@tinymce/tinymce-vue": "4.0.5",
|
||||
"ant-design-vue": "3.2.10",
|
||||
"axios": "0.24.0",
|
||||
"@ant-design/colors": "7.0.0",
|
||||
"@ant-design/icons-vue": "6.1.0",
|
||||
"@antv/g2plot": "2.4.28",
|
||||
"@chenfengyuan/vue-qrcode": "2.0.0",
|
||||
"@highlightjs/vue-plugin": "2.1.0",
|
||||
"@tinymce/tinymce-vue": "5.0.0",
|
||||
"ant-design-vue": "3.2.14",
|
||||
"axios": "1.1.3",
|
||||
"cropperjs": "1.5.12",
|
||||
"dayjs": "^1.11.5",
|
||||
"echarts": "5.2.2",
|
||||
"echarts-stat": "^1.2.0",
|
||||
"enquire.js": "^2.1.6",
|
||||
"highlight.js": "^11.6.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"dayjs": "1.11.7",
|
||||
"echarts": "5.4.0",
|
||||
"echarts-stat": "1.2.0",
|
||||
"enquire.js": "2.1.6",
|
||||
"fuse.js": "6.6.2",
|
||||
"highlight.js": "11.6.0",
|
||||
"hotkeys-js": "3.10.1",
|
||||
"js-pinyin": "0.1.9",
|
||||
"lodash-es": "4.17.21",
|
||||
"nprogress": "0.2.0",
|
||||
"screenfull": "^6.0.2",
|
||||
"sm-crypto": "^0.3.11",
|
||||
"snowflake-id": "^1.1.0",
|
||||
"sortablejs": "1.14.0",
|
||||
"tinymce": "5.10.2",
|
||||
"vue": "3.2.31",
|
||||
"vue-cropper": "^1.0.1",
|
||||
"vue-i18n": "^9.1.10",
|
||||
"vue-router": "4.0.12",
|
||||
"vue3-colorpicker": "^2.0.4",
|
||||
"vue3-tree-org": "^3.1.6",
|
||||
"vuedraggable-es": "4.1.0",
|
||||
"vuex": "4.0.2"
|
||||
"pinia": "2.0.33",
|
||||
"qs": "6.11.1",
|
||||
"screenfull": "6.0.2",
|
||||
"sm-crypto": "0.3.11",
|
||||
"snowflake-id": "1.1.0",
|
||||
"sortablejs": "1.15.0",
|
||||
"tinymce": "6.2.0",
|
||||
"vue": "3.2.44",
|
||||
"vue-cropper": "1.0.5",
|
||||
"vue-i18n": "9.2.2",
|
||||
"vue-router": "4.1.6",
|
||||
"vue3-colorpicker": "2.0.4",
|
||||
"vue3-tree-org": "4.1.1",
|
||||
"vuedraggable-es": "4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^0.18.3",
|
||||
"@vitejs/plugin-legacy": "^1.6.4",
|
||||
"@vitejs/plugin-vue": "^2.1.0",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.8",
|
||||
"@vue/compiler-sfc": "^3.2.31",
|
||||
"@vue/eslint-config-standard": "^4.0.0",
|
||||
"antd-dayjs-vite-plugin": "^1.2.0",
|
||||
"antd-less-to-css-variable": "^1.0.5",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"babel-eslint": "10.1.0",
|
||||
"eslint": "^7.11.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-vue": "^9.1.1",
|
||||
"less": "^4.1.2",
|
||||
"postcss": "^8.4.7",
|
||||
"prettier": "^2.4.1",
|
||||
"rollup-plugin-visualizer": "^5.7.1",
|
||||
"tailwindcss": "^3.0.23",
|
||||
"typescript": "^4.5.5",
|
||||
"unplugin-auto-import": "^0.11.1",
|
||||
"unplugin-vue-components": "^0.17.14",
|
||||
"vite": "2.8.6",
|
||||
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||
"vue-eslint-parser": "^9.0.3"
|
||||
"@antfu/eslint-config": "0.29.4",
|
||||
"@babel/eslint-parser": "7.19.1",
|
||||
"@vitejs/plugin-legacy": "3.0.2",
|
||||
"@vitejs/plugin-vue": "4.1.0",
|
||||
"@vitejs/plugin-vue-jsx": "3.0.1",
|
||||
"@vue/compiler-sfc": "3.2.47",
|
||||
"@vue/eslint-config-standard": "8.0.1",
|
||||
"antd-less-to-css-variable": "1.0.5",
|
||||
"autoprefixer": "10.4.13",
|
||||
"eslint": "8.26.0",
|
||||
"eslint-config-prettier": "8.5.0",
|
||||
"eslint-plugin-prettier": "4.2.1",
|
||||
"eslint-plugin-vue": "9.7.0",
|
||||
"less": "4.1.3",
|
||||
"postcss": "8.4.21",
|
||||
"prettier": "2.8.7",
|
||||
"rollup-plugin-visualizer": "5.8.3",
|
||||
"tailwindcss": "3.2.7",
|
||||
"typescript": "4.9.5",
|
||||
"unplugin-auto-import": "0.15.2",
|
||||
"unplugin-vue-components": "0.24.1",
|
||||
"vite": "4.2.1",
|
||||
"vite-plugin-compression": "0.5.1",
|
||||
"vite-plugin-vue-setup-extend": "0.4.0",
|
||||
"vue-eslint-parser": "9.1.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
|
@ -15,7 +15,7 @@ module.exports = {
|
||||
tabWidth: 2,
|
||||
// 使用tab符缩进,false为空格缩进
|
||||
useTabs: true,
|
||||
// 行尾不需要分号
|
||||
// 行尾需要分号
|
||||
semi: false,
|
||||
// 使用单引号
|
||||
singleQuote: true,
|
||||
@ -31,15 +31,6 @@ module.exports = {
|
||||
jsxBracketSameLine: true,
|
||||
// 箭头函数,只有一个参数的时候,也需要括号
|
||||
arrowParens: 'always',
|
||||
// 每个文件格式化的范围是文件的全部内容
|
||||
rangeStart: 0,
|
||||
rangeEnd: Infinity,
|
||||
// 不需要写文件开头的 @prettier
|
||||
requirePragma: false,
|
||||
// 不需要自动在文件开头插入 @prettier
|
||||
insertPragma: false,
|
||||
// 使用默认的折行标准
|
||||
proseWrap: 'preserve',
|
||||
// 根据显示样式决定 html 要不要折行
|
||||
htmlWhitespaceSensitivity: 'css',
|
||||
// 换行符使用 lf
|
||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 31 KiB |
@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 750 750" style="enable-background:new 0 0 750 750;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{opacity:0.35;fill:#B3B3B3;}
|
||||
.st1{opacity:0.1;fill:#B3B3B3;}
|
||||
.st2{opacity:0.3;fill:#B3B3B3;}
|
||||
.st3{opacity:0.1;}
|
||||
.st4{fill:#B3B3B3;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M465.1,261.4H264c-1.3,0-2.4,1.1-2.4,2.4v255.6c0,1.3,1.1,2.4,2.4,2.4h201.1c1.3,0,2.4-1.1,2.4-2.4V263.8
|
||||
C467.5,262.4,466.4,261.4,465.1,261.4z M417.9,443c0,1.3-1.1,2.4-2.4,2.4h-102c-1.3,0-2.4-1.1-2.4-2.4v-11.3c0-1.3,1.1-2.4,2.4-2.4
|
||||
h102c1.3,0,2.4,1.1,2.4,2.4V443z M417.9,397.2c0,1.3-1.1,2.4-2.4,2.4h-102c-1.3,0-2.4-1.1-2.4-2.4v-11.3c0-1.3,1.1-2.4,2.4-2.4h102
|
||||
c1.3,0,2.4,1.1,2.4,2.4V397.2z M417.9,351.5c0,1.3-1.1,2.4-2.4,2.4h-102c-1.3,0-2.4-1.1-2.4-2.4v-11.3c0-1.3,1.1-2.4,2.4-2.4h102
|
||||
c1.3,0,2.4,1.1,2.4,2.4V351.5z"/>
|
||||
<g>
|
||||
<path class="st1" d="M462.1,236.8L462.1,236.8C384.8,236.2,321,295.1,314,370.7c-18.5-19.1-44.4-31.1-73.1-31.3h0
|
||||
c-56.8-0.4-103.2,45.3-103.6,102.1l-0.8,101.4l175.6,1.3l30.1,0.2l265.1,2l1.2-160.9C609.2,304,543.6,237.4,462.1,236.8z"/>
|
||||
<path class="st2" d="M216.9,227.4c-3.4,0-6.5,1.1-9,2.9c0.2-1,0.3-2,0.3-3c0.1-8.3-6.6-15.1-15-15.2s-15.1,6.6-15.2,15
|
||||
c0,0.3,0,0.6,0,0.9c-1.6-0.6-3.4-1-5.2-1c-8.3-0.1-15.1,6.6-15.2,15c-0.1,8.2,6.4,14.9,14.5,15.2l0,0l44.6,0.3
|
||||
c8.3,0.1,15.1-6.6,15.2-15S225.2,227.5,216.9,227.4z"/>
|
||||
<path class="st2" d="M596.4,194.2c-3.4,0-6.5,1.1-9,2.9c0.2-1,0.3-2,0.3-3c0.1-8.3-6.6-15.1-15-15.2s-15.1,6.6-15.2,15
|
||||
c0,0.3,0,0.6,0,0.9c-1.6-0.6-3.4-1-5.2-1c-8.3-0.1-15.1,6.6-15.2,15c-0.1,8.2,6.4,14.9,14.5,15.2l0,0l44.6,0.3
|
||||
c8.3,0.1,15.1-6.6,15.2-15S604.7,194.3,596.4,194.2z"/>
|
||||
<g>
|
||||
<g class="st3">
|
||||
<path class="st4" d="M496.9,497.5c-2.1,0-3.7,1.6-3.7,3.7c0,1.5,0.8,2.7,2,3.3l-0.5,65.1l3.5,0l0.5-65.3
|
||||
c1.1-0.6,1.8-1.8,1.8-3.1C500.6,499.1,499,497.6,496.9,497.5z"/>
|
||||
<path class="st4" d="M572.3,501.7c0-1.9-1.6-3.6-3.7-3.7c-2.1,0-3.7,1.6-3.7,3.7c0,1.4,0.8,2.6,1.9,3.2l-0.5,65.2l3.5,0
|
||||
l0.5-65.2C571.5,504.3,572.2,503.1,572.3,501.7z"/>
|
||||
</g>
|
||||
|
||||
<rect x="522.7" y="472.2" transform="matrix(7.448311e-03 -1 1 7.448311e-03 8.6828 1045.4733)" class="st1" width="16.5" height="92.3"/>
|
||||
<polygon class="st1" points="495.4,509.8 495.2,510.1 485.5,526.3 484.8,526.3 484.9,509.8 "/>
|
||||
<polygon class="st1" points="518.7,510 508.8,526.5 496.3,526.4 500.2,519.8 506,509.9 "/>
|
||||
<polygon class="st1" points="542,510.2 532.1,526.6 519.6,526.5 529.3,510.1 "/>
|
||||
<polygon class="st1" points="565.3,510.4 555.5,526.8 542.9,526.7 552.7,510.3 "/>
|
||||
<polygon class="st1" points="577.2,510.4 577.1,527 566.2,526.9 576,510.4 "/>
|
||||
|
||||
<rect x="522.5" y="497.7" transform="matrix(7.448311e-03 -1 1 7.448311e-03 -17.0149 1070.603)" class="st1" width="16.5" height="92.3"/>
|
||||
<polygon class="st1" points="495.2,535.3 495,535.6 485.3,551.8 484.6,551.8 484.7,535.3 "/>
|
||||
<polygon class="st1" points="518.5,535.5 508.6,552 496.1,551.9 500,545.3 505.8,535.4 "/>
|
||||
<polygon class="st1" points="541.8,535.7 531.9,552.1 519.4,552 529.1,535.6 "/>
|
||||
<polygon class="st1" points="565.1,535.9 555.4,552.3 542.7,552.2 552.5,535.8 "/>
|
||||
<polygon class="st1" points="577,536 576.9,552.5 566,552.4 575.8,536 "/>
|
||||
<path class="st1" d="M577.1,527c0,0,0-0.1,0-0.3l0-0.9c0-0.7,0-1.8,0-3.2c0-2.8,0.1-6.9,0.1-12.2l0.1,0.1l-92.3-0.5l0,0l0.1-0.1
|
||||
c0,5.6-0.1,11.2-0.1,16.5l-0.1-0.1l65.8,0.6l19.5,0.1l5.3,0l0,0l-5.3,0l-19.5-0.1l-65.8-0.3l-0.3,0l0.1-16.8l0.1,0l92.3,0.8
|
||||
l0.1,0l0,0.1c0,5.3-0.1,9.4-0.1,12.2c0,1.5,0,2.5,0,3.2l0,0.7C577.1,526.8,577.1,527,577.1,527z"/>
|
||||
<path class="st1" d="M576.9,552.5c0,0,0-0.1,0-0.3l0-0.9c0-0.7,0-1.8,0-3.2c0-2.8,0.1-6.9,0.1-12.2l0.1,0.1l-92.3-0.5l0,0
|
||||
l0.1-0.1c0,5.6-0.1,11.2-0.1,16.5l-0.1-0.1l65.8,0.6l19.5,0.1l5.3,0l0,0l-5.3,0l-19.5-0.1l-65.8-0.3l-0.3,0l0.1-16.7l0.1,0
|
||||
l92.3,0.8l0.1,0l0,0.1c0,5.3-0.1,9.4-0.1,12.2c0,1.5,0,2.5,0,3.2l0,0.7C576.9,552.3,576.9,552.5,576.9,552.5z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 4.1 KiB |
File diff suppressed because one or more lines are too long
@ -1,236 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 456 262.1" style="enable-background:new 0 0 456 262.1;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{opacity:0.4;fill:url(#SVGID_1_);enable-background:new ;}
|
||||
.st1{opacity:0.7;}
|
||||
.st2{opacity:0.4;fill:url(#SVGID_2_);enable-background:new ;}
|
||||
.st3{opacity:0.4;fill:url(#SVGID_3_);enable-background:new ;}
|
||||
.st4{opacity:0.4;fill:url(#SVGID_4_);enable-background:new ;}
|
||||
.st5{opacity:0.4;fill:url(#SVGID_5_);enable-background:new ;}
|
||||
.st6{opacity:0.6;}
|
||||
.st7{fill:#0073CD;}
|
||||
.st8{fill:#40A8F5;}
|
||||
.st9{fill:#53B9F5;}
|
||||
.st10{fill:#85D3FF;}
|
||||
.st11{fill:#8CD7FF;}
|
||||
.st12{fill:#EBFCFF;}
|
||||
.st13{fill:none;stroke:url(#SVGID_6_);stroke-width:2;stroke-miterlimit:10;}
|
||||
.st14{fill:none;stroke:url(#SVGID_7_);stroke-width:2;stroke-miterlimit:10;}
|
||||
.st15{fill:none;stroke:url(#SVGID_8_);stroke-width:2;stroke-miterlimit:10;}
|
||||
.st16{fill:none;stroke:url(#SVGID_9_);stroke-width:2;stroke-miterlimit:10;}
|
||||
.st17{fill:none;stroke:url(#SVGID_10_);stroke-width:2;stroke-miterlimit:10;}
|
||||
.st18{fill:none;stroke:url(#SVGID_11_);stroke-width:2;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<title>升级中</title>
|
||||
<g id="图层_2_1_">
|
||||
<g id="图层_1-2">
|
||||
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="232.745" y1="39.57" x2="232.745" y2="1.88" gradientTransform="matrix(1 0 0 -1 0 264)">
|
||||
<stop offset="0" style="stop-color:#81CFFF"/>
|
||||
<stop offset="1" style="stop-color:#5ECFFF;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<path class="st0" d="M412.3,262.1c-23-23-61-37.7-179.5-37.7S76.2,239.1,53.2,262.1H412.3z"/>
|
||||
<g class="st1">
|
||||
|
||||
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="349.365" y1="237.3224" x2="349.365" y2="59.9676" gradientTransform="matrix(1 0 0 -1 0 264)">
|
||||
<stop offset="0" style="stop-color:#81CFFF"/>
|
||||
<stop offset="1" style="stop-color:#5ECFFF;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<path class="st2" d="M380.7,26.7h-62.6c-1.5-0.1-2.8,1.1-2.8,2.6v172.2c0.1,1.5,1.3,2.7,2.8,2.6h62.6c1.5,0.1,2.7-1.1,2.8-2.6
|
||||
V29.3C383.4,27.8,382.2,26.6,380.7,26.7z M328.3,147c0,0.5-0.4,0.9-0.9,0.9c0,0,0,0,0,0h-3.6c-0.5,0-0.9-0.4-0.9-0.8c0,0,0,0,0,0
|
||||
v-19.7c0-0.5,0.4-0.9,0.9-0.9c0,0,0,0,0,0h3.6c0.5,0,0.9,0.4,0.9,0.9c0,0,0,0,0,0V147z M328.3,116.8c0,0.5-0.4,0.9-0.9,0.9
|
||||
c0,0,0,0,0,0h-3.6c-0.5,0-0.9-0.4-0.9-0.9c0,0,0,0,0,0V97c0-0.5,0.4-0.9,0.9-0.9c0,0,0,0,0,0h3.6c0.5,0,0.9,0.4,0.9,0.9
|
||||
c0,0,0,0,0,0V116.8z M328.3,86.5c0,0.5-0.4,0.9-0.9,0.9c0,0,0,0,0,0h-3.6c-0.5,0-0.9-0.4-0.9-0.9c0,0,0,0,0,0V66.8
|
||||
c0-0.5,0.4-0.9,0.9-0.9c0,0,0,0,0,0h3.6c0.5,0,0.9,0.4,0.9,0.9c0,0,0,0,0,0V86.5z M328.3,56.3c0,0.5-0.4,0.9-0.9,0.9c0,0,0,0,0,0
|
||||
h-3.6c-0.5,0-0.9-0.4-0.9-0.9c0,0,0,0,0,0V36.6c0-0.5,0.4-0.9,0.9-0.9c0,0,0,0,0,0h3.6c0.5,0,0.9,0.4,0.9,0.9c0,0,0,0,0,0V56.3z
|
||||
M340,147c0,0.5-0.4,0.9-0.9,0.9c0,0,0,0,0,0h-3.6c-0.5,0-0.9-0.4-0.9-0.9c0,0,0,0,0,0v-19.7c0-0.5,0.4-0.9,1-0.9h3.6
|
||||
c0.5,0,0.9,0.4,0.9,0.9V147z M340,116.8c0,0.5-0.4,0.9-0.9,0.9h-3.6c-0.5,0-0.9-0.4-1-0.9V97c0-0.5,0.4-0.9,1-0.9h3.6
|
||||
c0.5,0,0.9,0.4,0.9,0.9V116.8z M340,86.5c0,0.5-0.4,0.9-0.9,0.9h-3.6c-0.5,0-0.9-0.4-1-0.9V66.8c0-0.5,0.4-0.9,1-0.9h3.6
|
||||
c0.5,0,0.9,0.4,0.9,0.9V86.5z M340,56.3c0,0.5-0.4,0.9-0.9,0.9h-3.6c-0.5,0-0.9-0.4-1-0.9V36.6c0-0.5,0.4-0.9,1-0.9h3.6
|
||||
c0.5,0,0.9,0.4,0.9,0.9V56.3z M351.7,147c0,0.5-0.4,0.9-0.9,0.9c0,0,0,0,0,0h-3.6c-0.5,0-0.9-0.4-0.9-0.9c0,0,0,0,0,0v-19.7
|
||||
c0-0.5,0.4-0.9,0.9-0.9h3.6c0.5,0,0.9,0.4,0.9,0.9V147z M351.7,116.8c0,0.5-0.4,0.9-0.9,0.9h-3.6c-0.5,0-0.9-0.4-0.9-0.9V97
|
||||
c0-0.5,0.4-0.9,0.9-0.9h3.6c0.5,0,0.9,0.4,0.9,0.9V116.8z M351.7,86.5c0,0.5-0.4,0.9-0.9,0.9h-3.6c-0.5,0-0.9-0.4-0.9-0.9V66.8
|
||||
c0-0.5,0.4-0.9,0.9-0.9h3.6c0.5,0,0.9,0.4,0.9,0.9V86.5z M351.7,56.3c0,0.5-0.4,0.9-0.9,0.9h-3.6c-0.5,0-0.9-0.4-0.9-0.9V36.6
|
||||
c0-0.5,0.4-0.9,0.9-0.9h3.6c0.5,0,0.9,0.4,0.9,0.9V56.3z M363.4,147c0,0.5-0.4,0.9-0.9,0.9c0,0,0,0,0,0h-3.6
|
||||
c-0.5,0-0.9-0.4-0.9-0.9c0,0,0,0,0,0v-19.7c0-0.5,0.4-0.9,0.9-0.9h3.6c0.5,0,0.9,0.4,0.9,0.9V147z M363.4,116.8
|
||||
c0,0.5-0.4,0.9-0.9,0.9h-3.6c-0.5,0-0.9-0.4-0.9-0.9V97c0-0.5,0.4-0.9,0.9-0.9h3.6c0.5,0,0.9,0.4,0.9,0.9V116.8z M363.4,86.5
|
||||
c0,0.5-0.4,0.9-0.9,0.9h-3.6c-0.5,0-0.9-0.4-0.9-0.9V66.8c0-0.5,0.4-0.9,0.9-0.9h3.6c0.5,0,0.9,0.4,0.9,0.9V86.5z M363.4,56.3
|
||||
c0,0.5-0.4,0.9-0.9,0.9h-3.6c-0.5,0-0.9-0.4-0.9-0.9V36.6c0-0.5,0.4-0.9,0.9-0.9h3.6c0.5,0,0.9,0.4,0.9,0.9V56.3z M375.1,147
|
||||
c0,0.5-0.4,0.9-0.9,0.9c0,0,0,0,0,0h-3.6c-0.5,0-0.9-0.4-0.9-0.9c0,0,0,0,0,0v-19.7c0-0.5,0.4-0.9,0.9-0.9h3.6
|
||||
c0.5,0,0.9,0.4,1,0.9V147z M375.1,116.8c0,0.5-0.4,0.9-1,0.9h-3.6c-0.5,0-0.9-0.4-0.9-0.9V97c0-0.5,0.4-0.9,0.9-0.9h3.6
|
||||
c0.5,0,0.9,0.4,1,0.9V116.8z M375.1,86.5c0,0.5-0.4,0.9-1,0.9h-3.6c-0.5,0-0.9-0.4-0.9-0.9V66.8c0-0.5,0.4-0.9,0.9-0.9h3.6
|
||||
c0.5,0,0.9,0.4,1,0.9V86.5z M375.1,56.3c0,0.5-0.4,0.9-1,0.9h-3.6c-0.5,0-0.9-0.4-0.9-0.9V36.6c0-0.5,0.4-0.9,0.9-0.9h3.6
|
||||
c0.5,0,0.9,0.4,1,0.9V56.3z"/>
|
||||
|
||||
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="201.46" y1="208.3924" x2="201.46" y2="59.9976" gradientTransform="matrix(1 0 0 -1 0 264)">
|
||||
<stop offset="0" style="stop-color:#81CFFF"/>
|
||||
<stop offset="1" style="stop-color:#5ECFFF;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<path class="st3" d="M231.1,55.6h-59.3c-1.5-0.1-2.7,1.1-2.8,2.6v143.2c0.1,1.5,1.3,2.6,2.8,2.6h59.3c1.5,0.1,2.8-1.1,2.8-2.6
|
||||
V58.2C233.9,56.7,232.6,55.5,231.1,55.6z M182.5,159.4c0,0.6-0.6,1.1-1.2,1.1h-5.4c-0.6,0-1.2-0.5-1.2-1.1v-5.2
|
||||
c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h5.4c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0V159.4z M182.5,146.5c0,0.6-0.6,1.1-1.2,1.1
|
||||
c0,0,0,0,0,0h-5.4c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.2c0-0.6,0.6-1.1,1.2-1.1h5.4c0.6,0,1.2,0.5,1.2,1.1V146.5z
|
||||
M182.5,133.6c0,0.6-0.6,1.1-1.2,1.1h-5.4c-0.6,0-1.2-0.5-1.2-1.1v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h5.4
|
||||
c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0V133.6z M182.5,120.7c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0h-5.4c-0.6,0-1.2-0.5-1.2-1.1
|
||||
c0,0,0,0,0,0v-5.2c0-0.6,0.6-1.1,1.2-1.1h5.4c0.6,0,1.2,0.5,1.2,1.1V120.7z M182.5,107.8c0,0.6-0.6,1.1-1.2,1.1h-5.4
|
||||
c-0.6,0-1.2-0.5-1.2-1.1v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h5.4c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0V107.8z M182.5,94.9
|
||||
c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0h-5.4c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.2c0-0.6,0.6-1.1,1.2-1.1h5.4
|
||||
c0.6,0,1.2,0.5,1.2,1.1V94.9z M182.5,82.1c0,0.6-0.6,1.1-1.2,1.1h-5.4c-0.6,0-1.2-0.5-1.2-1.1v-5.2c0-0.6,0.6-1.1,1.2-1.1
|
||||
c0,0,0,0,0,0h5.4c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0V82.1z M182.5,69.2c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0h-5.4
|
||||
c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0V64c0-0.6,0.6-1.1,1.2-1.1h5.4c0.6,0,1.2,0.5,1.2,1.1V69.2z M192.6,159.4
|
||||
c0,0.6-0.6,1.1-1.2,1.1H186c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.2c0-0.6,0.6-1.1,1.2-1.1h5.4c0.6,0,1.2,0.5,1.2,1.1
|
||||
c0,0,0,0,0,0L192.6,159.4z M192.6,146.5c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0H186c-0.6,0-1.2-0.5-1.2-1.1v-5.2
|
||||
c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h5.4c0.6,0,1.2,0.5,1.2,1.1L192.6,146.5z M192.6,133.6c0,0.6-0.6,1.1-1.2,1.1H186
|
||||
c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.2c0-0.6,0.6-1.1,1.2-1.1h5.4c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0L192.6,133.6z
|
||||
M192.6,120.7c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0H186c-0.6,0-1.2-0.5-1.2-1.1v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h5.4
|
||||
c0.6,0,1.2,0.5,1.2,1.1L192.6,120.7z M192.6,107.8c0,0.6-0.6,1.1-1.2,1.1H186c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.2
|
||||
c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h5.4c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0L192.6,107.8z M192.6,94.9c0,0.6-0.6,1.1-1.2,1.1
|
||||
c0,0,0,0,0,0H186c-0.6,0-1.2-0.5-1.2-1.1v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h5.4c0.6,0,1.2,0.5,1.2,1.1L192.6,94.9z
|
||||
M192.6,82.1c0,0.6-0.6,1.1-1.2,1.1H186c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h5.4
|
||||
c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0L192.6,82.1z M192.6,69.2c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0H186c-0.6,0-1.2-0.5-1.2-1.1V64
|
||||
c0-0.6,0.5-1.2,1.2-1.2c0,0,0,0,0,0h5.4c0.6,0,1.2,0.5,1.2,1.1L192.6,69.2z M202.6,159.4c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0H196
|
||||
c-0.6,0-1.2-0.5-1.2-1.1v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h5.4c0.6,0,1.2,0.5,1.2,1.1L202.6,159.4z M202.6,146.5
|
||||
c0,0.6-0.6,1.1-1.2,1.1H196c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.2c0-0.6,0.6-1.1,1.2-1.1h5.4c0.6,0,1.2,0.5,1.2,1.1
|
||||
c0,0,0,0,0,0L202.6,146.5z M202.6,133.6c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0H196c-0.6,0-1.2-0.5-1.2-1.1v-5.2
|
||||
c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h5.4c0.6,0,1.2,0.5,1.2,1.1L202.6,133.6z M202.6,120.7c0,0.6-0.6,1.1-1.2,1.1H196
|
||||
c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.2c0-0.6,0.6-1.1,1.2-1.1h5.4c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0L202.6,120.7z
|
||||
M202.6,107.8c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0H196c-0.6,0-1.2-0.5-1.2-1.1v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h5.4
|
||||
c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0L202.6,107.8z M202.6,94.9c0,0.6-0.6,1.1-1.2,1.1H196c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0
|
||||
v-5.2c0-0.6,0.6-1.1,1.2-1.1h5.4c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0L202.6,94.9z M202.6,82.1c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0
|
||||
H196c-0.6,0-1.2-0.5-1.2-1.1v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h5.4c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0L202.6,82.1z
|
||||
M202.6,69.2c0,0.6-0.6,1.1-1.2,1.1H196c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0V64c0-0.6,0.6-1.1,1.2-1.1h5.4c0.6,0,1.2,0.4,1.2,1.1
|
||||
c0,0,0,0,0,0V69.2z M227.8,159.4c0,0.6-0.6,1.1-1.2,1.1h-20.5c-0.6,0-1.2-0.5-1.2-1.1v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0
|
||||
h20.5c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0L227.8,159.4z M227.8,146.5c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0h-20.5
|
||||
c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.2c0-0.6,0.6-1.1,1.2-1.1h20.5c0.6,0,1.2,0.5,1.2,1.1L227.8,146.5z M227.8,133.6
|
||||
c0,0.6-0.6,1.1-1.2,1.1h-20.5c-0.6,0-1.2-0.5-1.2-1.1v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h20.5c0.6,0,1.2,0.5,1.2,1.1
|
||||
c0,0,0,0,0,0L227.8,133.6z M227.8,120.7c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0h-20.5c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.2
|
||||
c0-0.6,0.6-1.1,1.2-1.1h20.5c0.6,0,1.2,0.5,1.2,1.1L227.8,120.7z M227.8,107.8c0,0.6-0.6,1.1-1.2,1.1h-20.5
|
||||
c-0.6,0-1.2-0.5-1.2-1.1v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h20.5c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0L227.8,107.8z
|
||||
M227.8,94.9c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0h-20.5c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.2c0-0.6,0.6-1.1,1.2-1.1h20.5
|
||||
c0.6,0,1.2,0.5,1.2,1.1L227.8,94.9z M227.8,82.1c0,0.6-0.6,1.1-1.2,1.1h-20.5c-0.6,0-1.2-0.5-1.2-1.1v-5.2c0-0.6,0.6-1.1,1.2-1.1
|
||||
c0,0,0,0,0,0h20.5c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0L227.8,82.1z M227.8,69.2c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0h-20.5
|
||||
c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0V64c0-0.6,0.6-1.1,1.2-1.1h20.5c0.6,0,1.2,0.5,1.2,1.1L227.8,69.2z"/>
|
||||
|
||||
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="122.975" y1="237.3228" x2="122.975" y2="59.9971" gradientTransform="matrix(1 0 0 -1 0 264)">
|
||||
<stop offset="0" style="stop-color:#81CFFF"/>
|
||||
<stop offset="1" style="stop-color:#5ECFFF;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<path class="st4" d="M161.1,26.7H84.8c-1.5-0.1-2.8,1.1-2.8,2.6c0,0,0,0,0,0v172.2c0.1,1.5,1.3,2.6,2.8,2.6h76.3
|
||||
c1.5,0.1,2.8-1.1,2.8-2.6V29.3C163.9,27.8,162.6,26.6,161.1,26.7z M154.3,161c0,0.6-0.6,1.1-1.2,1.1H92.8c-0.6,0-1.2-0.5-1.2-1.1
|
||||
c0,0,0,0,0,0v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h60.3c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0V161z M154.3,146.3
|
||||
c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0H92.8c-0.6,0-1.2-0.5-1.2-1.1v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h60.3
|
||||
c0.6,0,1.2,0.5,1.2,1.1V146.3z M154.3,131.6c0,0.6-0.6,1.1-1.2,1.1H92.8c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.2
|
||||
c0-0.6,0.6-1.1,1.2-1.1h60.3c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0V131.6z M154.3,117c0,0.6-0.6,1.1-1.2,1.1H92.8
|
||||
c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.2c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h60.3c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0V117z
|
||||
M154.3,102.3c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0H92.8c-0.6,0-1.2-0.5-1.2-1.1V97c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h60.3
|
||||
c0.6,0,1.2,0.5,1.2,1.1V102.3z M154.3,87.6c0,0.6-0.6,1.1-1.2,1.1H92.8c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.3
|
||||
c0-0.6,0.6-1.1,1.2-1.1h60.3c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0V87.6z M154.3,72.9c0,0.6-0.6,1.1-1.2,1.1H92.8
|
||||
c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.3c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h60.3c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0V72.9z
|
||||
M154.3,58.3c0,0.6-0.6,1.1-1.2,1.1c0,0,0,0,0,0H92.8c-0.6,0-1.2-0.5-1.2-1.1V53c0-0.6,0.6-1.1,1.2-1.1c0,0,0,0,0,0h60.3
|
||||
c0.6,0,1.2,0.5,1.2,1.1V58.3z M154.3,43.6c0,0.6-0.6,1.1-1.2,1.1H92.8c-0.6,0-1.2-0.5-1.2-1.1c0,0,0,0,0,0v-5.3
|
||||
c0-0.6,0.6-1.1,1.2-1.1h60.3c0.6,0,1.2,0.5,1.2,1.1c0,0,0,0,0,0V43.6z"/>
|
||||
|
||||
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="273.51" y1="264" x2="273.51" y2="54.46" gradientTransform="matrix(1 0 0 -1 0 264)">
|
||||
<stop offset="0" style="stop-color:#81CFFF"/>
|
||||
<stop offset="1" style="stop-color:#5ECFFF;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<path class="st5" d="M306.2,0h-65.4c-1.4,0-2.5,1.2-2.4,2.6v204.4c-0.1,1.4,1,2.5,2.4,2.6c0,0,0,0,0,0h65.4
|
||||
c1.4-0.1,2.5-1.2,2.4-2.6V2.6C308.7,1.2,307.6,0.1,306.2,0z M300.4,119.6c0,0.6-0.4,1.1-1,1.1h-51.7c-0.6,0-1-0.5-1-1.1v-5.2
|
||||
c0-0.6,0.4-1.1,1-1.1h51.7c0.6,0,1,0.5,1,1.1L300.4,119.6z M300.4,90.3c0,0.6-0.4,1.1-1,1.1h-51.7c-0.6,0-1-0.5-1-1.1V85
|
||||
c0-0.6,0.4-1.1,1-1.1h51.7c0.6,0,1,0.5,1,1.1L300.4,90.3z M300.4,60.9c0,0.6-0.4,1.1-1,1.1h-51.7c-0.6,0-1-0.5-1-1.1v-5.2
|
||||
c0-0.6,0.4-1.1,1-1.1h51.7c0.6,0,1,0.5,1,1.1L300.4,60.9z M300.4,31.5c0,0.6-0.4,1.1-1,1.1h-51.7c-0.6,0-1-0.5-1-1.1v-5.2
|
||||
c0-0.6,0.4-1.1,1-1.1h51.7c0.6,0,1,0.5,1,1.1L300.4,31.5z M300.4,16.9c0,0.6-0.4,1.1-1,1.1h-51.7c-0.6,0-1-0.5-1-1.1v-5.2
|
||||
c0-0.6,0.4-1.1,1-1.1h51.7c0.6,0,1,0.5,1,1.1L300.4,16.9z"/>
|
||||
</g>
|
||||
<g class="st6">
|
||||
<path class="st7" d="M244.2,130.7c3.3,1.9,5.7,13.6,1,20.7c-5.3,6.8-7,9-6.1,14c-4.3-7.3-0.6-7.4-5.8-14.2
|
||||
c-4.6-6.2-2.5-17.4,0.7-20.5C237.4,131.3,240.8,131.3,244.2,130.7L244.2,130.7z"/>
|
||||
<path class="st8" d="M280.4,211.9c-0.1,0.6-0.1,1.2-0.1,1.7c0,0.7,0.1,1.3,0.2,2c-2.1-0.8-4.3-1.2-6.5-1.2
|
||||
c-2.6,0-5.2,0.6-7.5,1.7c-0.8-4.2-4.8-7-9-6.2c-2.8,0.5-5,2.5-5.9,5.2c-3.4-2.1-7.7-2-11.1,0.1c-0.4-5.7-4.1-0.8-9.8-0.8
|
||||
c-6,0-11.8-4.4-11.8,1.7c0,1.1,0.2,2.2,0.4,3.2c-1.1,0.1-2.1,0.5-3,1c-0.9-7-6.8-12.4-13.9-12.7c22.6-10.3,22.4-44.6,24.8-74.6
|
||||
c0.1-1.7,1.2-4.1,1.8-4.4l0,0c1.5,1.1,3.2,1.8,5.1,2.1c-3.2,3.1-5.4,14.3-0.7,20.5c5.3,6.8,1.6,6.9,5.8,14.2
|
||||
c-0.9-5,0.8-7.2,6.1-14c4.8-7.2,2.3-18.8-1-20.7c1.8-0.3,3.6-1,5.1-2.1l0,0c0.6,0.3,1.7,2.7,1.8,4.4
|
||||
C253.6,164.6,250.4,198.5,280.4,211.9z"/>
|
||||
<path class="st9" d="M303.3,203.2c-5.4,0-9.8,4.4-9.8,9.8c0,0.3,0,0.6,0,0.9c-1.5-1.7-3.7-2.6-6-2.5c-0.7,0-1.4,0.1-2.1,0.3
|
||||
c0.7-1.3,1.1-2.8,1.1-4.3c-0.1-4.6-3.9-8.3-8.5-8.2c-4,0.1-7.4,3-8.1,6.9c-0.1,0.4-0.1,0.9-0.1,1.3c0,0.5,0,1,0.1,1.6
|
||||
c-3.5-1.4-7.4-1.3-10.8,0.4c-0.7-3.2-3.9-5.3-7.2-4.6c-2,0.4-3.6,1.9-4.3,3.8c-1.3-0.8-2.7-1.2-4.2-1.2c-1.5,0-3.1,0.4-4.4,1.3
|
||||
c-0.2-4.6-4.1-8.2-8.7-8s-8.2,4.1-8,8.7l0,0c0,0.8,0.1,1.7,0.3,2.5c-0.8,0.1-1.6,0.4-2.3,0.8c-0.7-5.4-5.2-9.6-10.7-9.8h-0.4
|
||||
c-3.4,0-6.7,1.6-8.8,4.3c-3-6.2-10.4-8.9-16.7-5.9c-2.9,1.4-5.2,3.9-6.3,7c4.1,3,6.6,7.8,6.6,12.9c0,2.3-0.5,4.6-1.5,6.6
|
||||
c2-2.2,4.8-3.4,7.8-3.4c0.9,0,1.8,0.1,2.7,0.3c-2.9-5-1.2-11.5,3.8-14.4c1.2-0.7,2.6-1.2,3.9-1.3c0.5-0.1,0.9-0.1,1.4-0.1
|
||||
c5.8,0,10.6,4.7,10.6,10.6l0,0c0,0.6-0.1,1.3-0.2,1.9c4.4-1.7,9.3-1.6,13.6,0.4c0.9-4.1,4.9-6.7,9-5.8c2.6,0.6,4.7,2.4,5.5,4.9
|
||||
c1.6-0.9,3.5-1.4,5.3-1.4c1.9,0,3.8,0.5,5.4,1.5l0.1,0.1c0.3-4.5,3.6-8.4,8-9.4c0.8-0.2,1.7-0.3,2.5-0.3
|
||||
c5.8,0,10.6,4.7,10.6,10.6c0,1-0.2,2-0.4,3c1.1,0.1,2.1,0.5,3,1c1-7,7-12.1,14-12.1c1.5,0,3,0.2,4.4,0.7c2.6,0.8,5,2.5,6.7,4.6
|
||||
c2.4-4.8,7-8.2,12.4-8.8C311.4,205.9,307.6,203.2,303.3,203.2z"/>
|
||||
<path class="st10" d="M314.4,209.9c-0.6,0-1.2,0-1.8,0.1c-5.4,0.6-10.1,3.9-12.5,8.7c-1.7-2.2-4-3.8-6.7-4.6
|
||||
c-1.4-0.5-2.9-0.7-4.4-0.7c-7,0-13,5.2-14,12.1c-0.9-0.5-1.9-0.9-3-1c0.3-1,0.4-2,0.4-3c0-5.8-4.7-10.5-10.5-10.5
|
||||
c-0.8,0-1.7,0.1-2.5,0.3c-4.4,1.1-7.7,4.9-8,9.4l-0.1-0.1c-1.6-1-3.5-1.5-5.4-1.5c-1.9,0-3.7,0.5-5.3,1.4c-1.4-3.9-5.7-6-9.6-4.6
|
||||
c-2.5,0.9-4.3,3-4.9,5.5c-4.3-2-9.2-2.1-13.6-0.4c0.1-0.6,0.2-1.3,0.2-1.9c0-5.8-4.7-10.6-10.6-10.6l0,0c-0.5,0-0.9,0-1.4,0.1
|
||||
c-5.8,0.8-9.9,6.1-9.1,11.8c0.2,1.4,0.6,2.7,1.3,3.9c-0.9-0.2-1.8-0.3-2.7-0.3c-2.9,0-5.8,1.2-7.8,3.4c1-2.1,1.5-4.3,1.5-6.6
|
||||
c0-5.1-2.4-9.9-6.6-12.9l0,0c-7.1-5.2-17-3.6-22.2,3.5c-5.2,7.1-3.6,17,3.5,22.2c6.8,5,16.4,3.7,21.7-2.8
|
||||
c-2.1,5.5,0.7,11.6,6.1,13.6c5.5,2.1,11.6-0.7,13.6-6.1c0.5-1.2,0.7-2.5,0.7-3.7c0-1.9,0.4-0.1,0.4,2.7c0,9.7,7.8,17.6,17.5,17.6
|
||||
c9.7,0,17.6-7.8,17.6-17.5c0-2.4-0.5-4.8-1.4-7l0.5-0.1c0.5,5.8,5.7,10.1,11.5,9.5c5-0.5,9-4.4,9.5-9.4c1.7,1,3.6,1.6,5.5,1.6
|
||||
c0.6,0,1.2,0,1.7-0.1v0.1c0,4.2,3.4,7.6,7.6,7.5c2.6,0,5-1.4,6.4-3.6c4.7,6.3,13.5,7.5,19.8,2.9c1.5-1.1,2.8-2.5,3.7-4.2
|
||||
c4.9,7.3,14.8,9.1,22.1,4.2s9.1-14.8,4.2-22.1C324.5,212.5,319.6,209.9,314.4,209.9L314.4,209.9z"/>
|
||||
</g>
|
||||
<path class="st11" d="M239.1,70c6.4,0,11.6,5.2,11.6,11.6c0,6.4-5.2,11.6-11.6,11.6c-6.4,0-11.6-5.2-11.6-11.6c0,0,0,0,0,0
|
||||
C227.5,75.2,232.7,70,239.1,70z"/>
|
||||
<path class="st8" d="M239.1,137.2c8.3,0,13.5-1.7,16.6-7.9c0,3.2-1.5,6.2-4.1,8.1c-1.9,1.3-4,2.2-6.2,2.6c-4.1,0.8-8.4,0.8-12.5,0
|
||||
c-2.2-0.4-4.3-1.3-6.2-2.6c-2.6-1.9-4.2-4.9-4.2-8.1C225.6,135.5,230.7,137.2,239.1,137.2z"/>
|
||||
<path class="st8" d="M288.4,151.7c0,0.5-0.3,0.8-0.8,0.8c-0.3,0-0.5-0.1-0.7-0.3c-7.6-10.3-25.5-25-30.4-24.7
|
||||
c2.4-6.1,3.4-15.9,3.6-31.2C271.5,100.3,288.3,122.4,288.4,151.7z"/>
|
||||
<path class="st8" d="M218.1,96.3c0.3,15.2,1.2,25,3.6,31.1l-0.2,0.1c-4.9-0.3-22.8,14.5-30.4,24.7c-0.3,0.4-0.8,0.5-1.1,0.2
|
||||
c-0.2-0.2-0.4-0.4-0.3-0.7C189.7,122.3,206.6,100.2,218.1,96.3L218.1,96.3z"/>
|
||||
<path class="st8" d="M250.7,81.6c0-6.4-5.2-11.6-11.6-11.6c-6.4,0-11.6,5.2-11.6,11.6s5.2,11.6,11.6,11.6l0,0
|
||||
C245.5,93.2,250.7,88,250.7,81.6z M252.9,81.6c0,7.6-6.2,13.8-13.8,13.8c-7.6,0-13.8-6.2-13.8-13.8c0-7.6,6.2-13.8,13.8-13.8
|
||||
c0,0,0,0,0,0C246.7,67.8,252.9,74,252.9,81.6z"/>
|
||||
<path class="st8" d="M239.1,48.7c5.7,0,10.7-2,13.8-4.9c0.5,1.3,1,2.6,1.4,4c-3.3,3.3-8.9,5.4-15.3,5.4s-11.9-2.1-15.3-5.4
|
||||
c0.5-1.3,1-2.7,1.4-4C228.4,46.8,233.4,48.7,239.1,48.7z"/>
|
||||
<path class="st9" d="M252.9,43.8c-3.1,3-8.1,4.9-13.8,4.9s-10.7-2-13.8-4.9c2-5.1,4.5-10,7.6-14.5c0.5-0.7,0.9-1.3,1.4-1.9
|
||||
c2-2.7,5.8-3.2,8.5-1.2c0.4,0.3,0.8,0.7,1.2,1.2c0.5,0.6,0.9,1.2,1.4,1.9C248.4,33.8,250.9,38.7,252.9,43.8z"/>
|
||||
<path class="st10" d="M260.1,96.4c-0.3,15.3-1.2,25-3.6,31.2c-0.2,0.6-0.5,1.2-0.8,1.7c-3.1,6.2-8.3,7.9-16.6,7.9
|
||||
s-13.5-1.7-16.6-7.9c-0.3-0.6-0.5-1.1-0.8-1.8c-2.4-6.2-3.4-15.9-3.6-31.1c-0.1-3.4-0.1-7.1-0.1-11.1c-0.1-12.7,1.8-25.4,5.8-37.5
|
||||
c3.3,3.3,8.9,5.4,15.3,5.4s11.9-2.1,15.3-5.4c4,12.1,6,24.8,5.8,37.5C260.2,89.2,260.1,92.9,260.1,96.4z M252.9,81.6
|
||||
c0-7.6-6.2-13.8-13.8-13.8c-7.6,0-13.8,6.2-13.8,13.8c0,7.6,6.2,13.8,13.8,13.8c0,0,0,0,0,0C246.7,95.4,252.9,89.2,252.9,81.6
|
||||
L252.9,81.6z"/>
|
||||
<path class="st12" d="M139.2,246.1l18.4,0.4v0.7l-19.4-0.4v-0.7V246C138.4,246.1,138.6,246.1,139.2,246.1z"/>
|
||||
|
||||
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="112.2357" y1="190.775" x2="112.2357" y2="101.005" gradientTransform="matrix(1 0 0 -1 0 264)">
|
||||
<stop offset="0" style="stop-color:#81CFFF"/>
|
||||
<stop offset="1" style="stop-color:#5ECFFF;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<line class="st13" x1="112.2" y1="73.2" x2="112.2" y2="163"/>
|
||||
|
||||
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="348.955" y1="195.605" x2="348.955" y2="105.835" gradientTransform="matrix(1 0 0 -1 0 264)">
|
||||
<stop offset="0" style="stop-color:#81CFFF"/>
|
||||
<stop offset="1" style="stop-color:#5ECFFF;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<line class="st14" x1="349" y1="68.4" x2="349" y2="158.2"/>
|
||||
|
||||
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="40.9" y1="120.12" x2="40.9" y2="64.49" gradientTransform="matrix(1 0 0 -1 0 264)">
|
||||
<stop offset="0" style="stop-color:#81CFFF"/>
|
||||
<stop offset="1" style="stop-color:#5ECFFF;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<line class="st15" x1="40.9" y1="143.9" x2="40.9" y2="199.5"/>
|
||||
|
||||
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="64.97" y1="168.64" x2="64.97" y2="140.83" gradientTransform="matrix(1 0 0 -1 0 264)">
|
||||
<stop offset="0" style="stop-color:#81CFFF"/>
|
||||
<stop offset="1" style="stop-color:#5ECFFF;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<line class="st16" x1="65" y1="95.4" x2="65" y2="123.2"/>
|
||||
|
||||
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="397.23" y1="159.8" x2="397.23" y2="131.98" gradientTransform="matrix(1 0 0 -1 0 264)">
|
||||
<stop offset="0" style="stop-color:#81CFFF"/>
|
||||
<stop offset="1" style="stop-color:#5ECFFF;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<line class="st17" x1="397.2" y1="104.2" x2="397.2" y2="132"/>
|
||||
|
||||
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="424.75" y1="130.51" x2="424.75" y2="74.87" gradientTransform="matrix(1 0 0 -1 0 264)">
|
||||
<stop offset="0" style="stop-color:#81CFFF"/>
|
||||
<stop offset="1" style="stop-color:#5ECFFF;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<line class="st18" x1="424.8" y1="133.5" x2="424.8" y2="189.1"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 20 KiB |
@ -1,29 +1,14 @@
|
||||
<template>
|
||||
<a-config-provider :locale="locale">
|
||||
<router-view></router-view>
|
||||
<router-view />
|
||||
</a-config-provider>
|
||||
</template>
|
||||
|
||||
<script setup name="App">
|
||||
import i18n from '@/locales'
|
||||
import store from '@/store'
|
||||
import config from '@/config'
|
||||
import { globalStore } from '@/store'
|
||||
|
||||
import configApi from '@/api/dev/configApi'
|
||||
import { message } from 'ant-design-vue'
|
||||
import tool from '@/utils/tool'
|
||||
|
||||
store.commit('initTheme')
|
||||
const store = globalStore()
|
||||
store.initTheme()
|
||||
const locale = i18n.global.messages[i18n.global.locale].lang
|
||||
|
||||
let formData = ref(config.SYS_BASE_CONFIG)
|
||||
configApi.configSysBaseList().then((data) => {
|
||||
if (data) {
|
||||
data.forEach((item) => {
|
||||
formData.value[item.configKey] = item.configValue
|
||||
})
|
||||
tool.data.set('SNOWY_SYS_BASE_CONFIG', formData.value)
|
||||
store.commit('SET_sysBaseConfig', formData.value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
@ -8,9 +8,9 @@
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
import { baseRequest } from '@/utils/request'
|
||||
import { moduleRequest } from '@/utils/request'
|
||||
|
||||
const request = (url, ...arg) => baseRequest(`/auth/b/${url}`, ...arg)
|
||||
const request = moduleRequest(`/auth/b/`)
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
|
@ -69,5 +69,17 @@ export default {
|
||||
// 给人员授权角色
|
||||
grantRole(data) {
|
||||
return request('grantRole', data)
|
||||
},
|
||||
// 人员导出
|
||||
userExport(data) {
|
||||
return request('export', data, 'get', {
|
||||
responseType: 'blob'
|
||||
})
|
||||
},
|
||||
// 导出人员个人信息
|
||||
userExportUserInfo(data) {
|
||||
return request('exportUserInfo', data, 'get', {
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,10 @@ export default {
|
||||
jobRunJob(data) {
|
||||
return request('runJob', data)
|
||||
},
|
||||
// 运行定时任务
|
||||
jobRunJobNow(data) {
|
||||
return request('runJobNow', data)
|
||||
},
|
||||
// 获取定时任务类
|
||||
jobGetActionClass(data) {
|
||||
return request('getActionClass', data, 'get')
|
||||
|
45
snowy-admin-web/src/api/gen/genBasicApi.js
Normal file
45
snowy-admin-web/src/api/gen/genBasicApi.js
Normal file
@ -0,0 +1,45 @@
|
||||
import { baseRequest } from '@/utils/request'
|
||||
|
||||
const request = (url, ...arg) => baseRequest(`/gen/basic/${url}`, ...arg)
|
||||
|
||||
export default {
|
||||
// 获取代码生成基础分页
|
||||
basicPage(data) {
|
||||
return request('page', data, 'get')
|
||||
},
|
||||
// 提交表单 edit为true时为编辑,默认为新增
|
||||
submitForm(data, edit = false) {
|
||||
return request(edit ? 'add' : 'edit', data)
|
||||
},
|
||||
// 删除代码生成基础
|
||||
basicDelete(data) {
|
||||
return request('delete', data)
|
||||
},
|
||||
// 获取代码生成基础详情
|
||||
basicDetail(data) {
|
||||
return request('detail', data, 'get')
|
||||
},
|
||||
// 获取所有表信息
|
||||
basicTables(data) {
|
||||
return request('tables', data, 'get')
|
||||
},
|
||||
// 获取表内所有字段信息
|
||||
basicTableColumns(data) {
|
||||
return request('tableColumns', data, 'get')
|
||||
},
|
||||
// 执行代码生成 压缩包
|
||||
basicExecGenBiz(data) {
|
||||
const options = {
|
||||
responseType: 'blob'
|
||||
}
|
||||
return request('execGenZip', data, 'get', options)
|
||||
},
|
||||
// 执行代码生成 项目内
|
||||
basicExecGenPro(data) {
|
||||
return request('execGenPro', data)
|
||||
},
|
||||
// 预览代码生成
|
||||
basicPreviewGen(data) {
|
||||
return request('previewGen', data, 'get')
|
||||
}
|
||||
}
|
26
snowy-admin-web/src/api/gen/genConfigApi.js
Normal file
26
snowy-admin-web/src/api/gen/genConfigApi.js
Normal file
@ -0,0 +1,26 @@
|
||||
import { baseRequest } from '@/utils/request'
|
||||
|
||||
const request = (url, ...arg) => baseRequest(`/gen/config/${url}`, ...arg)
|
||||
|
||||
export default {
|
||||
// 获取代码生成详情配置列表
|
||||
configList(data) {
|
||||
return request('list', data, 'get')
|
||||
},
|
||||
// 提交表单 edit为true时为编辑,默认为新增
|
||||
submitForm(data, edit = false) {
|
||||
return request(edit ? 'add' : 'edit', data)
|
||||
},
|
||||
// 删除代码生成详情配置
|
||||
configDelete(data) {
|
||||
return request('delete', data)
|
||||
},
|
||||
// 获取代码生成详情配置详情
|
||||
configDetail(data) {
|
||||
return request('detail', data, 'get')
|
||||
},
|
||||
// 批量编辑代码生成详细配置
|
||||
configEditBatch(data) {
|
||||
return request('editBatch', data)
|
||||
}
|
||||
}
|
37
snowy-admin-web/src/api/mobile/resource/buttonApi.js
Normal file
37
snowy-admin-web/src/api/mobile/resource/buttonApi.js
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
import { baseRequest } from '@/utils/request'
|
||||
|
||||
const request = (url, ...arg) => baseRequest(`/mobile/button/${url}`, ...arg)
|
||||
/**
|
||||
* 按钮
|
||||
*
|
||||
* @author yubaoshan
|
||||
* @date 2022-09-22 22:33:20
|
||||
*/
|
||||
export default {
|
||||
// 获取按钮分页
|
||||
mobileButtonPage(data) {
|
||||
return request('page', data, 'get')
|
||||
},
|
||||
// 提交表单 edit为true时为编辑,默认为新增
|
||||
mobileButtonSubmitForm(data, edit = false) {
|
||||
return request(edit ? 'add' : 'edit', data)
|
||||
},
|
||||
// 删除按钮
|
||||
mobileButtonDelete(data) {
|
||||
return request('delete', data)
|
||||
},
|
||||
// 获取按钮详情
|
||||
mobileButtonDetail(data) {
|
||||
return request('detail', data, 'get')
|
||||
}
|
||||
}
|
44
snowy-admin-web/src/api/mobile/resource/menuApi.js
Normal file
44
snowy-admin-web/src/api/mobile/resource/menuApi.js
Normal file
@ -0,0 +1,44 @@
|
||||
import { baseRequest } from '@/utils/request'
|
||||
|
||||
const request = (url, ...arg) => baseRequest(`/mobile/menu/` + url, ...arg)
|
||||
|
||||
/**
|
||||
* 移动端菜单Api接口管理器
|
||||
*
|
||||
* @author yubaoshan
|
||||
* @date 2023/01/28 22:42
|
||||
**/
|
||||
export default {
|
||||
// 获取移动端菜单tree
|
||||
mobileMenuTree(data) {
|
||||
return request('tree', data, 'get')
|
||||
},
|
||||
// 获取移动端菜单列表
|
||||
mobileMenuList(data) {
|
||||
return request('list', data, 'get')
|
||||
},
|
||||
// 提交移动端菜单表单 edit为true时为编辑,默认为新增
|
||||
mobileMenuSubmitForm(data, edit = false) {
|
||||
return request(edit ? 'add' : 'edit', data)
|
||||
},
|
||||
// 更改菜单所属模块
|
||||
mobileMenuChangeModule(data) {
|
||||
return request('changeModule', data)
|
||||
},
|
||||
// 删除移动端菜单
|
||||
mobileMenuDelete(data) {
|
||||
return request('delete', data)
|
||||
},
|
||||
// 获取移动端菜单详情
|
||||
mobileMenuDetail(data) {
|
||||
return request('detail', data, 'get')
|
||||
},
|
||||
// 获取模块选择器
|
||||
mobileMenuModuleSelector(data) {
|
||||
return request('moduleSelector', data, 'get')
|
||||
},
|
||||
// 获取菜单树选择器
|
||||
mobileMenuTreeSelector(data) {
|
||||
return request('menuTreeSelector', data, 'get')
|
||||
}
|
||||
}
|
37
snowy-admin-web/src/api/mobile/resource/moduleApi.js
Normal file
37
snowy-admin-web/src/api/mobile/resource/moduleApi.js
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
import { baseRequest } from '@/utils/request'
|
||||
|
||||
const request = (url, ...arg) => baseRequest(`/mobile/module/${url}`, ...arg)
|
||||
/**
|
||||
* 类别
|
||||
*
|
||||
* @author yubaoshan
|
||||
* @date 2022-09-22 22:33:20
|
||||
*/
|
||||
export default {
|
||||
// 获取类别分页
|
||||
modulePage(data) {
|
||||
return request('page', data, 'get')
|
||||
},
|
||||
// 提交表单 edit为true时为编辑,默认为新增
|
||||
submitForm(data, edit = false) {
|
||||
return request(edit ? 'add' : 'edit', data)
|
||||
},
|
||||
// 删除类别
|
||||
moduleDelete(data) {
|
||||
return request('delete', data)
|
||||
},
|
||||
// 获取类别详情
|
||||
moduleDetail(data) {
|
||||
return request('detail', data, 'get')
|
||||
}
|
||||
}
|
@ -46,6 +46,14 @@ export default {
|
||||
roleGrantResource(data) {
|
||||
return request('grantResource', data)
|
||||
},
|
||||
// 获取角色拥有移动端菜单
|
||||
roleOwnMobileMenu(data) {
|
||||
return request('ownMobileMenu', data, 'get')
|
||||
},
|
||||
// 给角色授权移动端菜单
|
||||
roleGrantMobileMenu(data) {
|
||||
return request('grantMobileMenu', data)
|
||||
},
|
||||
// 获取角色拥有权限
|
||||
roleOwnPermission(data) {
|
||||
return request('ownPermission', data, 'get')
|
||||
@ -70,6 +78,10 @@ export default {
|
||||
roleResourceTreeSelector(data) {
|
||||
return request('resourceTreeSelector', data, 'get')
|
||||
},
|
||||
// 获取移动端菜单授权树
|
||||
roleMobileMenuTreeSelector(data) {
|
||||
return request('mobileMenuTreeSelector', data, 'get')
|
||||
},
|
||||
// 获取权限授权树
|
||||
rolePermissionTreeSelector(data) {
|
||||
return request('permissionTreeSelector', data, 'get')
|
||||
|
@ -69,5 +69,43 @@ export default {
|
||||
// 给用户授权角色
|
||||
grantRole(data) {
|
||||
return request('grantRole', data)
|
||||
},
|
||||
// 获取用户拥有资源
|
||||
userOwnResource(data) {
|
||||
return request('ownResource', data, 'get')
|
||||
},
|
||||
// 给用户授权资源
|
||||
userGrantResource(data) {
|
||||
return request('grantResource', data)
|
||||
},
|
||||
// 获取用户拥有权限
|
||||
userOwnPermission(data) {
|
||||
return request('ownPermission', data, 'get')
|
||||
},
|
||||
// 给用户授权权限
|
||||
userGrantPermission(data) {
|
||||
return request('grantPermission', data)
|
||||
},
|
||||
// 下载用户导入模板
|
||||
userDownloadImportUserTemplate(data) {
|
||||
return request('downloadImportUserTemplate', data, 'get', {
|
||||
responseType: 'blob'
|
||||
})
|
||||
},
|
||||
// 用户导入
|
||||
userImport(data) {
|
||||
return request('import', data)
|
||||
},
|
||||
// 用户导出
|
||||
userExport(data) {
|
||||
return request('export', data, 'get', {
|
||||
responseType: 'blob'
|
||||
})
|
||||
},
|
||||
// 导出用户个人信息
|
||||
userExportUserInfo(data) {
|
||||
return request('exportUserInfo', data, 'get', {
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
173
snowy-admin-web/src/assets/icons/mobile/filled/iconfont.css
Normal file
173
snowy-admin-web/src/assets/icons/mobile/filled/iconfont.css
Normal file
@ -0,0 +1,173 @@
|
||||
@font-face {
|
||||
font-family: "snowy"; /* Project id 3880534 */
|
||||
src: url('iconfont.ttf?t=1675528061732') format('truetype');
|
||||
}
|
||||
|
||||
.snowy {
|
||||
font-family: "snowy" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.arrow-up-filling:before {
|
||||
content: "\e688";
|
||||
}
|
||||
|
||||
.arrow-down-filling:before {
|
||||
content: "\e689";
|
||||
}
|
||||
|
||||
.arrow-left-filling:before {
|
||||
content: "\e68a";
|
||||
}
|
||||
|
||||
.arrow-right-filling:before {
|
||||
content: "\e68b";
|
||||
}
|
||||
|
||||
.caps-unlock-filling:before {
|
||||
content: "\e68c";
|
||||
}
|
||||
|
||||
.comment-filling:before {
|
||||
content: "\e68d";
|
||||
}
|
||||
|
||||
.check-item-filling:before {
|
||||
content: "\e68e";
|
||||
}
|
||||
|
||||
.clock-filling:before {
|
||||
content: "\e68f";
|
||||
}
|
||||
|
||||
.delete-filling:before {
|
||||
content: "\e690";
|
||||
}
|
||||
|
||||
.decline-filling:before {
|
||||
content: "\e691";
|
||||
}
|
||||
|
||||
.dynamic-filling:before {
|
||||
content: "\e692";
|
||||
}
|
||||
|
||||
.intermediate-filling:before {
|
||||
content: "\e693";
|
||||
}
|
||||
|
||||
.favorite-filling:before {
|
||||
content: "\e694";
|
||||
}
|
||||
|
||||
.layout-filling:before {
|
||||
content: "\e695";
|
||||
}
|
||||
|
||||
.help-filling:before {
|
||||
content: "\e696";
|
||||
}
|
||||
|
||||
.history-filling:before {
|
||||
content: "\e697";
|
||||
}
|
||||
|
||||
.filter-filling:before {
|
||||
content: "\e698";
|
||||
}
|
||||
|
||||
.file-common-filling:before {
|
||||
content: "\e699";
|
||||
}
|
||||
|
||||
.news-filling:before {
|
||||
content: "\e69a";
|
||||
}
|
||||
|
||||
.edit-filling:before {
|
||||
content: "\e69b";
|
||||
}
|
||||
|
||||
.fullscreen-expand-filling:before {
|
||||
content: "\e69c";
|
||||
}
|
||||
|
||||
.smile-filling:before {
|
||||
content: "\e69d";
|
||||
}
|
||||
|
||||
.rise-filling:before {
|
||||
content: "\e69e";
|
||||
}
|
||||
|
||||
.picture-filling:before {
|
||||
content: "\e69f";
|
||||
}
|
||||
|
||||
.notification-filling:before {
|
||||
content: "\e6a0";
|
||||
}
|
||||
|
||||
.user-filling:before {
|
||||
content: "\e6a1";
|
||||
}
|
||||
|
||||
.setting-filling:before {
|
||||
content: "\e6a2";
|
||||
}
|
||||
|
||||
.switch-filling:before {
|
||||
content: "\e6a3";
|
||||
}
|
||||
|
||||
.work-filling:before {
|
||||
content: "\e6a4";
|
||||
}
|
||||
|
||||
.task-filling:before {
|
||||
content: "\e6a5";
|
||||
}
|
||||
|
||||
.success-filling:before {
|
||||
content: "\e6a6";
|
||||
}
|
||||
|
||||
.warning-filling:before {
|
||||
content: "\e6a7";
|
||||
}
|
||||
|
||||
.folder-filling:before {
|
||||
content: "\e6a8";
|
||||
}
|
||||
|
||||
.map-filling:before {
|
||||
content: "\e6a9";
|
||||
}
|
||||
|
||||
.prompt-filling:before {
|
||||
content: "\e6aa";
|
||||
}
|
||||
|
||||
.meh-filling:before {
|
||||
content: "\e6ab";
|
||||
}
|
||||
|
||||
.cry-filling:before {
|
||||
content: "\e6ac";
|
||||
}
|
||||
|
||||
.top-filling:before {
|
||||
content: "\e6ad";
|
||||
}
|
||||
|
||||
.home-filling:before {
|
||||
content: "\e6ae";
|
||||
}
|
||||
|
||||
.sorting:before {
|
||||
content: "\e6af";
|
||||
}
|
||||
|
289
snowy-admin-web/src/assets/icons/mobile/filled/iconfont.json
Normal file
289
snowy-admin-web/src/assets/icons/mobile/filled/iconfont.json
Normal file
@ -0,0 +1,289 @@
|
||||
{
|
||||
"id": "3880534",
|
||||
"name": "snowy-app-filled",
|
||||
"font_family": "snowy",
|
||||
"css_prefix_text": "",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "15838581",
|
||||
"name": "arrow-up-filling",
|
||||
"font_class": "arrow-up-filling",
|
||||
"unicode": "e688",
|
||||
"unicode_decimal": 59016
|
||||
},
|
||||
{
|
||||
"icon_id": "15838582",
|
||||
"name": "arrow-down-filling",
|
||||
"font_class": "arrow-down-filling",
|
||||
"unicode": "e689",
|
||||
"unicode_decimal": 59017
|
||||
},
|
||||
{
|
||||
"icon_id": "15838583",
|
||||
"name": "arrow-left-filling",
|
||||
"font_class": "arrow-left-filling",
|
||||
"unicode": "e68a",
|
||||
"unicode_decimal": 59018
|
||||
},
|
||||
{
|
||||
"icon_id": "15838584",
|
||||
"name": "arrow-right-filling",
|
||||
"font_class": "arrow-right-filling",
|
||||
"unicode": "e68b",
|
||||
"unicode_decimal": 59019
|
||||
},
|
||||
{
|
||||
"icon_id": "15838585",
|
||||
"name": "caps-unlock-filling",
|
||||
"font_class": "caps-unlock-filling",
|
||||
"unicode": "e68c",
|
||||
"unicode_decimal": 59020
|
||||
},
|
||||
{
|
||||
"icon_id": "15838586",
|
||||
"name": "comment-filling",
|
||||
"font_class": "comment-filling",
|
||||
"unicode": "e68d",
|
||||
"unicode_decimal": 59021
|
||||
},
|
||||
{
|
||||
"icon_id": "15838587",
|
||||
"name": "check-item-filling",
|
||||
"font_class": "check-item-filling",
|
||||
"unicode": "e68e",
|
||||
"unicode_decimal": 59022
|
||||
},
|
||||
{
|
||||
"icon_id": "15838588",
|
||||
"name": "clock-filling",
|
||||
"font_class": "clock-filling",
|
||||
"unicode": "e68f",
|
||||
"unicode_decimal": 59023
|
||||
},
|
||||
{
|
||||
"icon_id": "15838589",
|
||||
"name": "delete-filling",
|
||||
"font_class": "delete-filling",
|
||||
"unicode": "e690",
|
||||
"unicode_decimal": 59024
|
||||
},
|
||||
{
|
||||
"icon_id": "15838590",
|
||||
"name": "decline-filling",
|
||||
"font_class": "decline-filling",
|
||||
"unicode": "e691",
|
||||
"unicode_decimal": 59025
|
||||
},
|
||||
{
|
||||
"icon_id": "15838591",
|
||||
"name": "dynamic-filling",
|
||||
"font_class": "dynamic-filling",
|
||||
"unicode": "e692",
|
||||
"unicode_decimal": 59026
|
||||
},
|
||||
{
|
||||
"icon_id": "15838592",
|
||||
"name": "intermediate-filling",
|
||||
"font_class": "intermediate-filling",
|
||||
"unicode": "e693",
|
||||
"unicode_decimal": 59027
|
||||
},
|
||||
{
|
||||
"icon_id": "15838593",
|
||||
"name": "favorite-filling",
|
||||
"font_class": "favorite-filling",
|
||||
"unicode": "e694",
|
||||
"unicode_decimal": 59028
|
||||
},
|
||||
{
|
||||
"icon_id": "15838594",
|
||||
"name": "layout-filling",
|
||||
"font_class": "layout-filling",
|
||||
"unicode": "e695",
|
||||
"unicode_decimal": 59029
|
||||
},
|
||||
{
|
||||
"icon_id": "15838595",
|
||||
"name": "help-filling",
|
||||
"font_class": "help-filling",
|
||||
"unicode": "e696",
|
||||
"unicode_decimal": 59030
|
||||
},
|
||||
{
|
||||
"icon_id": "15838596",
|
||||
"name": "history-filling",
|
||||
"font_class": "history-filling",
|
||||
"unicode": "e697",
|
||||
"unicode_decimal": 59031
|
||||
},
|
||||
{
|
||||
"icon_id": "15838597",
|
||||
"name": "filter-filling",
|
||||
"font_class": "filter-filling",
|
||||
"unicode": "e698",
|
||||
"unicode_decimal": 59032
|
||||
},
|
||||
{
|
||||
"icon_id": "15838598",
|
||||
"name": "file-common-filling",
|
||||
"font_class": "file-common-filling",
|
||||
"unicode": "e699",
|
||||
"unicode_decimal": 59033
|
||||
},
|
||||
{
|
||||
"icon_id": "15838599",
|
||||
"name": "news-filling",
|
||||
"font_class": "news-filling",
|
||||
"unicode": "e69a",
|
||||
"unicode_decimal": 59034
|
||||
},
|
||||
{
|
||||
"icon_id": "15838600",
|
||||
"name": "edit-filling",
|
||||
"font_class": "edit-filling",
|
||||
"unicode": "e69b",
|
||||
"unicode_decimal": 59035
|
||||
},
|
||||
{
|
||||
"icon_id": "15838601",
|
||||
"name": "fullscreen-expand-filling",
|
||||
"font_class": "fullscreen-expand-filling",
|
||||
"unicode": "e69c",
|
||||
"unicode_decimal": 59036
|
||||
},
|
||||
{
|
||||
"icon_id": "15838602",
|
||||
"name": "smile-filling",
|
||||
"font_class": "smile-filling",
|
||||
"unicode": "e69d",
|
||||
"unicode_decimal": 59037
|
||||
},
|
||||
{
|
||||
"icon_id": "15838603",
|
||||
"name": "rise-filling",
|
||||
"font_class": "rise-filling",
|
||||
"unicode": "e69e",
|
||||
"unicode_decimal": 59038
|
||||
},
|
||||
{
|
||||
"icon_id": "15838604",
|
||||
"name": "picture-filling",
|
||||
"font_class": "picture-filling",
|
||||
"unicode": "e69f",
|
||||
"unicode_decimal": 59039
|
||||
},
|
||||
{
|
||||
"icon_id": "15838605",
|
||||
"name": "notification-filling",
|
||||
"font_class": "notification-filling",
|
||||
"unicode": "e6a0",
|
||||
"unicode_decimal": 59040
|
||||
},
|
||||
{
|
||||
"icon_id": "15838606",
|
||||
"name": "user-filling",
|
||||
"font_class": "user-filling",
|
||||
"unicode": "e6a1",
|
||||
"unicode_decimal": 59041
|
||||
},
|
||||
{
|
||||
"icon_id": "15838607",
|
||||
"name": "setting-filling",
|
||||
"font_class": "setting-filling",
|
||||
"unicode": "e6a2",
|
||||
"unicode_decimal": 59042
|
||||
},
|
||||
{
|
||||
"icon_id": "15838608",
|
||||
"name": "switch-filling",
|
||||
"font_class": "switch-filling",
|
||||
"unicode": "e6a3",
|
||||
"unicode_decimal": 59043
|
||||
},
|
||||
{
|
||||
"icon_id": "15838609",
|
||||
"name": "work-filling",
|
||||
"font_class": "work-filling",
|
||||
"unicode": "e6a4",
|
||||
"unicode_decimal": 59044
|
||||
},
|
||||
{
|
||||
"icon_id": "15838610",
|
||||
"name": "task-filling",
|
||||
"font_class": "task-filling",
|
||||
"unicode": "e6a5",
|
||||
"unicode_decimal": 59045
|
||||
},
|
||||
{
|
||||
"icon_id": "15838611",
|
||||
"name": "success-filling",
|
||||
"font_class": "success-filling",
|
||||
"unicode": "e6a6",
|
||||
"unicode_decimal": 59046
|
||||
},
|
||||
{
|
||||
"icon_id": "15838612",
|
||||
"name": "warning-filling",
|
||||
"font_class": "warning-filling",
|
||||
"unicode": "e6a7",
|
||||
"unicode_decimal": 59047
|
||||
},
|
||||
{
|
||||
"icon_id": "15838613",
|
||||
"name": "folder-filling",
|
||||
"font_class": "folder-filling",
|
||||
"unicode": "e6a8",
|
||||
"unicode_decimal": 59048
|
||||
},
|
||||
{
|
||||
"icon_id": "15838614",
|
||||
"name": "map-filling",
|
||||
"font_class": "map-filling",
|
||||
"unicode": "e6a9",
|
||||
"unicode_decimal": 59049
|
||||
},
|
||||
{
|
||||
"icon_id": "15838615",
|
||||
"name": "prompt-filling",
|
||||
"font_class": "prompt-filling",
|
||||
"unicode": "e6aa",
|
||||
"unicode_decimal": 59050
|
||||
},
|
||||
{
|
||||
"icon_id": "15838616",
|
||||
"name": "meh-filling",
|
||||
"font_class": "meh-filling",
|
||||
"unicode": "e6ab",
|
||||
"unicode_decimal": 59051
|
||||
},
|
||||
{
|
||||
"icon_id": "15838617",
|
||||
"name": "cry-filling",
|
||||
"font_class": "cry-filling",
|
||||
"unicode": "e6ac",
|
||||
"unicode_decimal": 59052
|
||||
},
|
||||
{
|
||||
"icon_id": "15838618",
|
||||
"name": "top-filling",
|
||||
"font_class": "top-filling",
|
||||
"unicode": "e6ad",
|
||||
"unicode_decimal": 59053
|
||||
},
|
||||
{
|
||||
"icon_id": "15838619",
|
||||
"name": "home-filling",
|
||||
"font_class": "home-filling",
|
||||
"unicode": "e6ae",
|
||||
"unicode_decimal": 59054
|
||||
},
|
||||
{
|
||||
"icon_id": "15838620",
|
||||
"name": "sorting",
|
||||
"font_class": "sorting",
|
||||
"unicode": "e6af",
|
||||
"unicode_decimal": 59055
|
||||
}
|
||||
]
|
||||
}
|
BIN
snowy-admin-web/src/assets/icons/mobile/filled/iconfont.ttf
Normal file
BIN
snowy-admin-web/src/assets/icons/mobile/filled/iconfont.ttf
Normal file
Binary file not shown.
36
snowy-admin-web/src/assets/icons/mobile/index.js
Normal file
36
snowy-admin-web/src/assets/icons/mobile/index.js
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
import './line/iconfont.css'
|
||||
import lineJsonData from './line/iconfont.json'
|
||||
|
||||
import './filled/iconfont.css'
|
||||
import filledJsonData from './filled/iconfont.json'
|
||||
|
||||
export default {
|
||||
icons: [
|
||||
{
|
||||
name: '基础',
|
||||
key: 'default',
|
||||
iconItem: [
|
||||
{
|
||||
name: '线框风格',
|
||||
key: 'default',
|
||||
item: lineJsonData.glyphs
|
||||
},
|
||||
{
|
||||
name: '实底风格',
|
||||
key: 'filled',
|
||||
item: filledJsonData.glyphs
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
825
snowy-admin-web/src/assets/icons/mobile/line/iconfont.css
Normal file
825
snowy-admin-web/src/assets/icons/mobile/line/iconfont.css
Normal file
@ -0,0 +1,825 @@
|
||||
@font-face {
|
||||
font-family: "snowy"; /* Project id 3791763 */
|
||||
src: url('iconfont.ttf?t=1675526220710') format('truetype');
|
||||
}
|
||||
|
||||
.snowy {
|
||||
font-family: "snowy" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.export-outlined:before {
|
||||
content: "\e792";
|
||||
}
|
||||
|
||||
.experiment-outlined:before {
|
||||
content: "\e7c9";
|
||||
}
|
||||
|
||||
.expand-outlined:before {
|
||||
content: "\e915";
|
||||
}
|
||||
|
||||
.expand-alt-outlined:before {
|
||||
content: "\e7e9";
|
||||
}
|
||||
|
||||
.exception-outlined:before {
|
||||
content: "\e7bb";
|
||||
}
|
||||
|
||||
.euro-outlined:before {
|
||||
content: "\e78f";
|
||||
}
|
||||
|
||||
.euro-circle-outlined:before {
|
||||
content: "\eb62";
|
||||
}
|
||||
|
||||
.environment-outlined:before {
|
||||
content: "\e790";
|
||||
}
|
||||
|
||||
.ellipsis-outlined:before {
|
||||
content: "\e815";
|
||||
}
|
||||
|
||||
.download-outlined:before {
|
||||
content: "\e814";
|
||||
}
|
||||
|
||||
.dollar-outlined:before {
|
||||
content: "\e78d";
|
||||
}
|
||||
|
||||
.dollar-circle-outlined:before {
|
||||
content: "\eb61";
|
||||
}
|
||||
|
||||
.dislike-outlined:before {
|
||||
content: "\e7c8";
|
||||
}
|
||||
|
||||
.disconnect-outlined:before {
|
||||
content: "\e7e8";
|
||||
}
|
||||
|
||||
.dingtalk-outlined:before {
|
||||
content: "\e881";
|
||||
}
|
||||
|
||||
.desktop-outlined:before {
|
||||
content: "\e845";
|
||||
}
|
||||
|
||||
.deployment-unit-outlined:before {
|
||||
content: "\e7d2";
|
||||
}
|
||||
|
||||
.delivered-procedure-outlined:before {
|
||||
content: "\e911";
|
||||
}
|
||||
|
||||
.delete-column-outlined:before {
|
||||
content: "\e901";
|
||||
}
|
||||
|
||||
.delete-row-outlined:before {
|
||||
content: "\e902";
|
||||
}
|
||||
|
||||
.database-outlined:before {
|
||||
content: "\e7b9";
|
||||
}
|
||||
|
||||
.dashboard-outlined:before {
|
||||
content: "\e78b";
|
||||
}
|
||||
|
||||
.customer-service-outlined:before {
|
||||
content: "\e7ca";
|
||||
}
|
||||
|
||||
.crown-outlined:before {
|
||||
content: "\e844";
|
||||
}
|
||||
|
||||
.credit-card-outlined:before {
|
||||
content: "\e7e5";
|
||||
}
|
||||
|
||||
.copyright-outlined:before {
|
||||
content: "\e789";
|
||||
}
|
||||
|
||||
.copyright-circle-outlined:before {
|
||||
content: "\eb60";
|
||||
}
|
||||
|
||||
.control-outlined:before {
|
||||
content: "\e79c";
|
||||
}
|
||||
|
||||
.container-outlined:before {
|
||||
content: "\e7b8";
|
||||
}
|
||||
|
||||
.contacts-outlined:before {
|
||||
content: "\e7e4";
|
||||
}
|
||||
|
||||
.console-sql-outlined:before {
|
||||
content: "\e910";
|
||||
}
|
||||
|
||||
.compress-outlined:before {
|
||||
content: "\e914";
|
||||
}
|
||||
|
||||
.compass-outlined:before {
|
||||
content: "\e786";
|
||||
}
|
||||
|
||||
.comment-outlined:before {
|
||||
content: "\e8ea";
|
||||
}
|
||||
|
||||
.coffee-outlined:before {
|
||||
content: "\e6b5";
|
||||
}
|
||||
|
||||
.code-outlined:before {
|
||||
content: "\e79b";
|
||||
}
|
||||
|
||||
.cloud-server-outlined:before {
|
||||
content: "\e7db";
|
||||
}
|
||||
|
||||
.cloud-upload-outlined:before {
|
||||
content: "\e7dc";
|
||||
}
|
||||
|
||||
.cloud-outlined:before {
|
||||
content: "\e7dd";
|
||||
}
|
||||
|
||||
.cloud-download-outlined:before {
|
||||
content: "\e7de";
|
||||
}
|
||||
|
||||
.cloud-sync-outlined:before {
|
||||
content: "\e7e0";
|
||||
}
|
||||
|
||||
.clear-outlined:before {
|
||||
content: "\e900";
|
||||
}
|
||||
|
||||
.ci-circle-outlined:before {
|
||||
content: "\e77f";
|
||||
}
|
||||
|
||||
.carry-out-outlined:before {
|
||||
content: "\e7d6";
|
||||
}
|
||||
|
||||
.car-outlined:before {
|
||||
content: "\e7da";
|
||||
}
|
||||
|
||||
.ci-outlined:before {
|
||||
content: "\eb5f";
|
||||
}
|
||||
|
||||
.camera-outlined:before {
|
||||
content: "\e7d9";
|
||||
}
|
||||
|
||||
.calendar-outlined:before {
|
||||
content: "\e7d4";
|
||||
}
|
||||
|
||||
.calculator-outlined:before {
|
||||
content: "\e79a";
|
||||
}
|
||||
|
||||
.bulb-outlined:before {
|
||||
content: "\e7c7";
|
||||
}
|
||||
|
||||
.build-outlined:before {
|
||||
content: "\e7d5";
|
||||
}
|
||||
|
||||
.bug-outlined:before {
|
||||
content: "\e8e9";
|
||||
}
|
||||
|
||||
.branches-outlined:before {
|
||||
content: "\e7e7";
|
||||
}
|
||||
|
||||
.borderless-table-outlined:before {
|
||||
content: "\e813";
|
||||
}
|
||||
|
||||
.border-outlined:before {
|
||||
content: "\e7b7";
|
||||
}
|
||||
|
||||
.book-outlined:before {
|
||||
content: "\e7b6";
|
||||
}
|
||||
|
||||
.block-outlined:before {
|
||||
content: "\e7df";
|
||||
}
|
||||
|
||||
.bell-outlined:before {
|
||||
content: "\e7c5";
|
||||
}
|
||||
|
||||
.bars-outlined:before {
|
||||
content: "\e71a";
|
||||
}
|
||||
|
||||
.barcode-outlined:before {
|
||||
content: "\e7d8";
|
||||
}
|
||||
|
||||
.bank-outlined:before {
|
||||
content: "\e7c6";
|
||||
}
|
||||
|
||||
.audit-outlined:before {
|
||||
content: "\e7c0";
|
||||
}
|
||||
|
||||
.audio-outlined:before {
|
||||
content: "\e89b";
|
||||
}
|
||||
|
||||
.audio-muted-outlined:before {
|
||||
content: "\e8e8";
|
||||
}
|
||||
|
||||
.api-outlined:before {
|
||||
content: "\e7e3";
|
||||
}
|
||||
|
||||
.apartment-outlined:before {
|
||||
content: "\e89a";
|
||||
}
|
||||
|
||||
.alert-outlined:before {
|
||||
content: "\e7c4";
|
||||
}
|
||||
|
||||
.aim-outlined:before {
|
||||
content: "\e913";
|
||||
}
|
||||
|
||||
.account-book-outlined:before {
|
||||
content: "\e7d3";
|
||||
}
|
||||
|
||||
.column-height-outlined:before {
|
||||
content: "\e811";
|
||||
}
|
||||
|
||||
.column-width-outlined:before {
|
||||
content: "\e812";
|
||||
}
|
||||
|
||||
.radius-setting-outlined:before {
|
||||
content: "\e7b5";
|
||||
}
|
||||
|
||||
.unordered-list-outlined:before {
|
||||
content: "\e80f";
|
||||
}
|
||||
|
||||
.ordered-list-outlined:before {
|
||||
content: "\e810";
|
||||
}
|
||||
|
||||
.drag-outlined:before {
|
||||
content: "\e843";
|
||||
}
|
||||
|
||||
.sort-descending-outlined:before {
|
||||
content: "\e80d";
|
||||
}
|
||||
|
||||
.sort-ascending-outlined:before {
|
||||
content: "\e80e";
|
||||
}
|
||||
|
||||
.font-colors-outlined:before {
|
||||
content: "\e808";
|
||||
}
|
||||
|
||||
.font-size-outlined:before {
|
||||
content: "\e809";
|
||||
}
|
||||
|
||||
.line-height-outlined:before {
|
||||
content: "\e80a";
|
||||
}
|
||||
|
||||
.dash-outlined:before {
|
||||
content: "\e80b";
|
||||
}
|
||||
|
||||
.small-dash-outlined:before {
|
||||
content: "\e80c";
|
||||
}
|
||||
|
||||
.zoom-out-outlined:before {
|
||||
content: "\e898";
|
||||
}
|
||||
|
||||
.zoom-in-outlined:before {
|
||||
content: "\e899";
|
||||
}
|
||||
|
||||
.undo-outlined:before {
|
||||
content: "\e787";
|
||||
}
|
||||
|
||||
.redo-outlined:before {
|
||||
content: "\e788";
|
||||
}
|
||||
|
||||
.bold-outlined:before {
|
||||
content: "\e804";
|
||||
}
|
||||
|
||||
.strikethrough-outlined:before {
|
||||
content: "\e805";
|
||||
}
|
||||
|
||||
.underline-outlined:before {
|
||||
content: "\e806";
|
||||
}
|
||||
|
||||
.italic-outlined:before {
|
||||
content: "\e807";
|
||||
}
|
||||
|
||||
.bg-colors-outlined:before {
|
||||
content: "\e803";
|
||||
}
|
||||
|
||||
.align-right-outlined:before {
|
||||
content: "\e7fb";
|
||||
}
|
||||
|
||||
.align-left-outlined:before {
|
||||
content: "\e802";
|
||||
}
|
||||
|
||||
.align-center-outlined:before {
|
||||
content: "\e7f5";
|
||||
}
|
||||
|
||||
.highlight-outlined:before {
|
||||
content: "\e7e2";
|
||||
}
|
||||
|
||||
.diff-outlined:before {
|
||||
content: "\e7bf";
|
||||
}
|
||||
|
||||
.snippets-outlined:before {
|
||||
content: "\e7bd";
|
||||
}
|
||||
|
||||
.delete-outlined:before {
|
||||
content: "\e7c3";
|
||||
}
|
||||
|
||||
.scissor-outlined:before {
|
||||
content: "\e7e6";
|
||||
}
|
||||
|
||||
.copy-outlined:before {
|
||||
content: "\e7bc";
|
||||
}
|
||||
|
||||
.form-outlined:before {
|
||||
content: "\e791";
|
||||
}
|
||||
|
||||
.edit-outlined:before {
|
||||
content: "\e7e1";
|
||||
}
|
||||
|
||||
.stop-outlined:before {
|
||||
content: "\e842";
|
||||
}
|
||||
|
||||
.issues-close-outlined:before {
|
||||
content: "\e68e";
|
||||
}
|
||||
|
||||
.warning-outlined:before {
|
||||
content: "\e682";
|
||||
}
|
||||
|
||||
.clock-circle-outlined:before {
|
||||
content: "\e784";
|
||||
}
|
||||
|
||||
.check-circle-outlined:before {
|
||||
content: "\e77d";
|
||||
}
|
||||
|
||||
.check-square-outlined:before {
|
||||
content: "\e794";
|
||||
}
|
||||
|
||||
.check-outlined:before {
|
||||
content: "\e7fc";
|
||||
}
|
||||
|
||||
.exclamation-circle-outlined:before {
|
||||
content: "\e785";
|
||||
}
|
||||
|
||||
.exclamation-outlined:before {
|
||||
content: "\e7fa";
|
||||
}
|
||||
|
||||
.info-circle-outlined:before {
|
||||
content: "\e77e";
|
||||
}
|
||||
|
||||
.info-outlined:before {
|
||||
content: "\e7f9";
|
||||
}
|
||||
|
||||
.minus-square-outlined:before {
|
||||
content: "\e796";
|
||||
}
|
||||
|
||||
.plus-square-outlined:before {
|
||||
content: "\e797";
|
||||
}
|
||||
|
||||
.minus-circle-outlined:before {
|
||||
content: "\e780";
|
||||
}
|
||||
|
||||
.minus-outlined:before {
|
||||
content: "\e801";
|
||||
}
|
||||
|
||||
.pause-circle-outlined:before {
|
||||
content: "\e783";
|
||||
}
|
||||
|
||||
.pause-outlined:before {
|
||||
content: "\e800";
|
||||
}
|
||||
|
||||
.plus-circle-outlined:before {
|
||||
content: "\e781";
|
||||
}
|
||||
|
||||
.plus-outlined:before {
|
||||
content: "\e8fe";
|
||||
}
|
||||
|
||||
.question-circle-outlined:before {
|
||||
content: "\e782";
|
||||
}
|
||||
|
||||
.question-outlined:before {
|
||||
content: "\e7ff";
|
||||
}
|
||||
|
||||
.fullscreen-outlined:before {
|
||||
content: "\e7ec";
|
||||
}
|
||||
|
||||
.fullscreen-exit-outlined:before {
|
||||
content: "\e7ed";
|
||||
}
|
||||
|
||||
.radius-bottomleft-outlined:before {
|
||||
content: "\e7b1";
|
||||
}
|
||||
|
||||
.radius-bottomright-outlined:before {
|
||||
content: "\e7b2";
|
||||
}
|
||||
|
||||
.radius-upleft-outlined:before {
|
||||
content: "\e7b3";
|
||||
}
|
||||
|
||||
.radius-upright-outlined:before {
|
||||
content: "\e7b4";
|
||||
}
|
||||
|
||||
.pic-center-outlined:before {
|
||||
content: "\e7f6";
|
||||
}
|
||||
|
||||
.pic-right-outlined:before {
|
||||
content: "\e7f7";
|
||||
}
|
||||
|
||||
.pic-left-outlined:before {
|
||||
content: "\e7f8";
|
||||
}
|
||||
|
||||
.border-outer-outlined:before {
|
||||
content: "\e7a9";
|
||||
}
|
||||
|
||||
.border-top-outlined:before {
|
||||
content: "\e7aa";
|
||||
}
|
||||
|
||||
.border-bottom-outlined:before {
|
||||
content: "\e7ab";
|
||||
}
|
||||
|
||||
.border-left-outlined:before {
|
||||
content: "\e7ac";
|
||||
}
|
||||
|
||||
.border-right-outlined:before {
|
||||
content: "\e7ad";
|
||||
}
|
||||
|
||||
.border-inner-outlined:before {
|
||||
content: "\e7ae";
|
||||
}
|
||||
|
||||
.border-verticle-outlined:before {
|
||||
content: "\e7af";
|
||||
}
|
||||
|
||||
.border-horizontal-outlined:before {
|
||||
content: "\e7b0";
|
||||
}
|
||||
|
||||
.menu-unfold-outlined:before {
|
||||
content: "\e7f3";
|
||||
}
|
||||
|
||||
.menu-fold-outlined:before {
|
||||
content: "\e7f4";
|
||||
}
|
||||
|
||||
.logout-outlined:before {
|
||||
content: "\e78c";
|
||||
}
|
||||
|
||||
.login-outlined:before {
|
||||
content: "\e8f4";
|
||||
}
|
||||
|
||||
.cluster-outlined:before {
|
||||
content: "\e7d7";
|
||||
}
|
||||
|
||||
.down-square-outlined:before {
|
||||
content: "\e793";
|
||||
}
|
||||
|
||||
.left-square-outlined:before {
|
||||
content: "\e795";
|
||||
}
|
||||
|
||||
.right-square-outlined:before {
|
||||
content: "\e798";
|
||||
}
|
||||
|
||||
.up-Square-outlined:before {
|
||||
content: "\e799";
|
||||
}
|
||||
|
||||
.play-circle-outlined:before {
|
||||
content: "\e67a";
|
||||
}
|
||||
|
||||
.arrow-down-outlined:before {
|
||||
content: "\e66d";
|
||||
}
|
||||
|
||||
.arrow-right-outlined:before {
|
||||
content: "\e66e";
|
||||
}
|
||||
|
||||
.arrow-up-outlined:before {
|
||||
content: "\e66f";
|
||||
}
|
||||
|
||||
.arrow-left-outlined:before {
|
||||
content: "\e670";
|
||||
}
|
||||
|
||||
.swap-outlined:before {
|
||||
content: "\e7f2";
|
||||
}
|
||||
|
||||
.swap-right-outlined:before {
|
||||
content: "\e8f2";
|
||||
}
|
||||
|
||||
.swap-left-outlined:before {
|
||||
content: "\e8f3";
|
||||
}
|
||||
|
||||
.enter-outlined:before {
|
||||
content: "\e7fd";
|
||||
}
|
||||
|
||||
.rollback-outlined:before {
|
||||
content: "\e7fe";
|
||||
}
|
||||
|
||||
.retweet-outlined:before {
|
||||
content: "\e8f1";
|
||||
}
|
||||
|
||||
.fast-backward-outlined:before {
|
||||
content: "\e8ed";
|
||||
}
|
||||
|
||||
.fast-forward-outlined:before {
|
||||
content: "\e8ee";
|
||||
}
|
||||
|
||||
.vertical-align-bottom-outlined:before {
|
||||
content: "\e7ef";
|
||||
}
|
||||
|
||||
.vertical-align-middle-outlined:before {
|
||||
content: "\e7f0";
|
||||
}
|
||||
|
||||
.vertical-align-top-outlined:before {
|
||||
content: "\e7f1";
|
||||
}
|
||||
|
||||
.vertical-right-outlined:before {
|
||||
content: "\e7ea";
|
||||
}
|
||||
|
||||
.vertical-left-outlined:before {
|
||||
content: "\e7eb";
|
||||
}
|
||||
|
||||
.double-left-outlined:before {
|
||||
content: "\e66b";
|
||||
}
|
||||
|
||||
.double-right-outlined:before {
|
||||
content: "\e66c";
|
||||
}
|
||||
|
||||
.up-circle-outlined:before {
|
||||
content: "\e666";
|
||||
}
|
||||
|
||||
.right-circle-outlined:before {
|
||||
content: "\e667";
|
||||
}
|
||||
|
||||
.left-circle-outlined:before {
|
||||
content: "\e66a";
|
||||
}
|
||||
|
||||
.down-circle-outlined:before {
|
||||
content: "\eb5e";
|
||||
}
|
||||
|
||||
.caret-up-outlined:before {
|
||||
content: "\e689";
|
||||
}
|
||||
|
||||
.caret-down-outlined:before {
|
||||
content: "\e68a";
|
||||
}
|
||||
|
||||
.caret-left-outlined:before {
|
||||
content: "\e68b";
|
||||
}
|
||||
|
||||
.caret-right-outlined:before {
|
||||
content: "\e68c";
|
||||
}
|
||||
|
||||
.left-outlined:before {
|
||||
content: "\e685";
|
||||
}
|
||||
|
||||
.up-outlined:before {
|
||||
content: "\e686";
|
||||
}
|
||||
|
||||
.down-outlined:before {
|
||||
content: "\e687";
|
||||
}
|
||||
|
||||
.right-outlined:before {
|
||||
content: "\e688";
|
||||
}
|
||||
|
||||
.arrows-alt-outlined:before {
|
||||
content: "\e665";
|
||||
}
|
||||
|
||||
.shrink-outlined:before {
|
||||
content: "\e68d";
|
||||
}
|
||||
|
||||
.step-backward-outlined:before {
|
||||
content: "\e8ef";
|
||||
}
|
||||
|
||||
.step-forward-outlined:before {
|
||||
content: "\e8f0";
|
||||
}
|
||||
|
||||
.robot-outlined:before {
|
||||
content: "\e897";
|
||||
}
|
||||
|
||||
.file-word-outlined:before {
|
||||
content: "\e7ba";
|
||||
}
|
||||
|
||||
.usergroup-delete-outlined:before {
|
||||
content: "\e760";
|
||||
}
|
||||
|
||||
.field-time-outlined:before {
|
||||
content: "\eb5d";
|
||||
}
|
||||
|
||||
.setting-outlined:before {
|
||||
content: "\e78e";
|
||||
}
|
||||
|
||||
.file-search-outlined:before {
|
||||
content: "\e730";
|
||||
}
|
||||
|
||||
.team-outlined:before {
|
||||
content: "\e67d";
|
||||
}
|
||||
|
||||
.message-outlined:before {
|
||||
content: "\e78a";
|
||||
}
|
||||
|
||||
.mail-outlined:before {
|
||||
content: "\e62e";
|
||||
}
|
||||
|
||||
.send-outlined:before {
|
||||
content: "\e622";
|
||||
}
|
||||
|
||||
.appstore-add-outlined:before {
|
||||
content: "\e8eb";
|
||||
}
|
||||
|
||||
.user-outlined:before {
|
||||
content: "\e641";
|
||||
}
|
||||
|
||||
.project-outlined:before {
|
||||
content: "\e746";
|
||||
}
|
||||
|
||||
.hdd-outlined:before {
|
||||
content: "\e734";
|
||||
}
|
||||
|
||||
.tool-outlined:before {
|
||||
content: "\e75b";
|
||||
}
|
||||
|
||||
.user-switch-outlined:before {
|
||||
content: "\ea3d";
|
||||
}
|
||||
|
||||
.appstore-outlined:before {
|
||||
content: "\e601";
|
||||
}
|
||||
|
||||
.home-outlined:before {
|
||||
content: "\e965";
|
||||
}
|
||||
|
1430
snowy-admin-web/src/assets/icons/mobile/line/iconfont.json
Normal file
1430
snowy-admin-web/src/assets/icons/mobile/line/iconfont.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
snowy-admin-web/src/assets/icons/mobile/line/iconfont.ttf
Normal file
BIN
snowy-admin-web/src/assets/icons/mobile/line/iconfont.ttf
Normal file
Binary file not shown.
56
snowy-admin-web/src/auto-imports.d.ts
vendored
56
snowy-admin-web/src/auto-imports.d.ts
vendored
@ -1,56 +0,0 @@
|
||||
// Generated by 'unplugin-auto-import'
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const computed: typeof import('vue')['computed']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const h: typeof import('vue')['h']
|
||||
const hasPerm: typeof import('./utils/permission/index.js')['hasPerm']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
const isReadonly: typeof import('vue')['isReadonly']
|
||||
const isRef: typeof import('vue')['isRef']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
||||
const onMounted: typeof import('vue')['onMounted']
|
||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
const readonly: typeof import('vue')['readonly']
|
||||
const ref: typeof import('vue')['ref']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const toRaw: typeof import('vue')['toRaw']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const unref: typeof import('vue')['unref']
|
||||
const useAttrs: typeof import('vue')['useAttrs']
|
||||
const useCssModule: typeof import('vue')['useCssModule']
|
||||
const useCssVars: typeof import('vue')['useCssVars']
|
||||
const useSlots: typeof import('vue')['useSlots']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
<template>
|
||||
<div class="sceditor">
|
||||
<Editor v-model="contentValue" :init="init" :disabled="disabled" :placeholder="placeholder" @onClick="onClick" />
|
||||
</div>
|
||||
<Editor v-model="contentValue" :init="init" :disabled="disabled" :placeholder="placeholder" @onClick="onClick" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -10,13 +8,15 @@
|
||||
import tinymce from 'tinymce/tinymce'
|
||||
import 'tinymce/themes/silver'
|
||||
import 'tinymce/icons/default'
|
||||
|
||||
import 'tinymce/models/dom'
|
||||
// 引入编辑器插件
|
||||
import 'tinymce/plugins/code' // 编辑源码
|
||||
import 'tinymce/plugins/image' // 插入编辑图片
|
||||
import 'tinymce/plugins/link' // 超链接
|
||||
import 'tinymce/plugins/preview' // 预览
|
||||
import 'tinymce/plugins/table' // 表格
|
||||
import 'tinymce/plugins/lists' // 列表编号
|
||||
import 'tinymce/plugins/advlist' //高级列表编号
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -41,12 +41,12 @@
|
||||
},
|
||||
plugins: {
|
||||
type: [String, Array],
|
||||
default: 'code image link preview table'
|
||||
default: 'code image link preview table lists advlist'
|
||||
},
|
||||
toolbar: {
|
||||
type: [String, Array],
|
||||
default:
|
||||
'undo redo | forecolor backcolor bold italic underline strikethrough link | formatselect fontselect fontsizeselect | \
|
||||
'undo redo | forecolor backcolor bold italic underline strikethrough link | blocks fontfamily fontsize | \
|
||||
alignleft aligncenter alignright alignjustify outdent indent lineheight | bullist numlist | \
|
||||
image table preview | code selectall'
|
||||
}
|
||||
@ -69,15 +69,16 @@
|
||||
resize: true,
|
||||
elementpath: true,
|
||||
content_style: '',
|
||||
images_upload_handler: async (blobInfo, success, failure) => {
|
||||
const data = new FormData()
|
||||
data.append('file', blobInfo.blob(), blobInfo.filename())
|
||||
try {
|
||||
const res = await fileApi.fileUploadDynamicReturnUrl(data)
|
||||
success(res)
|
||||
} catch (error) {
|
||||
failure('Image upload failed')
|
||||
}
|
||||
images_upload_handler(blobInfo, progress) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = new FormData()
|
||||
data.append('file', blobInfo.blob(), blobInfo.filename())
|
||||
fileApi.fileUploadDynamicReturnUrl(data).then((res) => {
|
||||
return resolve(res)
|
||||
}).catch((err) => {
|
||||
return reject('err:' + err)
|
||||
})
|
||||
})
|
||||
},
|
||||
setup: (editor) => {
|
||||
editor.on('init', function () {
|
||||
@ -106,5 +107,3 @@
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
|
143
snowy-admin-web/src/components/Selector/iconMobileSelector.vue
Normal file
143
snowy-admin-web/src/components/Selector/iconMobileSelector.vue
Normal file
@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="visible"
|
||||
title="移动端图标选择"
|
||||
:mask-closable="false"
|
||||
:width="800"
|
||||
:destroy-on-close="true"
|
||||
:footer="null"
|
||||
@cancel="onCancel"
|
||||
>
|
||||
<a-tabs v-model:activeKey="activeKey" tab-position="left" size="small" @change="paneChange">
|
||||
<a-tab-pane v-for="item in iconData" :key="item.key" :tab="item.name">
|
||||
<div v-if="item.iconItem.length > 1" class="xn-icon-select-radio">
|
||||
<a-radio-group v-model:value="iconItemDefault" @change="radioGroupChange">
|
||||
<a-radio-button v-for="iconItem in item.iconItem" :key="iconItem.key" :value="iconItem.key">{{
|
||||
iconItem.name
|
||||
}}</a-radio-button>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
|
||||
<div :key="iconItemIns" v-for="iconItemIns in item.iconItem">
|
||||
<div v-if="iconItemIns.key === iconItemDefault" class="xn-icon-select-list">
|
||||
<ul>
|
||||
<li
|
||||
v-for="icon in iconItemIns.item"
|
||||
:key="icon"
|
||||
:class="icon === modelValue ? 'active' : ''"
|
||||
@click="selectIcon(icon.font_class)"
|
||||
>
|
||||
<span class="snowy xn-icons" :class="icon.font_class" ></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from '@/assets/icons/mobile'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
iconData: [],
|
||||
modelValue: '',
|
||||
activeKey: 'default',
|
||||
iconItemDefault: 'default',
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.iconData.push(...config.icons)
|
||||
},
|
||||
methods: {
|
||||
// 打开
|
||||
showIconModal(value) {
|
||||
this.visible = true
|
||||
this.defaultSetting(value)
|
||||
},
|
||||
// 默认配置
|
||||
defaultSetting(value) {
|
||||
if (value) {
|
||||
this.modelValue = value
|
||||
// 判断展开哪个
|
||||
if (value.indexOf('-outlined') > -1 || value.indexOf('-filled') > -1 || value.indexOf('-two-tone') > -1) {
|
||||
this.activeKey = 'default'
|
||||
if (value.indexOf('-two-tone') > -1) {
|
||||
this.iconItemDefault = 'twotone'
|
||||
} else if (value.indexOf('-filled') > -1) {
|
||||
this.iconItemDefault = 'filled'
|
||||
}
|
||||
} else if (value.indexOf('-extend') > -1) {
|
||||
// 扩展列表
|
||||
this.activeKey = 'extend'
|
||||
// 如扩展其他顶部单选的情况,默认选中在这里配置,同时这里需要做判断
|
||||
// this.iconItemDefault = '您的json中配置的'
|
||||
}
|
||||
}
|
||||
},
|
||||
// 切换标签页,如果是切换到了没用额外的标签页的地方,我们将其置为默认
|
||||
paneChange(e) {
|
||||
if (e.indexOf('default') === -1) {
|
||||
this.iconItemDefault = 'default'
|
||||
}
|
||||
},
|
||||
// 切换icon风格
|
||||
radioGroupChange(e) {
|
||||
this.iconItemDefault = e.target.value
|
||||
},
|
||||
// 选择图标后关闭并返回
|
||||
selectIcon(value) {
|
||||
this.defaultValue = value
|
||||
this.visible = false
|
||||
// eslint-disable-next-line vue/require-explicit-emits
|
||||
this.$emit('iconCallBack', this.defaultValue)
|
||||
},
|
||||
onCancel() {
|
||||
this.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.xn-icon-select-radio {
|
||||
padding-left: 5px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.xn-icons {
|
||||
font-size: 26px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.xn-icon-select-list {
|
||||
height: 360px;
|
||||
overflow: auto;
|
||||
}
|
||||
.xn-icon-select-list ul {
|
||||
li {
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
padding: 18px;
|
||||
margin: 5px;
|
||||
border-radius: 2px;
|
||||
vertical-align: top;
|
||||
box-shadow: 0 0 0 1px var(--border-color-split);
|
||||
transition: all 0.1s;
|
||||
position: relative;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
cursor: pointer;
|
||||
color: #ffffff;
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -60,7 +60,7 @@
|
||||
},
|
||||
// 默认配置
|
||||
defaultSetting(value) {
|
||||
if ((value !== undefined) & (value !== '') & (value !== 'undefined')) {
|
||||
if (value) {
|
||||
this.modelValue = value
|
||||
// 判断展开哪个
|
||||
if (value.indexOf('-outlined') > -1 || value.indexOf('-filled') > -1 || value.indexOf('-two-tone') > -1) {
|
||||
|
@ -6,6 +6,7 @@
|
||||
import './index.less'
|
||||
|
||||
export default {
|
||||
name: 'STable',
|
||||
components: {
|
||||
draggable,
|
||||
columnSetting
|
||||
@ -13,10 +14,8 @@
|
||||
data() {
|
||||
return {
|
||||
needTotalList: [],
|
||||
|
||||
selectedRows: [],
|
||||
selectedRowKeys: [],
|
||||
|
||||
localLoading: false,
|
||||
localDataSource: [],
|
||||
localPagination: Object.assign({}, this.pagination),
|
||||
@ -44,8 +43,8 @@
|
||||
default: 1
|
||||
},
|
||||
size: {
|
||||
// type: Number,
|
||||
default: '10'
|
||||
type: Number,
|
||||
default: 10
|
||||
},
|
||||
showSizeChanger: {
|
||||
type: Boolean,
|
||||
@ -72,6 +71,14 @@
|
||||
type: [String, Boolean],
|
||||
default: 'auto'
|
||||
},
|
||||
defaultPageSize: {
|
||||
type: Number,
|
||||
default: 10
|
||||
},
|
||||
pageSizeOptions: {
|
||||
type: Array,
|
||||
default: () => ['10', '20', '50', '100']
|
||||
},
|
||||
/**
|
||||
* enable page URI mode
|
||||
*
|
||||
@ -137,10 +144,12 @@
|
||||
(['auto', true].includes(this.showPagination) &&
|
||||
Object.assign({}, this.localPagination, {
|
||||
current: localPageNum,
|
||||
size: this.size, //this.compSize, size// 改动
|
||||
pageSize: this.size, //this.compSize, size// 改动
|
||||
showSizeChanger: this.showSizeChanger,
|
||||
defaultPageSize: this.defaultPageSize,
|
||||
pageSizeOptions: this.pageSizeOptions,
|
||||
showTotal: (total, range) => {
|
||||
return `${range[0]}-${range[1]}共${total}条`
|
||||
return `${range[0]}-${range[1]} 共 ${total} 条 `
|
||||
}
|
||||
})) ||
|
||||
false
|
||||
@ -160,7 +169,7 @@
|
||||
{},
|
||||
{
|
||||
current: 1,
|
||||
size: this.size
|
||||
pageSize: this.localPagination.pageSize
|
||||
}
|
||||
))
|
||||
this.loadData()
|
||||
@ -179,7 +188,12 @@
|
||||
(pagination && pagination.current) ||
|
||||
(this.showPagination && this.localPagination.current) ||
|
||||
this.pageNum,
|
||||
size: (pagination && pagination.pageSize) || (this.showPagination && this.localPagination.size) || this.size
|
||||
// 此处后端使用size作为分页参数
|
||||
size:
|
||||
(pagination && pagination.pageSize) ||
|
||||
(this.showPagination && this.localPagination.pageSize) ||
|
||||
this.pageSize ||
|
||||
this.localPagination.pageSize
|
||||
},
|
||||
(sorter &&
|
||||
sorter.field && {
|
||||
@ -196,7 +210,6 @@
|
||||
}
|
||||
)
|
||||
const result = this.data(parameter)
|
||||
// 对接自己的通用数据接口需要修改下方代码中的 r.current, r.totalCount, r.data
|
||||
// eslint-disable-next-line
|
||||
if (
|
||||
(typeof result === 'object' || typeof result === 'function') &&
|
||||
@ -213,7 +226,10 @@
|
||||
current: r.current, // pageNo, // 返回结果中的当前分页数
|
||||
total: r.total, // totalRows, // 返回结果中的总记录数
|
||||
showSizeChanger: this.showSizeChanger,
|
||||
size: (pagination && pagination.size) || this.localPagination.size
|
||||
showTotal: (total, range) => {
|
||||
return `${range[0]}-${range[1]} 共 ${total} 条 `
|
||||
},
|
||||
pageSize: (pagination && pagination.pageSize) || this.localPagination.pageSize
|
||||
})) ||
|
||||
false
|
||||
// 后端数据records为null保存修复
|
||||
@ -226,11 +242,14 @@
|
||||
this.loadData()
|
||||
return
|
||||
}
|
||||
|
||||
// 这里用于判断接口是否有返回 r.totalCount(total) 且 this.showPagination = true 且 current 和 size 存在 且 totalCount 小于等于 current * size 的大小
|
||||
// 当情况满足时,表示数据不满足分页大小,关闭 table 分页功能
|
||||
try {
|
||||
if (['auto', true].includes(this.showPagination) && r.total <= r.pages * this.localPagination.size) {
|
||||
/*
|
||||
if ((['auto', true].includes(this.showPagination) && r.total <= (r.pages * this.localPagination.size))) {
|
||||
this.localPagination.hideOnSinglePage = true
|
||||
}
|
||||
*/
|
||||
if (!this.showPagination) {
|
||||
this.localPagination.hideOnSinglePage = true
|
||||
}
|
||||
} catch (e) {
|
||||
@ -238,8 +257,11 @@
|
||||
}
|
||||
// 返回结果中的数组数据
|
||||
if (this.showPagination === false) {
|
||||
// 因为按住小诺的套路,不分页的直接是在data中,我们在界面中直接就是返回了data
|
||||
this.localDataSource = r
|
||||
// 既然配置了不分页,那么我们这里接收到肯定是数组
|
||||
this.localDataSource = []
|
||||
if (r instanceof Array) {
|
||||
this.localDataSource = r
|
||||
}
|
||||
} else {
|
||||
this.localDataSource = r.records
|
||||
}
|
||||
@ -321,21 +343,19 @@
|
||||
const needTotalItems = this.needTotalList.map((item) => {
|
||||
return (
|
||||
<span className="mr-3">
|
||||
{item.title}总计{' '}
|
||||
{item.title} 总计{' '}
|
||||
<a className="font-6">{!item.customRender ? item.total : item.customRender(item.total)}</a>
|
||||
</span>
|
||||
)
|
||||
})
|
||||
|
||||
// 绘制 清空 按钮
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const clearItem =
|
||||
typeof this.alert.clear === 'boolean' && this.alert.clear
|
||||
typeof this.alert === 'boolean' && this.alert
|
||||
? this.renderClear(this.clearSelected)
|
||||
: typeof this.alert.clear === 'function'
|
||||
? this.renderClear(this.alert.clear)
|
||||
: null
|
||||
|
||||
// 绘制 alert 组件
|
||||
if (alert) {
|
||||
const message = (
|
||||
@ -347,7 +367,6 @@
|
||||
{clearItem}
|
||||
</div>
|
||||
)
|
||||
|
||||
return <a-alert showIcon class="mb-4" message={message} />
|
||||
}
|
||||
},
|
||||
@ -400,24 +419,21 @@
|
||||
}
|
||||
|
||||
// 斑马纹
|
||||
const changeRowClass = (val) => {
|
||||
const changeRowClass = (value) => {
|
||||
const val = value.target.checked
|
||||
this.localSettings.rowClassNameSwitch = val
|
||||
const evenClass = val ? (_record, index) => (index % 2 === 1 ? 'table-striped' : null) : this.rowClassName
|
||||
this.localSettings.rowClassName = evenClass
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="s-table-tool">
|
||||
<div className="s-table-tool-left">{this.$slots.operator && this.$slots.operator()}</div>
|
||||
<div className="layout-items-center s-table-tool-right">
|
||||
{this.toolConfig.striped ? (
|
||||
<div className="layout-items-center ml-4">
|
||||
<span>斑马线</span>
|
||||
<a-switch
|
||||
checked={this.localSettings.rowClassNameSwitch}
|
||||
onChange={changeRowClass}
|
||||
className="ml-2"
|
||||
/>
|
||||
<a-checkbox checked={this.localSettings.rowClassNameSwitch} onChange={changeRowClass}>
|
||||
斑马纹
|
||||
</a-checkbox>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
@ -430,7 +446,6 @@
|
||||
{tool.icon}
|
||||
</a-tooltip>
|
||||
)
|
||||
|
||||
if (tool.isPopover) {
|
||||
return (
|
||||
<a-popover
|
||||
|
67
snowy-admin-web/src/components/XnBatchButton/index.vue
Normal file
67
snowy-admin-web/src/components/XnBatchButton/index.vue
Normal file
@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<a-popconfirm
|
||||
title="批量处理此信息?"
|
||||
:visible="batchVisible"
|
||||
@visibleChange="batchVisibleChange"
|
||||
@confirm="deleteBatch"
|
||||
>
|
||||
<a-button :type="props.buttonType" :danger="props.buttonDanger">
|
||||
<template #icon v-if="props.icon">
|
||||
<component :is="props.icon" />
|
||||
</template>
|
||||
{{ props.buttonName }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
|
||||
<script setup name="commonBatchButton">
|
||||
import { message } from 'ant-design-vue'
|
||||
const batchVisible = ref(false)
|
||||
const emit = defineEmits({ batchCallBack: null })
|
||||
const props = defineProps({
|
||||
buttonName: {
|
||||
type: String,
|
||||
default: () => '批量操作'
|
||||
},
|
||||
buttonDanger: {
|
||||
type: Boolean,
|
||||
default: () => false
|
||||
},
|
||||
buttonType: {
|
||||
type: String,
|
||||
default: () => ''
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: () => ''
|
||||
},
|
||||
selectedRowKeys: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
// 参数校验
|
||||
const batchVisibleChange = () => {
|
||||
if (batchVisible.value) {
|
||||
batchVisible.value = false
|
||||
return false
|
||||
}
|
||||
if (props.selectedRowKeys.length < 1) {
|
||||
message.warning('请选择一条或多条数据')
|
||||
batchVisible.value = false
|
||||
return false
|
||||
} else {
|
||||
batchVisible.value = true
|
||||
}
|
||||
}
|
||||
// 批量操作
|
||||
const deleteBatch = () => {
|
||||
const params = props.selectedRowKeys.map((m) => {
|
||||
return {
|
||||
id: m
|
||||
}
|
||||
})
|
||||
// 发起方法调用,谁的谁来实现
|
||||
emit('batchCallBack', params)
|
||||
}
|
||||
</script>
|
53
snowy-admin-web/src/components/XnBatchDelete/index.vue
Normal file
53
snowy-admin-web/src/components/XnBatchDelete/index.vue
Normal file
@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<a-popconfirm
|
||||
title="删除此信息?"
|
||||
:visible="deleteVisible"
|
||||
@visibleChange="deleteVisibleChange"
|
||||
@confirm="deleteBatch"
|
||||
>
|
||||
<a-button danger>
|
||||
<template #icon><delete-outlined /></template>
|
||||
{{ props.buttonName }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
|
||||
<script setup name="commonBatchDelete">
|
||||
import { message } from 'ant-design-vue'
|
||||
const deleteVisible = ref(false)
|
||||
const emit = defineEmits({ batchDelete: null })
|
||||
const props = defineProps({
|
||||
buttonName: {
|
||||
type: String,
|
||||
default: () => '批量删除'
|
||||
},
|
||||
selectedRowKeys: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
// 参数校验
|
||||
const deleteVisibleChange = () => {
|
||||
if (deleteVisible.value) {
|
||||
deleteVisible.value = false
|
||||
return false
|
||||
}
|
||||
if (props.selectedRowKeys.length < 1) {
|
||||
message.warning('请选择一条或多条数据')
|
||||
deleteVisible.value = false
|
||||
return false
|
||||
} else {
|
||||
deleteVisible.value = true
|
||||
}
|
||||
}
|
||||
// 批量删除
|
||||
const deleteBatch = () => {
|
||||
const params = props.selectedRowKeys.map((m) => {
|
||||
return {
|
||||
id: m
|
||||
}
|
||||
})
|
||||
// 发起方法调用,谁的谁来实现
|
||||
emit('batchDelete', params)
|
||||
}
|
||||
</script>
|
88
snowy-admin-web/src/components/XnContextMenu/index.vue
Normal file
88
snowy-admin-web/src/components/XnContextMenu/index.vue
Normal file
@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<div :style="style" v-show="show" @mousedown.stop @contextmenu.prevent>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'XnContextMenu',
|
||||
props: {
|
||||
target: null,
|
||||
show: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
triggerShowFn: () => {},
|
||||
triggerHideFn: () => {},
|
||||
x: null,
|
||||
y: null,
|
||||
style: {},
|
||||
binded: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show(show) {
|
||||
if (show) {
|
||||
this.bindHideEvents()
|
||||
} else {
|
||||
this.unbindHideEvents()
|
||||
}
|
||||
},
|
||||
target(target) {
|
||||
this.bindEvents()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.bindEvents()
|
||||
},
|
||||
methods: {
|
||||
// 初始化事件
|
||||
bindEvents() {
|
||||
this.$nextTick(() => {
|
||||
if (!this.target || this.binded) return
|
||||
this.triggerShowFn = this.contextMenuHandler.bind(this)
|
||||
this.target.addEventListener('contextmenu', this.triggerShowFn)
|
||||
this.binded = true
|
||||
})
|
||||
},
|
||||
// 取消绑定事件
|
||||
unbindEvents() {
|
||||
if (!this.target) return
|
||||
this.target.removeEventListener('contextmenu', this.triggerShowFn)
|
||||
},
|
||||
// 绑定隐藏菜单事件
|
||||
bindHideEvents() {
|
||||
this.triggerHideFn = this.clickDocumentHandler.bind(this)
|
||||
document.addEventListener('mousedown', this.triggerHideFn)
|
||||
document.addEventListener('mousewheel', this.triggerHideFn)
|
||||
},
|
||||
// 取消绑定隐藏菜单事件
|
||||
unbindHideEvents() {
|
||||
document.removeEventListener('mousedown', this.triggerHideFn)
|
||||
document.removeEventListener('mousewheel', this.triggerHideFn)
|
||||
},
|
||||
// 鼠标按压事件处理器
|
||||
clickDocumentHandler(e) {
|
||||
this.$emit('update:show', false)
|
||||
},
|
||||
// 右键事件事件处理
|
||||
contextMenuHandler(e) {
|
||||
this.x = e.clientX
|
||||
this.y = e.clientY
|
||||
this.layout()
|
||||
this.$emit('update:show', true)
|
||||
this.$emit('get-context-menu', e)
|
||||
e.preventDefault()
|
||||
},
|
||||
// 布局
|
||||
layout() {
|
||||
this.style = {
|
||||
left: this.x + 'px',
|
||||
top: this.y + 'px',
|
||||
display: 'block'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
47
snowy-admin-web/src/components/XnFormContainer/index.vue
Normal file
47
snowy-admin-web/src/components/XnFormContainer/index.vue
Normal file
@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<a-modal v-if="isModal" :visible="visible" @cancel="cancel" v-bind="$attrs">
|
||||
<template v-for="slotKey in slotKeys" #[slotKey]>
|
||||
<slot :name="slotKey" />
|
||||
</template>
|
||||
</a-modal>
|
||||
<a-drawer v-else :visible="visible" v-bind="$attrs" :footer-style="{ textAlign: 'right' }">
|
||||
<template v-for="slotKey in slotKeys" #[slotKey]>
|
||||
<slot :name="slotKey" />
|
||||
</template>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'pinia'
|
||||
import { globalStore } from '@/store'
|
||||
|
||||
const FormContainerTypeEnum = {
|
||||
DRAWER: 'drawer',
|
||||
MODAL: 'modal'
|
||||
}
|
||||
export default {
|
||||
name: 'XnFormContainer',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(globalStore, ['formStyle']),
|
||||
slotKeys() {
|
||||
return Object.keys(this.$slots)
|
||||
},
|
||||
isModal() {
|
||||
return FormContainerTypeEnum.MODAL === this.formStyle
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
cancel() {
|
||||
this.$emit('close')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<!-- 本组件这兄弟写的很好 请参照:https://blog.csdn.net/weixin_41897680/article/details/124925222-->
|
||||
<div class="hljs-container" :codetype="props.language">
|
||||
<highlightjs :language="props.language" :autodetect="false" :code="props.code"></highlightjs>
|
||||
<highlightjs :language="props.language" :autodetect="!props.language" :code="props.code"></highlightjs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
const props = defineProps({
|
||||
language: {
|
||||
type: String,
|
||||
default: () => 'JavaScript'
|
||||
default: () => undefined
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
@ -54,7 +54,7 @@
|
||||
}*/
|
||||
|
||||
/** 滚动条 */
|
||||
/*:deep(.hljs,.hljs-container) {
|
||||
:deep(.hljs,.hljs-container) {
|
||||
max-height: 300px!important;
|
||||
overflow-x: auto;
|
||||
}
|
||||
@ -87,5 +87,5 @@
|
||||
|
||||
::-webkit-scrollbar-button {
|
||||
display: none;
|
||||
}*/
|
||||
}
|
||||
</style>
|
||||
|
@ -1,5 +1,12 @@
|
||||
<template>
|
||||
<a-modal ref="signModel" v-model:visible="visible" :width="600" title="电子签名" @cancel="handleClear" @ok="handleOk">
|
||||
<xn-form-container
|
||||
ref="signModel"
|
||||
v-model:visible="visible"
|
||||
:width="700"
|
||||
title="电子签名"
|
||||
@close="handleClear"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<a-row :gutter="5">
|
||||
<a-col :span="15">
|
||||
<div style="border: 1px solid rgb(236 236 236)">
|
||||
@ -40,7 +47,11 @@
|
||||
<a-button @click="handleReset">清屏</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-modal>
|
||||
<template #footer>
|
||||
<a-button style="margin-right: 8px" @click="handleClear">取消</a-button>
|
||||
<a-button type="primary" @click="handleOk">确定</a-button>
|
||||
</template>
|
||||
</xn-form-container>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
@ -36,6 +36,7 @@
|
||||
import tool from '@/utils/tool'
|
||||
import sysConfig from '@/config/index'
|
||||
const fileList = ref([])
|
||||
const emit = defineEmits({ uploadDone: null })
|
||||
const headers = ref({
|
||||
token: tool.data.get('TOKEN')
|
||||
})
|
||||
@ -45,12 +46,6 @@
|
||||
default: '/dev/file/uploadDynamicReturnUrl',
|
||||
required: false
|
||||
},
|
||||
// 允许多个
|
||||
allowMultiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: false
|
||||
},
|
||||
// 上传方式 defaults || drag
|
||||
uploadMode: {
|
||||
type: String,
|
||||
@ -66,22 +61,20 @@
|
||||
})
|
||||
const action = sysConfig.API_URL + props.action
|
||||
|
||||
const handleChange = () => {}
|
||||
|
||||
// 获取上传的内容
|
||||
const getUploadData = () => {
|
||||
return fileList.value.map((item) => {
|
||||
return {
|
||||
uid: item.uid,
|
||||
name: item.name,
|
||||
status: item.status,
|
||||
url: item.response.data
|
||||
const handleChange = () => {
|
||||
let result = []
|
||||
for (let a = 0; a < props.uploadMumber; a++) {
|
||||
const file = fileList.value[a]
|
||||
if (file.status === 'done' && file.response && file.response.code === 200) {
|
||||
const resultObj = {
|
||||
name: file.name,
|
||||
url: file.response.data
|
||||
}
|
||||
result.push(resultObj)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (result.length > 0) {
|
||||
emit('uploadDone', result)
|
||||
}
|
||||
}
|
||||
defineExpose({
|
||||
getUploadData
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -27,19 +27,6 @@ body {
|
||||
margin: 24px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ant-table-wrapper
|
||||
* 覆盖的表格手机模式样式,如果想修改在手机上表格最低宽度,可以在这里改动
|
||||
*/
|
||||
.ant-table-wrapper {
|
||||
.ant-table-content {
|
||||
overflow-y: auto;
|
||||
}
|
||||
.ant-table-body {
|
||||
min-width: 800px;
|
||||
}
|
||||
}
|
||||
.topmenu {
|
||||
/* 必须为 topmenu 才能启用流式布局 */
|
||||
&.content-width-Fluid {
|
||||
|
@ -16,7 +16,7 @@ const DEFAULT_CONFIG = {
|
||||
API_URL: import.meta.env.VITE_API_BASEURL,
|
||||
|
||||
// 请求超时
|
||||
TIMEOUT: 10000,
|
||||
TIMEOUT: 60000,
|
||||
|
||||
// TokenName // Authorization
|
||||
TOKEN_NAME: 'token',
|
||||
@ -36,7 +36,7 @@ const DEFAULT_CONFIG = {
|
||||
// 菜单是否折叠
|
||||
SNOWY_MENU_COLLAPSE: false,
|
||||
|
||||
// 目录坞
|
||||
// 模块坞
|
||||
SNOWY_MODULE_UNFOLD_OPEN: true,
|
||||
|
||||
// 是否开启多标签
|
||||
@ -63,10 +63,15 @@ const DEFAULT_CONFIG = {
|
||||
// 默认整体主题
|
||||
SNOWY_THEME: 'dark',
|
||||
|
||||
// 整体表单风格
|
||||
SNOWY_FORM_STYLE: 'drawer',
|
||||
|
||||
// 成功色
|
||||
success: '#52c41a',
|
||||
|
||||
// 警告色
|
||||
warning: '#faad14',
|
||||
|
||||
// 错误色
|
||||
error: '#f5222f',
|
||||
|
||||
|
@ -1,18 +1,8 @@
|
||||
/* eslint-disable eqeqeq */
|
||||
<!--
|
||||
* @Descripttion: 处理iframe持久化,涉及store(VUEX)
|
||||
* @version: 1.0
|
||||
* @Author: sakuya
|
||||
* @Date: 2021年6月30日13:20:41
|
||||
* @LastEditors:
|
||||
* @LastEditTime:
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div v-show="$route.meta.type == 'iframe'" class="iframe-pages">
|
||||
<div v-show="$route.meta.type === 'iframe'" class="iframe-pages">
|
||||
<iframe
|
||||
v-for="item in iframeList"
|
||||
v-show="$route.meta.url == item.meta.url"
|
||||
v-show="$route.meta.url === item.meta.url"
|
||||
:key="item.meta.url"
|
||||
:src="item.meta.url"
|
||||
frameborder="0"
|
||||
@ -21,20 +11,16 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapActions } from 'pinia'
|
||||
import { iframeStore, globalStore } from '@/store'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
iframeList() {
|
||||
return this.$store.state.iframe.iframeList
|
||||
},
|
||||
ismobile() {
|
||||
return this.$store.state.global.ismobile
|
||||
},
|
||||
layoutTags() {
|
||||
return this.$store.state.global.layoutTags
|
||||
}
|
||||
...mapState(iframeStore, ['iframeList']),
|
||||
...mapState(globalStore, ['ismobile', 'layoutTags'])
|
||||
},
|
||||
watch: {
|
||||
$route(e) {
|
||||
@ -46,16 +32,16 @@
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
...mapActions(iframeStore, ['setIframeList', 'pushIframeList', 'clearIframeList']),
|
||||
push(route) {
|
||||
// eslint-disable-next-line eqeqeq
|
||||
if (route.meta.type == 'iframe') {
|
||||
if (route.meta.type === 'iframe') {
|
||||
if (this.ismobile || !this.layoutTags) {
|
||||
this.$store.commit('setIframeList', route)
|
||||
this.setIframeList(route)
|
||||
} else {
|
||||
this.$store.commit('pushIframeList', route)
|
||||
this.pushIframeList(route)
|
||||
}
|
||||
} else if (this.ismobile || !this.layoutTags) {
|
||||
this.$store.commit('clearIframeList')
|
||||
this.clearIframeList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
58
snowy-admin-web/src/layout/components/mixins/search.js
Executable file
58
snowy-admin-web/src/layout/components/mixins/search.js
Executable file
@ -0,0 +1,58 @@
|
||||
import { mapState, mapActions } from 'pinia'
|
||||
import hotkeys from 'hotkeys-js'
|
||||
import { searchStore } from '@/store'
|
||||
|
||||
export default {
|
||||
mounted() {
|
||||
// 绑定搜索功能快捷键 [ 打开 ]
|
||||
hotkeys(this.searchHotkey.open, (event) => {
|
||||
event.preventDefault()
|
||||
this.searchPanelOpen()
|
||||
})
|
||||
// 绑定搜索功能快捷键 [ 关闭 ]
|
||||
hotkeys(this.searchHotkey.close, (event) => {
|
||||
event.preventDefault()
|
||||
this.searchPanelClose()
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
hotkeys.unbind(this.searchHotkey.open)
|
||||
hotkeys.unbind(this.searchHotkey.close)
|
||||
},
|
||||
computed: {
|
||||
...mapState(searchStore, {
|
||||
searchActive: (state) => state.active,
|
||||
searchHotkey: (state) => state.hotkey
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
...mapActions(searchStore, ['toggleActive', 'setActive']),
|
||||
// 接收点击搜索按钮
|
||||
handleSearchClick() {
|
||||
this.toggleActive()
|
||||
if (this.searchActive) {
|
||||
setTimeout(() => {
|
||||
if (this.$refs.panelSearch) {
|
||||
this.$refs.panelSearch.focus()
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
},
|
||||
searchPanelOpen() {
|
||||
if (!this.searchActive) {
|
||||
this.setActive(true)
|
||||
setTimeout(() => {
|
||||
if (this.$refs.panelSearch) {
|
||||
this.$refs.panelSearch.focus()
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
},
|
||||
// 关闭搜索面板
|
||||
searchPanelClose() {
|
||||
if (this.searchActive) {
|
||||
this.setActive(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +1,27 @@
|
||||
<template>
|
||||
<div v-if="moduleUnfoldOpen">
|
||||
<a-menu v-model:selectedKeys="selectedKeys" mode="horizontal" v-if="menu && menu.length > 1" class="module-menu" id="moduleMunu">
|
||||
<a-menu-item v-for="item in menu" :key="item.id" style="padding-right: 5px" @click="moduleClick(item.id)">
|
||||
<div class="layout-items-center" v-if="moduleUnfoldOpen">
|
||||
<a-menu
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
mode="horizontal"
|
||||
v-if="menu && menu.length > 1"
|
||||
class="module-menu"
|
||||
id="moduleMunu"
|
||||
>
|
||||
<a-menu-item
|
||||
v-for="item in menu"
|
||||
:key="item.id"
|
||||
class="!px-3"
|
||||
style="position: relative"
|
||||
@click="moduleClick(item.id)"
|
||||
>
|
||||
<template #icon>
|
||||
<component :is="item.meta.icon"/>
|
||||
<component :is="item.meta.icon" />
|
||||
</template>
|
||||
<span style="margin-left:-5px">{{ item.meta.title }}</span>
|
||||
<span style="margin-left: -5px">{{ item.meta.title }}</span>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-else class="panel-item hidden-sm-and-down">
|
||||
<a-popover v-if="menu.length > 1" placement="bottomLeft">
|
||||
<template #content>
|
||||
<a-row :gutter="[0, 5]" class="module-row">
|
||||
@ -23,9 +35,7 @@
|
||||
</div>
|
||||
</a-row>
|
||||
</template>
|
||||
<div class="module-comp">
|
||||
<appstore-outlined />
|
||||
</div>
|
||||
<appstore-outlined />
|
||||
</a-popover>
|
||||
</div>
|
||||
</template>
|
||||
@ -33,18 +43,23 @@
|
||||
<script setup>
|
||||
import router from '@/router'
|
||||
import tool from '@/utils/tool'
|
||||
import store from '@/store'
|
||||
import { globalStore } from '@/store'
|
||||
import { watch } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const store = globalStore()
|
||||
|
||||
const { moduleUnfoldOpen, topHanderThemeColorOpen } = storeToRefs(store)
|
||||
const moduleBackColor = ref(topHanderThemeColorOpen)
|
||||
|
||||
// 监听目录是否折叠
|
||||
watch(() => store.state.global.moduleUnfoldOpen, (newValue) => {
|
||||
moduleUnfoldOpen.value = newValue
|
||||
watch(moduleUnfoldOpen, (newValue) => {
|
||||
nextTick(() => {
|
||||
setModuleBackColor()
|
||||
})
|
||||
})
|
||||
// 监听是否开启了顶栏颜色
|
||||
watch(() => store.state.global.topHanderThemeColorOpen, (newValue) => {
|
||||
watch(topHanderThemeColorOpen, (newValue) => {
|
||||
moduleBackColor.value = newValue
|
||||
setModuleBackColor()
|
||||
})
|
||||
@ -60,26 +75,27 @@
|
||||
})
|
||||
}
|
||||
|
||||
const moduleUnfoldOpen = ref(store.state.global.moduleUnfoldOpen)
|
||||
const moduleBackColor = ref(store.state.global.topHanderThemeColorOpen)
|
||||
|
||||
onMounted(() => {
|
||||
setModuleBackColor()
|
||||
})
|
||||
// 设置背景色
|
||||
const setModuleBackColor = () => {
|
||||
if (moduleUnfoldOpen.value) {
|
||||
const moduleMunu = document.getElementById('moduleMunu')
|
||||
moduleBackColor.value? moduleMunu.classList.add('module-menu-color')
|
||||
: moduleMunu.classList.remove('module-menu-color')
|
||||
try {
|
||||
const moduleMunu = document.getElementById('moduleMunu')
|
||||
moduleBackColor.value
|
||||
? moduleMunu.classList.add('module-menu-color')
|
||||
: moduleMunu.classList.remove('module-menu-color')
|
||||
} catch (err) {}
|
||||
setSelectedKeys()
|
||||
}
|
||||
}
|
||||
// 设置选中
|
||||
const setSelectedKeys = () => {
|
||||
// 顶部应用列表让显示出来默认的,不这么实现不会显示的,相信老俞
|
||||
moduleBackColor.value? selectedKeys.value = new Array([])
|
||||
: selectedKeys.value = [tool.data.get('SNOWY_MENU_MODULE_ID')]
|
||||
moduleBackColor.value
|
||||
? (selectedKeys.value = new Array([]))
|
||||
: (selectedKeys.value = [tool.data.get('SNOWY_MENU_MODULE_ID')])
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -99,32 +115,23 @@
|
||||
.module-card-icon {
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
padding-top: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.module-card-font {
|
||||
color: white;
|
||||
font-size: 8px;
|
||||
}
|
||||
.module-comp {
|
||||
display: flex;
|
||||
padding: 0 15px;
|
||||
height: 49px;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.module-comp:hover {
|
||||
background: var(--header-color-split);
|
||||
}
|
||||
.ant-menu-horizontal > .ant-menu-item::after, .ant-menu-horizontal > .ant-menu-submenu::after {
|
||||
.ant-menu-horizontal > .ant-menu-item::after,
|
||||
.ant-menu-horizontal > .ant-menu-submenu::after {
|
||||
content: none;
|
||||
}
|
||||
.module-menu{
|
||||
.module-menu {
|
||||
line-height: 50px;
|
||||
border-bottom: 0px
|
||||
border-bottom: 0px;
|
||||
width: 105%;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.module-menu-color{
|
||||
.module-menu-color {
|
||||
color: white;
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
|
275
snowy-admin-web/src/layout/components/panel-search/index.vue
Normal file
275
snowy-admin-web/src/layout/components/panel-search/index.vue
Normal file
@ -0,0 +1,275 @@
|
||||
<template>
|
||||
<div @keyup.up="handleKeyUp" @keyup.down="handleKeyDown" @keyup.enter="handleKeyEnter" @click.self="handlePanelClick">
|
||||
<a-input
|
||||
ref="input"
|
||||
v-model="searchText"
|
||||
class="search-box"
|
||||
style="width: 100%"
|
||||
allowClear
|
||||
placeholder="搜索页面(支持拼音检索)"
|
||||
@change="querySearch"
|
||||
>
|
||||
<template #prefix>
|
||||
<search-outlined />
|
||||
</template>
|
||||
</a-input>
|
||||
<a-card
|
||||
:body-style="{ padding: '0 0' }"
|
||||
hoverable
|
||||
@mouseenter="onCardIn"
|
||||
@mouseleave="onCardOut"
|
||||
@keypress.up="handleKeyUp"
|
||||
@keypress.down="handleKeyDown"
|
||||
style="margin: 10px 0"
|
||||
>
|
||||
<div ref="cardList" class="search-card beauty-scroll">
|
||||
<a-list size="small" :data-source="resultsList">
|
||||
<template #renderItem="{ item, index }">
|
||||
<a-list-item
|
||||
@click="handleSelect(item.fullPath)"
|
||||
@mouseover="onCardItemHover(index)"
|
||||
:class="{ active: index === cardIndex }"
|
||||
style="padding-right: 10px"
|
||||
>
|
||||
<template #actions>
|
||||
<a>
|
||||
<enter-outlined />
|
||||
</a>
|
||||
</template>
|
||||
<a-list-item-meta :description="item.fullName">
|
||||
<template #title>
|
||||
<a>{{ item.name }}</a>
|
||||
</template>
|
||||
<template #avatar>
|
||||
<a-avatar style="color: var(--text-color); background-color: transparent" :type="item.icon">
|
||||
<template #icon>
|
||||
<component :is="item.icon" />
|
||||
</template>
|
||||
</a-avatar>
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
</div>
|
||||
</a-card>
|
||||
<div class="search-tips">
|
||||
<span class="key">S</span>
|
||||
<span class="tips">打开搜索面板</span>
|
||||
|
||||
<span class="key">
|
||||
<arrow-up-outlined />
|
||||
</span>
|
||||
<span class="key">
|
||||
<arrow-down-outlined />
|
||||
</span>
|
||||
<span class="tips">选择</span>
|
||||
|
||||
<span class="key">
|
||||
<enter-outlined />
|
||||
</span>
|
||||
<span class="tips">确认</span>
|
||||
|
||||
<span class="key left">Esc</span>
|
||||
<span class="tips">关闭</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Fuse from 'fuse.js'
|
||||
import { mapState } from 'pinia'
|
||||
import { searchStore } from '@/store'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
searchText: '',
|
||||
cardIndex: 0,
|
||||
results: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(searchStore, ['pool']),
|
||||
// 这份数据是展示在搜索面板下面的
|
||||
resultsList() {
|
||||
return this.results.length === 0 || this.searchText === '' ? this.pool : this.results
|
||||
},
|
||||
// 根据 pool 更新 fuse 实例
|
||||
fuse() {
|
||||
return new Fuse(this.pool, {
|
||||
shouldSort: true, // 按分数对结果列表进行排序
|
||||
threshold: 0.6, // 什么时候放弃
|
||||
location: 0, // 大致位置
|
||||
distance: 100, // 接近程度
|
||||
minMatchCharLength: 1, // 匹配长度
|
||||
keys: ['name', 'namePinyin', 'namePinyinFirst']
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 过滤选项 这个方法在每次输入框的值发生变化时会触发
|
||||
querySearch(e) {
|
||||
let queryString = e.target.value || ''
|
||||
const results = queryString && this.fuse.search(queryString).map((e) => e.item)
|
||||
this.searchText = queryString
|
||||
this.results = results
|
||||
},
|
||||
// 聚焦输入框
|
||||
focus() {
|
||||
this.searchText = ''
|
||||
setTimeout(() => {
|
||||
if (this.$refs.input) {
|
||||
this.$refs.input.focus()
|
||||
}
|
||||
// 还原
|
||||
this.searchText = ''
|
||||
this.results = []
|
||||
}, 300)
|
||||
},
|
||||
handleKeyEnter() {
|
||||
let idx = this.cardIndex
|
||||
if (this.resultsList[idx]) {
|
||||
this.handleSelect(this.resultsList[idx].fullPath)
|
||||
}
|
||||
},
|
||||
handleKeyUp() {
|
||||
this.handleKeyUpOrDown(true)
|
||||
},
|
||||
handleKeyDown() {
|
||||
this.handleKeyUpOrDown(false)
|
||||
},
|
||||
handleKeyUpOrDown(up) {
|
||||
let len = this.resultsList.length - 1
|
||||
let idx = this.cardIndex
|
||||
if (up) {
|
||||
// 上
|
||||
if (idx > 0) {
|
||||
idx--
|
||||
} else {
|
||||
idx = len
|
||||
}
|
||||
} else {
|
||||
// 下
|
||||
if (idx < len) {
|
||||
idx++
|
||||
} else {
|
||||
idx = 0
|
||||
}
|
||||
}
|
||||
this.cardIndex = idx
|
||||
if (this.$refs.cardList.getElementsByClassName('ant-list-item')[idx]) {
|
||||
this.$refs.cardList.scrollTop = this.$refs.cardList.getElementsByClassName('ant-list-item')[idx].offsetTop
|
||||
} else {
|
||||
this.$refs.cardList.scrollTop = 0
|
||||
}
|
||||
},
|
||||
onCardIn() {
|
||||
this.$refs.input.activated = false
|
||||
this.$refs.input.blur()
|
||||
},
|
||||
onCardOut() {
|
||||
this.cardIndex = -1
|
||||
},
|
||||
onCardItemHover(index) {
|
||||
this.cardIndex = index
|
||||
},
|
||||
// 接收用户在下拉菜单中选中事件
|
||||
handleSelect(path) {
|
||||
// 如果用户选择的就是当前页面 就直接关闭搜索面板
|
||||
if (path === this.$route.path) {
|
||||
this.handleEsc()
|
||||
return
|
||||
}
|
||||
this.$router.push({ path })
|
||||
this.handleEsc()
|
||||
},
|
||||
// 关闭输入框的下拉菜单
|
||||
closeSuggestion() {
|
||||
if (this.$refs.input.activated) {
|
||||
this.results = []
|
||||
this.$refs.input.activated = false
|
||||
}
|
||||
},
|
||||
// 接收用户点击空白区域的关闭
|
||||
handlePanelClick(e) {
|
||||
if ('INPUT' !== e.target.tagName) {
|
||||
this.handleEsc()
|
||||
}
|
||||
},
|
||||
// 接收用户触发的关闭
|
||||
async handleEsc() {
|
||||
this.closeSuggestion()
|
||||
await this.$nextTick()
|
||||
this.$emit('close')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
:deep(.ant-input) {
|
||||
height: 35px;
|
||||
}
|
||||
:deep(.ant-input:not(:first-child)) {
|
||||
padding-left: 10px;
|
||||
}
|
||||
:deep(.ant-input-prefix) {
|
||||
font-size: 20px;
|
||||
}
|
||||
:deep(.ant-list-sm .ant-list-item) {
|
||||
padding: 4px 16px;
|
||||
}
|
||||
:deep(.ant-list-item-meta) {
|
||||
align-items: center;
|
||||
}
|
||||
:deep(.ant-list-item.active) {
|
||||
background-color: var(--primary-1);
|
||||
}
|
||||
.search-box {
|
||||
width: 100%;
|
||||
}
|
||||
.beauty-scroll {
|
||||
scrollbar-color: var(--primary-color) var(--primary-2);
|
||||
scrollbar-width: thin;
|
||||
-ms-overflow-style: none;
|
||||
position: relative;
|
||||
&::-webkit-scrollbar {
|
||||
width: 3px;
|
||||
height: 1px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 3px;
|
||||
background: var(--primary-color);
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
-webkit-box-shadow: inset 0 0 1px rgba(0, 0, 0, 0);
|
||||
border-radius: 3px;
|
||||
background: var(--primary-3);
|
||||
}
|
||||
}
|
||||
.search-card {
|
||||
height: 220px;
|
||||
overflow: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.search-tips {
|
||||
display: flex;
|
||||
border-top: 1px solid var(--component-background);
|
||||
padding-top: 10px;
|
||||
.tips {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.key {
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
padding-bottom: 2px;
|
||||
margin: 0px 4px;
|
||||
border-radius: 2px;
|
||||
box-shadow: inset 0 -2px #cdcde6, inset 0 0 1px 1px #fff, 0 1px 2px 1px #1e235a66;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
102
snowy-admin-web/src/layout/components/panel-search/item.vue
Executable file
102
snowy-admin-web/src/layout/components/panel-search/item.vue
Executable file
@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<div class="d2-panel-search-item" :class="hoverMode ? 'can-hover' : ''" flex>
|
||||
<div class="d2-panel-search-item__icon" flex-box="0">
|
||||
<div class="d2-panel-search-item__icon-box" flex="main:center cross:center">
|
||||
<a-icon v-if="item.icon" :type="item.icon" />
|
||||
<a-icon v-else type="menu" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="d2-panel-search-item__info" flex-box="1" flex="dir:top">
|
||||
<div class="d2-panel-search-item__info-title" flex-box="1" flex="cross:center">
|
||||
<span>{{ item.title }}</span>
|
||||
</div>
|
||||
<div class="d2-panel-search-item__info-fullTitle" flex-box="0">
|
||||
<span>{{ item.fullTitle }}</span>
|
||||
</div>
|
||||
<div class="d2-panel-search-item__info-path" flex-box="0">
|
||||
<span>{{ item.path }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
item: {
|
||||
default: () => ({})
|
||||
},
|
||||
hoverMode: {
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.d2-panel-search-item {
|
||||
height: 64px;
|
||||
margin: 0px -20px;
|
||||
&.can-hover {
|
||||
margin: 0px;
|
||||
&:hover {
|
||||
background-color: #f5f7fa;
|
||||
.d2-panel-search-item__icon {
|
||||
.d2-panel-search-item__icon-box {
|
||||
i {
|
||||
font-size: 24px;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
.d2-panel-search-item__info {
|
||||
.d2-panel-search-item__info-title {
|
||||
//color: $color-text-main;
|
||||
}
|
||||
.d2-panel-search-item__info-fullTitle {
|
||||
//color: $color-text-normal;
|
||||
}
|
||||
.d2-panel-search-item__info-path {
|
||||
//color: $color-text-normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.d2-panel-search-item__icon {
|
||||
width: 64px;
|
||||
.d2-panel-search-item__icon-box {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
border-right: 1px solid #ccc;
|
||||
i {
|
||||
font-size: 20px;
|
||||
//color: $color-text-sub;
|
||||
}
|
||||
svg {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.d2-panel-search-item__info {
|
||||
margin-left: 10px;
|
||||
.d2-panel-search-item__info-title {
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
font-weight: bold;
|
||||
//color: $color-text-normal;
|
||||
}
|
||||
.d2-panel-search-item__info-fullTitle {
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
color: grey;
|
||||
}
|
||||
.d2-panel-search-item__info-path {
|
||||
margin-bottom: 4px;
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
color: grey;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -4,20 +4,21 @@
|
||||
<h3>整体风格设置</h3>
|
||||
<div class="snowy-setting-checkbox">
|
||||
<a-tooltip v-for="(a, i) in sideStyleList" :key="i" placement="top">
|
||||
<template #title
|
||||
><span>{{ a.tips }}</span></template
|
||||
>
|
||||
<template #title>
|
||||
<span>{{ a.tips }}</span>
|
||||
</template>
|
||||
<div :class="['snowy-setting-checkbox-item', a.style]" @click="setSideStyle(a.value)">
|
||||
<check-outlined v-if="sideStyle === a.value" class="snowy-setting-checkbox-item-select-icon" />
|
||||
<check-outlined v-if="theme === a.value" class="snowy-setting-checkbox-item-select-icon" />
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<h3>整体界面布局</h3>
|
||||
<div class="snowy-setting-checkbox">
|
||||
<a-tooltip v-for="(a, i) in layoutList" :key="i" placement="top">
|
||||
<template #title
|
||||
><span>{{ a.tips }}</span></template
|
||||
>
|
||||
<template #title>
|
||||
<span>{{ a.tips }}</span>
|
||||
</template>
|
||||
|
||||
<div :class="['snowy-setting-checkbox-item', a.style]" @click="layoutStyle(a.value)">
|
||||
<div class="snowy-setting-layout-menu-doublerow-inner" />
|
||||
<check-outlined v-if="layout === a.value" class="snowy-setting-checkbox-item-select-icon" />
|
||||
@ -25,9 +26,9 @@
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<a-divider />
|
||||
<div :style="{ marginBottom: '24px' }">
|
||||
<div class="mb-4">
|
||||
<h3>主题色</h3>
|
||||
<div style="height: 50px">
|
||||
<div class="h-[50px]">
|
||||
<a-tooltip v-for="(item, index) in colorList" :key="index" class="snowy-setting-theme-color-colorBlock">
|
||||
<template #title>
|
||||
<span>{{ item.key }}</span>
|
||||
@ -38,37 +39,44 @@
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div :style="{ marginBottom: '24px' }">
|
||||
<span
|
||||
><h4>顶栏应用主题色:<a-switch style="float: right" v-model:checked="topHanderThemeColorOpen" /></h4
|
||||
></span>
|
||||
<div class="mb-4 layout-slide">
|
||||
<h4 class="">顶栏应用主题色:</h4>
|
||||
<a-switch :checked="topHanderThemeColorOpen" @change="changeTopHanderThemeColorOpen" />
|
||||
</div>
|
||||
<div :style="{ marginBottom: '24px' }">
|
||||
<span
|
||||
><h4>
|
||||
顶栏主题色通栏:<a-switch
|
||||
style="float: right"
|
||||
v-model:checked="topHanderThemeColorSpread"
|
||||
:disabled="!topHanderThemeColorOpen"
|
||||
/></h4
|
||||
></span>
|
||||
<div class="mb-4 layout-slide">
|
||||
<h4>顶栏主题色通栏:</h4>
|
||||
<a-switch
|
||||
style="float: right"
|
||||
:checked="topHanderThemeColorSpread"
|
||||
:disabled="!topHanderThemeColorOpen"
|
||||
@change="changeTopHanderThemeColorSpread"
|
||||
/>
|
||||
</div>
|
||||
<a-divider />
|
||||
<a-form ref="form" style="text-align: right">
|
||||
<a-form-item label="目录坞">
|
||||
<a-switch v-model:checked="moduleUnfoldOpen" />
|
||||
<a-form ref="form" class="text-right">
|
||||
<a-form-item label="模块坞">
|
||||
<a-switch :checked="moduleUnfoldOpen" @change="toggleState('moduleUnfoldOpen')" />
|
||||
</a-form-item>
|
||||
<a-form-item label="面包屑">
|
||||
<a-switch v-model:checked="breadcrumbOpen" />
|
||||
<a-switch :checked="breadcrumbOpen" @change="toggleState('breadcrumbOpen')" />
|
||||
</a-form-item>
|
||||
<a-form-item label="多标签">
|
||||
<a-switch v-model:checked="layoutTagsOpen" />
|
||||
<a-switch :checked="layoutTagsOpen" @change="toggleState('layoutTagsOpen')" />
|
||||
</a-form-item>
|
||||
<a-form-item label="折叠菜单">
|
||||
<a-switch v-model:checked="menuIsCollapse" />
|
||||
<a-switch :checked="menuIsCollapse" @change="toggleState('menuIsCollapse')" />
|
||||
</a-form-item>
|
||||
<a-form-item label="菜单排他展开">
|
||||
<a-switch v-model:checked="sideUniqueOpen" />
|
||||
<a-switch :checked="sideUniqueOpen" @change="toggleState('sideUniqueOpen')" />
|
||||
</a-form-item>
|
||||
<a-form-item label="表单风格">
|
||||
<a-select
|
||||
:value="formStyle"
|
||||
class="!w-[80px]"
|
||||
size="small"
|
||||
:options="xnFormStyleOptions"
|
||||
@change="formStyleChange"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<a-alert
|
||||
@ -80,14 +88,24 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { colorList } from '../../config/settingConfig'
|
||||
import { ThemeModeEnum } from '../../utils/enum'
|
||||
import { colorList } from '@/config/settingConfig'
|
||||
import { ThemeModeEnum } from '@/utils/enum'
|
||||
import { globalStore } from '@/store'
|
||||
import { mapState, mapStores } from 'pinia'
|
||||
import tool from '@/utils/tool'
|
||||
|
||||
const toolDataNameMap = {
|
||||
menuIsCollapse: 'MENU_COLLAPSE',
|
||||
sideUniqueOpen: 'SIDE_UNIQUE_OPEN',
|
||||
layoutTagsOpen: 'LAYOUT_TAGS_OPEN',
|
||||
breadcrumbOpen: 'BREADCRUMD_OPEN',
|
||||
topHanderThemeColorOpen: 'TOP_HANDER_THEME_COLOR_OPEN',
|
||||
topHanderThemeColorSpread: 'TOP_HANDER_THEME_COLOR_SPREAD',
|
||||
moduleUnfoldOpen: 'MODULE_UNFOLD_OPEN'
|
||||
}
|
||||
export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
// 整体风格
|
||||
sideStyle: this.$TOOL.data.get('SNOWY_THEME') || this.$store.state.global.theme,
|
||||
sideStyleList: [
|
||||
{
|
||||
tips: '暗色主题风格',
|
||||
@ -105,7 +123,6 @@
|
||||
style: 'snowy-setting-checkbox-item-realdark'
|
||||
}
|
||||
],
|
||||
layout: this.$TOOL.data.get('SNOWY_LAYOUT') || this.$store.state.global.layout,
|
||||
layoutList: [
|
||||
{
|
||||
tips: '经典',
|
||||
@ -118,100 +135,71 @@
|
||||
style: 'snowy-setting-layout-menu-doublerow'
|
||||
}
|
||||
],
|
||||
topHanderThemeColorOpen:
|
||||
this.$TOOL.data.get('SNOWY_TOP_HANDER_THEME_COLOR_OPEN') || this.$store.state.global.topHanderThemeColorOpen,
|
||||
topHanderThemeColorSpread:
|
||||
this.$TOOL.data.get('SNOWY_TOP_HANDER_THEME_COLOR_SPREAD') ||
|
||||
this.$store.state.global.topHanderThemeColorSpread,
|
||||
menuIsCollapse: this.$TOOL.data.get('SNOWY_MENU_COLLAPSE') || this.$store.state.global.menuIsCollapse,
|
||||
sideUniqueOpen: this.$TOOL.data.get('SNOWY_SIDE_UNIQUE_OPEN') || this.$store.state.global.sideUniqueOpen,
|
||||
layoutTagsOpen: this.$TOOL.data.get('SNOWY_LAYOUT_TAGS_OPEN') || this.$store.state.global.layoutTagsOpen,
|
||||
breadcrumbOpen: this.$TOOL.data.get('SNOWY_BREADCRUMD_OPEN') || this.$store.state.global.breadcrumbOpen,
|
||||
moduleUnfoldOpen: this.$TOOL.data.get('SNOWY_MODULE_UNFOLD_OPEN') || this.$store.state.global.moduleUnfoldOpen,
|
||||
theme: this.$TOOL.data.get('APP_THEME') || this.$store.state.global.theme,
|
||||
themeColor: this.$TOOL.data.get('SNOWY_THEME_COLOR') || this.$store.state.global.themeColor,
|
||||
xnFormStyleOptions: [
|
||||
{
|
||||
label: '抽屉',
|
||||
value: 'drawer'
|
||||
},
|
||||
{
|
||||
label: '对话框',
|
||||
value: 'modal'
|
||||
}
|
||||
],
|
||||
colorList
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
menuIsCollapse() {
|
||||
this.$store.commit('TOGGLE_menuIsCollapse')
|
||||
if (this.$store.state.global.menuIsCollapse) {
|
||||
this.$TOOL.data.set('SNOWY_MENU_COLLAPSE', true)
|
||||
} else {
|
||||
this.$TOOL.data.set('SNOWY_MENU_COLLAPSE', false)
|
||||
}
|
||||
},
|
||||
sideUniqueOpen() {
|
||||
this.$store.commit('TOGGLE_sideUniqueOpen')
|
||||
if (this.$store.state.global.sideUniqueOpen) {
|
||||
this.$TOOL.data.set('SNOWY_SIDE_UNIQUE_OPEN', true)
|
||||
} else {
|
||||
this.$TOOL.data.set('SNOWY_SIDE_UNIQUE_OPEN', false)
|
||||
}
|
||||
},
|
||||
layoutTagsOpen() {
|
||||
this.$store.commit('TOGGLE_layoutTagsOpen')
|
||||
if (this.$store.state.global.layoutTagsOpen) {
|
||||
this.$TOOL.data.set('SNOWY_LAYOUT_TAGS_OPEN', true)
|
||||
} else {
|
||||
this.$TOOL.data.set('SNOWY_LAYOUT_TAGS_OPEN', false)
|
||||
}
|
||||
},
|
||||
breadcrumbOpen() {
|
||||
this.$store.commit('TOGGLE_breadcrumbOpen')
|
||||
if (this.$store.state.global.breadcrumbOpen) {
|
||||
this.$TOOL.data.set('SNOWY_BREADCRUMD_OPEN', true)
|
||||
} else {
|
||||
this.$TOOL.data.set('SNOWY_BREADCRUMD_OPEN', false)
|
||||
}
|
||||
},
|
||||
topHanderThemeColorOpen() {
|
||||
this.$store.commit('TOGGLE_topHanderThemeColorOpen')
|
||||
if (this.$store.state.global.topHanderThemeColorOpen) {
|
||||
this.$TOOL.data.set('SNOWY_TOP_HANDER_THEME_COLOR_OPEN', true)
|
||||
} else {
|
||||
// 关闭顶栏主题色
|
||||
this.$TOOL.data.set('SNOWY_TOP_HANDER_THEME_COLOR_OPEN', false)
|
||||
// 这个时候我们吧通栏的设置也给搞为false
|
||||
this.topHanderThemeColorSpread = false
|
||||
}
|
||||
},
|
||||
topHanderThemeColorSpread() {
|
||||
this.$store.commit('TOGGLE_topHanderThemeColorSpread')
|
||||
if (this.$store.state.global.topHanderThemeColorSpread) {
|
||||
this.$TOOL.data.set('SNOWY_TOP_HANDER_THEME_COLOR_SPREAD', true)
|
||||
} else {
|
||||
this.$TOOL.data.set('SNOWY_TOP_HANDER_THEME_COLOR_SPREAD', false)
|
||||
}
|
||||
},
|
||||
moduleUnfoldOpen() {
|
||||
this.$store.commit('TOGGLE_moduleUnfoldOpen')
|
||||
if (this.$store.state.global.moduleUnfoldOpen) {
|
||||
this.$TOOL.data.set('SNOWY_MODULE_UNFOLD_OPEN', true)
|
||||
} else {
|
||||
this.$TOOL.data.set('SNOWY_MODULE_UNFOLD_OPEN', false)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapStores(globalStore),
|
||||
...mapState(globalStore, [
|
||||
'theme',
|
||||
'themeColor',
|
||||
'layout',
|
||||
'menuIsCollapse',
|
||||
'sideUniqueOpen',
|
||||
'layoutTagsOpen',
|
||||
'breadcrumbOpen',
|
||||
'moduleUnfoldOpen',
|
||||
'topHanderThemeColorOpen',
|
||||
'topHanderThemeColorSpread',
|
||||
'formStyle'
|
||||
])
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
changeTopHanderThemeColorOpen() {
|
||||
this.toggleState('topHanderThemeColorOpen')
|
||||
if (!this.topHanderThemeColorOpen) {
|
||||
this.globalStore.topHanderThemeColorSpread = false
|
||||
tool.data.set('SNOWY_TOP_HANDER_THEME_COLOR_SPREAD', false)
|
||||
}
|
||||
},
|
||||
changeTopHanderThemeColorSpread() {
|
||||
this.toggleState('topHanderThemeColorSpread')
|
||||
},
|
||||
toggleState(stateName) {
|
||||
this.globalStore.toggleConfig(stateName)
|
||||
const toolDataName = toolDataNameMap[stateName]
|
||||
tool.data.set(`SNOWY_${toolDataName}`, this.globalStore[stateName])
|
||||
},
|
||||
// 设置整体风格主题
|
||||
setSideStyle(value) {
|
||||
this.$store.commit('SET_theme', value)
|
||||
this.sideStyle = value
|
||||
this.$TOOL.data.set('SNOWY_THEME', value)
|
||||
this.globalStore.setTheme(value)
|
||||
tool.data.set('SNOWY_THEME', value)
|
||||
},
|
||||
// 设置整体界面布局
|
||||
layoutStyle(value) {
|
||||
this.$store.commit('SET_layout', value)
|
||||
this.$TOOL.data.set('SNOWY_LAYOUT', value)
|
||||
this.layout = value
|
||||
this.globalStore.setLayout(value)
|
||||
tool.data.set('SNOWY_LAYOUT', value)
|
||||
},
|
||||
// 切换颜色
|
||||
tagColor(value) {
|
||||
this.themeColor = value
|
||||
this.$TOOL.data.set('SNOWY_THEME_COLOR', value)
|
||||
this.$store.commit('SET_themeColor', value)
|
||||
tool.data.set('SNOWY_THEME_COLOR', value)
|
||||
this.globalStore.setThemeColor(value)
|
||||
},
|
||||
// 切换表单风格
|
||||
formStyleChange(value) {
|
||||
tool.data.set('SNOWY_FORM_STYLE', value)
|
||||
this.globalStore.setFormStyle(value)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -19,8 +19,8 @@
|
||||
|
||||
<script>
|
||||
import NavMenu from './NavMenu.vue'
|
||||
import tool from '@/utils/tool'
|
||||
import store from '@/store'
|
||||
import { globalStore } from '@/store'
|
||||
import { mapState } from 'pinia'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -69,10 +69,12 @@
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
menu: [],
|
||||
sysBaseConfig: tool.data.get('SNOWY_SYS_BASE_CONFIG') || store.state.global.sysBaseConfig
|
||||
menu: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(globalStore, ['sysBaseConfig'])
|
||||
},
|
||||
created() {
|
||||
const menu = this.$router.getMenu()
|
||||
this.menu = this.filterUrl(menu)
|
||||
|
@ -1,10 +1,42 @@
|
||||
<template>
|
||||
<div class="snowy-tags">
|
||||
<xn-context-menu
|
||||
class="right-menu"
|
||||
:target="contextMenuTarget"
|
||||
:show="contextMenuVisible"
|
||||
@update:show="(show) => (contextMenuVisible = show)"
|
||||
@get-context-menu="handleTabContextMenu"
|
||||
>
|
||||
<div class="right-menu-item" @click="refreshTab">
|
||||
<reload-outlined class="snowy-header-tags-right" />
|
||||
<div class="pl-3">刷新</div>
|
||||
</div>
|
||||
|
||||
<div class="right-menu-item" @click="closeTabs">
|
||||
<close-outlined class="snowy-header-tags-right" />
|
||||
<div class="pl-3">关闭</div>
|
||||
</div>
|
||||
|
||||
<div class="right-menu-item" @click="closeOtherTabs">
|
||||
<close-outlined class="snowy-header-tags-right" />
|
||||
<div class="pl-3">关闭其他标签</div>
|
||||
</div>
|
||||
|
||||
<div class="right-menu-item" @click="maximize">
|
||||
<expand-outlined class="snowy-header-tags-right" />
|
||||
<div class="pl-3">最大化</div>
|
||||
</div>
|
||||
<div class="right-menu-item" @click="openWindow">
|
||||
<select-outlined class="snowy-header-tags-right" />
|
||||
<div class="pl-3">新窗口打开</div>
|
||||
</div>
|
||||
</xn-context-menu>
|
||||
<a-tabs
|
||||
v-model:activeKey="activeKey"
|
||||
type="editable-card"
|
||||
class="snowy-admin-tabs"
|
||||
hide-add
|
||||
ref="tabs"
|
||||
@edit="onTabRemove"
|
||||
@tabClick="onTabClick"
|
||||
>
|
||||
@ -17,41 +49,8 @@
|
||||
<div class="snowy-admin-tabs-arrow" @click="scrollRight">
|
||||
<right-outlined />
|
||||
</div>
|
||||
|
||||
<a-dropdown>
|
||||
<div class="snowy-admin-tabs-drop">
|
||||
<DownOutlined />
|
||||
</div>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item>
|
||||
<div class="layout-items-center" @click="refreshTab">
|
||||
<reload-outlined class="snowy-header-tags-right" />
|
||||
<div class="pl-3">刷新</div>
|
||||
</div>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<div class="layout-items-center" @click="closeOtherTabs">
|
||||
<close-outlined class="snowy-header-tags-right" />
|
||||
<div class="pl-3">关闭其他标签</div>
|
||||
</div>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<div class="layout-items-center" @click="maximize">
|
||||
<expand-outlined class="snowy-header-tags-right" />
|
||||
<div class="pl-3">最大化</div>
|
||||
</div>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<div class="layout-items-center" @click="openWindow">
|
||||
<select-outlined class="snowy-header-tags-right" />
|
||||
<div class="pl-3">在新的窗口中打开</div>
|
||||
</div>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
|
||||
<a-tab-pane v-for="tag in tagList" :key="tag.fullPath" :tab="tag.meta.title" :closable="!tag.meta.affix">
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
@ -59,22 +58,38 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { LeftOutlined, RightOutlined } from '@ant-design/icons-vue'
|
||||
import Sortable from 'sortablejs'
|
||||
import tool from '@/utils/tool'
|
||||
import XnContextMenu from '@/components/XnContextMenu/index.vue'
|
||||
import {globalStore, iframeStore, keepAliveStore, viewTagsStore} from '@/store'
|
||||
import { mapState, mapActions } from 'pinia'
|
||||
|
||||
export default {
|
||||
name: 'Tags',
|
||||
components: { XnContextMenu },
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
tagList: this.$store.state.viewTags.viewTags,
|
||||
activeKey: this.$route.fullPath
|
||||
// tagList: [],
|
||||
activeKey: this.$route.fullPath,
|
||||
maxTabs: 20,
|
||||
contextMenuTarget: null,
|
||||
contextMenuVisible: false,
|
||||
currentContextMenuTabIndex: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(viewTagsStore, ['viewTags']),
|
||||
...mapState(globalStore, ['layoutTagsOpen']),
|
||||
tagList() {
|
||||
return this.viewTags
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route(e) {
|
||||
this.addViewTags(e)
|
||||
$route(to) {
|
||||
this.addViewTags(to)
|
||||
},
|
||||
layoutTagsOpen() {
|
||||
this.closeOtherCacheTabs()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@ -88,12 +103,30 @@
|
||||
this.addViewTags(this.$route)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const tabNavList = document.querySelector('.ant-tabs-nav-list')
|
||||
if (tabNavList) {
|
||||
this.contextMenuTarget = tabNavList
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(viewTagsStore, ['addViewTags', 'pushViewTags', 'removeViewTags']),
|
||||
...mapActions(iframeStore, ['addIframe', 'removeIframeList', 'refreshIframe']),
|
||||
...mapActions(keepAliveStore, ['pushKeepLive', 'removeKeepLive', 'setRouteShow']),
|
||||
handleTabContextMenu(evt) {
|
||||
evt.preventDefault()
|
||||
let target = evt.target
|
||||
if (target.classList.contains('ant-tabs-tab-btn')) {
|
||||
target = target.parentNode
|
||||
}
|
||||
const tabList = document.querySelectorAll('.ant-tabs-nav-list .ant-tabs-tab')
|
||||
this.currentContextMenuTabIndex = Array.from(tabList).findIndex((tab) => tab === target)
|
||||
},
|
||||
onTabClick(tab) {
|
||||
this.$router.push(tab)
|
||||
},
|
||||
getCurrentTag() {
|
||||
return this.tagList.find((tag) => tag.fullPath === this.activeKey)
|
||||
return this.tagList[this.currentContextMenuTabIndex]
|
||||
},
|
||||
onTabRemove(tabKey, action) {
|
||||
if (action === 'remove') {
|
||||
@ -133,8 +166,12 @@
|
||||
addViewTags(route) {
|
||||
this.activeKey = route.fullPath
|
||||
if (route.name && !route.meta.fullpage) {
|
||||
this.$store.commit('pushViewTags', route)
|
||||
this.$store.commit('pushKeepLive', route.name)
|
||||
this.pushViewTags(route)
|
||||
this.pushKeepLive(route.name)
|
||||
}
|
||||
if (this.tagList.length - 1 > this.maxTabs) {
|
||||
const firstTag = this.tagList[1]
|
||||
this.removeViewTags(firstTag)
|
||||
}
|
||||
},
|
||||
// 高亮tag
|
||||
@ -143,9 +180,9 @@
|
||||
},
|
||||
// 关闭tag
|
||||
closeSelectedTag(tag, autoPushLatestView = true) {
|
||||
this.$store.commit('removeViewTags', tag)
|
||||
this.$store.commit('removeIframeList', tag)
|
||||
this.$store.commit('removeKeepLive', tag.name)
|
||||
this.removeViewTags(tag)
|
||||
this.removeIframeList(tag)
|
||||
this.removeKeepLive(tag.name)
|
||||
if (autoPushLatestView && this.isActive(tag)) {
|
||||
const latestView = this.tagList.slice(-1)[0]
|
||||
if (latestView) {
|
||||
@ -157,6 +194,7 @@
|
||||
},
|
||||
// TAB 刷新
|
||||
refreshTab() {
|
||||
this.contextMenuVisible = false
|
||||
const nowTag = this.getCurrentTag()
|
||||
// 判断是否当前路由,否的话跳转
|
||||
// eslint-disable-next-line eqeqeq
|
||||
@ -166,18 +204,19 @@
|
||||
query: nowTag.query
|
||||
})
|
||||
}
|
||||
this.$store.commit('refreshIframe', nowTag)
|
||||
this.refreshIframe(nowTag)
|
||||
setTimeout(() => {
|
||||
this.$store.commit('removeKeepLive', nowTag.name)
|
||||
this.$store.commit('setRouteShow', false)
|
||||
this.removeKeepLive(nowTag.name)
|
||||
this.setRouteShow(false)
|
||||
this.$nextTick(() => {
|
||||
this.$store.commit('pushKeepLive', nowTag.name)
|
||||
this.$store.commit('setRouteShow', true)
|
||||
this.pushKeepLive(nowTag.name)
|
||||
this.setRouteShow(true)
|
||||
})
|
||||
}, 0)
|
||||
},
|
||||
// TAB 关闭
|
||||
closeTabs() {
|
||||
this.contextMenuVisible = false
|
||||
const nowTag = this.getCurrentTag()
|
||||
if (!nowTag.meta.affix) {
|
||||
this.closeSelectedTag(nowTag)
|
||||
@ -185,6 +224,7 @@
|
||||
},
|
||||
// TAB 关闭其他
|
||||
closeOtherTabs() {
|
||||
this.contextMenuVisible = false
|
||||
const nowTag = this.getCurrentTag()
|
||||
// 判断是否当前路由,否的话跳转
|
||||
// eslint-disable-next-line eqeqeq
|
||||
@ -204,8 +244,16 @@
|
||||
}
|
||||
})
|
||||
},
|
||||
// 多标签功能关闭时关闭被缓存的标签
|
||||
closeOtherCacheTabs () {
|
||||
const tags = [...this.tagList]
|
||||
tags.forEach((tag) => {
|
||||
this.closeSelectedTag(tag, false)
|
||||
})
|
||||
},
|
||||
// TAB 最大化(包括标签栏)
|
||||
maximize() {
|
||||
this.contextMenuVisible = false
|
||||
const nowTag = this.getCurrentTag()
|
||||
// 判断是否当前路由,否的话跳转
|
||||
// eslint-disable-next-line eqeqeq
|
||||
@ -219,6 +267,7 @@
|
||||
},
|
||||
// 新窗口打开
|
||||
openWindow() {
|
||||
this.contextMenuVisible = false
|
||||
const nowTag = this.getCurrentTag()
|
||||
const url = nowTag.href || '/'
|
||||
if (!nowTag.meta.affix) {
|
||||
@ -284,4 +333,25 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.right-menu {
|
||||
position: fixed;
|
||||
background: #fff;
|
||||
z-index: 999;
|
||||
border: 1px solid #eee;
|
||||
box-shadow: 0 0.5em 1em 0 rgb(0 0 0 / 10%);
|
||||
border-radius: 1px;
|
||||
}
|
||||
.snowy-tags {
|
||||
.right-menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
padding: 10px 20px;
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: var(--primary-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<div class="user-bar">
|
||||
<div v-if="!ismobile" class="search panel-item hidden-sm-and-down" @click="handleSearchClick">
|
||||
<search-outlined />
|
||||
</div>
|
||||
<div v-if="!ismobile" class="screen panel-item hidden-sm-and-down" @click="fullscreen">
|
||||
<fullscreen-outlined />
|
||||
</div>
|
||||
@ -40,15 +43,30 @@
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
<div class="setting panel-item" @click="openSetting">
|
||||
<div v-if="setDeawer === 'true'" class="setting panel-item" @click="openSetting">
|
||||
<layout-outlined />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 整体风格设置抽屉 -->
|
||||
<a-drawer v-model:visible="settingDialog" :closable="false" width="300">
|
||||
<setting></setting>
|
||||
<setting />
|
||||
</a-drawer>
|
||||
<!-- 搜索面板 -->
|
||||
<xn-form-container
|
||||
title="搜索"
|
||||
:visible="searchActive"
|
||||
:closable="false"
|
||||
:footer="null"
|
||||
:width="600"
|
||||
style="overflow: hidden"
|
||||
destroyOnClose
|
||||
dialogClass="searchModal"
|
||||
:bodyStyle="{ maxHeight: '520px', overflow: 'auto', padding: '14px' }"
|
||||
@close="searchPanelClose"
|
||||
>
|
||||
<panel-search ref="panelSearch" @close="searchPanelClose" />
|
||||
</xn-form-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -61,37 +79,33 @@
|
||||
import tool from '@/utils/tool'
|
||||
import loginApi from '@/api/auth/loginApi'
|
||||
import devUserMessage from './message.vue'
|
||||
import panelSearch from './panel-search/index.vue'
|
||||
import mixinSearch from './mixins/search'
|
||||
import { mapState } from 'pinia'
|
||||
import { globalStore } from '@/store'
|
||||
export default {
|
||||
components: {
|
||||
setting,
|
||||
devUserMessage
|
||||
devUserMessage,
|
||||
panelSearch
|
||||
},
|
||||
mixins: [mixinSearch],
|
||||
data() {
|
||||
return {
|
||||
lang: [],
|
||||
settingDialog: false,
|
||||
userInfo: {},
|
||||
userName: '',
|
||||
userNameF: ''
|
||||
userNameF: '',
|
||||
setDeawer: import.meta.env.VITE_SET_DRAWER
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
ismobile() {
|
||||
return this.$store.state.global.ismobile
|
||||
},
|
||||
userInfoWatch() {
|
||||
return this.$store.state.global.userInfo
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
userInfoWatch(newVal, oldVal) {
|
||||
this.userInfo = newVal
|
||||
}
|
||||
...mapState(globalStore, ['ismobile', 'userInfo'])
|
||||
},
|
||||
|
||||
created() {
|
||||
// 获取默认语言
|
||||
this.lang = new Array(this.$TOOL.data.get('APP_LANG') || this.$CONFIG.LANG)
|
||||
this.userInfo = this.$TOOL.data.get('USER_INFO')
|
||||
this.userName = this.userInfo?.userName || ''
|
||||
this.userNameF = this.userName.substring(0, 1)
|
||||
},
|
||||
@ -171,29 +185,25 @@
|
||||
if (screenfull.isEnabled) {
|
||||
screenfull.toggle(element)
|
||||
}
|
||||
}
|
||||
},
|
||||
// 搜索
|
||||
fullSearch() {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="less" scoped>
|
||||
:deep(.ant-modal) {
|
||||
top: 20px;
|
||||
}
|
||||
:deep(.ant-modal-content) {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.user-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
.user-bar .panel-item {
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.user-bar .panel-item i {
|
||||
}
|
||||
.user-bar .panel-item:hover {
|
||||
background: var(--header-color-split);
|
||||
}
|
||||
.user-bar .user-avatar {
|
||||
height: 49px;
|
||||
display: flex;
|
||||
|
@ -4,7 +4,7 @@
|
||||
<a-layout>
|
||||
<a-layout-sider
|
||||
v-if="!ismobile"
|
||||
v-model:collapsed="$store.state.global.menuIsCollapse"
|
||||
v-model:collapsed="menuIsCollapse"
|
||||
:trigger="null"
|
||||
collapsible
|
||||
:theme="sideTheme"
|
||||
@ -18,7 +18,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div :class="$store.state.global.menuIsCollapse ? 'aminui-side isCollapse' : 'aminui-side'">
|
||||
<div :class="menuIsCollapse ? 'aminui-side isCollapse' : 'aminui-side'">
|
||||
<div class="adminui-side-scroll">
|
||||
<a-menu
|
||||
v-model:openKeys="openKeys"
|
||||
@ -28,17 +28,21 @@
|
||||
@select="onSelect"
|
||||
@openChange="onOpenChange"
|
||||
>
|
||||
<NavMenu :nav-menus="menu"></NavMenu>
|
||||
<NavMenu :nav-menus="menu" />
|
||||
</a-menu>
|
||||
</div>
|
||||
</div>
|
||||
</a-layout-sider>
|
||||
<!-- 手机端情况下的左侧菜单 -->
|
||||
<Side-m v-if="ismobile"></Side-m>
|
||||
<Side-m v-if="ismobile" />
|
||||
<!-- 右侧布局 -->
|
||||
<a-layout>
|
||||
<div id="snowyHeader" class="snowy-header">
|
||||
<div class="snowy-header-left" style="padding-left: 0px">
|
||||
<div v-if="!ismobile" class="panel-item hidden-sm-and-down" @click="menuIsCollapseClick">
|
||||
<MenuUnfoldOutlined v-if="menuIsCollapse" />
|
||||
<MenuFoldOutlined v-else />
|
||||
</div>
|
||||
<moduleMenu @switchModule="switchModule" />
|
||||
<Topbar v-if="!ismobile && breadcrumbOpen" />
|
||||
</div>
|
||||
@ -47,15 +51,15 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- 多标签 -->
|
||||
<Tags v-if="!ismobile && layoutTagsOpen"></Tags>
|
||||
<Tags v-if="!ismobile && layoutTagsOpen" />
|
||||
<a-layout-content class="main-content-wrapper">
|
||||
<div id="adminui-main" class="adminui-main">
|
||||
<router-view v-slot="{ Component }">
|
||||
<keep-alive :include="$store.state.keepAlive.keepLiveRoute">
|
||||
<component :is="Component" :key="$route.name" v-if="$store.state.keepAlive.routeShow" />
|
||||
<keep-alive :include="keepLiveRoute">
|
||||
<component :is="Component" :key="$route.name" v-if="routeShow" />
|
||||
</keep-alive>
|
||||
</router-view>
|
||||
<iframe-view></iframe-view>
|
||||
<iframe-view />
|
||||
<div class="main-bottom-wrapper">
|
||||
<a style="color: #a0a0a0" :href="sysBaseConfig.SNOWY_SYS_COPYRIGHT_URL" target="_blank">{{
|
||||
sysBaseConfig.SNOWY_SYS_COPYRIGHT
|
||||
@ -63,13 +67,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</a-layout-content>
|
||||
<!--
|
||||
<a-layout-footer style="text-align: center">
|
||||
<a style="color: #a0a0a0" :href="sysBaseConfig.SNOWY_SYS_COPYRIGHT_URL" target="_blank">{{
|
||||
sysBaseConfig.SNOWY_SYS_COPYRIGHT
|
||||
}}</a>
|
||||
</a-layout-footer>
|
||||
-->
|
||||
</a-layout>
|
||||
</a-layout>
|
||||
</template>
|
||||
@ -122,7 +119,7 @@
|
||||
<a-layout-sider
|
||||
v-if="!ismobile"
|
||||
v-show="layoutSiderDowbleMenu"
|
||||
v-model:collapsed="$store.state.global.menuIsCollapse"
|
||||
v-model:collapsed="menuIsCollapse"
|
||||
:trigger="null"
|
||||
width="170"
|
||||
collapsible
|
||||
@ -132,21 +129,25 @@
|
||||
<h2 class="snowy-title">{{ pmenu.meta.title }}</h2>
|
||||
</div>
|
||||
<a-menu
|
||||
v-model:collapsed="$store.state.global.menuIsCollapse"
|
||||
v-model:collapsed="menuIsCollapse"
|
||||
v-model:openKeys="openKeys"
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
mode="inline"
|
||||
:theme="secondMenuSideTheme"
|
||||
@select="onSelect"
|
||||
>
|
||||
<NavMenu :nav-menus="nextMenu"></NavMenu>
|
||||
<NavMenu :nav-menus="nextMenu" />
|
||||
</a-menu>
|
||||
</a-layout-sider>
|
||||
<!-- 手机端情况下的左侧菜单 -->
|
||||
<Side-m v-if="ismobile"></Side-m>
|
||||
<Side-m v-if="ismobile" />
|
||||
<a-layout>
|
||||
<div id="snowyHeader" class="snowy-header">
|
||||
<div class="snowy-header-left" style="padding-left: 0px">
|
||||
<div v-if="!ismobile" class="panel-item hidden-sm-and-down" @click="menuIsCollapseClick">
|
||||
<MenuUnfoldOutlined v-if="menuIsCollapse" />
|
||||
<MenuFoldOutlined v-else />
|
||||
</div>
|
||||
<moduleMenu @switchModule="switchModule" />
|
||||
<Topbar v-if="!ismobile && breadcrumbOpen" />
|
||||
</div>
|
||||
@ -159,18 +160,18 @@
|
||||
<a-layout-content class="main-content-wrapper">
|
||||
<div id="adminui-main" class="adminui-main">
|
||||
<router-view v-slot="{ Component }">
|
||||
<keep-alive :include="$store.state.keepAlive.keepLiveRoute">
|
||||
<component :is="Component" v-if="$store.state.keepAlive.routeShow" :key="$route.name" />
|
||||
<keep-alive :include="keepLiveRoute">
|
||||
<component :is="Component" v-if="routeShow" :key="$route.name" />
|
||||
</keep-alive>
|
||||
</router-view>
|
||||
<iframe-view></iframe-view>
|
||||
<iframe-view />
|
||||
<div class="main-bottom-wrapper">
|
||||
<a style="color: #a0a0a0" :href="sysBaseConfig.SNOWY_SYS_COPYRIGHT_URL" target="_blank">{{
|
||||
sysBaseConfig.SNOWY_SYS_COPYRIGHT
|
||||
}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</a-layout-content>
|
||||
<a-layout-footer style="text-align: center">
|
||||
<a style="color: #a0a0a0" :href="sysBaseConfig.SNOWY_SYS_COPYRIGHT_URL" target="_blank">{{
|
||||
sysBaseConfig.SNOWY_SYS_COPYRIGHT
|
||||
}}</a>
|
||||
</a-layout-footer>
|
||||
</a-layout>
|
||||
</a-layout>
|
||||
</template>
|
||||
@ -190,8 +191,9 @@
|
||||
import iframeView from './components/iframeView.vue'
|
||||
import moduleMenu from './components/moduleMenu.vue'
|
||||
import { ThemeModeEnum } from '@/utils/enum'
|
||||
import { globalStore, keepAliveStore } from '@/store'
|
||||
import { mapState, mapStores, mapActions } from 'pinia'
|
||||
import tool from '@/utils/tool'
|
||||
import store from '@/store'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Index',
|
||||
@ -215,39 +217,32 @@
|
||||
onSelectTag: false,
|
||||
selectedKeys: [],
|
||||
openKeys: [],
|
||||
openKeysOther: [],
|
||||
sysBaseConfig: tool.data.get('SNOWY_SYS_BASE_CONFIG') || store.state.global.sysBaseConfig
|
||||
openKeysOther: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapStores(globalStore),
|
||||
...mapState(globalStore, [
|
||||
'theme',
|
||||
'ismobile',
|
||||
'layout',
|
||||
'layoutTagsOpen',
|
||||
'menuIsCollapse',
|
||||
'breadcrumbOpen',
|
||||
'topHanderThemeColorOpen',
|
||||
'topHanderThemeColorSpread',
|
||||
'topHanderThemeColor',
|
||||
'sideUniqueOpen',
|
||||
'sysBaseConfig'
|
||||
]),
|
||||
...mapState(keepAliveStore, ['keepLiveRoute', 'routeShow']),
|
||||
sideTheme() {
|
||||
const theme = this.$store.state.global.theme
|
||||
const theme = this.theme
|
||||
return theme === ThemeModeEnum.REAL_DARK ? ThemeModeEnum.DARK : theme
|
||||
},
|
||||
secondMenuSideTheme() {
|
||||
const theme = this.$store.state.global.theme
|
||||
const theme = this.theme
|
||||
return theme === ThemeModeEnum.REAL_DARK ? ThemeModeEnum.DARK : ThemeModeEnum.LIGHT
|
||||
},
|
||||
ismobile() {
|
||||
return this.$store.state.global.ismobile
|
||||
},
|
||||
layout() {
|
||||
return this.$store.state.global.layout
|
||||
},
|
||||
layoutTagsOpen() {
|
||||
return this.$store.state.global.layoutTagsOpen
|
||||
},
|
||||
menuIsCollapse() {
|
||||
return this.$store.state.global.menuIsCollapse
|
||||
},
|
||||
breadcrumbOpen() {
|
||||
return this.$store.state.global.breadcrumbOpen
|
||||
},
|
||||
topHanderThemeColorOpen() {
|
||||
return this.$store.state.global.topHanderThemeColorOpen
|
||||
},
|
||||
topHanderThemeColorSpread() {
|
||||
return this.$store.state.global.topHanderThemeColorSpread
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -280,7 +275,7 @@
|
||||
window.addEventListener('resize', this.onLayoutResize)
|
||||
this.moduleMenu = this.$router.getMenu()
|
||||
// 获取缓存中的菜单模块是哪个
|
||||
const menuModuleId = this.$TOOL.data.get('SNOWY_MENU_MODULE_ID')
|
||||
const menuModuleId = tool.data.get('SNOWY_MENU_MODULE_ID')
|
||||
let menu = []
|
||||
if (menuModuleId) {
|
||||
// 防止切换一个无此应用的人
|
||||
@ -301,6 +296,7 @@
|
||||
this.switchoverTopHanderThemeColor()
|
||||
},
|
||||
methods: {
|
||||
...mapActions(globalStore, ['setTheme', 'setIsmobile', 'setLayout', 'setMenuIsCollapse']),
|
||||
// 切换应用
|
||||
switchModule(id) {
|
||||
const menu = this.moduleMenu
|
||||
@ -308,7 +304,7 @@
|
||||
const menus = menu.filter((item) => item.id === id)[0].children
|
||||
if (menus.length > 0) {
|
||||
// 将此模块的唯一值加入缓存
|
||||
this.$TOOL.data.set('SNOWY_MENU_MODULE_ID', id)
|
||||
tool.data.set('SNOWY_MENU_MODULE_ID', id)
|
||||
// 正儿八百的菜单
|
||||
this.menu = this.filterUrl(menus)
|
||||
// 然后将其跳转至指定界面,默认始终取排序第一的
|
||||
@ -342,11 +338,7 @@
|
||||
},
|
||||
onLayoutResize() {
|
||||
const clientWidth = document.body.clientWidth
|
||||
if (clientWidth < 992) {
|
||||
this.$store.commit('SET_ismobile', true)
|
||||
} else {
|
||||
this.$store.commit('SET_ismobile', false)
|
||||
}
|
||||
this.setIsmobile(clientWidth < 992)
|
||||
},
|
||||
// 路由监听高亮
|
||||
showThis() {
|
||||
@ -368,7 +360,7 @@
|
||||
if (!this.onSelectTag) {
|
||||
const pidKey = this.getParentKeys(this.menu, active)
|
||||
this.openKeys = pidKey
|
||||
} else if (this.$store.state.global.sideUniqueOpen) {
|
||||
} else if (this.sideUniqueOpen) {
|
||||
const pidKey = this.getParentKeys(this.menu, active)
|
||||
this.openKeys = pidKey
|
||||
}
|
||||
@ -419,7 +411,7 @@
|
||||
},
|
||||
// 菜单展开/关闭的回调
|
||||
onOpenChange(keys) {
|
||||
if (this.$store.state.global.sideUniqueOpen) {
|
||||
if (this.sideUniqueOpen) {
|
||||
// 获取最新的
|
||||
const openKey = keys[keys.length - 1]
|
||||
if (keys.length > 1) {
|
||||
@ -471,6 +463,9 @@
|
||||
})
|
||||
return newMap
|
||||
},
|
||||
menuIsCollapseClick() {
|
||||
this.globalStore.toggleConfig('menuIsCollapse')
|
||||
},
|
||||
// 退出最大化
|
||||
exitMaximize() {
|
||||
document.getElementById('app').classList.remove('main-maximize')
|
||||
@ -484,17 +479,19 @@
|
||||
: header.classList.remove('snowy-header-primary-color')
|
||||
// 判断是否开启了通栏
|
||||
const headerLogin = document.getElementById('snowyHeaderLogo')
|
||||
this.topHanderThemeColorSpread
|
||||
? headerLogin.classList.add('snowy-header-logo-primary-color')
|
||||
: headerLogin.classList.remove('snowy-header-logo-primary-color')
|
||||
try {
|
||||
this.topHanderThemeColorSpread
|
||||
? headerLogin.classList.add('snowy-header-logo-primary-color')
|
||||
: headerLogin.classList.remove('snowy-header-logo-primary-color')
|
||||
} catch (e) {}
|
||||
// 如果是双排菜单,吧第二排的也给渲染了
|
||||
if (this.layout === 'doublerow') {
|
||||
const snowyDoublerowSideTop = document.getElementById('snowyDoublerowSideTop')
|
||||
try{
|
||||
try {
|
||||
this.topHanderThemeColorSpread
|
||||
? snowyDoublerowSideTop.classList.add('snowy-doublerow-side-top-primary-color')
|
||||
: snowyDoublerowSideTop.classList.remove('snowy-doublerow-side-top-primary-color')
|
||||
}catch (e) { }
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import enGB from 'ant-design-vue/es/locale/en_GB'
|
||||
import zh_cn from './lang/zh-cn.js'
|
||||
import en from './lang/en.js'
|
||||
import tool from '@/utils/tool'
|
||||
import sysConfig from '@/config/index.js'
|
||||
import sysConfig from '@/config/index'
|
||||
|
||||
export const messages = {
|
||||
'zh-cn': {
|
||||
|
@ -16,7 +16,11 @@ export default {
|
||||
editButton: 'edit',
|
||||
removeButton: 'delete',
|
||||
batchRemoveButton: 'batch Remove',
|
||||
detailButton: 'detail'
|
||||
detailButton: 'detail',
|
||||
searchKey: 'Search Key',
|
||||
imports: 'Import',
|
||||
more: 'More',
|
||||
export: 'Export',
|
||||
},
|
||||
model: {
|
||||
user: 'user',
|
||||
@ -50,5 +54,19 @@ export default {
|
||||
emailCodePlaceholder: 'Please input a Email code',
|
||||
restPhoneType: 'For phone rest',
|
||||
restEmailType: 'For email rest'
|
||||
},
|
||||
user: {
|
||||
userStatus: 'User Status',
|
||||
resetPassword: 'Reset Password',
|
||||
role: 'Role',
|
||||
batchExportButton: 'Batch Export',
|
||||
grantRole: 'Grant Role',
|
||||
grantResource: 'Grant Resource',
|
||||
grantPermission: 'Grant Permission',
|
||||
exportUserInfo: 'Export UserInfo',
|
||||
placeholderNameAndSearchKey: 'Please enter your name or keyword',
|
||||
placeholderUserStatus: 'Please select status',
|
||||
popconfirmDeleteUser: 'Are you sure you want to delete it?',
|
||||
popconfirmResatUserPwd: 'Are you sure you want to reset?'
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,11 @@ export default {
|
||||
editButton: '编辑',
|
||||
removeButton: '删除',
|
||||
batchRemoveButton: '批量删除',
|
||||
detailButton: '详情'
|
||||
detailButton: '详情',
|
||||
searchKey: '关键词',
|
||||
imports: '导入',
|
||||
more: '更多',
|
||||
export: '导出',
|
||||
},
|
||||
model: {
|
||||
user: '用户',
|
||||
@ -52,5 +56,19 @@ export default {
|
||||
emailCodePlaceholder: '请输入邮件验证码',
|
||||
restPhoneType: '手机号找回',
|
||||
restEmailType: '邮箱找回'
|
||||
},
|
||||
user: {
|
||||
userStatus: '用户状态',
|
||||
resetPassword: '重置密码',
|
||||
role: '角色',
|
||||
batchExportButton: '批量导出',
|
||||
grantRole: '授权角色',
|
||||
grantResource: '授权资源',
|
||||
grantPermission: '授权权限',
|
||||
exportUserInfo: '导出信息',
|
||||
placeholderNameAndSearchKey: '请输入姓名或关键词',
|
||||
placeholderUserStatus: '请选择状态',
|
||||
popconfirmDeleteUser: '确定要删除吗?',
|
||||
popconfirmResatUserPwd: '确定要重置吗?'
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,16 @@
|
||||
import { createApp } from 'vue'
|
||||
import Antd from 'ant-design-vue'
|
||||
import { createPinia } from 'pinia'
|
||||
|
||||
import './style/index.less'
|
||||
import snowy from './snowy'
|
||||
import i18n from './locales'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import App from './App.vue'
|
||||
import './tailwind.css'
|
||||
|
||||
const app = createApp(App)
|
||||
app.use(store)
|
||||
app.use(createPinia())
|
||||
app.use(router)
|
||||
app.use(Antd)
|
||||
app.use(i18n)
|
||||
|
@ -8,11 +8,8 @@
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
/* eslint-disable eqeqeq */
|
||||
/* eslint-disable camelcase */
|
||||
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { notification } from 'ant-design-vue'
|
||||
import config from '@/config'
|
||||
import NProgress from 'nprogress'
|
||||
import 'nprogress/nprogress.css'
|
||||
import systemRouter from './systemRouter'
|
||||
@ -22,34 +19,32 @@ import userRoutes from '@/config/route'
|
||||
import tool from '@/utils/tool'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
const modules = import.meta.glob('/src/views/**/**.vue')
|
||||
import store from '@/store'
|
||||
const sysBaseConfig = tool.data.get('SNOWY_SYS_BASE_CONFIG') || store.state.global.sysBaseConfig
|
||||
import { globalStore, searchStore } from '@/store'
|
||||
|
||||
// 进度条配置
|
||||
NProgress.configure({ showSpinner: false, speed: 500 })
|
||||
|
||||
// 系统路由
|
||||
const routes = [...systemRouter, ...whiteListRouters]
|
||||
|
||||
// 系统特殊路由
|
||||
const routes_404 = {
|
||||
path: '/:pathMatch(.*)*',
|
||||
hidden: true,
|
||||
component: () => import('@/layout/other/404.vue')
|
||||
}
|
||||
let routes_404_r = () => {}
|
||||
const routes_404 = [
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
hidden: true,
|
||||
component: () => import('@/layout/other/404.vue')
|
||||
}
|
||||
]
|
||||
// 系统路由
|
||||
const routes = [...systemRouter, ...whiteListRouters, ...routes_404]
|
||||
|
||||
const router = createRouter({
|
||||
// 此方式不带 # 号 // createWebHashHistory()带#号
|
||||
history: createWebHistory(),
|
||||
routes
|
||||
})
|
||||
|
||||
// 设置标题
|
||||
document.title = sysBaseConfig.SNOWY_SYS_NAME
|
||||
// document.title = sysBaseConfig.SNOWY_SYS_NAME
|
||||
|
||||
// 判断是否已加载过动态/静态路由
|
||||
let isGetRouter = false
|
||||
const isGetRouter = ref(false)
|
||||
|
||||
// 白名单校验
|
||||
const exportWhiteListFromRouter = (router) => {
|
||||
@ -59,33 +54,11 @@ const exportWhiteListFromRouter = (router) => {
|
||||
}
|
||||
const whiteList = exportWhiteListFromRouter(whiteListRouters)
|
||||
|
||||
// 加载动态/静态路由
|
||||
const handleGetRouter = (to) => {
|
||||
if (!isGetRouter) {
|
||||
let apiMenu = tool.data.get('MENU') || []
|
||||
if (apiMenu.length === 0) {
|
||||
// 创建默认模块,显示默认菜单
|
||||
apiMenu[0] = cloneDeep(userRoutes.module[0])
|
||||
const userMenu = userRoutes.menu
|
||||
const childrenApiMenu = apiMenu[0].children
|
||||
apiMenu[0].children = [...userMenu, ...childrenApiMenu]
|
||||
}
|
||||
|
||||
let menuRouter = filterAsyncRouter(apiMenu)
|
||||
menuRouter = flatAsyncRoutes(menuRouter)
|
||||
menuRouter.forEach((item) => {
|
||||
router.addRoute('layout', item)
|
||||
})
|
||||
routes_404_r = router.addRoute(routes_404)
|
||||
if (to && to.matched.length === 0) {
|
||||
router.push(to.fullPath)
|
||||
}
|
||||
isGetRouter = true
|
||||
}
|
||||
}
|
||||
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
NProgress.start()
|
||||
const store = globalStore()
|
||||
|
||||
const sysBaseConfig = tool.data.get('SNOWY_SYS_BASE_CONFIG') || store.sysBaseConfig
|
||||
// 动态标题
|
||||
document.title = to.meta.title
|
||||
? `${to.meta.title} - ${sysBaseConfig.SNOWY_SYS_NAME}`
|
||||
@ -109,11 +82,12 @@ router.beforeEach(async (to, from, next) => {
|
||||
}
|
||||
// 删除路由(替换当前layout路由)
|
||||
router.addRoute(routes[0])
|
||||
// 删除路由(404)
|
||||
routes_404_r()
|
||||
isGetRouter = false
|
||||
isGetRouter.value = false
|
||||
next()
|
||||
return false
|
||||
} else {
|
||||
// 这里需要使用 localStorage 保存登录之前要访问的页面
|
||||
tool.data.set('LAST_VIEWS_PATH', to.fullPath)
|
||||
}
|
||||
if (!token) {
|
||||
next({
|
||||
@ -126,7 +100,27 @@ router.beforeEach(async (to, from, next) => {
|
||||
to.matched = [to.matched[to.matched.length - 1]]
|
||||
}
|
||||
// 加载动态/静态路由
|
||||
handleGetRouter(to)
|
||||
if (!isGetRouter.value) {
|
||||
const apiMenu = tool.data.get('MENU') || []
|
||||
if (apiMenu.length === 0) {
|
||||
// 创建默认模块,显示默认菜单
|
||||
apiMenu[0] = cloneDeep(userRoutes.module[0])
|
||||
const userMenu = userRoutes.menu
|
||||
const childrenApiMenu = apiMenu[0].children
|
||||
apiMenu[0].children = [...userMenu, ...childrenApiMenu]
|
||||
}
|
||||
let menuRouter = filterAsyncRouter(apiMenu)
|
||||
menuRouter = flatAsyncRoutes(menuRouter)
|
||||
menuRouter.forEach((item) => {
|
||||
router.addRoute('layout', item)
|
||||
})
|
||||
|
||||
const search_store = searchStore()
|
||||
search_store.init(menuRouter)
|
||||
isGetRouter.value = true
|
||||
next({ ...to, replace: true })
|
||||
return false
|
||||
}
|
||||
beforeEach(to, from)
|
||||
next()
|
||||
})
|
||||
|
@ -9,14 +9,15 @@
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
import { nextTick } from 'vue'
|
||||
import store from '@/store'
|
||||
import { viewTagsStore } from '@/store'
|
||||
|
||||
export function beforeEach(to, from) {
|
||||
const adminMain = document.querySelector('#adminui-main')
|
||||
if (!adminMain) {
|
||||
return false
|
||||
}
|
||||
store.commit('updateViewTags', {
|
||||
const store = viewTagsStore()
|
||||
store.updateViewTags({
|
||||
fullPath: from.fullPath,
|
||||
scrollTop: adminMain.scrollTop
|
||||
})
|
||||
@ -28,7 +29,8 @@ export function afterEach(to) {
|
||||
return false
|
||||
}
|
||||
nextTick(() => {
|
||||
const beforeRoute = store.state.viewTags.viewTags.filter((v) => v.fullPath == to.fullPath)[0]
|
||||
const store = viewTagsStore()
|
||||
const beforeRoute = store.viewTags.filter((v) => v.fullPath == to.fullPath)[0]
|
||||
if (beforeRoute) {
|
||||
adminMain.scrollTop = beforeRoute.scrollTop || 0
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { hasPerm } from './utils/permission/index'
|
||||
import errorHandler from './utils/errorHandler'
|
||||
import customIcons from './assets/icons/index.js'
|
||||
import 'highlight.js/styles/atom-one-dark.css'
|
||||
import 'highlight.js/lib/common'
|
||||
import hljsCommon from 'highlight.js/lib/common'
|
||||
import hljsVuePlugin from '@highlightjs/vue-plugin'
|
||||
import STable from './components/Table/index.vue'
|
||||
import Ellipsis from './components/Ellipsis/index.vue'
|
||||
@ -28,6 +28,8 @@ export default {
|
||||
// 统一注册自定义全局图标
|
||||
app.use(customIcons)
|
||||
// 注册代码高亮组件 (博客:https://blog.csdn.net/weixin_41897680/article/details/124925222)
|
||||
// 注意:解决Vue使用highlight.js build打包发布后样式消失问题,原因是webpack在打包的时候没有把未被使用的代码打包进去,因此,在此处引用一下,看似无意义实则有用
|
||||
hljsCommon.highlightAuto('<h1>Highlight.js has been registered successfully!</h1>').value
|
||||
app.use(hljsVuePlugin)
|
||||
|
||||
// 全局代码错误捕捉
|
||||
|
@ -8,7 +8,8 @@
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
import { changeColor, getLocalSetting } from '@/utils/themeUtil'
|
||||
import { defineStore } from 'pinia'
|
||||
import { changeColor } from '@/utils/themeUtil'
|
||||
import config from '@/config'
|
||||
import { message } from 'ant-design-vue'
|
||||
import tool from '@/utils/tool'
|
||||
@ -25,8 +26,13 @@ const getCacheConfig = (value) => {
|
||||
}
|
||||
return data
|
||||
}
|
||||
export default {
|
||||
state: {
|
||||
|
||||
/**
|
||||
* deprecated 请使用 useGlobalStore
|
||||
*/
|
||||
export const globalStore = defineStore({
|
||||
id: 'global',
|
||||
state: () => ({
|
||||
// 移动端布局
|
||||
ismobile: false,
|
||||
// 布局
|
||||
@ -42,66 +48,55 @@ export default {
|
||||
// 顶栏是否应用主题色
|
||||
topHanderThemeColorOpen: getCacheConfig('SNOWY_TOP_HANDER_THEME_COLOR_OPEN'),
|
||||
// 顶栏主题色通栏
|
||||
topHanderThemeColorSpread:
|
||||
getCacheConfig('SNOWY_TOP_HANDER_THEME_COLOR_SPREAD'),
|
||||
// 目录坞
|
||||
topHanderThemeColorSpread: getCacheConfig('SNOWY_TOP_HANDER_THEME_COLOR_SPREAD'),
|
||||
// 模块坞
|
||||
moduleUnfoldOpen: getCacheConfig('SNOWY_MODULE_UNFOLD_OPEN'),
|
||||
// 主题
|
||||
theme: getCacheConfig('SNOWY_THEME'),
|
||||
// 主题颜色
|
||||
themeColor: toolDataGet('SNOWY_THEME_COLOR') || config.COLOR,
|
||||
// 整体表单风格
|
||||
formStyle: getCacheConfig('SNOWY_FORM_STYLE'),
|
||||
// 用户信息
|
||||
userInfo: toolDataGet('USER_INFO') || {},
|
||||
// 系统配置
|
||||
sysBaseConfig: toolDataGet('SNOWY_SYS_BASE_CONFIG') || config.SYS_BASE_CONFIG
|
||||
},
|
||||
mutations: {
|
||||
SET_ismobile(state, key) {
|
||||
state.ismobile = key
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
setIsmobile(key) {
|
||||
this.ismobile = key
|
||||
},
|
||||
SET_layout(state, key) {
|
||||
state.layout = key
|
||||
setLayout(key) {
|
||||
this.layout = key
|
||||
},
|
||||
SET_theme(state, key) {
|
||||
state.theme = key
|
||||
setTheme(key) {
|
||||
this.theme = key
|
||||
const closeMessage = message.loading(`加载中...`)
|
||||
changeColor(state.themeColor, key).then(closeMessage)
|
||||
changeColor(this.themeColor, key).then(closeMessage)
|
||||
},
|
||||
SET_themeColor(state, key) {
|
||||
state.themeColor = key
|
||||
setThemeColor(key) {
|
||||
this.themeColor = key
|
||||
const closeMessage = message.loading(`加载中...`)
|
||||
changeColor(key, state.theme).then(closeMessage)
|
||||
changeColor(key, this.theme).then(closeMessage)
|
||||
},
|
||||
initTheme(state) {
|
||||
initTheme() {
|
||||
const closeMessage = message.loading(`加载中...`)
|
||||
changeColor(state.themeColor, state.theme).then(closeMessage)
|
||||
changeColor(this.themeColor, this.theme).then(closeMessage)
|
||||
},
|
||||
TOGGLE_menuIsCollapse(state) {
|
||||
state.menuIsCollapse = !state.menuIsCollapse
|
||||
toggleConfig(key) {
|
||||
this[key] = !this[key]
|
||||
},
|
||||
TOGGLE_sideUniqueOpen(state) {
|
||||
state.sideUniqueOpen = !state.sideUniqueOpen
|
||||
setFormStyle(key) {
|
||||
this.formStyle = key
|
||||
},
|
||||
TOGGLE_layoutTagsOpen(state) {
|
||||
state.layoutTagsOpen = !state.layoutTagsOpen
|
||||
setUserInfo(key) {
|
||||
this.userInfo = key
|
||||
},
|
||||
TOGGLE_breadcrumbOpen(state) {
|
||||
state.breadcrumbOpen = !state.breadcrumbOpen
|
||||
},
|
||||
TOGGLE_topHanderThemeColorOpen(state) {
|
||||
state.topHanderThemeColorOpen = !state.topHanderThemeColorOpen
|
||||
},
|
||||
TOGGLE_topHanderThemeColorSpread(state) {
|
||||
state.topHanderThemeColorSpread = !state.topHanderThemeColorSpread
|
||||
},
|
||||
TOGGLE_moduleUnfoldOpen(state) {
|
||||
state.moduleUnfoldOpen = !state.moduleUnfoldOpen
|
||||
},
|
||||
SET_userInfo(state, key) {
|
||||
state.userInfo = key
|
||||
},
|
||||
SET_sysBaseConfig(state, key) {
|
||||
state.sysBaseConfig = key
|
||||
setSysBaseConfig(key) {
|
||||
this.sysBaseConfig = key
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const useGlobalStore = globalStore
|
@ -8,31 +8,34 @@
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
/* eslint-disable eqeqeq */
|
||||
export default {
|
||||
state: {
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const iframeStore = defineStore({
|
||||
id: 'iframe',
|
||||
state: () => ({
|
||||
iframeList: []
|
||||
},
|
||||
mutations: {
|
||||
setIframeList(state, route) {
|
||||
state.iframeList = []
|
||||
state.iframeList.push(route)
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
setIframeList(route) {
|
||||
this.iframeList = []
|
||||
this.iframeList.push(route)
|
||||
},
|
||||
pushIframeList(state, route) {
|
||||
const target = state.iframeList.find((item) => item.path === route.path)
|
||||
pushIframeList(route) {
|
||||
const target = this.iframeList.find((item) => item.path === route.path)
|
||||
if (!target) {
|
||||
state.iframeList.push(route)
|
||||
this.iframeList.push(route)
|
||||
}
|
||||
},
|
||||
removeIframeList(state, route) {
|
||||
state.iframeList.forEach((item, index) => {
|
||||
removeIframeList(route) {
|
||||
this.iframeList.forEach((item, index) => {
|
||||
if (item.path === route.path) {
|
||||
state.iframeList.splice(index, 1)
|
||||
this.iframeList.splice(index, 1)
|
||||
}
|
||||
})
|
||||
},
|
||||
refreshIframe(state, route) {
|
||||
state.iframeList.forEach((item) => {
|
||||
refreshIframe(route) {
|
||||
this.iframeList.forEach((item) => {
|
||||
if (item.path === route.path) {
|
||||
const url = route.meta.url
|
||||
item.meta.url = ''
|
||||
@ -42,8 +45,8 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
clearIframeList(state) {
|
||||
state.iframeList = []
|
||||
clearIframeList() {
|
||||
this.iframeList = []
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
@ -1,25 +1,5 @@
|
||||
/**
|
||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
import { createStore } from 'vuex'
|
||||
|
||||
import global from './modules/global'
|
||||
import iframe from './modules/iframe'
|
||||
import keepAlive from './modules/keepAlive'
|
||||
import viewTags from './modules/viewTags'
|
||||
// 自动import导入所有 vuex 模块
|
||||
export default createStore({
|
||||
modules: {
|
||||
global,
|
||||
iframe,
|
||||
keepAlive,
|
||||
viewTags
|
||||
}
|
||||
})
|
||||
export * from './global'
|
||||
export * from './search'
|
||||
export * from './iframe'
|
||||
export * from './keepAlive'
|
||||
export * from './viewTags'
|
||||
|
@ -8,37 +8,39 @@
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
export default {
|
||||
state: {
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const keepAliveStore = defineStore({
|
||||
id: 'keepAlive',
|
||||
state: () => ({
|
||||
keepLiveRoute: [],
|
||||
routeKey: null,
|
||||
routeShow: true
|
||||
},
|
||||
mutations: {
|
||||
pushKeepLive(state, component) {
|
||||
if (!state.keepLiveRoute.includes(component)) {
|
||||
state.keepLiveRoute.push(component)
|
||||
}
|
||||
},
|
||||
removeKeepLive(state, component) {
|
||||
const index = state.keepLiveRoute.indexOf(component)
|
||||
if (index !== -1) {
|
||||
state.keepLiveRoute.splice(index, 1)
|
||||
}
|
||||
},
|
||||
clearKeepLive(state) {
|
||||
state.keepLiveRoute = []
|
||||
},
|
||||
setRouteKey(state, key) {
|
||||
state.routeKey = key
|
||||
},
|
||||
setRouteShow(state, key) {
|
||||
state.routeShow = key
|
||||
}
|
||||
},
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
setRouteKey({ commit }, key) {
|
||||
commit('setRouteKey', key)
|
||||
pushKeepLive(component) {
|
||||
if (!this.keepLiveRoute.includes(component)) {
|
||||
this.keepLiveRoute.push(component)
|
||||
}
|
||||
},
|
||||
removeKeepLive(component) {
|
||||
const index = this.keepLiveRoute.indexOf(component)
|
||||
if (index !== -1) {
|
||||
this.keepLiveRoute.splice(index, 1)
|
||||
}
|
||||
},
|
||||
clearKeepLive() {
|
||||
this.keepLiveRoute = []
|
||||
},
|
||||
setRouteKey(key) {
|
||||
this.routeKey = key
|
||||
},
|
||||
setRouteShow(key) {
|
||||
this.routeShow = key
|
||||
},
|
||||
setRouteKeyAction(key) {
|
||||
this.setRouteKey(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
57
snowy-admin-web/src/store/search.js
Executable file
57
snowy-admin-web/src/store/search.js
Executable file
@ -0,0 +1,57 @@
|
||||
import '@/utils/objects'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const searchStore = defineStore({
|
||||
id: 'search',
|
||||
state: () => ({
|
||||
active: false,
|
||||
hotkey: {
|
||||
open: 's',
|
||||
close: 'esc'
|
||||
},
|
||||
pool: []
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
toggleActive() {
|
||||
this.active = !this.active
|
||||
},
|
||||
setActive(active) {
|
||||
this.active = active
|
||||
},
|
||||
init(menu) {
|
||||
const pool = []
|
||||
const getFullName = function (meta) {
|
||||
if (meta.breadcrumb) {
|
||||
let list = []
|
||||
meta.breadcrumb.forEach((item) => {
|
||||
list.push(item.meta.title)
|
||||
})
|
||||
return list.join(' / ')
|
||||
}
|
||||
return meta.title
|
||||
}
|
||||
const push = function (menu) {
|
||||
menu.forEach((m) => {
|
||||
if ('menu' === m.meta.type) {
|
||||
if (m.children) {
|
||||
push(m.children)
|
||||
} else if (m.children === null) {
|
||||
pool.push({
|
||||
icon: m.meta.icon,
|
||||
path: m.path,
|
||||
fullPath: m.path,
|
||||
name: m.meta.title,
|
||||
fullName: getFullName(m.meta),
|
||||
namePinyin: m.meta.title.toPinyin(),
|
||||
namePinyinFirst: m.meta.title.toPinyin(true)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
push(menu)
|
||||
this.pool = pool
|
||||
}
|
||||
}
|
||||
})
|
@ -8,43 +8,46 @@
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
/* eslint-disable eqeqeq */
|
||||
export default {
|
||||
state: {
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const viewTagsStore = defineStore({
|
||||
id: 'viewTags',
|
||||
state: () => ({
|
||||
viewTags: []
|
||||
},
|
||||
mutations: {
|
||||
pushViewTags(state, route) {
|
||||
const target = state.viewTags.find((item) => item.fullPath === route.fullPath)
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
pushViewTags(route) {
|
||||
const target = this.viewTags.find((item) => item.fullPath === route.fullPath)
|
||||
const isName = route.name
|
||||
if (!target && isName) {
|
||||
state.viewTags.push(route)
|
||||
this.viewTags.push(route)
|
||||
}
|
||||
},
|
||||
removeViewTags(state, route) {
|
||||
state.viewTags.forEach((item, index) => {
|
||||
removeViewTags(route) {
|
||||
this.viewTags.forEach((item, index) => {
|
||||
if (item.fullPath === route.fullPath) {
|
||||
state.viewTags.splice(index, 1)
|
||||
this.viewTags.splice(index, 1)
|
||||
}
|
||||
})
|
||||
},
|
||||
updateViewTags(state, route) {
|
||||
state.viewTags.forEach((item) => {
|
||||
updateViewTags(route) {
|
||||
this.viewTags.forEach((item) => {
|
||||
if (item.fullPath == route.fullPath) {
|
||||
item = Object.assign(item, route)
|
||||
Object.assign(item, route)
|
||||
}
|
||||
})
|
||||
},
|
||||
updateViewTagsTitle(state, title = '') {
|
||||
updateViewTagsTitle(title = '') {
|
||||
const nowFullPath = location.hash.substring(1)
|
||||
state.viewTags.forEach((item) => {
|
||||
this.viewTags.forEach((item) => {
|
||||
if (item.fullPath == nowFullPath) {
|
||||
item.meta.title = title
|
||||
}
|
||||
})
|
||||
},
|
||||
clearViewTags(state) {
|
||||
state.viewTags = []
|
||||
clearViewTags() {
|
||||
this.viewTags = []
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
@ -7,9 +7,9 @@
|
||||
/* 全局 */
|
||||
/*
|
||||
#app, body, html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f6f8f9;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f6f8f9;
|
||||
}
|
||||
*/
|
||||
.body, html {
|
||||
@ -19,31 +19,31 @@
|
||||
}
|
||||
|
||||
a, button, input, textarea {
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
box-sizing: border-box;
|
||||
outline: none !important;
|
||||
-webkit-appearance: none;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
box-sizing: border-box;
|
||||
outline: none !important;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* 大布局样式 */
|
||||
.aminui {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
||||
|
||||
.aminui-wrapper {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.adminui-main {
|
||||
@ -71,31 +71,31 @@ a, button, input, textarea {
|
||||
|
||||
/* 双排菜单布局 */
|
||||
.snowy-doublerow-layout-menu {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
line-height: 0;
|
||||
align-items: center;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
line-height: 0;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.snowy-doublerow-layout-menu-item-fort-div {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
opacity: 1;
|
||||
display: block;
|
||||
flex: auto;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
opacity: 1;
|
||||
display: block;
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
.snowy-doublerow-layout-menu-item-fort-div-span {
|
||||
font-size: 12px;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 12px;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.snowy-doublerow-side-top {
|
||||
border-bottom: 1px solid var(--border-color-split);
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
padding-left: 20px;
|
||||
font-size: 12px
|
||||
border-bottom: 1px solid var(--border-color-split);
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
padding-left: 20px;
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
// 应用主题色
|
||||
@ -107,49 +107,54 @@ a, button, input, textarea {
|
||||
}
|
||||
|
||||
.snowy-title{
|
||||
color: var(--text-color);
|
||||
color: var(--text-color);
|
||||
}
|
||||
.ant-layout-sider-collapsed{
|
||||
.logo-bar>span{
|
||||
display: none;
|
||||
}
|
||||
.logo-bar>span{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.ant-layout-sider-dark{
|
||||
.snowy-header-logo{
|
||||
color: #fff;
|
||||
}
|
||||
.snowy-header-logo{
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 设置抽屉样式 */
|
||||
.layout-setting {
|
||||
position: fixed;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 3px 0 0 3px;
|
||||
bottom: 50%;
|
||||
right: 0px;
|
||||
z-index: 100;
|
||||
background: @primary-color;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
position: fixed;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 3px 0 0 3px;
|
||||
bottom: 50%;
|
||||
right: 0px;
|
||||
z-index: 100;
|
||||
background: @primary-color;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.layout-setting i {
|
||||
color: #fff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 头部 */
|
||||
.snowy-header {
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid var(--border-color-split);
|
||||
box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
|
||||
background-color: var(--body-background);
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid var(--border-color-split);
|
||||
box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
|
||||
background-color: var(--body-background);
|
||||
|
||||
.ant-menu-item{
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
}
|
||||
}
|
||||
// 应用主题色
|
||||
.snowy-header-primary-color {
|
||||
@ -164,33 +169,38 @@ a, button, input, textarea {
|
||||
.ant-breadcrumb-separator {
|
||||
color: white;
|
||||
}
|
||||
.ant-menu-light .ant-menu-item:hover{
|
||||
color: #ccc;
|
||||
background-color: var(--primary-7);
|
||||
}
|
||||
}
|
||||
|
||||
.ant-layout-sider-dark {
|
||||
.snowy-title{
|
||||
color: #fff;
|
||||
}
|
||||
.snowy-title{
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.snowy-header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.snowy-header-left .menu-unfold-outlined {
|
||||
padding: 0 12px
|
||||
padding: 0 12px
|
||||
}
|
||||
|
||||
.snowy-header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.snowy-header-logo {
|
||||
height: 49px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
|
||||
}
|
||||
|
||||
.snowy-header-logo-primary-color {
|
||||
@ -199,101 +209,112 @@ a, button, input, textarea {
|
||||
}
|
||||
|
||||
.snowy-header-logo .logo-bar {
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.snowy-header-logo .logo-bar .logo {
|
||||
margin-right: 10px;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
margin-right: 10px;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
/* 面包屑 */
|
||||
.adminui-topbar {
|
||||
padding-left: 15px
|
||||
padding-left: 15px
|
||||
}
|
||||
|
||||
.adminui-topbar .left-panel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.adminui-topbar .right-panel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.panel-item {
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.panel-item:hover {
|
||||
background: var(--header-color-split);
|
||||
}
|
||||
|
||||
/* 多标签 */
|
||||
.snowy-tags {
|
||||
height: 40px;
|
||||
background: var(--component-background);
|
||||
height: 40px;
|
||||
background: var(--component-background);
|
||||
}
|
||||
|
||||
.snowy-tags ul {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
padding-left: 0;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.snowy-tags li {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
line-height: 39.5px;
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
line-height: 39.5px;
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.snowy-tags li::after {
|
||||
content: " ";
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
background-image: linear-gradient(#fff, #e6e6e6);
|
||||
content: " ";
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
background-image: linear-gradient(#fff, #e6e6e6);
|
||||
}
|
||||
|
||||
.snowy-tags li a {
|
||||
padding: 0 10px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.snowy-tags li i {
|
||||
margin-left: 10px;
|
||||
border-radius: 3px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 10px;
|
||||
border-radius: 3px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.snowy-tags li i:hover {
|
||||
background: rgba(0, 0, 0, .2);
|
||||
color: @body-background;
|
||||
background: rgba(0, 0, 0, .2);
|
||||
color: @body-background;
|
||||
}
|
||||
|
||||
.snowy-tags li:hover {
|
||||
background: @body-background;
|
||||
background: @body-background;
|
||||
}
|
||||
|
||||
.snowy-tags li.active {
|
||||
background: @primary-color;
|
||||
background: @primary-color;
|
||||
}
|
||||
|
||||
.snowy-tags li.active a {
|
||||
color: #fff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.snowy-tags li.sortable-ghost {
|
||||
opacity: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.snowy-header-tags-right {
|
||||
@ -343,38 +364,37 @@ a, button, input, textarea {
|
||||
|
||||
/*页面最大化*/
|
||||
.aminui.main-maximize {
|
||||
.main-maximize-exit {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ant-layout-sider, .ant-layout-sider-dark, .layout-setting, .snowy-header {
|
||||
display: none;
|
||||
}
|
||||
.main-maximize-exit {
|
||||
display: block;
|
||||
}
|
||||
.ant-layout-sider, .ant-layout-sider-dark, .layout-setting, .snowy-header {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* 最大化后的退出按钮 */
|
||||
.main-maximize-exit {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 3000;
|
||||
top: -20px;
|
||||
padding-top: 18px;
|
||||
left: 50%;
|
||||
margin-left: -20px;
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
cursor: pointer;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
text-align: center;
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 3000;
|
||||
top: -20px;
|
||||
padding-top: 18px;
|
||||
left: 50%;
|
||||
margin-left: -20px;
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
cursor: pointer;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.main-maximize-exit:hover {
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.ant-layout-sider{
|
||||
overflow: auto;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* 重写antdv的一些样式,定义到全局 */
|
||||
@ -388,6 +408,24 @@ a, button, input, textarea {
|
||||
padding: 12px 0!important;
|
||||
}
|
||||
|
||||
/* 重写antdv的表格滚动条 */
|
||||
.ant-table-body {
|
||||
&::-webkit-scrollbar {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
-webkit-box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.1);
|
||||
background: @border-color-split;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
-webkit-box-shadow: 0;
|
||||
border-radius: 10px;
|
||||
background: @background-color-base;
|
||||
}
|
||||
}
|
||||
|
||||
// 滚动条,需要哪里,加哪个class
|
||||
body,
|
||||
.ant-drawer-wrapper-body,
|
||||
@ -407,46 +445,47 @@ body,
|
||||
.org-table,
|
||||
.pos-table,
|
||||
.poi-list,
|
||||
.ant-table-body,
|
||||
.snowy-orgpos-vis,
|
||||
.index-message-list,
|
||||
.ant-picker-time-panel-column,
|
||||
.timeline-div,
|
||||
.gen-preview-content,
|
||||
.ant-menu,
|
||||
|
||||
.adminui-main{
|
||||
&::-webkit-scrollbar {
|
||||
/*滚动条整体样式*/
|
||||
width : 0px; /*高宽分别对应横竖滚动条的尺寸*/
|
||||
height: 0px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
/*滚动条里面小方块*/
|
||||
border-radius : 10px;
|
||||
background-color: @component-background; // skyblue
|
||||
background-image: -webkit-linear-gradient(
|
||||
45deg,
|
||||
rgba(255, 255, 255, 0.2) 25%,
|
||||
transparent 25%,
|
||||
transparent 50%,
|
||||
rgba(255, 255, 255, 0.2) 50%,
|
||||
rgba(255, 255, 255, 0.2) 75%,
|
||||
transparent 75%,
|
||||
transparent
|
||||
);
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
/*滚动条里面轨道*/
|
||||
box-shadow : inset 0 0 2px rgba(0, 0, 0, 0.2);
|
||||
background : @component-background;
|
||||
border-radius: 5px;
|
||||
opacity: 0;
|
||||
display: none;
|
||||
}
|
||||
&::-webkit-scrollbar {
|
||||
/*滚动条整体样式*/
|
||||
width : 0px; /*高宽分别对应横竖滚动条的尺寸*/
|
||||
height: 0px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
/*滚动条里面小方块*/
|
||||
border-radius : 10px;
|
||||
background-color: @component-background; // skyblue
|
||||
background-image: -webkit-linear-gradient(
|
||||
45deg,
|
||||
rgba(255, 255, 255, 0.2) 25%,
|
||||
transparent 25%,
|
||||
transparent 50%,
|
||||
rgba(255, 255, 255, 0.2) 50%,
|
||||
rgba(255, 255, 255, 0.2) 75%,
|
||||
transparent 75%,
|
||||
transparent
|
||||
);
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
/*滚动条里面轨道*/
|
||||
box-shadow : inset 0 0 2px rgba(0, 0, 0, 0.2);
|
||||
background : @component-background;
|
||||
border-radius: 5px;
|
||||
opacity: 0;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.json-box-9136076486841527{
|
||||
overflow: hidden!important;;
|
||||
.CodeMirror-scrollbar-filler{
|
||||
display: none!important;
|
||||
}
|
||||
overflow: hidden!important;;
|
||||
.CodeMirror-scrollbar-filler{
|
||||
display: none!important;
|
||||
}
|
||||
}
|
||||
|
37
snowy-admin-web/src/utils/downloadUtil.js
Normal file
37
snowy-admin-web/src/utils/downloadUtil.js
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
export default {
|
||||
// 对下载的流进行处理,直接从浏览器下载下来
|
||||
resultDownload (res) {
|
||||
if (res.data.type === 'application/json') {
|
||||
// 错误以及无权限
|
||||
const reader = new FileReader(res.data)
|
||||
reader.readAsText(res.data)
|
||||
reader.onload = () => {
|
||||
const result = JSON.parse(reader.result)
|
||||
message.error(result.msg)
|
||||
}
|
||||
} else {
|
||||
const blob = new Blob([res.data], { type: 'application/octet-stream;charset=UTF-8' })
|
||||
const contentDisposition = res.headers['content-disposition']
|
||||
const patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*')
|
||||
const $link = document.createElement('a')
|
||||
$link.href = URL.createObjectURL(blob)
|
||||
$link.download = decodeURIComponent(patt.exec(contentDisposition)[1])
|
||||
$link.click()
|
||||
document.body.appendChild($link)
|
||||
document.body.removeChild($link) // 下载完成移除元素
|
||||
window.URL.revokeObjectURL($link.href) // 释放掉blob对象
|
||||
}
|
||||
}
|
||||
}
|
@ -8,10 +8,10 @@
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
export const required = (text, method = ['blur', 'change']) => ({
|
||||
export const required = (message, trigger = ['blur', 'change']) => ({
|
||||
required: true,
|
||||
message: text,
|
||||
trigger: method
|
||||
message,
|
||||
trigger
|
||||
})
|
||||
|
||||
// 常用正则规则大全:https://any86.github.io/any-rule/
|
||||
@ -42,5 +42,10 @@ export const rules = {
|
||||
pattern: /^\d{1,}$/,
|
||||
message: '填写内容必须是纯数字',
|
||||
trigger: 'blur'
|
||||
},
|
||||
price: {
|
||||
pattern: /(?:^[1-9]([0-9]+)?(?:\.[0-9]{1,2})?$)|(?:^(?:0)$)|(?:^[0-9]\.[0-9](?:[0-9])?$)/,
|
||||
message: '只支持正数金额',
|
||||
trigger: 'blur'
|
||||
}
|
||||
}
|
||||
|
@ -1,85 +0,0 @@
|
||||
/**
|
||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
import { mapState } from 'vuex'
|
||||
import { DEVICE_TYPE, deviceEnquire } from '@/utils/device'
|
||||
|
||||
// const mixinsComputed = Vue.config.optionMergeStrategies.computed
|
||||
// const mixinsMethods = Vue.config.optionMergeStrategies.methods
|
||||
|
||||
const mixin = {
|
||||
computed: {
|
||||
...mapState({
|
||||
layoutMode: (state) => state.app.layout,
|
||||
navTheme: (state) => state.app.theme,
|
||||
primaryColor: (state) => state.app.color,
|
||||
colorWeak: (state) => state.app.weak,
|
||||
fixedHeader: (state) => state.app.fixedHeader,
|
||||
fixSiderbar: (state) => state.app.fixSiderbar,
|
||||
fixSidebar: (state) => state.app.fixSiderbar,
|
||||
contentWidth: (state) => state.app.contentWidth,
|
||||
autoHideHeader: (state) => state.app.autoHideHeader,
|
||||
sidebarOpened: (state) => state.app.sidebar,
|
||||
multiTab: (state) => state.app.multiTab
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
isTopMenu() {
|
||||
return this.layoutMode === 'topmenu'
|
||||
},
|
||||
isSideMenu() {
|
||||
return !this.isTopMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mixinDevice = {
|
||||
computed: {
|
||||
...mapState({
|
||||
device: (state) => state.app.device
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
isMobile() {
|
||||
return this.device === DEVICE_TYPE.MOBILE
|
||||
},
|
||||
isDesktop() {
|
||||
return this.device === DEVICE_TYPE.DESKTOP
|
||||
},
|
||||
isTablet() {
|
||||
return this.device === DEVICE_TYPE.TABLET
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const AppDeviceEnquire = {
|
||||
mounted() {
|
||||
const { $store } = this
|
||||
deviceEnquire((deviceType) => {
|
||||
switch (deviceType) {
|
||||
case DEVICE_TYPE.DESKTOP:
|
||||
$store.commit('TOGGLE_DEVICE', 'desktop')
|
||||
$store.dispatch('setSidebar', true)
|
||||
break
|
||||
case DEVICE_TYPE.TABLET:
|
||||
$store.commit('TOGGLE_DEVICE', 'tablet')
|
||||
$store.dispatch('setSidebar', false)
|
||||
break
|
||||
case DEVICE_TYPE.MOBILE:
|
||||
default:
|
||||
$store.commit('TOGGLE_DEVICE', 'mobile')
|
||||
$store.dispatch('setSidebar', true)
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { mixin, AppDeviceEnquire, mixinDevice }
|
29
snowy-admin-web/src/utils/objects.js
Normal file
29
snowy-admin-web/src/utils/objects.js
Normal file
@ -0,0 +1,29 @@
|
||||
import pinyin from 'js-pinyin'
|
||||
|
||||
// 中文转拼音 传入仅首字母
|
||||
Object.defineProperty(String.prototype, 'toPinyin', {
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
value: function (first) {
|
||||
let str = this
|
||||
if (first) {
|
||||
return pinyin.getCamelChars(str).replace(/\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDE4F]/g, '')
|
||||
}
|
||||
return pinyin.getFullChars(str).replace(/\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDE4F]/g, '')
|
||||
}
|
||||
})
|
||||
|
||||
// 字符检索 传入检索值
|
||||
Object.defineProperty(String.prototype, 'filter', {
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
value: function (input) {
|
||||
let str = this
|
||||
let en = str.toLowerCase().includes(input.toLowerCase())
|
||||
let zhFull = str.toPinyin().toLowerCase().includes(input.toLowerCase())
|
||||
let zhFirst = str.toPinyin(true).toLowerCase().includes(input.toLowerCase())
|
||||
return en || zhFull || zhFirst
|
||||
}
|
||||
})
|
@ -1,156 +0,0 @@
|
||||
/**
|
||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
/* eslint-disable */
|
||||
// 打印类属性、方法定义
|
||||
const Print = function(dom, options) {
|
||||
if (!(this instanceof Print)) return new Print(dom, options)
|
||||
|
||||
this.options = this.extend({
|
||||
noPrint: '.no-print',
|
||||
}, options)
|
||||
|
||||
if ((typeof dom) === 'string') {
|
||||
try {
|
||||
this.dom = document.querySelector(dom)
|
||||
}
|
||||
catch {
|
||||
const createDom = document.createElement('div')
|
||||
createDom.innerHTML = dom
|
||||
this.dom = createDom
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.isDOM(dom)
|
||||
this.dom = this.isDOM(dom) ? dom : dom.$el
|
||||
}
|
||||
|
||||
this.init()
|
||||
}
|
||||
Print.prototype = {
|
||||
init() {
|
||||
const content = this.getStyle() + this.getHtml()
|
||||
this.writeIframe(content)
|
||||
},
|
||||
extend(obj, obj2) {
|
||||
for (const k in obj2) {
|
||||
obj[k] = obj2[k]
|
||||
}
|
||||
return obj
|
||||
},
|
||||
|
||||
getStyle() {
|
||||
let str = ''
|
||||
const styles = document.querySelectorAll('style,link')
|
||||
for (let i = 0; i < styles.length; i++) {
|
||||
str += styles[i].outerHTML
|
||||
}
|
||||
str += `<style>${ this.options.noPrint ? this.options.noPrint : '.no-print'
|
||||
}{display:none;}</style>`
|
||||
str += '<style>html,body{background-color:#fff;}</style>'
|
||||
return str
|
||||
},
|
||||
|
||||
getHtml() {
|
||||
const inputs = document.querySelectorAll('input')
|
||||
const textareas = document.querySelectorAll('textarea')
|
||||
const selects = document.querySelectorAll('select')
|
||||
|
||||
for (let k = 0; k < inputs.length; k++) {
|
||||
if (inputs[k].type == 'checkbox' || inputs[k].type == 'radio') {
|
||||
if (inputs[k].checked == true) {
|
||||
inputs[k].setAttribute('checked', 'checked')
|
||||
}
|
||||
else {
|
||||
inputs[k].removeAttribute('checked')
|
||||
}
|
||||
}
|
||||
else if (inputs[k].type == 'text') {
|
||||
inputs[k].setAttribute('value', inputs[k].value)
|
||||
}
|
||||
else {
|
||||
inputs[k].setAttribute('value', inputs[k].value)
|
||||
}
|
||||
}
|
||||
|
||||
for (let k2 = 0; k2 < textareas.length; k2++) {
|
||||
if (textareas[k2].type == 'textarea') {
|
||||
textareas[k2].innerHTML = textareas[k2].value
|
||||
}
|
||||
}
|
||||
|
||||
for (let k3 = 0; k3 < selects.length; k3++) {
|
||||
if (selects[k3].type == 'select-one') {
|
||||
const child = selects[k3].children
|
||||
for (const i in child) {
|
||||
if (child[i].tagName == 'OPTION') {
|
||||
if (child[i].selected == true) {
|
||||
child[i].setAttribute('selected', 'selected')
|
||||
}
|
||||
else {
|
||||
child[i].removeAttribute('selected')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.dom.outerHTML
|
||||
},
|
||||
|
||||
writeIframe(content) {
|
||||
let w; let doc; const iframe = document.createElement('iframe')
|
||||
const f = document.body.appendChild(iframe)
|
||||
iframe.id = 'myIframe'
|
||||
// iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
|
||||
iframe.setAttribute('style', 'position:absolute;width:0;height:0;top:-10px;left:-10px;')
|
||||
w = f.contentWindow || f.contentDocument
|
||||
doc = f.contentDocument || f.contentWindow.document
|
||||
doc.open()
|
||||
doc.write(content)
|
||||
doc.close()
|
||||
const _this = this
|
||||
iframe.onload = function() {
|
||||
_this.toPrint(w)
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(iframe)
|
||||
}, 100)
|
||||
}
|
||||
},
|
||||
|
||||
toPrint(frameWindow) {
|
||||
try {
|
||||
setTimeout(() => {
|
||||
frameWindow.focus()
|
||||
try {
|
||||
if (!frameWindow.document.execCommand('print', false, null)) {
|
||||
frameWindow.print()
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
frameWindow.print()
|
||||
}
|
||||
frameWindow.close()
|
||||
}, 10)
|
||||
}
|
||||
catch (err) {
|
||||
console.log('err', err)
|
||||
}
|
||||
},
|
||||
isDOM: (typeof HTMLElement === 'object')
|
||||
? function(obj) {
|
||||
return obj instanceof HTMLElement
|
||||
}
|
||||
: function(obj) {
|
||||
return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string'
|
||||
},
|
||||
}
|
||||
|
||||
export default Print
|
@ -10,6 +10,7 @@
|
||||
*/
|
||||
// 统一的请求发送
|
||||
import axios from 'axios'
|
||||
import qs from 'qs'
|
||||
import { Modal, message, notification } from 'ant-design-vue'
|
||||
import sysConfig from '@/config/index'
|
||||
import tool from '@/utils/tool'
|
||||
@ -108,8 +109,25 @@ service.interceptors.response.use(
|
||||
} else {
|
||||
// 统一成功提示
|
||||
const responseUrl = response.config.url
|
||||
const apiNameArray = ['add', 'edit', 'delete', 'update', 'grant', 'reset', 'start', 'stop',
|
||||
'pass', 'disable', 'enable', 'revoke', 'suspend', 'active', 'turn', 'adjust', 'reject']
|
||||
const apiNameArray = [
|
||||
'add',
|
||||
'edit',
|
||||
'delete',
|
||||
'update',
|
||||
'grant',
|
||||
'reset',
|
||||
'start',
|
||||
'stop',
|
||||
'pass',
|
||||
'disable',
|
||||
'enable',
|
||||
'revoke',
|
||||
'suspend',
|
||||
'active',
|
||||
'turn',
|
||||
'adjust',
|
||||
'reject'
|
||||
]
|
||||
apiNameArray.forEach((apiName) => {
|
||||
if (responseUrl.includes(apiName)) {
|
||||
message.success(data.msg)
|
||||
@ -131,37 +149,37 @@ service.interceptors.response.use(
|
||||
}
|
||||
)
|
||||
|
||||
// 适配器, 用于适配不同的请求方式
|
||||
export const baseRequest = (url, value = {}, method = 'post', options = {}) => {
|
||||
url = sysConfig.API_URL + url
|
||||
if (method === 'post') {
|
||||
return service.post(url, value, options)
|
||||
} else if (method === 'get') {
|
||||
return service.get(url, {
|
||||
params: value,
|
||||
...options
|
||||
})
|
||||
return service.get(url, { params: value, ...options })
|
||||
} else if (method === 'formdata') {
|
||||
return service({
|
||||
method: 'post',
|
||||
url,
|
||||
data: value,
|
||||
// 转换数据的方法
|
||||
transformRequest: [
|
||||
function (data) {
|
||||
let ret = ''
|
||||
for (const it in data) {
|
||||
ret += `${encodeURIComponent(it)}=${encodeURIComponent(data[it])}&`
|
||||
}
|
||||
ret = ret.substring(0, ret.length - 1)
|
||||
return ret
|
||||
}
|
||||
],
|
||||
// 设置请求头
|
||||
// form-data表单提交的方式
|
||||
return service.post(url, qs.stringify(value), {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
},
|
||||
...options
|
||||
})
|
||||
} else {
|
||||
// 其他请求方式,例如:put、delete
|
||||
return service({
|
||||
method: method,
|
||||
url: url,
|
||||
data: value,
|
||||
...options
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 模块内的请求, 会自动加上模块的前缀
|
||||
export const moduleRequest =
|
||||
(moduleUrl) =>
|
||||
(url, ...arg) => {
|
||||
return baseRequest(moduleUrl + url, ...arg)
|
||||
}
|
||||
|
||||
export default service
|
||||
|
@ -17,13 +17,9 @@
|
||||
import smCrypto from 'sm-crypto'
|
||||
|
||||
const sm2 = smCrypto.sm2
|
||||
const sm3 = smCrypto.sm3
|
||||
const sm4 = smCrypto.sm4
|
||||
const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为1
|
||||
const publicKey =
|
||||
'04298364ec840088475eae92a591e01284d1abefcda348b47eb324bb521bb03b0b2a5bc393f6b71dabb8f15c99a0050818b56b23f31743b93df9cf8948f15ddb54'
|
||||
const privateKey = '3037723d47292171677ec8bd7dc9af696c7472bc5f251b2cec07e65fdef22e25'
|
||||
const key = '0123456789abcdeffedcba9876543210'
|
||||
|
||||
/**
|
||||
* 国密加解密工具类
|
||||
@ -33,36 +29,8 @@ export default {
|
||||
doSm2Encrypt(msgString) {
|
||||
return sm2.doEncrypt(msgString, publicKey, cipherMode)
|
||||
},
|
||||
// SM2解密
|
||||
doSm2Decrypt(encryptData) {
|
||||
return sm2.doDecrypt(encryptData, privateKey, cipherMode)
|
||||
},
|
||||
// SM2数组加密
|
||||
doSm2ArrayEncrypt(msgString) {
|
||||
return sm2.doEncrypt(msgString, publicKey, cipherMode)
|
||||
},
|
||||
// SM2数组解密
|
||||
doSm2ArrayDecrypt(encryptData) {
|
||||
return sm2.doDecrypt(encryptData, privateKey, cipherMode, { output: 'array' })
|
||||
},
|
||||
// SM3哈希
|
||||
doSm3Hash(msgString) {
|
||||
return sm3(msgString)
|
||||
},
|
||||
// SM4 CBC加密
|
||||
doSm4Encrypt(msgString) {
|
||||
return sm4.encrypt(msgString, key)
|
||||
},
|
||||
// SM4 CBC加密
|
||||
doSm4CbcEncrypt(msgString) {
|
||||
return sm4.encrypt(msgString, key, { mode: 'cbc', iv: 'fedcba98765432100123456789abcdef' })
|
||||
},
|
||||
// SM4 解密
|
||||
doSm4Decrypt(encryptData) {
|
||||
return sm4.decrypt(encryptData, key)
|
||||
},
|
||||
// SM4 CBC解密
|
||||
doSm4CbcDecrypt(encryptData) {
|
||||
return sm4.decrypt(encryptData, key, { mode: 'cbc', iv: 'fedcba98765432100123456789abcdef' })
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
import generate from '@ant-design/colors/lib/generate'
|
||||
import { generate } from '@ant-design/colors';
|
||||
import tool from '../utils/tool'
|
||||
import config from '../config'
|
||||
import { ThemeModeEnum } from './enum'
|
||||
|
@ -14,15 +14,9 @@
|
||||
* @LastEditors: yubaoshan
|
||||
* @LastEditTime: 2022年4月19日10:58:41
|
||||
*/
|
||||
|
||||
const tool = {}
|
||||
|
||||
/**
|
||||
* localStorage
|
||||
*
|
||||
* @author yubaoshan
|
||||
* @date 2022-05-18 22:59
|
||||
*/
|
||||
// localStorage
|
||||
tool.data = {
|
||||
set(table, settings) {
|
||||
const _set = JSON.stringify(settings)
|
||||
@ -46,12 +40,7 @@ tool.data = {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sessionStorage
|
||||
*
|
||||
* @author yubaoshan
|
||||
* @date 2022-05-18 22:59
|
||||
*/
|
||||
// sessionStorage
|
||||
tool.session = {
|
||||
set(table, settings) {
|
||||
const _set = JSON.stringify(settings)
|
||||
@ -74,12 +63,7 @@ tool.session = {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 千分符
|
||||
*
|
||||
* @author yubaoshan
|
||||
* @date 2022-05-18 22:59
|
||||
*/
|
||||
// 千分符
|
||||
tool.groupSeparator = (num) => {
|
||||
num = `${num}`
|
||||
if (!num.includes('.')) num += '.'
|
||||
@ -91,24 +75,12 @@ tool.groupSeparator = (num) => {
|
||||
.replace(/\.$/, '')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有字典数组
|
||||
*
|
||||
* @author yubaoshan
|
||||
* @date 2022-04-08 01:11
|
||||
*/
|
||||
// 获取所有字典数组
|
||||
tool.dictDataAll = () => {
|
||||
return tool.data.get('DICT_TYPE_TREE_DATA')
|
||||
}
|
||||
|
||||
/**
|
||||
* 字典翻译方法
|
||||
* 界面插槽使用方法 {{ $TOOL.dictType('sex', record.sex) }}
|
||||
*
|
||||
* @author yubaoshan
|
||||
* @date 2022-04-08 01:11
|
||||
*/
|
||||
// todo 每次都从localStorage获取并重新解析,会有性能问题,应该在内存中做一层缓存,后面需要优化掉
|
||||
// 字典翻译方法,界面插槽使用方法 {{ $TOOL.dictType('sex', record.sex) }}
|
||||
tool.dictTypeData = (dictValue, value) => {
|
||||
const dictTypeTree = tool.dictDataAll()
|
||||
if (!dictTypeTree) {
|
||||
@ -120,15 +92,10 @@ tool.dictTypeData = (dictValue, value) => {
|
||||
}
|
||||
const children = tree.children
|
||||
const dict = children.find((item) => item.dictValue === value)
|
||||
return dict?.name || '无此字典'
|
||||
return dict ? dict.dictLabel : '无此字典项'
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个code下字典的列表,多用于字典下拉框
|
||||
*
|
||||
* @author yubaoshan
|
||||
* @date 2022-04-08 01:11
|
||||
*/
|
||||
// 获取某个code下字典的列表,多用于字典下拉框
|
||||
tool.dictTypeList = (dictValue) => {
|
||||
const dictTypeTree = tool.dictDataAll()
|
||||
if (!dictTypeTree) {
|
||||
@ -141,12 +108,25 @@ tool.dictTypeList = (dictValue) => {
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成UUID
|
||||
*
|
||||
* @author yubaoshan
|
||||
* @date 2022-05-18 22:59
|
||||
*/
|
||||
// 获取某个code下字典的列表,基于dictTypeList 改进,保留老的,逐步替换
|
||||
tool.dictList = (dictValue) => {
|
||||
const dictTypeTree = tool.dictDataAll()
|
||||
if (!dictTypeTree) {
|
||||
return []
|
||||
}
|
||||
const tree = dictTypeTree.find((item) => item.dictValue === dictValue)
|
||||
if (tree) {
|
||||
return tree.children.map((item) => {
|
||||
return {
|
||||
value: item['dictValue'],
|
||||
label: item['name']
|
||||
}
|
||||
})
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
// 生成UUID
|
||||
tool.snowyUuid = () => {
|
||||
let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
||||
let r = (Math.random() * 16) | 0,
|
||||
|
@ -12,28 +12,29 @@ import { nextTick } from 'vue'
|
||||
import NProgress from 'nprogress'
|
||||
import 'nprogress/nprogress.css'
|
||||
import router from '@/router'
|
||||
import store from '@/store'
|
||||
|
||||
import { iframeStore, keepAliveStore, viewTagsStore } from '@/store'
|
||||
export default {
|
||||
// 刷新标签
|
||||
refresh() {
|
||||
NProgress.start()
|
||||
const keepAlive = keepAliveStore()
|
||||
const route = router.currentRoute.value
|
||||
store.commit('removeKeepLive', route.name)
|
||||
store.commit('setRouteShow', false)
|
||||
keepAlive.removeKeepLive(route.name)
|
||||
keepAlive.setRouteShow(false)
|
||||
nextTick(() => {
|
||||
store.commit('pushKeepLive', route.name)
|
||||
store.commit('setRouteShow', true)
|
||||
keepAlive.pushKeepLive(route.name)
|
||||
keepAlive.setRouteShow(true)
|
||||
NProgress.done()
|
||||
})
|
||||
},
|
||||
// 关闭标签
|
||||
close(tag) {
|
||||
const route = tag || router.currentRoute.value
|
||||
store.commit('removeViewTags', route)
|
||||
store.commit('removeIframeList', route)
|
||||
store.commit('removeKeepLive', route.name)
|
||||
const tagList = store.state.viewTags.viewTags
|
||||
const store = viewTagsStore()
|
||||
store.removeViewTags(route)
|
||||
iframeStore().removeIframeList(route)
|
||||
keepAliveStore().removeKeepLive(route.name)
|
||||
const tagList = store.viewTags
|
||||
const latestView = tagList.slice(-1)[0]
|
||||
if (latestView) {
|
||||
router.push(latestView)
|
||||
@ -44,21 +45,23 @@ export default {
|
||||
// 关闭标签后处理
|
||||
closeNext(next) {
|
||||
const route = router.currentRoute.value
|
||||
store.commit('removeViewTags', route)
|
||||
store.commit('removeIframeList', route)
|
||||
store.commit('removeKeepLive', route.name)
|
||||
const store = viewTagsStore()
|
||||
store.removeViewTags(route)
|
||||
iframeStore().removeIframeList(route)
|
||||
keepAliveStore().removeKeepLive(route.name)
|
||||
if (next) {
|
||||
const tagList = store.state.viewTags.viewTags
|
||||
const tagList = store.viewTags
|
||||
next(tagList)
|
||||
}
|
||||
},
|
||||
// 关闭其他
|
||||
closeOther() {
|
||||
const route = router.currentRoute.value
|
||||
const tagList = [...store.state.viewTags.viewTags]
|
||||
const store = viewTagsStore()
|
||||
const tagList = [...store.viewTags]
|
||||
tagList.forEach((tag) => {
|
||||
// eslint-disable-next-line prettier/prettier
|
||||
if (tag.meta && tag.meta.affix || route.fullPath == tag.fullPath) {
|
||||
if ((tag.meta && tag.meta.affix) || route.fullPath == tag.fullPath) {
|
||||
return true
|
||||
} else {
|
||||
this.close(tag)
|
||||
@ -67,6 +70,6 @@ export default {
|
||||
},
|
||||
// 设置标题
|
||||
setTitle(title) {
|
||||
store.commit('updateViewTagsTitle', title)
|
||||
viewTagsStore().updateViewTagsTitle(title)
|
||||
}
|
||||
}
|
||||
|
@ -92,6 +92,7 @@
|
||||
import router from '@/router'
|
||||
import { required, rules } from '@/utils/formRules'
|
||||
import userCenterApi from '@/api/sys/userCenterApi'
|
||||
import smCrypto from '@/utils/smCrypto'
|
||||
const emailResetFormRef = ref()
|
||||
const emailFormData = ref({})
|
||||
const islogin = ref(false)
|
||||
@ -102,7 +103,7 @@
|
||||
let formRules = ref({})
|
||||
const emailValidCodeReqNo = ref('')
|
||||
|
||||
// 点击获取短信验证码
|
||||
// 点击获取邮箱验证码
|
||||
const getEmailValidCode = () => {
|
||||
formRules.value.email = [required(), rules.email]
|
||||
delete formRules.value.emailValidCode
|
||||
@ -122,8 +123,8 @@
|
||||
|
||||
emailResetFormRef.value.validate().then(() => {
|
||||
emailFormData.value.validCode = emailFormData.value.emailValidCode
|
||||
// delete emailFormData.value.emailValidCode
|
||||
emailFormData.value.validCodeReqNo = emailValidCodeReqNo.value
|
||||
emailFormData.value.newPassword = smCrypto.doSm2Encrypt(emailFormData.value.newPassword)
|
||||
islogin.value = true
|
||||
userCenterApi
|
||||
.userFindPasswordByEmail(emailFormData.value)
|
||||
@ -144,7 +145,6 @@
|
||||
const emailLoginFormModalRef = ref()
|
||||
const emailFormModalData = ref({})
|
||||
const validCodeBase64 = ref('')
|
||||
const validCodeReqNo = ref('')
|
||||
const formModalRules = {
|
||||
validCode: [required(), rules.lettersNum]
|
||||
}
|
||||
@ -158,10 +158,10 @@
|
||||
visible.value = false
|
||||
}
|
||||
const handleOk = () => {
|
||||
// 获取到里面的验证码,并发送短信
|
||||
// 获取到里面的验证码,并发送邮箱
|
||||
emailLoginFormModalRef.value.validate().then(() => {
|
||||
visible.value = false
|
||||
// 发送短信,首先拿到刚刚输入的手机号
|
||||
// 发送邮箱,首先拿到刚刚输入的邮箱
|
||||
emailFormModalData.value.email = emailFormData.value.email
|
||||
// 禁用发送按钮,并设置为倒计时
|
||||
state.value.smsSendBtn = true
|
||||
@ -180,13 +180,15 @@
|
||||
emailValidCodeReqNo.value = data
|
||||
visible.value = false
|
||||
setTimeout(hide, 500)
|
||||
emailFormModalData.value.validCode = ''
|
||||
})
|
||||
.catch(() => {
|
||||
setTimeout(hide, 100)
|
||||
clearInterval(interval)
|
||||
state.value.smsSendBtn = false
|
||||
})
|
||||
.finally(() => {
|
||||
emailFormModalData.value.validCode = ''
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
@ -93,6 +93,7 @@
|
||||
import router from '@/router'
|
||||
import { required, rules } from '@/utils/formRules'
|
||||
import userCenterApi from '@/api/sys/userCenterApi'
|
||||
import smCrypto from '@/utils/smCrypto'
|
||||
const phoneLoginFormRef = ref()
|
||||
const phoneFormData = ref({})
|
||||
const islogin = ref(false)
|
||||
@ -123,8 +124,8 @@
|
||||
|
||||
phoneLoginFormRef.value.validate().then(() => {
|
||||
phoneFormData.value.validCode = phoneFormData.value.phoneValidCode
|
||||
// delete phoneFormData.value.phoneValidCode
|
||||
phoneFormData.value.validCodeReqNo = phoneValidCodeReqNo.value
|
||||
phoneFormData.value.newPassword = smCrypto.doSm2Encrypt(phoneFormData.value.newPassword)
|
||||
islogin.value = true
|
||||
userCenterApi
|
||||
.userFindPasswordByPhone(phoneFormData.value)
|
||||
@ -145,7 +146,6 @@
|
||||
const phoneLoginFormModalRef = ref()
|
||||
const phoneFormModalData = ref({})
|
||||
const validCodeBase64 = ref('')
|
||||
const validCodeReqNo = ref('')
|
||||
const formModalRules = {
|
||||
validCode: [required(), rules.lettersNum]
|
||||
}
|
||||
@ -181,13 +181,15 @@
|
||||
phoneValidCodeReqNo.value = data
|
||||
visible.value = false
|
||||
setTimeout(hide, 500)
|
||||
phoneFormModalData.value.validCode = ''
|
||||
})
|
||||
.catch(() => {
|
||||
setTimeout(hide, 100)
|
||||
clearInterval(interval)
|
||||
state.value.smsSendBtn = false
|
||||
})
|
||||
.finally(() => {
|
||||
phoneFormModalData.value.validCode = ''
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
@ -8,7 +8,7 @@
|
||||
<h2>三方登录</h2>
|
||||
</div>
|
||||
<a-spin tip="正在登录中...">
|
||||
<div style="height: 300px">
|
||||
<div class="h-[300px]">
|
||||
<a-skeleton />
|
||||
</div>
|
||||
</a-spin>
|
||||
@ -20,7 +20,6 @@
|
||||
|
||||
<script setup name="loginCallback">
|
||||
import { message } from 'ant-design-vue'
|
||||
import { nextTick } from 'vue'
|
||||
import tool from '@/utils/tool'
|
||||
import router from '@/router'
|
||||
import thirdApi from '@/api/auth/thirdApi'
|
||||
@ -31,24 +30,21 @@
|
||||
|
||||
onMounted(() => {
|
||||
// 获取当前url
|
||||
const url = window.location.href
|
||||
let parameter = url.split('?')[1]
|
||||
if (!parameter) {
|
||||
// 这个界面无参数属于非法访问,跳转到登录界面让他登录去
|
||||
window.location.href = '/login'
|
||||
}
|
||||
const parameterArray = parameter.split('&')
|
||||
const url = new URL(window.location.href)
|
||||
let argLength = 0
|
||||
const params = {}
|
||||
url.searchParams.forEach((value, key) => {
|
||||
argLength += 1
|
||||
params[key] = value
|
||||
})
|
||||
// 当然了,不可能只有一个参数
|
||||
if (!parameterArray) {
|
||||
if (argLength < 2) {
|
||||
window.location.href = '/login'
|
||||
return
|
||||
}
|
||||
const parameterObject = {}
|
||||
// 遍历数组,拿到json对象
|
||||
for (let i = 0; i < parameterArray.length; i++) {
|
||||
parameterObject[parameterArray[i].split('=')[0]] = parameterArray[i].split('=')[1]
|
||||
}
|
||||
|
||||
thirdApi
|
||||
.thirdCallback(parameterObject)
|
||||
.thirdCallback(params)
|
||||
.then((data) => {
|
||||
tool.data.set('TOKEN', data)
|
||||
// 获取登录的用户信息
|
||||
@ -64,11 +60,9 @@
|
||||
path: indexMenu
|
||||
})
|
||||
message.success('登录成功')
|
||||
nextTick(() => {
|
||||
dictApi.dictTree().then((dictData) => {
|
||||
// 设置字典到store中
|
||||
tool.data.set('DICT_TYPE_TREE_DATA', dictData)
|
||||
})
|
||||
dictApi.dictTree().then((dictData) => {
|
||||
// 设置字典到store中
|
||||
tool.data.set('DICT_TYPE_TREE_DATA', dictData)
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -79,155 +73,5 @@
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.login_background {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-image: url(/img/login_background.png);
|
||||
}
|
||||
.login_background_front {
|
||||
width: 450px;
|
||||
height: 450px;
|
||||
margin-left: 100px;
|
||||
margin-top: 15%;
|
||||
overflow: hidden;
|
||||
/*position: relative;*/
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-image: url(/img/login_background_front.png);
|
||||
animation-name: myfirst;
|
||||
animation-duration: 5s;
|
||||
animation-timing-function: linear;
|
||||
animation-delay: 1s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-direction: alternate;
|
||||
animation-play-state: running;
|
||||
/* Safari and Chrome: */
|
||||
-webkit-animation-name: myfirst;
|
||||
-webkit-animation-duration: 5s;
|
||||
-webkit-animation-timing-function: linear;
|
||||
-webkit-animation-delay: 1s;
|
||||
-webkit-animation-iteration-count: infinite;
|
||||
-webkit-animation-direction: alternate;
|
||||
-webkit-animation-play-state: running;
|
||||
}
|
||||
@keyframes myfirst {
|
||||
0% {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
50% {
|
||||
left: 50px;
|
||||
top: 0px;
|
||||
}
|
||||
100% {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes myfirst /* Safari and Chrome */ {
|
||||
0% {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
50% {
|
||||
left: 50px;
|
||||
top: 0px;
|
||||
}
|
||||
100% {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
.login_adv__title h2 {
|
||||
font-size: 40px;
|
||||
}
|
||||
.login_adv__title h4 {
|
||||
font-size: 18px;
|
||||
margin-top: 10px;
|
||||
font-weight: normal;
|
||||
}
|
||||
.login_adv__title p {
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
line-height: 1.8;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
.login_adv__title div {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.login_adv__title div span {
|
||||
margin-right: 15px;
|
||||
}
|
||||
.login_adv__title div i {
|
||||
font-size: 40px;
|
||||
}
|
||||
.login_adv__title div i.add {
|
||||
font-size: 20px;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
/*background-image:linear-gradient(transparent, #000);*/
|
||||
.login_main {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
}
|
||||
.login-form {
|
||||
top: 15%;
|
||||
right: 15%;
|
||||
position: absolute;
|
||||
width: 450px;
|
||||
margin-left: 10%;
|
||||
margin-top: 20px;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.login-header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.login-header .logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.login-header .logo img {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
vertical-align: bottom;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.login-header .logo label {
|
||||
font-size: 24px;
|
||||
}
|
||||
.login-header h2 {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin-top: 40px;
|
||||
}
|
||||
.login_config {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
@media (max-width: 1200px) {
|
||||
.login-form {
|
||||
width: 340px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 1000px) {
|
||||
.login_main {
|
||||
display: block;
|
||||
}
|
||||
.login_background_front {
|
||||
display: none;
|
||||
}
|
||||
.login-form {
|
||||
width: 100%;
|
||||
padding: 20px 40px;
|
||||
right: 0 !important;
|
||||
top: 0 !important;
|
||||
}
|
||||
}
|
||||
@import 'login';
|
||||
</style>
|
||||
|
152
snowy-admin-web/src/views/auth/login/login.less
Normal file
152
snowy-admin-web/src/views/auth/login/login.less
Normal file
@ -0,0 +1,152 @@
|
||||
.login-icon-gray {
|
||||
color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.login-validCode-img {
|
||||
border: 1px solid var(--border-color-split);
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
}
|
||||
.login_background {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-image: url(/img/login_background.png);
|
||||
}
|
||||
.login_background_front {
|
||||
width: 450px;
|
||||
height: 450px;
|
||||
margin-left: 100px;
|
||||
margin-top: 15%;
|
||||
overflow: hidden;
|
||||
/*position: relative;*/
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-image: url(/img/login_background_front.png);
|
||||
animation-name: myfirst;
|
||||
animation-duration: 5s;
|
||||
animation-timing-function: linear;
|
||||
animation-delay: 1s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-direction: alternate;
|
||||
animation-play-state: running;
|
||||
}
|
||||
@keyframes myfirst {
|
||||
0% {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
50% {
|
||||
left: 50px;
|
||||
top: 0px;
|
||||
}
|
||||
100% {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes myfirst /* Safari and Chrome */ {
|
||||
0% {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
50% {
|
||||
left: 50px;
|
||||
top: 0px;
|
||||
}
|
||||
100% {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
.login_adv__title h2 {
|
||||
font-size: 40px;
|
||||
}
|
||||
.login_adv__title h4 {
|
||||
font-size: 18px;
|
||||
margin-top: 10px;
|
||||
font-weight: normal;
|
||||
}
|
||||
.login_adv__title p {
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
line-height: 1.8;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
.login_adv__title div {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.login_adv__title div span {
|
||||
margin-right: 15px;
|
||||
}
|
||||
.login_adv__title div i {
|
||||
font-size: 40px;
|
||||
}
|
||||
.login_adv__title div i.add {
|
||||
font-size: 20px;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
/*background-image:linear-gradient(transparent, #000);*/
|
||||
.login_main {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
}
|
||||
.login-form {
|
||||
top: 15%;
|
||||
right: 15%;
|
||||
position: absolute;
|
||||
width: 450px;
|
||||
margin-left: 10%;
|
||||
margin-top: 20px;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.login-header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.login-header .logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.login-header .logo img {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
vertical-align: bottom;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.login-header .logo label {
|
||||
font-size: 24px;
|
||||
}
|
||||
.login-header h2 {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin-top: 40px;
|
||||
}
|
||||
.login_config {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
@media (max-width: 1200px) {
|
||||
.login-form {
|
||||
width: 340px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 1000px) {
|
||||
.login_main {
|
||||
display: block;
|
||||
}
|
||||
.login_background_front {
|
||||
display: none;
|
||||
}
|
||||
.login-form {
|
||||
width: 100%;
|
||||
padding: 20px 40px;
|
||||
right: 0 !important;
|
||||
top: 0 !important;
|
||||
}
|
||||
}
|
@ -33,9 +33,14 @@
|
||||
<a-tab-pane key="userAccount" :tab="$t('login.accountPassword')">
|
||||
<a-form ref="loginForm" :model="ruleForm" :rules="rules">
|
||||
<a-form-item name="account">
|
||||
<a-input v-model:value="ruleForm.account" :placeholder="$t('login.accountPlaceholder')" size="large">
|
||||
<a-input
|
||||
v-model:value="ruleForm.account"
|
||||
:placeholder="$t('login.accountPlaceholder')"
|
||||
size="large"
|
||||
@keyup.enter="login"
|
||||
>
|
||||
<template #prefix>
|
||||
<UserOutlined style="color: rgba(0, 0, 0, 0.25)" />
|
||||
<UserOutlined class="login-icon-gray" />
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
@ -45,31 +50,29 @@
|
||||
:placeholder="$t('login.PWPlaceholder')"
|
||||
size="large"
|
||||
autocomplete="off"
|
||||
@keyup.enter="login"
|
||||
>
|
||||
<template #prefix>
|
||||
<LockOutlined style="color: rgba(0, 0, 0, 0.25)" />
|
||||
<LockOutlined class="login-icon-gray" />
|
||||
</template>
|
||||
</a-input-password>
|
||||
</a-form-item>
|
||||
<a-form-item name="validCode" v-if="sysBaseConfig.SNOWY_SYS_DEFAULT_CAPTCHA_OPEN === 'true'">
|
||||
<a-form-item name="validCode" v-if="captchaOpen === 'true'">
|
||||
<a-row :gutter="8">
|
||||
<a-col :span="17">
|
||||
<a-input
|
||||
v-model:value="ruleForm.validCode"
|
||||
:placeholder="$t('login.validLaceholder')"
|
||||
size="large"
|
||||
@keyup.enter="login"
|
||||
>
|
||||
<template #prefix>
|
||||
<verified-outlined style="color: rgba(0, 0, 0, 0.25)" />
|
||||
<verified-outlined class="login-icon-gray" />
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="7">
|
||||
<img
|
||||
:src="validCodeBase64"
|
||||
style="border: 1px solid var(--border-color-split); cursor: pointer; width: 100%; height: 40px"
|
||||
@click="loginCaptcha"
|
||||
/>
|
||||
<img :src="validCodeBase64" class="login-validCode-img" @click="loginCaptcha" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form-item>
|
||||
@ -78,7 +81,7 @@
|
||||
<a href="/findpwd" style="color: #0d84ff">{{ $t('login.forgetPassword') }}?</a>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button type="primary" style="width: 100%" :loading="islogin" round size="large" @click="login"
|
||||
<a-button type="primary" class="w-full" :loading="loading" round size="large" @click="login"
|
||||
>{{ $t('login.signIn') }}
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
@ -97,13 +100,19 @@
|
||||
|
||||
<script>
|
||||
import loginApi from '@/api/auth/loginApi'
|
||||
import userCenterApi from '@/api/sys/userCenterApi'
|
||||
import dictApi from '@/api/dev/dictApi'
|
||||
import phoneLoginForm from './phoneLoginForm.vue'
|
||||
import threeLogin from './threeLogin.vue'
|
||||
import smCrypto from '@/utils/smCrypto'
|
||||
import { required } from '@/utils/formRules'
|
||||
import { afterLogin } from './util'
|
||||
import config from '@/config'
|
||||
import configApi from '@/api/dev/configApi'
|
||||
import tool from '@/utils/tool'
|
||||
import { globalStore, iframeStore, keepAliveStore, viewTagsStore } from '@/store'
|
||||
import { mapActions, mapState } from 'pinia'
|
||||
|
||||
export default {
|
||||
name: 'Login',
|
||||
components: {
|
||||
phoneLoginForm,
|
||||
threeLogin
|
||||
@ -111,7 +120,7 @@
|
||||
data() {
|
||||
return {
|
||||
activeKey: 'userAccount',
|
||||
sysBaseConfig: this.$TOOL.data.get('SNOWY_SYS_BASE_CONFIG') || this.$store.state.global.sysBaseConfig,
|
||||
captchaOpen: config.SYS_BASE_CONFIG.SNOWY_SYS_DEFAULT_CAPTCHA_OPEN,
|
||||
validCodeBase64: '',
|
||||
ruleForm: {
|
||||
account: 'superAdmin',
|
||||
@ -121,13 +130,13 @@
|
||||
autologin: false
|
||||
},
|
||||
rules: {
|
||||
account: [{ required: true, message: this.$t('login.accountError'), trigger: 'blur' }],
|
||||
password: [{ required: true, message: this.$t('login.PWError'), trigger: 'blur' }]
|
||||
account: [required(this.$t('login.accountError'), 'blur')],
|
||||
password: [required(this.$t('login.PWError'), 'blur')]
|
||||
},
|
||||
islogin: false,
|
||||
loading: false,
|
||||
config: {
|
||||
lang: this.$TOOL.data.get('APP_LANG') || this.$CONFIG.LANG,
|
||||
theme: this.$TOOL.data.get('APP_THEME') || 'default'
|
||||
lang: tool.data.get('APP_LANG') || this.$CONFIG.LANG,
|
||||
theme: tool.data.get('APP_THEME') || 'default'
|
||||
},
|
||||
lang: [
|
||||
{
|
||||
@ -142,9 +151,7 @@
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
sysBaseConfigWatch() {
|
||||
return this.$store.state.global.sysBaseConfig
|
||||
}
|
||||
...mapState(globalStore, ['sysBaseConfig']),
|
||||
},
|
||||
watch: {
|
||||
'config.theme': function (val) {
|
||||
@ -152,41 +159,41 @@
|
||||
},
|
||||
'config.lang': function (val) {
|
||||
this.$i18n.locale = val
|
||||
this.$TOOL.data.set('APP_LANG', val)
|
||||
},
|
||||
sysBaseConfigWatch(val) {
|
||||
this.sysBaseConfig = val
|
||||
this.refreshSwitch()
|
||||
tool.data.set('APP_LANG', val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$store.commit('clearViewTags')
|
||||
this.$store.commit('clearKeepLive')
|
||||
this.$store.commit('clearIframeList')
|
||||
this.clearViewTags()
|
||||
this.clearKeepLive()
|
||||
this.clearIframeList()
|
||||
},
|
||||
mounted() {
|
||||
this.refreshSwitch()
|
||||
// 获取回车键事件
|
||||
document.onkeydown = (e) => {
|
||||
if (e.defaultPrevented) {
|
||||
return;
|
||||
let formData = ref(config.SYS_BASE_CONFIG)
|
||||
configApi.configSysBaseList().then((data) => {
|
||||
if (data) {
|
||||
data.forEach((item) => {
|
||||
formData.value[item.configKey] = item.configValue
|
||||
})
|
||||
this.captchaOpen = formData.value.SNOWY_SYS_DEFAULT_CAPTCHA_OPEN
|
||||
tool.data.set('SNOWY_SYS_BASE_CONFIG', formData.value)
|
||||
this.setSysBaseConfig(formData.value)
|
||||
this.refreshSwitch()
|
||||
}
|
||||
const body = document.getElementsByTagName('body')[0];
|
||||
// match(浏览器中的地址,不需要包括https、http或者www),是为了防止其他页面触发
|
||||
if (e.keyCode === 13 && e.target.baseURI.match("/login") && e.target === body) {
|
||||
this.login()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
...mapActions(keepAliveStore, ['clearKeepLive']),
|
||||
...mapActions(viewTagsStore, ['clearViewTags']),
|
||||
...mapActions(iframeStore, ['clearIframeList']),
|
||||
...mapActions(globalStore, ['setSysBaseConfig']),
|
||||
// 通过开关加载内容
|
||||
refreshSwitch() {
|
||||
// 判断是否开启验证码
|
||||
if (this.sysBaseConfig.SNOWY_SYS_DEFAULT_CAPTCHA_OPEN === 'true') {
|
||||
if (this.captchaOpen === 'true') {
|
||||
// 加载验证码
|
||||
this.loginCaptcha()
|
||||
// 加入校验
|
||||
this.rules.validCode = [{ required: true, message: this.$t('login.validError'), trigger: 'blur' }]
|
||||
this.rules.validCode = [required(this.$t('login.validError'), 'blur')]
|
||||
}
|
||||
},
|
||||
// 获取验证码
|
||||
@ -198,45 +205,23 @@
|
||||
},
|
||||
// 用户名密码登录
|
||||
async login() {
|
||||
const validate = await this.$refs.loginForm.validate().catch(() => {})
|
||||
if (!validate) return false
|
||||
|
||||
this.islogin = true
|
||||
const loginData = {
|
||||
account: this.ruleForm.account,
|
||||
// 密码进行SM2加密,传输过程中看到的只有密文,后端存储使用hash
|
||||
password: smCrypto.doSm2Encrypt(this.ruleForm.password),
|
||||
validCode: this.ruleForm.validCode,
|
||||
validCodeReqNo: this.ruleForm.validCodeReqNo
|
||||
}
|
||||
// 获取token
|
||||
const login = await loginApi.login(loginData).finally(() => {
|
||||
this.islogin = false
|
||||
})
|
||||
this.$TOOL.data.set('TOKEN', login)
|
||||
// 获取登录的用户信息
|
||||
const loginUser = await loginApi.getLoginUser()
|
||||
this.$TOOL.data.set('USER_INFO', loginUser)
|
||||
|
||||
// 获取用户的菜单
|
||||
const menu = await userCenterApi.userLoginMenu().catch(() => {
|
||||
this.islogin = false
|
||||
return
|
||||
})
|
||||
this.islogin = false
|
||||
const indexMenu = menu[0].children[0].path
|
||||
this.$TOOL.data.set('MENU', menu)
|
||||
// 重置系统默认应用
|
||||
this.$TOOL.data.set('SNOWY_MENU_MODULE_ID', menu[0].id)
|
||||
this.$router.replace({
|
||||
path: indexMenu
|
||||
})
|
||||
this.$message.success('登录成功')
|
||||
this.$nextTick(() => {
|
||||
dictApi.dictTree().then((data) => {
|
||||
// 设置字典到store中
|
||||
this.$TOOL.data.set('DICT_TYPE_TREE_DATA', data)
|
||||
})
|
||||
this.$refs.loginForm.validate().then(async () => {
|
||||
this.loading = true
|
||||
const loginData = {
|
||||
account: this.ruleForm.account,
|
||||
// 密码进行SM2加密,传输过程中看到的只有密文,后端存储使用hash
|
||||
password: smCrypto.doSm2Encrypt(this.ruleForm.password),
|
||||
validCode: this.ruleForm.validCode,
|
||||
validCodeReqNo: this.ruleForm.validCodeReqNo
|
||||
}
|
||||
// 获取token
|
||||
try {
|
||||
const loginToken = await loginApi.login(loginData)
|
||||
afterLogin(loginToken)
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
this.loginCaptcha()
|
||||
}
|
||||
})
|
||||
},
|
||||
configLang(key) {
|
||||
@ -246,156 +231,6 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.login_background {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-image: url(/img/login_background.png);
|
||||
}
|
||||
.login_background_front {
|
||||
width: 450px;
|
||||
height: 450px;
|
||||
margin-left: 100px;
|
||||
margin-top: 15%;
|
||||
overflow: hidden;
|
||||
/*position: relative;*/
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-image: url(/img/login_background_front.png);
|
||||
animation-name: myfirst;
|
||||
animation-duration: 5s;
|
||||
animation-timing-function: linear;
|
||||
animation-delay: 1s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-direction: alternate;
|
||||
animation-play-state: running;
|
||||
/* Safari and Chrome: */
|
||||
-webkit-animation-name: myfirst;
|
||||
-webkit-animation-duration: 5s;
|
||||
-webkit-animation-timing-function: linear;
|
||||
-webkit-animation-delay: 1s;
|
||||
-webkit-animation-iteration-count: infinite;
|
||||
-webkit-animation-direction: alternate;
|
||||
-webkit-animation-play-state: running;
|
||||
}
|
||||
@keyframes myfirst {
|
||||
0% {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
50% {
|
||||
left: 50px;
|
||||
top: 0px;
|
||||
}
|
||||
100% {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes myfirst /* Safari and Chrome */ {
|
||||
0% {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
50% {
|
||||
left: 50px;
|
||||
top: 0px;
|
||||
}
|
||||
100% {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
.login_adv__title h2 {
|
||||
font-size: 40px;
|
||||
}
|
||||
.login_adv__title h4 {
|
||||
font-size: 18px;
|
||||
margin-top: 10px;
|
||||
font-weight: normal;
|
||||
}
|
||||
.login_adv__title p {
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
line-height: 1.8;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
.login_adv__title div {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.login_adv__title div span {
|
||||
margin-right: 15px;
|
||||
}
|
||||
.login_adv__title div i {
|
||||
font-size: 40px;
|
||||
}
|
||||
.login_adv__title div i.add {
|
||||
font-size: 20px;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
/*background-image:linear-gradient(transparent, #000);*/
|
||||
.login_main {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
}
|
||||
.login-form {
|
||||
top: 15%;
|
||||
right: 15%;
|
||||
position: absolute;
|
||||
width: 450px;
|
||||
margin-left: 10%;
|
||||
margin-top: 20px;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.login-header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.login-header .logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.login-header .logo img {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
vertical-align: bottom;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.login-header .logo label {
|
||||
font-size: 24px;
|
||||
}
|
||||
.login-header h2 {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin-top: 40px;
|
||||
}
|
||||
.login_config {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
@media (max-width: 1200px) {
|
||||
.login-form {
|
||||
width: 340px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 1000px) {
|
||||
.login_main {
|
||||
display: block;
|
||||
}
|
||||
.login_background_front {
|
||||
display: none;
|
||||
}
|
||||
.login-form {
|
||||
width: 100%;
|
||||
padding: 20px 40px;
|
||||
right: 0 !important;
|
||||
top: 0 !important;
|
||||
}
|
||||
}
|
||||
<style lang="less">
|
||||
@import 'login';
|
||||
</style>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<a-form-item name="phone">
|
||||
<a-input v-model:value="phoneFormData.phone" :placeholder="$t('login.phonePlaceholder')" size="large">
|
||||
<template #prefix>
|
||||
<mobile-outlined style="color: rgba(0, 0, 0, 0.25)" />
|
||||
<mobile-outlined class="text-black text-opacity-25" />
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
@ -16,21 +16,21 @@
|
||||
size="large"
|
||||
>
|
||||
<template #prefix>
|
||||
<mail-outlined style="color: rgba(0, 0, 0, 0.25)" />
|
||||
<mail-outlined class="text-black text-opacity-25" />
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="7">
|
||||
<a-button size="large" style="width: 100%" @click="getPhoneValidCode" :disabled="state.smsSendBtn">{{
|
||||
(!state.smsSendBtn && $t('login.getSmsCode')) || state.time + ' s'
|
||||
}}</a-button>
|
||||
<a-button size="large" style="width: 100%" @click="getPhoneValidCode" :disabled="state.smsSendBtn">
|
||||
{{ (!state.smsSendBtn && $t('login.getSmsCode')) || state.time + ' s' }}
|
||||
</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button type="primary" style="width: 100%" :loading="islogin" round size="large" @click="submitLogin">{{
|
||||
$t('login.signIn')
|
||||
}}</a-button>
|
||||
<a-button type="primary" style="width: 100%" :loading="loading" round size="large" @click="submitLogin">
|
||||
{{ $t('login.signIn') }}
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<a-modal
|
||||
@ -50,7 +50,7 @@
|
||||
size="large"
|
||||
>
|
||||
<template #prefix>
|
||||
<verified-outlined style="color: rgba(0, 0, 0, 0.25)" />
|
||||
<verified-outlined class="text-black text-opacity-25" />
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
@ -69,16 +69,13 @@
|
||||
|
||||
<script setup name="smsLoginForm">
|
||||
import { message } from 'ant-design-vue'
|
||||
import { nextTick } from 'vue'
|
||||
import tool from '@/utils/tool'
|
||||
import router from '@/router'
|
||||
import { required, rules } from '@/utils/formRules'
|
||||
import loginApi from '@/api/auth/loginApi'
|
||||
import userCenterApi from '@/api/sys/userCenterApi'
|
||||
import dictApi from '@/api/dev/dictApi'
|
||||
import { afterLogin } from './util'
|
||||
|
||||
const phoneLoginFormRef = ref()
|
||||
const phoneFormData = ref({})
|
||||
const islogin = ref(false)
|
||||
const loading = ref(false)
|
||||
let state = ref({
|
||||
time: 60,
|
||||
smsSendBtn: false
|
||||
@ -109,36 +106,13 @@
|
||||
// delete phoneFormData.value.phoneValidCode
|
||||
phoneFormData.value.validCodeReqNo = phoneValidCodeReqNo.value
|
||||
|
||||
islogin.value = true
|
||||
const token = await loginApi.loginByPhone(phoneFormData.value).finally(() => {
|
||||
islogin.value = false
|
||||
})
|
||||
|
||||
tool.data.set('TOKEN', token)
|
||||
// 获取登录的用户信息
|
||||
const loginUser = await loginApi.getLoginUser()
|
||||
tool.data.set('USER_INFO', loginUser)
|
||||
|
||||
// 获取用户的菜单
|
||||
const menu = await userCenterApi.userLoginMenu().catch(() => {
|
||||
islogin.value = false
|
||||
return
|
||||
})
|
||||
islogin.value = false
|
||||
const indexMenu = menu[0].children[0].path
|
||||
tool.data.set('MENU', menu)
|
||||
// 重置系统默认应用
|
||||
tool.data.set('SNOWY_MENU_MODULE_ID', menu[0].id)
|
||||
router.replace({
|
||||
path: indexMenu
|
||||
})
|
||||
message.success('登录成功')
|
||||
nextTick(() => {
|
||||
dictApi.dictTree().then((data) => {
|
||||
// 设置字典到store中
|
||||
tool.data.set('DICT_TYPE_TREE_DATA', data)
|
||||
})
|
||||
})
|
||||
loading.value = true
|
||||
try {
|
||||
const token = await loginApi.loginByPhone(phoneFormData.value)
|
||||
afterLogin(token)
|
||||
} catch (err) {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 弹框的
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<a-divider>{{ $t('login.signInOther') }}</a-divider>
|
||||
<div class="login-oauth">
|
||||
<div class="login-oauth layout-center">
|
||||
<a-space align="start">
|
||||
<a @click="getLoginRenderUrl('gitee')"><GiteeIcon /></a>
|
||||
<a-button type="primary" shape="circle">
|
||||
@ -23,9 +23,4 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.login-oauth {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
35
snowy-admin-web/src/views/auth/login/util.js
Normal file
35
snowy-admin-web/src/views/auth/login/util.js
Normal file
@ -0,0 +1,35 @@
|
||||
import loginApi from '@/api/auth/loginApi'
|
||||
import userCenterApi from '@/api/sys/userCenterApi'
|
||||
import dictApi from '@/api/dev/dictApi'
|
||||
import router from '@/router'
|
||||
import tool from '@/utils/tool'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { useGlobalStore } from '@/store'
|
||||
|
||||
export const afterLogin = async (loginToken) => {
|
||||
tool.data.set('TOKEN', loginToken)
|
||||
// 获取登录的用户信息
|
||||
const loginUser = await loginApi.getLoginUser()
|
||||
const globalStore = useGlobalStore()
|
||||
globalStore.setUserInfo(loginUser)
|
||||
tool.data.set('USER_INFO', loginUser)
|
||||
|
||||
// 获取用户的菜单
|
||||
const menu = await userCenterApi.userLoginMenu()
|
||||
let indexMenu = menu[0].children[0].path
|
||||
tool.data.set('MENU', menu)
|
||||
// 重置系统默认应用
|
||||
tool.data.set('SNOWY_MENU_MODULE_ID', menu[0].id)
|
||||
message.success('登录成功')
|
||||
if (!!tool.data.get('LAST_VIEWS_PATH')) {
|
||||
// 如果有缓存,将其登录跳转到最后访问的路由
|
||||
indexMenu = tool.data.get('LAST_VIEWS_PATH')
|
||||
}
|
||||
await router.replace({
|
||||
path: indexMenu
|
||||
})
|
||||
dictApi.dictTree().then((data) => {
|
||||
// 设置字典到store中
|
||||
tool.data.set('DICT_TYPE_TREE_DATA', data)
|
||||
})
|
||||
}
|
@ -1,11 +1,9 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
<xn-form-container
|
||||
title="令牌列表"
|
||||
:width="650"
|
||||
:visible="visible"
|
||||
:destroy-on-close="true"
|
||||
:body-style="{ paddingBottom: '80px' }"
|
||||
:footer-style="{ textAlign: 'right' }"
|
||||
@close="onClose"
|
||||
>
|
||||
<a-button
|
||||
@ -66,12 +64,12 @@
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'action'">
|
||||
<a-popconfirm title="确定要强退此令牌吗?" @confirm="exitToken(record)">
|
||||
<a-button type="link" danger size="small" :loading="exitLoading" >强退</a-button>
|
||||
<a-button type="link" danger size="small" :loading="exitLoading">强退</a-button>
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-drawer>
|
||||
</xn-form-container>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<a-card :bordered="false" :body-style="{ 'padding-bottom': '0px' }" class="mb-2">
|
||||
<a-form ref="formRef" name="advanced_search" :model="searchFormState" class="ant-advanced-search-form">
|
||||
<a-form ref="searchFormRef" name="advanced_search" :model="searchFormState" class="ant-advanced-search-form">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="8">
|
||||
<a-form-item label="关键字" name="searchKey">
|
||||
@ -15,7 +15,7 @@
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-button type="primary" @click="table.refresh(true)">查询</a-button>
|
||||
<a-button style="margin: 0 8px" @click="() => formRef.resetFields()">重置</a-button>
|
||||
<a-button style="margin: 0 8px" @click="reset">重置</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
@ -46,7 +46,7 @@
|
||||
import thirdApi from '@/api/auth/thirdApi'
|
||||
import tool from '@/utils/tool'
|
||||
let searchFormState = reactive({})
|
||||
const formRef = ref()
|
||||
const searchFormRef = ref()
|
||||
const table = ref()
|
||||
const toolConfig = { refresh: true, height: true, columnSetting: false, striped: false }
|
||||
const columns = [
|
||||
@ -87,11 +87,11 @@
|
||||
return res
|
||||
})
|
||||
}
|
||||
// 重置
|
||||
const reset = () => {
|
||||
searchFormRef.value.resetFields();
|
||||
table.value.refresh(true)
|
||||
}
|
||||
// 分类
|
||||
const categoryOptions = tool.dictTypeList('THIRD_CATEGORY').map((item) => {
|
||||
return {
|
||||
value: item['dictValue'],
|
||||
label: item['name']
|
||||
}
|
||||
})
|
||||
const categoryOptions = tool.dictList('THIRD_CATEGORY')
|
||||
</script>
|
||||
|
@ -1,11 +1,9 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
<xn-form-container
|
||||
:title="formData.id ? '编辑机构' : '增加机构'"
|
||||
:width="500"
|
||||
:width="550"
|
||||
:visible="visible"
|
||||
:destroy-on-close="true"
|
||||
:body-style="{ paddingBottom: '80px' }"
|
||||
:footer-style="{ textAlign: 'right' }"
|
||||
@close="onClose"
|
||||
>
|
||||
<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
|
||||
@ -25,7 +23,7 @@
|
||||
}"
|
||||
selectable="false"
|
||||
tree-line
|
||||
></a-tree-select>
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="机构名称:" name="name">
|
||||
<a-input v-model:value="formData.name" placeholder="请输入机构名称" allow-clear />
|
||||
@ -36,11 +34,10 @@
|
||||
:options="orgCategoryOptions"
|
||||
style="width: 100%"
|
||||
placeholder="请选择机构分类"
|
||||
>
|
||||
</a-select>
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序:" name="sortCode">
|
||||
<a-slider v-model:value="formData.sortCode" :max="100" />
|
||||
<a-input-number style="width: 100%" v-model:value="formData.sortCode" :max="100" />
|
||||
</a-form-item>
|
||||
<a-form-item label="指定主管:" name="directorId">
|
||||
<a-button type="link" style="padding-left: 0px" @click="openSelector(formData.directorId)">选择</a-button>
|
||||
@ -61,19 +58,17 @@
|
||||
:radio-model="true"
|
||||
@onBack="userBack"
|
||||
/>
|
||||
</a-drawer>
|
||||
</xn-form-container>
|
||||
</template>
|
||||
|
||||
<script setup name="bizOrgForm">
|
||||
import { required, rules } from '@/utils/formRules'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { required } from '@/utils/formRules'
|
||||
import bizOrgApi from '@/api/biz/bizOrgApi'
|
||||
import { getCurrentInstance } from 'vue'
|
||||
import userSelectorPlus from '@/components/Selector/userSelectorPlus.vue'
|
||||
import tool from '@/utils/tool'
|
||||
|
||||
// 定义emit事件
|
||||
const emit = defineEmits({ successful: null })
|
||||
const { proxy } = getCurrentInstance()
|
||||
// 默认是关闭状态
|
||||
let visible = $ref(false)
|
||||
let UserSelectorPlus = ref()
|
||||
@ -86,12 +81,15 @@
|
||||
const submitLoading = ref(false)
|
||||
|
||||
// 打开抽屉
|
||||
const onOpen = (record) => {
|
||||
const onOpen = (record, parentId) => {
|
||||
visible = true
|
||||
extJson.value = ref([])
|
||||
formData.value = {
|
||||
sortCode: 99
|
||||
}
|
||||
if (parentId) {
|
||||
formData.value.parentId = parentId
|
||||
}
|
||||
if (record) {
|
||||
const param = {
|
||||
id: record.id
|
||||
@ -124,12 +122,7 @@
|
||||
sortCode: [required('请选择排序')]
|
||||
}
|
||||
// 机构分类字典
|
||||
let orgCategoryOptions = proxy.$TOOL.dictTypeList('ORG_CATEGORY').map((item) => {
|
||||
return {
|
||||
value: item['dictValue'],
|
||||
label: item['name']
|
||||
}
|
||||
})
|
||||
const orgCategoryOptions = tool.dictList('ORG_CATEGORY')
|
||||
// 打开人员选择器,选择主管
|
||||
const openSelector = (id) => {
|
||||
let checkedUserIds = []
|
||||
@ -157,11 +150,15 @@
|
||||
.then(() => {
|
||||
submitLoading.value = true
|
||||
formData.value.extJson = JSON.stringify(extJson.value)
|
||||
bizOrgApi.submitForm(formData.value, !formData.value.id).then(() => {
|
||||
submitLoading.value = false
|
||||
visible = false
|
||||
emit('successful')
|
||||
})
|
||||
bizOrgApi
|
||||
.submitForm(formData.value, !formData.value.id)
|
||||
.then(() => {
|
||||
visible = false
|
||||
emit('successful')
|
||||
})
|
||||
.finally(() => {
|
||||
submitLoading.value = false
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
@ -170,5 +167,3 @@
|
||||
onOpen
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="8">
|
||||
<a-form-item name="searchKey" label="名称关键词">
|
||||
<a-input v-model:value="searchFormState.searchKey" placeholder="请输入机构名称关键词"></a-input>
|
||||
<a-input v-model:value="searchFormState.searchKey" placeholder="请输入机构名称关键词" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
@ -27,7 +27,7 @@
|
||||
<template #icon><SearchOutlined /></template>
|
||||
查询
|
||||
</a-button>
|
||||
<a-button class="snowy-buttom-left" @click="() => searchFormRef.resetFields()">
|
||||
<a-button class="snowy-buttom-left" @click="reset">
|
||||
<template #icon><redo-outlined /></template>
|
||||
重置
|
||||
</a-button>
|
||||
@ -39,20 +39,29 @@
|
||||
<s-table
|
||||
ref="table"
|
||||
:columns="columns"
|
||||
:data="loadDate"
|
||||
:data="loadData"
|
||||
:expand-row-by-click="true"
|
||||
:alert="options.alert.show"
|
||||
bordered
|
||||
:row-key="(record) => record.id"
|
||||
:tool-config="toolConfig"
|
||||
:row-selection="options.rowSelection"
|
||||
>
|
||||
<template #operator class="table-operator">
|
||||
<a-space>
|
||||
<a-button type="primary" @click="form.onOpen()" v-if="hasPerm('bizOrgAdd')">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="form.onOpen(undefined, searchFormState.parentId)"
|
||||
v-if="hasPerm('bizOrgAdd')"
|
||||
>
|
||||
<template #icon><plus-outlined /></template>
|
||||
新增
|
||||
</a-button>
|
||||
<a-button danger @click="deleteBatchOrg()" v-if="hasPerm('bizOrgBatchDelete')">删除</a-button>
|
||||
<xn-batch-delete
|
||||
v-if="hasPerm('bizOrgBatchDelete')"
|
||||
:selectedRowKeys="selectedRowKeys"
|
||||
@batchDelete="deleteBatchOrg"
|
||||
/>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
@ -75,7 +84,7 @@
|
||||
</template>
|
||||
|
||||
<script setup name="bizOrg">
|
||||
import { message, Empty } from 'ant-design-vue'
|
||||
import { Empty } from 'ant-design-vue'
|
||||
import bizOrgApi from '@/api/biz/bizOrgApi'
|
||||
import Form from './form.vue'
|
||||
|
||||
@ -116,6 +125,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
const toolConfig = { refresh: true, height: true, columnSetting: true }
|
||||
// 定义tableDOM
|
||||
const table = ref(null)
|
||||
const form = ref()
|
||||
@ -129,33 +139,43 @@
|
||||
const cardLoading = ref(true)
|
||||
|
||||
// 表格查询 返回 Promise 对象
|
||||
const loadDate = (parameter) => {
|
||||
const loadData = (parameter) => {
|
||||
loadTreeData()
|
||||
return bizOrgApi.orgPage(Object.assign(parameter, searchFormState)).then((res) => {
|
||||
return res
|
||||
})
|
||||
}
|
||||
// 重置
|
||||
const reset = () => {
|
||||
searchFormRef.value.resetFields()
|
||||
table.value.refresh(true)
|
||||
}
|
||||
// 加载左侧的树
|
||||
const loadTreeData = () => {
|
||||
bizOrgApi.orgTree().then((res) => {
|
||||
cardLoading.value = false
|
||||
if (res !== null) {
|
||||
treeData.value = res
|
||||
// 默认展开2级
|
||||
treeData.value.forEach((item) => {
|
||||
// 因为0的顶级
|
||||
if (item.parentId === '0') {
|
||||
defaultExpandedKeys.value.push(item.id)
|
||||
// 取到下级ID
|
||||
if (item.children) {
|
||||
item.children.forEach((items) => {
|
||||
defaultExpandedKeys.value.push(items.id)
|
||||
})
|
||||
bizOrgApi
|
||||
.orgTree()
|
||||
.then((res) => {
|
||||
cardLoading.value = false
|
||||
if (res !== null) {
|
||||
treeData.value = res
|
||||
// 默认展开2级
|
||||
treeData.value.forEach((item) => {
|
||||
// 因为0的顶级
|
||||
if (item.parentId === '0') {
|
||||
defaultExpandedKeys.value.push(item.id)
|
||||
// 取到下级ID
|
||||
if (item.children) {
|
||||
item.children.forEach((items) => {
|
||||
defaultExpandedKeys.value.push(items.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
cardLoading.value = false
|
||||
})
|
||||
}
|
||||
// 点击树查询
|
||||
const treeSelect = (selectedKeys) => {
|
||||
@ -178,16 +198,7 @@
|
||||
})
|
||||
}
|
||||
// 批量删除
|
||||
const deleteBatchOrg = () => {
|
||||
if (selectedRowKeys.value.length < 1) {
|
||||
message.warning('请选择一条或多条数据')
|
||||
return false
|
||||
}
|
||||
const params = selectedRowKeys.value.map((m) => {
|
||||
return {
|
||||
id: m
|
||||
}
|
||||
})
|
||||
const deleteBatchOrg = (params) => {
|
||||
bizOrgApi.orgDelete(params).then(() => {
|
||||
table.value.clearRefreshSelected()
|
||||
})
|
||||
|
@ -1,11 +1,9 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
<xn-form-container
|
||||
:title="formData.id ? '编辑岗位' : '增加岗位'"
|
||||
:width="500"
|
||||
:width="550"
|
||||
:visible="visible"
|
||||
:destroy-on-close="true"
|
||||
:body-style="{ paddingBottom: '80px' }"
|
||||
:footer-style="{ textAlign: 'right' }"
|
||||
@close="onClose"
|
||||
>
|
||||
<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
|
||||
@ -40,26 +38,24 @@
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序:" name="sortCode">
|
||||
<a-slider v-model:value="formData.sortCode" :max="100" />
|
||||
<a-input-number style="width: 100%" v-model:value="formData.sortCode" :max="100" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<a-button style="margin-right: 8px" @click="onClose">关闭</a-button>
|
||||
<a-button type="primary" :loading="submitLoading" @click="onSubmit">保存</a-button>
|
||||
</template>
|
||||
</a-drawer>
|
||||
</xn-form-container>
|
||||
</template>
|
||||
|
||||
<script setup name="bizPositionForm">
|
||||
import { required } from '@/utils/formRules'
|
||||
import { getCurrentInstance } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import bizOrgApi from '@/api/biz/bizOrgApi'
|
||||
import bizPositionApi from '@/api/biz/bizPositionApi'
|
||||
import tool from '@/utils/tool'
|
||||
|
||||
// 定义emit事件
|
||||
const emit = defineEmits({ successful: null })
|
||||
const { proxy } = getCurrentInstance()
|
||||
// 默认是关闭状态
|
||||
let visible = $ref(false)
|
||||
const formRef = ref()
|
||||
@ -70,11 +66,14 @@
|
||||
const submitLoading = ref(false)
|
||||
|
||||
// 打开抽屉
|
||||
const onOpen = (record) => {
|
||||
const onOpen = (record, orgId) => {
|
||||
visible = true
|
||||
formData.value = {
|
||||
sortCode: 99
|
||||
}
|
||||
if (orgId) {
|
||||
formData.value.orgId = orgId
|
||||
}
|
||||
if (record) {
|
||||
formData.value = Object.assign({}, record)
|
||||
}
|
||||
@ -101,23 +100,22 @@
|
||||
category: [required('请选择岗位分类')],
|
||||
sortCode: [required('请选择排序')]
|
||||
}
|
||||
let positionCategoryOptions = proxy.$TOOL.dictTypeList('POSITION_CATEGORY').map((item) => {
|
||||
return {
|
||||
value: item['dictValue'],
|
||||
label: item['name']
|
||||
}
|
||||
})
|
||||
const positionCategoryOptions = tool.dictList('POSITION_CATEGORY')
|
||||
// 验证并提交数据
|
||||
const onSubmit = () => {
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
submitLoading.value = true
|
||||
bizPositionApi.submitForm(formData.value, !formData.value.id).then(() => {
|
||||
visible = false
|
||||
submitLoading.value = false
|
||||
emit('successful')
|
||||
})
|
||||
bizPositionApi
|
||||
.submitForm(formData.value, !formData.value.id)
|
||||
.then(() => {
|
||||
visible = false
|
||||
emit('successful')
|
||||
})
|
||||
.finally(() => {
|
||||
submitLoading.value = false
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="8">
|
||||
<a-form-item name="searchKey" label="名称关键词">
|
||||
<a-input v-model:value="searchFormState.searchKey" placeholder="请输入岗位名称关键词"></a-input>
|
||||
<a-input v-model:value="searchFormState.searchKey" placeholder="请输入岗位名称关键词" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
@ -27,7 +27,7 @@
|
||||
<template #icon><SearchOutlined /></template>
|
||||
查询
|
||||
</a-button>
|
||||
<a-button class="snowy-buttom-left" @click="() => searchFormRef.resetFields()">
|
||||
<a-button class="snowy-buttom-left" @click="reset">
|
||||
<template #icon><redo-outlined /></template>
|
||||
重置
|
||||
</a-button>
|
||||
@ -39,20 +39,29 @@
|
||||
<s-table
|
||||
ref="table"
|
||||
:columns="columns"
|
||||
:data="loadDate"
|
||||
:data="loadData"
|
||||
:expand-row-by-click="true"
|
||||
:alert="options.alert.show"
|
||||
bordered
|
||||
:tool-config="toolConfig"
|
||||
:row-key="(record) => record.id"
|
||||
:row-selection="options.rowSelection"
|
||||
>
|
||||
<template #operator class="table-operator">
|
||||
<a-space>
|
||||
<a-button type="primary" @click="form.onOpen()" v-if="hasPerm('bizPositionAdd')">
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="form.onOpen(undefined, searchFormState.orgId)"
|
||||
v-if="hasPerm('bizPositionAdd')"
|
||||
>
|
||||
<template #icon><plus-outlined /></template>
|
||||
新增
|
||||
</a-button>
|
||||
<a-button danger @click="deleteBatchPosition()" v-if="hasPerm('bizPositionBatchDelete')">删除</a-button>
|
||||
<xn-batch-delete
|
||||
v-if="hasPerm('bizPositionBatchDelete')"
|
||||
:selectedRowKeys="selectedRowKeys"
|
||||
@batchDelete="deleteBatchPosition"
|
||||
/>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
@ -75,7 +84,7 @@
|
||||
</template>
|
||||
|
||||
<script setup name="bizPosition">
|
||||
import { message, Empty } from 'ant-design-vue'
|
||||
import { Empty } from 'ant-design-vue'
|
||||
import bizPositionApi from '@/api/biz/bizPositionApi'
|
||||
import bizOrgApi from '@/api/biz/bizOrgApi'
|
||||
import Form from './form.vue'
|
||||
@ -117,6 +126,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
const toolConfig = { refresh: true, height: true, columnSetting: true }
|
||||
// 定义tableDOM
|
||||
const table = ref(null)
|
||||
const form = ref()
|
||||
@ -130,31 +140,41 @@
|
||||
const cardLoading = ref(true)
|
||||
|
||||
// 表格查询 返回 Promise 对象
|
||||
const loadDate = (parameter) => {
|
||||
const loadData = (parameter) => {
|
||||
return bizPositionApi.positionPage(Object.assign(parameter, searchFormState)).then((res) => {
|
||||
return res
|
||||
})
|
||||
}
|
||||
// 重置
|
||||
const reset = () => {
|
||||
searchFormRef.value.resetFields()
|
||||
table.value.refresh(true)
|
||||
}
|
||||
// 加载左侧的树
|
||||
bizOrgApi.orgTree().then((res) => {
|
||||
cardLoading.value = false
|
||||
if (res !== null) {
|
||||
treeData.value = res
|
||||
// 默认展开2级
|
||||
treeData.value.forEach((item) => {
|
||||
// 因为0的顶级
|
||||
if (item.parentId === '0') {
|
||||
defaultExpandedKeys.value.push(item.id)
|
||||
// 取到下级ID
|
||||
if (item.children) {
|
||||
item.children.forEach((items) => {
|
||||
defaultExpandedKeys.value.push(items.id)
|
||||
})
|
||||
bizOrgApi
|
||||
.orgTree()
|
||||
.then((res) => {
|
||||
cardLoading.value = false
|
||||
if (res !== null) {
|
||||
treeData.value = res
|
||||
// 默认展开2级
|
||||
treeData.value.forEach((item) => {
|
||||
// 因为0的顶级
|
||||
if (item.parentId === '0') {
|
||||
defaultExpandedKeys.value.push(item.id)
|
||||
// 取到下级ID
|
||||
if (item.children) {
|
||||
item.children.forEach((items) => {
|
||||
defaultExpandedKeys.value.push(items.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
cardLoading.value = false
|
||||
})
|
||||
// 点击树查询
|
||||
const treeSelect = (selectedKeys) => {
|
||||
if (selectedKeys.length > 0) {
|
||||
@ -176,16 +196,7 @@
|
||||
})
|
||||
}
|
||||
// 批量删除
|
||||
const deleteBatchPosition = () => {
|
||||
if (selectedRowKeys.value.length < 1) {
|
||||
message.warning('请选择一条或多条数据')
|
||||
return false
|
||||
}
|
||||
const params = selectedRowKeys.value.map((m) => {
|
||||
return {
|
||||
id: m
|
||||
}
|
||||
})
|
||||
const deleteBatchPosition = (params) => {
|
||||
bizPositionApi.positionDelete(params).then(() => {
|
||||
table.value.clearRefreshSelected()
|
||||
})
|
||||
|
@ -1,11 +1,10 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
<xn-form-container
|
||||
:title="formData.id ? '编辑人员' : '增加人员'"
|
||||
:width="620"
|
||||
:width="800"
|
||||
:visible="visible"
|
||||
:destroy-on-close="true"
|
||||
:body-style="{ paddingBottom: '80px', 'padding-top': '0px' }"
|
||||
:footer-style="{ textAlign: 'right' }"
|
||||
:body-style="{ 'padding-top': '0px' }"
|
||||
@close="onClose"
|
||||
>
|
||||
<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
|
||||
@ -232,8 +231,8 @@
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="证据号码:" name="idCardNumber">
|
||||
<a-input v-model:value="formData.idCardNumber" placeholder="请输入通信地址" allow-clear />
|
||||
<a-form-item label="证件号码:" name="idCardNumber">
|
||||
<a-input v-model:value="formData.idCardNumber" placeholder="请输入证件号码" allow-clear />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
@ -325,17 +324,17 @@
|
||||
<a-button style="margin-right: 8px" @click="onClose">关闭</a-button>
|
||||
<a-button type="primary" :loading="formLoading" @click="onSubmit">保存</a-button>
|
||||
</template>
|
||||
</a-drawer>
|
||||
</xn-form-container>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import bizUserApi from '@/api/biz/bizUserApi'
|
||||
import { required, rules } from '@/utils/formRules'
|
||||
import { required } from '@/utils/formRules'
|
||||
import tool from '@/utils/tool'
|
||||
// 默认是关闭状态
|
||||
let visible = $ref(false)
|
||||
const formRef = ref()
|
||||
const activeTabsKey = ref('1')
|
||||
const { proxy } = getCurrentInstance()
|
||||
const emit = defineEmits({ successful: null })
|
||||
const formLoading = ref(false)
|
||||
const treeData = ref([])
|
||||
@ -351,33 +350,42 @@
|
||||
let formData = ref({})
|
||||
|
||||
// 打开抽屉
|
||||
const onOpen = (record) => {
|
||||
const onOpen = (record, orgId) => {
|
||||
visible = true
|
||||
formData.value = {
|
||||
gender: '男',
|
||||
positionJson: []
|
||||
}
|
||||
if (orgId) {
|
||||
formData.value.orgId = orgId
|
||||
// 通过机构再查询职位、主管
|
||||
nextTick(() => {
|
||||
selePositionData(orgId)
|
||||
})
|
||||
}
|
||||
if (record) {
|
||||
convertFormData(record)
|
||||
}
|
||||
// 机构选择器数据
|
||||
bizUserApi.userOrgTreeSelector().then((res) => {
|
||||
if (res !== null) {
|
||||
treeData.value = res
|
||||
// 默认展开2级
|
||||
treeData.value.forEach((item) => {
|
||||
// 因为0的顶级
|
||||
if (item.parentId === '0') {
|
||||
treeDefaultExpandedKeys.value.push(item.id)
|
||||
// 取到下级ID
|
||||
if (item.children) {
|
||||
item.children.forEach((items) => {
|
||||
treeDefaultExpandedKeys.value.push(items.id)
|
||||
})
|
||||
nextTick(() => {
|
||||
// 机构选择器数据
|
||||
bizUserApi.userOrgTreeSelector().then((res) => {
|
||||
if (res !== null) {
|
||||
treeData.value = res
|
||||
// 默认展开2级
|
||||
treeData.value.forEach((item) => {
|
||||
// 因为0的顶级
|
||||
if (item.parentId === '0') {
|
||||
treeDefaultExpandedKeys.value.push(item.id)
|
||||
// 取到下级ID
|
||||
if (item.children) {
|
||||
item.children.forEach((items) => {
|
||||
treeDefaultExpandedKeys.value.push(items.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
// 关闭抽屉
|
||||
@ -496,7 +504,11 @@
|
||||
formRef.value.validate().then(() => {
|
||||
// 因为不切断,我下面转换数据格式,影响上面表单会报错
|
||||
let formDatas = JSON.parse(JSON.stringify(formData.value))
|
||||
formDatas.positionJson = JSON.stringify(formDatas.positionJson)
|
||||
if (formDatas.positionJson && formDatas.positionJson.length > 0) {
|
||||
formDatas.positionJson = JSON.stringify(formDatas.positionJson)
|
||||
} else {
|
||||
delete formDatas.positionJson
|
||||
}
|
||||
formLoading.value = true
|
||||
bizUserApi
|
||||
.submitForm(formDatas, !formDatas.id)
|
||||
@ -510,33 +522,13 @@
|
||||
})
|
||||
}
|
||||
// 性别
|
||||
const genderOptions = proxy.$TOOL.dictTypeList('GENDER').map((item) => {
|
||||
return {
|
||||
value: item['dictValue'],
|
||||
label: item['name']
|
||||
}
|
||||
})
|
||||
const genderOptions = tool.dictList('GENDER')
|
||||
// 民族
|
||||
const nationOptions = proxy.$TOOL.dictTypeList('NATION').map((item) => {
|
||||
return {
|
||||
value: item['dictValue'],
|
||||
label: item['name']
|
||||
}
|
||||
})
|
||||
const nationOptions = tool.dictList('NATION')
|
||||
// 身份证件
|
||||
const idcardTypeOptions = proxy.$TOOL.dictTypeList('IDCARD_TYPE').map((item) => {
|
||||
return {
|
||||
value: item['dictValue'],
|
||||
label: item['name']
|
||||
}
|
||||
})
|
||||
const idcardTypeOptions = tool.dictList('IDCARD_TYPE')
|
||||
// 文化程度
|
||||
const cultureLevelOptions = proxy.$TOOL.dictTypeList('CULTURE_LEVEL').map((item) => {
|
||||
return {
|
||||
value: item['dictValue'],
|
||||
label: item['name']
|
||||
}
|
||||
})
|
||||
const cultureLevelOptions = tool.dictList('CULTURE_LEVEL')
|
||||
|
||||
// 调用这个函数将子组件的一些数据和方法暴露出去
|
||||
defineExpose({
|
||||
|
@ -14,55 +14,72 @@
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="19">
|
||||
<a-card :bordered="false" style="margin-bottom: 10px">
|
||||
<a-form ref="searchFormRef" name="advanced_search" class="ant-advanced-search-form" :model="searchFormState">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="8">
|
||||
<a-form-item name="searchKey" :label="$t('common.searchKey')">
|
||||
<a-input
|
||||
v-model:value="searchFormState.searchKey"
|
||||
:placeholder="$t('user.placeholderNameAndSearchKey')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item name="userStatus" :label="$t('user.userStatus')">
|
||||
<a-select v-model:value="searchFormState.userStatus" :placeholder="$t('user.placeholderUserStatus')">
|
||||
<a-select-option v-for="item in statusData" :key="item.value" :value="item.value">{{
|
||||
item.label
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-button type="primary" @click="table.refresh(true)">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
{{ $t('common.searchButton') }}
|
||||
</a-button>
|
||||
<a-button class="snowy-buttom-left" @click="reset">
|
||||
<template #icon><redo-outlined /></template>
|
||||
{{ $t('common.resetButton') }}
|
||||
</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
<a-card :bordered="false">
|
||||
<s-table
|
||||
ref="table"
|
||||
:columns="columns"
|
||||
:data="loadDate"
|
||||
:data="loadData"
|
||||
:expand-row-by-click="true"
|
||||
bordered
|
||||
:alert="options.alert.show"
|
||||
:tool-config="toolConfig"
|
||||
:row-key="(record) => record.id"
|
||||
:row-selection="options.rowSelection"
|
||||
>
|
||||
<template #operator class="table-operator">
|
||||
<a-form
|
||||
ref="searchFormRef"
|
||||
name="advanced_search"
|
||||
class="ant-advanced-search-form"
|
||||
:model="searchFormState"
|
||||
>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="6">
|
||||
<a-form-item name="searchKey">
|
||||
<a-input v-model:value="searchFormState.searchKey" placeholder="请输入姓名或账号"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item name="userStatus">
|
||||
<a-select v-model:value="searchFormState.userStatus" placeholder="请选择状态">
|
||||
<a-select-option v-for="item in statusData" :key="item.dictValue" :value="item.dictValue">{{
|
||||
item.name
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-button type="primary" @click="table.refresh(true)">{{ $t('common.searchButton') }}</a-button>
|
||||
<a-button class="snowy-buttom-left" @click="() => searchFormRef.resetFields()">{{
|
||||
$t('common.resetButton')
|
||||
}}</a-button>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-button type="primary" class="primaryAdd" @click="form.onOpen()" v-if="hasPerm('bizUserAdd')">
|
||||
<span>{{ $t('common.addButton') }}{{ $t('model.bizUser') }}</span>
|
||||
</a-button>
|
||||
<a-button danger @click="removeBatchUser()" v-if="hasPerm('bizUserBatchDelete')">{{
|
||||
$t('common.batchRemoveButton')
|
||||
}}</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
<a-space>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="form.onOpen(undefined, searchFormState.orgId)"
|
||||
v-if="hasPerm('bizUserAdd')"
|
||||
>
|
||||
<template #icon><plus-outlined /></template>
|
||||
<span>{{ $t('common.addButton') }}{{ $t('model.user') }}</span>
|
||||
</a-button>
|
||||
<a-button @click="exportBatchUserVerify" v-if="hasPerm('bizUserBatchExport')">
|
||||
<template #icon><export-outlined /></template>
|
||||
{{ $t('user.batchExportButton') }}
|
||||
</a-button>
|
||||
<xn-batch-delete
|
||||
v-if="hasPerm('bizUserBatchDelete')"
|
||||
:buttonName="$t('common.batchRemoveButton')"
|
||||
:selectedRowKeys="selectedRowKeys"
|
||||
@batchDelete="deleteBatchUser"
|
||||
/>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'avatar'">
|
||||
@ -82,18 +99,41 @@
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'action'">
|
||||
<a @click="form.onOpen(record)" v-if="hasPerm('bizUserEdit')">{{ $t('common.editButton') }}</a>
|
||||
<a-divider type="vertical" v-if="hasPerm(['bizUserEdit', 'bizUserGrantRole'], 'and')" />
|
||||
<a @click="selectRole(record)" v-if="hasPerm('bizUserGrantRole')">角色</a>
|
||||
<a-divider type="vertical" v-if="hasPerm(['bizUserGrantRole', 'bizUserPwdReset'], 'and')" />
|
||||
<a-popconfirm title="确定重置此人员密码?" @confirm="resetPassword(record)">
|
||||
<a v-if="hasPerm('bizUserPwdReset')">重置密码</a>
|
||||
</a-popconfirm>
|
||||
<a-divider type="vertical" v-if="hasPerm(['bizUserPwdReset', 'bizUserDelete'], 'and')" />
|
||||
<a-popconfirm title="确定要删除此人员吗?" @confirm="removeUser(record)">
|
||||
<a-divider type="vertical" v-if="hasPerm(['bizUserEdit', 'bizUserDelete'], 'and')" />
|
||||
<a-popconfirm :title="$t('user.popconfirmDeleteUser')" @confirm="removeUser(record)">
|
||||
<a-button type="link" danger size="small" v-if="hasPerm('bizUserDelete')">{{
|
||||
$t('common.removeButton')
|
||||
}}</a-button>
|
||||
</a-popconfirm>
|
||||
<a-divider
|
||||
type="vertical"
|
||||
v-if="hasPerm(['bizUserGrantRole', 'bizUserPwdReset', 'bizUserExportUserInfo'], 'and')"
|
||||
/>
|
||||
<a-dropdown v-if="hasPerm(['bizUserGrantRole', 'bizUserPwdReset', 'bizUserExportUserInfo'], 'and')">
|
||||
<a class="ant-dropdown-link">
|
||||
{{ $t('common.more') }}
|
||||
<DownOutlined />
|
||||
</a>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item v-if="hasPerm('bizUserPwdReset')">
|
||||
<a-popconfirm
|
||||
:title="$t('user.popconfirmResatUserPwd')"
|
||||
placement="topRight"
|
||||
@confirm="resetPassword(record)"
|
||||
>
|
||||
<a>{{ $t('user.resetPassword') }}</a>
|
||||
</a-popconfirm>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-if="hasPerm('bizUserGrantRole')">
|
||||
<a @click="selectRole(record)">{{ $t('user.grantRole') }}</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-if="hasPerm('bizUserExportUserInfo')">
|
||||
<a @click="exportUserInfo(record)">{{ $t('user.exportUserInfo') }}</a>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
</template>
|
||||
</s-table>
|
||||
@ -111,7 +151,8 @@
|
||||
</template>
|
||||
<script setup name="bizUser">
|
||||
import { message, Empty } from 'ant-design-vue'
|
||||
import { getCurrentInstance } from 'vue'
|
||||
import tool from '@/utils/tool'
|
||||
import downloadUtil from '@/utils/downloadUtil'
|
||||
import bizUserApi from '@/api/biz/bizUserApi'
|
||||
import roleSelectorPlus from '@/components/Selector/roleSelectorPlus.vue'
|
||||
import Form from './form.vue'
|
||||
@ -158,16 +199,16 @@
|
||||
width: '80px'
|
||||
}
|
||||
]
|
||||
if (hasPerm(['bizUserEdit', 'bizUserGrantRole', 'bizUserPwdReset', 'bizUserDelete'])) {
|
||||
if (hasPerm(['bizUserEdit', 'bizUserGrantRole', 'bizUserPwdReset', 'bizUserExportUserInfo', 'bizUserDelete'])) {
|
||||
columns.push({
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
align: 'center',
|
||||
width: '240px'
|
||||
width: '220px'
|
||||
})
|
||||
}
|
||||
const { proxy } = getCurrentInstance()
|
||||
const statusData = proxy.$TOOL.dictTypeList('COMMON_STATUS')
|
||||
const toolConfig = { refresh: true, height: true, columnSetting: true }
|
||||
const statusData = tool.dictList('COMMON_STATUS')
|
||||
const searchFormRef = ref()
|
||||
let defaultExpandedKeys = ref([])
|
||||
let searchFormState = reactive({})
|
||||
@ -181,33 +222,43 @@
|
||||
const selectedRecord = ref({})
|
||||
const loading = ref(false)
|
||||
const cardLoading = ref(true)
|
||||
|
||||
const ImpExpRef = ref()
|
||||
// 表格查询 返回 Promise 对象
|
||||
const loadDate = (parameter) => {
|
||||
const loadData = (parameter) => {
|
||||
return bizUserApi.userPage(Object.assign(parameter, searchFormState)).then((res) => {
|
||||
return res
|
||||
})
|
||||
}
|
||||
// 重置
|
||||
const reset = () => {
|
||||
searchFormRef.value.resetFields()
|
||||
table.value.refresh(true)
|
||||
}
|
||||
// 左侧树查询
|
||||
bizUserApi.userOrgTreeSelector().then((res) => {
|
||||
cardLoading.value = false
|
||||
if (res !== null) {
|
||||
treeData.value = res
|
||||
// 默认展开2级
|
||||
treeData.value.forEach((item) => {
|
||||
// 因为0的顶级
|
||||
if (item.parentId === '0') {
|
||||
defaultExpandedKeys.value.push(item.id)
|
||||
// 取到下级ID
|
||||
if (item.children) {
|
||||
item.children.forEach((items) => {
|
||||
defaultExpandedKeys.value.push(items.id)
|
||||
})
|
||||
bizUserApi
|
||||
.userOrgTreeSelector()
|
||||
.then((res) => {
|
||||
cardLoading.value = false
|
||||
if (res !== null) {
|
||||
treeData.value = res
|
||||
// 默认展开2级
|
||||
treeData.value.forEach((item) => {
|
||||
// 因为0的顶级
|
||||
if (item.parentId === '0') {
|
||||
defaultExpandedKeys.value.push(item.id)
|
||||
// 取到下级ID
|
||||
if (item.children) {
|
||||
item.children.forEach((items) => {
|
||||
defaultExpandedKeys.value.push(items.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
cardLoading.value = false
|
||||
})
|
||||
// 列表选择配置
|
||||
const options = {
|
||||
alert: {
|
||||
@ -235,15 +286,23 @@
|
||||
const editStatus = (record) => {
|
||||
loading.value = true
|
||||
if (record.userStatus === 'ENABLE') {
|
||||
bizUserApi.userDisableUser(record).then(() => {
|
||||
loading.value = false
|
||||
table.value.refresh()
|
||||
})
|
||||
bizUserApi
|
||||
.userDisableUser(record)
|
||||
.then(() => {
|
||||
table.value.refresh()
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
} else {
|
||||
bizUserApi.userEnableUser(record).then(() => {
|
||||
loading.value = false
|
||||
table.value.refresh()
|
||||
})
|
||||
bizUserApi
|
||||
.userEnableUser(record)
|
||||
.then(() => {
|
||||
table.value.refresh()
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
// 删除人员
|
||||
@ -257,17 +316,39 @@
|
||||
table.value.refresh()
|
||||
})
|
||||
}
|
||||
// 批量删除人员
|
||||
const removeBatchUser = () => {
|
||||
if (selectedRowKeys.value.length < 1) {
|
||||
message.warning('请选择一条或多条数据')
|
||||
// 批量导出校验并加参数
|
||||
const exportBatchUserVerify = () => {
|
||||
if ((selectedRowKeys.value.length < 1) & !searchFormState.searchKey & !searchFormState.userStatus) {
|
||||
message.warning('请输入查询条件或勾选要导出的信息')
|
||||
}
|
||||
if (selectedRowKeys.value.length > 0) {
|
||||
const params = {
|
||||
userIds: selectedRowKeys.value
|
||||
.map((m) => {
|
||||
return m
|
||||
})
|
||||
.join()
|
||||
}
|
||||
exportBatchUser(params)
|
||||
return
|
||||
}
|
||||
const params = selectedRowKeys.value.map((m) => {
|
||||
return {
|
||||
id: m
|
||||
if (searchFormState.searchKey || searchFormState.userStatus) {
|
||||
const params = {
|
||||
searchKey: searchFormState.searchKey,
|
||||
userStatus: searchFormState.userStatus
|
||||
}
|
||||
exportBatchUser(params)
|
||||
}
|
||||
}
|
||||
// 批量导出
|
||||
const exportBatchUser = (params) => {
|
||||
bizUserApi.userExport(params).then((res) => {
|
||||
downloadUtil.resultDownload(res)
|
||||
table.value.clearSelected()
|
||||
})
|
||||
}
|
||||
// 批量删除
|
||||
const deleteBatchUser = (params) => {
|
||||
bizUserApi.userDelete(params).then(() => {
|
||||
table.value.clearRefreshSelected()
|
||||
})
|
||||
@ -300,6 +381,15 @@
|
||||
const resetPassword = (record) => {
|
||||
bizUserApi.userResetPassword(record).then(() => {})
|
||||
}
|
||||
// 导出用户信息
|
||||
const exportUserInfo = (record) => {
|
||||
const params = {
|
||||
id: record.id
|
||||
}
|
||||
bizUserApi.userExportUserInfo(params).then((res) => {
|
||||
downloadUtil.resultDownload(res)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
@ -59,24 +59,22 @@
|
||||
}
|
||||
// 验证并提交数据
|
||||
const onSubmit = () => {
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
submitLoading.value = true
|
||||
let submitParam = cloneDeep(formData.value)
|
||||
const param = Object.entries(submitParam).map((item) => {
|
||||
return {
|
||||
configKey: item[0],
|
||||
configValue: item[1]
|
||||
}
|
||||
})
|
||||
configApi
|
||||
.configEditForm(param)
|
||||
.then(() => {})
|
||||
.finally(() => {
|
||||
submitLoading.value = false
|
||||
})
|
||||
formRef.value.validate().then(() => {
|
||||
submitLoading.value = true
|
||||
let submitParam = cloneDeep(formData.value)
|
||||
const param = Object.entries(submitParam).map((item) => {
|
||||
return {
|
||||
configKey: item[0],
|
||||
configValue: item[1]
|
||||
}
|
||||
})
|
||||
configApi
|
||||
.configEditForm(param)
|
||||
.then(() => {})
|
||||
.finally(() => {
|
||||
submitLoading.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
const layout = {
|
||||
labelCol: {
|
||||
|
@ -55,24 +55,22 @@
|
||||
}
|
||||
// 验证并提交数据
|
||||
const onSubmit = () => {
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
submitLoading.value = true
|
||||
let submitParam = cloneDeep(formData.value)
|
||||
const param = Object.entries(submitParam).map((item) => {
|
||||
return {
|
||||
configKey: item[0],
|
||||
configValue: item[1]
|
||||
}
|
||||
})
|
||||
configApi
|
||||
.configEditForm(param)
|
||||
.then(() => {})
|
||||
.finally(() => {
|
||||
submitLoading.value = false
|
||||
})
|
||||
formRef.value.validate().then(() => {
|
||||
submitLoading.value = true
|
||||
let submitParam = cloneDeep(formData.value)
|
||||
const param = Object.entries(submitParam).map((item) => {
|
||||
return {
|
||||
configKey: item[0],
|
||||
configValue: item[1]
|
||||
}
|
||||
})
|
||||
configApi
|
||||
.configEditForm(param)
|
||||
.then(() => {})
|
||||
.finally(() => {
|
||||
submitLoading.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
const layout = {
|
||||
labelCol: {
|
||||
|
@ -63,24 +63,22 @@
|
||||
}
|
||||
// 验证并提交数据
|
||||
const onSubmit = () => {
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
submitLoading.value = true
|
||||
let submitParam = cloneDeep(formData.value)
|
||||
const param = Object.entries(submitParam).map((item) => {
|
||||
return {
|
||||
configKey: item[0],
|
||||
configValue: item[1]
|
||||
}
|
||||
})
|
||||
configApi
|
||||
.configEditForm(param)
|
||||
.then(() => {})
|
||||
.finally(() => {
|
||||
submitLoading.value = false
|
||||
})
|
||||
formRef.value.validate().then(() => {
|
||||
submitLoading.value = true
|
||||
let submitParam = cloneDeep(formData.value)
|
||||
const param = Object.entries(submitParam).map((item) => {
|
||||
return {
|
||||
configKey: item[0],
|
||||
configValue: item[1]
|
||||
}
|
||||
})
|
||||
configApi
|
||||
.configEditForm(param)
|
||||
.then(() => {})
|
||||
.finally(() => {
|
||||
submitLoading.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
const layout = {
|
||||
labelCol: {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user