切换为vue3的前端版本
82
README.md
@@ -1,30 +1,14 @@
|
|||||||
<p align="center">
|
# 平台简介
|
||||||
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png">
|
|
||||||
</p>
|
|
||||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.3</h1>
|
|
||||||
<h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4>
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a>
|
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.3-brightgreen.svg"></a>
|
|
||||||
<a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
## 平台简介
|
基于若依V3.6.3
|
||||||
|
|
||||||
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
|
|
||||||
|
|
||||||
* 采用前后端分离的模式,微服务版本前端(基于 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue))。
|
* 采用前后端分离的模式,微服务版本前端(基于 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue))。
|
||||||
* 后端采用Spring Boot、Spring Cloud & Alibaba。
|
* 后端采用Spring Boot、Spring Cloud & Alibaba。
|
||||||
* 注册中心、配置中心选型Nacos,权限认证使用Redis。
|
* 注册中心、配置中心选型Nacos,权限认证使用Redis。
|
||||||
* 流量控制框架选型Sentinel,分布式事务选型Seata。
|
* 流量控制框架选型Sentinel,分布式事务选型Seata。
|
||||||
* 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Cloud-Vue3](https://github.com/yangzongzhuan/RuoYi-Cloud-Vue3),保持同步更新。
|
* 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Cloud-Vue3](https://github.com/yangzongzhuan/RuoYi-Cloud-Vue3),保持同步更新。
|
||||||
* 如需不分离应用,请移步 [RuoYi](https://gitee.com/y_project/RuoYi),如需分离应用,请移步 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue)
|
|
||||||
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)
|
|
||||||
* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)
|
|
||||||
|
|
||||||
#### 友情链接 [若依/RuoYi-Cloud](https://gitee.com/zhangmrit/ruoyi-cloud) Ant Design版本。
|
# 系统模块
|
||||||
|
|
||||||
## 系统模块
|
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
com.ruoyi
|
com.ruoyi
|
||||||
@@ -52,11 +36,7 @@ com.ruoyi
|
|||||||
├──pom.xml // 公共依赖
|
├──pom.xml // 公共依赖
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
## 架构图
|
# 内置功能
|
||||||
|
|
||||||
<img src="https://oscimg.oschina.net/oscnet/up-82e9722ecb846786405a904bafcf19f73f3.png"/>
|
|
||||||
|
|
||||||
## 内置功能
|
|
||||||
|
|
||||||
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
||||||
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
|
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
|
||||||
@@ -75,57 +55,3 @@ com.ruoyi
|
|||||||
15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
|
15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
|
||||||
16. 在线构建器:拖动表单元素生成相应的HTML代码。
|
16. 在线构建器:拖动表单元素生成相应的HTML代码。
|
||||||
17. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
|
17. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
|
||||||
|
|
||||||
## 在线体验
|
|
||||||
|
|
||||||
- admin/admin123
|
|
||||||
- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
|
|
||||||
|
|
||||||
演示地址:http://ruoyi.vip
|
|
||||||
文档地址:http://doc.ruoyi.vip
|
|
||||||
|
|
||||||
## 演示图
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/cd1f90be5f2684f4560c9519c0f2a232ee8.jpg"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-4148b24f58660a9dc347761e4cf6162f28f.png"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-ece3fd37a3d4bb75a3926e905a3c5629055.png"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-92ffb7f3835855cff100fa0f754a6be0d99.png"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-ff9e3066561574aca73005c5730c6a41f15.png"/></td>
|
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
|
||||||
## 若依微服务交流群
|
|
||||||
|
|
||||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) 点击按钮入群。
|
|
||||||
3
pom.xml
@@ -9,14 +9,13 @@
|
|||||||
<version>3.6.3</version>
|
<version>3.6.3</version>
|
||||||
|
|
||||||
<name>ruoyi</name>
|
<name>ruoyi</name>
|
||||||
<url>http://www.ruoyi.vip</url>
|
|
||||||
<description>若依微服务系统</description>
|
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<ruoyi.version>3.6.3</ruoyi.version>
|
<ruoyi.version>3.6.3</ruoyi.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
|
|
||||||
<spring-boot.version>2.7.18</spring-boot.version>
|
<spring-boot.version>2.7.18</spring-boot.version>
|
||||||
<spring-cloud.version>2021.0.8</spring-cloud.version>
|
<spring-cloud.version>2021.0.8</spring-cloud.version>
|
||||||
<spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
|
<spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
# 告诉EditorConfig插件,这是根文件,不用继续往上查找
|
|
||||||
root = true
|
|
||||||
|
|
||||||
# 匹配全部文件
|
|
||||||
[*]
|
|
||||||
# 设置字符集
|
|
||||||
charset = utf-8
|
|
||||||
# 缩进风格,可选space、tab
|
|
||||||
indent_style = space
|
|
||||||
# 缩进的空格数
|
|
||||||
indent_size = 2
|
|
||||||
# 结尾换行符,可选lf、cr、crlf
|
|
||||||
end_of_line = lf
|
|
||||||
# 在文件结尾插入新行
|
|
||||||
insert_final_newline = true
|
|
||||||
# 删除一行中的前后空格
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
|
|
||||||
# 匹配md结尾的文件
|
|
||||||
[*.md]
|
|
||||||
insert_final_newline = false
|
|
||||||
trim_trailing_whitespace = false
|
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
# 页面标题
|
# 页面标题
|
||||||
VUE_APP_TITLE = 若依管理系统
|
VITE_APP_TITLE = 若依管理系统DEV
|
||||||
|
|
||||||
# 开发环境配置
|
# 开发环境配置
|
||||||
ENV = 'development'
|
VITE_APP_ENV = 'development'
|
||||||
|
|
||||||
# 若依管理系统/开发环境
|
# 若依管理系统/开发环境
|
||||||
VUE_APP_BASE_API = '/dev-api'
|
VITE_APP_BASE_API = '/dev-api'
|
||||||
|
|
||||||
# 路由懒加载
|
|
||||||
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
# 页面标题
|
# 页面标题
|
||||||
VUE_APP_TITLE = 若依管理系统
|
VITE_APP_TITLE = 若依管理系统PROD
|
||||||
|
|
||||||
# 生产环境配置
|
# 生产环境配置
|
||||||
ENV = 'production'
|
VITE_APP_ENV = 'production'
|
||||||
|
|
||||||
# 若依管理系统/生产环境
|
# 若依管理系统/生产环境
|
||||||
VUE_APP_BASE_API = '/prod-api'
|
VITE_APP_BASE_API = '/prod-api'
|
||||||
|
|
||||||
|
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||||
|
VITE_BUILD_COMPRESS = gzip
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
# 页面标题
|
# 页面标题
|
||||||
VUE_APP_TITLE = 若依管理系统
|
VITE_APP_TITLE = 若依管理系统STAGING
|
||||||
|
|
||||||
NODE_ENV = production
|
# 生产环境配置
|
||||||
|
VITE_APP_ENV = 'staging'
|
||||||
# 测试环境配置
|
|
||||||
ENV = 'staging'
|
# 若依管理系统/生产环境
|
||||||
|
VITE_APP_BASE_API = '/stage-api'
|
||||||
# 若依管理系统/测试环境
|
|
||||||
VUE_APP_BASE_API = '/stage-api'
|
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||||
|
VITE_BUILD_COMPRESS = gzip
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# 忽略build目录下类型为js的文件的语法检查
|
|
||||||
build/*.js
|
|
||||||
# 忽略src/assets目录下文件的语法检查
|
|
||||||
src/assets
|
|
||||||
# 忽略public目录下文件的语法检查
|
|
||||||
public
|
|
||||||
# 忽略当前目录下为js的文件的语法检查
|
|
||||||
*.js
|
|
||||||
# 忽略当前目录下为vue的文件的语法检查
|
|
||||||
*.vue
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
// ESlint 检查配置
|
|
||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
parserOptions: {
|
|
||||||
parser: 'babel-eslint',
|
|
||||||
sourceType: 'module'
|
|
||||||
},
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
node: true,
|
|
||||||
es6: true,
|
|
||||||
},
|
|
||||||
extends: ['plugin:vue/recommended', 'eslint:recommended'],
|
|
||||||
|
|
||||||
// add your custom rules here
|
|
||||||
//it is base on https://github.com/vuejs/eslint-config-vue
|
|
||||||
rules: {
|
|
||||||
"vue/max-attributes-per-line": [2, {
|
|
||||||
"singleline": 10,
|
|
||||||
"multiline": {
|
|
||||||
"max": 1,
|
|
||||||
"allowFirstLine": false
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
"vue/singleline-html-element-content-newline": "off",
|
|
||||||
"vue/multiline-html-element-content-newline":"off",
|
|
||||||
"vue/name-property-casing": ["error", "PascalCase"],
|
|
||||||
"vue/no-v-html": "off",
|
|
||||||
'accessor-pairs': 2,
|
|
||||||
'arrow-spacing': [2, {
|
|
||||||
'before': true,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'block-spacing': [2, 'always'],
|
|
||||||
'brace-style': [2, '1tbs', {
|
|
||||||
'allowSingleLine': true
|
|
||||||
}],
|
|
||||||
'camelcase': [0, {
|
|
||||||
'properties': 'always'
|
|
||||||
}],
|
|
||||||
'comma-dangle': [2, 'never'],
|
|
||||||
'comma-spacing': [2, {
|
|
||||||
'before': false,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'comma-style': [2, 'last'],
|
|
||||||
'constructor-super': 2,
|
|
||||||
'curly': [2, 'multi-line'],
|
|
||||||
'dot-location': [2, 'property'],
|
|
||||||
'eol-last': 2,
|
|
||||||
'eqeqeq': ["error", "always", {"null": "ignore"}],
|
|
||||||
'generator-star-spacing': [2, {
|
|
||||||
'before': true,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'handle-callback-err': [2, '^(err|error)$'],
|
|
||||||
'indent': [2, 2, {
|
|
||||||
'SwitchCase': 1
|
|
||||||
}],
|
|
||||||
'jsx-quotes': [2, 'prefer-single'],
|
|
||||||
'key-spacing': [2, {
|
|
||||||
'beforeColon': false,
|
|
||||||
'afterColon': true
|
|
||||||
}],
|
|
||||||
'keyword-spacing': [2, {
|
|
||||||
'before': true,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'new-cap': [2, {
|
|
||||||
'newIsCap': true,
|
|
||||||
'capIsNew': false
|
|
||||||
}],
|
|
||||||
'new-parens': 2,
|
|
||||||
'no-array-constructor': 2,
|
|
||||||
'no-caller': 2,
|
|
||||||
'no-console': 'off',
|
|
||||||
'no-class-assign': 2,
|
|
||||||
'no-cond-assign': 2,
|
|
||||||
'no-const-assign': 2,
|
|
||||||
'no-control-regex': 0,
|
|
||||||
'no-delete-var': 2,
|
|
||||||
'no-dupe-args': 2,
|
|
||||||
'no-dupe-class-members': 2,
|
|
||||||
'no-dupe-keys': 2,
|
|
||||||
'no-duplicate-case': 2,
|
|
||||||
'no-empty-character-class': 2,
|
|
||||||
'no-empty-pattern': 2,
|
|
||||||
'no-eval': 2,
|
|
||||||
'no-ex-assign': 2,
|
|
||||||
'no-extend-native': 2,
|
|
||||||
'no-extra-bind': 2,
|
|
||||||
'no-extra-boolean-cast': 2,
|
|
||||||
'no-extra-parens': [2, 'functions'],
|
|
||||||
'no-fallthrough': 2,
|
|
||||||
'no-floating-decimal': 2,
|
|
||||||
'no-func-assign': 2,
|
|
||||||
'no-implied-eval': 2,
|
|
||||||
'no-inner-declarations': [2, 'functions'],
|
|
||||||
'no-invalid-regexp': 2,
|
|
||||||
'no-irregular-whitespace': 2,
|
|
||||||
'no-iterator': 2,
|
|
||||||
'no-label-var': 2,
|
|
||||||
'no-labels': [2, {
|
|
||||||
'allowLoop': false,
|
|
||||||
'allowSwitch': false
|
|
||||||
}],
|
|
||||||
'no-lone-blocks': 2,
|
|
||||||
'no-mixed-spaces-and-tabs': 2,
|
|
||||||
'no-multi-spaces': 2,
|
|
||||||
'no-multi-str': 2,
|
|
||||||
'no-multiple-empty-lines': [2, {
|
|
||||||
'max': 1
|
|
||||||
}],
|
|
||||||
'no-native-reassign': 2,
|
|
||||||
'no-negated-in-lhs': 2,
|
|
||||||
'no-new-object': 2,
|
|
||||||
'no-new-require': 2,
|
|
||||||
'no-new-symbol': 2,
|
|
||||||
'no-new-wrappers': 2,
|
|
||||||
'no-obj-calls': 2,
|
|
||||||
'no-octal': 2,
|
|
||||||
'no-octal-escape': 2,
|
|
||||||
'no-path-concat': 2,
|
|
||||||
'no-proto': 2,
|
|
||||||
'no-redeclare': 2,
|
|
||||||
'no-regex-spaces': 2,
|
|
||||||
'no-return-assign': [2, 'except-parens'],
|
|
||||||
'no-self-assign': 2,
|
|
||||||
'no-self-compare': 2,
|
|
||||||
'no-sequences': 2,
|
|
||||||
'no-shadow-restricted-names': 2,
|
|
||||||
'no-spaced-func': 2,
|
|
||||||
'no-sparse-arrays': 2,
|
|
||||||
'no-this-before-super': 2,
|
|
||||||
'no-throw-literal': 2,
|
|
||||||
'no-trailing-spaces': 2,
|
|
||||||
'no-undef': 2,
|
|
||||||
'no-undef-init': 2,
|
|
||||||
'no-unexpected-multiline': 2,
|
|
||||||
'no-unmodified-loop-condition': 2,
|
|
||||||
'no-unneeded-ternary': [2, {
|
|
||||||
'defaultAssignment': false
|
|
||||||
}],
|
|
||||||
'no-unreachable': 2,
|
|
||||||
'no-unsafe-finally': 2,
|
|
||||||
'no-unused-vars': [2, {
|
|
||||||
'vars': 'all',
|
|
||||||
'args': 'none'
|
|
||||||
}],
|
|
||||||
'no-useless-call': 2,
|
|
||||||
'no-useless-computed-key': 2,
|
|
||||||
'no-useless-constructor': 2,
|
|
||||||
'no-useless-escape': 0,
|
|
||||||
'no-whitespace-before-property': 2,
|
|
||||||
'no-with': 2,
|
|
||||||
'one-var': [2, {
|
|
||||||
'initialized': 'never'
|
|
||||||
}],
|
|
||||||
'operator-linebreak': [2, 'after', {
|
|
||||||
'overrides': {
|
|
||||||
'?': 'before',
|
|
||||||
':': 'before'
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
'padded-blocks': [2, 'never'],
|
|
||||||
'quotes': [2, 'single', {
|
|
||||||
'avoidEscape': true,
|
|
||||||
'allowTemplateLiterals': true
|
|
||||||
}],
|
|
||||||
'semi': [2, 'never'],
|
|
||||||
'semi-spacing': [2, {
|
|
||||||
'before': false,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'space-before-blocks': [2, 'always'],
|
|
||||||
'space-before-function-paren': [2, 'never'],
|
|
||||||
'space-in-parens': [2, 'never'],
|
|
||||||
'space-infix-ops': 2,
|
|
||||||
'space-unary-ops': [2, {
|
|
||||||
'words': true,
|
|
||||||
'nonwords': false
|
|
||||||
}],
|
|
||||||
'spaced-comment': [2, 'always', {
|
|
||||||
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
|
|
||||||
}],
|
|
||||||
'template-curly-spacing': [2, 'never'],
|
|
||||||
'use-isnan': 2,
|
|
||||||
'valid-typeof': 2,
|
|
||||||
'wrap-iife': [2, 'any'],
|
|
||||||
'yield-star-spacing': [2, 'both'],
|
|
||||||
'yoda': [2, 'never'],
|
|
||||||
'prefer-const': 2,
|
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
|
|
||||||
'object-curly-spacing': [2, 'always', {
|
|
||||||
objectsInObjects: false
|
|
||||||
}],
|
|
||||||
'array-bracket-spacing': [2, 'never']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
46
ruoyi-ui/.gitignore
vendored
@@ -1,23 +1,23 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
dist/
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
**/*.log
|
**/*.log
|
||||||
|
|
||||||
tests/**/coverage/
|
tests/**/coverage/
|
||||||
tests/e2e/reports
|
tests/e2e/reports
|
||||||
selenium-debug.log
|
selenium-debug.log
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
*.suo
|
*.suo
|
||||||
*.ntvs*
|
*.ntvs*
|
||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.local
|
*.local
|
||||||
|
|
||||||
package-lock.json
|
package-lock.json
|
||||||
yarn.lock
|
yarn.lock
|
||||||
|
|||||||
20
ruoyi-ui/LICENSE
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2018 RuoYi
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
@@ -1,30 +1,143 @@
|
|||||||
## 开发
|
<p align="center">
|
||||||
|
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png">
|
||||||
```bash
|
</p>
|
||||||
# 克隆项目
|
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.3</h1>
|
||||||
git clone https://gitee.com/y_project/RuoYi-Vue
|
<h4 align="center">基于 Vue3/Element Plus 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4>
|
||||||
|
<p align="center">
|
||||||
# 进入项目目录
|
<a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a>
|
||||||
cd ruoyi-ui
|
<a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.3-brightgreen.svg"></a>
|
||||||
|
<a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
||||||
# 安装依赖
|
</p>
|
||||||
npm install
|
|
||||||
|
## 平台简介
|
||||||
# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
|
|
||||||
npm install --registry=https://registry.npmmirror.com
|
* 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。
|
||||||
|
* 配套后端代码仓库地址[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud) 或 [RuoYi-Cloud-Oracle](https://github.com/yangzongzhuan/RuoYi-Cloud-Oracle) 版本。
|
||||||
# 启动服务
|
* 前端技术栈([Vue2](https://cn.vuejs.org) + [Element](https://github.com/ElemeFE/element) + [Vue CLI](https://cli.vuejs.org/zh)),请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud/tree/master/ruoyi-ui)。
|
||||||
npm run dev
|
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)
|
||||||
```
|
* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)
|
||||||
|
|
||||||
浏览器访问 http://localhost:80
|
## 前端运行
|
||||||
|
|
||||||
## 发布
|
```bash
|
||||||
|
# 克隆项目
|
||||||
```bash
|
git clone https://github.com/yangzongzhuan/RuoYi-Cloud-Vue3.git
|
||||||
# 构建测试环境
|
|
||||||
npm run build:stage
|
# 进入项目目录
|
||||||
|
cd RuoYi-Cloud-Vue3
|
||||||
# 构建生产环境
|
|
||||||
npm run build:prod
|
# 安装依赖
|
||||||
```
|
yarn --registry=https://registry.npmmirror.com
|
||||||
|
|
||||||
|
# 启动服务
|
||||||
|
yarn dev
|
||||||
|
|
||||||
|
# 构建测试环境 yarn build:stage
|
||||||
|
# 构建生产环境 yarn build:prod
|
||||||
|
# 前端访问地址 http://localhost:80
|
||||||
|
```
|
||||||
|
|
||||||
|
## 系统模块
|
||||||
|
|
||||||
|
~~~
|
||||||
|
com.ruoyi
|
||||||
|
├── ruoyi-ui // 前端框架 [80]
|
||||||
|
├── ruoyi-gateway // 网关模块 [8080]
|
||||||
|
├── ruoyi-auth // 认证中心 [9200]
|
||||||
|
├── ruoyi-api // 接口模块
|
||||||
|
│ └── ruoyi-api-system // 系统接口
|
||||||
|
├── ruoyi-common // 通用模块
|
||||||
|
│ └── ruoyi-common-core // 核心模块
|
||||||
|
│ └── ruoyi-common-datascope // 权限范围
|
||||||
|
│ └── ruoyi-common-datasource // 多数据源
|
||||||
|
│ └── ruoyi-common-log // 日志记录
|
||||||
|
│ └── ruoyi-common-redis // 缓存服务
|
||||||
|
│ └── ruoyi-common-security // 安全模块
|
||||||
|
│ └── ruoyi-common-swagger // 系统接口
|
||||||
|
├── ruoyi-modules // 业务模块
|
||||||
|
│ └── ruoyi-system // 系统模块 [9201]
|
||||||
|
│ └── ruoyi-gen // 代码生成 [9202]
|
||||||
|
│ └── ruoyi-job // 定时任务 [9203]
|
||||||
|
│ └── ruoyi-file // 文件服务 [9300]
|
||||||
|
├── ruoyi-visual // 图形化管理模块
|
||||||
|
│ └── ruoyi-visual-monitor // 监控中心 [9100]
|
||||||
|
├──pom.xml // 公共依赖
|
||||||
|
~~~
|
||||||
|
|
||||||
|
## 架构图
|
||||||
|
|
||||||
|
<img src="https://oscimg.oschina.net/oscnet/up-82e9722ecb846786405a904bafcf19f73f3.png"/>
|
||||||
|
|
||||||
|
## 内置功能
|
||||||
|
|
||||||
|
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
||||||
|
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
|
||||||
|
3. 岗位管理:配置系统用户所属担任职务。
|
||||||
|
4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
|
||||||
|
5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
|
||||||
|
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
|
||||||
|
7. 参数管理:对系统动态配置常用参数。
|
||||||
|
8. 通知公告:系统通知公告信息发布维护。
|
||||||
|
9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
|
||||||
|
10. 登录日志:系统登录日志记录查询包含登录异常。
|
||||||
|
11. 在线用户:当前系统中活跃用户状态监控。
|
||||||
|
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
|
||||||
|
13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
|
||||||
|
14. 系统接口:根据业务代码自动生成相关的api接口文档。
|
||||||
|
15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
|
||||||
|
16. 在线构建器:拖动表单元素生成相应的HTML代码。
|
||||||
|
17. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
|
||||||
|
|
||||||
|
## 在线体验
|
||||||
|
|
||||||
|
- admin/admin123
|
||||||
|
- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
|
||||||
|
|
||||||
|
演示地址:http://ruoyi.vip
|
||||||
|
文档地址:http://doc.ruoyi.vip
|
||||||
|
|
||||||
|
## 演示图
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/cd1f90be5f2684f4560c9519c0f2a232ee8.jpg"/></td>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-4148b24f58660a9dc347761e4cf6162f28f.png"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-ece3fd37a3d4bb75a3926e905a3c5629055.png"/></td>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-92ffb7f3835855cff100fa0f754a6be0d99.png"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-ff9e3066561574aca73005c5730c6a41f15.png"/></td>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
## 若依微服务交流群
|
||||||
|
|
||||||
|
QQ群: [](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) 点击按钮入群。
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
presets: [
|
|
||||||
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
|
|
||||||
'@vue/cli-plugin-babel/preset'
|
|
||||||
],
|
|
||||||
'env': {
|
|
||||||
'development': {
|
|
||||||
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
|
|
||||||
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
|
|
||||||
'plugins': ['dynamic-import-node']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
@echo off
|
@echo off
|
||||||
echo.
|
echo.
|
||||||
echo [信息] 打包Web工程,生成dist文件。
|
echo [信息] 打包Web工程,生成dist文件。
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
%~d0
|
%~d0
|
||||||
cd %~dp0
|
cd %~dp0
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
npm run build:prod
|
yarn build:prod
|
||||||
|
|
||||||
pause
|
pause
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
@echo off
|
@echo off
|
||||||
echo.
|
echo.
|
||||||
echo [信息] 安装Web工程,生成node_modules文件。
|
echo [信息] 安装Web工程,生成node_modules文件。
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
%~d0
|
%~d0
|
||||||
cd %~dp0
|
cd %~dp0
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
npm install --registry=https://registry.npmmirror.com
|
yarn --registry=https://registry.npmmirror.com
|
||||||
|
|
||||||
pause
|
pause
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
@echo off
|
@echo off
|
||||||
echo.
|
echo.
|
||||||
echo [信息] 使用 Vue CLI 命令运行 Web 工程。
|
echo [信息] 使用 Vite 命令运行 Web 工程。
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
%~d0
|
%~d0
|
||||||
cd %~dp0
|
cd %~dp0
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
npm run dev
|
yarn dev
|
||||||
|
|
||||||
pause
|
pause
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
const { run } = require('runjs')
|
|
||||||
const chalk = require('chalk')
|
|
||||||
const config = require('../vue.config.js')
|
|
||||||
const rawArgv = process.argv.slice(2)
|
|
||||||
const args = rawArgv.join(' ')
|
|
||||||
|
|
||||||
if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
|
|
||||||
const report = rawArgv.includes('--report')
|
|
||||||
|
|
||||||
run(`vue-cli-service build ${args}`)
|
|
||||||
|
|
||||||
const port = 9526
|
|
||||||
const publicPath = config.publicPath
|
|
||||||
|
|
||||||
var connect = require('connect')
|
|
||||||
var serveStatic = require('serve-static')
|
|
||||||
const app = connect()
|
|
||||||
|
|
||||||
app.use(
|
|
||||||
publicPath,
|
|
||||||
serveStatic('./dist', {
|
|
||||||
index: ['index.html', '/']
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
app.listen(port, function () {
|
|
||||||
console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`))
|
|
||||||
if (report) {
|
|
||||||
console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`))
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
run(`vue-cli-service build ${args}`)
|
|
||||||
}
|
|
||||||
@@ -1,208 +1,215 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
<head>
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
<meta charset="utf-8">
|
||||||
<meta name="renderer" content="webkit">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
<meta name="renderer" content="webkit">
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
<title><%= webpackConfig.name %></title>
|
<link rel="icon" href="/favicon.ico">
|
||||||
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
|
<title>若依管理系统</title>
|
||||||
<style>
|
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
|
||||||
html,
|
<style>
|
||||||
body,
|
html,
|
||||||
#app {
|
body,
|
||||||
height: 100%;
|
#app {
|
||||||
margin: 0px;
|
height: 100%;
|
||||||
padding: 0px;
|
margin: 0px;
|
||||||
}
|
padding: 0px;
|
||||||
.chromeframe {
|
}
|
||||||
margin: 0.2em 0;
|
|
||||||
background: #ccc;
|
.chromeframe {
|
||||||
color: #000;
|
margin: 0.2em 0;
|
||||||
padding: 0.2em 0;
|
background: #ccc;
|
||||||
}
|
color: #000;
|
||||||
|
padding: 0.2em 0;
|
||||||
#loader-wrapper {
|
}
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
#loader-wrapper {
|
||||||
left: 0;
|
position: fixed;
|
||||||
width: 100%;
|
top: 0;
|
||||||
height: 100%;
|
left: 0;
|
||||||
z-index: 999999;
|
width: 100%;
|
||||||
}
|
height: 100%;
|
||||||
|
z-index: 999999;
|
||||||
#loader {
|
}
|
||||||
display: block;
|
|
||||||
position: relative;
|
#loader {
|
||||||
left: 50%;
|
display: block;
|
||||||
top: 50%;
|
position: relative;
|
||||||
width: 150px;
|
left: 50%;
|
||||||
height: 150px;
|
top: 50%;
|
||||||
margin: -75px 0 0 -75px;
|
width: 150px;
|
||||||
border-radius: 50%;
|
height: 150px;
|
||||||
border: 3px solid transparent;
|
margin: -75px 0 0 -75px;
|
||||||
border-top-color: #FFF;
|
border-radius: 50%;
|
||||||
-webkit-animation: spin 2s linear infinite;
|
border: 3px solid transparent;
|
||||||
-ms-animation: spin 2s linear infinite;
|
border-top-color: #FFF;
|
||||||
-moz-animation: spin 2s linear infinite;
|
-webkit-animation: spin 2s linear infinite;
|
||||||
-o-animation: spin 2s linear infinite;
|
-ms-animation: spin 2s linear infinite;
|
||||||
animation: spin 2s linear infinite;
|
-moz-animation: spin 2s linear infinite;
|
||||||
z-index: 1001;
|
-o-animation: spin 2s linear infinite;
|
||||||
}
|
animation: spin 2s linear infinite;
|
||||||
|
z-index: 1001;
|
||||||
#loader:before {
|
}
|
||||||
content: "";
|
|
||||||
position: absolute;
|
#loader:before {
|
||||||
top: 5px;
|
content: "";
|
||||||
left: 5px;
|
position: absolute;
|
||||||
right: 5px;
|
top: 5px;
|
||||||
bottom: 5px;
|
left: 5px;
|
||||||
border-radius: 50%;
|
right: 5px;
|
||||||
border: 3px solid transparent;
|
bottom: 5px;
|
||||||
border-top-color: #FFF;
|
border-radius: 50%;
|
||||||
-webkit-animation: spin 3s linear infinite;
|
border: 3px solid transparent;
|
||||||
-moz-animation: spin 3s linear infinite;
|
border-top-color: #FFF;
|
||||||
-o-animation: spin 3s linear infinite;
|
-webkit-animation: spin 3s linear infinite;
|
||||||
-ms-animation: spin 3s linear infinite;
|
-moz-animation: spin 3s linear infinite;
|
||||||
animation: spin 3s linear infinite;
|
-o-animation: spin 3s linear infinite;
|
||||||
}
|
-ms-animation: spin 3s linear infinite;
|
||||||
|
animation: spin 3s linear infinite;
|
||||||
#loader:after {
|
}
|
||||||
content: "";
|
|
||||||
position: absolute;
|
#loader:after {
|
||||||
top: 15px;
|
content: "";
|
||||||
left: 15px;
|
position: absolute;
|
||||||
right: 15px;
|
top: 15px;
|
||||||
bottom: 15px;
|
left: 15px;
|
||||||
border-radius: 50%;
|
right: 15px;
|
||||||
border: 3px solid transparent;
|
bottom: 15px;
|
||||||
border-top-color: #FFF;
|
border-radius: 50%;
|
||||||
-moz-animation: spin 1.5s linear infinite;
|
border: 3px solid transparent;
|
||||||
-o-animation: spin 1.5s linear infinite;
|
border-top-color: #FFF;
|
||||||
-ms-animation: spin 1.5s linear infinite;
|
-moz-animation: spin 1.5s linear infinite;
|
||||||
-webkit-animation: spin 1.5s linear infinite;
|
-o-animation: spin 1.5s linear infinite;
|
||||||
animation: spin 1.5s linear infinite;
|
-ms-animation: spin 1.5s linear infinite;
|
||||||
}
|
-webkit-animation: spin 1.5s linear infinite;
|
||||||
|
animation: spin 1.5s linear infinite;
|
||||||
|
}
|
||||||
@-webkit-keyframes spin {
|
|
||||||
0% {
|
|
||||||
-webkit-transform: rotate(0deg);
|
@-webkit-keyframes spin {
|
||||||
-ms-transform: rotate(0deg);
|
0% {
|
||||||
transform: rotate(0deg);
|
-webkit-transform: rotate(0deg);
|
||||||
}
|
-ms-transform: rotate(0deg);
|
||||||
100% {
|
transform: rotate(0deg);
|
||||||
-webkit-transform: rotate(360deg);
|
}
|
||||||
-ms-transform: rotate(360deg);
|
|
||||||
transform: rotate(360deg);
|
100% {
|
||||||
}
|
-webkit-transform: rotate(360deg);
|
||||||
}
|
-ms-transform: rotate(360deg);
|
||||||
|
transform: rotate(360deg);
|
||||||
@keyframes spin {
|
}
|
||||||
0% {
|
}
|
||||||
-webkit-transform: rotate(0deg);
|
|
||||||
-ms-transform: rotate(0deg);
|
@keyframes spin {
|
||||||
transform: rotate(0deg);
|
0% {
|
||||||
}
|
-webkit-transform: rotate(0deg);
|
||||||
100% {
|
-ms-transform: rotate(0deg);
|
||||||
-webkit-transform: rotate(360deg);
|
transform: rotate(0deg);
|
||||||
-ms-transform: rotate(360deg);
|
}
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
100% {
|
||||||
}
|
-webkit-transform: rotate(360deg);
|
||||||
|
-ms-transform: rotate(360deg);
|
||||||
|
transform: rotate(360deg);
|
||||||
#loader-wrapper .loader-section {
|
}
|
||||||
position: fixed;
|
}
|
||||||
top: 0;
|
|
||||||
width: 51%;
|
|
||||||
height: 100%;
|
#loader-wrapper .loader-section {
|
||||||
background: #7171C6;
|
position: fixed;
|
||||||
z-index: 1000;
|
top: 0;
|
||||||
-webkit-transform: translateX(0);
|
width: 51%;
|
||||||
-ms-transform: translateX(0);
|
height: 100%;
|
||||||
transform: translateX(0);
|
background: #7171C6;
|
||||||
}
|
z-index: 1000;
|
||||||
|
-webkit-transform: translateX(0);
|
||||||
#loader-wrapper .loader-section.section-left {
|
-ms-transform: translateX(0);
|
||||||
left: 0;
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#loader-wrapper .loader-section.section-right {
|
#loader-wrapper .loader-section.section-left {
|
||||||
right: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#loader-wrapper .loader-section.section-right {
|
||||||
.loaded #loader-wrapper .loader-section.section-left {
|
right: 0;
|
||||||
-webkit-transform: translateX(-100%);
|
}
|
||||||
-ms-transform: translateX(-100%);
|
|
||||||
transform: translateX(-100%);
|
|
||||||
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
.loaded #loader-wrapper .loader-section.section-left {
|
||||||
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
-webkit-transform: translateX(-100%);
|
||||||
}
|
-ms-transform: translateX(-100%);
|
||||||
|
transform: translateX(-100%);
|
||||||
.loaded #loader-wrapper .loader-section.section-right {
|
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||||
-webkit-transform: translateX(100%);
|
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||||
-ms-transform: translateX(100%);
|
}
|
||||||
transform: translateX(100%);
|
|
||||||
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
.loaded #loader-wrapper .loader-section.section-right {
|
||||||
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
-webkit-transform: translateX(100%);
|
||||||
}
|
-ms-transform: translateX(100%);
|
||||||
|
transform: translateX(100%);
|
||||||
.loaded #loader {
|
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||||
opacity: 0;
|
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||||
-webkit-transition: all 0.3s ease-out;
|
}
|
||||||
transition: all 0.3s ease-out;
|
|
||||||
}
|
.loaded #loader {
|
||||||
|
opacity: 0;
|
||||||
.loaded #loader-wrapper {
|
-webkit-transition: all 0.3s ease-out;
|
||||||
visibility: hidden;
|
transition: all 0.3s ease-out;
|
||||||
-webkit-transform: translateY(-100%);
|
}
|
||||||
-ms-transform: translateY(-100%);
|
|
||||||
transform: translateY(-100%);
|
.loaded #loader-wrapper {
|
||||||
-webkit-transition: all 0.3s 1s ease-out;
|
visibility: hidden;
|
||||||
transition: all 0.3s 1s ease-out;
|
-webkit-transform: translateY(-100%);
|
||||||
}
|
-ms-transform: translateY(-100%);
|
||||||
|
transform: translateY(-100%);
|
||||||
.no-js #loader-wrapper {
|
-webkit-transition: all 0.3s 1s ease-out;
|
||||||
display: none;
|
transition: all 0.3s 1s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-js h1 {
|
.no-js #loader-wrapper {
|
||||||
color: #222222;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#loader-wrapper .load_title {
|
.no-js h1 {
|
||||||
font-family: 'Open Sans';
|
color: #222222;
|
||||||
color: #FFF;
|
}
|
||||||
font-size: 19px;
|
|
||||||
width: 100%;
|
#loader-wrapper .load_title {
|
||||||
text-align: center;
|
font-family: 'Open Sans';
|
||||||
z-index: 9999999999999;
|
color: #FFF;
|
||||||
position: absolute;
|
font-size: 19px;
|
||||||
top: 60%;
|
width: 100%;
|
||||||
opacity: 1;
|
text-align: center;
|
||||||
line-height: 30px;
|
z-index: 9999999999999;
|
||||||
}
|
position: absolute;
|
||||||
|
top: 60%;
|
||||||
#loader-wrapper .load_title span {
|
opacity: 1;
|
||||||
font-weight: normal;
|
line-height: 30px;
|
||||||
font-style: italic;
|
}
|
||||||
font-size: 13px;
|
|
||||||
color: #FFF;
|
#loader-wrapper .load_title span {
|
||||||
opacity: 0.5;
|
font-weight: normal;
|
||||||
}
|
font-style: italic;
|
||||||
</style>
|
font-size: 13px;
|
||||||
</head>
|
color: #FFF;
|
||||||
<body>
|
opacity: 0.5;
|
||||||
<div id="app">
|
}
|
||||||
<div id="loader-wrapper">
|
</style>
|
||||||
<div id="loader"></div>
|
</head>
|
||||||
<div class="loader-section section-left"></div>
|
|
||||||
<div class="loader-section section-right"></div>
|
<body>
|
||||||
<div class="load_title">正在加载系统资源,请耐心等待</div>
|
<div id="app">
|
||||||
</div>
|
<div id="loader-wrapper">
|
||||||
</div>
|
<div id="loader"></div>
|
||||||
</body>
|
<div class="loader-section section-left"></div>
|
||||||
</html>
|
<div class="loader-section section-right"></div>
|
||||||
|
<div class="load_title">正在加载系统资源,请耐心等待</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="module" src="/src/main.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -1,90 +1,45 @@
|
|||||||
{
|
{
|
||||||
"name": "ruoyi",
|
"name": "ruoyi",
|
||||||
"version": "3.6.3",
|
"version": "3.6.3",
|
||||||
"description": "若依管理系统",
|
"description": "若依管理系统",
|
||||||
"author": "若依",
|
"author": "若依",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"type": "module",
|
||||||
"dev": "vue-cli-service serve",
|
"scripts": {
|
||||||
"build:prod": "vue-cli-service build",
|
"dev": "vite",
|
||||||
"build:stage": "vue-cli-service build --mode staging",
|
"build:prod": "vite build",
|
||||||
"preview": "node build/index.js --preview",
|
"build:stage": "vite build --mode staging",
|
||||||
"lint": "eslint --ext .js,.vue src"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"husky": {
|
"repository": {
|
||||||
"hooks": {
|
"type": "git",
|
||||||
"pre-commit": "lint-staged"
|
"url": "https://gitee.com/y_project/RuoYi-Cloud.git"
|
||||||
}
|
},
|
||||||
},
|
"dependencies": {
|
||||||
"lint-staged": {
|
"@element-plus/icons-vue": "2.3.1",
|
||||||
"src/**/*.{js,vue}": [
|
"@vueup/vue-quill": "1.2.0",
|
||||||
"eslint --fix",
|
"@vueuse/core": "10.6.1",
|
||||||
"git add"
|
"axios": "0.27.2",
|
||||||
]
|
"echarts": "5.4.3",
|
||||||
},
|
"element-plus": "2.4.3",
|
||||||
"keywords": [
|
"file-saver": "2.0.5",
|
||||||
"vue",
|
"fuse.js": "6.6.2",
|
||||||
"admin",
|
"js-cookie": "3.0.5",
|
||||||
"dashboard",
|
"jsencrypt": "3.3.2",
|
||||||
"element-ui",
|
"nprogress": "0.2.0",
|
||||||
"boilerplate",
|
"pinia": "2.1.7",
|
||||||
"admin-template",
|
"vue": "3.3.9",
|
||||||
"management-system"
|
"vue-cropper": "1.1.1",
|
||||||
],
|
"vue-router": "4.2.5"
|
||||||
"repository": {
|
},
|
||||||
"type": "git",
|
"devDependencies": {
|
||||||
"url": "https://gitee.com/y_project/RuoYi-Cloud.git"
|
"@vitejs/plugin-vue": "4.5.0",
|
||||||
},
|
"@vue/compiler-sfc": "3.3.9",
|
||||||
"dependencies": {
|
"sass": "1.69.5",
|
||||||
"@riophae/vue-treeselect": "0.4.0",
|
"unplugin-auto-import": "0.17.1",
|
||||||
"axios": "0.24.0",
|
"vite": "5.0.4",
|
||||||
"clipboard": "2.0.8",
|
"vite-plugin-compression": "0.5.1",
|
||||||
"core-js": "3.25.3",
|
"vite-plugin-svg-icons": "2.0.1",
|
||||||
"echarts": "5.4.0",
|
"unplugin-vue-setup-extend-plus": "1.0.0"
|
||||||
"element-ui": "2.15.14",
|
}
|
||||||
"file-saver": "2.0.5",
|
}
|
||||||
"fuse.js": "6.4.3",
|
|
||||||
"highlight.js": "9.18.5",
|
|
||||||
"js-beautify": "1.13.0",
|
|
||||||
"js-cookie": "3.0.1",
|
|
||||||
"jsencrypt": "3.0.0-rc.1",
|
|
||||||
"nprogress": "0.2.0",
|
|
||||||
"quill": "1.3.7",
|
|
||||||
"screenfull": "5.0.2",
|
|
||||||
"sortablejs": "1.10.2",
|
|
||||||
"vue": "2.6.12",
|
|
||||||
"vue-count-to": "1.0.13",
|
|
||||||
"vue-cropper": "0.5.5",
|
|
||||||
"vue-meta": "2.4.0",
|
|
||||||
"vue-router": "3.4.9",
|
|
||||||
"vuedraggable": "2.24.3",
|
|
||||||
"vuex": "3.6.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@vue/cli-plugin-babel": "4.4.6",
|
|
||||||
"@vue/cli-plugin-eslint": "4.4.6",
|
|
||||||
"@vue/cli-service": "4.4.6",
|
|
||||||
"babel-eslint": "10.1.0",
|
|
||||||
"babel-plugin-dynamic-import-node": "2.3.3",
|
|
||||||
"chalk": "4.1.0",
|
|
||||||
"compression-webpack-plugin": "5.0.2",
|
|
||||||
"connect": "3.6.6",
|
|
||||||
"eslint": "7.15.0",
|
|
||||||
"eslint-plugin-vue": "7.2.0",
|
|
||||||
"lint-staged": "10.5.3",
|
|
||||||
"runjs": "4.4.2",
|
|
||||||
"sass": "1.32.13",
|
|
||||||
"sass-loader": "10.1.1",
|
|
||||||
"script-ext-html-webpack-plugin": "2.1.5",
|
|
||||||
"svg-sprite-loader": "5.1.1",
|
|
||||||
"vue-template-compiler": "2.6.12"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.9",
|
|
||||||
"npm": ">= 3.0.0"
|
|
||||||
},
|
|
||||||
"browserslist": [
|
|
||||||
"> 1%",
|
|
||||||
"last 2 versions"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
User-agent: *
|
|
||||||
Disallow: /
|
|
||||||
@@ -1,28 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<router-view />
|
||||||
<router-view />
|
</template>
|
||||||
<theme-picker />
|
|
||||||
</div>
|
<script setup>
|
||||||
</template>
|
import useSettingsStore from '@/store/modules/settings'
|
||||||
|
import { handleThemeStyle } from '@/utils/theme'
|
||||||
<script>
|
|
||||||
import ThemePicker from "@/components/ThemePicker";
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
export default {
|
// ³õʼ»¯Ö÷ÌâÑùʽ
|
||||||
name: "App",
|
handleThemeStyle(useSettingsStore().theme)
|
||||||
components: { ThemePicker },
|
})
|
||||||
metaInfo() {
|
})
|
||||||
return {
|
</script>
|
||||||
title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
|
|
||||||
titleTemplate: title => {
|
|
||||||
return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style scoped>
|
|
||||||
#app .theme-picker {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,62 +1,62 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 登录方法
|
// 登录方法
|
||||||
export function login(username, password, code, uuid) {
|
export function login(username, password, code, uuid) {
|
||||||
return request({
|
return request({
|
||||||
url: '/auth/login',
|
url: '/auth/login',
|
||||||
headers: {
|
headers: {
|
||||||
isToken: false,
|
isToken: false,
|
||||||
repeatSubmit: false
|
repeatSubmit: false
|
||||||
},
|
},
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: { username, password, code, uuid }
|
data: { username, password, code, uuid }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册方法
|
// 注册方法
|
||||||
export function register(data) {
|
export function register(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/auth/register',
|
url: '/auth/register',
|
||||||
headers: {
|
headers: {
|
||||||
isToken: false
|
isToken: false
|
||||||
},
|
},
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 刷新方法
|
// 刷新方法
|
||||||
export function refreshToken() {
|
export function refreshToken() {
|
||||||
return request({
|
return request({
|
||||||
url: '/auth/refresh',
|
url: '/auth/refresh',
|
||||||
method: 'post'
|
method: 'post'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取用户详细信息
|
// 获取用户详细信息
|
||||||
export function getInfo() {
|
export function getInfo() {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/getInfo',
|
url: '/system/user/getInfo',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 退出方法
|
// 退出方法
|
||||||
export function logout() {
|
export function logout() {
|
||||||
return request({
|
return request({
|
||||||
url: '/auth/logout',
|
url: '/auth/logout',
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取验证码
|
// 获取验证码
|
||||||
export function getCodeImg() {
|
export function getCodeImg() {
|
||||||
return request({
|
return request({
|
||||||
url: '/code',
|
url: '/code',
|
||||||
headers: {
|
headers: {
|
||||||
isToken: false
|
isToken: false
|
||||||
},
|
},
|
||||||
method: 'get',
|
method: 'get',
|
||||||
timeout: 20000
|
timeout: 20000
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 获取路由
|
// 获取路由
|
||||||
export const getRouters = () => {
|
export const getRouters = () => {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/menu/getRouters',
|
url: '/system/menu/getRouters',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1,71 +1,71 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询定时任务调度列表
|
// 查询定时任务调度列表
|
||||||
export function listJob(query) {
|
export function listJob(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/schedule/job/list',
|
url: '/schedule/job/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询定时任务调度详细
|
// 查询定时任务调度详细
|
||||||
export function getJob(jobId) {
|
export function getJob(jobId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/schedule/job/' + jobId,
|
url: '/schedule/job/' + jobId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增定时任务调度
|
// 新增定时任务调度
|
||||||
export function addJob(data) {
|
export function addJob(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/schedule/job',
|
url: '/schedule/job',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改定时任务调度
|
// 修改定时任务调度
|
||||||
export function updateJob(data) {
|
export function updateJob(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/schedule/job',
|
url: '/schedule/job',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除定时任务调度
|
// 删除定时任务调度
|
||||||
export function delJob(jobId) {
|
export function delJob(jobId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/schedule/job/' + jobId,
|
url: '/schedule/job/' + jobId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 任务状态修改
|
// 任务状态修改
|
||||||
export function changeJobStatus(jobId, status) {
|
export function changeJobStatus(jobId, status) {
|
||||||
const data = {
|
const data = {
|
||||||
jobId,
|
jobId,
|
||||||
status
|
status
|
||||||
}
|
}
|
||||||
return request({
|
return request({
|
||||||
url: '/schedule/job/changeStatus',
|
url: '/schedule/job/changeStatus',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 定时任务立即执行一次
|
// 定时任务立即执行一次
|
||||||
export function runJob(jobId, jobGroup) {
|
export function runJob(jobId, jobGroup) {
|
||||||
const data = {
|
const data = {
|
||||||
jobId,
|
jobId,
|
||||||
jobGroup
|
jobGroup
|
||||||
}
|
}
|
||||||
return request({
|
return request({
|
||||||
url: '/schedule/job/run',
|
url: '/schedule/job/run',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1,26 +1,26 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询调度日志列表
|
// 查询调度日志列表
|
||||||
export function listJobLog(query) {
|
export function listJobLog(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/schedule/job/log/list',
|
url: '/schedule/job/log/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除调度日志
|
// 删除调度日志
|
||||||
export function delJobLog(jobLogId) {
|
export function delJobLog(jobLogId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/schedule/job/log/' + jobLogId,
|
url: '/schedule/job/log/' + jobLogId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清空调度日志
|
// 清空调度日志
|
||||||
export function cleanJobLog() {
|
export function cleanJobLog() {
|
||||||
return request({
|
return request({
|
||||||
url: '/schedule/job/log/clean',
|
url: '/schedule/job/log/clean',
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询在线用户列表
|
// 查询在线用户列表
|
||||||
export function list(query) {
|
export function list(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/online/list',
|
url: '/system/online/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 强退用户
|
// 强退用户
|
||||||
export function forceLogout(tokenId) {
|
export function forceLogout(tokenId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/online/' + tokenId,
|
url: '/system/online/' + tokenId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,60 +1,60 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询参数列表
|
// 查询参数列表
|
||||||
export function listConfig(query) {
|
export function listConfig(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/config/list',
|
url: '/system/config/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询参数详细
|
// 查询参数详细
|
||||||
export function getConfig(configId) {
|
export function getConfig(configId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/config/' + configId,
|
url: '/system/config/' + configId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据参数键名查询参数值
|
// 根据参数键名查询参数值
|
||||||
export function getConfigKey(configKey) {
|
export function getConfigKey(configKey) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/config/configKey/' + configKey,
|
url: '/system/config/configKey/' + configKey,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增参数配置
|
// 新增参数配置
|
||||||
export function addConfig(data) {
|
export function addConfig(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/config',
|
url: '/system/config',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改参数配置
|
// 修改参数配置
|
||||||
export function updateConfig(data) {
|
export function updateConfig(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/config',
|
url: '/system/config',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除参数配置
|
// 删除参数配置
|
||||||
export function delConfig(configId) {
|
export function delConfig(configId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/config/' + configId,
|
url: '/system/config/' + configId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 刷新参数缓存
|
// 刷新参数缓存
|
||||||
export function refreshCache() {
|
export function refreshCache() {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/config/refreshCache',
|
url: '/system/config/refreshCache',
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +1,52 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询部门列表
|
// 查询部门列表
|
||||||
export function listDept(query) {
|
export function listDept(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dept/list',
|
url: '/system/dept/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询部门列表(排除节点)
|
// 查询部门列表(排除节点)
|
||||||
export function listDeptExcludeChild(deptId) {
|
export function listDeptExcludeChild(deptId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dept/list/exclude/' + deptId,
|
url: '/system/dept/list/exclude/' + deptId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询部门详细
|
// 查询部门详细
|
||||||
export function getDept(deptId) {
|
export function getDept(deptId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dept/' + deptId,
|
url: '/system/dept/' + deptId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增部门
|
// 新增部门
|
||||||
export function addDept(data) {
|
export function addDept(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dept',
|
url: '/system/dept',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改部门
|
// 修改部门
|
||||||
export function updateDept(data) {
|
export function updateDept(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dept',
|
url: '/system/dept',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除部门
|
// 删除部门
|
||||||
export function delDept(deptId) {
|
export function delDept(deptId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dept/' + deptId,
|
url: '/system/dept/' + deptId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1,52 +1,52 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询字典数据列表
|
// 查询字典数据列表
|
||||||
export function listData(query) {
|
export function listData(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dict/data/list',
|
url: '/system/dict/data/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询字典数据详细
|
// 查询字典数据详细
|
||||||
export function getData(dictCode) {
|
export function getData(dictCode) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dict/data/' + dictCode,
|
url: '/system/dict/data/' + dictCode,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据字典类型查询字典数据信息
|
// 根据字典类型查询字典数据信息
|
||||||
export function getDicts(dictType) {
|
export function getDicts(dictType) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dict/data/type/' + dictType,
|
url: '/system/dict/data/type/' + dictType,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增字典数据
|
// 新增字典数据
|
||||||
export function addData(data) {
|
export function addData(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dict/data',
|
url: '/system/dict/data',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改字典数据
|
// 修改字典数据
|
||||||
export function updateData(data) {
|
export function updateData(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dict/data',
|
url: '/system/dict/data',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除字典数据
|
// 删除字典数据
|
||||||
export function delData(dictCode) {
|
export function delData(dictCode) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dict/data/' + dictCode,
|
url: '/system/dict/data/' + dictCode,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,60 +1,60 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询字典类型列表
|
// 查询字典类型列表
|
||||||
export function listType(query) {
|
export function listType(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dict/type/list',
|
url: '/system/dict/type/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询字典类型详细
|
// 查询字典类型详细
|
||||||
export function getType(dictId) {
|
export function getType(dictId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dict/type/' + dictId,
|
url: '/system/dict/type/' + dictId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增字典类型
|
// 新增字典类型
|
||||||
export function addType(data) {
|
export function addType(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dict/type',
|
url: '/system/dict/type',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改字典类型
|
// 修改字典类型
|
||||||
export function updateType(data) {
|
export function updateType(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dict/type',
|
url: '/system/dict/type',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除字典类型
|
// 删除字典类型
|
||||||
export function delType(dictId) {
|
export function delType(dictId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dict/type/' + dictId,
|
url: '/system/dict/type/' + dictId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 刷新字典缓存
|
// 刷新字典缓存
|
||||||
export function refreshCache() {
|
export function refreshCache() {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dict/type/refreshCache',
|
url: '/system/dict/type/refreshCache',
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取字典选择框列表
|
// 获取字典选择框列表
|
||||||
export function optionselect() {
|
export function optionselect() {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/dict/type/optionselect',
|
url: '/system/dict/type/optionselect',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询登录日志列表
|
// 查询登录日志列表
|
||||||
export function list(query) {
|
export function list(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/logininfor/list',
|
url: '/system/logininfor/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除登录日志
|
// 删除登录日志
|
||||||
export function delLogininfor(infoId) {
|
export function delLogininfor(infoId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/logininfor/' + infoId,
|
url: '/system/logininfor/' + infoId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解锁用户登录状态
|
// 解锁用户登录状态
|
||||||
export function unlockLogininfor(userName) {
|
export function unlockLogininfor(userName) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/logininfor/unlock/' + userName,
|
url: '/system/logininfor/unlock/' + userName,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 清空登录日志
|
// 清空登录日志
|
||||||
export function cleanLogininfor() {
|
export function cleanLogininfor() {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/logininfor/clean',
|
url: '/system/logininfor/clean',
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,60 +1,60 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询菜单列表
|
// 查询菜单列表
|
||||||
export function listMenu(query) {
|
export function listMenu(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/menu/list',
|
url: '/system/menu/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询菜单详细
|
// 查询菜单详细
|
||||||
export function getMenu(menuId) {
|
export function getMenu(menuId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/menu/' + menuId,
|
url: '/system/menu/' + menuId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询菜单下拉树结构
|
// 查询菜单下拉树结构
|
||||||
export function treeselect() {
|
export function treeselect() {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/menu/treeselect',
|
url: '/system/menu/treeselect',
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据角色ID查询菜单下拉树结构
|
// 根据角色ID查询菜单下拉树结构
|
||||||
export function roleMenuTreeselect(roleId) {
|
export function roleMenuTreeselect(roleId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/menu/roleMenuTreeselect/' + roleId,
|
url: '/system/menu/roleMenuTreeselect/' + roleId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增菜单
|
// 新增菜单
|
||||||
export function addMenu(data) {
|
export function addMenu(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/menu',
|
url: '/system/menu',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改菜单
|
// 修改菜单
|
||||||
export function updateMenu(data) {
|
export function updateMenu(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/menu',
|
url: '/system/menu',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除菜单
|
// 删除菜单
|
||||||
export function delMenu(menuId) {
|
export function delMenu(menuId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/menu/' + menuId,
|
url: '/system/menu/' + menuId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1,44 +1,44 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询公告列表
|
// 查询公告列表
|
||||||
export function listNotice(query) {
|
export function listNotice(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/notice/list',
|
url: '/system/notice/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询公告详细
|
// 查询公告详细
|
||||||
export function getNotice(noticeId) {
|
export function getNotice(noticeId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/notice/' + noticeId,
|
url: '/system/notice/' + noticeId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增公告
|
// 新增公告
|
||||||
export function addNotice(data) {
|
export function addNotice(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/notice',
|
url: '/system/notice',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改公告
|
// 修改公告
|
||||||
export function updateNotice(data) {
|
export function updateNotice(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/notice',
|
url: '/system/notice',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除公告
|
// 删除公告
|
||||||
export function delNotice(noticeId) {
|
export function delNotice(noticeId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/notice/' + noticeId,
|
url: '/system/notice/' + noticeId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1,26 +1,26 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询操作日志列表
|
// 查询操作日志列表
|
||||||
export function list(query) {
|
export function list(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/operlog/list',
|
url: '/system/operlog/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除操作日志
|
// 删除操作日志
|
||||||
export function delOperlog(operId) {
|
export function delOperlog(operId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/operlog/' + operId,
|
url: '/system/operlog/' + operId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清空操作日志
|
// 清空操作日志
|
||||||
export function cleanOperlog() {
|
export function cleanOperlog() {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/operlog/clean',
|
url: '/system/operlog/clean',
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,44 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询岗位列表
|
// 查询岗位列表
|
||||||
export function listPost(query) {
|
export function listPost(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/post/list',
|
url: '/system/post/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询岗位详细
|
// 查询岗位详细
|
||||||
export function getPost(postId) {
|
export function getPost(postId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/post/' + postId,
|
url: '/system/post/' + postId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增岗位
|
// 新增岗位
|
||||||
export function addPost(data) {
|
export function addPost(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/post',
|
url: '/system/post',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改岗位
|
// 修改岗位
|
||||||
export function updatePost(data) {
|
export function updatePost(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/post',
|
url: '/system/post',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除岗位
|
// 删除岗位
|
||||||
export function delPost(postId) {
|
export function delPost(postId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/post/' + postId,
|
url: '/system/post/' + postId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,119 +1,119 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询角色列表
|
// 查询角色列表
|
||||||
export function listRole(query) {
|
export function listRole(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/list',
|
url: '/system/role/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询角色详细
|
// 查询角色详细
|
||||||
export function getRole(roleId) {
|
export function getRole(roleId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/' + roleId,
|
url: '/system/role/' + roleId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增角色
|
// 新增角色
|
||||||
export function addRole(data) {
|
export function addRole(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role',
|
url: '/system/role',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改角色
|
// 修改角色
|
||||||
export function updateRole(data) {
|
export function updateRole(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role',
|
url: '/system/role',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 角色数据权限
|
// 角色数据权限
|
||||||
export function dataScope(data) {
|
export function dataScope(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/dataScope',
|
url: '/system/role/dataScope',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 角色状态修改
|
// 角色状态修改
|
||||||
export function changeRoleStatus(roleId, status) {
|
export function changeRoleStatus(roleId, status) {
|
||||||
const data = {
|
const data = {
|
||||||
roleId,
|
roleId,
|
||||||
status
|
status
|
||||||
}
|
}
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/changeStatus',
|
url: '/system/role/changeStatus',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除角色
|
// 删除角色
|
||||||
export function delRole(roleId) {
|
export function delRole(roleId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/' + roleId,
|
url: '/system/role/' + roleId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询角色已授权用户列表
|
// 查询角色已授权用户列表
|
||||||
export function allocatedUserList(query) {
|
export function allocatedUserList(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/authUser/allocatedList',
|
url: '/system/role/authUser/allocatedList',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询角色未授权用户列表
|
// 查询角色未授权用户列表
|
||||||
export function unallocatedUserList(query) {
|
export function unallocatedUserList(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/authUser/unallocatedList',
|
url: '/system/role/authUser/unallocatedList',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取消用户授权角色
|
// 取消用户授权角色
|
||||||
export function authUserCancel(data) {
|
export function authUserCancel(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/authUser/cancel',
|
url: '/system/role/authUser/cancel',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量取消用户授权角色
|
// 批量取消用户授权角色
|
||||||
export function authUserCancelAll(data) {
|
export function authUserCancelAll(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/authUser/cancelAll',
|
url: '/system/role/authUser/cancelAll',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
params: data
|
params: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 授权用户选择
|
// 授权用户选择
|
||||||
export function authUserSelectAll(data) {
|
export function authUserSelectAll(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/authUser/selectAll',
|
url: '/system/role/authUser/selectAll',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
params: data
|
params: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据角色ID查询部门树结构
|
// 根据角色ID查询部门树结构
|
||||||
export function deptTreeSelect(roleId) {
|
export function deptTreeSelect(roleId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/deptTree/' + roleId,
|
url: '/system/role/deptTree/' + roleId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,76 +1,76 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
// 查询生成表数据
|
// 查询生成表数据
|
||||||
export function listTable(query) {
|
export function listTable(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/code/gen/list',
|
url: '/code/gen/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 查询db数据库列表
|
// 查询db数据库列表
|
||||||
export function listDbTable(query) {
|
export function listDbTable(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/code/gen/db/list',
|
url: '/code/gen/db/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询表详细信息
|
// 查询表详细信息
|
||||||
export function getGenTable(tableId) {
|
export function getGenTable(tableId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/code/gen/' + tableId,
|
url: '/code/gen/' + tableId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改代码生成信息
|
// 修改代码生成信息
|
||||||
export function updateGenTable(data) {
|
export function updateGenTable(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/code/gen',
|
url: '/code/gen',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导入表
|
// 导入表
|
||||||
export function importTable(data) {
|
export function importTable(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/code/gen/importTable',
|
url: '/code/gen/importTable',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
params: data
|
params: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 预览生成代码
|
// 预览生成代码
|
||||||
export function previewTable(tableId) {
|
export function previewTable(tableId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/code/gen/preview/' + tableId,
|
url: '/code/gen/preview/' + tableId,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除表数据
|
// 删除表数据
|
||||||
export function delTable(tableId) {
|
export function delTable(tableId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/code/gen/' + tableId,
|
url: '/code/gen/' + tableId,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成代码(自定义路径)
|
// 生成代码(自定义路径)
|
||||||
export function genCode(tableName) {
|
export function genCode(tableName) {
|
||||||
return request({
|
return request({
|
||||||
url: '/code/gen/genCode/' + tableName,
|
url: '/code/gen/genCode/' + tableName,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 同步数据库
|
// 同步数据库
|
||||||
export function synchDb(tableName) {
|
export function synchDb(tableName) {
|
||||||
return request({
|
return request({
|
||||||
url: '/code/gen/synchDb/' + tableName,
|
url: '/code/gen/synchDb/' + tableName,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
import Vue from 'vue'
|
|
||||||
import SvgIcon from '@/components/SvgIcon'// svg component
|
|
||||||
|
|
||||||
// register globally
|
|
||||||
Vue.component('svg-icon', SvgIcon)
|
|
||||||
|
|
||||||
const req = require.context('./svg', false, /\.svg$/)
|
|
||||||
const requireAll = requireContext => requireContext.keys().map(requireContext)
|
|
||||||
requireAll(req)
|
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543827393750" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4695" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; }
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543827393750" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4695" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; }
|
||||||
</style></defs><path d="M64 64V640H896V64H64zM0 0h960v704H0V0z" p-id="4696"></path><path d="M192 896H768v64H192zM448 640H512v256h-64z" p-id="4697"></path><path d="M479.232 561.604267l309.9904-348.330667-47.803733-42.5472-259.566934 291.669333L303.957333 240.008533 163.208533 438.6048l52.224 37.009067 91.6224-129.28z" p-id="4698"></path></svg>
|
</style></defs><path d="M64 64V640H896V64H64zM0 0h960v704H0V0z" p-id="4696"></path><path d="M192 896H768v64H192zM448 640H512v256h-64z" p-id="4697"></path><path d="M479.232 561.604267l309.9904-348.330667-47.803733-42.5472-259.566934 291.669333L303.957333 240.008533 163.208533 438.6048l52.224 37.009067 91.6224-129.28z" p-id="4698"></path></svg>
|
||||||
|
Before Width: | Height: | Size: 884 B After Width: | Height: | Size: 883 B |
1
ruoyi-ui/src/assets/icons/svg/redis.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1605865043777" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="856" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M1023.786667 611.84c-0.426667 9.770667-13.354667 20.693333-39.893334 34.56-54.613333 28.458667-337.749333 144.896-397.994666 176.298667-60.288 31.402667-93.738667 31.104-141.354667 8.32-47.616-22.741333-348.842667-144.469333-403.114667-170.368-27.093333-12.970667-40.917333-23.893333-41.386666-34.218667v103.509333c0 10.325333 14.250667 21.290667 41.386666 34.261334 54.272 25.941333 355.541333 147.626667 403.114667 170.368 47.616 22.784 81.066667 23.082667 141.354667-8.362667 60.245333-31.402667 343.338667-147.797333 397.994666-176.298667 27.776-14.464 40.106667-25.728 40.106667-35.925333v-102.058667l-0.213333-0.085333z m0-168.746667c-0.512 9.770667-13.397333 20.650667-39.893334 34.517334-54.613333 28.458667-337.749333 144.896-397.994666 176.298666-60.288 31.402667-93.738667 31.104-141.354667 8.362667-47.616-22.741333-348.842667-144.469333-403.114667-170.410667-27.093333-12.928-40.917333-23.893333-41.386666-34.176v103.509334c0 10.325333 14.250667 21.248 41.386666 34.218666 54.272 25.941333 355.498667 147.626667 403.114667 170.368 47.616 22.784 81.066667 23.082667 141.354667-8.32 60.245333-31.402667 343.338667-147.84 397.994666-176.298666 27.776-14.506667 40.106667-25.770667 40.106667-35.968v-102.058667l-0.256-0.042667z m0-175.018666c0.469333-10.410667-13.141333-19.541333-40.533334-29.610667-53.248-19.498667-334.634667-131.498667-388.522666-151.253333-53.888-19.712-75.818667-18.901333-139.093334 3.84C392.234667 113.706667 92.629333 231.253333 39.338667 252.074667c-26.666667 10.496-39.68 20.181333-39.253334 30.506666V386.133333c0 10.325333 14.250667 21.248 41.386667 34.218667 54.272 25.941333 355.498667 147.669333 403.114667 170.410667 47.616 22.741333 81.066667 23.04 141.354666-8.362667 60.245333-31.402667 343.338667-147.84 397.994667-176.298667 27.776-14.506667 40.106667-25.770667 40.106667-35.968V268.074667h-0.341334zM366.677333 366.08l237.269334-36.437333-71.68 105.088-165.546667-68.650667z m524.8-94.634667l-140.330666 55.466667-15.232 5.973333-140.245334-55.466666 155.392-61.44 140.373334 55.466666z m-411.989333-101.674666l-22.954667-42.325334 71.594667 27.989334 67.498667-22.101334-18.261334 43.733334 68.778667 25.770666-88.704 9.216-19.882667 47.786667-32.085333-53.290667-102.4-9.216 76.416-27.562666z m-176.768 59.733333c70.058667 0 126.805333 21.973333 126.805333 49.109333s-56.746667 49.152-126.805333 49.152-126.848-22.058667-126.848-49.152c0-27.136 56.789333-49.152 126.848-49.152z" p-id="857"></path></svg>
|
||||||
|
After Width: | Height: | Size: 2.8 KiB |
@@ -1,2 +1,2 @@
|
|||||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543827724451" class="icon" style="" viewBox="0 0 1084 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10233" xmlns:xlink="http://www.w3.org/1999/xlink" width="211.71875" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; }
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543827724451" class="icon" style="" viewBox="0 0 1084 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10233" xmlns:xlink="http://www.w3.org/1999/xlink" width="211.71875" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; }
|
||||||
</style></defs><path d="M1080.09609 434.500756c-4.216302-23.731757-26.9241-47.945376-50.595623-53.185637l-17.648235-4.095836a175.940257 175.940257 0 0 1-101.612877-80.832531 177.807476 177.807476 0 0 1-18.732427-129.801867l5.541425-16.684509c7.10748-23.129428-2.108151-54.992624-20.599646-70.833873 0 0-16.624276-14.094495-63.244529-41.199293-46.800951-26.984332-66.858502-34.513443-66.858502-34.513443-22.76803-8.372371-54.631227-0.361397-71.255503 17.407304l-12.287509 13.251234a173.470708 173.470708 0 0 1-120.465769 48.065842A174.13327 174.13327 0 0 1 421.329029 33.590675L409.583617 20.761071C393.140039 2.99237 361.096144-4.898138 338.267881 3.353767c0 0-20.358715 7.529111-67.099434 34.513443-46.800951 27.34573-63.244529 41.440225-63.244529 41.440225-18.431263 15.66055-27.646894 47.222582-20.539413 70.592941l5.059562 16.865207a178.048407 178.048407 0 0 1-18.672194 129.621169 174.916297 174.916297 0 0 1-102.275439 81.073463l-17.045906 3.854904c-23.310126 5.42096-46.258856 29.333415-50.595623 53.185637 0 0-3.854905 21.382674-3.854905 75.712737 0 54.330062 3.854905 75.712736 3.854905 75.712736 4.216302 23.972688 26.9241 47.945376 50.595623 53.185637l16.624276 3.854905a174.253736 174.253736 0 0 1 102.395904 81.314394c23.310126 40.837896 28.911785 87.337683 18.732427 129.801867l-4.81863 16.443578c-7.10748 23.129428 2.108151 54.992624 20.599646 70.833872 0 0 16.624276 14.094495 63.244529 41.199293 46.800951 27.104798 66.918735 34.513443 66.918735 34.513443 22.707798 8.372371 54.631227 0.361397 71.255503-17.407303l11.624947-12.588673a175.096996 175.096996 0 0 1 242.256662 0.120465l11.624947 12.648906c16.383345 17.708468 48.427239 25.598976 71.255503 17.347071 0 0 20.358715-7.529111 67.159666-34.513443 46.740719-27.104798 63.124063-41.199293 63.124064-41.199293 18.491496-15.600317 27.707127-47.463513 20.599646-70.833873l-5.059562-17.106139a176.723284 176.723284 0 0 1 18.672194-129.139305 176.060722 176.060722 0 0 1 102.395904-81.314394l16.68451-3.854905c23.310126-5.42096 46.258856-29.333415 50.595623-53.185637 0 0 3.854905-21.382674 3.854904-75.712737-0.240932-54.330062-4.095836-75.833202-4.095836-75.833202z m-537.819428 293.334149c-119.261112 0-216.175824-97.336342-216.175824-217.621412a216.657687 216.657687 0 0 1 216.236057-217.320249c119.200879 0 216.115591 97.276109 216.11559 217.56118-0.240932 120.044139-96.974945 217.320248-216.175823 217.320249z" p-id="10234"></path></svg>
|
</style></defs><path d="M1080.09609 434.500756c-4.216302-23.731757-26.9241-47.945376-50.595623-53.185637l-17.648235-4.095836a175.940257 175.940257 0 0 1-101.612877-80.832531 177.807476 177.807476 0 0 1-18.732427-129.801867l5.541425-16.684509c7.10748-23.129428-2.108151-54.992624-20.599646-70.833873 0 0-16.624276-14.094495-63.244529-41.199293-46.800951-26.984332-66.858502-34.513443-66.858502-34.513443-22.76803-8.372371-54.631227-0.361397-71.255503 17.407304l-12.287509 13.251234a173.470708 173.470708 0 0 1-120.465769 48.065842A174.13327 174.13327 0 0 1 421.329029 33.590675L409.583617 20.761071C393.140039 2.99237 361.096144-4.898138 338.267881 3.353767c0 0-20.358715 7.529111-67.099434 34.513443-46.800951 27.34573-63.244529 41.440225-63.244529 41.440225-18.431263 15.66055-27.646894 47.222582-20.539413 70.592941l5.059562 16.865207a178.048407 178.048407 0 0 1-18.672194 129.621169 174.916297 174.916297 0 0 1-102.275439 81.073463l-17.045906 3.854904c-23.310126 5.42096-46.258856 29.333415-50.595623 53.185637 0 0-3.854905 21.382674-3.854905 75.712737 0 54.330062 3.854905 75.712736 3.854905 75.712736 4.216302 23.972688 26.9241 47.945376 50.595623 53.185637l16.624276 3.854905a174.253736 174.253736 0 0 1 102.395904 81.314394c23.310126 40.837896 28.911785 87.337683 18.732427 129.801867l-4.81863 16.443578c-7.10748 23.129428 2.108151 54.992624 20.599646 70.833872 0 0 16.624276 14.094495 63.244529 41.199293 46.800951 27.104798 66.918735 34.513443 66.918735 34.513443 22.707798 8.372371 54.631227 0.361397 71.255503-17.407303l11.624947-12.588673a175.096996 175.096996 0 0 1 242.256662 0.120465l11.624947 12.648906c16.383345 17.708468 48.427239 25.598976 71.255503 17.347071 0 0 20.358715-7.529111 67.159666-34.513443 46.740719-27.104798 63.124063-41.199293 63.124064-41.199293 18.491496-15.600317 27.707127-47.463513 20.599646-70.833873l-5.059562-17.106139a176.723284 176.723284 0 0 1 18.672194-129.139305 176.060722 176.060722 0 0 1 102.395904-81.314394l16.68451-3.854905c23.310126-5.42096 46.258856-29.333415 50.595623-53.185637 0 0 3.854905-21.382674 3.854904-75.712737-0.240932-54.330062-4.095836-75.833202-4.095836-75.833202z m-537.819428 293.334149c-119.261112 0-216.175824-97.336342-216.175824-217.621412a216.657687 216.657687 0 0 1 216.236057-217.320249c119.200879 0 216.115591 97.276109 216.11559 217.56118-0.240932 120.044139-96.974945 217.320248-216.175823 217.320249z" p-id="10234"></path></svg>
|
||||||
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
@@ -1,22 +0,0 @@
|
|||||||
# replace default config
|
|
||||||
|
|
||||||
# multipass: true
|
|
||||||
# full: true
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
|
|
||||||
# - name
|
|
||||||
#
|
|
||||||
# or:
|
|
||||||
# - name: false
|
|
||||||
# - name: true
|
|
||||||
#
|
|
||||||
# or:
|
|
||||||
# - name:
|
|
||||||
# param1: 1
|
|
||||||
# param2: 2
|
|
||||||
|
|
||||||
- removeAttrs:
|
|
||||||
attrs:
|
|
||||||
- 'fill'
|
|
||||||
- 'fill-rule'
|
|
||||||
@@ -1,39 +1,39 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1"
|
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<defs>
|
<defs>
|
||||||
<filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
|
<filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
|
||||||
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||||
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
|
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
|
||||||
<feMerge>
|
<feMerge>
|
||||||
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
|
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
|
||||||
<feMergeNode in="SourceGraphic"></feMergeNode>
|
<feMergeNode in="SourceGraphic"></feMergeNode>
|
||||||
</feMerge>
|
</feMerge>
|
||||||
</filter>
|
</filter>
|
||||||
<rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
|
<rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
|
||||||
<filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
|
<filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
|
||||||
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||||
<feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
<feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
|
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
|
||||||
</filter>
|
</filter>
|
||||||
</defs>
|
</defs>
|
||||||
<g id="配置面板" width="48" height="40" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
<g id="配置面板" width="48" height="40" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
<g id="setting-copy-2" width="48" height="40" transform="translate(-1190.000000, -136.000000)">
|
<g id="setting-copy-2" width="48" height="40" transform="translate(-1190.000000, -136.000000)">
|
||||||
<g id="Group-8" width="48" height="40" transform="translate(1167.000000, 0.000000)">
|
<g id="Group-8" width="48" height="40" transform="translate(1167.000000, 0.000000)">
|
||||||
<g id="Group-5-Copy-5" filter="url(#filter-1)" transform="translate(25.000000, 137.000000)">
|
<g id="Group-5-Copy-5" filter="url(#filter-1)" transform="translate(25.000000, 137.000000)">
|
||||||
<mask id="mask-3" fill="white">
|
<mask id="mask-3" fill="white">
|
||||||
<use xlink:href="#path-2"></use>
|
<use xlink:href="#path-2"></use>
|
||||||
</mask>
|
</mask>
|
||||||
<g id="Rectangle-18">
|
<g id="Rectangle-18">
|
||||||
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
|
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
|
||||||
<use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
|
<use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
|
||||||
</g>
|
</g>
|
||||||
<rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect>
|
<rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect>
|
||||||
<rect id="Rectangle-18" fill="#303648" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect>
|
<rect id="Rectangle-18" fill="#303648" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.5 KiB |
@@ -1,39 +1,39 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1"
|
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<defs>
|
<defs>
|
||||||
<filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
|
<filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
|
||||||
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||||
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
|
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
|
||||||
<feMerge>
|
<feMerge>
|
||||||
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
|
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
|
||||||
<feMergeNode in="SourceGraphic"></feMergeNode>
|
<feMergeNode in="SourceGraphic"></feMergeNode>
|
||||||
</feMerge>
|
</feMerge>
|
||||||
</filter>
|
</filter>
|
||||||
<rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
|
<rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
|
||||||
<filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
|
<filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
|
||||||
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||||
<feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
<feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
|
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
|
||||||
</filter>
|
</filter>
|
||||||
</defs>
|
</defs>
|
||||||
<g id="配置面板" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
<g id="配置面板" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
<g id="setting-copy-2" transform="translate(-1254.000000, -136.000000)">
|
<g id="setting-copy-2" transform="translate(-1254.000000, -136.000000)">
|
||||||
<g id="Group-8" transform="translate(1167.000000, 0.000000)">
|
<g id="Group-8" transform="translate(1167.000000, 0.000000)">
|
||||||
<g id="Group-5" filter="url(#filter-1)" transform="translate(89.000000, 137.000000)">
|
<g id="Group-5" filter="url(#filter-1)" transform="translate(89.000000, 137.000000)">
|
||||||
<mask id="mask-3" fill="white">
|
<mask id="mask-3" fill="white">
|
||||||
<use xlink:href="#path-2"></use>
|
<use xlink:href="#path-2"></use>
|
||||||
</mask>
|
</mask>
|
||||||
<g id="Rectangle-18">
|
<g id="Rectangle-18">
|
||||||
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
|
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
|
||||||
<use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
|
<use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
|
||||||
</g>
|
</g>
|
||||||
<rect id="Rectangle-18" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect>
|
<rect id="Rectangle-18" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect>
|
||||||
<rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect>
|
<rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.5 KiB |
@@ -1,99 +1,99 @@
|
|||||||
@import './variables.scss';
|
@import './variables.module.scss';
|
||||||
|
|
||||||
@mixin colorBtn($color) {
|
@mixin colorBtn($color) {
|
||||||
background: $color;
|
background: $color;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $color;
|
color: $color;
|
||||||
|
|
||||||
&:before,
|
&:before,
|
||||||
&:after {
|
&:after {
|
||||||
background: $color;
|
background: $color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.blue-btn {
|
.blue-btn {
|
||||||
@include colorBtn($blue)
|
@include colorBtn($blue)
|
||||||
}
|
}
|
||||||
|
|
||||||
.light-blue-btn {
|
.light-blue-btn {
|
||||||
@include colorBtn($light-blue)
|
@include colorBtn($light-blue)
|
||||||
}
|
}
|
||||||
|
|
||||||
.red-btn {
|
.red-btn {
|
||||||
@include colorBtn($red)
|
@include colorBtn($red)
|
||||||
}
|
}
|
||||||
|
|
||||||
.pink-btn {
|
.pink-btn {
|
||||||
@include colorBtn($pink)
|
@include colorBtn($pink)
|
||||||
}
|
}
|
||||||
|
|
||||||
.green-btn {
|
.green-btn {
|
||||||
@include colorBtn($green)
|
@include colorBtn($green)
|
||||||
}
|
}
|
||||||
|
|
||||||
.tiffany-btn {
|
.tiffany-btn {
|
||||||
@include colorBtn($tiffany)
|
@include colorBtn($tiffany)
|
||||||
}
|
}
|
||||||
|
|
||||||
.yellow-btn {
|
.yellow-btn {
|
||||||
@include colorBtn($yellow)
|
@include colorBtn($yellow)
|
||||||
}
|
}
|
||||||
|
|
||||||
.pan-btn {
|
.pan-btn {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding: 14px 36px;
|
padding: 14px 36px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
transition: 600ms ease all;
|
transition: 600ms ease all;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
||||||
&:before,
|
&:before,
|
||||||
&:after {
|
&:after {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
transition: 600ms ease all;
|
transition: 600ms ease all;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:before,
|
&:before,
|
||||||
&:after {
|
&:after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
width: 0;
|
width: 0;
|
||||||
transition: 400ms ease all;
|
transition: 400ms ease all;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
right: inherit;
|
right: inherit;
|
||||||
top: inherit;
|
top: inherit;
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-button {
|
.custom-button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,84 +1,96 @@
|
|||||||
// cover some element-ui styles
|
// cover some element-ui styles
|
||||||
|
|
||||||
.el-breadcrumb__inner,
|
.el-breadcrumb__inner,
|
||||||
.el-breadcrumb__inner a {
|
.el-breadcrumb__inner a {
|
||||||
font-weight: 400 !important;
|
font-weight: 400 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-upload {
|
.el-upload {
|
||||||
input[type="file"] {
|
input[type="file"] {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-upload__input {
|
.el-upload__input {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cell {
|
.cell {
|
||||||
.el-tag {
|
.el-tag {
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.small-padding {
|
.small-padding {
|
||||||
.cell {
|
.cell {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.fixed-width {
|
.fixed-width {
|
||||||
.el-button--mini {
|
.el-button--mini {
|
||||||
padding: 7px 10px;
|
padding: 7px 10px;
|
||||||
width: 60px;
|
width: 60px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-col {
|
.status-col {
|
||||||
.cell {
|
.cell {
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
.el-tag {
|
.el-tag {
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// to fixed https://github.com/ElemeFE/element/issues/2461
|
// to fixed https://github.com/ElemeFE/element/issues/2461
|
||||||
.el-dialog {
|
.el-dialog {
|
||||||
transform: none;
|
transform: none;
|
||||||
left: 0;
|
left: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
// refine element ui upload
|
// refine element ui upload
|
||||||
.upload-container {
|
.upload-container {
|
||||||
.el-upload {
|
.el-upload {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.el-upload-dragger {
|
.el-upload-dragger {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dropdown
|
// dropdown
|
||||||
.el-dropdown-menu {
|
.el-dropdown-menu {
|
||||||
a {
|
a {
|
||||||
display: block
|
display: block
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fix date-picker ui bug in filter-item
|
// fix date-picker ui bug in filter-item
|
||||||
.el-range-editor.el-input__inner {
|
.el-range-editor.el-input__inner {
|
||||||
display: inline-flex !important;
|
display: inline-flex !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
// to fix el-date-picker css style
|
// to fix el-date-picker css style
|
||||||
.el-range-separator {
|
.el-range-separator {
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-menu--collapse
|
||||||
|
> div
|
||||||
|
> .el-submenu
|
||||||
|
> .el-submenu__title
|
||||||
|
.el-submenu__icon-arrow {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dropdown .el-dropdown-link{
|
||||||
|
color: var(--el-color-primary) !important;
|
||||||
|
}
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
/**
|
|
||||||
* I think element-ui's default theme color is too light for long-term use.
|
|
||||||
* So I modified the default color and you can modify it to your liking.
|
|
||||||
**/
|
|
||||||
|
|
||||||
/* theme color */
|
|
||||||
$--color-primary: #1890ff;
|
|
||||||
$--color-success: #13ce66;
|
|
||||||
$--color-warning: #ffba00;
|
|
||||||
$--color-danger: #ff4949;
|
|
||||||
// $--color-info: #1E1E1E;
|
|
||||||
|
|
||||||
$--button-font-weight: 400;
|
|
||||||
|
|
||||||
// $--color-text-regular: #1f2d3d;
|
|
||||||
|
|
||||||
$--border-color-light: #dfe4ed;
|
|
||||||
$--border-color-lighter: #e6ebf5;
|
|
||||||
|
|
||||||
$--table-border:1px solid#dfe6ec;
|
|
||||||
|
|
||||||
/* icon font path, required */
|
|
||||||
$--font-path: '~element-ui/lib/theme-chalk/fonts';
|
|
||||||
|
|
||||||
@import "~element-ui/packages/theme-chalk/src/index";
|
|
||||||
|
|
||||||
// the :export directive is the magic sauce for webpack
|
|
||||||
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
|
|
||||||
:export {
|
|
||||||
theme: $--color-primary;
|
|
||||||
}
|
|
||||||
@@ -1,182 +1,184 @@
|
|||||||
@import './variables.scss';
|
@import './variables.module.scss';
|
||||||
@import './mixin.scss';
|
@import './mixin.scss';
|
||||||
@import './transition.scss';
|
@import './transition.scss';
|
||||||
@import './element-ui.scss';
|
@import './element-ui.scss';
|
||||||
@import './sidebar.scss';
|
@import './sidebar.scss';
|
||||||
@import './btn.scss';
|
@import './btn.scss';
|
||||||
|
@import './ruoyi.scss';
|
||||||
body {
|
|
||||||
height: 100%;
|
body {
|
||||||
-moz-osx-font-smoothing: grayscale;
|
height: 100%;
|
||||||
-webkit-font-smoothing: antialiased;
|
margin: 0;
|
||||||
text-rendering: optimizeLegibility;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
text-rendering: optimizeLegibility;
|
||||||
|
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
|
||||||
label {
|
}
|
||||||
font-weight: 700;
|
|
||||||
}
|
label {
|
||||||
|
font-weight: 700;
|
||||||
html {
|
}
|
||||||
height: 100%;
|
|
||||||
box-sizing: border-box;
|
html {
|
||||||
}
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
#app {
|
}
|
||||||
height: 100%;
|
|
||||||
}
|
#app {
|
||||||
|
height: 100%;
|
||||||
*,
|
}
|
||||||
*:before,
|
|
||||||
*:after {
|
*,
|
||||||
box-sizing: inherit;
|
*:before,
|
||||||
}
|
*:after {
|
||||||
|
box-sizing: inherit;
|
||||||
.no-padding {
|
}
|
||||||
padding: 0px !important;
|
|
||||||
}
|
.no-padding {
|
||||||
|
padding: 0px !important;
|
||||||
.padding-content {
|
}
|
||||||
padding: 4px 0;
|
|
||||||
}
|
.padding-content {
|
||||||
|
padding: 4px 0;
|
||||||
a:focus,
|
}
|
||||||
a:active {
|
|
||||||
outline: none;
|
a:focus,
|
||||||
}
|
a:active {
|
||||||
|
outline: none;
|
||||||
a,
|
}
|
||||||
a:focus,
|
|
||||||
a:hover {
|
a,
|
||||||
cursor: pointer;
|
a:focus,
|
||||||
color: inherit;
|
a:hover {
|
||||||
text-decoration: none;
|
cursor: pointer;
|
||||||
}
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
div:focus {
|
}
|
||||||
outline: none;
|
|
||||||
}
|
div:focus {
|
||||||
|
outline: none;
|
||||||
.fr {
|
}
|
||||||
float: right;
|
|
||||||
}
|
.fr {
|
||||||
|
float: right;
|
||||||
.fl {
|
}
|
||||||
float: left;
|
|
||||||
}
|
.fl {
|
||||||
|
float: left;
|
||||||
.pr-5 {
|
}
|
||||||
padding-right: 5px;
|
|
||||||
}
|
.pr-5 {
|
||||||
|
padding-right: 5px;
|
||||||
.pl-5 {
|
}
|
||||||
padding-left: 5px;
|
|
||||||
}
|
.pl-5 {
|
||||||
|
padding-left: 5px;
|
||||||
.block {
|
}
|
||||||
display: block;
|
|
||||||
}
|
.block {
|
||||||
|
display: block;
|
||||||
.pointer {
|
}
|
||||||
cursor: pointer;
|
|
||||||
}
|
.pointer {
|
||||||
|
cursor: pointer;
|
||||||
.inlineBlock {
|
}
|
||||||
display: block;
|
|
||||||
}
|
.inlineBlock {
|
||||||
|
display: block;
|
||||||
.clearfix {
|
}
|
||||||
&:after {
|
|
||||||
visibility: hidden;
|
.clearfix {
|
||||||
display: block;
|
&:after {
|
||||||
font-size: 0;
|
visibility: hidden;
|
||||||
content: " ";
|
display: block;
|
||||||
clear: both;
|
font-size: 0;
|
||||||
height: 0;
|
content: " ";
|
||||||
}
|
clear: both;
|
||||||
}
|
height: 0;
|
||||||
|
}
|
||||||
aside {
|
}
|
||||||
background: #eef1f6;
|
|
||||||
padding: 8px 24px;
|
aside {
|
||||||
margin-bottom: 20px;
|
background: #eef1f6;
|
||||||
border-radius: 2px;
|
padding: 8px 24px;
|
||||||
display: block;
|
margin-bottom: 20px;
|
||||||
line-height: 32px;
|
border-radius: 2px;
|
||||||
font-size: 16px;
|
display: block;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
line-height: 32px;
|
||||||
color: #2c3e50;
|
font-size: 16px;
|
||||||
-webkit-font-smoothing: antialiased;
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
color: #2c3e50;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
a {
|
-moz-osx-font-smoothing: grayscale;
|
||||||
color: #337ab7;
|
|
||||||
cursor: pointer;
|
a {
|
||||||
|
color: #337ab7;
|
||||||
&:hover {
|
cursor: pointer;
|
||||||
color: rgb(32, 160, 255);
|
|
||||||
}
|
&:hover {
|
||||||
}
|
color: rgb(32, 160, 255);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//main-container全局样式
|
}
|
||||||
.app-container {
|
|
||||||
padding: 20px;
|
//main-container全局样式
|
||||||
}
|
.app-container {
|
||||||
|
padding: 20px;
|
||||||
.components-container {
|
}
|
||||||
margin: 30px 50px;
|
|
||||||
position: relative;
|
.components-container {
|
||||||
}
|
margin: 30px 50px;
|
||||||
|
position: relative;
|
||||||
.pagination-container {
|
}
|
||||||
margin-top: 30px;
|
|
||||||
}
|
.pagination-container {
|
||||||
|
margin-top: 30px;
|
||||||
.text-center {
|
}
|
||||||
text-align: center
|
|
||||||
}
|
.text-center {
|
||||||
|
text-align: center
|
||||||
.sub-navbar {
|
}
|
||||||
height: 50px;
|
|
||||||
line-height: 50px;
|
.sub-navbar {
|
||||||
position: relative;
|
height: 50px;
|
||||||
width: 100%;
|
line-height: 50px;
|
||||||
text-align: right;
|
position: relative;
|
||||||
padding-right: 20px;
|
width: 100%;
|
||||||
transition: 600ms ease position;
|
text-align: right;
|
||||||
background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
|
padding-right: 20px;
|
||||||
|
transition: 600ms ease position;
|
||||||
.subtitle {
|
background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
|
||||||
font-size: 20px;
|
|
||||||
color: #fff;
|
.subtitle {
|
||||||
}
|
font-size: 20px;
|
||||||
|
color: #fff;
|
||||||
&.draft {
|
}
|
||||||
background: #d0d0d0;
|
|
||||||
}
|
&.draft {
|
||||||
|
background: #d0d0d0;
|
||||||
&.deleted {
|
}
|
||||||
background: #d0d0d0;
|
|
||||||
}
|
&.deleted {
|
||||||
}
|
background: #d0d0d0;
|
||||||
|
}
|
||||||
.link-type,
|
}
|
||||||
.link-type:focus {
|
|
||||||
color: #337ab7;
|
.link-type,
|
||||||
cursor: pointer;
|
.link-type:focus {
|
||||||
|
color: #337ab7;
|
||||||
&:hover {
|
cursor: pointer;
|
||||||
color: rgb(32, 160, 255);
|
|
||||||
}
|
&:hover {
|
||||||
}
|
color: rgb(32, 160, 255);
|
||||||
|
}
|
||||||
.filter-container {
|
}
|
||||||
padding-bottom: 10px;
|
|
||||||
|
.filter-container {
|
||||||
.filter-item {
|
padding-bottom: 10px;
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
.filter-item {
|
||||||
margin-bottom: 10px;
|
display: inline-block;
|
||||||
}
|
vertical-align: middle;
|
||||||
}
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,66 +1,66 @@
|
|||||||
@mixin clearfix {
|
@mixin clearfix {
|
||||||
&:after {
|
&:after {
|
||||||
content: "";
|
content: "";
|
||||||
display: table;
|
display: table;
|
||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin scrollBar {
|
@mixin scrollBar {
|
||||||
&::-webkit-scrollbar-track-piece {
|
&::-webkit-scrollbar-track-piece {
|
||||||
background: #d3dce6;
|
background: #d3dce6;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
background: #99a9bf;
|
background: #99a9bf;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin relative {
|
@mixin relative {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin pct($pct) {
|
@mixin pct($pct) {
|
||||||
width: #{$pct};
|
width: #{$pct};
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin triangle($width, $height, $color, $direction) {
|
@mixin triangle($width, $height, $color, $direction) {
|
||||||
$width: $width/2;
|
$width: $width/2;
|
||||||
$color-border-style: $height solid $color;
|
$color-border-style: $height solid $color;
|
||||||
$transparent-border-style: $width solid transparent;
|
$transparent-border-style: $width solid transparent;
|
||||||
height: 0;
|
height: 0;
|
||||||
width: 0;
|
width: 0;
|
||||||
|
|
||||||
@if $direction==up {
|
@if $direction==up {
|
||||||
border-bottom: $color-border-style;
|
border-bottom: $color-border-style;
|
||||||
border-left: $transparent-border-style;
|
border-left: $transparent-border-style;
|
||||||
border-right: $transparent-border-style;
|
border-right: $transparent-border-style;
|
||||||
}
|
}
|
||||||
|
|
||||||
@else if $direction==right {
|
@else if $direction==right {
|
||||||
border-left: $color-border-style;
|
border-left: $color-border-style;
|
||||||
border-top: $transparent-border-style;
|
border-top: $transparent-border-style;
|
||||||
border-bottom: $transparent-border-style;
|
border-bottom: $transparent-border-style;
|
||||||
}
|
}
|
||||||
|
|
||||||
@else if $direction==down {
|
@else if $direction==down {
|
||||||
border-top: $color-border-style;
|
border-top: $color-border-style;
|
||||||
border-left: $transparent-border-style;
|
border-left: $transparent-border-style;
|
||||||
border-right: $transparent-border-style;
|
border-right: $transparent-border-style;
|
||||||
}
|
}
|
||||||
|
|
||||||
@else if $direction==left {
|
@else if $direction==left {
|
||||||
border-right: $color-border-style;
|
border-right: $color-border-style;
|
||||||
border-top: $transparent-border-style;
|
border-top: $transparent-border-style;
|
||||||
border-bottom: $transparent-border-style;
|
border-bottom: $transparent-border-style;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,291 +1,281 @@
|
|||||||
/**
|
/**
|
||||||
* 通用css样式布局处理
|
* 通用css样式布局处理
|
||||||
* Copyright (c) 2019 ruoyi
|
* Copyright (c) 2019 ruoyi
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** 基础通用 **/
|
/** 基础通用 **/
|
||||||
.pt5 {
|
.pt5 {
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
}
|
}
|
||||||
|
.pr5 {
|
||||||
.pr5 {
|
padding-right: 5px;
|
||||||
padding-right: 5px;
|
}
|
||||||
}
|
.pb5 {
|
||||||
|
padding-bottom: 5px;
|
||||||
.pb5 {
|
}
|
||||||
padding-bottom: 5px;
|
.mt5 {
|
||||||
}
|
margin-top: 5px;
|
||||||
|
}
|
||||||
.mt5 {
|
.mr5 {
|
||||||
margin-top: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
.mb5 {
|
||||||
.mr5 {
|
margin-bottom: 5px;
|
||||||
margin-right: 5px;
|
}
|
||||||
}
|
.mb8 {
|
||||||
|
margin-bottom: 8px;
|
||||||
.mb5 {
|
}
|
||||||
margin-bottom: 5px;
|
.ml5 {
|
||||||
}
|
margin-left: 5px;
|
||||||
|
}
|
||||||
.mb8 {
|
.mt10 {
|
||||||
margin-bottom: 8px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
.mr10 {
|
||||||
.ml5 {
|
margin-right: 10px;
|
||||||
margin-left: 5px;
|
}
|
||||||
}
|
.mb10 {
|
||||||
|
margin-bottom: 10px;
|
||||||
.mt10 {
|
}
|
||||||
margin-top: 10px;
|
.ml10 {
|
||||||
}
|
margin-left: 10px;
|
||||||
|
}
|
||||||
.mr10 {
|
.mt20 {
|
||||||
margin-right: 10px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
.mr20 {
|
||||||
.mb10 {
|
margin-right: 20px;
|
||||||
margin-bottom: 10px;
|
}
|
||||||
}
|
.mb20 {
|
||||||
.ml10 {
|
margin-bottom: 20px;
|
||||||
margin-left: 10px;
|
}
|
||||||
}
|
.ml20 {
|
||||||
|
margin-left: 20px;
|
||||||
.mt20 {
|
}
|
||||||
margin-top: 20px;
|
|
||||||
}
|
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-family: inherit;
|
||||||
.mr20 {
|
font-weight: 500;
|
||||||
margin-right: 20px;
|
line-height: 1.1;
|
||||||
}
|
color: inherit;
|
||||||
|
}
|
||||||
.mb20 {
|
|
||||||
margin-bottom: 20px;
|
.el-form .el-form-item__label {
|
||||||
}
|
font-weight: 700;
|
||||||
.ml20 {
|
}
|
||||||
margin-left: 20px;
|
.el-dialog:not(.is-fullscreen) {
|
||||||
}
|
margin-top: 6vh !important;
|
||||||
|
}
|
||||||
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
|
|
||||||
font-family: inherit;
|
.el-dialog.scrollbar .el-dialog__body {
|
||||||
font-weight: 500;
|
overflow: auto;
|
||||||
line-height: 1.1;
|
overflow-x: hidden;
|
||||||
color: inherit;
|
max-height: 70vh;
|
||||||
}
|
padding: 10px 20px 0;
|
||||||
|
}
|
||||||
.el-message-box__status + .el-message-box__message{
|
|
||||||
word-break: break-word;
|
.el-table {
|
||||||
}
|
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
|
||||||
|
th {
|
||||||
.el-dialog:not(.is-fullscreen) {
|
word-break: break-word;
|
||||||
margin-top: 6vh !important;
|
background-color: #f8f8f9 !important;
|
||||||
}
|
color: #515a6e;
|
||||||
|
height: 40px !important;
|
||||||
.el-dialog__wrapper.scrollbar .el-dialog .el-dialog__body {
|
font-size: 13px;
|
||||||
overflow: auto;
|
}
|
||||||
overflow-x: hidden;
|
}
|
||||||
max-height: 70vh;
|
.el-table__body-wrapper {
|
||||||
padding: 10px 20px 0;
|
.el-button [class*="el-icon-"] + span {
|
||||||
}
|
margin-left: 1px;
|
||||||
|
}
|
||||||
.el-table {
|
}
|
||||||
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
|
}
|
||||||
th {
|
|
||||||
word-break: break-word;
|
/** 表单布局 **/
|
||||||
background-color: #f8f8f9;
|
.form-header {
|
||||||
color: #515a6e;
|
font-size:15px;
|
||||||
height: 40px;
|
color:#6379bb;
|
||||||
font-size: 13px;
|
border-bottom:1px solid #ddd;
|
||||||
}
|
margin:8px 10px 25px 10px;
|
||||||
}
|
padding-bottom:5px
|
||||||
|
}
|
||||||
.el-table__body-wrapper {
|
|
||||||
.el-button [class*="el-icon-"] + span {
|
/** 表格布局 **/
|
||||||
margin-left: 1px;
|
.pagination-container {
|
||||||
}
|
position: relative;
|
||||||
}
|
height: 25px;
|
||||||
}
|
margin-bottom: 10px;
|
||||||
|
margin-top: 15px;
|
||||||
/** 表单布局 **/
|
padding: 10px 20px !important;
|
||||||
.form-header {
|
}
|
||||||
font-size: 15px;
|
|
||||||
color: #6379bb;
|
.el-dialog .pagination-container {
|
||||||
border-bottom: 1px solid #ddd;
|
position: static !important;
|
||||||
margin: 8px 10px 25px 10px;
|
}
|
||||||
padding-bottom: 5px
|
|
||||||
}
|
/* tree border */
|
||||||
|
.tree-border {
|
||||||
/** 表格布局 **/
|
margin-top: 5px;
|
||||||
.pagination-container {
|
border: 1px solid #e5e6e7;
|
||||||
position: relative;
|
background: #FFFFFF none;
|
||||||
height: 25px;
|
border-radius:4px;
|
||||||
margin-bottom: 10px;
|
width: 100%;
|
||||||
margin-top: 15px;
|
}
|
||||||
padding: 10px 20px !important;
|
|
||||||
}
|
.pagination-container .el-pagination {
|
||||||
|
right: 0;
|
||||||
/* tree border */
|
position: absolute;
|
||||||
.tree-border {
|
}
|
||||||
margin-top: 5px;
|
|
||||||
border: 1px solid #e5e6e7;
|
@media ( max-width : 768px) {
|
||||||
background: #FFFFFF none;
|
.pagination-container .el-pagination > .el-pagination__jump {
|
||||||
border-radius: 4px;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
.pagination-container .el-pagination > .el-pagination__sizes {
|
||||||
.pagination-container .el-pagination {
|
display: none !important;
|
||||||
right: 0;
|
}
|
||||||
position: absolute;
|
}
|
||||||
}
|
|
||||||
|
.el-table .fixed-width .el-button--small {
|
||||||
@media (max-width: 768px) {
|
padding-left: 0;
|
||||||
.pagination-container .el-pagination > .el-pagination__jump {
|
padding-right: 0;
|
||||||
display: none !important;
|
width: inherit;
|
||||||
}
|
}
|
||||||
.pagination-container .el-pagination > .el-pagination__sizes {
|
|
||||||
display: none !important;
|
/** 表格更多操作下拉样式 */
|
||||||
}
|
.el-table .el-dropdown-link {
|
||||||
}
|
cursor: pointer;
|
||||||
|
color: #409EFF;
|
||||||
.el-table .fixed-width .el-button--mini {
|
margin-left: 10px;
|
||||||
padding-left: 0;
|
}
|
||||||
padding-right: 0;
|
|
||||||
width: inherit;
|
.el-table .el-dropdown, .el-icon-arrow-down {
|
||||||
}
|
font-size: 12px;
|
||||||
|
}
|
||||||
/** 表格更多操作下拉样式 */
|
|
||||||
.el-table .el-dropdown-link,.el-table .el-dropdown-selfdefine {
|
.el-tree-node__content > .el-checkbox {
|
||||||
cursor: pointer;
|
margin-right: 8px;
|
||||||
margin-left: 5px;
|
}
|
||||||
}
|
|
||||||
|
.list-group-striped > .list-group-item {
|
||||||
.el-table .el-dropdown, .el-icon-arrow-down {
|
border-left: 0;
|
||||||
font-size: 12px;
|
border-right: 0;
|
||||||
}
|
border-radius: 0;
|
||||||
|
padding-left: 0;
|
||||||
.el-tree-node__content > .el-checkbox {
|
padding-right: 0;
|
||||||
margin-right: 8px;
|
}
|
||||||
}
|
|
||||||
|
.list-group {
|
||||||
.list-group-striped > .list-group-item {
|
padding-left: 0px;
|
||||||
border-left: 0;
|
list-style: none;
|
||||||
border-right: 0;
|
}
|
||||||
border-radius: 0;
|
|
||||||
padding-left: 0;
|
.list-group-item {
|
||||||
padding-right: 0;
|
border-bottom: 1px solid #e7eaec;
|
||||||
}
|
border-top: 1px solid #e7eaec;
|
||||||
|
margin-bottom: -1px;
|
||||||
.list-group {
|
padding: 11px 0px;
|
||||||
padding-left: 0px;
|
font-size: 13px;
|
||||||
list-style: none;
|
}
|
||||||
}
|
|
||||||
|
.pull-right {
|
||||||
.list-group-item {
|
float: right !important;
|
||||||
border-bottom: 1px solid #e7eaec;
|
}
|
||||||
border-top: 1px solid #e7eaec;
|
|
||||||
margin-bottom: -1px;
|
.el-card__header {
|
||||||
padding: 11px 0px;
|
padding: 14px 15px 7px !important;
|
||||||
font-size: 13px;
|
min-height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pull-right {
|
.el-card__body {
|
||||||
float: right !important;
|
padding: 15px 20px 20px 20px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-card__header {
|
.card-box {
|
||||||
padding: 14px 15px 7px;
|
padding-right: 15px;
|
||||||
min-height: 40px;
|
padding-left: 15px;
|
||||||
}
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
.el-card__body {
|
|
||||||
padding: 15px 20px 20px 20px;
|
/* button color */
|
||||||
}
|
.el-button--cyan.is-active,
|
||||||
|
.el-button--cyan:active {
|
||||||
.card-box {
|
background: #20B2AA;
|
||||||
padding-right: 15px;
|
border-color: #20B2AA;
|
||||||
padding-left: 15px;
|
color: #FFFFFF;
|
||||||
margin-bottom: 10px;
|
}
|
||||||
}
|
|
||||||
|
.el-button--cyan:focus,
|
||||||
/* button color */
|
.el-button--cyan:hover {
|
||||||
.el-button--cyan.is-active,
|
background: #48D1CC;
|
||||||
.el-button--cyan:active {
|
border-color: #48D1CC;
|
||||||
background: #20B2AA;
|
color: #FFFFFF;
|
||||||
border-color: #20B2AA;
|
}
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
.el-button--cyan {
|
||||||
|
background-color: #20B2AA;
|
||||||
.el-button--cyan:focus,
|
border-color: #20B2AA;
|
||||||
.el-button--cyan:hover {
|
color: #FFFFFF;
|
||||||
background: #48D1CC;
|
}
|
||||||
border-color: #48D1CC;
|
|
||||||
color: #FFFFFF;
|
/* text color */
|
||||||
}
|
.text-navy {
|
||||||
|
color: #1ab394;
|
||||||
.el-button--cyan {
|
}
|
||||||
background-color: #20B2AA;
|
|
||||||
border-color: #20B2AA;
|
.text-primary {
|
||||||
color: #FFFFFF;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* text color */
|
.text-success {
|
||||||
.text-navy {
|
color: #1c84c6;
|
||||||
color: #1ab394;
|
}
|
||||||
}
|
|
||||||
|
.text-info {
|
||||||
.text-primary {
|
color: #23c6c8;
|
||||||
color: inherit;
|
}
|
||||||
}
|
|
||||||
|
.text-warning {
|
||||||
.text-success {
|
color: #f8ac59;
|
||||||
color: #1c84c6;
|
}
|
||||||
}
|
|
||||||
|
.text-danger {
|
||||||
.text-info {
|
color: #ed5565;
|
||||||
color: #23c6c8;
|
}
|
||||||
}
|
|
||||||
|
.text-muted {
|
||||||
.text-warning {
|
color: #888888;
|
||||||
color: #f8ac59;
|
}
|
||||||
}
|
|
||||||
|
/* image */
|
||||||
.text-danger {
|
.img-circle {
|
||||||
color: #ed5565;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-muted {
|
.img-lg {
|
||||||
color: #888888;
|
width: 120px;
|
||||||
}
|
height: 120px;
|
||||||
|
}
|
||||||
/* image */
|
|
||||||
.img-circle {
|
.avatar-upload-preview {
|
||||||
border-radius: 50%;
|
position: absolute;
|
||||||
}
|
top: 50%;
|
||||||
|
transform: translate(50%, -50%);
|
||||||
.img-lg {
|
width: 200px;
|
||||||
width: 120px;
|
height: 200px;
|
||||||
height: 120px;
|
border-radius: 50%;
|
||||||
}
|
box-shadow: 0 0 4px #ccc;
|
||||||
|
overflow: hidden;
|
||||||
.avatar-upload-preview {
|
}
|
||||||
position: relative;
|
|
||||||
top: 50%;
|
/* 拖拽列样式 */
|
||||||
left: 50%;
|
.sortable-ghost{
|
||||||
transform: translate(-50%, -50%);
|
opacity: .8;
|
||||||
width: 200px;
|
color: #fff!important;
|
||||||
height: 200px;
|
background: #42b983!important;
|
||||||
border-radius: 50%;
|
}
|
||||||
box-shadow: 0 0 4px #ccc;
|
|
||||||
overflow: hidden;
|
/* 表格右侧工具栏样式 */
|
||||||
}
|
.top-right-btn {
|
||||||
|
margin-left: auto;
|
||||||
/* 拖拽列样式 */
|
}
|
||||||
.sortable-ghost {
|
|
||||||
opacity: .8;
|
|
||||||
color: #fff !important;
|
|
||||||
background: #42b983 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-right-btn {
|
|
||||||
position: relative;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,227 +1,238 @@
|
|||||||
#app {
|
#app {
|
||||||
|
|
||||||
.main-container {
|
.main-container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
transition: margin-left .28s;
|
transition: margin-left .28s;
|
||||||
margin-left: $base-sidebar-width;
|
margin-left: $base-sidebar-width;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebarHide {
|
.sidebarHide {
|
||||||
margin-left: 0!important;
|
margin-left: 0!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-container {
|
.sidebar-container {
|
||||||
-webkit-transition: width .28s;
|
-webkit-transition: width .28s;
|
||||||
transition: width 0.28s;
|
transition: width 0.28s;
|
||||||
width: $base-sidebar-width !important;
|
width: $base-sidebar-width !important;
|
||||||
background-color: $base-menu-background;
|
background-color: $base-menu-background;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
font-size: 0px;
|
font-size: 0px;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 1001;
|
z-index: 1001;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
-webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
|
-webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
|
||||||
box-shadow: 2px 0 6px rgba(0,21,41,.35);
|
box-shadow: 2px 0 6px rgba(0,21,41,.35);
|
||||||
|
|
||||||
// reset element-ui css
|
// reset element-ui css
|
||||||
.horizontal-collapse-transition {
|
.horizontal-collapse-transition {
|
||||||
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
|
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollbar-wrapper {
|
.scrollbar-wrapper {
|
||||||
overflow-x: hidden !important;
|
overflow-x: hidden !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-scrollbar__bar.is-vertical {
|
.el-scrollbar__bar.is-vertical {
|
||||||
right: 0px;
|
right: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-scrollbar {
|
.el-scrollbar {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.has-logo {
|
&.has-logo {
|
||||||
.el-scrollbar {
|
.el-scrollbar {
|
||||||
height: calc(100% - 50px);
|
height: calc(100% - 50px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-horizontal {
|
.is-horizontal {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.svg-icon {
|
.svg-icon {
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-menu {
|
.el-menu {
|
||||||
border: none;
|
border: none;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-menu-item, .el-submenu__title {
|
.el-menu-item, .menu-title {
|
||||||
overflow: hidden !important;
|
overflow: hidden !important;
|
||||||
text-overflow: ellipsis !important;
|
text-overflow: ellipsis !important;
|
||||||
white-space: nowrap !important;
|
white-space: nowrap !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
// menu hover
|
.el-menu-item .el-menu-tooltip__trigger {
|
||||||
.submenu-title-noDropdown,
|
display: inline-block !important;
|
||||||
.el-submenu__title {
|
}
|
||||||
&:hover {
|
|
||||||
background-color: rgba(0, 0, 0, 0.06) !important;
|
// menu hover
|
||||||
}
|
.sub-menu-title-noDropdown,
|
||||||
}
|
.el-sub-menu__title {
|
||||||
|
&:hover {
|
||||||
& .theme-dark .is-active > .el-submenu__title {
|
background-color: rgba(0, 0, 0, 0.06) !important;
|
||||||
color: $base-menu-color-active !important;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& .nest-menu .el-submenu>.el-submenu__title,
|
& .theme-dark .is-active > .el-sub-menu__title {
|
||||||
& .el-submenu .el-menu-item {
|
color: $base-menu-color-active !important;
|
||||||
min-width: $base-sidebar-width !important;
|
}
|
||||||
|
|
||||||
&:hover {
|
& .nest-menu .el-sub-menu>.el-sub-menu__title,
|
||||||
background-color: rgba(0, 0, 0, 0.06) !important;
|
& .el-sub-menu .el-menu-item {
|
||||||
}
|
min-width: $base-sidebar-width !important;
|
||||||
}
|
|
||||||
|
&:hover {
|
||||||
& .theme-dark .nest-menu .el-submenu>.el-submenu__title,
|
background-color: rgba(0, 0, 0, 0.06) !important;
|
||||||
& .theme-dark .el-submenu .el-menu-item {
|
}
|
||||||
background-color: $base-sub-menu-background !important;
|
}
|
||||||
|
|
||||||
&:hover {
|
& .theme-dark .nest-menu .el-sub-menu>.el-sub-menu__title,
|
||||||
background-color: $base-sub-menu-hover !important;
|
& .theme-dark .el-sub-menu .el-menu-item {
|
||||||
}
|
background-color: $base-sub-menu-background !important;
|
||||||
}
|
|
||||||
}
|
&:hover {
|
||||||
|
background-color: $base-sub-menu-hover !important;
|
||||||
.hideSidebar {
|
}
|
||||||
.sidebar-container {
|
}
|
||||||
width: 54px !important;
|
}
|
||||||
}
|
|
||||||
|
.hideSidebar {
|
||||||
.main-container {
|
.sidebar-container {
|
||||||
margin-left: 54px;
|
width: 54px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.submenu-title-noDropdown {
|
.main-container {
|
||||||
padding: 0 !important;
|
margin-left: 54px;
|
||||||
position: relative;
|
}
|
||||||
|
|
||||||
.el-tooltip {
|
.sub-menu-title-noDropdown {
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
|
position: relative;
|
||||||
.svg-icon {
|
|
||||||
margin-left: 20px;
|
.el-tooltip {
|
||||||
}
|
padding: 0 !important;
|
||||||
}
|
|
||||||
}
|
.svg-icon {
|
||||||
|
margin-left: 20px;
|
||||||
.el-submenu {
|
}
|
||||||
overflow: hidden;
|
}
|
||||||
|
}
|
||||||
&>.el-submenu__title {
|
|
||||||
padding: 0 !important;
|
.el-sub-menu {
|
||||||
|
overflow: hidden;
|
||||||
.svg-icon {
|
|
||||||
margin-left: 20px;
|
&>.el-sub-menu__title {
|
||||||
}
|
padding: 0 !important;
|
||||||
|
|
||||||
}
|
.svg-icon {
|
||||||
}
|
margin-left: 20px;
|
||||||
|
}
|
||||||
.el-menu--collapse {
|
|
||||||
.el-submenu {
|
}
|
||||||
&>.el-submenu__title {
|
}
|
||||||
&>span {
|
|
||||||
height: 0;
|
.el-menu--collapse {
|
||||||
width: 0;
|
.el-sub-menu {
|
||||||
overflow: hidden;
|
&>.el-sub-menu__title {
|
||||||
visibility: hidden;
|
&>span {
|
||||||
display: inline-block;
|
height: 0;
|
||||||
}
|
width: 0;
|
||||||
}
|
overflow: hidden;
|
||||||
}
|
visibility: hidden;
|
||||||
}
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
&>i {
|
||||||
.el-menu--collapse .el-menu .el-submenu {
|
height: 0;
|
||||||
min-width: $base-sidebar-width !important;
|
width: 0;
|
||||||
}
|
overflow: hidden;
|
||||||
|
visibility: hidden;
|
||||||
// mobile responsive
|
display: inline-block;
|
||||||
.mobile {
|
}
|
||||||
.main-container {
|
}
|
||||||
margin-left: 0px;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.sidebar-container {
|
|
||||||
transition: transform .28s;
|
.el-menu--collapse .el-menu .el-sub-menu {
|
||||||
width: $base-sidebar-width !important;
|
min-width: $base-sidebar-width !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.hideSidebar {
|
// mobile responsive
|
||||||
.sidebar-container {
|
.mobile {
|
||||||
pointer-events: none;
|
.main-container {
|
||||||
transition-duration: 0.3s;
|
margin-left: 0px;
|
||||||
transform: translate3d(-$base-sidebar-width, 0, 0);
|
}
|
||||||
}
|
|
||||||
}
|
.sidebar-container {
|
||||||
}
|
transition: transform .28s;
|
||||||
|
width: $base-sidebar-width !important;
|
||||||
.withoutAnimation {
|
}
|
||||||
|
|
||||||
.main-container,
|
&.hideSidebar {
|
||||||
.sidebar-container {
|
.sidebar-container {
|
||||||
transition: none;
|
pointer-events: none;
|
||||||
}
|
transition-duration: 0.3s;
|
||||||
}
|
transform: translate3d(-$base-sidebar-width, 0, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// when menu collapsed
|
}
|
||||||
.el-menu--vertical {
|
|
||||||
&>.el-menu {
|
.withoutAnimation {
|
||||||
.svg-icon {
|
|
||||||
margin-right: 16px;
|
.main-container,
|
||||||
}
|
.sidebar-container {
|
||||||
}
|
transition: none;
|
||||||
|
}
|
||||||
.nest-menu .el-submenu>.el-submenu__title,
|
}
|
||||||
.el-menu-item {
|
}
|
||||||
&:hover {
|
|
||||||
// you can use $subMenuHover
|
// when menu collapsed
|
||||||
background-color: rgba(0, 0, 0, 0.06) !important;
|
.el-menu--vertical {
|
||||||
}
|
&>.el-menu {
|
||||||
}
|
.svg-icon {
|
||||||
|
margin-right: 16px;
|
||||||
// the scroll bar appears when the subMenu is too long
|
}
|
||||||
>.el-menu--popup {
|
}
|
||||||
max-height: 100vh;
|
|
||||||
overflow-y: auto;
|
.nest-menu .el-sub-menu>.el-sub-menu__title,
|
||||||
|
.el-menu-item {
|
||||||
&::-webkit-scrollbar-track-piece {
|
&:hover {
|
||||||
background: #d3dce6;
|
// you can use $sub-menuHover
|
||||||
}
|
background-color: rgba(0, 0, 0, 0.06) !important;
|
||||||
|
}
|
||||||
&::-webkit-scrollbar {
|
}
|
||||||
width: 6px;
|
|
||||||
}
|
// the scroll bar appears when the sub-menu is too long
|
||||||
|
>.el-menu--popup {
|
||||||
&::-webkit-scrollbar-thumb {
|
max-height: 100vh;
|
||||||
background: #99a9bf;
|
overflow-y: auto;
|
||||||
border-radius: 20px;
|
|
||||||
}
|
&::-webkit-scrollbar-track-piece {
|
||||||
}
|
background: #d3dce6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: #99a9bf;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,49 +1,49 @@
|
|||||||
// global transition css
|
// global transition css
|
||||||
|
|
||||||
/* fade */
|
/* fade */
|
||||||
.fade-enter-active,
|
.fade-enter-active,
|
||||||
.fade-leave-active {
|
.fade-leave-active {
|
||||||
transition: opacity 0.28s;
|
transition: opacity 0.28s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-enter,
|
.fade-enter,
|
||||||
.fade-leave-active {
|
.fade-leave-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fade-transform */
|
/* fade-transform */
|
||||||
.fade-transform--move,
|
.fade-transform--move,
|
||||||
.fade-transform-leave-active,
|
.fade-transform-leave-active,
|
||||||
.fade-transform-enter-active {
|
.fade-transform-enter-active {
|
||||||
transition: all .5s;
|
transition: all .5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-transform-enter {
|
.fade-transform-enter {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(-30px);
|
transform: translateX(-30px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-transform-leave-to {
|
.fade-transform-leave-to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(30px);
|
transform: translateX(30px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* breadcrumb transition */
|
/* breadcrumb transition */
|
||||||
.breadcrumb-enter-active,
|
.breadcrumb-enter-active,
|
||||||
.breadcrumb-leave-active {
|
.breadcrumb-leave-active {
|
||||||
transition: all .5s;
|
transition: all .5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb-enter,
|
.breadcrumb-enter,
|
||||||
.breadcrumb-leave-active {
|
.breadcrumb-leave-active {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(20px);
|
transform: translateX(20px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb-move {
|
.breadcrumb-move {
|
||||||
transition: all .5s;
|
transition: all .5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb-leave-active {
|
.breadcrumb-leave-active {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +1,65 @@
|
|||||||
// base color
|
// base color
|
||||||
$blue:#324157;
|
$blue: #324157;
|
||||||
$light-blue:#3A71A8;
|
$light-blue: #3A71A8;
|
||||||
$red:#C03639;
|
$red: #C03639;
|
||||||
$pink: #E65D6E;
|
$pink: #E65D6E;
|
||||||
$green: #30B08F;
|
$green: #30B08F;
|
||||||
$tiffany: #4AB7BD;
|
$tiffany: #4AB7BD;
|
||||||
$yellow:#FEC171;
|
$yellow: #FEC171;
|
||||||
$panGreen: #30B08F;
|
$panGreen: #30B08F;
|
||||||
|
|
||||||
// 默认菜单主题风格
|
// 默认菜单主题风格
|
||||||
$base-menu-color:#bfcbd9;
|
$base-menu-color: #bfcbd9;
|
||||||
$base-menu-color-active:#f4f4f5;
|
$base-menu-color-active: #f4f4f5;
|
||||||
$base-menu-background:#304156;
|
$base-menu-background: #304156;
|
||||||
$base-logo-title-color: #ffffff;
|
$base-logo-title-color: #ffffff;
|
||||||
|
|
||||||
$base-menu-light-color:rgba(0,0,0,.70);
|
$base-menu-light-color: rgba(0, 0, 0, 0.7);
|
||||||
$base-menu-light-background:#ffffff;
|
$base-menu-light-background: #ffffff;
|
||||||
$base-logo-light-title-color: #001529;
|
$base-logo-light-title-color: #001529;
|
||||||
|
|
||||||
$base-sub-menu-background:#1f2d3d;
|
$base-sub-menu-background: #1f2d3d;
|
||||||
$base-sub-menu-hover:#001528;
|
$base-sub-menu-hover: #001528;
|
||||||
|
|
||||||
// 自定义暗色菜单风格
|
// 自定义暗色菜单风格
|
||||||
/**
|
/**
|
||||||
$base-menu-color:hsla(0,0%,100%,.65);
|
$base-menu-color:hsla(0,0%,100%,.65);
|
||||||
$base-menu-color-active:#fff;
|
$base-menu-color-active:#fff;
|
||||||
$base-menu-background:#001529;
|
$base-menu-background:#001529;
|
||||||
$base-logo-title-color: #ffffff;
|
$base-logo-title-color: #ffffff;
|
||||||
|
|
||||||
$base-menu-light-color:rgba(0,0,0,.70);
|
$base-menu-light-color:rgba(0,0,0,.70);
|
||||||
$base-menu-light-background:#ffffff;
|
$base-menu-light-background:#ffffff;
|
||||||
$base-logo-light-title-color: #001529;
|
$base-logo-light-title-color: #001529;
|
||||||
|
|
||||||
$base-sub-menu-background:#000c17;
|
$base-sub-menu-background:#000c17;
|
||||||
$base-sub-menu-hover:#001528;
|
$base-sub-menu-hover:#001528;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$base-sidebar-width: 200px;
|
$--color-primary: #409EFF;
|
||||||
|
$--color-success: #67C23A;
|
||||||
// the :export directive is the magic sauce for webpack
|
$--color-warning: #E6A23C;
|
||||||
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
|
$--color-danger: #F56C6C;
|
||||||
:export {
|
$--color-info: #909399;
|
||||||
menuColor: $base-menu-color;
|
|
||||||
menuLightColor: $base-menu-light-color;
|
$base-sidebar-width: 200px;
|
||||||
menuColorActive: $base-menu-color-active;
|
|
||||||
menuBackground: $base-menu-background;
|
// the :export directive is the magic sauce for webpack
|
||||||
menuLightBackground: $base-menu-light-background;
|
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
|
||||||
subMenuBackground: $base-sub-menu-background;
|
:export {
|
||||||
subMenuHover: $base-sub-menu-hover;
|
menuColor: $base-menu-color;
|
||||||
sideBarWidth: $base-sidebar-width;
|
menuLightColor: $base-menu-light-color;
|
||||||
logoTitleColor: $base-logo-title-color;
|
menuColorActive: $base-menu-color-active;
|
||||||
logoLightTitleColor: $base-logo-light-title-color
|
menuBackground: $base-menu-background;
|
||||||
}
|
menuLightBackground: $base-menu-light-background;
|
||||||
|
subMenuBackground: $base-sub-menu-background;
|
||||||
|
subMenuHover: $base-sub-menu-hover;
|
||||||
|
sideBarWidth: $base-sidebar-width;
|
||||||
|
logoTitleColor: $base-logo-title-color;
|
||||||
|
logoLightTitleColor: $base-logo-light-title-color;
|
||||||
|
primaryColor: $--color-primary;
|
||||||
|
successColor: $--color-success;
|
||||||
|
dangerColor: $--color-danger;
|
||||||
|
infoColor: $--color-info;
|
||||||
|
warningColor: $--color-warning;
|
||||||
|
}
|
||||||
@@ -1,74 +1,66 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-breadcrumb class="app-breadcrumb" separator="/">
|
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||||
<transition-group name="breadcrumb">
|
<transition-group name="breadcrumb">
|
||||||
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
|
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
|
||||||
<span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ item.meta.title }}</span>
|
<span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ item.meta.title }}</span>
|
||||||
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
|
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
|
||||||
</el-breadcrumb-item>
|
</el-breadcrumb-item>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
</el-breadcrumb>
|
</el-breadcrumb>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
const route = useRoute();
|
||||||
data() {
|
const router = useRouter();
|
||||||
return {
|
const levelList = ref([])
|
||||||
levelList: null
|
|
||||||
}
|
function getBreadcrumb() {
|
||||||
},
|
// only show routes with meta.title
|
||||||
watch: {
|
let matched = route.matched.filter(item => item.meta && item.meta.title);
|
||||||
$route(route) {
|
const first = matched[0]
|
||||||
// if you go to the redirect page, do not update the breadcrumbs
|
// 判断是否为首页
|
||||||
if (route.path.startsWith('/redirect/')) {
|
if (!isDashboard(first)) {
|
||||||
return
|
matched = [{ path: '/index', meta: { title: '首页' } }].concat(matched)
|
||||||
}
|
}
|
||||||
this.getBreadcrumb()
|
|
||||||
}
|
levelList.value = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
||||||
},
|
}
|
||||||
created() {
|
function isDashboard(route) {
|
||||||
this.getBreadcrumb()
|
const name = route && route.name
|
||||||
},
|
if (!name) {
|
||||||
methods: {
|
return false
|
||||||
getBreadcrumb() {
|
}
|
||||||
// only show routes with meta.title
|
return name.trim() === 'Index'
|
||||||
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
|
}
|
||||||
const first = matched[0]
|
function handleLink(item) {
|
||||||
|
const { redirect, path } = item
|
||||||
if (!this.isDashboard(first)) {
|
if (redirect) {
|
||||||
matched = [{ path: '/index', meta: { title: '首页' }}].concat(matched)
|
router.push(redirect)
|
||||||
}
|
return
|
||||||
|
}
|
||||||
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
router.push(path)
|
||||||
},
|
}
|
||||||
isDashboard(route) {
|
|
||||||
const name = route && route.name
|
watchEffect(() => {
|
||||||
if (!name) {
|
// if you go to the redirect page, do not update the breadcrumbs
|
||||||
return false
|
if (route.path.startsWith('/redirect/')) {
|
||||||
}
|
return
|
||||||
return name.trim() === 'Index'
|
}
|
||||||
},
|
getBreadcrumb()
|
||||||
handleLink(item) {
|
})
|
||||||
const { redirect, path } = item
|
getBreadcrumb();
|
||||||
if (redirect) {
|
</script>
|
||||||
this.$router.push(redirect)
|
|
||||||
return
|
<style lang='scss' scoped>
|
||||||
}
|
.app-breadcrumb.el-breadcrumb {
|
||||||
this.$router.push(path)
|
display: inline-block;
|
||||||
}
|
font-size: 14px;
|
||||||
}
|
line-height: 50px;
|
||||||
}
|
margin-left: 8px;
|
||||||
</script>
|
|
||||||
|
.no-redirect {
|
||||||
<style lang="scss" scoped>
|
color: #97a8be;
|
||||||
.app-breadcrumb.el-breadcrumb {
|
cursor: text;
|
||||||
display: inline-block;
|
}
|
||||||
font-size: 14px;
|
}
|
||||||
line-height: 50px;
|
</style>
|
||||||
margin-left: 8px;
|
|
||||||
|
|
||||||
.no-redirect {
|
|
||||||
color: #97a8be;
|
|
||||||
cursor: text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,161 +1,174 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size="small">
|
<el-form>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="1">
|
<el-radio v-model='radioValue' :label="1">
|
||||||
日,允许的通配符[, - * ? / L W]
|
日,允许的通配符[, - * ? / L W]
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="2">
|
<el-radio v-model='radioValue' :label="2">
|
||||||
不指定
|
不指定
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="3">
|
<el-radio v-model='radioValue' :label="3">
|
||||||
周期从
|
周期从
|
||||||
<el-input-number v-model='cycle01' :min="1" :max="30" /> -
|
<el-input-number v-model='cycle01' :min="1" :max="30" /> -
|
||||||
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="31" /> 日
|
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="31" /> 日
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="4">
|
<el-radio v-model='radioValue' :label="4">
|
||||||
从
|
从
|
||||||
<el-input-number v-model='average01' :min="1" :max="30" /> 号开始,每
|
<el-input-number v-model='average01' :min="1" :max="30" /> 号开始,每
|
||||||
<el-input-number v-model='average02' :min="1" :max="31 - average01 || 1" /> 日执行一次
|
<el-input-number v-model='average02' :min="1" :max="31 - average01" /> 日执行一次
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="5">
|
<el-radio v-model='radioValue' :label="5">
|
||||||
每月
|
每月
|
||||||
<el-input-number v-model='workday' :min="1" :max="31" /> 号最近的那个工作日
|
<el-input-number v-model='workday' :min="1" :max="31" /> 号最近的那个工作日
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="6">
|
<el-radio v-model='radioValue' :label="6">
|
||||||
本月最后一天
|
本月最后一天
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="7">
|
<el-radio v-model='radioValue' :label="7">
|
||||||
指定
|
指定
|
||||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
|
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
|
||||||
<el-option v-for="item in 31" :key="item" :value="item">{{item}}</el-option>
|
<el-option v-for="item in 31" :key="item" :label="item" :value="item" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
|
<script setup>
|
||||||
<script>
|
const emit = defineEmits(['update'])
|
||||||
export default {
|
const props = defineProps({
|
||||||
data() {
|
cron: {
|
||||||
return {
|
type: Object,
|
||||||
radioValue: 1,
|
default: {
|
||||||
workday: 1,
|
second: "*",
|
||||||
cycle01: 1,
|
min: "*",
|
||||||
cycle02: 2,
|
hour: "*",
|
||||||
average01: 1,
|
day: "*",
|
||||||
average02: 1,
|
month: "*",
|
||||||
checkboxList: [],
|
week: "?",
|
||||||
checkNum: this.$options.propsData.check
|
year: "",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
name: 'crontab-day',
|
check: {
|
||||||
props: ['check', 'cron'],
|
type: Function,
|
||||||
methods: {
|
default: () => {
|
||||||
// 单选按钮值变化时
|
}
|
||||||
radioChange() {
|
}
|
||||||
('day rachange');
|
})
|
||||||
if (this.radioValue !== 2 && this.cron.week !== '?') {
|
const radioValue = ref(1)
|
||||||
this.$emit('update', 'week', '?', 'day')
|
const cycle01 = ref(1)
|
||||||
}
|
const cycle02 = ref(2)
|
||||||
|
const average01 = ref(1)
|
||||||
switch (this.radioValue) {
|
const average02 = ref(1)
|
||||||
case 1:
|
const workday = ref(1)
|
||||||
this.$emit('update', 'day', '*');
|
const checkboxList = ref([])
|
||||||
break;
|
const checkCopy = ref([1])
|
||||||
case 2:
|
const cycleTotal = computed(() => {
|
||||||
this.$emit('update', 'day', '?');
|
cycle01.value = props.check(cycle01.value, 1, 30)
|
||||||
break;
|
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 31)
|
||||||
case 3:
|
return cycle01.value + '-' + cycle02.value
|
||||||
this.$emit('update', 'day', this.cycleTotal);
|
})
|
||||||
break;
|
const averageTotal = computed(() => {
|
||||||
case 4:
|
average01.value = props.check(average01.value, 1, 30)
|
||||||
this.$emit('update', 'day', this.averageTotal);
|
average02.value = props.check(average02.value, 1, 31 - average01.value)
|
||||||
break;
|
return average01.value + '/' + average02.value
|
||||||
case 5:
|
})
|
||||||
this.$emit('update', 'day', this.workday + 'W');
|
const workdayTotal = computed(() => {
|
||||||
break;
|
workday.value = props.check(workday.value, 1, 31)
|
||||||
case 6:
|
return workday.value + 'W'
|
||||||
this.$emit('update', 'day', 'L');
|
})
|
||||||
break;
|
const checkboxString = computed(() => {
|
||||||
case 7:
|
return checkboxList.value.join(',')
|
||||||
this.$emit('update', 'day', this.checkboxString);
|
})
|
||||||
break;
|
watch(() => props.cron.day, value => changeRadioValue(value))
|
||||||
}
|
watch([radioValue, cycleTotal, averageTotal, workdayTotal, checkboxString], () => onRadioChange())
|
||||||
('day rachange end');
|
function changeRadioValue(value) {
|
||||||
},
|
if (value === "*") {
|
||||||
// 周期两个值变化时
|
radioValue.value = 1
|
||||||
cycleChange() {
|
} else if (value === "?") {
|
||||||
if (this.radioValue == '3') {
|
radioValue.value = 2
|
||||||
this.$emit('update', 'day', this.cycleTotal);
|
} else if (value.indexOf("-") > -1) {
|
||||||
}
|
const indexArr = value.split('-')
|
||||||
},
|
cycle01.value = Number(indexArr[0])
|
||||||
// 平均两个值变化时
|
cycle02.value = Number(indexArr[1])
|
||||||
averageChange() {
|
radioValue.value = 3
|
||||||
if (this.radioValue == '4') {
|
} else if (value.indexOf("/") > -1) {
|
||||||
this.$emit('update', 'day', this.averageTotal);
|
const indexArr = value.split('/')
|
||||||
}
|
average01.value = Number(indexArr[0])
|
||||||
},
|
average02.value = Number(indexArr[1])
|
||||||
// 最近工作日值变化时
|
radioValue.value = 4
|
||||||
workdayChange() {
|
} else if (value.indexOf("W") > -1) {
|
||||||
if (this.radioValue == '5') {
|
const indexArr = value.split("W")
|
||||||
this.$emit('update', 'day', this.workdayCheck + 'W');
|
workday.value = Number(indexArr[0])
|
||||||
}
|
radioValue.value = 5
|
||||||
},
|
} else if (value === "L") {
|
||||||
// checkbox值变化时
|
radioValue.value = 6
|
||||||
checkboxChange() {
|
} else {
|
||||||
if (this.radioValue == '7') {
|
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
|
||||||
this.$emit('update', 'day', this.checkboxString);
|
radioValue.value = 7
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
// 单选按钮值变化时
|
||||||
watch: {
|
function onRadioChange() {
|
||||||
'radioValue': 'radioChange',
|
if (radioValue.value === 2 && props.cron.week === '?') {
|
||||||
'cycleTotal': 'cycleChange',
|
emit('update', 'week', '*', 'day')
|
||||||
'averageTotal': 'averageChange',
|
}
|
||||||
'workdayCheck': 'workdayChange',
|
if (radioValue.value !== 2 && props.cron.week !== '?') {
|
||||||
'checkboxString': 'checkboxChange',
|
emit('update', 'week', '?', 'day')
|
||||||
},
|
}
|
||||||
computed: {
|
switch (radioValue.value) {
|
||||||
// 计算两个周期值
|
case 1:
|
||||||
cycleTotal: function () {
|
emit('update', 'day', '*', 'day')
|
||||||
const cycle01 = this.checkNum(this.cycle01, 1, 30)
|
break
|
||||||
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 31, 31)
|
case 2:
|
||||||
return cycle01 + '-' + cycle02;
|
emit('update', 'day', '?', 'day')
|
||||||
},
|
break
|
||||||
// 计算平均用到的值
|
case 3:
|
||||||
averageTotal: function () {
|
emit('update', 'day', cycleTotal.value, 'day')
|
||||||
const average01 = this.checkNum(this.average01, 1, 30)
|
break
|
||||||
const average02 = this.checkNum(this.average02, 1, 31 - average01 || 0)
|
case 4:
|
||||||
return average01 + '/' + average02;
|
emit('update', 'day', averageTotal.value, 'day')
|
||||||
},
|
break
|
||||||
// 计算工作日格式
|
case 5:
|
||||||
workdayCheck: function () {
|
emit('update', 'day', workdayTotal.value, 'day')
|
||||||
const workday = this.checkNum(this.workday, 1, 31)
|
break
|
||||||
return workday;
|
case 6:
|
||||||
},
|
emit('update', 'day', 'L', 'day')
|
||||||
// 计算勾选的checkbox值合集
|
break
|
||||||
checkboxString: function () {
|
case 7:
|
||||||
let str = this.checkboxList.join();
|
if (checkboxList.value.length === 0) {
|
||||||
return str == '' ? '*' : str;
|
checkboxList.value.push(checkCopy.value[0])
|
||||||
}
|
} else {
|
||||||
}
|
checkCopy.value = checkboxList.value
|
||||||
|
}
|
||||||
|
emit('update', 'day', checkboxString.value, 'day')
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.el-input-number--small, .el-select, .el-select--small {
|
||||||
|
margin: 0 0.2rem;
|
||||||
|
}
|
||||||
|
.el-select, .el-select--small {
|
||||||
|
width: 18.8rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,114 +1,127 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size="small">
|
<el-form>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="1">
|
<el-radio v-model='radioValue' :label="1">
|
||||||
小时,允许的通配符[, - * /]
|
小时,允许的通配符[, - * /]
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="2">
|
<el-radio v-model='radioValue' :label="2">
|
||||||
周期从
|
周期从
|
||||||
<el-input-number v-model='cycle01' :min="0" :max="22" /> -
|
<el-input-number v-model='cycle01' :min="0" :max="22" /> -
|
||||||
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="23" /> 小时
|
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="23" /> 时
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="3">
|
<el-radio v-model='radioValue' :label="3">
|
||||||
从
|
从
|
||||||
<el-input-number v-model='average01' :min="0" :max="22" /> 小时开始,每
|
<el-input-number v-model='average01' :min="0" :max="22" /> 时开始,每
|
||||||
<el-input-number v-model='average02' :min="1" :max="23 - average01 || 0" /> 小时执行一次
|
<el-input-number v-model='average02' :min="1" :max="23 - average01" /> 小时执行一次
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="4">
|
<el-radio v-model='radioValue' :label="4">
|
||||||
指定
|
指定
|
||||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
|
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
|
||||||
<el-option v-for="item in 24" :key="item" :value="item-1">{{item-1}}</el-option>
|
<el-option v-for="item in 24" :key="item" :label="item - 1" :value="item - 1" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
const emit = defineEmits(['update'])
|
||||||
data() {
|
const props = defineProps({
|
||||||
return {
|
cron: {
|
||||||
radioValue: 1,
|
type: Object,
|
||||||
cycle01: 0,
|
default: {
|
||||||
cycle02: 1,
|
second: "*",
|
||||||
average01: 0,
|
min: "*",
|
||||||
average02: 1,
|
hour: "*",
|
||||||
checkboxList: [],
|
day: "*",
|
||||||
checkNum: this.$options.propsData.check
|
month: "*",
|
||||||
}
|
week: "?",
|
||||||
},
|
year: "",
|
||||||
name: 'crontab-hour',
|
}
|
||||||
props: ['check', 'cron'],
|
},
|
||||||
methods: {
|
check: {
|
||||||
// 单选按钮值变化时
|
type: Function,
|
||||||
radioChange() {
|
default: () => {
|
||||||
switch (this.radioValue) {
|
}
|
||||||
case 1:
|
}
|
||||||
this.$emit('update', 'hour', '*')
|
})
|
||||||
break;
|
const radioValue = ref(1)
|
||||||
case 2:
|
const cycle01 = ref(0)
|
||||||
this.$emit('update', 'hour', this.cycleTotal);
|
const cycle02 = ref(1)
|
||||||
break;
|
const average01 = ref(0)
|
||||||
case 3:
|
const average02 = ref(1)
|
||||||
this.$emit('update', 'hour', this.averageTotal);
|
const checkboxList = ref([])
|
||||||
break;
|
const checkCopy = ref([0])
|
||||||
case 4:
|
const cycleTotal = computed(() => {
|
||||||
this.$emit('update', 'hour', this.checkboxString);
|
cycle01.value = props.check(cycle01.value, 0, 22)
|
||||||
break;
|
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 23)
|
||||||
}
|
return cycle01.value + '-' + cycle02.value
|
||||||
},
|
})
|
||||||
// 周期两个值变化时
|
const averageTotal = computed(() => {
|
||||||
cycleChange() {
|
average01.value = props.check(average01.value, 0, 22)
|
||||||
if (this.radioValue == '2') {
|
average02.value = props.check(average02.value, 1, 23 - average01.value)
|
||||||
this.$emit('update', 'hour', this.cycleTotal);
|
return average01.value + '/' + average02.value
|
||||||
}
|
})
|
||||||
},
|
const checkboxString = computed(() => {
|
||||||
// 平均两个值变化时
|
return checkboxList.value.join(',')
|
||||||
averageChange() {
|
})
|
||||||
if (this.radioValue == '3') {
|
watch(() => props.cron.hour, value => changeRadioValue(value))
|
||||||
this.$emit('update', 'hour', this.averageTotal);
|
watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
|
||||||
}
|
function changeRadioValue(value) {
|
||||||
},
|
if (value === '*') {
|
||||||
// checkbox值变化时
|
radioValue.value = 1
|
||||||
checkboxChange() {
|
} else if (value.indexOf('-') > -1) {
|
||||||
if (this.radioValue == '4') {
|
const indexArr = value.split('-')
|
||||||
this.$emit('update', 'hour', this.checkboxString);
|
cycle01.value = Number(indexArr[0])
|
||||||
}
|
cycle02.value = Number(indexArr[1])
|
||||||
}
|
radioValue.value = 2
|
||||||
},
|
} else if (value.indexOf('/') > -1) {
|
||||||
watch: {
|
const indexArr = value.split('/')
|
||||||
'radioValue': 'radioChange',
|
average01.value = Number(indexArr[0])
|
||||||
'cycleTotal': 'cycleChange',
|
average02.value = Number(indexArr[1])
|
||||||
'averageTotal': 'averageChange',
|
radioValue.value = 3
|
||||||
'checkboxString': 'checkboxChange'
|
} else {
|
||||||
},
|
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
|
||||||
computed: {
|
radioValue.value = 4
|
||||||
// 计算两个周期值
|
}
|
||||||
cycleTotal: function () {
|
}
|
||||||
const cycle01 = this.checkNum(this.cycle01, 0, 22)
|
function onRadioChange() {
|
||||||
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 23)
|
switch (radioValue.value) {
|
||||||
return cycle01 + '-' + cycle02;
|
case 1:
|
||||||
},
|
emit('update', 'hour', '*', 'hour')
|
||||||
// 计算平均用到的值
|
break
|
||||||
averageTotal: function () {
|
case 2:
|
||||||
const average01 = this.checkNum(this.average01, 0, 22)
|
emit('update', 'hour', cycleTotal.value, 'hour')
|
||||||
const average02 = this.checkNum(this.average02, 1, 23 - average01 || 0)
|
break
|
||||||
return average01 + '/' + average02;
|
case 3:
|
||||||
},
|
emit('update', 'hour', averageTotal.value, 'hour')
|
||||||
// 计算勾选的checkbox值合集
|
break
|
||||||
checkboxString: function () {
|
case 4:
|
||||||
let str = this.checkboxList.join();
|
if (checkboxList.value.length === 0) {
|
||||||
return str == '' ? '*' : str;
|
checkboxList.value.push(checkCopy.value[0])
|
||||||
}
|
} else {
|
||||||
}
|
checkCopy.value = checkboxList.value
|
||||||
|
}
|
||||||
|
emit('update', 'hour', checkboxString.value, 'hour')
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.el-input-number--small, .el-select, .el-select--small {
|
||||||
|
margin: 0 0.2rem;
|
||||||
|
}
|
||||||
|
.el-select, .el-select--small {
|
||||||
|
width: 18.8rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,320 +1,233 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-tabs type="border-card">
|
<el-tabs type="border-card">
|
||||||
<el-tab-pane label="秒" v-if="shouldHide('second')">
|
<el-tab-pane label="秒" v-if="shouldHide('second')">
|
||||||
<CrontabSecond
|
<CrontabSecond
|
||||||
@update="updateCrontabValue"
|
@update="updateCrontabValue"
|
||||||
:check="checkNumber"
|
:check="checkNumber"
|
||||||
:cron="crontabValueObj"
|
:cron="crontabValueObj"
|
||||||
ref="cronsecond"
|
ref="cronsecond"
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="分钟" v-if="shouldHide('min')">
|
<el-tab-pane label="分钟" v-if="shouldHide('min')">
|
||||||
<CrontabMin
|
<CrontabMin
|
||||||
@update="updateCrontabValue"
|
@update="updateCrontabValue"
|
||||||
:check="checkNumber"
|
:check="checkNumber"
|
||||||
:cron="crontabValueObj"
|
:cron="crontabValueObj"
|
||||||
ref="cronmin"
|
ref="cronmin"
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="小时" v-if="shouldHide('hour')">
|
<el-tab-pane label="小时" v-if="shouldHide('hour')">
|
||||||
<CrontabHour
|
<CrontabHour
|
||||||
@update="updateCrontabValue"
|
@update="updateCrontabValue"
|
||||||
:check="checkNumber"
|
:check="checkNumber"
|
||||||
:cron="crontabValueObj"
|
:cron="crontabValueObj"
|
||||||
ref="cronhour"
|
ref="cronhour"
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="日" v-if="shouldHide('day')">
|
<el-tab-pane label="日" v-if="shouldHide('day')">
|
||||||
<CrontabDay
|
<CrontabDay
|
||||||
@update="updateCrontabValue"
|
@update="updateCrontabValue"
|
||||||
:check="checkNumber"
|
:check="checkNumber"
|
||||||
:cron="crontabValueObj"
|
:cron="crontabValueObj"
|
||||||
ref="cronday"
|
ref="cronday"
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="月" v-if="shouldHide('month')">
|
<el-tab-pane label="月" v-if="shouldHide('month')">
|
||||||
<CrontabMonth
|
<CrontabMonth
|
||||||
@update="updateCrontabValue"
|
@update="updateCrontabValue"
|
||||||
:check="checkNumber"
|
:check="checkNumber"
|
||||||
:cron="crontabValueObj"
|
:cron="crontabValueObj"
|
||||||
ref="cronmonth"
|
ref="cronmonth"
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="周" v-if="shouldHide('week')">
|
<el-tab-pane label="周" v-if="shouldHide('week')">
|
||||||
<CrontabWeek
|
<CrontabWeek
|
||||||
@update="updateCrontabValue"
|
@update="updateCrontabValue"
|
||||||
:check="checkNumber"
|
:check="checkNumber"
|
||||||
:cron="crontabValueObj"
|
:cron="crontabValueObj"
|
||||||
ref="cronweek"
|
ref="cronweek"
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="年" v-if="shouldHide('year')">
|
<el-tab-pane label="年" v-if="shouldHide('year')">
|
||||||
<CrontabYear
|
<CrontabYear
|
||||||
@update="updateCrontabValue"
|
@update="updateCrontabValue"
|
||||||
:check="checkNumber"
|
:check="checkNumber"
|
||||||
:cron="crontabValueObj"
|
:cron="crontabValueObj"
|
||||||
ref="cronyear"
|
ref="cronyear"
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
|
||||||
<div class="popup-main">
|
<div class="popup-main">
|
||||||
<div class="popup-result">
|
<div class="popup-result">
|
||||||
<p class="title">时间表达式</p>
|
<p class="title">时间表达式</p>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<th v-for="item of tabTitles" width="40" :key="item">{{item}}</th>
|
<th v-for="item of tabTitles" :key="item">{{item}}</th>
|
||||||
<th>Cron 表达式</th>
|
<th>Cron 表达式</th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<td>
|
<td>
|
||||||
<span>{{crontabValueObj.second}}</span>
|
<span v-if="crontabValueObj.second.length < 10">{{crontabValueObj.second}}</span>
|
||||||
</td>
|
<el-tooltip v-else :content="crontabValueObj.second" placement="top"><span>{{crontabValueObj.second}}</span></el-tooltip>
|
||||||
<td>
|
</td>
|
||||||
<span>{{crontabValueObj.min}}</span>
|
<td>
|
||||||
</td>
|
<span v-if="crontabValueObj.min.length < 10">{{crontabValueObj.min}}</span>
|
||||||
<td>
|
<el-tooltip v-else :content="crontabValueObj.min" placement="top"><span>{{crontabValueObj.min}}</span></el-tooltip>
|
||||||
<span>{{crontabValueObj.hour}}</span>
|
</td>
|
||||||
</td>
|
<td>
|
||||||
<td>
|
<span v-if="crontabValueObj.hour.length < 10">{{crontabValueObj.hour}}</span>
|
||||||
<span>{{crontabValueObj.day}}</span>
|
<el-tooltip v-else :content="crontabValueObj.hour" placement="top"><span>{{crontabValueObj.hour}}</span></el-tooltip>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span>{{crontabValueObj.month}}</span>
|
<span v-if="crontabValueObj.day.length < 10">{{crontabValueObj.day}}</span>
|
||||||
</td>
|
<el-tooltip v-else :content="crontabValueObj.day" placement="top"><span>{{crontabValueObj.day}}</span></el-tooltip>
|
||||||
<td>
|
</td>
|
||||||
<span>{{crontabValueObj.week}}</span>
|
<td>
|
||||||
</td>
|
<span v-if="crontabValueObj.month.length < 10">{{crontabValueObj.month}}</span>
|
||||||
<td>
|
<el-tooltip v-else :content="crontabValueObj.month" placement="top"><span>{{crontabValueObj.month}}</span></el-tooltip>
|
||||||
<span>{{crontabValueObj.year}}</span>
|
</td>
|
||||||
</td>
|
<td>
|
||||||
<td>
|
<span v-if="crontabValueObj.week.length < 10">{{crontabValueObj.week}}</span>
|
||||||
<span>{{crontabValueString}}</span>
|
<el-tooltip v-else :content="crontabValueObj.week" placement="top"><span>{{crontabValueObj.week}}</span></el-tooltip>
|
||||||
</td>
|
</td>
|
||||||
</tbody>
|
<td>
|
||||||
</table>
|
<span v-if="crontabValueObj.year.length < 10">{{crontabValueObj.year}}</span>
|
||||||
</div>
|
<el-tooltip v-else :content="crontabValueObj.year" placement="top"><span>{{crontabValueObj.year}}</span></el-tooltip>
|
||||||
<CrontabResult :ex="crontabValueString"></CrontabResult>
|
</td>
|
||||||
|
<td class="result">
|
||||||
|
<span v-if="crontabValueString.length < 90">{{crontabValueString}}</span>
|
||||||
|
<el-tooltip v-else :content="crontabValueString" placement="top"><span>{{crontabValueString}}</span></el-tooltip>
|
||||||
|
</td>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<CrontabResult :ex="crontabValueString"></CrontabResult>
|
||||||
|
|
||||||
<div class="pop_btn">
|
<div class="pop_btn">
|
||||||
<el-button size="small" type="primary" @click="submitFill">确定</el-button>
|
<el-button type="primary" @click="submitFill">确定</el-button>
|
||||||
<el-button size="small" type="warning" @click="clearCron">重置</el-button>
|
<el-button type="warning" @click="clearCron">重置</el-button>
|
||||||
<el-button size="small" @click="hidePopup">取消</el-button>
|
<el-button @click="hidePopup">取消</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import CrontabSecond from "./second.vue";
|
import CrontabSecond from "./second.vue"
|
||||||
import CrontabMin from "./min.vue";
|
import CrontabMin from "./min.vue"
|
||||||
import CrontabHour from "./hour.vue";
|
import CrontabHour from "./hour.vue"
|
||||||
import CrontabDay from "./day.vue";
|
import CrontabDay from "./day.vue"
|
||||||
import CrontabMonth from "./month.vue";
|
import CrontabMonth from "./month.vue"
|
||||||
import CrontabWeek from "./week.vue";
|
import CrontabWeek from "./week.vue"
|
||||||
import CrontabYear from "./year.vue";
|
import CrontabYear from "./year.vue"
|
||||||
import CrontabResult from "./result.vue";
|
import CrontabResult from "./result.vue"
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
export default {
|
const emit = defineEmits(['hide', 'fill'])
|
||||||
data() {
|
const props = defineProps({
|
||||||
return {
|
hideComponent: {
|
||||||
tabTitles: ["秒", "分钟", "小时", "日", "月", "周", "年"],
|
type: Array,
|
||||||
tabActive: 0,
|
default: () => [],
|
||||||
myindex: 0,
|
|
||||||
crontabValueObj: {
|
|
||||||
second: "*",
|
|
||||||
min: "*",
|
|
||||||
hour: "*",
|
|
||||||
day: "*",
|
|
||||||
month: "*",
|
|
||||||
week: "?",
|
|
||||||
year: "",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
name: "vcrontab",
|
|
||||||
props: ["expression", "hideComponent"],
|
|
||||||
methods: {
|
|
||||||
shouldHide(key) {
|
|
||||||
if (this.hideComponent && this.hideComponent.includes(key)) return false;
|
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
resolveExp() {
|
expression: {
|
||||||
// 反解析 表达式
|
type: String,
|
||||||
if (this.expression) {
|
default: ""
|
||||||
let arr = this.expression.split(" ");
|
}
|
||||||
|
})
|
||||||
|
const tabTitles = ref(["秒", "分钟", "小时", "日", "月", "周", "年"])
|
||||||
|
const tabActive = ref(0)
|
||||||
|
const hideComponent = ref([])
|
||||||
|
const expression = ref('')
|
||||||
|
const crontabValueObj = ref({
|
||||||
|
second: "*",
|
||||||
|
min: "*",
|
||||||
|
hour: "*",
|
||||||
|
day: "*",
|
||||||
|
month: "*",
|
||||||
|
week: "?",
|
||||||
|
year: "",
|
||||||
|
})
|
||||||
|
const crontabValueString = computed(() => {
|
||||||
|
const obj = crontabValueObj.value
|
||||||
|
return obj.second
|
||||||
|
+ " "
|
||||||
|
+ obj.min
|
||||||
|
+ " "
|
||||||
|
+ obj.hour
|
||||||
|
+ " "
|
||||||
|
+ obj.day
|
||||||
|
+ " "
|
||||||
|
+ obj.month
|
||||||
|
+ " "
|
||||||
|
+ obj.week
|
||||||
|
+ (obj.year === "" ? "" : " " + obj.year)
|
||||||
|
})
|
||||||
|
watch(expression, () => resolveExp())
|
||||||
|
function shouldHide(key) {
|
||||||
|
return !(hideComponent.value && hideComponent.value.includes(key))
|
||||||
|
}
|
||||||
|
function resolveExp() {
|
||||||
|
// 反解析 表达式
|
||||||
|
if (expression.value) {
|
||||||
|
const arr = expression.value.split(/\s+/)
|
||||||
if (arr.length >= 6) {
|
if (arr.length >= 6) {
|
||||||
//6 位以上是合法表达式
|
//6 位以上是合法表达式
|
||||||
let obj = {
|
let obj = {
|
||||||
second: arr[0],
|
second: arr[0],
|
||||||
min: arr[1],
|
min: arr[1],
|
||||||
hour: arr[2],
|
hour: arr[2],
|
||||||
day: arr[3],
|
day: arr[3],
|
||||||
month: arr[4],
|
month: arr[4],
|
||||||
week: arr[5],
|
week: arr[5],
|
||||||
year: arr[6] ? arr[6] : "",
|
year: arr[6] ? arr[6] : ""
|
||||||
};
|
}
|
||||||
this.crontabValueObj = {
|
crontabValueObj.value = {
|
||||||
...obj,
|
...obj,
|
||||||
};
|
}
|
||||||
for (let i in obj) {
|
|
||||||
if (obj[i]) this.changeRadio(i, obj[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 没有传入的表达式 则还原
|
// 没有传入的表达式 则还原
|
||||||
this.clearCron();
|
clearCron()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
// tab切换值
|
// tab切换值
|
||||||
tabCheck(index) {
|
function tabCheck(index) {
|
||||||
this.tabActive = index;
|
tabActive.value = index
|
||||||
},
|
}
|
||||||
// 由子组件触发,更改表达式组成的字段值
|
// 由子组件触发,更改表达式组成的字段值
|
||||||
updateCrontabValue(name, value, from) {
|
function updateCrontabValue(name, value, from) {
|
||||||
"updateCrontabValue", name, value, from;
|
crontabValueObj.value[name] = value
|
||||||
this.crontabValueObj[name] = value;
|
}
|
||||||
if (from && from !== name) {
|
// 表单选项的子组件校验数字格式(通过-props传递)
|
||||||
console.log(`来自组件 ${from} 改变了 ${name} ${value}`);
|
function checkNumber(value, minLimit, maxLimit) {
|
||||||
this.changeRadio(name, value);
|
// 检查必须为整数
|
||||||
}
|
value = Math.floor(value)
|
||||||
},
|
if (value < minLimit) {
|
||||||
// 赋值到组件
|
value = minLimit
|
||||||
changeRadio(name, value) {
|
} else if (value > maxLimit) {
|
||||||
let arr = ["second", "min", "hour", "month"],
|
value = maxLimit
|
||||||
refName = "cron" + name,
|
}
|
||||||
insValue;
|
return value
|
||||||
|
}
|
||||||
if (!this.$refs[refName]) return;
|
// 隐藏弹窗
|
||||||
|
function hidePopup() {
|
||||||
if (arr.includes(name)) {
|
emit("hide")
|
||||||
if (value === "*") {
|
}
|
||||||
insValue = 1;
|
// 填充表达式
|
||||||
} else if (value.indexOf("-") > -1) {
|
function submitFill() {
|
||||||
let indexArr = value.split("-");
|
emit("fill", crontabValueString.value)
|
||||||
isNaN(indexArr[0])
|
hidePopup()
|
||||||
? (this.$refs[refName].cycle01 = 0)
|
}
|
||||||
: (this.$refs[refName].cycle01 = indexArr[0]);
|
function clearCron() {
|
||||||
this.$refs[refName].cycle02 = indexArr[1];
|
// 还原选择项
|
||||||
insValue = 2;
|
crontabValueObj.value = {
|
||||||
} else if (value.indexOf("/") > -1) {
|
|
||||||
let indexArr = value.split("/");
|
|
||||||
isNaN(indexArr[0])
|
|
||||||
? (this.$refs[refName].average01 = 0)
|
|
||||||
: (this.$refs[refName].average01 = indexArr[0]);
|
|
||||||
this.$refs[refName].average02 = indexArr[1];
|
|
||||||
insValue = 3;
|
|
||||||
} else {
|
|
||||||
insValue = 4;
|
|
||||||
this.$refs[refName].checkboxList = value.split(",");
|
|
||||||
}
|
|
||||||
} else if (name == "day") {
|
|
||||||
if (value === "*") {
|
|
||||||
insValue = 1;
|
|
||||||
} else if (value == "?") {
|
|
||||||
insValue = 2;
|
|
||||||
} else if (value.indexOf("-") > -1) {
|
|
||||||
let indexArr = value.split("-");
|
|
||||||
isNaN(indexArr[0])
|
|
||||||
? (this.$refs[refName].cycle01 = 0)
|
|
||||||
: (this.$refs[refName].cycle01 = indexArr[0]);
|
|
||||||
this.$refs[refName].cycle02 = indexArr[1];
|
|
||||||
insValue = 3;
|
|
||||||
} else if (value.indexOf("/") > -1) {
|
|
||||||
let indexArr = value.split("/");
|
|
||||||
isNaN(indexArr[0])
|
|
||||||
? (this.$refs[refName].average01 = 0)
|
|
||||||
: (this.$refs[refName].average01 = indexArr[0]);
|
|
||||||
this.$refs[refName].average02 = indexArr[1];
|
|
||||||
insValue = 4;
|
|
||||||
} else if (value.indexOf("W") > -1) {
|
|
||||||
let indexArr = value.split("W");
|
|
||||||
isNaN(indexArr[0])
|
|
||||||
? (this.$refs[refName].workday = 0)
|
|
||||||
: (this.$refs[refName].workday = indexArr[0]);
|
|
||||||
insValue = 5;
|
|
||||||
} else if (value === "L") {
|
|
||||||
insValue = 6;
|
|
||||||
} else {
|
|
||||||
this.$refs[refName].checkboxList = value.split(",");
|
|
||||||
insValue = 7;
|
|
||||||
}
|
|
||||||
} else if (name == "week") {
|
|
||||||
if (value === "*") {
|
|
||||||
insValue = 1;
|
|
||||||
} else if (value == "?") {
|
|
||||||
insValue = 2;
|
|
||||||
} else if (value.indexOf("-") > -1) {
|
|
||||||
let indexArr = value.split("-");
|
|
||||||
isNaN(indexArr[0])
|
|
||||||
? (this.$refs[refName].cycle01 = 0)
|
|
||||||
: (this.$refs[refName].cycle01 = indexArr[0]);
|
|
||||||
this.$refs[refName].cycle02 = indexArr[1];
|
|
||||||
insValue = 3;
|
|
||||||
} else if (value.indexOf("#") > -1) {
|
|
||||||
let indexArr = value.split("#");
|
|
||||||
isNaN(indexArr[0])
|
|
||||||
? (this.$refs[refName].average01 = 1)
|
|
||||||
: (this.$refs[refName].average01 = indexArr[0]);
|
|
||||||
this.$refs[refName].average02 = indexArr[1];
|
|
||||||
insValue = 4;
|
|
||||||
} else if (value.indexOf("L") > -1) {
|
|
||||||
let indexArr = value.split("L");
|
|
||||||
isNaN(indexArr[0])
|
|
||||||
? (this.$refs[refName].weekday = 1)
|
|
||||||
: (this.$refs[refName].weekday = indexArr[0]);
|
|
||||||
insValue = 5;
|
|
||||||
} else {
|
|
||||||
this.$refs[refName].checkboxList = value.split(",");
|
|
||||||
insValue = 6;
|
|
||||||
}
|
|
||||||
} else if (name == "year") {
|
|
||||||
if (value == "") {
|
|
||||||
insValue = 1;
|
|
||||||
} else if (value == "*") {
|
|
||||||
insValue = 2;
|
|
||||||
} else if (value.indexOf("-") > -1) {
|
|
||||||
insValue = 3;
|
|
||||||
} else if (value.indexOf("/") > -1) {
|
|
||||||
insValue = 4;
|
|
||||||
} else {
|
|
||||||
this.$refs[refName].checkboxList = value.split(",");
|
|
||||||
insValue = 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.$refs[refName].radioValue = insValue;
|
|
||||||
},
|
|
||||||
// 表单选项的子组件校验数字格式(通过-props传递)
|
|
||||||
checkNumber(value, minLimit, maxLimit) {
|
|
||||||
// 检查必须为整数
|
|
||||||
value = Math.floor(value);
|
|
||||||
if (value < minLimit) {
|
|
||||||
value = minLimit;
|
|
||||||
} else if (value > maxLimit) {
|
|
||||||
value = maxLimit;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
// 隐藏弹窗
|
|
||||||
hidePopup() {
|
|
||||||
this.$emit("hide");
|
|
||||||
},
|
|
||||||
// 填充表达式
|
|
||||||
submitFill() {
|
|
||||||
this.$emit("fill", this.crontabValueString);
|
|
||||||
this.hidePopup();
|
|
||||||
},
|
|
||||||
clearCron() {
|
|
||||||
// 还原选择项
|
|
||||||
("准备还原");
|
|
||||||
this.crontabValueObj = {
|
|
||||||
second: "*",
|
second: "*",
|
||||||
min: "*",
|
min: "*",
|
||||||
hour: "*",
|
hour: "*",
|
||||||
@@ -322,109 +235,76 @@ export default {
|
|||||||
month: "*",
|
month: "*",
|
||||||
week: "?",
|
week: "?",
|
||||||
year: "",
|
year: "",
|
||||||
};
|
}
|
||||||
for (let j in this.crontabValueObj) {
|
}
|
||||||
this.changeRadio(j, this.crontabValueObj[j]);
|
onMounted(() => {
|
||||||
}
|
expression.value = props.expression
|
||||||
},
|
hideComponent.value = props.hideComponent
|
||||||
},
|
})
|
||||||
computed: {
|
|
||||||
crontabValueString: function() {
|
|
||||||
let obj = this.crontabValueObj;
|
|
||||||
let str =
|
|
||||||
obj.second +
|
|
||||||
" " +
|
|
||||||
obj.min +
|
|
||||||
" " +
|
|
||||||
obj.hour +
|
|
||||||
" " +
|
|
||||||
obj.day +
|
|
||||||
" " +
|
|
||||||
obj.month +
|
|
||||||
" " +
|
|
||||||
obj.week +
|
|
||||||
(obj.year == "" ? "" : " " + obj.year);
|
|
||||||
return str;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
CrontabSecond,
|
|
||||||
CrontabMin,
|
|
||||||
CrontabHour,
|
|
||||||
CrontabDay,
|
|
||||||
CrontabMonth,
|
|
||||||
CrontabWeek,
|
|
||||||
CrontabYear,
|
|
||||||
CrontabResult,
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
expression: "resolveExp",
|
|
||||||
hideComponent(value) {
|
|
||||||
// 隐藏部分组件
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted: function() {
|
|
||||||
this.resolveExp();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
.pop_btn {
|
.pop_btn {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
.popup-main {
|
.popup-main {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.popup-title {
|
.popup-title {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
line-height: 34px;
|
line-height: 34px;
|
||||||
padding-top: 6px;
|
padding-top: 6px;
|
||||||
background: #f2f2f2;
|
background: #f2f2f2;
|
||||||
}
|
}
|
||||||
.popup-result {
|
.popup-result {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
margin: 25px auto;
|
margin: 25px auto;
|
||||||
padding: 15px 10px 10px;
|
padding: 15px 10px 10px;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.popup-result .title {
|
.popup-result .title {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -28px;
|
top: -28px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
width: 140px;
|
width: 140px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-left: -70px;
|
margin-left: -70px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
.popup-result table {
|
.popup-result table {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.popup-result table td:not(.result) {
|
||||||
|
width: 3.5rem;
|
||||||
|
min-width: 3.5rem;
|
||||||
|
max-width: 3.5rem;
|
||||||
}
|
}
|
||||||
.popup-result table span {
|
.popup-result table span {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-family: arial;
|
font-family: arial;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 1px solid #e8e8e8;
|
border: 1px solid #e8e8e8;
|
||||||
}
|
}
|
||||||
.popup-result-scroll {
|
.popup-result-scroll {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
height: 10em;
|
height: 10em;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -1,116 +1,126 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size="small">
|
<el-form>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="1">
|
<el-radio v-model='radioValue' :label="1">
|
||||||
分钟,允许的通配符[, - * /]
|
分钟,允许的通配符[, - * /]
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="2">
|
<el-radio v-model='radioValue' :label="2">
|
||||||
周期从
|
周期从
|
||||||
<el-input-number v-model='cycle01' :min="0" :max="58" /> -
|
<el-input-number v-model='cycle01' :min="0" :max="58" /> -
|
||||||
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 分钟
|
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="59" /> 分钟
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="3">
|
<el-radio v-model='radioValue' :label="3">
|
||||||
从
|
从
|
||||||
<el-input-number v-model='average01' :min="0" :max="58" /> 分钟开始,每
|
<el-input-number v-model='average01' :min="0" :max="58" /> 分钟开始, 每
|
||||||
<el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 分钟执行一次
|
<el-input-number v-model='average02' :min="1" :max="59 - average01" /> 分钟执行一次
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
|
||||||
<el-radio v-model='radioValue' :label="4">
|
|
||||||
指定
|
|
||||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
|
|
||||||
<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-radio>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio v-model='radioValue' :label="4">
|
||||||
|
指定
|
||||||
|
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
|
||||||
|
<el-option v-for="item in 60" :key="item" :label="item - 1" :value="item - 1" />
|
||||||
|
</el-select>
|
||||||
|
</el-radio>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
|
<script setup>
|
||||||
<script>
|
const emit = defineEmits(['update'])
|
||||||
export default {
|
const props = defineProps({
|
||||||
data() {
|
cron: {
|
||||||
return {
|
type: Object,
|
||||||
radioValue: 1,
|
default: {
|
||||||
cycle01: 1,
|
second: "*",
|
||||||
cycle02: 2,
|
min: "*",
|
||||||
average01: 0,
|
hour: "*",
|
||||||
average02: 1,
|
day: "*",
|
||||||
checkboxList: [],
|
month: "*",
|
||||||
checkNum: this.$options.propsData.check
|
week: "?",
|
||||||
}
|
year: "",
|
||||||
},
|
}
|
||||||
name: 'crontab-min',
|
},
|
||||||
props: ['check', 'cron'],
|
check: {
|
||||||
methods: {
|
type: Function,
|
||||||
// 单选按钮值变化时
|
default: () => {
|
||||||
radioChange() {
|
}
|
||||||
switch (this.radioValue) {
|
}
|
||||||
case 1:
|
})
|
||||||
this.$emit('update', 'min', '*', 'min');
|
const radioValue = ref(1)
|
||||||
break;
|
const cycle01 = ref(0)
|
||||||
case 2:
|
const cycle02 = ref(1)
|
||||||
this.$emit('update', 'min', this.cycleTotal, 'min');
|
const average01 = ref(0)
|
||||||
break;
|
const average02 = ref(1)
|
||||||
case 3:
|
const checkboxList = ref([])
|
||||||
this.$emit('update', 'min', this.averageTotal, 'min');
|
const checkCopy = ref([0])
|
||||||
break;
|
const cycleTotal = computed(() => {
|
||||||
case 4:
|
cycle01.value = props.check(cycle01.value, 0, 58)
|
||||||
this.$emit('update', 'min', this.checkboxString, 'min');
|
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 59)
|
||||||
break;
|
return cycle01.value + '-' + cycle02.value
|
||||||
}
|
})
|
||||||
},
|
const averageTotal = computed(() => {
|
||||||
// 周期两个值变化时
|
average01.value = props.check(average01.value, 0, 58)
|
||||||
cycleChange() {
|
average02.value = props.check(average02.value, 1, 59 - average01.value)
|
||||||
if (this.radioValue == '2') {
|
return average01.value + '/' + average02.value
|
||||||
this.$emit('update', 'min', this.cycleTotal, 'min');
|
})
|
||||||
}
|
const checkboxString = computed(() => {
|
||||||
},
|
return checkboxList.value.join(',')
|
||||||
// 平均两个值变化时
|
})
|
||||||
averageChange() {
|
watch(() => props.cron.min, value => changeRadioValue(value))
|
||||||
if (this.radioValue == '3') {
|
watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
|
||||||
this.$emit('update', 'min', this.averageTotal, 'min');
|
function changeRadioValue(value) {
|
||||||
}
|
if (value === '*') {
|
||||||
},
|
radioValue.value = 1
|
||||||
// checkbox值变化时
|
} else if (value.indexOf('-') > -1) {
|
||||||
checkboxChange() {
|
const indexArr = value.split('-')
|
||||||
if (this.radioValue == '4') {
|
cycle01.value = Number(indexArr[0])
|
||||||
this.$emit('update', 'min', this.checkboxString, 'min');
|
cycle02.value = Number(indexArr[1])
|
||||||
}
|
radioValue.value = 2
|
||||||
},
|
} else if (value.indexOf('/') > -1) {
|
||||||
|
const indexArr = value.split('/')
|
||||||
},
|
average01.value = Number(indexArr[0])
|
||||||
watch: {
|
average02.value = Number(indexArr[1])
|
||||||
'radioValue': 'radioChange',
|
radioValue.value = 3
|
||||||
'cycleTotal': 'cycleChange',
|
} else {
|
||||||
'averageTotal': 'averageChange',
|
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
|
||||||
'checkboxString': 'checkboxChange',
|
radioValue.value = 4
|
||||||
},
|
}
|
||||||
computed: {
|
|
||||||
// 计算两个周期值
|
|
||||||
cycleTotal: function () {
|
|
||||||
const cycle01 = this.checkNum(this.cycle01, 0, 58)
|
|
||||||
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59)
|
|
||||||
return cycle01 + '-' + cycle02;
|
|
||||||
},
|
|
||||||
// 计算平均用到的值
|
|
||||||
averageTotal: function () {
|
|
||||||
const average01 = this.checkNum(this.average01, 0, 58)
|
|
||||||
const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0)
|
|
||||||
return average01 + '/' + average02;
|
|
||||||
},
|
|
||||||
// 计算勾选的checkbox值合集
|
|
||||||
checkboxString: function () {
|
|
||||||
let str = this.checkboxList.join();
|
|
||||||
return str == '' ? '*' : str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
function onRadioChange() {
|
||||||
|
switch (radioValue.value) {
|
||||||
|
case 1:
|
||||||
|
emit('update', 'min', '*', 'min')
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
emit('update', 'min', cycleTotal.value, 'min')
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
emit('update', 'min', averageTotal.value, 'min')
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
if (checkboxList.value.length === 0) {
|
||||||
|
checkboxList.value.push(checkCopy.value[0])
|
||||||
|
} else {
|
||||||
|
checkCopy.value = checkboxList.value
|
||||||
|
}
|
||||||
|
emit('update', 'min', checkboxString.value, 'min')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.el-input-number--small, .el-select, .el-select--small {
|
||||||
|
margin: 0 0.2rem;
|
||||||
|
}
|
||||||
|
.el-select, .el-select--small {
|
||||||
|
width: 19.8rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,114 +1,141 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size='small'>
|
<el-form>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="1">
|
<el-radio v-model='radioValue' :label="1">
|
||||||
月,允许的通配符[, - * /]
|
月,允许的通配符[, - * /]
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="2">
|
<el-radio v-model='radioValue' :label="2">
|
||||||
周期从
|
周期从
|
||||||
<el-input-number v-model='cycle01' :min="1" :max="11" /> -
|
<el-input-number v-model='cycle01' :min="1" :max="11" /> -
|
||||||
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="12" /> 月
|
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="12" /> 月
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="3">
|
<el-radio v-model='radioValue' :label="3">
|
||||||
从
|
从
|
||||||
<el-input-number v-model='average01' :min="1" :max="11" /> 月开始,每
|
<el-input-number v-model='average01' :min="1" :max="11" /> 月开始,每
|
||||||
<el-input-number v-model='average02' :min="1" :max="12 - average01 || 0" /> 月月执行一次
|
<el-input-number v-model='average02' :min="1" :max="12 - average01" /> 月月执行一次
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="4">
|
<el-radio v-model='radioValue' :label="4">
|
||||||
指定
|
指定
|
||||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
|
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="8">
|
||||||
<el-option v-for="item in 12" :key="item" :value="item">{{item}}</el-option>
|
<el-option v-for="item in monthList" :key="item.key" :label="item.value" :value="item.key" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
const emit = defineEmits(['update'])
|
||||||
data() {
|
const props = defineProps({
|
||||||
return {
|
cron: {
|
||||||
radioValue: 1,
|
type: Object,
|
||||||
cycle01: 1,
|
default: {
|
||||||
cycle02: 2,
|
second: "*",
|
||||||
average01: 1,
|
min: "*",
|
||||||
average02: 1,
|
hour: "*",
|
||||||
checkboxList: [],
|
day: "*",
|
||||||
checkNum: this.check
|
month: "*",
|
||||||
}
|
week: "?",
|
||||||
},
|
year: "",
|
||||||
name: 'crontab-month',
|
}
|
||||||
props: ['check', 'cron'],
|
},
|
||||||
methods: {
|
check: {
|
||||||
// 单选按钮值变化时
|
type: Function,
|
||||||
radioChange() {
|
default: () => {
|
||||||
switch (this.radioValue) {
|
}
|
||||||
case 1:
|
}
|
||||||
this.$emit('update', 'month', '*');
|
})
|
||||||
break;
|
const radioValue = ref(1)
|
||||||
case 2:
|
const cycle01 = ref(1)
|
||||||
this.$emit('update', 'month', this.cycleTotal);
|
const cycle02 = ref(2)
|
||||||
break;
|
const average01 = ref(1)
|
||||||
case 3:
|
const average02 = ref(1)
|
||||||
this.$emit('update', 'month', this.averageTotal);
|
const checkboxList = ref([])
|
||||||
break;
|
const checkCopy = ref([1])
|
||||||
case 4:
|
const monthList = ref([
|
||||||
this.$emit('update', 'month', this.checkboxString);
|
{key: 1, value: '一月'},
|
||||||
break;
|
{key: 2, value: '二月'},
|
||||||
}
|
{key: 3, value: '三月'},
|
||||||
},
|
{key: 4, value: '四月'},
|
||||||
// 周期两个值变化时
|
{key: 5, value: '五月'},
|
||||||
cycleChange() {
|
{key: 6, value: '六月'},
|
||||||
if (this.radioValue == '2') {
|
{key: 7, value: '七月'},
|
||||||
this.$emit('update', 'month', this.cycleTotal);
|
{key: 8, value: '八月'},
|
||||||
}
|
{key: 9, value: '九月'},
|
||||||
},
|
{key: 10, value: '十月'},
|
||||||
// 平均两个值变化时
|
{key: 11, value: '十一月'},
|
||||||
averageChange() {
|
{key: 12, value: '十二月'}
|
||||||
if (this.radioValue == '3') {
|
])
|
||||||
this.$emit('update', 'month', this.averageTotal);
|
const cycleTotal = computed(() => {
|
||||||
}
|
cycle01.value = props.check(cycle01.value, 1, 11)
|
||||||
},
|
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 12)
|
||||||
// checkbox值变化时
|
return cycle01.value + '-' + cycle02.value
|
||||||
checkboxChange() {
|
})
|
||||||
if (this.radioValue == '4') {
|
const averageTotal = computed(() => {
|
||||||
this.$emit('update', 'month', this.checkboxString);
|
average01.value = props.check(average01.value, 1, 11)
|
||||||
}
|
average02.value = props.check(average02.value, 1, 12 - average01.value)
|
||||||
}
|
return average01.value + '/' + average02.value
|
||||||
},
|
})
|
||||||
watch: {
|
const checkboxString = computed(() => {
|
||||||
'radioValue': 'radioChange',
|
return checkboxList.value.join(',')
|
||||||
'cycleTotal': 'cycleChange',
|
})
|
||||||
'averageTotal': 'averageChange',
|
watch(() => props.cron.month, value => changeRadioValue(value))
|
||||||
'checkboxString': 'checkboxChange'
|
watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
|
||||||
},
|
function changeRadioValue(value) {
|
||||||
computed: {
|
if (value === '*') {
|
||||||
// 计算两个周期值
|
radioValue.value = 1
|
||||||
cycleTotal: function () {
|
} else if (value.indexOf('-') > -1) {
|
||||||
const cycle01 = this.checkNum(this.cycle01, 1, 11)
|
const indexArr = value.split('-')
|
||||||
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 12)
|
cycle01.value = Number(indexArr[0])
|
||||||
return cycle01 + '-' + cycle02;
|
cycle02.value = Number(indexArr[1])
|
||||||
},
|
radioValue.value = 2
|
||||||
// 计算平均用到的值
|
} else if (value.indexOf('/') > -1) {
|
||||||
averageTotal: function () {
|
const indexArr = value.split('/')
|
||||||
const average01 = this.checkNum(this.average01, 1, 11)
|
average01.value = Number(indexArr[0])
|
||||||
const average02 = this.checkNum(this.average02, 1, 12 - average01 || 0)
|
average02.value = Number(indexArr[1])
|
||||||
return average01 + '/' + average02;
|
radioValue.value = 3
|
||||||
},
|
} else {
|
||||||
// 计算勾选的checkbox值合集
|
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
|
||||||
checkboxString: function () {
|
radioValue.value = 4
|
||||||
let str = this.checkboxList.join();
|
}
|
||||||
return str == '' ? '*' : str;
|
}
|
||||||
}
|
function onRadioChange() {
|
||||||
}
|
switch (radioValue.value) {
|
||||||
}
|
case 1:
|
||||||
</script>
|
emit('update', 'month', '*', 'month')
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
emit('update', 'month', cycleTotal.value, 'month')
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
emit('update', 'month', averageTotal.value, 'month')
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
if (checkboxList.value.length === 0) {
|
||||||
|
checkboxList.value.push(checkCopy.value[0])
|
||||||
|
} else {
|
||||||
|
checkCopy.value = checkboxList.value
|
||||||
|
}
|
||||||
|
emit('update', 'month', checkboxString.value, 'month')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.el-input-number--small, .el-select, .el-select--small {
|
||||||
|
margin: 0 0.2rem;
|
||||||
|
}
|
||||||
|
.el-select, .el-select--small {
|
||||||
|
width: 18.8rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,117 +1,128 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size="small">
|
<el-form>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="1">
|
<el-radio v-model='radioValue' :label="1">
|
||||||
秒,允许的通配符[, - * /]
|
秒,允许的通配符[, - * /]
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="2">
|
<el-radio v-model='radioValue' :label="2">
|
||||||
周期从
|
周期从
|
||||||
<el-input-number v-model='cycle01' :min="0" :max="58" /> -
|
<el-input-number v-model='cycle01' :min="0" :max="58" /> -
|
||||||
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 秒
|
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="59" /> 秒
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="3">
|
<el-radio v-model='radioValue' :label="3">
|
||||||
从
|
从
|
||||||
<el-input-number v-model='average01' :min="0" :max="58" /> 秒开始,每
|
<el-input-number v-model='average01' :min="0" :max="58" /> 秒开始,每
|
||||||
<el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 秒执行一次
|
<el-input-number v-model='average02' :min="1" :max="59 - average01" /> 秒执行一次
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="4">
|
<el-radio v-model='radioValue' :label="4">
|
||||||
指定
|
指定
|
||||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
|
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
|
||||||
<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
|
<el-option v-for="item in 60" :key="item" :label="item - 1" :value="item - 1" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
const emit = defineEmits(['update'])
|
||||||
data() {
|
const props = defineProps({
|
||||||
return {
|
cron: {
|
||||||
radioValue: 1,
|
type: Object,
|
||||||
cycle01: 1,
|
default: {
|
||||||
cycle02: 2,
|
second: "*",
|
||||||
average01: 0,
|
min: "*",
|
||||||
average02: 1,
|
hour: "*",
|
||||||
checkboxList: [],
|
day: "*",
|
||||||
checkNum: this.$options.propsData.check
|
month: "*",
|
||||||
}
|
week: "?",
|
||||||
},
|
year: "",
|
||||||
name: 'crontab-second',
|
}
|
||||||
props: ['check', 'radioParent'],
|
},
|
||||||
methods: {
|
check: {
|
||||||
// 单选按钮值变化时
|
type: Function,
|
||||||
radioChange() {
|
default: () => {
|
||||||
switch (this.radioValue) {
|
}
|
||||||
case 1:
|
}
|
||||||
this.$emit('update', 'second', '*', 'second');
|
})
|
||||||
break;
|
const radioValue = ref(1)
|
||||||
case 2:
|
const cycle01 = ref(0)
|
||||||
this.$emit('update', 'second', this.cycleTotal);
|
const cycle02 = ref(1)
|
||||||
break;
|
const average01 = ref(0)
|
||||||
case 3:
|
const average02 = ref(1)
|
||||||
this.$emit('update', 'second', this.averageTotal);
|
const checkboxList = ref([])
|
||||||
break;
|
const checkCopy = ref([0])
|
||||||
case 4:
|
const cycleTotal = computed(() => {
|
||||||
this.$emit('update', 'second', this.checkboxString);
|
cycle01.value = props.check(cycle01.value, 0, 58)
|
||||||
break;
|
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 59)
|
||||||
}
|
return cycle01.value + '-' + cycle02.value
|
||||||
},
|
})
|
||||||
// 周期两个值变化时
|
const averageTotal = computed(() => {
|
||||||
cycleChange() {
|
average01.value = props.check(average01.value, 0, 58)
|
||||||
if (this.radioValue == '2') {
|
average02.value = props.check(average02.value, 1, 59 - average01.value)
|
||||||
this.$emit('update', 'second', this.cycleTotal);
|
return average01.value + '/' + average02.value
|
||||||
}
|
})
|
||||||
},
|
const checkboxString = computed(() => {
|
||||||
// 平均两个值变化时
|
return checkboxList.value.join(',')
|
||||||
averageChange() {
|
})
|
||||||
if (this.radioValue == '3') {
|
watch(() => props.cron.second, value => changeRadioValue(value))
|
||||||
this.$emit('update', 'second', this.averageTotal);
|
watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
|
||||||
}
|
function changeRadioValue(value) {
|
||||||
},
|
if (value === '*') {
|
||||||
// checkbox值变化时
|
radioValue.value = 1
|
||||||
checkboxChange() {
|
} else if (value.indexOf('-') > -1) {
|
||||||
if (this.radioValue == '4') {
|
const indexArr = value.split('-')
|
||||||
this.$emit('update', 'second', this.checkboxString);
|
cycle01.value = Number(indexArr[0])
|
||||||
}
|
cycle02.value = Number(indexArr[1])
|
||||||
}
|
radioValue.value = 2
|
||||||
},
|
} else if (value.indexOf('/') > -1) {
|
||||||
watch: {
|
const indexArr = value.split('/')
|
||||||
'radioValue': 'radioChange',
|
average01.value = Number(indexArr[0])
|
||||||
'cycleTotal': 'cycleChange',
|
average02.value = Number(indexArr[1])
|
||||||
'averageTotal': 'averageChange',
|
radioValue.value = 3
|
||||||
'checkboxString': 'checkboxChange',
|
} else {
|
||||||
radioParent() {
|
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
|
||||||
this.radioValue = this.radioParent
|
radioValue.value = 4
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
computed: {
|
// 单选按钮值变化时
|
||||||
// 计算两个周期值
|
function onRadioChange() {
|
||||||
cycleTotal: function () {
|
switch (radioValue.value) {
|
||||||
const cycle01 = this.checkNum(this.cycle01, 0, 58)
|
case 1:
|
||||||
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59)
|
emit('update', 'second', '*', 'second')
|
||||||
return cycle01 + '-' + cycle02;
|
break
|
||||||
},
|
case 2:
|
||||||
// 计算平均用到的值
|
emit('update', 'second', cycleTotal.value, 'second')
|
||||||
averageTotal: function () {
|
break
|
||||||
const average01 = this.checkNum(this.average01, 0, 58)
|
case 3:
|
||||||
const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0)
|
emit('update', 'second', averageTotal.value, 'second')
|
||||||
return average01 + '/' + average02;
|
break
|
||||||
},
|
case 4:
|
||||||
// 计算勾选的checkbox值合集
|
if (checkboxList.value.length === 0) {
|
||||||
checkboxString: function () {
|
checkboxList.value.push(checkCopy.value[0])
|
||||||
let str = this.checkboxList.join();
|
} else {
|
||||||
return str == '' ? '*' : str;
|
checkCopy.value = checkboxList.value
|
||||||
}
|
}
|
||||||
}
|
emit('update', 'second', checkboxString.value, 'second')
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.el-input-number--small, .el-select, .el-select--small {
|
||||||
|
margin: 0 0.2rem;
|
||||||
|
}
|
||||||
|
.el-select, .el-select--small {
|
||||||
|
width: 18.8rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,202 +1,197 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size='small'>
|
<el-form>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="1">
|
<el-radio v-model='radioValue' :label="1">
|
||||||
周,允许的通配符[, - * ? / L #]
|
周,允许的通配符[, - * ? / L #]
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="2">
|
<el-radio v-model='radioValue' :label="2">
|
||||||
不指定
|
不指定
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="3">
|
<el-radio v-model='radioValue' :label="3">
|
||||||
周期从星期
|
周期从
|
||||||
<el-select clearable v-model="cycle01">
|
<el-select clearable v-model="cycle01">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="(item,index) of weekList"
|
v-for="(item,index) of weekList"
|
||||||
:key="index"
|
:key="index"
|
||||||
:label="item.value"
|
:label="item.value"
|
||||||
:value="item.key"
|
:value="item.key"
|
||||||
:disabled="item.key === 1"
|
:disabled="item.key === 7"
|
||||||
>{{item.value}}</el-option>
|
>{{item.value}}</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
-
|
-
|
||||||
<el-select clearable v-model="cycle02">
|
<el-select clearable v-model="cycle02">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="(item,index) of weekList"
|
v-for="(item,index) of weekList"
|
||||||
:key="index"
|
:key="index"
|
||||||
:label="item.value"
|
:label="item.value"
|
||||||
:value="item.key"
|
:value="item.key"
|
||||||
:disabled="item.key < cycle01 && item.key !== 1"
|
:disabled="item.key <= cycle01"
|
||||||
>{{item.value}}</el-option>
|
>{{item.value}}</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="4">
|
<el-radio v-model='radioValue' :label="4">
|
||||||
第
|
第
|
||||||
<el-input-number v-model='average01' :min="1" :max="4" /> 周的星期
|
<el-input-number v-model='average01' :min="1" :max="4" /> 周的
|
||||||
<el-select clearable v-model="average02">
|
<el-select clearable v-model="average02">
|
||||||
<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option>
|
<el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="5">
|
<el-radio v-model='radioValue' :label="5">
|
||||||
本月最后一个星期
|
本月最后一个
|
||||||
<el-select clearable v-model="weekday">
|
<el-select clearable v-model="weekday">
|
||||||
<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option>
|
<el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio v-model='radioValue' :label="6">
|
<el-radio v-model='radioValue' :label="6">
|
||||||
指定
|
指定
|
||||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
|
<el-select class="multiselect" clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="6">
|
||||||
<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="String(item.key)">{{item.value}}</el-option>
|
<el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
const emit = defineEmits(['update'])
|
||||||
data() {
|
const props = defineProps({
|
||||||
return {
|
cron: {
|
||||||
radioValue: 2,
|
type: Object,
|
||||||
weekday: 2,
|
default: {
|
||||||
cycle01: 2,
|
second: "*",
|
||||||
cycle02: 3,
|
min: "*",
|
||||||
average01: 1,
|
hour: "*",
|
||||||
average02: 2,
|
day: "*",
|
||||||
checkboxList: [],
|
month: "*",
|
||||||
weekList: [
|
week: "?",
|
||||||
{
|
year: ""
|
||||||
key: 2,
|
}
|
||||||
value: '星期一'
|
},
|
||||||
},
|
check: {
|
||||||
{
|
type: Function,
|
||||||
key: 3,
|
default: () => {
|
||||||
value: '星期二'
|
}
|
||||||
},
|
}
|
||||||
{
|
})
|
||||||
key: 4,
|
const radioValue = ref(2)
|
||||||
value: '星期三'
|
const cycle01 = ref(2)
|
||||||
},
|
const cycle02 = ref(3)
|
||||||
{
|
const average01 = ref(1)
|
||||||
key: 5,
|
const average02 = ref(2)
|
||||||
value: '星期四'
|
const weekday = ref(2)
|
||||||
},
|
const checkboxList = ref([])
|
||||||
{
|
const checkCopy = ref([2])
|
||||||
key: 6,
|
const weekList = ref([
|
||||||
value: '星期五'
|
{key: 1, value: '星期日'},
|
||||||
},
|
{key: 2, value: '星期一'},
|
||||||
{
|
{key: 3, value: '星期二'},
|
||||||
key: 7,
|
{key: 4, value: '星期三'},
|
||||||
value: '星期六'
|
{key: 5, value: '星期四'},
|
||||||
},
|
{key: 6, value: '星期五'},
|
||||||
{
|
{key: 7, value: '星期六'}
|
||||||
key: 1,
|
])
|
||||||
value: '星期日'
|
const cycleTotal = computed(() => {
|
||||||
}
|
cycle01.value = props.check(cycle01.value, 1, 6)
|
||||||
],
|
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 7)
|
||||||
checkNum: this.$options.propsData.check
|
return cycle01.value + '-' + cycle02.value
|
||||||
}
|
})
|
||||||
},
|
const averageTotal = computed(() => {
|
||||||
name: 'crontab-week',
|
average01.value = props.check(average01.value, 1, 4)
|
||||||
props: ['check', 'cron'],
|
average02.value = props.check(average02.value, 1, 7)
|
||||||
methods: {
|
return average02.value + '#' + average01.value
|
||||||
// 单选按钮值变化时
|
})
|
||||||
radioChange() {
|
const weekdayTotal = computed(() => {
|
||||||
if (this.radioValue !== 2 && this.cron.day !== '?') {
|
weekday.value = props.check(weekday.value, 1, 7)
|
||||||
this.$emit('update', 'day', '?', 'week');
|
return weekday.value + 'L'
|
||||||
}
|
})
|
||||||
switch (this.radioValue) {
|
const checkboxString = computed(() => {
|
||||||
case 1:
|
return checkboxList.value.join(',')
|
||||||
this.$emit('update', 'week', '*');
|
})
|
||||||
break;
|
watch(() => props.cron.week, value => changeRadioValue(value))
|
||||||
case 2:
|
watch([radioValue, cycleTotal, averageTotal, weekdayTotal, checkboxString], () => onRadioChange())
|
||||||
this.$emit('update', 'week', '?');
|
function changeRadioValue(value) {
|
||||||
break;
|
if (value === "*") {
|
||||||
case 3:
|
radioValue.value = 1
|
||||||
this.$emit('update', 'week', this.cycleTotal);
|
} else if (value === "?") {
|
||||||
break;
|
radioValue.value = 2
|
||||||
case 4:
|
} else if (value.indexOf("-") > -1) {
|
||||||
this.$emit('update', 'week', this.averageTotal);
|
const indexArr = value.split('-')
|
||||||
break;
|
cycle01.value = Number(indexArr[0])
|
||||||
case 5:
|
cycle02.value = Number(indexArr[1])
|
||||||
this.$emit('update', 'week', this.weekdayCheck + 'L');
|
radioValue.value = 3
|
||||||
break;
|
} else if (value.indexOf("#") > -1) {
|
||||||
case 6:
|
const indexArr = value.split('#')
|
||||||
this.$emit('update', 'week', this.checkboxString);
|
average01.value = Number(indexArr[1])
|
||||||
break;
|
average02.value = Number(indexArr[0])
|
||||||
}
|
radioValue.value = 4
|
||||||
},
|
} else if (value.indexOf("L") > -1) {
|
||||||
|
const indexArr = value.split("L")
|
||||||
// 周期两个值变化时
|
weekday.value = Number(indexArr[0])
|
||||||
cycleChange() {
|
radioValue.value = 5
|
||||||
if (this.radioValue == '3') {
|
} else {
|
||||||
this.$emit('update', 'week', this.cycleTotal);
|
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
|
||||||
}
|
radioValue.value = 6
|
||||||
},
|
}
|
||||||
// 平均两个值变化时
|
}
|
||||||
averageChange() {
|
function onRadioChange() {
|
||||||
if (this.radioValue == '4') {
|
if (radioValue.value === 2 && props.cron.day === '?') {
|
||||||
this.$emit('update', 'week', this.averageTotal);
|
emit('update', 'day', '*', 'week')
|
||||||
}
|
}
|
||||||
},
|
if (radioValue.value !== 2 && props.cron.day !== '?') {
|
||||||
// 最近工作日值变化时
|
emit('update', 'day', '?', 'week')
|
||||||
weekdayChange() {
|
}
|
||||||
if (this.radioValue == '5') {
|
switch (radioValue.value) {
|
||||||
this.$emit('update', 'week', this.weekday + 'L');
|
case 1:
|
||||||
}
|
emit('update', 'week', '*', 'week')
|
||||||
},
|
break
|
||||||
// checkbox值变化时
|
case 2:
|
||||||
checkboxChange() {
|
emit('update', 'week', '?', 'week')
|
||||||
if (this.radioValue == '6') {
|
break
|
||||||
this.$emit('update', 'week', this.checkboxString);
|
case 3:
|
||||||
}
|
emit('update', 'week', cycleTotal.value, 'week')
|
||||||
},
|
break
|
||||||
},
|
case 4:
|
||||||
watch: {
|
emit('update', 'week', averageTotal.value, 'week')
|
||||||
'radioValue': 'radioChange',
|
break
|
||||||
'cycleTotal': 'cycleChange',
|
case 5:
|
||||||
'averageTotal': 'averageChange',
|
emit('update', 'week', weekdayTotal.value, 'week')
|
||||||
'weekdayCheck': 'weekdayChange',
|
break
|
||||||
'checkboxString': 'checkboxChange',
|
case 6:
|
||||||
},
|
if (checkboxList.value.length === 0) {
|
||||||
computed: {
|
checkboxList.value.push(checkCopy.value[0])
|
||||||
// 计算两个周期值
|
} else {
|
||||||
cycleTotal: function () {
|
checkCopy.value = checkboxList.value
|
||||||
this.cycle01 = this.checkNum(this.cycle01, 1, 7)
|
}
|
||||||
this.cycle02 = this.checkNum(this.cycle02, 1, 7)
|
emit('update', 'week', checkboxString.value, 'week')
|
||||||
return this.cycle01 + '-' + this.cycle02;
|
break
|
||||||
},
|
}
|
||||||
// 计算平均用到的值
|
|
||||||
averageTotal: function () {
|
|
||||||
this.average01 = this.checkNum(this.average01, 1, 4)
|
|
||||||
this.average02 = this.checkNum(this.average02, 1, 7)
|
|
||||||
return this.average02 + '#' + this.average01;
|
|
||||||
},
|
|
||||||
// 最近的工作日(格式)
|
|
||||||
weekdayCheck: function () {
|
|
||||||
this.weekday = this.checkNum(this.weekday, 1, 7)
|
|
||||||
return this.weekday;
|
|
||||||
},
|
|
||||||
// 计算勾选的checkbox值合集
|
|
||||||
checkboxString: function () {
|
|
||||||
let str = this.checkboxList.join();
|
|
||||||
return str == '' ? '*' : str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.el-input-number--small, .el-select, .el-select--small {
|
||||||
|
margin: 0 0.5rem;
|
||||||
|
}
|
||||||
|
.el-select, .el-select--small {
|
||||||
|
width: 8rem;
|
||||||
|
}
|
||||||
|
.el-select.multiselect, .el-select--small.multiselect {
|
||||||
|
width: 17.8rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,131 +1,149 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form size="small">
|
<el-form>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio :label="1" v-model='radioValue'>
|
<el-radio :label="1" v-model='radioValue'>
|
||||||
不填,允许的通配符[, - * /]
|
不填,允许的通配符[, - * /]
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio :label="2" v-model='radioValue'>
|
<el-radio :label="2" v-model='radioValue'>
|
||||||
每年
|
每年
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio :label="3" v-model='radioValue'>
|
<el-radio :label="3" v-model='radioValue'>
|
||||||
周期从
|
周期从
|
||||||
<el-input-number v-model='cycle01' :min='fullYear' :max="2098" /> -
|
<el-input-number v-model='cycle01' :min='fullYear' :max="2098"/> -
|
||||||
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : fullYear + 1" :max="2099" />
|
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : fullYear + 1" :max="2099"/>
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio :label="4" v-model='radioValue'>
|
<el-radio :label="4" v-model='radioValue'>
|
||||||
从
|
从
|
||||||
<el-input-number v-model='average01' :min='fullYear' :max="2098"/> 年开始,每
|
<el-input-number v-model='average01' :min='fullYear' :max="2098"/> 年开始,每
|
||||||
<el-input-number v-model='average02' :min="1" :max="2099 - average01 || fullYear" /> 年执行一次
|
<el-input-number v-model='average02' :min="1" :max="2099 - average01 || fullYear"/> 年执行一次
|
||||||
</el-radio>
|
</el-radio>
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-radio :label="5" v-model='radioValue'>
|
<el-radio :label="5" v-model='radioValue'>
|
||||||
指定
|
指定
|
||||||
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple>
|
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="8">
|
||||||
<el-option v-for="item in 9" :key="item" :value="item - 1 + fullYear" :label="item -1 + fullYear" />
|
<el-option v-for="item in 9" :key="item" :value="item - 1 + fullYear" :label="item -1 + fullYear" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
const emit = defineEmits(['update'])
|
||||||
data() {
|
const props = defineProps({
|
||||||
return {
|
cron: {
|
||||||
fullYear: 0,
|
type: Object,
|
||||||
radioValue: 1,
|
default: {
|
||||||
cycle01: 0,
|
second: "*",
|
||||||
cycle02: 0,
|
min: "*",
|
||||||
average01: 0,
|
hour: "*",
|
||||||
average02: 1,
|
day: "*",
|
||||||
checkboxList: [],
|
month: "*",
|
||||||
checkNum: this.$options.propsData.check
|
week: "?",
|
||||||
}
|
year: ""
|
||||||
},
|
}
|
||||||
name: 'crontab-year',
|
},
|
||||||
props: ['check', 'month', 'cron'],
|
check: {
|
||||||
methods: {
|
type: Function,
|
||||||
// 单选按钮值变化时
|
default: () => {
|
||||||
radioChange() {
|
}
|
||||||
switch (this.radioValue) {
|
}
|
||||||
case 1:
|
})
|
||||||
this.$emit('update', 'year', '');
|
const fullYear = ref(0)
|
||||||
break;
|
const maxFullYear = ref(0)
|
||||||
case 2:
|
const radioValue = ref(1)
|
||||||
this.$emit('update', 'year', '*');
|
const cycle01 = ref(0)
|
||||||
break;
|
const cycle02 = ref(0)
|
||||||
case 3:
|
const average01 = ref(0)
|
||||||
this.$emit('update', 'year', this.cycleTotal);
|
const average02 = ref(1)
|
||||||
break;
|
const checkboxList = ref([])
|
||||||
case 4:
|
const checkCopy = ref([])
|
||||||
this.$emit('update', 'year', this.averageTotal);
|
const cycleTotal = computed(() => {
|
||||||
break;
|
cycle01.value = props.check(cycle01.value, fullYear.value, maxFullYear.value - 1)
|
||||||
case 5:
|
cycle02.value = props.check(cycle02.value, cycle01.value + 1, maxFullYear.value)
|
||||||
this.$emit('update', 'year', this.checkboxString);
|
return cycle01.value + '-' + cycle02.value
|
||||||
break;
|
})
|
||||||
}
|
const averageTotal = computed(() => {
|
||||||
},
|
average01.value = props.check(average01.value, fullYear.value, maxFullYear.value - 1)
|
||||||
// 周期两个值变化时
|
average02.value = props.check(average02.value, 1, 10)
|
||||||
cycleChange() {
|
return average01.value + '/' + average02.value
|
||||||
if (this.radioValue == '3') {
|
})
|
||||||
this.$emit('update', 'year', this.cycleTotal);
|
const checkboxString = computed(() => {
|
||||||
}
|
return checkboxList.value.join(',')
|
||||||
},
|
})
|
||||||
// 平均两个值变化时
|
watch(() => props.cron.year, value => changeRadioValue(value))
|
||||||
averageChange() {
|
watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
|
||||||
if (this.radioValue == '4') {
|
function changeRadioValue(value) {
|
||||||
this.$emit('update', 'year', this.averageTotal);
|
if (value === '') {
|
||||||
}
|
radioValue.value = 1
|
||||||
},
|
} else if (value === "*") {
|
||||||
// checkbox值变化时
|
radioValue.value = 2
|
||||||
checkboxChange() {
|
} else if (value.indexOf("-") > -1) {
|
||||||
if (this.radioValue == '5') {
|
const indexArr = value.split('-')
|
||||||
this.$emit('update', 'year', this.checkboxString);
|
cycle01.value = Number(indexArr[0])
|
||||||
}
|
cycle02.value = Number(indexArr[1])
|
||||||
}
|
radioValue.value = 3
|
||||||
},
|
} else if (value.indexOf("/") > -1) {
|
||||||
watch: {
|
const indexArr = value.split('/')
|
||||||
'radioValue': 'radioChange',
|
average01.value = Number(indexArr[1])
|
||||||
'cycleTotal': 'cycleChange',
|
average02.value = Number(indexArr[0])
|
||||||
'averageTotal': 'averageChange',
|
radioValue.value = 4
|
||||||
'checkboxString': 'checkboxChange'
|
} else {
|
||||||
},
|
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
|
||||||
computed: {
|
radioValue.value = 5
|
||||||
// 计算两个周期值
|
}
|
||||||
cycleTotal: function () {
|
|
||||||
const cycle01 = this.checkNum(this.cycle01, this.fullYear, 2098)
|
|
||||||
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : this.fullYear + 1, 2099)
|
|
||||||
return cycle01 + '-' + cycle02;
|
|
||||||
},
|
|
||||||
// 计算平均用到的值
|
|
||||||
averageTotal: function () {
|
|
||||||
const average01 = this.checkNum(this.average01, this.fullYear, 2098)
|
|
||||||
const average02 = this.checkNum(this.average02, 1, 2099 - average01 || this.fullYear)
|
|
||||||
return average01 + '/' + average02;
|
|
||||||
},
|
|
||||||
// 计算勾选的checkbox值合集
|
|
||||||
checkboxString: function () {
|
|
||||||
let str = this.checkboxList.join();
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted: function () {
|
|
||||||
// 仅获取当前年份
|
|
||||||
this.fullYear = Number(new Date().getFullYear());
|
|
||||||
this.cycle01 = this.fullYear
|
|
||||||
this.average01 = this.fullYear
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
function onRadioChange() {
|
||||||
|
switch (radioValue.value) {
|
||||||
|
case 1:
|
||||||
|
emit('update', 'year', '', 'year')
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
emit('update', 'year', '*', 'year')
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
emit('update', 'year', cycleTotal.value, 'year')
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
emit('update', 'year', averageTotal.value, 'year')
|
||||||
|
break
|
||||||
|
case 5:
|
||||||
|
if (checkboxList.value.length === 0) {
|
||||||
|
checkboxList.value.push(checkCopy.value[0])
|
||||||
|
} else {
|
||||||
|
checkCopy.value = checkboxList.value
|
||||||
|
}
|
||||||
|
emit('update', 'year', checkboxString.value, 'year')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
fullYear.value = Number(new Date().getFullYear())
|
||||||
|
maxFullYear.value = fullYear.value + 10
|
||||||
|
cycle01.value = fullYear.value
|
||||||
|
cycle02.value = cycle01.value + 1
|
||||||
|
average01.value = fullYear.value
|
||||||
|
checkCopy.value = [fullYear.value]
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.el-input-number--small, .el-select, .el-select--small {
|
||||||
|
margin: 0 0.2rem;
|
||||||
|
}
|
||||||
|
.el-select, .el-select--small {
|
||||||
|
width: 18.8rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import Vue from 'vue'
|
|
||||||
import store from '@/store'
|
|
||||||
import DataDict from '@/utils/dict'
|
|
||||||
import { getDicts as getDicts } from '@/api/system/dict/data'
|
|
||||||
|
|
||||||
function searchDictByKey(dict, key) {
|
|
||||||
if (key == null && key == "") {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
for (let i = 0; i < dict.length; i++) {
|
|
||||||
if (dict[i].key == key) {
|
|
||||||
return dict[i].value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function install() {
|
|
||||||
Vue.use(DataDict, {
|
|
||||||
metas: {
|
|
||||||
'*': {
|
|
||||||
labelField: 'dictLabel',
|
|
||||||
valueField: 'dictValue',
|
|
||||||
request(dictMeta) {
|
|
||||||
const storeDict = searchDictByKey(store.getters.dict, dictMeta.type)
|
|
||||||
if (storeDict) {
|
|
||||||
return new Promise(resolve => { resolve(storeDict) })
|
|
||||||
} else {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
getDicts(dictMeta.type).then(res => {
|
|
||||||
store.dispatch('dict/setDict', { key: dictMeta.type, value: res.data })
|
|
||||||
resolve(res.data)
|
|
||||||
}).catch(error => {
|
|
||||||
reject(error)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
install,
|
|
||||||
}
|
|
||||||
@@ -1,89 +1,82 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<template v-for="(item, index) in options">
|
<template v-for="(item, index) in options">
|
||||||
<template v-if="values.includes(item.value)">
|
<template v-if="values.includes(item.value)">
|
||||||
<span
|
<span
|
||||||
v-if="(item.raw.listClass == 'default' || item.raw.listClass == '') && (item.raw.cssClass == '' || item.raw.cssClass == null)"
|
v-if="(item.elTagType == 'default' || item.elTagType == '') && (item.elTagClass == '' || item.elTagClass == null)"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
:index="index"
|
:index="index"
|
||||||
:class="item.raw.cssClass"
|
:class="item.elTagClass"
|
||||||
>{{ item.label + ' ' }}</span
|
>{{ item.label + " " }}</span>
|
||||||
>
|
<el-tag
|
||||||
<el-tag
|
v-else
|
||||||
v-else
|
:disable-transitions="true"
|
||||||
:disable-transitions="true"
|
:key="item.value + ''"
|
||||||
:key="item.value"
|
:index="index"
|
||||||
:index="index"
|
:type="item.elTagType === 'primary' ? '' : item.elTagType"
|
||||||
:type="item.raw.listClass == 'primary' ? '' : item.raw.listClass"
|
:class="item.elTagClass"
|
||||||
:class="item.raw.cssClass"
|
>{{ item.label + " " }}</el-tag>
|
||||||
>
|
</template>
|
||||||
{{ item.label + ' ' }}
|
</template>
|
||||||
</el-tag>
|
<template v-if="unmatch && showValue">
|
||||||
</template>
|
{{ unmatchArray | handleArray }}
|
||||||
</template>
|
</template>
|
||||||
<template v-if="unmatch && showValue">
|
</div>
|
||||||
{{ unmatchArray | handleArray }}
|
</template>
|
||||||
</template>
|
|
||||||
</div>
|
<script setup>
|
||||||
</template>
|
// 记录未匹配的项
|
||||||
|
const unmatchArray = ref([]);
|
||||||
<script>
|
|
||||||
export default {
|
const props = defineProps({
|
||||||
name: "DictTag",
|
// 数据
|
||||||
props: {
|
options: {
|
||||||
options: {
|
type: Array,
|
||||||
type: Array,
|
default: null,
|
||||||
default: null,
|
},
|
||||||
},
|
// 当前的值
|
||||||
value: [Number, String, Array],
|
value: [Number, String, Array],
|
||||||
// 当未找到匹配的数据时,显示value
|
// 当未找到匹配的数据时,显示value
|
||||||
showValue: {
|
showValue: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
separator: {
|
separator: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ","
|
default: ",",
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
data() {
|
|
||||||
return {
|
const values = computed(() => {
|
||||||
unmatchArray: [], // 记录未匹配的项
|
if (props.value === null || typeof props.value === 'undefined' || props.value === '') return [];
|
||||||
}
|
return Array.isArray(props.value) ? props.value.map(item => '' + item) : String(props.value).split(props.separator);
|
||||||
},
|
});
|
||||||
computed: {
|
|
||||||
values() {
|
const unmatch = computed(() => {
|
||||||
if (this.value === null || typeof this.value === 'undefined' || this.value === '') return []
|
unmatchArray.value = [];
|
||||||
return Array.isArray(this.value) ? this.value.map(item => '' + item) : String(this.value).split(this.separator)
|
// 没有value不显示
|
||||||
},
|
if (props.value === null || typeof props.value === 'undefined' || props.value === '' || props.options.length === 0) return false
|
||||||
unmatch() {
|
// 传入值为数组
|
||||||
this.unmatchArray = []
|
let unmatch = false // 添加一个标志来判断是否有未匹配项
|
||||||
// 没有value不显示
|
values.value.forEach(item => {
|
||||||
if (this.value === null || typeof this.value === 'undefined' || this.value === '' || this.options.length === 0) return false
|
if (!props.options.some(v => v.value === item)) {
|
||||||
// 传入值为数组
|
unmatchArray.value.push(item)
|
||||||
let unmatch = false // 添加一个标志来判断是否有未匹配项
|
unmatch = true // 如果有未匹配项,将标志设置为true
|
||||||
this.values.forEach(item => {
|
}
|
||||||
if (!this.options.some(v => v.value === item)) {
|
})
|
||||||
this.unmatchArray.push(item)
|
return unmatch // 返回标志的值
|
||||||
unmatch = true // 如果有未匹配项,将标志设置为true
|
});
|
||||||
}
|
|
||||||
})
|
function handleArray(array) {
|
||||||
return unmatch // 返回标志的值
|
if (array.length === 0) return "";
|
||||||
},
|
return array.reduce((pre, cur) => {
|
||||||
|
return pre + " " + cur;
|
||||||
},
|
});
|
||||||
filters: {
|
}
|
||||||
handleArray(array) {
|
</script>
|
||||||
if (array.length === 0) return '';
|
|
||||||
return array.reduce((pre, cur) => {
|
<style scoped>
|
||||||
return pre + ' ' + cur;
|
.el-tag + .el-tag {
|
||||||
})
|
margin-left: 10px;
|
||||||
},
|
}
|
||||||
}
|
</style>
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style scoped>
|
|
||||||
.el-tag + .el-tag {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,274 +1,251 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-upload
|
<el-upload
|
||||||
:action="uploadUrl"
|
:action="uploadUrl"
|
||||||
:before-upload="handleBeforeUpload"
|
:before-upload="handleBeforeUpload"
|
||||||
:on-success="handleUploadSuccess"
|
:on-success="handleUploadSuccess"
|
||||||
:on-error="handleUploadError"
|
:on-error="handleUploadError"
|
||||||
name="file"
|
name="file"
|
||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
style="display: none"
|
class="editor-img-uploader"
|
||||||
ref="upload"
|
v-if="type == 'url'"
|
||||||
v-if="this.type == 'url'"
|
>
|
||||||
>
|
<i ref="uploadRef" class="editor-img-uploader"></i>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
<div class="editor" ref="editor" :style="styles"></div>
|
</div>
|
||||||
</div>
|
<div class="editor">
|
||||||
</template>
|
<quill-editor
|
||||||
|
ref="quillEditorRef"
|
||||||
<script>
|
v-model:content="content"
|
||||||
import Quill from "quill";
|
contentType="html"
|
||||||
import "quill/dist/quill.core.css";
|
@textChange="(e) => $emit('update:modelValue', content)"
|
||||||
import "quill/dist/quill.snow.css";
|
:options="options"
|
||||||
import "quill/dist/quill.bubble.css";
|
:style="styles"
|
||||||
import { getToken } from "@/utils/auth";
|
/>
|
||||||
|
</div>
|
||||||
export default {
|
</template>
|
||||||
name: "Editor",
|
|
||||||
props: {
|
<script setup>
|
||||||
/* 编辑器的内容 */
|
import { QuillEditor } from "@vueup/vue-quill";
|
||||||
value: {
|
import "@vueup/vue-quill/dist/vue-quill.snow.css";
|
||||||
type: String,
|
import { getToken } from "@/utils/auth";
|
||||||
default: "",
|
|
||||||
},
|
const { proxy } = getCurrentInstance();
|
||||||
/* 高度 */
|
|
||||||
height: {
|
const quillEditorRef = ref();
|
||||||
type: Number,
|
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // 上传的图片服务器地址
|
||||||
default: null,
|
const headers = ref({
|
||||||
},
|
Authorization: "Bearer " + getToken()
|
||||||
/* 最小高度 */
|
});
|
||||||
minHeight: {
|
|
||||||
type: Number,
|
const props = defineProps({
|
||||||
default: null,
|
/* 编辑器的内容 */
|
||||||
},
|
modelValue: {
|
||||||
/* 只读 */
|
type: String,
|
||||||
readOnly: {
|
},
|
||||||
type: Boolean,
|
/* 高度 */
|
||||||
default: false,
|
height: {
|
||||||
},
|
type: Number,
|
||||||
/* 上传文件大小限制(MB) */
|
default: null,
|
||||||
fileSize: {
|
},
|
||||||
type: Number,
|
/* 最小高度 */
|
||||||
default: 5,
|
minHeight: {
|
||||||
},
|
type: Number,
|
||||||
/* 类型(base64格式、url格式) */
|
default: null,
|
||||||
type: {
|
},
|
||||||
type: String,
|
/* 只读 */
|
||||||
default: "url",
|
readOnly: {
|
||||||
}
|
type: Boolean,
|
||||||
},
|
default: false,
|
||||||
data() {
|
},
|
||||||
return {
|
/* 上传文件大小限制(MB) */
|
||||||
uploadUrl: process.env.VUE_APP_BASE_API + "/file/upload", // 上传的图片服务器地址
|
fileSize: {
|
||||||
headers: {
|
type: Number,
|
||||||
Authorization: "Bearer " + getToken()
|
default: 5,
|
||||||
},
|
},
|
||||||
Quill: null,
|
/* 类型(base64格式、url格式) */
|
||||||
currentValue: "",
|
type: {
|
||||||
options: {
|
type: String,
|
||||||
theme: "snow",
|
default: "base64",
|
||||||
bounds: document.body,
|
}
|
||||||
debug: "warn",
|
});
|
||||||
modules: {
|
|
||||||
// 工具栏配置
|
const options = ref({
|
||||||
toolbar: [
|
theme: "snow",
|
||||||
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
|
bounds: document.body,
|
||||||
["blockquote", "code-block"], // 引用 代码块
|
debug: "warn",
|
||||||
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
|
modules: {
|
||||||
[{ indent: "-1" }, { indent: "+1" }], // 缩进
|
// 工具栏配置
|
||||||
[{ size: ["small", false, "large", "huge"] }], // 字体大小
|
toolbar: [
|
||||||
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
|
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
|
||||||
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
|
["blockquote", "code-block"], // 引用 代码块
|
||||||
[{ align: [] }], // 对齐方式
|
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
|
||||||
["clean"], // 清除文本格式
|
[{ indent: "-1" }, { indent: "+1" }], // 缩进
|
||||||
["link", "image", "video"] // 链接、图片、视频
|
[{ size: ["small", false, "large", "huge"] }], // 字体大小
|
||||||
],
|
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
|
||||||
},
|
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
|
||||||
placeholder: "请输入内容",
|
[{ align: [] }], // 对齐方式
|
||||||
readOnly: this.readOnly,
|
["clean"], // 清除文本格式
|
||||||
},
|
["link", "image", "video"] // 链接、图片、视频
|
||||||
};
|
],
|
||||||
},
|
},
|
||||||
computed: {
|
placeholder: "请输入内容",
|
||||||
styles() {
|
readOnly: props.readOnly
|
||||||
let style = {};
|
});
|
||||||
if (this.minHeight) {
|
|
||||||
style.minHeight = `${this.minHeight}px`;
|
const styles = computed(() => {
|
||||||
}
|
let style = {};
|
||||||
if (this.height) {
|
if (props.minHeight) {
|
||||||
style.height = `${this.height}px`;
|
style.minHeight = `${props.minHeight}px`;
|
||||||
}
|
}
|
||||||
return style;
|
if (props.height) {
|
||||||
},
|
style.height = `${props.height}px`;
|
||||||
},
|
}
|
||||||
watch: {
|
return style;
|
||||||
value: {
|
});
|
||||||
handler(val) {
|
|
||||||
if (val !== this.currentValue) {
|
const content = ref("");
|
||||||
this.currentValue = val === null ? "" : val;
|
watch(() => props.modelValue, (v) => {
|
||||||
if (this.Quill) {
|
if (v !== content.value) {
|
||||||
this.Quill.pasteHTML(this.currentValue);
|
content.value = v === undefined ? "<p></p>" : v;
|
||||||
}
|
}
|
||||||
}
|
}, { immediate: true });
|
||||||
},
|
|
||||||
immediate: true,
|
// 如果设置了上传地址则自定义图片上传事件
|
||||||
},
|
onMounted(() => {
|
||||||
},
|
if (props.type == 'url') {
|
||||||
mounted() {
|
let quill = quillEditorRef.value.getQuill();
|
||||||
this.init();
|
let toolbar = quill.getModule("toolbar");
|
||||||
},
|
toolbar.addHandler("image", (value) => {
|
||||||
beforeDestroy() {
|
if (value) {
|
||||||
this.Quill = null;
|
proxy.$refs.uploadRef.click();
|
||||||
},
|
} else {
|
||||||
methods: {
|
quill.format("image", false);
|
||||||
init() {
|
}
|
||||||
const editor = this.$refs.editor;
|
});
|
||||||
this.Quill = new Quill(editor, this.options);
|
}
|
||||||
// 如果设置了上传地址则自定义图片上传事件
|
});
|
||||||
if (this.type == 'url') {
|
|
||||||
let toolbar = this.Quill.getModule("toolbar");
|
// 上传前校检格式和大小
|
||||||
toolbar.addHandler("image", (value) => {
|
function handleBeforeUpload(file) {
|
||||||
if (value) {
|
const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"];
|
||||||
this.$refs.upload.$children[0].$refs.input.click();
|
const isJPG = type.includes(file.type);
|
||||||
} else {
|
//检验文件格式
|
||||||
this.quill.format("image", false);
|
if (!isJPG) {
|
||||||
}
|
proxy.$modal.msgError(`图片格式错误!`);
|
||||||
});
|
return false;
|
||||||
}
|
}
|
||||||
this.Quill.pasteHTML(this.currentValue);
|
// 校检文件大小
|
||||||
this.Quill.on("text-change", (delta, oldDelta, source) => {
|
if (props.fileSize) {
|
||||||
const html = this.$refs.editor.children[0].innerHTML;
|
const isLt = file.size / 1024 / 1024 < props.fileSize;
|
||||||
const text = this.Quill.getText();
|
if (!isLt) {
|
||||||
const quill = this.Quill;
|
proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
|
||||||
this.currentValue = html;
|
return false;
|
||||||
this.$emit("input", html);
|
}
|
||||||
this.$emit("on-change", { html, text, quill });
|
}
|
||||||
});
|
return true;
|
||||||
this.Quill.on("text-change", (delta, oldDelta, source) => {
|
}
|
||||||
this.$emit("on-text-change", delta, oldDelta, source);
|
|
||||||
});
|
// 上传成功处理
|
||||||
this.Quill.on("selection-change", (range, oldRange, source) => {
|
function handleUploadSuccess(res, file) {
|
||||||
this.$emit("on-selection-change", range, oldRange, source);
|
// 如果上传成功
|
||||||
});
|
if (res.code == 200) {
|
||||||
this.Quill.on("editor-change", (eventName, ...args) => {
|
// 获取富文本实例
|
||||||
this.$emit("on-editor-change", eventName, ...args);
|
let quill = toRaw(quillEditorRef.value).getQuill();
|
||||||
});
|
// 获取光标位置
|
||||||
},
|
let length = quill.selection.savedRange.index;
|
||||||
// 上传前校检格式和大小
|
// 插入图片,res.url为服务器返回的图片链接地址
|
||||||
handleBeforeUpload(file) {
|
quill.insertEmbed(length, "image", res.data.url);
|
||||||
const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"];
|
// 调整光标到最后
|
||||||
const isJPG = type.includes(file.type);
|
quill.setSelection(length + 1);
|
||||||
// 检验文件格式
|
} else {
|
||||||
if (!isJPG) {
|
proxy.$modal.msgError("图片插入失败");
|
||||||
this.$message.error(`图片格式错误!`);
|
}
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
// 校检文件大小
|
// 上传失败处理
|
||||||
if (this.fileSize) {
|
function handleUploadError() {
|
||||||
const isLt = file.size / 1024 / 1024 < this.fileSize;
|
proxy.$modal.msgError("图片插入失败");
|
||||||
if (!isLt) {
|
}
|
||||||
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
|
</script>
|
||||||
return false;
|
|
||||||
}
|
<style>
|
||||||
}
|
.editor-img-uploader {
|
||||||
return true;
|
display: none;
|
||||||
},
|
}
|
||||||
handleUploadSuccess(res, file) {
|
.editor, .ql-toolbar {
|
||||||
// 如果上传成功
|
white-space: pre-wrap !important;
|
||||||
if (res.code == 200) {
|
line-height: normal !important;
|
||||||
// 获取富文本组件实例
|
}
|
||||||
let quill = this.Quill;
|
.quill-img {
|
||||||
// 获取光标所在位置
|
display: none;
|
||||||
let length = quill.getSelection().index;
|
}
|
||||||
// 插入图片 res.url为服务器返回的图片地址
|
.ql-snow .ql-tooltip[data-mode="link"]::before {
|
||||||
quill.insertEmbed(length, "image", res.data.url);
|
content: "请输入链接地址:";
|
||||||
// 调整光标到最后
|
}
|
||||||
quill.setSelection(length + 1);
|
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
|
||||||
} else {
|
border-right: 0px;
|
||||||
this.$message.error("图片插入失败");
|
content: "保存";
|
||||||
}
|
padding-right: 0px;
|
||||||
},
|
}
|
||||||
handleUploadError() {
|
.ql-snow .ql-tooltip[data-mode="video"]::before {
|
||||||
this.$message.error("图片插入失败");
|
content: "请输入视频地址:";
|
||||||
},
|
}
|
||||||
},
|
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
|
||||||
};
|
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
|
||||||
</script>
|
content: "14px";
|
||||||
|
}
|
||||||
<style>
|
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
|
||||||
.editor, .ql-toolbar {
|
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
|
||||||
white-space: pre-wrap !important;
|
content: "10px";
|
||||||
line-height: normal !important;
|
}
|
||||||
}
|
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
|
||||||
.quill-img {
|
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
|
||||||
display: none;
|
content: "18px";
|
||||||
}
|
}
|
||||||
.ql-snow .ql-tooltip[data-mode="link"]::before {
|
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
|
||||||
content: "请输入链接地址:";
|
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
|
||||||
}
|
content: "32px";
|
||||||
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
|
}
|
||||||
border-right: 0px;
|
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
|
||||||
content: "保存";
|
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
|
||||||
padding-right: 0px;
|
content: "文本";
|
||||||
}
|
}
|
||||||
.ql-snow .ql-tooltip[data-mode="video"]::before {
|
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
|
||||||
content: "请输入视频地址:";
|
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
|
||||||
}
|
content: "标题1";
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
|
}
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
|
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
|
||||||
content: "14px";
|
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
|
||||||
}
|
content: "标题2";
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
|
}
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
|
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
|
||||||
content: "10px";
|
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
|
||||||
}
|
content: "标题3";
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
|
}
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
|
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
|
||||||
content: "18px";
|
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
|
||||||
}
|
content: "标题4";
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
|
}
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
|
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
|
||||||
content: "32px";
|
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
|
||||||
}
|
content: "标题5";
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
|
}
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
|
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
|
||||||
content: "文本";
|
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
|
||||||
}
|
content: "标题6";
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
|
}
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
|
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
|
||||||
content: "标题1";
|
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
|
||||||
}
|
content: "标准字体";
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
|
}
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
|
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
|
||||||
content: "标题2";
|
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
|
||||||
}
|
content: "衬线字体";
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
|
}
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
|
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
|
||||||
content: "标题3";
|
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
|
||||||
}
|
content: "等宽字体";
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
|
}
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
|
</style>
|
||||||
content: "标题4";
|
|
||||||
}
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
|
|
||||||
content: "标题5";
|
|
||||||
}
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
|
|
||||||
content: "标题6";
|
|
||||||
}
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
|
|
||||||
content: "标准字体";
|
|
||||||
}
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
|
|
||||||
content: "衬线字体";
|
|
||||||
}
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
|
|
||||||
content: "等宽字体";
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,215 +1,206 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="upload-file">
|
<div class="upload-file">
|
||||||
<el-upload
|
<el-upload
|
||||||
multiple
|
multiple
|
||||||
:action="uploadFileUrl"
|
:action="uploadFileUrl"
|
||||||
:before-upload="handleBeforeUpload"
|
:before-upload="handleBeforeUpload"
|
||||||
:file-list="fileList"
|
:file-list="fileList"
|
||||||
:limit="limit"
|
:limit="limit"
|
||||||
:on-error="handleUploadError"
|
:on-error="handleUploadError"
|
||||||
:on-exceed="handleExceed"
|
:on-exceed="handleExceed"
|
||||||
:on-success="handleUploadSuccess"
|
:on-success="handleUploadSuccess"
|
||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
class="upload-file-uploader"
|
class="upload-file-uploader"
|
||||||
ref="fileUpload"
|
ref="fileUpload"
|
||||||
>
|
>
|
||||||
<!-- 上传按钮 -->
|
<!-- 上传按钮 -->
|
||||||
<el-button size="mini" type="primary">选取文件</el-button>
|
<el-button type="primary">选取文件</el-button>
|
||||||
<!-- 上传提示 -->
|
</el-upload>
|
||||||
<div class="el-upload__tip" slot="tip" v-if="showTip">
|
<!-- 上传提示 -->
|
||||||
请上传
|
<div class="el-upload__tip" v-if="showTip">
|
||||||
<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
|
请上传
|
||||||
<template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
|
<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
|
||||||
的文件
|
<template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
|
||||||
</div>
|
的文件
|
||||||
</el-upload>
|
</div>
|
||||||
|
<!-- 文件列表 -->
|
||||||
<!-- 文件列表 -->
|
<transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
|
||||||
<transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
|
<li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
|
||||||
<li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
|
<el-link :href="file.url" :underline="false" target="_blank">
|
||||||
<el-link :href="file.url" :underline="false" target="_blank">
|
<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
|
||||||
<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
|
</el-link>
|
||||||
</el-link>
|
<div class="ele-upload-list__item-content-action">
|
||||||
<div class="ele-upload-list__item-content-action">
|
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
|
||||||
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
|
</div>
|
||||||
</div>
|
</li>
|
||||||
</li>
|
</transition-group>
|
||||||
</transition-group>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</template>
|
|
||||||
|
<script setup>
|
||||||
<script>
|
import { getToken } from "@/utils/auth";
|
||||||
import { getToken } from "@/utils/auth";
|
|
||||||
|
const props = defineProps({
|
||||||
export default {
|
modelValue: [String, Object, Array],
|
||||||
name: "FileUpload",
|
// 数量限制
|
||||||
props: {
|
limit: {
|
||||||
// 值
|
type: Number,
|
||||||
value: [String, Object, Array],
|
default: 5,
|
||||||
// 数量限制
|
},
|
||||||
limit: {
|
// 大小限制(MB)
|
||||||
type: Number,
|
fileSize: {
|
||||||
default: 5,
|
type: Number,
|
||||||
},
|
default: 5,
|
||||||
// 大小限制(MB)
|
},
|
||||||
fileSize: {
|
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||||
type: Number,
|
fileType: {
|
||||||
default: 5,
|
type: Array,
|
||||||
},
|
default: () => ["doc", "xls", "ppt", "txt", "pdf"],
|
||||||
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
},
|
||||||
fileType: {
|
// 是否显示提示
|
||||||
type: Array,
|
isShowTip: {
|
||||||
default: () => ["doc", "xls", "ppt", "txt", "pdf"],
|
type: Boolean,
|
||||||
},
|
default: true
|
||||||
// 是否显示提示
|
}
|
||||||
isShowTip: {
|
});
|
||||||
type: Boolean,
|
|
||||||
default: true
|
const { proxy } = getCurrentInstance();
|
||||||
}
|
const emit = defineEmits();
|
||||||
},
|
const number = ref(0);
|
||||||
data() {
|
const uploadList = ref([]);
|
||||||
return {
|
const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // 上传文件服务器地址
|
||||||
number: 0,
|
const headers = ref({ Authorization: "Bearer " + getToken() });
|
||||||
uploadList: [],
|
const fileList = ref([]);
|
||||||
uploadFileUrl: process.env.VUE_APP_BASE_API + "/file/upload", // 上传文件服务器地址
|
const showTip = computed(
|
||||||
headers: {
|
() => props.isShowTip && (props.fileType || props.fileSize)
|
||||||
Authorization: "Bearer " + getToken(),
|
);
|
||||||
},
|
|
||||||
fileList: [],
|
watch(() => props.modelValue, val => {
|
||||||
};
|
if (val) {
|
||||||
},
|
let temp = 1;
|
||||||
watch: {
|
// 首先将值转为数组
|
||||||
value: {
|
const list = Array.isArray(val) ? val : props.modelValue.split(',');
|
||||||
handler(val) {
|
// 然后将数组转为对象数组
|
||||||
if (val) {
|
fileList.value = list.map(item => {
|
||||||
let temp = 1;
|
if (typeof item === "string") {
|
||||||
// 首先将值转为数组
|
item = { name: item, url: item };
|
||||||
const list = Array.isArray(val) ? val : this.value.split(',');
|
}
|
||||||
// 然后将数组转为对象数组
|
item.uid = item.uid || new Date().getTime() + temp++;
|
||||||
this.fileList = list.map(item => {
|
return item;
|
||||||
if (typeof item === "string") {
|
});
|
||||||
item = { name: item, url: item };
|
} else {
|
||||||
}
|
fileList.value = [];
|
||||||
item.uid = item.uid || new Date().getTime() + temp++;
|
return [];
|
||||||
return item;
|
}
|
||||||
});
|
},{ deep: true, immediate: true });
|
||||||
} else {
|
|
||||||
this.fileList = [];
|
// 上传前校检格式和大小
|
||||||
return [];
|
function handleBeforeUpload(file) {
|
||||||
}
|
// 校检文件类型
|
||||||
},
|
if (props.fileType.length) {
|
||||||
deep: true,
|
const fileName = file.name.split('.');
|
||||||
immediate: true
|
const fileExt = fileName[fileName.length - 1];
|
||||||
}
|
const isTypeOk = props.fileType.indexOf(fileExt) >= 0;
|
||||||
},
|
if (!isTypeOk) {
|
||||||
computed: {
|
proxy.$modal.msgError(`文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`);
|
||||||
// 是否显示提示
|
return false;
|
||||||
showTip() {
|
}
|
||||||
return this.isShowTip && (this.fileType || this.fileSize);
|
}
|
||||||
},
|
// 校检文件大小
|
||||||
},
|
if (props.fileSize) {
|
||||||
methods: {
|
const isLt = file.size / 1024 / 1024 < props.fileSize;
|
||||||
// 上传前校检格式和大小
|
if (!isLt) {
|
||||||
handleBeforeUpload(file) {
|
proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
|
||||||
// 校检文件类型
|
return false;
|
||||||
if (this.fileType) {
|
}
|
||||||
const fileName = file.name.split('.');
|
}
|
||||||
const fileExt = fileName[fileName.length - 1];
|
proxy.$modal.loading("正在上传文件,请稍候...");
|
||||||
const isTypeOk = this.fileType.indexOf(fileExt) >= 0;
|
number.value++;
|
||||||
if (!isTypeOk) {
|
return true;
|
||||||
this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
|
}
|
||||||
return false;
|
|
||||||
}
|
// 文件个数超出
|
||||||
}
|
function handleExceed() {
|
||||||
// 校检文件大小
|
proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
|
||||||
if (this.fileSize) {
|
}
|
||||||
const isLt = file.size / 1024 / 1024 < this.fileSize;
|
|
||||||
if (!isLt) {
|
// 上传失败
|
||||||
this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);
|
function handleUploadError(err) {
|
||||||
return false;
|
proxy.$modal.msgError("上传文件失败");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
this.$modal.loading("正在上传文件,请稍候...");
|
// 上传成功回调
|
||||||
this.number++;
|
function handleUploadSuccess(res, file) {
|
||||||
return true;
|
if (res.code === 200) {
|
||||||
},
|
uploadList.value.push({ name: res.data.url, url: res.data.url });
|
||||||
// 文件个数超出
|
uploadedSuccessfully();
|
||||||
handleExceed() {
|
} else {
|
||||||
this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
|
number.value--;
|
||||||
},
|
proxy.$modal.closeLoading();
|
||||||
// 上传失败
|
proxy.$modal.msgError(res.msg);
|
||||||
handleUploadError(err) {
|
proxy.$refs.fileUpload.handleRemove(file);
|
||||||
this.$modal.msgError("上传文件失败,请重试");
|
uploadedSuccessfully();
|
||||||
this.$modal.closeLoading()
|
}
|
||||||
},
|
}
|
||||||
// 上传成功回调
|
|
||||||
handleUploadSuccess(res, file) {
|
// 删除文件
|
||||||
if (res.code === 200) {
|
function handleDelete(index) {
|
||||||
this.uploadList.push({ name: res.data.url, url: res.data.url });
|
fileList.value.splice(index, 1);
|
||||||
this.uploadedSuccessfully();
|
emit("update:modelValue", listToString(fileList.value));
|
||||||
} else {
|
}
|
||||||
this.number--;
|
|
||||||
this.$modal.closeLoading();
|
// 上传结束处理
|
||||||
this.$modal.msgError(res.msg);
|
function uploadedSuccessfully() {
|
||||||
this.$refs.fileUpload.handleRemove(file);
|
if (number.value > 0 && uploadList.value.length === number.value) {
|
||||||
this.uploadedSuccessfully();
|
fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value);
|
||||||
}
|
uploadList.value = [];
|
||||||
},
|
number.value = 0;
|
||||||
// 删除文件
|
emit("update:modelValue", listToString(fileList.value));
|
||||||
handleDelete(index) {
|
proxy.$modal.closeLoading();
|
||||||
this.fileList.splice(index, 1);
|
}
|
||||||
this.$emit("input", this.listToString(this.fileList));
|
}
|
||||||
},
|
|
||||||
// 上传结束处理
|
// 获取文件名称
|
||||||
uploadedSuccessfully() {
|
function getFileName(name) {
|
||||||
if (this.number > 0 && this.uploadList.length === this.number) {
|
// 如果是url那么取最后的名字 如果不是直接返回
|
||||||
this.fileList = this.fileList.concat(this.uploadList);
|
if (name.lastIndexOf("/") > -1) {
|
||||||
this.uploadList = [];
|
return name.slice(name.lastIndexOf("/") + 1);
|
||||||
this.number = 0;
|
} else {
|
||||||
this.$emit("input", this.listToString(this.fileList));
|
return name;
|
||||||
this.$modal.closeLoading();
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
// 获取文件名称
|
// 对象转成指定字符串分隔
|
||||||
getFileName(name) {
|
function listToString(list, separator) {
|
||||||
// 如果是url那么取最后的名字 如果不是直接返回
|
let strs = "";
|
||||||
if (name.lastIndexOf("/") > -1) {
|
separator = separator || ",";
|
||||||
return name.slice(name.lastIndexOf("/") + 1);
|
for (let i in list) {
|
||||||
} else {
|
if (list[i].url) {
|
||||||
return name;
|
strs += list[i].url + separator;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
// 对象转成指定字符串分隔
|
return strs != '' ? strs.substr(0, strs.length - 1) : '';
|
||||||
listToString(list, separator) {
|
}
|
||||||
let strs = "";
|
</script>
|
||||||
separator = separator || ",";
|
|
||||||
for (let i in list) {
|
<style scoped lang="scss">
|
||||||
strs += list[i].url + separator;
|
.upload-file-uploader {
|
||||||
}
|
margin-bottom: 5px;
|
||||||
return strs != '' ? strs.substr(0, strs.length - 1) : '';
|
}
|
||||||
}
|
.upload-file-list .el-upload-list__item {
|
||||||
}
|
border: 1px solid #e4e7ed;
|
||||||
};
|
line-height: 2;
|
||||||
</script>
|
margin-bottom: 10px;
|
||||||
|
position: relative;
|
||||||
<style scoped lang="scss">
|
}
|
||||||
.upload-file-uploader {
|
.upload-file-list .ele-upload-list__item-content {
|
||||||
margin-bottom: 5px;
|
display: flex;
|
||||||
}
|
justify-content: space-between;
|
||||||
.upload-file-list .el-upload-list__item {
|
align-items: center;
|
||||||
border: 1px solid #e4e7ed;
|
color: inherit;
|
||||||
line-height: 2;
|
}
|
||||||
margin-bottom: 10px;
|
.ele-upload-list__item-content-action .el-link {
|
||||||
position: relative;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
.upload-file-list .ele-upload-list__item-content {
|
</style>
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
.ele-upload-list__item-content-action .el-link {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,44 +1,41 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="padding: 0 15px;" @click="toggleClick">
|
<div style="padding: 0 15px;" @click="toggleClick">
|
||||||
<svg
|
<svg
|
||||||
:class="{'is-active':isActive}"
|
:class="{'is-active':isActive}"
|
||||||
class="hamburger"
|
class="hamburger"
|
||||||
viewBox="0 0 1024 1024"
|
viewBox="0 0 1024 1024"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="64"
|
width="64"
|
||||||
height="64"
|
height="64"
|
||||||
>
|
>
|
||||||
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
|
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
defineProps({
|
||||||
name: 'Hamburger',
|
isActive: {
|
||||||
props: {
|
type: Boolean,
|
||||||
isActive: {
|
default: false
|
||||||
type: Boolean,
|
}
|
||||||
default: false
|
})
|
||||||
}
|
|
||||||
},
|
const emit = defineEmits()
|
||||||
methods: {
|
const toggleClick = () => {
|
||||||
toggleClick() {
|
emit('toggleClick');
|
||||||
this.$emit('toggleClick')
|
}
|
||||||
}
|
</script>
|
||||||
}
|
|
||||||
}
|
<style scoped>
|
||||||
</script>
|
.hamburger {
|
||||||
|
display: inline-block;
|
||||||
<style scoped>
|
vertical-align: middle;
|
||||||
.hamburger {
|
width: 20px;
|
||||||
display: inline-block;
|
height: 20px;
|
||||||
vertical-align: middle;
|
}
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
.hamburger.is-active {
|
||||||
}
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
.hamburger.is-active {
|
</style>
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,198 +1,187 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="{'show':show}" class="header-search">
|
<div :class="{ 'show': show }" class="header-search">
|
||||||
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
|
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
|
||||||
<el-select
|
<el-select
|
||||||
ref="headerSearchSelect"
|
ref="headerSearchSelectRef"
|
||||||
v-model="search"
|
v-model="search"
|
||||||
:remote-method="querySearch"
|
:remote-method="querySearch"
|
||||||
filterable
|
filterable
|
||||||
default-first-option
|
default-first-option
|
||||||
remote
|
remote
|
||||||
placeholder="Search"
|
placeholder="Search"
|
||||||
class="header-search-select"
|
class="header-search-select"
|
||||||
@change="change"
|
@change="change"
|
||||||
>
|
>
|
||||||
<el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')" />
|
<el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
// fuse is a lightweight fuzzy-search module
|
import Fuse from 'fuse.js'
|
||||||
// make search results more in line with expectations
|
import { getNormalPath } from '@/utils/ruoyi'
|
||||||
import Fuse from 'fuse.js/dist/fuse.min.js'
|
import { isHttp } from '@/utils/validate'
|
||||||
import path from 'path'
|
import usePermissionStore from '@/store/modules/permission'
|
||||||
|
|
||||||
export default {
|
const search = ref('');
|
||||||
name: 'HeaderSearch',
|
const options = ref([]);
|
||||||
data() {
|
const searchPool = ref([]);
|
||||||
return {
|
const show = ref(false);
|
||||||
search: '',
|
const fuse = ref(undefined);
|
||||||
options: [],
|
const headerSearchSelectRef = ref(null);
|
||||||
searchPool: [],
|
const router = useRouter();
|
||||||
show: false,
|
const routes = computed(() => usePermissionStore().routes);
|
||||||
fuse: undefined
|
|
||||||
}
|
function click() {
|
||||||
},
|
show.value = !show.value
|
||||||
computed: {
|
if (show.value) {
|
||||||
routes() {
|
headerSearchSelectRef.value && headerSearchSelectRef.value.focus()
|
||||||
return this.$store.getters.permission_routes
|
}
|
||||||
}
|
};
|
||||||
},
|
function close() {
|
||||||
watch: {
|
headerSearchSelectRef.value && headerSearchSelectRef.value.blur()
|
||||||
routes() {
|
options.value = []
|
||||||
this.searchPool = this.generateRoutes(this.routes)
|
show.value = false
|
||||||
},
|
}
|
||||||
searchPool(list) {
|
function change(val) {
|
||||||
this.initFuse(list)
|
const path = val.path;
|
||||||
},
|
const query = val.query;
|
||||||
show(value) {
|
if (isHttp(path)) {
|
||||||
if (value) {
|
// http(s):// 路径新窗口打开
|
||||||
document.body.addEventListener('click', this.close)
|
const pindex = path.indexOf("http");
|
||||||
} else {
|
window.open(path.substr(pindex, path.length), "_blank");
|
||||||
document.body.removeEventListener('click', this.close)
|
} else {
|
||||||
}
|
if (query) {
|
||||||
}
|
router.push({ path: path, query: JSON.parse(query) });
|
||||||
},
|
} else {
|
||||||
mounted() {
|
router.push(path)
|
||||||
this.searchPool = this.generateRoutes(this.routes)
|
}
|
||||||
},
|
}
|
||||||
methods: {
|
|
||||||
click() {
|
search.value = ''
|
||||||
this.show = !this.show
|
options.value = []
|
||||||
if (this.show) {
|
nextTick(() => {
|
||||||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
|
show.value = false
|
||||||
}
|
})
|
||||||
},
|
}
|
||||||
close() {
|
function initFuse(list) {
|
||||||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
|
fuse.value = new Fuse(list, {
|
||||||
this.options = []
|
shouldSort: true,
|
||||||
this.show = false
|
threshold: 0.4,
|
||||||
},
|
location: 0,
|
||||||
change(val) {
|
distance: 100,
|
||||||
const path = val.path;
|
minMatchCharLength: 1,
|
||||||
const query = val.query;
|
keys: [{
|
||||||
if(this.ishttp(val.path)) {
|
name: 'title',
|
||||||
// http(s):// 路径新窗口打开
|
weight: 0.7
|
||||||
const pindex = path.indexOf("http");
|
}, {
|
||||||
window.open(path.substr(pindex, path.length), "_blank");
|
name: 'path',
|
||||||
} else {
|
weight: 0.3
|
||||||
if (query) {
|
}]
|
||||||
this.$router.push({ path: path, query: JSON.parse(query) });
|
})
|
||||||
} else {
|
}
|
||||||
this.$router.push(path)
|
// Filter out the routes that can be displayed in the sidebar
|
||||||
}
|
// And generate the internationalized title
|
||||||
}
|
function generateRoutes(routes, basePath = '', prefixTitle = []) {
|
||||||
this.search = ''
|
let res = []
|
||||||
this.options = []
|
|
||||||
this.$nextTick(() => {
|
for (const r of routes) {
|
||||||
this.show = false
|
// skip hidden router
|
||||||
})
|
if (r.hidden) { continue }
|
||||||
},
|
const p = r.path.length > 0 && r.path[0] === '/' ? r.path : '/' + r.path;
|
||||||
initFuse(list) {
|
const data = {
|
||||||
this.fuse = new Fuse(list, {
|
path: !isHttp(r.path) ? getNormalPath(basePath + p) : r.path,
|
||||||
shouldSort: true,
|
title: [...prefixTitle]
|
||||||
threshold: 0.4,
|
}
|
||||||
location: 0,
|
|
||||||
distance: 100,
|
if (r.meta && r.meta.title) {
|
||||||
minMatchCharLength: 1,
|
data.title = [...data.title, r.meta.title]
|
||||||
keys: [{
|
|
||||||
name: 'title',
|
if (r.redirect !== 'noRedirect') {
|
||||||
weight: 0.7
|
// only push the routes with title
|
||||||
}, {
|
// special case: need to exclude parent router without redirect
|
||||||
name: 'path',
|
res.push(data)
|
||||||
weight: 0.3
|
}
|
||||||
}]
|
}
|
||||||
})
|
if (r.query) {
|
||||||
},
|
data.query = r.query
|
||||||
// Filter out the routes that can be displayed in the sidebar
|
}
|
||||||
// And generate the internationalized title
|
|
||||||
generateRoutes(routes, basePath = '/', prefixTitle = []) {
|
// recursive child routes
|
||||||
let res = []
|
if (r.children) {
|
||||||
|
const tempRoutes = generateRoutes(r.children, data.path, data.title)
|
||||||
for (const router of routes) {
|
if (tempRoutes.length >= 1) {
|
||||||
// skip hidden router
|
res = [...res, ...tempRoutes]
|
||||||
if (router.hidden) { continue }
|
}
|
||||||
|
}
|
||||||
const data = {
|
}
|
||||||
path: !this.ishttp(router.path) ? path.resolve(basePath, router.path) : router.path,
|
return res
|
||||||
title: [...prefixTitle]
|
}
|
||||||
}
|
function querySearch(query) {
|
||||||
|
if (query !== '') {
|
||||||
if (router.meta && router.meta.title) {
|
options.value = fuse.value.search(query)
|
||||||
data.title = [...data.title, router.meta.title]
|
} else {
|
||||||
|
options.value = []
|
||||||
if (router.redirect !== 'noRedirect') {
|
}
|
||||||
// only push the routes with title
|
}
|
||||||
// special case: need to exclude parent router without redirect
|
|
||||||
res.push(data)
|
onMounted(() => {
|
||||||
}
|
searchPool.value = generateRoutes(routes.value);
|
||||||
}
|
})
|
||||||
|
|
||||||
if (router.query) {
|
watchEffect(() => {
|
||||||
data.query = router.query
|
searchPool.value = generateRoutes(routes.value)
|
||||||
}
|
})
|
||||||
|
|
||||||
// recursive child routes
|
watch(show, (value) => {
|
||||||
if (router.children) {
|
if (value) {
|
||||||
const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
|
document.body.addEventListener('click', close)
|
||||||
if (tempRoutes.length >= 1) {
|
} else {
|
||||||
res = [...res, ...tempRoutes]
|
document.body.removeEventListener('click', close)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
|
||||||
return res
|
watch(searchPool, (list) => {
|
||||||
},
|
initFuse(list)
|
||||||
querySearch(query) {
|
})
|
||||||
if (query !== '') {
|
</script>
|
||||||
this.options = this.fuse.search(query)
|
|
||||||
} else {
|
<style lang='scss' scoped>
|
||||||
this.options = []
|
.header-search {
|
||||||
}
|
font-size: 0 !important;
|
||||||
},
|
|
||||||
ishttp(url) {
|
.search-icon {
|
||||||
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
|
cursor: pointer;
|
||||||
}
|
font-size: 18px;
|
||||||
}
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
</script>
|
|
||||||
|
.header-search-select {
|
||||||
<style lang="scss" scoped>
|
font-size: 18px;
|
||||||
.header-search {
|
transition: width 0.2s;
|
||||||
font-size: 0 !important;
|
width: 0;
|
||||||
|
overflow: hidden;
|
||||||
.search-icon {
|
background: transparent;
|
||||||
cursor: pointer;
|
border-radius: 0;
|
||||||
font-size: 18px;
|
display: inline-block;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
|
||||||
|
:deep(.el-input__inner) {
|
||||||
.header-search-select {
|
border-radius: 0;
|
||||||
font-size: 18px;
|
border: 0;
|
||||||
transition: width 0.2s;
|
padding-left: 0;
|
||||||
width: 0;
|
padding-right: 0;
|
||||||
overflow: hidden;
|
box-shadow: none !important;
|
||||||
background: transparent;
|
border-bottom: 1px solid #d9d9d9;
|
||||||
border-radius: 0;
|
vertical-align: middle;
|
||||||
display: inline-block;
|
}
|
||||||
vertical-align: middle;
|
}
|
||||||
|
|
||||||
::v-deep .el-input__inner {
|
&.show {
|
||||||
border-radius: 0;
|
.header-search-select {
|
||||||
border: 0;
|
width: 210px;
|
||||||
padding-left: 0;
|
margin-left: 10px;
|
||||||
padding-right: 0;
|
}
|
||||||
box-shadow: none !important;
|
}
|
||||||
border-bottom: 1px solid #d9d9d9;
|
}
|
||||||
vertical-align: middle;
|
</style>
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.show {
|
|
||||||
.header-search-select {
|
|
||||||
width: 210px;
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,104 +1,111 @@
|
|||||||
<!-- @author zhengjie -->
|
<template>
|
||||||
<template>
|
<div class="icon-body">
|
||||||
<div class="icon-body">
|
<el-input
|
||||||
<el-input v-model="name" class="icon-search" clearable placeholder="请输入图标名称" @clear="filterIcons" @input="filterIcons">
|
v-model="iconName"
|
||||||
<i slot="suffix" class="el-icon-search el-input__icon" />
|
class="icon-search"
|
||||||
</el-input>
|
clearable
|
||||||
<div class="icon-list">
|
placeholder="请输入图标名称"
|
||||||
<div class="list-container">
|
@clear="filterIcons"
|
||||||
<div v-for="(item, index) in iconList" class="icon-item-wrapper" :key="index" @click="selectedIcon(item)">
|
@input="filterIcons"
|
||||||
<div :class="['icon-item', { active: activeIcon === item }]">
|
>
|
||||||
<svg-icon :icon-class="item" class-name="icon" style="height: 25px;width: 16px;"/>
|
<template #suffix><i class="el-icon-search el-input__icon" /></template>
|
||||||
<span>{{ item }}</span>
|
</el-input>
|
||||||
</div>
|
<div class="icon-list">
|
||||||
</div>
|
<div class="list-container">
|
||||||
</div>
|
<div v-for="(item, index) in iconList" class="icon-item-wrapper" :key="index" @click="selectedIcon(item)">
|
||||||
</div>
|
<div :class="['icon-item', { active: activeIcon === item }]">
|
||||||
</div>
|
<svg-icon :icon-class="item" class-name="icon" style="height: 25px;width: 16px;"/>
|
||||||
</template>
|
<span>{{ item }}</span>
|
||||||
|
</div>
|
||||||
<script>
|
</div>
|
||||||
import icons from './requireIcons'
|
</div>
|
||||||
export default {
|
</div>
|
||||||
name: 'IconSelect',
|
</div>
|
||||||
props: {
|
</template>
|
||||||
activeIcon: {
|
|
||||||
type: String
|
<script setup>
|
||||||
}
|
import icons from './requireIcons'
|
||||||
},
|
|
||||||
data() {
|
const props = defineProps({
|
||||||
return {
|
activeIcon: {
|
||||||
name: '',
|
type: String
|
||||||
iconList: icons
|
}
|
||||||
}
|
});
|
||||||
},
|
|
||||||
methods: {
|
const iconName = ref('');
|
||||||
filterIcons() {
|
const iconList = ref(icons);
|
||||||
this.iconList = icons
|
const emit = defineEmits(['selected']);
|
||||||
if (this.name) {
|
|
||||||
this.iconList = this.iconList.filter(item => item.includes(this.name))
|
function filterIcons() {
|
||||||
}
|
iconList.value = icons
|
||||||
},
|
if (iconName.value) {
|
||||||
selectedIcon(name) {
|
iconList.value = icons.filter(item => item.indexOf(iconName.value) !== -1)
|
||||||
this.$emit('selected', name)
|
}
|
||||||
document.body.click()
|
}
|
||||||
},
|
|
||||||
reset() {
|
function selectedIcon(name) {
|
||||||
this.name = ''
|
emit('selected', name)
|
||||||
this.iconList = icons
|
document.body.click()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
function reset() {
|
||||||
</script>
|
iconName.value = ''
|
||||||
|
iconList.value = icons
|
||||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
}
|
||||||
.icon-body {
|
|
||||||
width: 100%;
|
defineExpose({
|
||||||
padding: 10px;
|
reset
|
||||||
.icon-search {
|
})
|
||||||
position: relative;
|
</script>
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
<style lang='scss' scoped>
|
||||||
.icon-list {
|
.icon-body {
|
||||||
height: 200px;
|
width: 100%;
|
||||||
overflow: auto;
|
padding: 10px;
|
||||||
.list-container {
|
.icon-search {
|
||||||
display: flex;
|
position: relative;
|
||||||
flex-wrap: wrap;
|
margin-bottom: 5px;
|
||||||
.icon-item-wrapper {
|
}
|
||||||
width: calc(100% / 3);
|
.icon-list {
|
||||||
height: 25px;
|
height: 200px;
|
||||||
line-height: 25px;
|
overflow: auto;
|
||||||
cursor: pointer;
|
.list-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
.icon-item {
|
flex-wrap: wrap;
|
||||||
display: flex;
|
.icon-item-wrapper {
|
||||||
max-width: 100%;
|
width: calc(100% / 3);
|
||||||
height: 100%;
|
height: 25px;
|
||||||
padding: 0 5px;
|
line-height: 25px;
|
||||||
&:hover {
|
cursor: pointer;
|
||||||
background: #ececec;
|
display: flex;
|
||||||
border-radius: 5px;
|
.icon-item {
|
||||||
}
|
display: flex;
|
||||||
.icon {
|
max-width: 100%;
|
||||||
flex-shrink: 0;
|
height: 100%;
|
||||||
}
|
padding: 0 5px;
|
||||||
span {
|
&:hover {
|
||||||
display: inline-block;
|
background: #ececec;
|
||||||
vertical-align: -0.15em;
|
border-radius: 5px;
|
||||||
fill: currentColor;
|
}
|
||||||
padding-left: 2px;
|
.icon {
|
||||||
overflow: hidden;
|
flex-shrink: 0;
|
||||||
text-overflow: ellipsis;
|
}
|
||||||
white-space: nowrap;
|
span {
|
||||||
}
|
display: inline-block;
|
||||||
}
|
vertical-align: -0.15em;
|
||||||
.icon-item.active {
|
fill: currentColor;
|
||||||
background: #ececec;
|
padding-left: 2px;
|
||||||
border-radius: 5px;
|
overflow: hidden;
|
||||||
}
|
text-overflow: ellipsis;
|
||||||
}
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
.icon-item.active {
|
||||||
</style>
|
background: #ececec;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
|
let icons = []
|
||||||
const req = require.context('../../assets/icons/svg', false, /\.svg$/)
|
const modules = import.meta.glob('./../../assets/icons/svg/*.svg');
|
||||||
const requireAll = requireContext => requireContext.keys()
|
for (const path in modules) {
|
||||||
|
const p = path.split('assets/icons/svg/')[1].split('.svg')[0];
|
||||||
const re = /\.\/(.*)\.svg/
|
icons.push(p);
|
||||||
|
}
|
||||||
const icons = requireAll(req).map(i => {
|
|
||||||
return i.match(re)[1]
|
export default icons
|
||||||
})
|
|
||||||
|
|
||||||
export default icons
|
|
||||||
@@ -4,57 +4,59 @@
|
|||||||
fit="cover"
|
fit="cover"
|
||||||
:style="`width:${realWidth};height:${realHeight};`"
|
:style="`width:${realWidth};height:${realHeight};`"
|
||||||
:preview-src-list="realSrcList"
|
:preview-src-list="realSrcList"
|
||||||
|
preview-teleported
|
||||||
>
|
>
|
||||||
<div slot="error" class="image-slot">
|
<template #error>
|
||||||
<i class="el-icon-picture-outline"></i>
|
<div class="image-slot">
|
||||||
</div>
|
<el-icon><picture-filled /></el-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</el-image>
|
</el-image>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
const props = defineProps({
|
||||||
name: "ImagePreview",
|
src: {
|
||||||
props: {
|
type: String,
|
||||||
src: {
|
default: ""
|
||||||
type: String,
|
|
||||||
default: ""
|
|
||||||
},
|
|
||||||
width: {
|
|
||||||
type: [Number, String],
|
|
||||||
default: ""
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: [Number, String],
|
|
||||||
default: ""
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
computed: {
|
width: {
|
||||||
realSrc() {
|
type: [Number, String],
|
||||||
if (!this.src) {
|
default: ""
|
||||||
return;
|
|
||||||
}
|
|
||||||
let real_src = this.src.split(",")[0];
|
|
||||||
return real_src;
|
|
||||||
},
|
|
||||||
realSrcList() {
|
|
||||||
if (!this.src) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let real_src_list = this.src.split(",");
|
|
||||||
let srcList = [];
|
|
||||||
real_src_list.forEach(item => {
|
|
||||||
return srcList.push(item);
|
|
||||||
});
|
|
||||||
return srcList;
|
|
||||||
},
|
|
||||||
realWidth() {
|
|
||||||
return typeof this.width == "string" ? this.width : `${this.width}px`;
|
|
||||||
},
|
|
||||||
realHeight() {
|
|
||||||
return typeof this.height == "string" ? this.height : `${this.height}px`;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
height: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: ""
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const realSrc = computed(() => {
|
||||||
|
if (!props.src) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let real_src = props.src.split(",")[0];
|
||||||
|
return real_src;
|
||||||
|
});
|
||||||
|
|
||||||
|
const realSrcList = computed(() => {
|
||||||
|
if (!props.src) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let real_src_list = props.src.split(",");
|
||||||
|
let srcList = [];
|
||||||
|
real_src_list.forEach(item => {
|
||||||
|
return srcList.push(item);
|
||||||
|
});
|
||||||
|
return srcList;
|
||||||
|
});
|
||||||
|
|
||||||
|
const realWidth = computed(() =>
|
||||||
|
typeof props.width == "string" ? props.width : `${props.width}px`
|
||||||
|
);
|
||||||
|
|
||||||
|
const realHeight = computed(() =>
|
||||||
|
typeof props.height == "string" ? props.height : `${props.height}px`
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -62,14 +64,14 @@ export default {
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background-color: #ebeef5;
|
background-color: #ebeef5;
|
||||||
box-shadow: 0 0 5px 1px #ccc;
|
box-shadow: 0 0 5px 1px #ccc;
|
||||||
::v-deep .el-image__inner {
|
:deep(.el-image__inner) {
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: scale(1.2);
|
transform: scale(1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
::v-deep .image-slot {
|
:deep(.image-slot) {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -1,221 +1,208 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="component-upload-image">
|
<div class="component-upload-image">
|
||||||
<el-upload
|
<el-upload
|
||||||
multiple
|
multiple
|
||||||
:action="uploadImgUrl"
|
:action="uploadImgUrl"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:on-success="handleUploadSuccess"
|
:on-success="handleUploadSuccess"
|
||||||
:before-upload="handleBeforeUpload"
|
:before-upload="handleBeforeUpload"
|
||||||
:limit="limit"
|
:limit="limit"
|
||||||
:on-error="handleUploadError"
|
:on-error="handleUploadError"
|
||||||
:on-exceed="handleExceed"
|
:on-exceed="handleExceed"
|
||||||
ref="imageUpload"
|
ref="imageUpload"
|
||||||
:on-remove="handleDelete"
|
:before-remove="handleDelete"
|
||||||
:show-file-list="true"
|
:show-file-list="true"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
:file-list="fileList"
|
:file-list="fileList"
|
||||||
:on-preview="handlePictureCardPreview"
|
:on-preview="handlePictureCardPreview"
|
||||||
:class="{hide: this.fileList.length >= this.limit}"
|
:class="{ hide: fileList.length >= limit }"
|
||||||
>
|
>
|
||||||
<i class="el-icon-plus"></i>
|
<el-icon class="avatar-uploader-icon"><plus /></el-icon>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
|
<!-- 上传提示 -->
|
||||||
<!-- 上传提示 -->
|
<div class="el-upload__tip" v-if="showTip">
|
||||||
<div class="el-upload__tip" slot="tip" v-if="showTip">
|
请上传
|
||||||
请上传
|
<template v-if="fileSize">
|
||||||
<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
|
大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
|
||||||
<template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
|
</template>
|
||||||
的文件
|
<template v-if="fileType">
|
||||||
</div>
|
格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b>
|
||||||
|
</template>
|
||||||
<el-dialog
|
的文件
|
||||||
:visible.sync="dialogVisible"
|
</div>
|
||||||
title="预览"
|
|
||||||
width="800"
|
<el-dialog
|
||||||
append-to-body
|
v-model="dialogVisible"
|
||||||
>
|
title="预览"
|
||||||
<img
|
width="800px"
|
||||||
:src="dialogImageUrl"
|
append-to-body
|
||||||
style="display: block; max-width: 100%; margin: 0 auto"
|
>
|
||||||
/>
|
<img
|
||||||
</el-dialog>
|
:src="dialogImageUrl"
|
||||||
</div>
|
style="display: block; max-width: 100%; margin: 0 auto"
|
||||||
</template>
|
/>
|
||||||
|
</el-dialog>
|
||||||
<script>
|
</div>
|
||||||
import { getToken } from "@/utils/auth";
|
</template>
|
||||||
|
|
||||||
export default {
|
<script setup>
|
||||||
props: {
|
import { getToken } from "@/utils/auth";
|
||||||
value: [String, Object, Array],
|
|
||||||
// 图片数量限制
|
const props = defineProps({
|
||||||
limit: {
|
modelValue: [String, Object, Array],
|
||||||
type: Number,
|
// 图片数量限制
|
||||||
default: 5,
|
limit: {
|
||||||
},
|
type: Number,
|
||||||
// 大小限制(MB)
|
default: 5,
|
||||||
fileSize: {
|
},
|
||||||
type: Number,
|
// 大小限制(MB)
|
||||||
default: 5,
|
fileSize: {
|
||||||
},
|
type: Number,
|
||||||
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
default: 5,
|
||||||
fileType: {
|
},
|
||||||
type: Array,
|
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||||
default: () => ["png", "jpg", "jpeg"],
|
fileType: {
|
||||||
},
|
type: Array,
|
||||||
// 是否显示提示
|
default: () => ["png", "jpg", "jpeg"],
|
||||||
isShowTip: {
|
},
|
||||||
type: Boolean,
|
// 是否显示提示
|
||||||
default: true
|
isShowTip: {
|
||||||
}
|
type: Boolean,
|
||||||
},
|
default: true
|
||||||
data() {
|
},
|
||||||
return {
|
});
|
||||||
number: 0,
|
|
||||||
uploadList: [],
|
const { proxy } = getCurrentInstance();
|
||||||
dialogImageUrl: "",
|
const emit = defineEmits();
|
||||||
dialogVisible: false,
|
const number = ref(0);
|
||||||
hideUpload: false,
|
const uploadList = ref([]);
|
||||||
uploadImgUrl: process.env.VUE_APP_BASE_API + "/file/upload", // 上传的图片服务器地址
|
const dialogImageUrl = ref("");
|
||||||
headers: {
|
const dialogVisible = ref(false);
|
||||||
Authorization: "Bearer " + getToken(),
|
const baseUrl = import.meta.env.VITE_APP_BASE_API;
|
||||||
},
|
const uploadImgUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // 上传的图片服务器地址
|
||||||
fileList: []
|
const headers = ref({ Authorization: "Bearer " + getToken() });
|
||||||
};
|
const fileList = ref([]);
|
||||||
},
|
const showTip = computed(
|
||||||
watch: {
|
() => props.isShowTip && (props.fileType || props.fileSize)
|
||||||
value: {
|
);
|
||||||
handler(val) {
|
|
||||||
if (val) {
|
watch(() => props.modelValue, val => {
|
||||||
// 首先将值转为数组
|
if (val) {
|
||||||
const list = Array.isArray(val) ? val : this.value.split(',');
|
// 首先将值转为数组
|
||||||
// 然后将数组转为对象数组
|
const list = Array.isArray(val) ? val : props.modelValue.split(",");
|
||||||
this.fileList = list.map(item => {
|
// 然后将数组转为对象数组
|
||||||
if (typeof item === "string") {
|
fileList.value = list.map(item => {
|
||||||
item = { name: item, url: item };
|
if (typeof item === "string") {
|
||||||
}
|
item = { name: item, url: item };
|
||||||
return item;
|
}
|
||||||
});
|
return item;
|
||||||
} else {
|
});
|
||||||
this.fileList = [];
|
} else {
|
||||||
return [];
|
fileList.value = [];
|
||||||
}
|
return [];
|
||||||
},
|
}
|
||||||
deep: true,
|
},{ deep: true, immediate: true });
|
||||||
immediate: true
|
|
||||||
}
|
// 上传前loading加载
|
||||||
},
|
function handleBeforeUpload(file) {
|
||||||
computed: {
|
let isImg = false;
|
||||||
// 是否显示提示
|
if (props.fileType.length) {
|
||||||
showTip() {
|
let fileExtension = "";
|
||||||
return this.isShowTip && (this.fileType || this.fileSize);
|
if (file.name.lastIndexOf(".") > -1) {
|
||||||
},
|
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
|
||||||
},
|
}
|
||||||
methods: {
|
isImg = props.fileType.some(type => {
|
||||||
// 上传前loading加载
|
if (file.type.indexOf(type) > -1) return true;
|
||||||
handleBeforeUpload(file) {
|
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
|
||||||
let isImg = false;
|
return false;
|
||||||
if (this.fileType.length) {
|
});
|
||||||
let fileExtension = "";
|
} else {
|
||||||
if (file.name.lastIndexOf(".") > -1) {
|
isImg = file.type.indexOf("image") > -1;
|
||||||
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
|
}
|
||||||
}
|
if (!isImg) {
|
||||||
isImg = this.fileType.some(type => {
|
proxy.$modal.msgError(
|
||||||
if (file.type.indexOf(type) > -1) return true;
|
`文件格式不正确, 请上传${props.fileType.join("/")}图片格式文件!`
|
||||||
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
|
);
|
||||||
return false;
|
return false;
|
||||||
});
|
}
|
||||||
} else {
|
if (props.fileSize) {
|
||||||
isImg = file.type.indexOf("image") > -1;
|
const isLt = file.size / 1024 / 1024 < props.fileSize;
|
||||||
}
|
if (!isLt) {
|
||||||
|
proxy.$modal.msgError(`上传头像图片大小不能超过 ${props.fileSize} MB!`);
|
||||||
if (!isImg) {
|
return false;
|
||||||
this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`);
|
}
|
||||||
return false;
|
}
|
||||||
}
|
proxy.$modal.loading("正在上传图片,请稍候...");
|
||||||
if (this.fileSize) {
|
number.value++;
|
||||||
const isLt = file.size / 1024 / 1024 < this.fileSize;
|
}
|
||||||
if (!isLt) {
|
|
||||||
this.$modal.msgError(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
|
// 文件个数超出
|
||||||
return false;
|
function handleExceed() {
|
||||||
}
|
proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
|
||||||
}
|
}
|
||||||
this.$modal.loading("正在上传图片,请稍候...");
|
|
||||||
this.number++;
|
// 上传成功回调
|
||||||
},
|
function handleUploadSuccess(res, file) {
|
||||||
// 文件个数超出
|
if (res.code === 200) {
|
||||||
handleExceed() {
|
uploadList.value.push({ name: res.data.url, url: res.data.url });
|
||||||
this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
|
uploadedSuccessfully();
|
||||||
},
|
} else {
|
||||||
// 上传成功回调
|
number.value--;
|
||||||
handleUploadSuccess(res, file) {
|
proxy.$modal.closeLoading();
|
||||||
if (res.code === 200) {
|
proxy.$modal.msgError(res.msg);
|
||||||
this.uploadList.push({ name: res.data.url, url: res.data.url });
|
proxy.$refs.imageUpload.handleRemove(file);
|
||||||
this.uploadedSuccessfully();
|
uploadedSuccessfully();
|
||||||
} else {
|
}
|
||||||
this.number--;
|
}
|
||||||
this.$modal.closeLoading();
|
|
||||||
this.$modal.msgError(res.msg);
|
// 删除图片
|
||||||
this.$refs.imageUpload.handleRemove(file);
|
function handleDelete(file) {
|
||||||
this.uploadedSuccessfully();
|
const findex = fileList.value.map(f => f.name).indexOf(file.name);
|
||||||
}
|
if (findex > -1 && uploadList.value.length === number.value) {
|
||||||
},
|
fileList.value.splice(findex, 1);
|
||||||
// 删除图片
|
emit("update:modelValue", listToString(fileList.value));
|
||||||
handleDelete(file) {
|
return false;
|
||||||
const findex = this.fileList.map(f => f.name).indexOf(file.name);
|
}
|
||||||
if (findex > -1) {
|
}
|
||||||
this.fileList.splice(findex, 1);
|
|
||||||
this.$emit("input", this.listToString(this.fileList));
|
// 上传结束处理
|
||||||
}
|
function uploadedSuccessfully() {
|
||||||
},
|
if (number.value > 0 && uploadList.value.length === number.value) {
|
||||||
// 上传失败
|
fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value);
|
||||||
handleUploadError() {
|
uploadList.value = [];
|
||||||
this.$modal.msgError("上传图片失败,请重试");
|
number.value = 0;
|
||||||
this.$modal.closeLoading();
|
emit("update:modelValue", listToString(fileList.value));
|
||||||
},
|
proxy.$modal.closeLoading();
|
||||||
// 上传结束处理
|
}
|
||||||
uploadedSuccessfully() {
|
}
|
||||||
if (this.number > 0 && this.uploadList.length === this.number) {
|
// 上传失败
|
||||||
this.fileList = this.fileList.concat(this.uploadList);
|
function handleUploadError() {
|
||||||
this.uploadList = [];
|
proxy.$modal.msgError("上传图片失败");
|
||||||
this.number = 0;
|
proxy.$modal.closeLoading();
|
||||||
this.$emit("input", this.listToString(this.fileList));
|
}
|
||||||
this.$modal.closeLoading();
|
|
||||||
}
|
// 预览
|
||||||
},
|
function handlePictureCardPreview(file) {
|
||||||
// 预览
|
dialogImageUrl.value = file.url;
|
||||||
handlePictureCardPreview(file) {
|
dialogVisible.value = true;
|
||||||
this.dialogImageUrl = file.url;
|
}
|
||||||
this.dialogVisible = true;
|
|
||||||
},
|
// 对象转成指定字符串分隔
|
||||||
// 对象转成指定字符串分隔
|
function listToString(list, separator) {
|
||||||
listToString(list, separator) {
|
let strs = "";
|
||||||
let strs = "";
|
separator = separator || ",";
|
||||||
separator = separator || ",";
|
for (let i in list) {
|
||||||
for (let i in list) {
|
if (undefined !== list[i].url && list[i].url.indexOf("blob:") !== 0) {
|
||||||
if (list[i].url) {
|
strs += list[i].url.replace(baseUrl, "") + separator;
|
||||||
strs += list[i].url.replace(this.baseUrl, "") + separator;
|
}
|
||||||
}
|
}
|
||||||
}
|
return strs != "" ? strs.substr(0, strs.length - 1) : "";
|
||||||
return strs != '' ? strs.substr(0, strs.length - 1) : '';
|
}
|
||||||
}
|
</script>
|
||||||
}
|
|
||||||
};
|
<style scoped lang="scss">
|
||||||
</script>
|
// .el-upload--picture-card 控制加号部分
|
||||||
<style scoped lang="scss">
|
:deep(.hide .el-upload--picture-card) {
|
||||||
// .el-upload--picture-card 控制加号部分
|
display: none;
|
||||||
::v-deep.hide .el-upload--picture-card {
|
}
|
||||||
display: none;
|
</style>
|
||||||
}
|
|
||||||
// 去掉动画效果
|
|
||||||
::v-deep .el-list-enter-active,
|
|
||||||
::v-deep .el-list-leave-active {
|
|
||||||
transition: all 0s;
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .el-list-enter, .el-list-leave-active {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@@ -1,114 +1,105 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="{'hidden':hidden}" class="pagination-container">
|
<div :class="{ 'hidden': hidden }" class="pagination-container">
|
||||||
<el-pagination
|
<el-pagination
|
||||||
:background="background"
|
:background="background"
|
||||||
:current-page.sync="currentPage"
|
v-model:current-page="currentPage"
|
||||||
:page-size.sync="pageSize"
|
v-model:page-size="pageSize"
|
||||||
:layout="layout"
|
:layout="layout"
|
||||||
:page-sizes="pageSizes"
|
:page-sizes="pageSizes"
|
||||||
:pager-count="pagerCount"
|
:pager-count="pagerCount"
|
||||||
:total="total"
|
:total="total"
|
||||||
v-bind="$attrs"
|
@size-change="handleSizeChange"
|
||||||
@size-change="handleSizeChange"
|
@current-change="handleCurrentChange"
|
||||||
@current-change="handleCurrentChange"
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</template>
|
|
||||||
|
<script setup>
|
||||||
<script>
|
import { scrollTo } from '@/utils/scroll-to'
|
||||||
import { scrollTo } from '@/utils/scroll-to'
|
|
||||||
|
const props = defineProps({
|
||||||
export default {
|
total: {
|
||||||
name: 'Pagination',
|
required: true,
|
||||||
props: {
|
type: Number
|
||||||
total: {
|
},
|
||||||
required: true,
|
page: {
|
||||||
type: Number
|
type: Number,
|
||||||
},
|
default: 1
|
||||||
page: {
|
},
|
||||||
type: Number,
|
limit: {
|
||||||
default: 1
|
type: Number,
|
||||||
},
|
default: 20
|
||||||
limit: {
|
},
|
||||||
type: Number,
|
pageSizes: {
|
||||||
default: 20
|
type: Array,
|
||||||
},
|
default() {
|
||||||
pageSizes: {
|
return [10, 20, 30, 50]
|
||||||
type: Array,
|
}
|
||||||
default() {
|
},
|
||||||
return [10, 20, 30, 50]
|
// 移动端页码按钮的数量端默认值5
|
||||||
}
|
pagerCount: {
|
||||||
},
|
type: Number,
|
||||||
// 移动端页码按钮的数量端默认值5
|
default: document.body.clientWidth < 992 ? 5 : 7
|
||||||
pagerCount: {
|
},
|
||||||
type: Number,
|
layout: {
|
||||||
default: document.body.clientWidth < 992 ? 5 : 7
|
type: String,
|
||||||
},
|
default: 'total, sizes, prev, pager, next, jumper'
|
||||||
layout: {
|
},
|
||||||
type: String,
|
background: {
|
||||||
default: 'total, sizes, prev, pager, next, jumper'
|
type: Boolean,
|
||||||
},
|
default: true
|
||||||
background: {
|
},
|
||||||
type: Boolean,
|
autoScroll: {
|
||||||
default: true
|
type: Boolean,
|
||||||
},
|
default: true
|
||||||
autoScroll: {
|
},
|
||||||
type: Boolean,
|
hidden: {
|
||||||
default: true
|
type: Boolean,
|
||||||
},
|
default: false
|
||||||
hidden: {
|
}
|
||||||
type: Boolean,
|
})
|
||||||
default: false
|
|
||||||
}
|
const emit = defineEmits();
|
||||||
},
|
const currentPage = computed({
|
||||||
data() {
|
get() {
|
||||||
return {
|
return props.page
|
||||||
};
|
},
|
||||||
},
|
set(val) {
|
||||||
computed: {
|
emit('update:page', val)
|
||||||
currentPage: {
|
}
|
||||||
get() {
|
})
|
||||||
return this.page
|
const pageSize = computed({
|
||||||
},
|
get() {
|
||||||
set(val) {
|
return props.limit
|
||||||
this.$emit('update:page', val)
|
},
|
||||||
}
|
set(val){
|
||||||
},
|
emit('update:limit', val)
|
||||||
pageSize: {
|
}
|
||||||
get() {
|
})
|
||||||
return this.limit
|
function handleSizeChange(val) {
|
||||||
},
|
if (currentPage.value * val > props.total) {
|
||||||
set(val) {
|
currentPage.value = 1
|
||||||
this.$emit('update:limit', val)
|
}
|
||||||
}
|
emit('pagination', { page: currentPage.value, limit: val })
|
||||||
}
|
if (props.autoScroll) {
|
||||||
},
|
scrollTo(0, 800)
|
||||||
methods: {
|
}
|
||||||
handleSizeChange(val) {
|
}
|
||||||
if (this.currentPage * val > this.total) {
|
function handleCurrentChange(val) {
|
||||||
this.currentPage = 1
|
emit('pagination', { page: val, limit: pageSize.value })
|
||||||
}
|
if (props.autoScroll) {
|
||||||
this.$emit('pagination', { page: this.currentPage, limit: val })
|
scrollTo(0, 800)
|
||||||
if (this.autoScroll) {
|
}
|
||||||
scrollTo(0, 800)
|
}
|
||||||
}
|
|
||||||
},
|
</script>
|
||||||
handleCurrentChange(val) {
|
|
||||||
this.$emit('pagination', { page: val, limit: this.pageSize })
|
<style scoped>
|
||||||
if (this.autoScroll) {
|
.pagination-container {
|
||||||
scrollTo(0, 800)
|
background: #fff;
|
||||||
}
|
padding: 32px 16px;
|
||||||
}
|
}
|
||||||
}
|
.pagination-container.hidden {
|
||||||
}
|
display: none;
|
||||||
</script>
|
}
|
||||||
|
</style>
|
||||||
<style scoped>
|
|
||||||
.pagination-container {
|
|
||||||
background: #fff;
|
|
||||||
padding: 32px 16px;
|
|
||||||
}
|
|
||||||
.pagination-container.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item">
|
|
||||||
<div class="pan-info">
|
|
||||||
<div class="pan-info-roles-container">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- eslint-disable-next-line -->
|
|
||||||
<div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'PanThumb',
|
|
||||||
props: {
|
|
||||||
image: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
zIndex: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
},
|
|
||||||
width: {
|
|
||||||
type: String,
|
|
||||||
default: '150px'
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: '150px'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.pan-item {
|
|
||||||
width: 200px;
|
|
||||||
height: 200px;
|
|
||||||
border-radius: 50%;
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
cursor: default;
|
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-info-roles-container {
|
|
||||||
padding: 20px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-thumb {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-position: center center;
|
|
||||||
background-size: cover;
|
|
||||||
border-radius: 50%;
|
|
||||||
overflow: hidden;
|
|
||||||
position: absolute;
|
|
||||||
transform-origin: 95% 40%;
|
|
||||||
transition: all 0.3s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .pan-thumb:after {
|
|
||||||
content: '';
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 50%;
|
|
||||||
top: 40%;
|
|
||||||
left: 95%;
|
|
||||||
margin: -4px 0 0 -4px;
|
|
||||||
background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%);
|
|
||||||
box-shadow: 0 0 1px rgba(255, 255, 255, 0.9);
|
|
||||||
} */
|
|
||||||
|
|
||||||
.pan-info {
|
|
||||||
position: absolute;
|
|
||||||
width: inherit;
|
|
||||||
height: inherit;
|
|
||||||
border-radius: 50%;
|
|
||||||
overflow: hidden;
|
|
||||||
box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-info h3 {
|
|
||||||
color: #fff;
|
|
||||||
text-transform: uppercase;
|
|
||||||
position: relative;
|
|
||||||
letter-spacing: 2px;
|
|
||||||
font-size: 18px;
|
|
||||||
margin: 0 60px;
|
|
||||||
padding: 22px 0 0 0;
|
|
||||||
height: 85px;
|
|
||||||
font-family: 'Open Sans', Arial, sans-serif;
|
|
||||||
text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-info p {
|
|
||||||
color: #fff;
|
|
||||||
padding: 10px 5px;
|
|
||||||
font-style: italic;
|
|
||||||
margin: 0 30px;
|
|
||||||
font-size: 12px;
|
|
||||||
border-top: 1px solid rgba(255, 255, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-info p a {
|
|
||||||
display: block;
|
|
||||||
color: #333;
|
|
||||||
width: 80px;
|
|
||||||
height: 80px;
|
|
||||||
background: rgba(255, 255, 255, 0.3);
|
|
||||||
border-radius: 50%;
|
|
||||||
color: #fff;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 700;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-size: 9px;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
padding-top: 24px;
|
|
||||||
margin: 7px auto 0;
|
|
||||||
font-family: 'Open Sans', Arial, sans-serif;
|
|
||||||
opacity: 0;
|
|
||||||
transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s;
|
|
||||||
transform: translateX(60px) rotate(90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-info p a:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-item:hover .pan-thumb {
|
|
||||||
transform: rotate(-110deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-item:hover .pan-info p a {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateX(0px) rotate(0deg);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div ref="rightPanel" class="rightPanel-container">
|
|
||||||
<div class="rightPanel-background" />
|
|
||||||
<div class="rightPanel">
|
|
||||||
<div class="rightPanel-items">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'RightPanel',
|
|
||||||
props: {
|
|
||||||
clickNotClose: {
|
|
||||||
default: false,
|
|
||||||
type: Boolean
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
show: {
|
|
||||||
get() {
|
|
||||||
return this.$store.state.settings.showSettings
|
|
||||||
},
|
|
||||||
set(val) {
|
|
||||||
this.$store.dispatch('settings/changeSetting', {
|
|
||||||
key: 'showSettings',
|
|
||||||
value: val
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
show(value) {
|
|
||||||
if (value && !this.clickNotClose) {
|
|
||||||
this.addEventClick()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.addEventClick()
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
const elx = this.$refs.rightPanel
|
|
||||||
elx.remove()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
addEventClick() {
|
|
||||||
window.addEventListener('click', this.closeSidebar)
|
|
||||||
},
|
|
||||||
closeSidebar(evt) {
|
|
||||||
const parent = evt.target.closest('.el-drawer__body')
|
|
||||||
if (!parent) {
|
|
||||||
this.show = false
|
|
||||||
window.removeEventListener('click', this.closeSidebar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.rightPanel-background {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity .3s cubic-bezier(.7, .3, .1, 1);
|
|
||||||
background: rgba(0, 0, 0, .2);
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightPanel {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 260px;
|
|
||||||
height: 100vh;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
|
|
||||||
transition: all .25s cubic-bezier(.7, .3, .1, 1);
|
|
||||||
transform: translate(100%);
|
|
||||||
background: #fff;
|
|
||||||
z-index: 40000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.handle-button {
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
position: absolute;
|
|
||||||
left: -48px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 24px;
|
|
||||||
border-radius: 6px 0 0 6px !important;
|
|
||||||
z-index: 0;
|
|
||||||
pointer-events: auto;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #fff;
|
|
||||||
line-height: 48px;
|
|
||||||
i {
|
|
||||||
font-size: 24px;
|
|
||||||
line-height: 48px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -2,26 +2,28 @@
|
|||||||
<div class="top-right-btn" :style="style">
|
<div class="top-right-btn" :style="style">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top" v-if="search">
|
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top" v-if="search">
|
||||||
<el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
|
<el-button circle icon="Search" @click="toggleSearch()" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
|
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
|
||||||
<el-button size="mini" circle icon="el-icon-refresh" @click="refresh()" />
|
<el-button circle icon="Refresh" @click="refresh()" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="columns">
|
<el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="columns">
|
||||||
<el-button size="mini" circle icon="el-icon-menu" @click="showColumn()" v-if="showColumnsType == 'transfer'"/>
|
<el-button circle icon="Menu" @click="showColumn()" v-if="showColumnsType == 'transfer'"/>
|
||||||
<el-dropdown trigger="click" :hide-on-click="false" style="padding-left: 12px" v-if="showColumnsType == 'checkbox'">
|
<el-dropdown trigger="click" :hide-on-click="false" style="padding-left: 12px" v-if="showColumnsType == 'checkbox'">
|
||||||
<el-button size="mini" circle icon="el-icon-menu" />
|
<el-button circle icon="Menu" />
|
||||||
<el-dropdown-menu slot="dropdown">
|
<template #dropdown>
|
||||||
<template v-for="item in columns">
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item :key="item.key">
|
<template v-for="item in columns" :key="item.key">
|
||||||
<el-checkbox :checked="item.visible" @change="checkboxChange($event, item.label)" :label="item.label" />
|
<el-dropdown-item>
|
||||||
</el-dropdown-item>
|
<el-checkbox :checked="item.visible" @change="checkboxChange($event, item.label)" :label="item.label" />
|
||||||
</template>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</template>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-dialog :title="title" :visible.sync="open" append-to-body>
|
<el-dialog :title="title" v-model="open" append-to-body>
|
||||||
<el-transfer
|
<el-transfer
|
||||||
:titles="['显示', '隐藏']"
|
:titles="['显示', '隐藏']"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
@@ -31,99 +33,102 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
|
||||||
export default {
|
<script setup>
|
||||||
name: "RightToolbar",
|
const props = defineProps({
|
||||||
data() {
|
/* 是否显示检索条件 */
|
||||||
return {
|
showSearch: {
|
||||||
// 显隐数据
|
type: Boolean,
|
||||||
value: [],
|
default: true,
|
||||||
// 弹出层标题
|
|
||||||
title: "显示/隐藏",
|
|
||||||
// 是否显示弹出层
|
|
||||||
open: false,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
props: {
|
/* 显隐列信息 */
|
||||||
/* 是否显示检索条件 */
|
columns: {
|
||||||
showSearch: {
|
type: Array,
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
/* 显隐列信息 */
|
|
||||||
columns: {
|
|
||||||
type: Array,
|
|
||||||
},
|
|
||||||
/* 是否显示检索图标 */
|
|
||||||
search: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
/* 显隐列类型(transfer穿梭框、checkbox复选框) */
|
|
||||||
showColumnsType: {
|
|
||||||
type: String,
|
|
||||||
default: "checkbox",
|
|
||||||
},
|
|
||||||
/* 右外边距 */
|
|
||||||
gutter: {
|
|
||||||
type: Number,
|
|
||||||
default: 10,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
computed: {
|
/* 是否显示检索图标 */
|
||||||
style() {
|
search: {
|
||||||
const ret = {};
|
type: Boolean,
|
||||||
if (this.gutter) {
|
default: true,
|
||||||
ret.marginRight = `${this.gutter / 2}px`;
|
},
|
||||||
}
|
/* 显隐列类型(transfer穿梭框、checkbox复选框) */
|
||||||
return ret;
|
showColumnsType: {
|
||||||
|
type: String,
|
||||||
|
default: "checkbox",
|
||||||
|
},
|
||||||
|
/* 右外边距 */
|
||||||
|
gutter: {
|
||||||
|
type: Number,
|
||||||
|
default: 10,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits(['update:showSearch', 'queryTable']);
|
||||||
|
|
||||||
|
// 显隐数据
|
||||||
|
const value = ref([]);
|
||||||
|
// 弹出层标题
|
||||||
|
const title = ref("显示/隐藏");
|
||||||
|
// 是否显示弹出层
|
||||||
|
const open = ref(false);
|
||||||
|
|
||||||
|
const style = computed(() => {
|
||||||
|
const ret = {};
|
||||||
|
if (props.gutter) {
|
||||||
|
ret.marginRight = `${props.gutter / 2}px`;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
function toggleSearch() {
|
||||||
|
emits("update:showSearch", !props.showSearch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新
|
||||||
|
function refresh() {
|
||||||
|
emits("queryTable");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧列表元素变化
|
||||||
|
function dataChange(data) {
|
||||||
|
for (let item in props.columns) {
|
||||||
|
const key = props.columns[item].key;
|
||||||
|
props.columns[item].visible = !data.includes(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开显隐列dialog
|
||||||
|
function showColumn() {
|
||||||
|
open.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.showColumnsType == 'transfer') {
|
||||||
|
// 显隐列初始默认隐藏列
|
||||||
|
for (let item in props.columns) {
|
||||||
|
if (props.columns[item].visible === false) {
|
||||||
|
value.value.push(parseInt(item));
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
created() {
|
}
|
||||||
if (this.showColumnsType == 'transfer') {
|
|
||||||
// 显隐列初始默认隐藏列
|
// 勾选
|
||||||
for (let item in this.columns) {
|
function checkboxChange(event, label) {
|
||||||
if (this.columns[item].visible === false) {
|
props.columns.filter(item => item.label == label)[0].visible = event;
|
||||||
this.value.push(parseInt(item));
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 搜索
|
|
||||||
toggleSearch() {
|
|
||||||
this.$emit("update:showSearch", !this.showSearch);
|
|
||||||
},
|
|
||||||
// 刷新
|
|
||||||
refresh() {
|
|
||||||
this.$emit("queryTable");
|
|
||||||
},
|
|
||||||
// 右侧列表元素变化
|
|
||||||
dataChange(data) {
|
|
||||||
for (let item in this.columns) {
|
|
||||||
const key = this.columns[item].key;
|
|
||||||
this.columns[item].visible = !data.includes(key);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 打开显隐列dialog
|
|
||||||
showColumn() {
|
|
||||||
this.open = true;
|
|
||||||
},
|
|
||||||
// 勾选
|
|
||||||
checkboxChange(event, label) {
|
|
||||||
this.columns.filter(item => item.label == label)[0].visible = event;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
|
||||||
::v-deep .el-transfer__button {
|
<style lang='scss' scoped>
|
||||||
|
:deep(.el-transfer__button) {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
padding: 12px;
|
|
||||||
display: block;
|
display: block;
|
||||||
margin-left: 0px;
|
margin-left: 0px;
|
||||||
}
|
}
|
||||||
::v-deep .el-transfer__button:first-child {
|
:deep(.el-transfer__button:first-child) {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
:deep(.el-dropdown-menu__item) {
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 0 17px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,18 +4,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
const url = ref('http://doc.ruoyi.vip/ruoyi-cloud');
|
||||||
name: 'RuoYiDoc',
|
|
||||||
data() {
|
function goto() {
|
||||||
return {
|
window.open(url.value)
|
||||||
url: 'http://doc.ruoyi.vip/ruoyi-cloud'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
goto() {
|
|
||||||
window.open(this.url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -4,18 +4,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
const url = ref('https://gitee.com/y_project/RuoYi-Cloud');
|
||||||
name: 'RuoYiGit',
|
|
||||||
data() {
|
function goto() {
|
||||||
return {
|
window.open(url.value)
|
||||||
url: 'https://gitee.com/y_project/RuoYi-Cloud'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
goto() {
|
|
||||||
window.open(this.url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,57 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" />
|
<svg-icon :icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'" @click="toggle" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import screenfull from 'screenfull'
|
import { useFullscreen } from '@vueuse/core'
|
||||||
|
|
||||||
export default {
|
const { isFullscreen, enter, exit, toggle } = useFullscreen();
|
||||||
name: 'Screenfull',
|
</script>
|
||||||
data() {
|
|
||||||
return {
|
<style lang='scss' scoped>
|
||||||
isFullscreen: false
|
.screenfull-svg {
|
||||||
}
|
display: inline-block;
|
||||||
},
|
cursor: pointer;
|
||||||
mounted() {
|
fill: #5a5e66;
|
||||||
this.init()
|
width: 20px;
|
||||||
},
|
height: 20px;
|
||||||
beforeDestroy() {
|
vertical-align: 10px;
|
||||||
this.destroy()
|
}
|
||||||
},
|
</style>
|
||||||
methods: {
|
|
||||||
click() {
|
|
||||||
if (!screenfull.isEnabled) {
|
|
||||||
this.$message({ message: '你的浏览器不支持全屏', type: 'warning' })
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
screenfull.toggle()
|
|
||||||
},
|
|
||||||
change() {
|
|
||||||
this.isFullscreen = screenfull.isFullscreen
|
|
||||||
},
|
|
||||||
init() {
|
|
||||||
if (screenfull.isEnabled) {
|
|
||||||
screenfull.on('change', this.change)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroy() {
|
|
||||||
if (screenfull.isEnabled) {
|
|
||||||
screenfull.off('change', this.change)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.screenfull-svg {
|
|
||||||
display: inline-block;
|
|
||||||
cursor: pointer;
|
|
||||||
fill: #5a5e66;;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
vertical-align: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,56 +1,45 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dropdown trigger="click" @command="handleSetSize">
|
<div>
|
||||||
<div>
|
<el-dropdown trigger="click" @command="handleSetSize">
|
||||||
<svg-icon class-name="size-icon" icon-class="size" />
|
<div class="size-icon--style">
|
||||||
</div>
|
<svg-icon class-name="size-icon" icon-class="size" />
|
||||||
<el-dropdown-menu slot="dropdown">
|
</div>
|
||||||
<el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size===item.value" :command="item.value">
|
<template #dropdown>
|
||||||
{{ item.label }}
|
<el-dropdown-menu>
|
||||||
</el-dropdown-item>
|
<el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size === item.value" :command="item.value">
|
||||||
</el-dropdown-menu>
|
{{ item.label }}
|
||||||
</el-dropdown>
|
</el-dropdown-item>
|
||||||
</template>
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
<script>
|
</el-dropdown>
|
||||||
export default {
|
</div>
|
||||||
data() {
|
</template>
|
||||||
return {
|
|
||||||
sizeOptions: [
|
<script setup>
|
||||||
{ label: 'Default', value: 'default' },
|
import useAppStore from "@/store/modules/app";
|
||||||
{ label: 'Medium', value: 'medium' },
|
|
||||||
{ label: 'Small', value: 'small' },
|
const appStore = useAppStore();
|
||||||
{ label: 'Mini', value: 'mini' }
|
const size = computed(() => appStore.size);
|
||||||
]
|
const route = useRoute();
|
||||||
}
|
const router = useRouter();
|
||||||
},
|
const { proxy } = getCurrentInstance();
|
||||||
computed: {
|
const sizeOptions = ref([
|
||||||
size() {
|
{ label: "较大", value: "large" },
|
||||||
return this.$store.getters.size
|
{ label: "默认", value: "default" },
|
||||||
}
|
{ label: "稍小", value: "small" },
|
||||||
},
|
]);
|
||||||
methods: {
|
|
||||||
handleSetSize(size) {
|
function handleSetSize(size) {
|
||||||
this.$ELEMENT.size = size
|
proxy.$modal.loading("正在设置布局大小,请稍候...");
|
||||||
this.$store.dispatch('app/setSize', size)
|
appStore.setSize(size);
|
||||||
this.refreshView()
|
setTimeout("window.location.reload()", 1000);
|
||||||
this.$message({
|
}
|
||||||
message: 'Switch Size Success',
|
</script>
|
||||||
type: 'success'
|
|
||||||
})
|
<style lang='scss' scoped>
|
||||||
},
|
.size-icon--style {
|
||||||
refreshView() {
|
font-size: 18px;
|
||||||
// In order to make the cached page re-rendered
|
line-height: 50px;
|
||||||
this.$store.dispatch('tagsView/delAllCachedViews', this.$route)
|
padding-right: 7px;
|
||||||
|
}
|
||||||
const { fullPath } = this.$route
|
</style>
|
||||||
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$router.replace({
|
|
||||||
path: '/redirect' + fullPath
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,61 +1,53 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
|
<svg :class="svgClass" aria-hidden="true">
|
||||||
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
|
<use :xlink:href="iconName" :fill="color" />
|
||||||
<use :xlink:href="iconName" />
|
</svg>
|
||||||
</svg>
|
</template>
|
||||||
</template>
|
|
||||||
|
<script>
|
||||||
<script>
|
export default defineComponent({
|
||||||
import { isExternal } from '@/utils/validate'
|
props: {
|
||||||
|
iconClass: {
|
||||||
export default {
|
type: String,
|
||||||
name: 'SvgIcon',
|
required: true
|
||||||
props: {
|
},
|
||||||
iconClass: {
|
className: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
default: ''
|
||||||
},
|
},
|
||||||
className: {
|
color: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
setup(props) {
|
||||||
isExternal() {
|
return {
|
||||||
return isExternal(this.iconClass)
|
iconName: computed(() => `#icon-${props.iconClass}`),
|
||||||
},
|
svgClass: computed(() => {
|
||||||
iconName() {
|
if (props.className) {
|
||||||
return `#icon-${this.iconClass}`
|
return `svg-icon ${props.className}`
|
||||||
},
|
}
|
||||||
svgClass() {
|
return 'svg-icon'
|
||||||
if (this.className) {
|
})
|
||||||
return 'svg-icon ' + this.className
|
}
|
||||||
} else {
|
}
|
||||||
return 'svg-icon'
|
})
|
||||||
}
|
</script>
|
||||||
},
|
|
||||||
styleExternalIcon() {
|
<style scope lang="scss">
|
||||||
return {
|
.sub-el-icon,
|
||||||
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
|
.nav-icon {
|
||||||
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
|
display: inline-block;
|
||||||
}
|
font-size: 15px;
|
||||||
}
|
margin-right: 12px;
|
||||||
}
|
position: relative;
|
||||||
}
|
}
|
||||||
</script>
|
|
||||||
|
.svg-icon {
|
||||||
<style scoped>
|
width: 1em;
|
||||||
.svg-icon {
|
height: 1em;
|
||||||
width: 1em;
|
position: relative;
|
||||||
height: 1em;
|
fill: currentColor;
|
||||||
vertical-align: -0.15em;
|
vertical-align: -2px;
|
||||||
fill: currentColor;
|
}
|
||||||
overflow: hidden;
|
</style>
|
||||||
}
|
|
||||||
|
|
||||||
.svg-external-icon {
|
|
||||||
background-color: currentColor;
|
|
||||||
mask-size: cover!important;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
10
ruoyi-ui/src/components/SvgIcon/svgicon.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import * as components from '@element-plus/icons-vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
install: (app) => {
|
||||||
|
for (const key in components) {
|
||||||
|
const componentConfig = components[key];
|
||||||
|
app.component(componentConfig.name, componentConfig);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-color-picker
|
|
||||||
v-model="theme"
|
|
||||||
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
|
|
||||||
class="theme-picker"
|
|
||||||
popper-class="theme-picker-dropdown"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const version = require('element-ui/package.json').version // element-ui version from node_modules
|
|
||||||
const ORIGINAL_THEME = '#409EFF' // default color
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chalk: '', // content of theme-chalk css
|
|
||||||
theme: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
defaultTheme() {
|
|
||||||
return this.$store.state.settings.theme
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
defaultTheme: {
|
|
||||||
handler: function(val, oldVal) {
|
|
||||||
this.theme = val
|
|
||||||
},
|
|
||||||
immediate: true
|
|
||||||
},
|
|
||||||
async theme(val) {
|
|
||||||
await this.setTheme(val)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
if(this.defaultTheme !== ORIGINAL_THEME) {
|
|
||||||
this.setTheme(this.defaultTheme)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
async setTheme(val) {
|
|
||||||
const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
|
|
||||||
if (typeof val !== 'string') return
|
|
||||||
const themeCluster = this.getThemeCluster(val.replace('#', ''))
|
|
||||||
const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
|
|
||||||
|
|
||||||
const getHandler = (variable, id) => {
|
|
||||||
return () => {
|
|
||||||
const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
|
|
||||||
const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
|
|
||||||
|
|
||||||
let styleTag = document.getElementById(id)
|
|
||||||
if (!styleTag) {
|
|
||||||
styleTag = document.createElement('style')
|
|
||||||
styleTag.setAttribute('id', id)
|
|
||||||
document.head.appendChild(styleTag)
|
|
||||||
}
|
|
||||||
styleTag.innerText = newStyle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.chalk) {
|
|
||||||
const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
|
|
||||||
await this.getCSSString(url, 'chalk')
|
|
||||||
}
|
|
||||||
|
|
||||||
const chalkHandler = getHandler('chalk', 'chalk-style')
|
|
||||||
|
|
||||||
chalkHandler()
|
|
||||||
|
|
||||||
const styles = [].slice.call(document.querySelectorAll('style'))
|
|
||||||
.filter(style => {
|
|
||||||
const text = style.innerText
|
|
||||||
return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
|
|
||||||
})
|
|
||||||
styles.forEach(style => {
|
|
||||||
const { innerText } = style
|
|
||||||
if (typeof innerText !== 'string') return
|
|
||||||
style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.$emit('change', val)
|
|
||||||
},
|
|
||||||
|
|
||||||
updateStyle(style, oldCluster, newCluster) {
|
|
||||||
let newStyle = style
|
|
||||||
oldCluster.forEach((color, index) => {
|
|
||||||
newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
|
|
||||||
})
|
|
||||||
return newStyle
|
|
||||||
},
|
|
||||||
|
|
||||||
getCSSString(url, variable) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
const xhr = new XMLHttpRequest()
|
|
||||||
xhr.onreadystatechange = () => {
|
|
||||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
|
||||||
this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
|
|
||||||
resolve()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xhr.open('GET', url)
|
|
||||||
xhr.send()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
getThemeCluster(theme) {
|
|
||||||
const tintColor = (color, tint) => {
|
|
||||||
let red = parseInt(color.slice(0, 2), 16)
|
|
||||||
let green = parseInt(color.slice(2, 4), 16)
|
|
||||||
let blue = parseInt(color.slice(4, 6), 16)
|
|
||||||
|
|
||||||
if (tint === 0) { // when primary color is in its rgb space
|
|
||||||
return [red, green, blue].join(',')
|
|
||||||
} else {
|
|
||||||
red += Math.round(tint * (255 - red))
|
|
||||||
green += Math.round(tint * (255 - green))
|
|
||||||
blue += Math.round(tint * (255 - blue))
|
|
||||||
|
|
||||||
red = red.toString(16)
|
|
||||||
green = green.toString(16)
|
|
||||||
blue = blue.toString(16)
|
|
||||||
|
|
||||||
return `#${red}${green}${blue}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const shadeColor = (color, shade) => {
|
|
||||||
let red = parseInt(color.slice(0, 2), 16)
|
|
||||||
let green = parseInt(color.slice(2, 4), 16)
|
|
||||||
let blue = parseInt(color.slice(4, 6), 16)
|
|
||||||
|
|
||||||
red = Math.round((1 - shade) * red)
|
|
||||||
green = Math.round((1 - shade) * green)
|
|
||||||
blue = Math.round((1 - shade) * blue)
|
|
||||||
|
|
||||||
red = red.toString(16)
|
|
||||||
green = green.toString(16)
|
|
||||||
blue = blue.toString(16)
|
|
||||||
|
|
||||||
return `#${red}${green}${blue}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const clusters = [theme]
|
|
||||||
for (let i = 0; i <= 9; i++) {
|
|
||||||
clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
|
|
||||||
}
|
|
||||||
clusters.push(shadeColor(theme, 0.1))
|
|
||||||
return clusters
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.theme-message,
|
|
||||||
.theme-picker-dropdown {
|
|
||||||
z-index: 99999 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-picker .el-color-picker__trigger {
|
|
||||||
height: 26px !important;
|
|
||||||
width: 26px !important;
|
|
||||||
padding: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-picker-dropdown .el-color-dropdown__link-btn {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
:default-active="activeMenu"
|
:default-active="activeMenu"
|
||||||
mode="horizontal"
|
mode="horizontal"
|
||||||
@select="handleSelect"
|
@select="handleSelect"
|
||||||
|
:ellipsis="false"
|
||||||
>
|
>
|
||||||
<template v-for="(item, index) in topMenus">
|
<template v-for="(item, index) in topMenus">
|
||||||
<el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber">
|
<el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber">
|
||||||
@@ -14,158 +15,158 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 顶部菜单超出数量折叠 -->
|
<!-- 顶部菜单超出数量折叠 -->
|
||||||
<el-submenu :style="{'--theme': theme}" index="more" v-if="topMenus.length > visibleNumber">
|
<el-sub-menu :style="{'--theme': theme}" index="more" v-if="topMenus.length > visibleNumber">
|
||||||
<template slot="title">更多菜单</template>
|
<template #title>更多菜单</template>
|
||||||
<template v-for="(item, index) in topMenus">
|
<template v-for="(item, index) in topMenus">
|
||||||
<el-menu-item
|
<el-menu-item
|
||||||
:index="item.path"
|
:index="item.path"
|
||||||
:key="index"
|
:key="index"
|
||||||
v-if="index >= visibleNumber">
|
v-if="index >= visibleNumber">
|
||||||
<svg-icon
|
<svg-icon
|
||||||
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
|
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
|
||||||
:icon-class="item.meta.icon"/>
|
:icon-class="item.meta.icon"/>
|
||||||
{{ item.meta.title }}
|
{{ item.meta.title }}
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</template>
|
</template>
|
||||||
</el-submenu>
|
</el-sub-menu>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import { constantRoutes } from "@/router";
|
import { constantRoutes } from "@/router"
|
||||||
|
import { isHttp } from '@/utils/validate'
|
||||||
|
import useAppStore from '@/store/modules/app'
|
||||||
|
import useSettingsStore from '@/store/modules/settings'
|
||||||
|
import usePermissionStore from '@/store/modules/permission'
|
||||||
|
|
||||||
|
// 顶部栏初始数
|
||||||
|
const visibleNumber = ref(null);
|
||||||
|
// 当前激活菜单的 index
|
||||||
|
const currentIndex = ref(null);
|
||||||
// 隐藏侧边栏路由
|
// 隐藏侧边栏路由
|
||||||
const hideList = ['/index', '/user/profile'];
|
const hideList = ['/index', '/user/profile'];
|
||||||
|
|
||||||
export default {
|
const appStore = useAppStore()
|
||||||
data() {
|
const settingsStore = useSettingsStore()
|
||||||
return {
|
const permissionStore = usePermissionStore()
|
||||||
// 顶部栏初始数
|
const route = useRoute();
|
||||||
visibleNumber: 5,
|
const router = useRouter();
|
||||||
// 当前激活菜单的 index
|
|
||||||
currentIndex: undefined
|
// 主题颜色
|
||||||
};
|
const theme = computed(() => settingsStore.theme);
|
||||||
},
|
// 所有的路由信息
|
||||||
computed: {
|
const routers = computed(() => permissionStore.topbarRouters);
|
||||||
theme() {
|
|
||||||
return this.$store.state.settings.theme;
|
// 顶部显示菜单
|
||||||
},
|
const topMenus = computed(() => {
|
||||||
// 顶部显示菜单
|
let topMenus = [];
|
||||||
topMenus() {
|
routers.value.map((menu) => {
|
||||||
let topMenus = [];
|
if (menu.hidden !== true) {
|
||||||
this.routers.map((menu) => {
|
// 兼容顶部栏一级菜单内部跳转
|
||||||
if (menu.hidden !== true) {
|
if (menu.path === "/") {
|
||||||
// 兼容顶部栏一级菜单内部跳转
|
topMenus.push(menu.children[0]);
|
||||||
if (menu.path === "/") {
|
|
||||||
topMenus.push(menu.children[0]);
|
|
||||||
} else {
|
|
||||||
topMenus.push(menu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return topMenus;
|
|
||||||
},
|
|
||||||
// 所有的路由信息
|
|
||||||
routers() {
|
|
||||||
return this.$store.state.permission.topbarRouters;
|
|
||||||
},
|
|
||||||
// 设置子路由
|
|
||||||
childrenMenus() {
|
|
||||||
var childrenMenus = [];
|
|
||||||
this.routers.map((router) => {
|
|
||||||
for (var item in router.children) {
|
|
||||||
if (router.children[item].parentPath === undefined) {
|
|
||||||
if(router.path === "/") {
|
|
||||||
router.children[item].path = "/" + router.children[item].path;
|
|
||||||
} else {
|
|
||||||
if(!this.ishttp(router.children[item].path)) {
|
|
||||||
router.children[item].path = router.path + "/" + router.children[item].path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
router.children[item].parentPath = router.path;
|
|
||||||
}
|
|
||||||
childrenMenus.push(router.children[item]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return constantRoutes.concat(childrenMenus);
|
|
||||||
},
|
|
||||||
// 默认激活的菜单
|
|
||||||
activeMenu() {
|
|
||||||
const path = this.$route.path;
|
|
||||||
let activePath = path;
|
|
||||||
if (path !== undefined && path.lastIndexOf("/") > 0 && hideList.indexOf(path) === -1) {
|
|
||||||
const tmpPath = path.substring(1, path.length);
|
|
||||||
activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/"));
|
|
||||||
if (!this.$route.meta.link) {
|
|
||||||
this.$store.dispatch('app/toggleSideBarHide', false);
|
|
||||||
}
|
|
||||||
} else if(!this.$route.children) {
|
|
||||||
activePath = path;
|
|
||||||
this.$store.dispatch('app/toggleSideBarHide', true);
|
|
||||||
}
|
|
||||||
this.activeRoutes(activePath);
|
|
||||||
return activePath;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
beforeMount() {
|
|
||||||
window.addEventListener('resize', this.setVisibleNumber)
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
window.removeEventListener('resize', this.setVisibleNumber)
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.setVisibleNumber();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 根据宽度计算设置显示栏数
|
|
||||||
setVisibleNumber() {
|
|
||||||
const width = document.body.getBoundingClientRect().width / 3;
|
|
||||||
this.visibleNumber = parseInt(width / 85);
|
|
||||||
},
|
|
||||||
// 菜单选择事件
|
|
||||||
handleSelect(key, keyPath) {
|
|
||||||
this.currentIndex = key;
|
|
||||||
const route = this.routers.find(item => item.path === key);
|
|
||||||
if (this.ishttp(key)) {
|
|
||||||
// http(s):// 路径新窗口打开
|
|
||||||
window.open(key, "_blank");
|
|
||||||
} else if (!route || !route.children) {
|
|
||||||
// 没有子路由路径内部打开
|
|
||||||
const routeMenu = this.childrenMenus.find(item => item.path === key);
|
|
||||||
if (routeMenu && routeMenu.query) {
|
|
||||||
let query = JSON.parse(routeMenu.query);
|
|
||||||
this.$router.push({ path: key, query: query });
|
|
||||||
} else {
|
|
||||||
this.$router.push({ path: key });
|
|
||||||
}
|
|
||||||
this.$store.dispatch('app/toggleSideBarHide', true);
|
|
||||||
} else {
|
} else {
|
||||||
// 显示左侧联动菜单
|
topMenus.push(menu);
|
||||||
this.activeRoutes(key);
|
|
||||||
this.$store.dispatch('app/toggleSideBarHide', false);
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
// 当前激活的路由
|
|
||||||
activeRoutes(key) {
|
|
||||||
var routes = [];
|
|
||||||
if (this.childrenMenus && this.childrenMenus.length > 0) {
|
|
||||||
this.childrenMenus.map((item) => {
|
|
||||||
if (key == item.parentPath || (key == "index" && "" == item.path)) {
|
|
||||||
routes.push(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if(routes.length > 0) {
|
|
||||||
this.$store.commit("SET_SIDEBAR_ROUTERS", routes);
|
|
||||||
} else {
|
|
||||||
this.$store.dispatch('app/toggleSideBarHide', true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ishttp(url) {
|
|
||||||
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
|
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
};
|
return topMenus;
|
||||||
|
})
|
||||||
|
|
||||||
|
// 设置子路由
|
||||||
|
const childrenMenus = computed(() => {
|
||||||
|
let childrenMenus = [];
|
||||||
|
routers.value.map((router) => {
|
||||||
|
for (let item in router.children) {
|
||||||
|
if (router.children[item].parentPath === undefined) {
|
||||||
|
if(router.path === "/") {
|
||||||
|
router.children[item].path = "/" + router.children[item].path;
|
||||||
|
} else {
|
||||||
|
if(!isHttp(router.children[item].path)) {
|
||||||
|
router.children[item].path = router.path + "/" + router.children[item].path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
router.children[item].parentPath = router.path;
|
||||||
|
}
|
||||||
|
childrenMenus.push(router.children[item]);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return constantRoutes.concat(childrenMenus);
|
||||||
|
})
|
||||||
|
|
||||||
|
// 默认激活的菜单
|
||||||
|
const activeMenu = computed(() => {
|
||||||
|
const path = route.path;
|
||||||
|
let activePath = path;
|
||||||
|
if (path !== undefined && path.lastIndexOf("/") > 0 && hideList.indexOf(path) === -1) {
|
||||||
|
const tmpPath = path.substring(1, path.length);
|
||||||
|
activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/"));
|
||||||
|
if (!route.meta.link) {
|
||||||
|
appStore.toggleSideBarHide(false);
|
||||||
|
}
|
||||||
|
} else if(!route.children) {
|
||||||
|
activePath = path;
|
||||||
|
appStore.toggleSideBarHide(true);
|
||||||
|
}
|
||||||
|
activeRoutes(activePath);
|
||||||
|
return activePath;
|
||||||
|
})
|
||||||
|
|
||||||
|
function setVisibleNumber() {
|
||||||
|
const width = document.body.getBoundingClientRect().width / 3;
|
||||||
|
visibleNumber.value = parseInt(width / 85);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelect(key, keyPath) {
|
||||||
|
currentIndex.value = key;
|
||||||
|
const route = routers.value.find(item => item.path === key);
|
||||||
|
if (isHttp(key)) {
|
||||||
|
// http(s):// 路径新窗口打开
|
||||||
|
window.open(key, "_blank");
|
||||||
|
} else if (!route || !route.children) {
|
||||||
|
// 没有子路由路径内部打开
|
||||||
|
const routeMenu = childrenMenus.value.find(item => item.path === key);
|
||||||
|
if (routeMenu && routeMenu.query) {
|
||||||
|
let query = JSON.parse(routeMenu.query);
|
||||||
|
router.push({ path: key, query: query });
|
||||||
|
} else {
|
||||||
|
router.push({ path: key });
|
||||||
|
}
|
||||||
|
appStore.toggleSideBarHide(true);
|
||||||
|
} else {
|
||||||
|
// 显示左侧联动菜单
|
||||||
|
activeRoutes(key);
|
||||||
|
appStore.toggleSideBarHide(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function activeRoutes(key) {
|
||||||
|
let routes = [];
|
||||||
|
if (childrenMenus.value && childrenMenus.value.length > 0) {
|
||||||
|
childrenMenus.value.map((item) => {
|
||||||
|
if (key == item.parentPath || (key == "index" && "" == item.path)) {
|
||||||
|
routes.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if(routes.length > 0) {
|
||||||
|
permissionStore.setSidebarRouters(routes);
|
||||||
|
} else {
|
||||||
|
appStore.toggleSideBarHide(true);
|
||||||
|
}
|
||||||
|
return routes;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
window.addEventListener('resize', setVisibleNumber)
|
||||||
|
})
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('resize', setVisibleNumber)
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setVisibleNumber()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@@ -178,13 +179,13 @@ export default {
|
|||||||
margin: 0 10px !important;
|
margin: 0 10px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topmenu-container.el-menu--horizontal > .el-menu-item.is-active, .el-menu--horizontal > .el-submenu.is-active .el-submenu__title {
|
.topmenu-container.el-menu--horizontal > .el-menu-item.is-active, .el-menu--horizontal > .el-sub-menu.is-active .el-submenu__title {
|
||||||
border-bottom: 2px solid #{'var(--theme)'} !important;
|
border-bottom: 2px solid #{'var(--theme)'} !important;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* submenu item */
|
/* sub-menu item */
|
||||||
.topmenu-container.el-menu--horizontal > .el-submenu .el-submenu__title {
|
.topmenu-container.el-menu--horizontal > .el-sub-menu .el-sub-menu__title {
|
||||||
float: left;
|
float: left;
|
||||||
height: 50px !important;
|
height: 50px !important;
|
||||||
line-height: 50px !important;
|
line-height: 50px !important;
|
||||||
@@ -192,4 +193,22 @@ export default {
|
|||||||
padding: 0 5px !important;
|
padding: 0 5px !important;
|
||||||
margin: 0 10px !important;
|
margin: 0 10px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 背景色隐藏 */
|
||||||
|
.topmenu-container.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus, .topmenu-container.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover, .topmenu-container.el-menu--horizontal>.el-submenu .el-submenu__title:hover {
|
||||||
|
background-color: #ffffff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 图标右间距 */
|
||||||
|
.topmenu-container .svg-icon {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* topmenu more arrow */
|
||||||
|
.topmenu-container .el-sub-menu .el-sub-menu__icon-arrow {
|
||||||
|
position: static;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
156
ruoyi-ui/src/components/TreeSelect/index.vue
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
<template>
|
||||||
|
<div class="el-tree-select">
|
||||||
|
<el-select
|
||||||
|
style="width: 100%"
|
||||||
|
v-model="valueId"
|
||||||
|
ref="treeSelect"
|
||||||
|
:filterable="true"
|
||||||
|
:clearable="true"
|
||||||
|
@clear="clearHandle"
|
||||||
|
:filter-method="selectFilterData"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
>
|
||||||
|
<el-option :value="valueId" :label="valueTitle">
|
||||||
|
<el-tree
|
||||||
|
id="tree-option"
|
||||||
|
ref="selectTree"
|
||||||
|
:accordion="accordion"
|
||||||
|
:data="options"
|
||||||
|
:props="objMap"
|
||||||
|
:node-key="objMap.value"
|
||||||
|
:expand-on-click-node="false"
|
||||||
|
:default-expanded-keys="defaultExpandedKey"
|
||||||
|
:filter-node-method="filterNode"
|
||||||
|
@node-click="handleNodeClick"
|
||||||
|
></el-tree>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
/* 配置项 */
|
||||||
|
objMap: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
value: 'id', // ID字段名
|
||||||
|
label: 'label', // 显示名称
|
||||||
|
children: 'children' // 子级字段名
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* 自动收起 */
|
||||||
|
accordion: {
|
||||||
|
type: Boolean,
|
||||||
|
default: () => {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**当前双向数据绑定的值 */
|
||||||
|
value: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
/**当前的数据 */
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
/**输入框内部的文字 */
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:value']);
|
||||||
|
|
||||||
|
const valueId = computed({
|
||||||
|
get: () => props.value,
|
||||||
|
set: (val) => {
|
||||||
|
emit('update:value', val)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const valueTitle = ref('');
|
||||||
|
const defaultExpandedKey = ref([]);
|
||||||
|
|
||||||
|
function initHandle() {
|
||||||
|
nextTick(() => {
|
||||||
|
const selectedValue = valueId.value;
|
||||||
|
if(selectedValue !== null && typeof (selectedValue) !== 'undefined') {
|
||||||
|
const node = proxy.$refs.selectTree.getNode(selectedValue)
|
||||||
|
if (node) {
|
||||||
|
valueTitle.value = node.data[props.objMap.label]
|
||||||
|
proxy.$refs.selectTree.setCurrentKey(selectedValue) // 设置默认选中
|
||||||
|
defaultExpandedKey.value = [selectedValue] // 设置默认展开
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clearHandle()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function handleNodeClick(node) {
|
||||||
|
valueTitle.value = node[props.objMap.label]
|
||||||
|
valueId.value = node[props.objMap.value];
|
||||||
|
defaultExpandedKey.value = [];
|
||||||
|
proxy.$refs.treeSelect.blur()
|
||||||
|
selectFilterData('')
|
||||||
|
}
|
||||||
|
function selectFilterData(val) {
|
||||||
|
proxy.$refs.selectTree.filter(val)
|
||||||
|
}
|
||||||
|
function filterNode(value, data) {
|
||||||
|
if (!value) return true
|
||||||
|
return data[props.objMap['label']].indexOf(value) !== -1
|
||||||
|
}
|
||||||
|
function clearHandle() {
|
||||||
|
valueTitle.value = ''
|
||||||
|
valueId.value = ''
|
||||||
|
defaultExpandedKey.value = [];
|
||||||
|
clearSelected()
|
||||||
|
}
|
||||||
|
function clearSelected() {
|
||||||
|
const allNode = document.querySelectorAll('#tree-option .el-tree-node')
|
||||||
|
allNode.forEach((element) => element.classList.remove('is-current'))
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
initHandle()
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(valueId, () => {
|
||||||
|
initHandle();
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
@import "@/assets/styles/variables.module.scss";
|
||||||
|
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
|
||||||
|
padding: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-select-dropdown__item.selected {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul li .el-tree .el-tree-node__content {
|
||||||
|
height: auto;
|
||||||
|
padding: 0 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-tree-node__content:hover),
|
||||||
|
:deep(.el-tree-node__content:active),
|
||||||
|
:deep(.is-current > div:first-child),
|
||||||
|
:deep(.el-tree-node__content:focus) {
|
||||||
|
background-color: mix(#fff, $--color-primary, 90%);
|
||||||
|
color: $--color-primary;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,36 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-loading="loading" :style="'height:' + height">
|
<div v-loading="loading" :style="'height:' + height">
|
||||||
<iframe
|
<iframe
|
||||||
:src="src"
|
:src="url"
|
||||||
frameborder="no"
|
frameborder="no"
|
||||||
style="width: 100%; height: 100%"
|
style="width: 100%; height: 100%"
|
||||||
scrolling="auto"
|
scrolling="auto" />
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
|
||||||
export default {
|
<script setup>
|
||||||
props: {
|
const props = defineProps({
|
||||||
src: {
|
src: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
height: document.documentElement.clientHeight - 94.5 + "px;",
|
|
||||||
loading: true,
|
|
||||||
url: this.src
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted: function () {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.loading = false;
|
|
||||||
}, 300);
|
|
||||||
const that = this;
|
|
||||||
window.onresize = function temp() {
|
|
||||||
that.height = document.documentElement.clientHeight - 94.5 + "px;";
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
})
|
||||||
|
|
||||||
|
const height = ref(document.documentElement.clientHeight - 94.5 + "px;")
|
||||||
|
const loading = ref(true)
|
||||||
|
const url = computed(() => props.src)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = false;
|
||||||
|
}, 300);
|
||||||
|
window.onresize = function temp() {
|
||||||
|
height.value = document.documentElement.clientHeight - 94.5 + "px;";
|
||||||
|
};
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
66
ruoyi-ui/src/directive/common/copyText.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* v-copyText 复制文本内容
|
||||||
|
* Copyright (c) 2022 ruoyi
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
beforeMount(el, { value, arg }) {
|
||||||
|
if (arg === "callback") {
|
||||||
|
el.$copyCallback = value;
|
||||||
|
} else {
|
||||||
|
el.$copyValue = value;
|
||||||
|
const handler = () => {
|
||||||
|
copyTextToClipboard(el.$copyValue);
|
||||||
|
if (el.$copyCallback) {
|
||||||
|
el.$copyCallback(el.$copyValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
el.addEventListener("click", handler);
|
||||||
|
el.$destroyCopy = () => el.removeEventListener("click", handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyTextToClipboard(input, { target = document.body } = {}) {
|
||||||
|
const element = document.createElement('textarea');
|
||||||
|
const previouslyFocusedElement = document.activeElement;
|
||||||
|
|
||||||
|
element.value = input;
|
||||||
|
|
||||||
|
// Prevent keyboard from showing on mobile
|
||||||
|
element.setAttribute('readonly', '');
|
||||||
|
|
||||||
|
element.style.contain = 'strict';
|
||||||
|
element.style.position = 'absolute';
|
||||||
|
element.style.left = '-9999px';
|
||||||
|
element.style.fontSize = '12pt'; // Prevent zooming on iOS
|
||||||
|
|
||||||
|
const selection = document.getSelection();
|
||||||
|
const originalRange = selection.rangeCount > 0 && selection.getRangeAt(0);
|
||||||
|
|
||||||
|
target.append(element);
|
||||||
|
element.select();
|
||||||
|
|
||||||
|
// Explicit selection workaround for iOS
|
||||||
|
element.selectionStart = 0;
|
||||||
|
element.selectionEnd = input.length;
|
||||||
|
|
||||||
|
let isSuccess = false;
|
||||||
|
try {
|
||||||
|
isSuccess = document.execCommand('copy');
|
||||||
|
} catch { }
|
||||||
|
|
||||||
|
element.remove();
|
||||||
|
|
||||||
|
if (originalRange) {
|
||||||
|
selection.removeAllRanges();
|
||||||
|
selection.addRange(originalRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the focus back on the previously focused element, if any
|
||||||
|
if (previouslyFocusedElement) {
|
||||||
|
previouslyFocusedElement.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
return isSuccess;
|
||||||
|
}
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
/**
|
|
||||||
* v-dialogDrag 弹窗拖拽
|
|
||||||
* Copyright (c) 2019 ruoyi
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default {
|
|
||||||
bind(el, binding, vnode, oldVnode) {
|
|
||||||
const value = binding.value
|
|
||||||
if (value == false) return
|
|
||||||
// 获取拖拽内容头部
|
|
||||||
const dialogHeaderEl = el.querySelector('.el-dialog__header');
|
|
||||||
const dragDom = el.querySelector('.el-dialog');
|
|
||||||
dialogHeaderEl.style.cursor = 'move';
|
|
||||||
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
|
|
||||||
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null);
|
|
||||||
dragDom.style.position = 'absolute';
|
|
||||||
dragDom.style.marginTop = 0;
|
|
||||||
let width = dragDom.style.width;
|
|
||||||
if (width.includes('%')) {
|
|
||||||
width = +document.body.clientWidth * (+width.replace(/\%/g, '') / 100);
|
|
||||||
} else {
|
|
||||||
width = +width.replace(/\px/g, '');
|
|
||||||
}
|
|
||||||
dragDom.style.left = `${(document.body.clientWidth - width) / 2}px`;
|
|
||||||
// 鼠标按下事件
|
|
||||||
dialogHeaderEl.onmousedown = (e) => {
|
|
||||||
// 鼠标按下,计算当前元素距离可视区的距离 (鼠标点击位置距离可视窗口的距离)
|
|
||||||
const disX = e.clientX - dialogHeaderEl.offsetLeft;
|
|
||||||
const disY = e.clientY - dialogHeaderEl.offsetTop;
|
|
||||||
|
|
||||||
// 获取到的值带px 正则匹配替换
|
|
||||||
let styL, styT;
|
|
||||||
|
|
||||||
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
|
|
||||||
if (sty.left.includes('%')) {
|
|
||||||
styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100);
|
|
||||||
styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100);
|
|
||||||
} else {
|
|
||||||
styL = +sty.left.replace(/\px/g, '');
|
|
||||||
styT = +sty.top.replace(/\px/g, '');
|
|
||||||
};
|
|
||||||
|
|
||||||
// 鼠标拖拽事件
|
|
||||||
document.onmousemove = function (e) {
|
|
||||||
// 通过事件委托,计算移动的距离 (开始拖拽至结束拖拽的距离)
|
|
||||||
const l = e.clientX - disX;
|
|
||||||
const t = e.clientY - disY;
|
|
||||||
|
|
||||||
let finallyL = l + styL
|
|
||||||
let finallyT = t + styT
|
|
||||||
|
|
||||||
// 移动当前元素
|
|
||||||
dragDom.style.left = `${finallyL}px`;
|
|
||||||
dragDom.style.top = `${finallyT}px`;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
document.onmouseup = function (e) {
|
|
||||||
document.onmousemove = null;
|
|
||||||
document.onmouseup = null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/**
|
|
||||||
* v-dialogDragWidth 可拖动弹窗高度(右下角)
|
|
||||||
* Copyright (c) 2019 ruoyi
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default {
|
|
||||||
bind(el) {
|
|
||||||
const dragDom = el.querySelector('.el-dialog');
|
|
||||||
const lineEl = document.createElement('div');
|
|
||||||
lineEl.style = 'width: 6px; background: inherit; height: 10px; position: absolute; right: 0; bottom: 0; margin: auto; z-index: 1; cursor: nwse-resize;';
|
|
||||||
lineEl.addEventListener('mousedown',
|
|
||||||
function(e) {
|
|
||||||
// 鼠标按下,计算当前元素距离可视区的距离
|
|
||||||
const disX = e.clientX - el.offsetLeft;
|
|
||||||
const disY = e.clientY - el.offsetTop;
|
|
||||||
// 当前宽度 高度
|
|
||||||
const curWidth = dragDom.offsetWidth;
|
|
||||||
const curHeight = dragDom.offsetHeight;
|
|
||||||
document.onmousemove = function(e) {
|
|
||||||
e.preventDefault(); // 移动时禁用默认事件
|
|
||||||
// 通过事件委托,计算移动的距离
|
|
||||||
const xl = e.clientX - disX;
|
|
||||||
const yl = e.clientY - disY
|
|
||||||
dragDom.style.width = `${curWidth + xl}px`;
|
|
||||||
dragDom.style.height = `${curHeight + yl}px`;
|
|
||||||
};
|
|
||||||
document.onmouseup = function(e) {
|
|
||||||
document.onmousemove = null;
|
|
||||||
document.onmouseup = null;
|
|
||||||
};
|
|
||||||
}, false);
|
|
||||||
dragDom.appendChild(lineEl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
/**
|
|
||||||
* v-dialogDragWidth 可拖动弹窗宽度(右侧边)
|
|
||||||
* Copyright (c) 2019 ruoyi
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default {
|
|
||||||
bind(el) {
|
|
||||||
const dragDom = el.querySelector('.el-dialog');
|
|
||||||
const lineEl = document.createElement('div');
|
|
||||||
lineEl.style = 'width: 5px; background: inherit; height: 80%; position: absolute; right: 0; top: 0; bottom: 0; margin: auto; z-index: 1; cursor: w-resize;';
|
|
||||||
lineEl.addEventListener('mousedown',
|
|
||||||
function (e) {
|
|
||||||
// 鼠标按下,计算当前元素距离可视区的距离
|
|
||||||
const disX = e.clientX - el.offsetLeft;
|
|
||||||
// 当前宽度
|
|
||||||
const curWidth = dragDom.offsetWidth;
|
|
||||||
document.onmousemove = function (e) {
|
|
||||||
e.preventDefault(); // 移动时禁用默认事件
|
|
||||||
// 通过事件委托,计算移动的距离
|
|
||||||
const l = e.clientX - disX;
|
|
||||||
dragDom.style.width = `${curWidth + l}px`;
|
|
||||||
};
|
|
||||||
document.onmouseup = function (e) {
|
|
||||||
document.onmousemove = null;
|
|
||||||
document.onmouseup = null;
|
|
||||||
};
|
|
||||||
}, false);
|
|
||||||
dragDom.appendChild(lineEl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +1,9 @@
|
|||||||
import hasRole from './permission/hasRole'
|
import hasRole from './permission/hasRole'
|
||||||
import hasPermi from './permission/hasPermi'
|
import hasPermi from './permission/hasPermi'
|
||||||
import dialogDrag from './dialog/drag'
|
import copyText from './common/copyText'
|
||||||
import dialogDragWidth from './dialog/dragWidth'
|
|
||||||
import dialogDragHeight from './dialog/dragHeight'
|
|
||||||
import clipboard from './module/clipboard'
|
|
||||||
|
|
||||||
const install = function(Vue) {
|
export default function directive(app){
|
||||||
Vue.directive('hasRole', hasRole)
|
app.directive('hasRole', hasRole)
|
||||||
Vue.directive('hasPermi', hasPermi)
|
app.directive('hasPermi', hasPermi)
|
||||||
Vue.directive('clipboard', clipboard)
|
app.directive('copyText', copyText)
|
||||||
Vue.directive('dialogDrag', dialogDrag)
|
}
|
||||||
Vue.directive('dialogDragWidth', dialogDragWidth)
|
|
||||||
Vue.directive('dialogDragHeight', dialogDragHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.Vue) {
|
|
||||||
window['hasRole'] = hasRole
|
|
||||||
window['hasPermi'] = hasPermi
|
|
||||||
Vue.use(install); // eslint-disable-line
|
|
||||||
}
|
|
||||||
|
|
||||||
export default install
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/**
|
|
||||||
* v-clipboard 文字复制剪贴
|
|
||||||
* Copyright (c) 2021 ruoyi
|
|
||||||
*/
|
|
||||||
|
|
||||||
import Clipboard from 'clipboard'
|
|
||||||
export default {
|
|
||||||
bind(el, binding, vnode) {
|
|
||||||
switch (binding.arg) {
|
|
||||||
case 'success':
|
|
||||||
el._vClipBoard_success = binding.value;
|
|
||||||
break;
|
|
||||||
case 'error':
|
|
||||||
el._vClipBoard_error = binding.value;
|
|
||||||
break;
|
|
||||||
default: {
|
|
||||||
const clipboard = new Clipboard(el, {
|
|
||||||
text: () => binding.value,
|
|
||||||
action: () => binding.arg === 'cut' ? 'cut' : 'copy'
|
|
||||||
});
|
|
||||||
clipboard.on('success', e => {
|
|
||||||
const callback = el._vClipBoard_success;
|
|
||||||
callback && callback(e);
|
|
||||||
});
|
|
||||||
clipboard.on('error', e => {
|
|
||||||
const callback = el._vClipBoard_error;
|
|
||||||
callback && callback(e);
|
|
||||||
});
|
|
||||||
el._vClipBoard = clipboard;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
update(el, binding) {
|
|
||||||
if (binding.arg === 'success') {
|
|
||||||
el._vClipBoard_success = binding.value;
|
|
||||||
} else if (binding.arg === 'error') {
|
|
||||||
el._vClipBoard_error = binding.value;
|
|
||||||
} else {
|
|
||||||
el._vClipBoard.text = function () { return binding.value; };
|
|
||||||
el._vClipBoard.action = () => binding.arg === 'cut' ? 'cut' : 'copy';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
unbind(el, binding) {
|
|
||||||
if (!el._vClipboard) return
|
|
||||||
if (binding.arg === 'success') {
|
|
||||||
delete el._vClipBoard_success;
|
|
||||||
} else if (binding.arg === 'error') {
|
|
||||||
delete el._vClipBoard_error;
|
|
||||||
} else {
|
|
||||||
el._vClipBoard.destroy();
|
|
||||||
delete el._vClipBoard;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +1,28 @@
|
|||||||
/**
|
/**
|
||||||
* v-hasPermi 操作权限处理
|
* v-hasPermi 操作权限处理
|
||||||
* Copyright (c) 2019 ruoyi
|
* Copyright (c) 2019 ruoyi
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import store from '@/store'
|
import useUserStore from '@/store/modules/user'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inserted(el, binding, vnode) {
|
mounted(el, binding, vnode) {
|
||||||
const { value } = binding
|
const { value } = binding
|
||||||
const all_permission = "*:*:*";
|
const all_permission = "*:*:*";
|
||||||
const permissions = store.getters && store.getters.permissions
|
const permissions = useUserStore().permissions
|
||||||
|
|
||||||
if (value && value instanceof Array && value.length > 0) {
|
if (value && value instanceof Array && value.length > 0) {
|
||||||
const permissionFlag = value
|
const permissionFlag = value
|
||||||
|
|
||||||
const hasPermissions = permissions.some(permission => {
|
const hasPermissions = permissions.some(permission => {
|
||||||
return all_permission === permission || permissionFlag.includes(permission)
|
return all_permission === permission || permissionFlag.includes(permission)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!hasPermissions) {
|
if (!hasPermissions) {
|
||||||
el.parentNode && el.parentNode.removeChild(el)
|
el.parentNode && el.parentNode.removeChild(el)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`请设置操作权限标签值`)
|
throw new Error(`请设置操作权限标签值`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
/**
|
/**
|
||||||
* v-hasRole 角色权限处理
|
* v-hasRole 角色权限处理
|
||||||
* Copyright (c) 2019 ruoyi
|
* Copyright (c) 2019 ruoyi
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import store from '@/store'
|
import useUserStore from '@/store/modules/user'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inserted(el, binding, vnode) {
|
mounted(el, binding, vnode) {
|
||||||
const { value } = binding
|
const { value } = binding
|
||||||
const super_admin = "admin";
|
const super_admin = "admin";
|
||||||
const roles = store.getters && store.getters.roles
|
const roles = useUserStore().roles
|
||||||
|
|
||||||
if (value && value instanceof Array && value.length > 0) {
|
if (value && value instanceof Array && value.length > 0) {
|
||||||
const roleFlag = value
|
const roleFlag = value
|
||||||
|
|
||||||
const hasRole = roles.some(role => {
|
const hasRole = roles.some(role => {
|
||||||
return super_admin === role || roleFlag.includes(role)
|
return super_admin === role || roleFlag.includes(role)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!hasRole) {
|
if (!hasRole) {
|
||||||
el.parentNode && el.parentNode.removeChild(el)
|
el.parentNode && el.parentNode.removeChild(el)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`请设置角色权限标签值"`)
|
throw new Error(`请设置角色权限标签值`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,75 +1,68 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="app-main">
|
<section class="app-main">
|
||||||
<transition name="fade-transform" mode="out-in">
|
<router-view v-slot="{ Component, route }">
|
||||||
<keep-alive :include="cachedViews">
|
<transition name="fade-transform" mode="out-in">
|
||||||
<router-view v-if="!$route.meta.link" :key="key" />
|
<keep-alive :include="tagsViewStore.cachedViews">
|
||||||
</keep-alive>
|
<component v-if="!route.meta.link" :is="Component" :key="route.path"/>
|
||||||
</transition>
|
</keep-alive>
|
||||||
<iframe-toggle />
|
</transition>
|
||||||
</section>
|
</router-view>
|
||||||
</template>
|
<iframe-toggle />
|
||||||
|
</section>
|
||||||
<script>
|
</template>
|
||||||
import iframeToggle from "./IframeToggle/index"
|
|
||||||
|
<script setup>
|
||||||
export default {
|
import iframeToggle from "./IframeToggle/index"
|
||||||
name: 'AppMain',
|
import useTagsViewStore from '@/store/modules/tagsView'
|
||||||
components: { iframeToggle },
|
|
||||||
computed: {
|
const tagsViewStore = useTagsViewStore()
|
||||||
cachedViews() {
|
</script>
|
||||||
return this.$store.state.tagsView.cachedViews
|
|
||||||
},
|
<style lang="scss" scoped>
|
||||||
key() {
|
.app-main {
|
||||||
return this.$route.path
|
/* 50= navbar 50 */
|
||||||
}
|
min-height: calc(100vh - 50px);
|
||||||
}
|
width: 100%;
|
||||||
}
|
position: relative;
|
||||||
</script>
|
overflow: hidden;
|
||||||
|
}
|
||||||
<style lang="scss" scoped>
|
|
||||||
.app-main {
|
.fixed-header + .app-main {
|
||||||
/* 50= navbar 50 */
|
padding-top: 50px;
|
||||||
min-height: calc(100vh - 50px);
|
}
|
||||||
width: 100%;
|
|
||||||
position: relative;
|
.hasTagsView {
|
||||||
overflow: hidden;
|
.app-main {
|
||||||
}
|
/* 84 = navbar + tags-view = 50 + 34 */
|
||||||
|
min-height: calc(100vh - 84px);
|
||||||
.fixed-header + .app-main {
|
}
|
||||||
padding-top: 50px;
|
|
||||||
}
|
.fixed-header + .app-main {
|
||||||
|
padding-top: 84px;
|
||||||
.hasTagsView {
|
}
|
||||||
.app-main {
|
}
|
||||||
/* 84 = navbar + tags-view = 50 + 34 */
|
</style>
|
||||||
min-height: calc(100vh - 84px);
|
|
||||||
}
|
<style lang="scss">
|
||||||
|
// fix css style bug in open el-dialog
|
||||||
.fixed-header + .app-main {
|
.el-popup-parent--hidden {
|
||||||
padding-top: 84px;
|
.fixed-header {
|
||||||
}
|
padding-right: 6px;
|
||||||
}
|
}
|
||||||
</style>
|
}
|
||||||
|
|
||||||
<style lang="scss">
|
::-webkit-scrollbar {
|
||||||
// fix css style bug in open el-dialog
|
width: 6px;
|
||||||
.el-popup-parent--hidden {
|
height: 6px;
|
||||||
.fixed-header {
|
}
|
||||||
padding-right: 6px;
|
|
||||||
}
|
::-webkit-scrollbar-track {
|
||||||
}
|
background-color: #f1f1f1;
|
||||||
|
}
|
||||||
::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
::-webkit-scrollbar-thumb {
|
||||||
height: 6px;
|
background-color: #c0c0c0;
|
||||||
}
|
border-radius: 3px;
|
||||||
|
}
|
||||||
::-webkit-scrollbar-track {
|
</style>
|
||||||
background-color: #f1f1f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
background-color: #c0c0c0;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,33 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition-group name="fade-transform" mode="out-in">
|
<inner-link
|
||||||
<inner-link
|
v-for="(item, index) in tagsViewStore.iframeViews"
|
||||||
v-for="(item, index) in iframeViews"
|
:key="item.path"
|
||||||
:key="item.path"
|
:iframeId="'iframe' + index"
|
||||||
:iframeId="'iframe' + index"
|
v-show="route.path === item.path"
|
||||||
v-show="$route.path === item.path"
|
:src="iframeUrl(item.meta.link, item.query)"
|
||||||
:src="iframeUrl(item.meta.link, item.query)"
|
></inner-link>
|
||||||
></inner-link>
|
</template>
|
||||||
</transition-group>
|
|
||||||
</template>
|
<script setup>
|
||||||
|
import InnerLink from "../InnerLink/index";
|
||||||
<script>
|
import useTagsViewStore from "@/store/modules/tagsView";
|
||||||
import InnerLink from "../InnerLink/index";
|
|
||||||
|
const route = useRoute();
|
||||||
export default {
|
const tagsViewStore = useTagsViewStore();
|
||||||
components: { InnerLink },
|
|
||||||
computed: {
|
function iframeUrl(url, query) {
|
||||||
iframeViews() {
|
if (Object.keys(query).length > 0) {
|
||||||
return this.$store.state.tagsView.iframeViews;
|
let params = Object.keys(query).map((key) => key + "=" + query[key]).join("&");
|
||||||
}
|
return url + "?" + params;
|
||||||
},
|
}
|
||||||
methods: {
|
return url;
|
||||||
iframeUrl(url, query) {
|
}
|
||||||
if (Object.keys(query).length > 0) {
|
</script>
|
||||||
let params = Object.keys(query).map((key) => key + "=" + query[key]).join("&");
|
|
||||||
return url + "?" + params;
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|||||||
@@ -1,47 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :style="'height:' + height" v-loading="loading" element-loading-text="正在加载页面,请稍候!">
|
<div :style="'height:' + height">
|
||||||
<iframe
|
<iframe
|
||||||
:id="iframeId"
|
:id="iframeId"
|
||||||
style="width: 100%; height: 100%"
|
style="width: 100%; height: 100%"
|
||||||
:src="src"
|
:src="src"
|
||||||
frameborder="no"
|
frameborder="no"
|
||||||
></iframe>
|
></iframe>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
const props = defineProps({
|
||||||
props: {
|
src: {
|
||||||
src: {
|
type: String,
|
||||||
type: String,
|
default: "/"
|
||||||
default: "/"
|
},
|
||||||
},
|
iframeId: {
|
||||||
iframeId: {
|
type: String
|
||||||
type: String
|
}
|
||||||
}
|
});
|
||||||
},
|
|
||||||
data() {
|
const height = ref(document.documentElement.clientHeight - 94.5 + "px");
|
||||||
return {
|
</script>
|
||||||
loading: false,
|
|
||||||
height: document.documentElement.clientHeight - 94.5 + "px;"
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
var _this = this;
|
|
||||||
const iframeId = ("#" + this.iframeId).replace(/\//g, "\\/");
|
|
||||||
const iframe = document.querySelector(iframeId);
|
|
||||||
// iframe页面loading控制
|
|
||||||
if (iframe.attachEvent) {
|
|
||||||
this.loading = true;
|
|
||||||
iframe.attachEvent("onload", function () {
|
|
||||||
_this.loading = false;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.loading = true;
|
|
||||||
iframe.onload = function () {
|
|
||||||
_this.loading = false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|||||||
@@ -1,200 +1,191 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
|
<hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
|
||||||
|
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!settingsStore.topNav" />
|
||||||
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/>
|
<top-nav id="topmenu-container" class="topmenu-container" v-if="settingsStore.topNav" />
|
||||||
<top-nav id="topmenu-container" class="topmenu-container" v-if="topNav"/>
|
|
||||||
|
<div class="right-menu">
|
||||||
<div class="right-menu">
|
<template v-if="appStore.device !== 'mobile'">
|
||||||
<template v-if="device!=='mobile'">
|
<header-search id="header-search" class="right-menu-item" />
|
||||||
<search id="header-search" class="right-menu-item" />
|
|
||||||
|
<el-tooltip content="源码地址" effect="dark" placement="bottom">
|
||||||
<el-tooltip content="源码地址" effect="dark" placement="bottom">
|
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
|
||||||
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
|
</el-tooltip>
|
||||||
</el-tooltip>
|
|
||||||
|
<el-tooltip content="文档地址" effect="dark" placement="bottom">
|
||||||
<el-tooltip content="文档地址" effect="dark" placement="bottom">
|
<ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
|
||||||
<ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
|
</el-tooltip>
|
||||||
</el-tooltip>
|
|
||||||
|
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
||||||
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
|
||||||
|
<el-tooltip content="布局大小" effect="dark" placement="bottom">
|
||||||
<el-tooltip content="布局大小" effect="dark" placement="bottom">
|
<size-select id="size-select" class="right-menu-item hover-effect" />
|
||||||
<size-select id="size-select" class="right-menu-item hover-effect" />
|
</el-tooltip>
|
||||||
</el-tooltip>
|
</template>
|
||||||
|
<div class="avatar-container">
|
||||||
</template>
|
<el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
|
||||||
|
<div class="avatar-wrapper">
|
||||||
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
|
<img :src="userStore.avatar" class="user-avatar" />
|
||||||
<div class="avatar-wrapper">
|
<el-icon><caret-bottom /></el-icon>
|
||||||
<img :src="avatar" class="user-avatar">
|
</div>
|
||||||
<i class="el-icon-caret-bottom" />
|
<template #dropdown>
|
||||||
</div>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-menu slot="dropdown">
|
<router-link to="/user/profile">
|
||||||
<router-link to="/user/profile">
|
<el-dropdown-item>个人中心</el-dropdown-item>
|
||||||
<el-dropdown-item>个人中心</el-dropdown-item>
|
</router-link>
|
||||||
</router-link>
|
<el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
|
||||||
<el-dropdown-item @click.native="setting = true">
|
<span>布局设置</span>
|
||||||
<span>布局设置</span>
|
</el-dropdown-item>
|
||||||
</el-dropdown-item>
|
<el-dropdown-item divided command="logout">
|
||||||
<el-dropdown-item divided @click.native="logout">
|
<span>退出登录</span>
|
||||||
<span>退出登录</span>
|
</el-dropdown-item>
|
||||||
</el-dropdown-item>
|
</el-dropdown-menu>
|
||||||
</el-dropdown-menu>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
|
</template>
|
||||||
<script>
|
|
||||||
import { mapGetters } from 'vuex'
|
<script setup>
|
||||||
import Breadcrumb from '@/components/Breadcrumb'
|
import { ElMessageBox } from 'element-plus'
|
||||||
import TopNav from '@/components/TopNav'
|
import Breadcrumb from '@/components/Breadcrumb'
|
||||||
import Hamburger from '@/components/Hamburger'
|
import TopNav from '@/components/TopNav'
|
||||||
import Screenfull from '@/components/Screenfull'
|
import Hamburger from '@/components/Hamburger'
|
||||||
import SizeSelect from '@/components/SizeSelect'
|
import Screenfull from '@/components/Screenfull'
|
||||||
import Search from '@/components/HeaderSearch'
|
import SizeSelect from '@/components/SizeSelect'
|
||||||
import RuoYiGit from '@/components/RuoYi/Git'
|
import HeaderSearch from '@/components/HeaderSearch'
|
||||||
import RuoYiDoc from '@/components/RuoYi/Doc'
|
import RuoYiGit from '@/components/RuoYi/Git'
|
||||||
|
import RuoYiDoc from '@/components/RuoYi/Doc'
|
||||||
export default {
|
import useAppStore from '@/store/modules/app'
|
||||||
components: {
|
import useUserStore from '@/store/modules/user'
|
||||||
Breadcrumb,
|
import useSettingsStore from '@/store/modules/settings'
|
||||||
TopNav,
|
|
||||||
Hamburger,
|
const appStore = useAppStore()
|
||||||
Screenfull,
|
const userStore = useUserStore()
|
||||||
SizeSelect,
|
const settingsStore = useSettingsStore()
|
||||||
Search,
|
|
||||||
RuoYiGit,
|
function toggleSideBar() {
|
||||||
RuoYiDoc
|
appStore.toggleSideBar()
|
||||||
},
|
}
|
||||||
computed: {
|
|
||||||
...mapGetters([
|
function handleCommand(command) {
|
||||||
'sidebar',
|
switch (command) {
|
||||||
'avatar',
|
case "setLayout":
|
||||||
'device'
|
setLayout();
|
||||||
]),
|
break;
|
||||||
setting: {
|
case "logout":
|
||||||
get() {
|
logout();
|
||||||
return this.$store.state.settings.showSettings
|
break;
|
||||||
},
|
default:
|
||||||
set(val) {
|
break;
|
||||||
this.$store.dispatch('settings/changeSetting', {
|
}
|
||||||
key: 'showSettings',
|
}
|
||||||
value: val
|
|
||||||
})
|
function logout() {
|
||||||
}
|
ElMessageBox.confirm('确定注销并退出系统吗?', '提示', {
|
||||||
},
|
confirmButtonText: '确定',
|
||||||
topNav: {
|
cancelButtonText: '取消',
|
||||||
get() {
|
type: 'warning'
|
||||||
return this.$store.state.settings.topNav
|
}).then(() => {
|
||||||
}
|
userStore.logOut().then(() => {
|
||||||
}
|
location.href = '/index';
|
||||||
},
|
})
|
||||||
methods: {
|
}).catch(() => { });
|
||||||
toggleSideBar() {
|
}
|
||||||
this.$store.dispatch('app/toggleSideBar')
|
|
||||||
},
|
const emits = defineEmits(['setLayout'])
|
||||||
async logout() {
|
function setLayout() {
|
||||||
this.$confirm('确定注销并退出系统吗?', '提示', {
|
emits('setLayout');
|
||||||
confirmButtonText: '确定',
|
}
|
||||||
cancelButtonText: '取消',
|
</script>
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
<style lang='scss' scoped>
|
||||||
this.$store.dispatch('LogOut').then(() => {
|
.navbar {
|
||||||
location.href = '/index';
|
height: 50px;
|
||||||
})
|
overflow: hidden;
|
||||||
}).catch(() => {});
|
position: relative;
|
||||||
}
|
background: #fff;
|
||||||
}
|
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
||||||
}
|
|
||||||
</script>
|
.hamburger-container {
|
||||||
|
line-height: 46px;
|
||||||
<style lang="scss" scoped>
|
height: 100%;
|
||||||
.navbar {
|
float: left;
|
||||||
height: 50px;
|
cursor: pointer;
|
||||||
overflow: hidden;
|
transition: background 0.3s;
|
||||||
position: relative;
|
-webkit-tap-highlight-color: transparent;
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
&:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.025);
|
||||||
.hamburger-container {
|
}
|
||||||
line-height: 46px;
|
}
|
||||||
height: 100%;
|
|
||||||
float: left;
|
.breadcrumb-container {
|
||||||
cursor: pointer;
|
float: left;
|
||||||
transition: background .3s;
|
}
|
||||||
-webkit-tap-highlight-color:transparent;
|
|
||||||
|
.topmenu-container {
|
||||||
&:hover {
|
position: absolute;
|
||||||
background: rgba(0, 0, 0, .025)
|
left: 50px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
.errLog-container {
|
||||||
.breadcrumb-container {
|
display: inline-block;
|
||||||
float: left;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topmenu-container {
|
.right-menu {
|
||||||
position: absolute;
|
float: right;
|
||||||
left: 50px;
|
height: 100%;
|
||||||
}
|
line-height: 50px;
|
||||||
|
display: flex;
|
||||||
.errLog-container {
|
|
||||||
display: inline-block;
|
&:focus {
|
||||||
vertical-align: top;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-menu {
|
.right-menu-item {
|
||||||
float: right;
|
display: inline-block;
|
||||||
height: 100%;
|
padding: 0 8px;
|
||||||
line-height: 50px;
|
height: 100%;
|
||||||
|
font-size: 18px;
|
||||||
&:focus {
|
color: #5a5e66;
|
||||||
outline: none;
|
vertical-align: text-bottom;
|
||||||
}
|
|
||||||
|
&.hover-effect {
|
||||||
.right-menu-item {
|
cursor: pointer;
|
||||||
display: inline-block;
|
transition: background 0.3s;
|
||||||
padding: 0 8px;
|
|
||||||
height: 100%;
|
&:hover {
|
||||||
font-size: 18px;
|
background: rgba(0, 0, 0, 0.025);
|
||||||
color: #5a5e66;
|
}
|
||||||
vertical-align: text-bottom;
|
}
|
||||||
|
}
|
||||||
&.hover-effect {
|
|
||||||
cursor: pointer;
|
.avatar-container {
|
||||||
transition: background .3s;
|
margin-right: 40px;
|
||||||
|
|
||||||
&:hover {
|
.avatar-wrapper {
|
||||||
background: rgba(0, 0, 0, .025)
|
margin-top: 5px;
|
||||||
}
|
position: relative;
|
||||||
}
|
|
||||||
}
|
.user-avatar {
|
||||||
|
cursor: pointer;
|
||||||
.avatar-container {
|
width: 40px;
|
||||||
margin-right: 30px;
|
height: 40px;
|
||||||
|
border-radius: 10px;
|
||||||
.avatar-wrapper {
|
}
|
||||||
margin-top: 5px;
|
|
||||||
position: relative;
|
i {
|
||||||
|
cursor: pointer;
|
||||||
.user-avatar {
|
position: absolute;
|
||||||
cursor: pointer;
|
right: -20px;
|
||||||
width: 40px;
|
top: 25px;
|
||||||
height: 40px;
|
font-size: 12px;
|
||||||
border-radius: 10px;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.el-icon-caret-bottom {
|
}
|
||||||
cursor: pointer;
|
}
|
||||||
position: absolute;
|
</style>
|
||||||
right: -20px;
|
|
||||||
top: 25px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||