feat/1
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 679 B |
|
After Width: | Height: | Size: 641 B |
|
After Width: | Height: | Size: 742 B |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
|
@ -0,0 +1,99 @@
|
||||||
|
@use './variables.module.scss' as *;
|
||||||
|
|
||||||
|
@mixin colorBtn($color) {
|
||||||
|
background: $color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $color;
|
||||||
|
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
background: $color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.blue-btn {
|
||||||
|
@include colorBtn($blue)
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-blue-btn {
|
||||||
|
@include colorBtn($light-blue)
|
||||||
|
}
|
||||||
|
|
||||||
|
.red-btn {
|
||||||
|
@include colorBtn($red)
|
||||||
|
}
|
||||||
|
|
||||||
|
.pink-btn {
|
||||||
|
@include colorBtn($pink)
|
||||||
|
}
|
||||||
|
|
||||||
|
.green-btn {
|
||||||
|
@include colorBtn($green)
|
||||||
|
}
|
||||||
|
|
||||||
|
.tiffany-btn {
|
||||||
|
@include colorBtn($tiffany)
|
||||||
|
}
|
||||||
|
|
||||||
|
.yellow-btn {
|
||||||
|
@include colorBtn($yellow)
|
||||||
|
}
|
||||||
|
|
||||||
|
.pan-btn {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #fff;
|
||||||
|
padding: 14px 36px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
transition: 600ms ease all;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
width: 100%;
|
||||||
|
transition: 600ms ease all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 2px;
|
||||||
|
width: 0;
|
||||||
|
transition: 400ms ease all;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
right: inherit;
|
||||||
|
top: inherit;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-button {
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
background: #fff;
|
||||||
|
color: #fff;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
outline: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 10px 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
// cover some element-ui styles
|
||||||
|
|
||||||
|
.el-breadcrumb__inner,
|
||||||
|
.el-breadcrumb__inner a {
|
||||||
|
font-weight: 400 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-upload {
|
||||||
|
input[type="file"] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-upload__input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell {
|
||||||
|
.el-tag {
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.small-padding {
|
||||||
|
.cell {
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-width {
|
||||||
|
.el-button--mini {
|
||||||
|
padding: 7px 10px;
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-col {
|
||||||
|
.cell {
|
||||||
|
padding: 0 10px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.el-tag {
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// to fixed https://github.com/ElemeFE/element/issues/2461
|
||||||
|
// .el-dialog {
|
||||||
|
// transform: none;
|
||||||
|
// left: 0;
|
||||||
|
// position: relative;
|
||||||
|
// margin: 0 auto;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// refine element ui upload
|
||||||
|
.upload-container {
|
||||||
|
.el-upload {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.el-upload-dragger {
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dropdown
|
||||||
|
.el-dropdown-menu {
|
||||||
|
a {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fix date-picker ui bug in filter-item
|
||||||
|
.el-range-editor.el-input__inner {
|
||||||
|
display: inline-flex !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// to fix el-date-picker css style
|
||||||
|
.el-range-separator {
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu--collapse
|
||||||
|
> div
|
||||||
|
> .el-submenu
|
||||||
|
> .el-submenu__title
|
||||||
|
.el-submenu__icon-arrow {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
@use './variables.module.scss' as *;
|
||||||
|
@use './mixin.scss' as *;
|
||||||
|
@use './transition.scss' as *;
|
||||||
|
@use './element-ui.scss' as *;
|
||||||
|
@use './sidebar.scss' as *;
|
||||||
|
@use './btn.scss' as *;
|
||||||
|
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
-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;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*:before,
|
||||||
|
*:after {
|
||||||
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-padding {
|
||||||
|
padding: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.padding-content {
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:focus,
|
||||||
|
a:active {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a,
|
||||||
|
a:focus,
|
||||||
|
a:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fr {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fl {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pr-5 {
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl-5 {
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inlineBlock {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearfix {
|
||||||
|
&:after {
|
||||||
|
visibility: hidden;
|
||||||
|
display: block;
|
||||||
|
font-size: 0;
|
||||||
|
content: " ";
|
||||||
|
clear: both;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aside {
|
||||||
|
background: #eef1f6;
|
||||||
|
padding: 8px 24px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-radius: 2px;
|
||||||
|
display: block;
|
||||||
|
line-height: 32px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||||
|
color: #2c3e50;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #337ab7;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: rgb(32, 160, 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-select,.el-time-picker,.el-range-editor {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.el-time-picker {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.el-range-editor--medium.el-input__inner {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.el-date-editor {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
//main-container全局样式
|
||||||
|
.app-container {
|
||||||
|
padding: 20px;
|
||||||
|
height: calc(100vh - 84px);
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.components-container {
|
||||||
|
margin: 30px 50px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-container {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-navbar {
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 20px;
|
||||||
|
transition: 600ms ease position;
|
||||||
|
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%);
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.draft {
|
||||||
|
background: #d0d0d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.deleted {
|
||||||
|
background: #d0d0d0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-type,
|
||||||
|
.link-type:focus {
|
||||||
|
color: #337ab7;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: rgb(32, 160, 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-container {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
@mixin clearfix {
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
display: table;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin scrollBar {
|
||||||
|
&::-webkit-scrollbar-track-piece {
|
||||||
|
background: #d3dce6;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: #99a9bf;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin relative {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin pct($pct) {
|
||||||
|
width: #{$pct};
|
||||||
|
position: relative;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin triangle($width, $height, $color, $direction) {
|
||||||
|
$width: $width/2;
|
||||||
|
$color-border-style: $height solid $color;
|
||||||
|
$transparent-border-style: $width solid transparent;
|
||||||
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
|
||||||
|
@if $direction==up {
|
||||||
|
border-bottom: $color-border-style;
|
||||||
|
border-left: $transparent-border-style;
|
||||||
|
border-right: $transparent-border-style;
|
||||||
|
}
|
||||||
|
|
||||||
|
@else if $direction==right {
|
||||||
|
border-left: $color-border-style;
|
||||||
|
border-top: $transparent-border-style;
|
||||||
|
border-bottom: $transparent-border-style;
|
||||||
|
}
|
||||||
|
|
||||||
|
@else if $direction==down {
|
||||||
|
border-top: $color-border-style;
|
||||||
|
border-left: $transparent-border-style;
|
||||||
|
border-right: $transparent-border-style;
|
||||||
|
}
|
||||||
|
|
||||||
|
@else if $direction==left {
|
||||||
|
border-right: $color-border-style;
|
||||||
|
border-top: $transparent-border-style;
|
||||||
|
border-bottom: $transparent-border-style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,291 @@
|
||||||
|
/**
|
||||||
|
* 通用css样式布局处理
|
||||||
|
* Copyright (c) 2019 ruoyi
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** 基础通用 **/
|
||||||
|
.pt5 {
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pr5 {
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pb5 {
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt5 {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr5 {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb5 {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb8 {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml5 {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt10 {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr10 {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb10 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.ml10 {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt20 {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr20 {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb20 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.ml20 {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-family: inherit;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.1;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-message-box__status + .el-message-box__message{
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog:not(.is-fullscreen) {
|
||||||
|
margin-top: 6vh !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__wrapper.scrollbar .el-dialog .el-dialog__body {
|
||||||
|
overflow: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
max-height: 70vh;
|
||||||
|
padding: 10px 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table {
|
||||||
|
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
|
||||||
|
th {
|
||||||
|
word-break: break-word;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
color: #515a6e;
|
||||||
|
height: 40px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table__body-wrapper {
|
||||||
|
.el-button [class*="el-icon-"] + span {
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表单布局 **/
|
||||||
|
.form-header {
|
||||||
|
font-size: 15px;
|
||||||
|
color: #6379bb;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
margin: 8px 10px 25px 10px;
|
||||||
|
padding-bottom: 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表格布局 **/
|
||||||
|
.pagination-container {
|
||||||
|
position: relative;
|
||||||
|
height: 25px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-top: 15px;
|
||||||
|
padding: 10px 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tree border */
|
||||||
|
.tree-border {
|
||||||
|
margin-top: 5px;
|
||||||
|
border: 1px solid #e5e6e7;
|
||||||
|
background: #FFFFFF none;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-container .el-pagination {
|
||||||
|
right: 0;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.pagination-container .el-pagination > .el-pagination__jump {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.pagination-container .el-pagination > .el-pagination__sizes {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table .fixed-width .el-button--mini {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
width: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表格更多操作下拉样式 */
|
||||||
|
.el-table .el-dropdown-link,.el-table .el-dropdown-selfdefine {
|
||||||
|
cursor: pointer;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table .el-dropdown, .el-icon-arrow-down {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tree-node__content > .el-checkbox {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-striped > .list-group-item {
|
||||||
|
border-left: 0;
|
||||||
|
border-right: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group {
|
||||||
|
padding-left: 0px;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item {
|
||||||
|
border-bottom: 1px solid #e7eaec;
|
||||||
|
border-top: 1px solid #e7eaec;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
padding: 11px 0px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pull-right {
|
||||||
|
float: right !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-card__header {
|
||||||
|
padding: 14px 15px 7px;
|
||||||
|
min-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-card__body {
|
||||||
|
padding: 15px 20px 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-box {
|
||||||
|
padding-right: 15px;
|
||||||
|
padding-left: 15px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* button color */
|
||||||
|
.el-button--cyan.is-active,
|
||||||
|
.el-button--cyan:active {
|
||||||
|
background: #20B2AA;
|
||||||
|
border-color: #20B2AA;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button--cyan:focus,
|
||||||
|
.el-button--cyan:hover {
|
||||||
|
background: #48D1CC;
|
||||||
|
border-color: #48D1CC;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button--cyan {
|
||||||
|
background-color: #20B2AA;
|
||||||
|
border-color: #20B2AA;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* text color */
|
||||||
|
.text-navy {
|
||||||
|
color: #1ab394;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-primary {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-success {
|
||||||
|
color: #1c84c6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-info {
|
||||||
|
color: #23c6c8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-warning {
|
||||||
|
color: #f8ac59;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-danger {
|
||||||
|
color: #ed5565;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-muted {
|
||||||
|
color: #888888;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* image */
|
||||||
|
.img-circle {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-lg {
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-upload-preview {
|
||||||
|
position: relative;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 0 4px #ccc;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 拖拽列样式 */
|
||||||
|
.sortable-ghost {
|
||||||
|
opacity: .8;
|
||||||
|
color: #fff !important;
|
||||||
|
background: #42b983 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-right-btn {
|
||||||
|
position: relative;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,232 @@
|
||||||
|
@use './variables.module.scss' as *;
|
||||||
|
|
||||||
|
#app {
|
||||||
|
|
||||||
|
.main-container {
|
||||||
|
height: 100%;
|
||||||
|
transition: margin-left .28s;
|
||||||
|
margin-left: $base-sidebar-width;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebarHide {
|
||||||
|
margin-left: 0!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-container {
|
||||||
|
-webkit-transition: width .28s;
|
||||||
|
transition: width 0.28s;
|
||||||
|
width: $base-sidebar-width !important;
|
||||||
|
height: 100%;
|
||||||
|
position: fixed;
|
||||||
|
font-size: 0px;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1001;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
|
||||||
|
box-shadow: 2px 0 6px rgba(0,21,41,.35);
|
||||||
|
|
||||||
|
// reset element-ui css
|
||||||
|
.horizontal-collapse-transition {
|
||||||
|
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-wrapper {
|
||||||
|
overflow-x: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-scrollbar__bar.is-vertical {
|
||||||
|
right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-scrollbar {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.has-logo {
|
||||||
|
.el-scrollbar {
|
||||||
|
height: calc(100% - 50px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-horizontal {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
// display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.svg-icon {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu {
|
||||||
|
border: none;
|
||||||
|
height: 100%;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
.el-menu-item {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.el-menu-item, .el-submenu__title {
|
||||||
|
overflow: hidden !important;
|
||||||
|
text-overflow: ellipsis !important;
|
||||||
|
white-space: nowrap !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// menu hover
|
||||||
|
.submenu-title-noDropdown,
|
||||||
|
.el-submenu__title {
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 0.06) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .theme-dark .is-active > .el-submenu__title {
|
||||||
|
color: $base-menu-color-active !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .nest-menu .el-submenu>.el-submenu__title,
|
||||||
|
& .el-submenu .el-menu-item {
|
||||||
|
min-width: $base-sidebar-width !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 0.06) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .theme-dark .nest-menu .el-submenu>.el-submenu__title,
|
||||||
|
& .theme-dark .el-submenu .el-menu-item {
|
||||||
|
background-color: $base-sub-menu-background !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $base-sub-menu-hover !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hideSidebar {
|
||||||
|
.sidebar-container {
|
||||||
|
width: 54px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-container {
|
||||||
|
margin-left: 54px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-title-noDropdown {
|
||||||
|
padding: 0 !important;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.el-tooltip {
|
||||||
|
padding: 0 !important;
|
||||||
|
|
||||||
|
.svg-icon {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-submenu {
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&>.el-submenu__title {
|
||||||
|
padding: 0 !important;
|
||||||
|
|
||||||
|
.svg-icon {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu--collapse {
|
||||||
|
.el-submenu {
|
||||||
|
&>.el-submenu__title {
|
||||||
|
&>span {
|
||||||
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
visibility: hidden;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu--collapse .el-menu .el-submenu {
|
||||||
|
min-width: $base-sidebar-width !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mobile responsive
|
||||||
|
.mobile {
|
||||||
|
.main-container {
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-container {
|
||||||
|
transition: transform .28s;
|
||||||
|
width: $base-sidebar-width !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hideSidebar {
|
||||||
|
.sidebar-container {
|
||||||
|
pointer-events: none;
|
||||||
|
transition-duration: 0.3s;
|
||||||
|
transform: translate3d(-$base-sidebar-width, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.withoutAnimation {
|
||||||
|
|
||||||
|
.main-container,
|
||||||
|
.sidebar-container {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// when menu collapsed
|
||||||
|
.el-menu--vertical {
|
||||||
|
&>.el-menu {
|
||||||
|
.svg-icon {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nest-menu .el-submenu>.el-submenu__title,
|
||||||
|
.el-menu-item {
|
||||||
|
&:hover {
|
||||||
|
// you can use $subMenuHover
|
||||||
|
background-color: rgba(0, 0, 0, 0.06) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the scroll bar appears when the subMenu is too long
|
||||||
|
>.el-menu--popup {
|
||||||
|
max-height: 100vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-track-piece {
|
||||||
|
background: #d3dce6;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: #99a9bf;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
// global transition css
|
||||||
|
|
||||||
|
/* fade */
|
||||||
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: opacity 0.28s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter,
|
||||||
|
.fade-leave-active {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fade-transform */
|
||||||
|
.fade-transform--move,
|
||||||
|
.fade-transform-leave-active,
|
||||||
|
.fade-transform-enter-active {
|
||||||
|
transition: all .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-transform-enter {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-30px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-transform-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(30px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* breadcrumb transition */
|
||||||
|
.breadcrumb-enter-active,
|
||||||
|
.breadcrumb-leave-active {
|
||||||
|
transition: all .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-enter,
|
||||||
|
.breadcrumb-leave-active {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-move {
|
||||||
|
transition: all .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-leave-active {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,221 @@
|
||||||
|
// base color
|
||||||
|
$blue: #324157;
|
||||||
|
$light-blue: #333c46;
|
||||||
|
$red: #C03639;
|
||||||
|
$pink: #E65D6E;
|
||||||
|
$green: #30B08F;
|
||||||
|
$tiffany: #4AB7BD;
|
||||||
|
$yellow: #FEC171;
|
||||||
|
$panGreen: #30B08F;
|
||||||
|
|
||||||
|
// 默认主题变量
|
||||||
|
$menuText: #bfcbd9;
|
||||||
|
$menuActiveText: #409eff;
|
||||||
|
$menuBg: #304156;
|
||||||
|
$menuHover: #263445;
|
||||||
|
|
||||||
|
// 浅色主题theme-light
|
||||||
|
$menuLightBg: #ffffff;
|
||||||
|
$menuLightHover: #f0f1f5;
|
||||||
|
$menuLightText: #303133;
|
||||||
|
$menuLightActiveText: #409EFF;
|
||||||
|
|
||||||
|
// 基础变量
|
||||||
|
$base-sidebar-width: 200px;
|
||||||
|
$sideBarWidth: 200px;
|
||||||
|
|
||||||
|
// 菜单暗色变量
|
||||||
|
$base-menu-color: #bfcbd9;
|
||||||
|
$base-menu-color-active: #f4f4f5;
|
||||||
|
$base-menu-background: #304156;
|
||||||
|
$base-sub-menu-background: #1f2d3d;
|
||||||
|
$base-sub-menu-hover: #001528;
|
||||||
|
|
||||||
|
// 组件变量
|
||||||
|
$--color-primary: #409EFF;
|
||||||
|
$--color-success: #67C23A;
|
||||||
|
$--color-warning: #E6A23C;
|
||||||
|
$--color-danger: #F56C6C;
|
||||||
|
$--color-info: #909399;
|
||||||
|
|
||||||
|
:export {
|
||||||
|
menuText: $menuText;
|
||||||
|
menuActiveText: $menuActiveText;
|
||||||
|
menuBg: $menuBg;
|
||||||
|
menuHover: $menuHover;
|
||||||
|
menuLightBg: $menuLightBg;
|
||||||
|
menuLightHover: $menuLightHover;
|
||||||
|
menuLightText: $menuLightText;
|
||||||
|
menuLightActiveText: $menuLightActiveText;
|
||||||
|
sideBarWidth: $sideBarWidth;
|
||||||
|
// 导出基础颜色
|
||||||
|
blue: $blue;
|
||||||
|
lightBlue: $light-blue;
|
||||||
|
red: $red;
|
||||||
|
pink: $pink;
|
||||||
|
green: $green;
|
||||||
|
tiffany: $tiffany;
|
||||||
|
yellow: $yellow;
|
||||||
|
panGreen: $panGreen;
|
||||||
|
// 导出组件颜色
|
||||||
|
colorPrimary: $--color-primary;
|
||||||
|
colorSuccess: $--color-success;
|
||||||
|
colorWarning: $--color-warning;
|
||||||
|
colorDanger: $--color-danger;
|
||||||
|
colorInfo: $--color-info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSS变量定义
|
||||||
|
:root {
|
||||||
|
/* 亮色模式变量 */
|
||||||
|
--sidebar-bg: #{$menuBg};
|
||||||
|
--sidebar-text: #{$menuText};
|
||||||
|
--menu-hover: #{$menuHover};
|
||||||
|
|
||||||
|
--navbar-bg: #ffffff;
|
||||||
|
--navbar-text: #303133;
|
||||||
|
|
||||||
|
/* splitpanes default-theme 变量 */
|
||||||
|
--splitpanes-default-bg: #ffffff;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 暗黑模式变量
|
||||||
|
html.dark {
|
||||||
|
/* 默认通用 */
|
||||||
|
--el-bg-color: #141414;
|
||||||
|
--el-bg-color-overlay: #1d1e1f;
|
||||||
|
--el-text-color-primary: #ffffff;
|
||||||
|
--el-text-color-regular: #d0d0d0;
|
||||||
|
--el-border-color: #434343;
|
||||||
|
--el-border-color-light: #434343;
|
||||||
|
|
||||||
|
/* 侧边栏 */
|
||||||
|
--sidebar-bg: #141414;
|
||||||
|
--sidebar-text: #ffffff;
|
||||||
|
--menu-hover: #2d2d2d;
|
||||||
|
--menu-active-text: #{$menuActiveText};
|
||||||
|
|
||||||
|
/* 顶部导航栏 */
|
||||||
|
--navbar-bg: #141414;
|
||||||
|
--navbar-text: #ffffff;
|
||||||
|
--navbar-hover: #141414;
|
||||||
|
|
||||||
|
/* 标签栏 */
|
||||||
|
--tags-bg: #141414;
|
||||||
|
--tags-item-bg: #1d1e1f;
|
||||||
|
--tags-item-border: #303030;
|
||||||
|
--tags-item-text: #d0d0d0;
|
||||||
|
--tags-item-hover: #2d2d2d;
|
||||||
|
--tags-close-hover: #64666a;
|
||||||
|
|
||||||
|
/* splitpanes 组件暗黑模式变量 */
|
||||||
|
--splitpanes-bg: #141414;
|
||||||
|
--splitpanes-border: #303030;
|
||||||
|
--splitpanes-splitter-bg: #1d1e1f;
|
||||||
|
--splitpanes-splitter-hover-bg: #2d2d2d;
|
||||||
|
|
||||||
|
/* blockquote 暗黑模式变量 */
|
||||||
|
--blockquote-bg: #1d1e1f;
|
||||||
|
--blockquote-border: #303030;
|
||||||
|
--blockquote-text: #d0d0d0;
|
||||||
|
|
||||||
|
/* Cron 时间表达式 模式变量 */
|
||||||
|
--cron-border: #303030;
|
||||||
|
|
||||||
|
/* splitpanes default-theme 暗黑模式变量 */
|
||||||
|
--splitpanes-default-bg: #141414;
|
||||||
|
|
||||||
|
/* 侧边栏菜单覆盖 */
|
||||||
|
.sidebar-container {
|
||||||
|
.el-menu-item, .menu-title {
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
}
|
||||||
|
& .theme-dark .nest-menu .el-sub-menu>.el-sub-menu__title,
|
||||||
|
& .theme-dark .el-sub-menu .el-menu-item {
|
||||||
|
background-color: var(--el-bg-color) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 顶部栏栏菜单覆盖 */
|
||||||
|
.el-menu--horizontal {
|
||||||
|
.el-menu-item {
|
||||||
|
&:not(.is-disabled) {
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background-color: var(--navbar-hover) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 分割窗格覆盖 */
|
||||||
|
.splitpanes {
|
||||||
|
background-color: var(--splitpanes-bg);
|
||||||
|
|
||||||
|
.splitpanes__pane {
|
||||||
|
background-color: var(--splitpanes-bg);
|
||||||
|
border-color: var(--splitpanes-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.splitpanes__splitter {
|
||||||
|
background-color: var(--splitpanes-splitter-bg);
|
||||||
|
border-color: var(--splitpanes-border);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--splitpanes-splitter-hover-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
background-color: var(--splitpanes-border);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表格样式覆盖 */
|
||||||
|
.el-table {
|
||||||
|
--el-table-header-bg-color: var(--el-bg-color-overlay) !important;
|
||||||
|
--el-table-header-text-color: var(--el-text-color-regular) !important;
|
||||||
|
--el-table-border-color: var(--el-border-color-light) !important;
|
||||||
|
--el-table-row-hover-bg-color: var(--el-bg-color-overlay) !important;
|
||||||
|
|
||||||
|
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
|
||||||
|
th {
|
||||||
|
background-color: var(--el-bg-color-overlay, #f8f8f9) !important;
|
||||||
|
color: var(--el-text-color-regular, #515a6e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 树组件高亮样式覆盖 */
|
||||||
|
.el-tree {
|
||||||
|
.el-tree-node.is-current > .el-tree-node__content {
|
||||||
|
background-color: var(--el-bg-color-overlay) !important;
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tree-node__content:hover {
|
||||||
|
background-color: var(--el-bg-color-overlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 下拉菜单样式覆盖 */
|
||||||
|
.el-dropdown-menu__item:not(.is-disabled):focus, .el-dropdown-menu__item:not(.is-disabled):hover{
|
||||||
|
background-color: var(--navbar-hover) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* blockquote样式覆盖 */
|
||||||
|
blockquote {
|
||||||
|
background-color: var(--blockquote-bg) !important;
|
||||||
|
border-left-color: var(--blockquote-border) !important;
|
||||||
|
color: var(--blockquote-text) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 时间表达式标题样式覆盖 */
|
||||||
|
.popup-result .title {
|
||||||
|
background: var(--cron-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
<template>
|
||||||
|
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||||
|
<transition-group name="breadcrumb">
|
||||||
|
<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>
|
||||||
|
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
|
||||||
|
</el-breadcrumb-item>
|
||||||
|
</transition-group>
|
||||||
|
</el-breadcrumb>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { usePermissionStore } from '@/store/modules/permission'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
const permissionStore = usePermissionStore()
|
||||||
|
const levelList = ref([])
|
||||||
|
|
||||||
|
function getBreadcrumb() {
|
||||||
|
// only show routes with meta.title
|
||||||
|
let matched = []
|
||||||
|
const pathNum = findPathNum(route.path)
|
||||||
|
// multi-level menu
|
||||||
|
if (pathNum > 2) {
|
||||||
|
const reg = /\/\w+/gi
|
||||||
|
const pathList = route.path.match(reg).map((item, index) => {
|
||||||
|
if (index !== 0) item = item.slice(1)
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
getMatched(pathList, permissionStore.defaultRoutes, matched)
|
||||||
|
} else {
|
||||||
|
matched = route.matched.filter((item) => item.meta && item.meta.title)
|
||||||
|
}
|
||||||
|
// 判断是否为首页
|
||||||
|
if (!isDashboard(matched[0])) {
|
||||||
|
matched = [{ path: "/index", meta: { title: "首页" } }].concat(matched)
|
||||||
|
}
|
||||||
|
levelList.value = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
||||||
|
}
|
||||||
|
function findPathNum(str, char = "/") {
|
||||||
|
let index = str.indexOf(char)
|
||||||
|
let num = 0
|
||||||
|
while (index !== -1) {
|
||||||
|
num++
|
||||||
|
index = str.indexOf(char, index + 1)
|
||||||
|
}
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
function getMatched(pathList, routeList, matched) {
|
||||||
|
let data = routeList.find(item => item.path == pathList[0] || (item.name += '').toLowerCase() == pathList[0])
|
||||||
|
if (data) {
|
||||||
|
matched.push(data)
|
||||||
|
if (data.children && pathList.length) {
|
||||||
|
pathList.shift()
|
||||||
|
getMatched(pathList, data.children, matched)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isDashboard(route) {
|
||||||
|
const name = route && route.name
|
||||||
|
if (!name) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return name.trim() === 'Index'
|
||||||
|
}
|
||||||
|
function handleLink(item) {
|
||||||
|
const { redirect, path } = item
|
||||||
|
if (redirect) {
|
||||||
|
router.push(redirect)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
router.push(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
// if you go to the redirect page, do not update the breadcrumbs
|
||||||
|
if (route.path.startsWith('/redirect/')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
getBreadcrumb()
|
||||||
|
})
|
||||||
|
getBreadcrumb()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
.app-breadcrumb.el-breadcrumb {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 50px;
|
||||||
|
margin-left: 8px;
|
||||||
|
|
||||||
|
.no-redirect {
|
||||||
|
color: #97a8be;
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,174 @@
|
||||||
|
<template>
|
||||||
|
<el-form>
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio v-model='radioValue' :value="1">
|
||||||
|
日,允许的通配符[, - * ? / L W]
|
||||||
|
</el-radio>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio v-model='radioValue' :value="2">
|
||||||
|
不指定
|
||||||
|
</el-radio>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio v-model='radioValue' :value="3">
|
||||||
|
周期从
|
||||||
|
<el-input-number v-model='cycle01' :min="1" :max="30" /> -
|
||||||
|
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="31" /> 日
|
||||||
|
</el-radio>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio v-model='radioValue' :value="4">
|
||||||
|
从
|
||||||
|
<el-input-number v-model='average01' :min="1" :max="30" /> 号开始,每
|
||||||
|
<el-input-number v-model='average02' :min="1" :max="31 - average01" /> 日执行一次
|
||||||
|
</el-radio>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio v-model='radioValue' :value="5">
|
||||||
|
每月
|
||||||
|
<el-input-number v-model='workday' :min="1" :max="31" /> 号最近的那个工作日
|
||||||
|
</el-radio>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio v-model='radioValue' :value="6">
|
||||||
|
本月最后一天
|
||||||
|
</el-radio>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio v-model='radioValue' :value="7">
|
||||||
|
指定
|
||||||
|
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
|
||||||
|
<el-option v-for="item in 31" :key="item" :label="item" :value="item" />
|
||||||
|
</el-select>
|
||||||
|
</el-radio>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
const emit = defineEmits(['update'])
|
||||||
|
const props = defineProps({
|
||||||
|
cron: {
|
||||||
|
type: Object,
|
||||||
|
default: {
|
||||||
|
second: "*",
|
||||||
|
min: "*",
|
||||||
|
hour: "*",
|
||||||
|
day: "*",
|
||||||
|
month: "*",
|
||||||
|
week: "?",
|
||||||
|
year: "",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
check: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const radioValue = ref(1)
|
||||||
|
const cycle01 = ref(1)
|
||||||
|
const cycle02 = ref(2)
|
||||||
|
const average01 = ref(1)
|
||||||
|
const average02 = ref(1)
|
||||||
|
const workday = ref(1)
|
||||||
|
const checkboxList = ref([])
|
||||||
|
const checkCopy = ref([1])
|
||||||
|
const cycleTotal = computed(() => {
|
||||||
|
cycle01.value = props.check(cycle01.value, 1, 30)
|
||||||
|
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 31)
|
||||||
|
return cycle01.value + '-' + cycle02.value
|
||||||
|
})
|
||||||
|
const averageTotal = computed(() => {
|
||||||
|
average01.value = props.check(average01.value, 1, 30)
|
||||||
|
average02.value = props.check(average02.value, 1, 31 - average01.value)
|
||||||
|
return average01.value + '/' + average02.value
|
||||||
|
})
|
||||||
|
const workdayTotal = computed(() => {
|
||||||
|
workday.value = props.check(workday.value, 1, 31)
|
||||||
|
return workday.value + 'W'
|
||||||
|
})
|
||||||
|
const checkboxString = computed(() => {
|
||||||
|
return checkboxList.value.join(',')
|
||||||
|
})
|
||||||
|
watch(() => props.cron.day, value => changeRadioValue(value))
|
||||||
|
watch([radioValue, cycleTotal, averageTotal, workdayTotal, checkboxString], () => onRadioChange())
|
||||||
|
function changeRadioValue(value) {
|
||||||
|
if (value === "*") {
|
||||||
|
radioValue.value = 1
|
||||||
|
} else if (value === "?") {
|
||||||
|
radioValue.value = 2
|
||||||
|
} else if (value.indexOf("-") > -1) {
|
||||||
|
const indexArr = value.split('-')
|
||||||
|
cycle01.value = Number(indexArr[0])
|
||||||
|
cycle02.value = Number(indexArr[1])
|
||||||
|
radioValue.value = 3
|
||||||
|
} else if (value.indexOf("/") > -1) {
|
||||||
|
const indexArr = value.split('/')
|
||||||
|
average01.value = Number(indexArr[0])
|
||||||
|
average02.value = Number(indexArr[1])
|
||||||
|
radioValue.value = 4
|
||||||
|
} else if (value.indexOf("W") > -1) {
|
||||||
|
const indexArr = value.split("W")
|
||||||
|
workday.value = Number(indexArr[0])
|
||||||
|
radioValue.value = 5
|
||||||
|
} else if (value === "L") {
|
||||||
|
radioValue.value = 6
|
||||||
|
} else {
|
||||||
|
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
|
||||||
|
radioValue.value = 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 单选按钮值变化时
|
||||||
|
function onRadioChange() {
|
||||||
|
if (radioValue.value === 2 && props.cron.week === '?') {
|
||||||
|
emit('update', 'week', '*', 'day')
|
||||||
|
}
|
||||||
|
if (radioValue.value !== 2 && props.cron.week !== '?') {
|
||||||
|
emit('update', 'week', '?', 'day')
|
||||||
|
}
|
||||||
|
switch (radioValue.value) {
|
||||||
|
case 1:
|
||||||
|
emit('update', 'day', '*', 'day')
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
emit('update', 'day', '?', 'day')
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
emit('update', 'day', cycleTotal.value, 'day')
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
emit('update', 'day', averageTotal.value, 'day')
|
||||||
|
break
|
||||||
|
case 5:
|
||||||
|
emit('update', 'day', workdayTotal.value, 'day')
|
||||||
|
break
|
||||||
|
case 6:
|
||||||
|
emit('update', 'day', 'L', 'day')
|
||||||
|
break
|
||||||
|
case 7:
|
||||||
|
if (checkboxList.value.length === 0) {
|
||||||
|
checkboxList.value.push(checkCopy.value[0])
|
||||||
|
} else {
|
||||||
|
checkCopy.value = checkboxList.value
|
||||||
|
}
|
||||||
|
emit('update', 'day', checkboxString.value, 'day')
|
||||||
|
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>
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
<template>
|
||||||
|
<el-form>
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio v-model='radioValue' :value="1">
|
||||||
|
小时,允许的通配符[, - * /]
|
||||||
|
</el-radio>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio v-model='radioValue' :value="2">
|
||||||
|
周期从
|
||||||
|
<el-input-number v-model='cycle01' :min="0" :max="22" /> -
|
||||||
|
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="23" /> 时
|
||||||
|
</el-radio>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio v-model='radioValue' :value="3">
|
||||||
|
从
|
||||||
|
<el-input-number v-model='average01' :min="0" :max="22" /> 时开始,每
|
||||||
|
<el-input-number v-model='average02' :min="1" :max="23 - average01" /> 小时执行一次
|
||||||
|
</el-radio>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-radio v-model='radioValue' :value="4">
|
||||||
|
指定
|
||||||
|
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
|
||||||
|
<el-option v-for="item in 24" :key="item" :label="item - 1" :value="item - 1" />
|
||||||
|
</el-select>
|
||||||
|
</el-radio>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const emit = defineEmits(['update'])
|
||||||
|
const props = defineProps({
|
||||||
|
cron: {
|
||||||
|
type: Object,
|
||||||
|
default: {
|
||||||
|
second: "*",
|
||||||
|
min: "*",
|
||||||
|
hour: "*",
|
||||||
|
day: "*",
|
||||||
|
month: "*",
|
||||||
|
week: "?",
|
||||||
|
year: "",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
check: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const radioValue = ref(1)
|
||||||
|
const cycle01 = ref(0)
|
||||||
|
const cycle02 = ref(1)
|
||||||
|
const average01 = ref(0)
|
||||||
|
const average02 = ref(1)
|
||||||
|
const checkboxList = ref([])
|
||||||
|
const checkCopy = ref([0])
|
||||||
|
const cycleTotal = computed(() => {
|
||||||
|
cycle01.value = props.check(cycle01.value, 0, 22)
|
||||||
|
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 23)
|
||||||
|
return cycle01.value + '-' + cycle02.value
|
||||||
|
})
|
||||||
|
const averageTotal = computed(() => {
|
||||||
|
average01.value = props.check(average01.value, 0, 22)
|
||||||
|
average02.value = props.check(average02.value, 1, 23 - average01.value)
|
||||||
|
return average01.value + '/' + average02.value
|
||||||
|
})
|
||||||
|
const checkboxString = computed(() => {
|
||||||
|
return checkboxList.value.join(',')
|
||||||
|
})
|
||||||
|
watch(() => props.cron.hour, value => changeRadioValue(value))
|
||||||
|
watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
|
||||||
|
function changeRadioValue(value) {
|
||||||
|
if (props.cron.min === '*') {
|
||||||
|
emit('update', 'min', '0', 'hour')
|
||||||
|
}
|
||||||
|
if (props.cron.second === '*') {
|
||||||
|
emit('update', 'second', '0', 'hour')
|
||||||
|
}
|
||||||
|
if (value === '*') {
|
||||||
|
radioValue.value = 1
|
||||||
|
} else if (value.indexOf('-') > -1) {
|
||||||
|
const indexArr = value.split('-')
|
||||||
|
cycle01.value = Number(indexArr[0])
|
||||||
|
cycle02.value = Number(indexArr[1])
|
||||||
|
radioValue.value = 2
|
||||||
|
} else if (value.indexOf('/') > -1) {
|
||||||
|
const indexArr = value.split('/')
|
||||||
|
average01.value = Number(indexArr[0])
|
||||||
|
average02.value = Number(indexArr[1])
|
||||||
|
radioValue.value = 3
|
||||||
|
} else {
|
||||||
|
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
|
||||||
|
radioValue.value = 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function onRadioChange() {
|
||||||
|
switch (radioValue.value) {
|
||||||
|
case 1:
|
||||||
|
emit('update', 'hour', '*', 'hour')
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
emit('update', 'hour', cycleTotal.value, 'hour')
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
emit('update', 'hour', averageTotal.value, 'hour')
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
if (checkboxList.value.length === 0) {
|
||||||
|
checkboxList.value.push(checkCopy.value[0])
|
||||||
|
} else {
|
||||||
|
checkCopy.value = checkboxList.value
|
||||||
|
}
|
||||||
|
emit('update', 'hour', checkboxString.value, 'hour')
|
||||||
|
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>
|
||||||
|
|
@ -0,0 +1,313 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-tabs type="border-card">
|
||||||
|
<el-tab-pane label="秒" v-if="shouldHide('second')">
|
||||||
|
<CrontabSecond
|
||||||
|
@update="updateCrontabValue"
|
||||||
|
:check="checkNumber"
|
||||||
|
:cron="crontabValueObj"
|
||||||
|
ref="cronsecond"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="分钟" v-if="shouldHide('min')">
|
||||||
|
<CrontabMin
|
||||||
|
@update="updateCrontabValue"
|
||||||
|
:check="checkNumber"
|
||||||
|
:cron="crontabValueObj"
|
||||||
|
ref="cronmin"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="小时" v-if="shouldHide('hour')">
|
||||||
|
<CrontabHour
|
||||||
|
@update="updateCrontabValue"
|
||||||
|
:check="checkNumber"
|
||||||
|
:cron="crontabValueObj"
|
||||||
|
ref="cronhour"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="日" v-if="shouldHide('day')">
|
||||||
|
<CrontabDay
|
||||||
|
@update="updateCrontabValue"
|
||||||
|
:check="checkNumber"
|
||||||
|
:cron="crontabValueObj"
|
||||||
|
ref="cronday"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="月" v-if="shouldHide('month')">
|
||||||
|
<CrontabMonth
|
||||||
|
@update="updateCrontabValue"
|
||||||
|
:check="checkNumber"
|
||||||
|
:cron="crontabValueObj"
|
||||||
|
ref="cronmonth"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="周" v-if="shouldHide('week')">
|
||||||
|
<CrontabWeek
|
||||||
|
@update="updateCrontabValue"
|
||||||
|
:check="checkNumber"
|
||||||
|
:cron="crontabValueObj"
|
||||||
|
ref="cronweek"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="年" v-if="shouldHide('year')">
|
||||||
|
<CrontabYear
|
||||||
|
@update="updateCrontabValue"
|
||||||
|
:check="checkNumber"
|
||||||
|
:cron="crontabValueObj"
|
||||||
|
ref="cronyear"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
|
<div class="popup-main">
|
||||||
|
<div class="popup-result">
|
||||||
|
<p class="title">时间表达式</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th v-for="item of tabTitles" :key="item">{{item}}</th>
|
||||||
|
<th>Cron 表达式</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span v-if="crontabValueObj.second.length < 10">{{crontabValueObj.second}}</span>
|
||||||
|
<el-tooltip v-else :content="crontabValueObj.second" placement="top"><span>{{crontabValueObj.second}}</span></el-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="crontabValueObj.min.length < 10">{{crontabValueObj.min}}</span>
|
||||||
|
<el-tooltip v-else :content="crontabValueObj.min" placement="top"><span>{{crontabValueObj.min}}</span></el-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="crontabValueObj.hour.length < 10">{{crontabValueObj.hour}}</span>
|
||||||
|
<el-tooltip v-else :content="crontabValueObj.hour" placement="top"><span>{{crontabValueObj.hour}}</span></el-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="crontabValueObj.day.length < 10">{{crontabValueObj.day}}</span>
|
||||||
|
<el-tooltip v-else :content="crontabValueObj.day" placement="top"><span>{{crontabValueObj.day}}</span></el-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="crontabValueObj.month.length < 10">{{crontabValueObj.month}}</span>
|
||||||
|
<el-tooltip v-else :content="crontabValueObj.month" placement="top"><span>{{crontabValueObj.month}}</span></el-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="crontabValueObj.week.length < 10">{{crontabValueObj.week}}</span>
|
||||||
|
<el-tooltip v-else :content="crontabValueObj.week" placement="top"><span>{{crontabValueObj.week}}</span></el-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="crontabValueObj.year.length < 10">{{crontabValueObj.year}}</span>
|
||||||
|
<el-tooltip v-else :content="crontabValueObj.year" placement="top"><span>{{crontabValueObj.year}}</span></el-tooltip>
|
||||||
|
</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>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<CrontabResult :ex="crontabValueString"></CrontabResult>
|
||||||
|
|
||||||
|
<div class="pop_btn">
|
||||||
|
<el-button type="primary" @click="submitFill">确定</el-button>
|
||||||
|
<el-button type="warning" @click="clearCron">重置</el-button>
|
||||||
|
<el-button @click="hidePopup">取消</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import CrontabSecond from "./second.vue"
|
||||||
|
import CrontabMin from "./min.vue"
|
||||||
|
import CrontabHour from "./hour.vue"
|
||||||
|
import CrontabDay from "./day.vue"
|
||||||
|
import CrontabMonth from "./month.vue"
|
||||||
|
import CrontabWeek from "./week.vue"
|
||||||
|
import CrontabYear from "./year.vue"
|
||||||
|
import CrontabResult from "./result.vue"
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
const emit = defineEmits(['hide', 'fill'])
|
||||||
|
const props = defineProps({
|
||||||
|
hideComponent: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
expression: {
|
||||||
|
type: String,
|
||||||
|
default: ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
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) {
|
||||||
|
//6 位以上是合法表达式
|
||||||
|
let obj = {
|
||||||
|
second: arr[0],
|
||||||
|
min: arr[1],
|
||||||
|
hour: arr[2],
|
||||||
|
day: arr[3],
|
||||||
|
month: arr[4],
|
||||||
|
week: arr[5],
|
||||||
|
year: arr[6] ? arr[6] : ""
|
||||||
|
}
|
||||||
|
crontabValueObj.value = {
|
||||||
|
...obj,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 没有传入的表达式 则还原
|
||||||
|
clearCron()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// tab切换值
|
||||||
|
function tabCheck(index) {
|
||||||
|
tabActive.value = index
|
||||||
|
}
|
||||||
|
// 由子组件触发,更改表达式组成的字段值
|
||||||
|
function updateCrontabValue(name, value, from) {
|
||||||
|
crontabValueObj.value[name] = value
|
||||||
|
}
|
||||||
|
// 表单选项的子组件校验数字格式(通过-props传递)
|
||||||
|
function checkNumber(value, minLimit, maxLimit) {
|
||||||
|
// 检查必须为整数
|
||||||
|
value = Math.floor(value)
|
||||||
|
if (value < minLimit) {
|
||||||
|
value = minLimit
|
||||||
|
} else if (value > maxLimit) {
|
||||||
|
value = maxLimit
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
// 隐藏弹窗
|
||||||
|
function hidePopup() {
|
||||||
|
emit("hide")
|
||||||
|
}
|
||||||
|
// 填充表达式
|
||||||
|
function submitFill() {
|
||||||
|
emit("fill", crontabValueString.value)
|
||||||
|
hidePopup()
|
||||||
|
}
|
||||||
|
function clearCron() {
|
||||||
|
// 还原选择项
|
||||||
|
crontabValueObj.value = {
|
||||||
|
second: "*",
|
||||||
|
min: "*",
|
||||||
|
hour: "*",
|
||||||
|
day: "*",
|
||||||
|
month: "*",
|
||||||
|
week: "?",
|
||||||
|
year: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
expression.value = props.expression
|
||||||
|
hideComponent.value = props.hideComponent
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.pop_btn {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.popup-main {
|
||||||
|
position: relative;
|
||||||
|
margin: 10px auto;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.popup-title {
|
||||||
|
overflow: hidden;
|
||||||
|
line-height: 34px;
|
||||||
|
padding-top: 6px;
|
||||||
|
background: #f2f2f2;
|
||||||
|
}
|
||||||
|
.popup-result {
|
||||||
|
box-sizing: border-box;
|
||||||
|
line-height: 24px;
|
||||||
|
margin: 25px auto;
|
||||||
|
padding: 15px 10px 10px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.popup-result .title {
|
||||||
|
position: absolute;
|
||||||
|
top: -28px;
|
||||||
|
left: 50%;
|
||||||
|
width: 140px;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-left: -70px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 30px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.popup-result table {
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.popup-result table td:not(.result) {
|
||||||
|
width: 3.5rem;
|
||||||
|
min-width: 3.5rem;
|
||||||
|
max-width: 3.5rem;
|
||||||
|
}
|
||||||
|
.popup-result table span {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
font-family: arial;
|
||||||
|
line-height: 30px;
|
||||||
|
height: 30px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid #e8e8e8;
|
||||||
|
}
|
||||||
|
.popup-result-scroll {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 24px;
|
||||||
|
height: 10em;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||