mirror of
https://github.com/cool-team-official/cool-admin-vue.git
synced 2024-11-01 14:10:27 +08:00
优化
This commit is contained in:
parent
92f00a613b
commit
5fc6bc1224
@ -12,7 +12,7 @@
|
|||||||
"cl-admin": "^1.3.1",
|
"cl-admin": "^1.3.1",
|
||||||
"cl-admin-crud": "^1.4.0",
|
"cl-admin-crud": "^1.4.0",
|
||||||
"cl-admin-export": "^1.0.5",
|
"cl-admin-export": "^1.0.5",
|
||||||
"cl-admin-theme": "^0.0.2",
|
"cl-admin-theme": "^0.0.3",
|
||||||
"clipboard": "^2.0.7",
|
"clipboard": "^2.0.7",
|
||||||
"codemirror": "^5.59.4",
|
"codemirror": "^5.59.4",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
|
@ -13124,6 +13124,13 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.app-slider .cl-slider-menu .el-menu .el-submenu__title:hover,
|
||||||
|
.app-slider .cl-slider-menu .el-menu .el-submenu__title.is-active,
|
||||||
|
.app-slider .cl-slider-menu .el-menu .el-menu-item:hover,
|
||||||
|
.app-slider .cl-slider-menu .el-menu .el-menu-item.is-active {
|
||||||
|
background-color: #1d1a1a !important;
|
||||||
|
}
|
||||||
|
|
||||||
.page-layout__right {
|
.page-layout__right {
|
||||||
background-color: rgba(47, 52, 71, 0.9);
|
background-color: rgba(47, 52, 71, 0.9);
|
||||||
}
|
}
|
||||||
@ -13159,3 +13166,4 @@
|
|||||||
.page-layout__topbar .cl-menu-topbar .el-menu .el-menu-item.is-active {
|
.page-layout__topbar .cl-menu-topbar .el-menu .el-menu-item.is-active {
|
||||||
background-color: rgba(47, 52, 71, 0.8) !important;
|
background-color: rgba(47, 52, 71, 0.8) !important;
|
||||||
}
|
}
|
||||||
|
/*# sourceMappingURL=index.css.map */
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
$color-primary: #4165d7;
|
$primary: #4165d7;
|
||||||
|
|
||||||
|
$color-primary: var(--color-primary, $primary);
|
||||||
$color-success: #67c23a;
|
$color-success: #67c23a;
|
||||||
$color-danger: #f56c6c;
|
$color-danger: #f56c6c;
|
||||||
$color-info: #909399;
|
$color-info: #909399;
|
||||||
$color-warning: #e6a23c;
|
$color-warning: #e6a23c;
|
||||||
|
|
||||||
|
:export {
|
||||||
|
colorPrimary: $primary;
|
||||||
|
colorSuccess: $color-success;
|
||||||
|
colorDanger: $color-danger;
|
||||||
|
colorInfo: $color-info;
|
||||||
|
colorWarning: $color-warning;
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
$--color-primary: $color-primary;
|
$--color-primary: $primary;
|
||||||
$--color-success: $color-success;
|
$--color-success: $color-success;
|
||||||
$--color-danger: $color-danger;
|
$--color-danger: $color-danger;
|
||||||
$--color-warning: $color-warning;
|
$--color-warning: $color-warning;
|
||||||
|
@ -30,7 +30,7 @@ export const baseUrl = (function() {
|
|||||||
export const iconfontUrl = ``;
|
export const iconfontUrl = ``;
|
||||||
|
|
||||||
// 程序配置参数
|
// 程序配置参数
|
||||||
export const app = {
|
export const app = store.get("__app__") || {
|
||||||
name: "COOL-ADMIN",
|
name: "COOL-ADMIN",
|
||||||
|
|
||||||
conf: {
|
conf: {
|
||||||
@ -41,7 +41,8 @@ export const app = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
theme: {
|
theme: {
|
||||||
url: "" // 主题样式地址
|
color: "", // 主题色
|
||||||
|
url: "http://192.168.199.148:5000/black/index.css" // 主题样式地址
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
import { iconfontUrl, app } from "@/config/env";
|
import { iconfontUrl, app } from "@/config/env";
|
||||||
import { createLink } from "../utils";
|
import { createLink } from "../utils";
|
||||||
|
import { colorPrimary } from "@/assets/css/common.scss";
|
||||||
|
|
||||||
if (app.theme) {
|
if (app.theme) {
|
||||||
if (app.theme.url) {
|
const { url, color } = app.theme;
|
||||||
createLink(app.theme.url);
|
|
||||||
|
if (url) {
|
||||||
|
createLink(url, "theme-style");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document
|
||||||
|
.getElementsByTagName("body")[0]
|
||||||
|
.style.setProperty("--color-primary", color || colorPrimary);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iconfontUrl) {
|
if (iconfontUrl) {
|
||||||
|
@ -11,14 +11,14 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(["menuList", "menuCollapse", "browser", "conf"])
|
...mapGetters(["menuList", "menuCollapse", "browser", "app"])
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
menuList() {
|
menuList() {
|
||||||
this.refresh();
|
this.refresh();
|
||||||
},
|
},
|
||||||
"conf.showAMenu"() {
|
"app.conf.showAMenu"() {
|
||||||
this.$store.commit("SET_MENU_LIST");
|
this.$store.commit("SET_MENU_LIST");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,33 +1,27 @@
|
|||||||
import { app } from "@/config/env";
|
import { app } from "@/config/env";
|
||||||
import { deepMerge, getBrowser } from "cl-admin/utils";
|
import { deepMerge, getBrowser } from "cl-admin/utils";
|
||||||
|
import store from "store";
|
||||||
|
import common from "@/assets/css/common.scss";
|
||||||
|
|
||||||
|
console.log(common);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
state: {
|
state: {
|
||||||
info: {
|
info: {
|
||||||
name: app.name
|
...app
|
||||||
},
|
|
||||||
conf: {
|
|
||||||
...app.conf
|
|
||||||
},
|
},
|
||||||
browser: {
|
browser: {
|
||||||
isMobile: false
|
isMobile: false
|
||||||
},
|
},
|
||||||
collapse: false,
|
collapse: false
|
||||||
upload: {
|
|
||||||
mode: "local"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
// 应用信息
|
|
||||||
appInfo: state => state.info,
|
|
||||||
// 应用配置
|
// 应用配置
|
||||||
conf: state => state.conf,
|
app: state => state.info,
|
||||||
// 浏览器信息
|
// 浏览器信息
|
||||||
browser: state => state.browser,
|
browser: state => state.browser,
|
||||||
// 左侧菜单是否收起
|
// 左侧菜单是否收起
|
||||||
menuCollapse: state => state.collapse,
|
menuCollapse: state => state.collapse
|
||||||
// 上传配置
|
|
||||||
upload: state => state.upload
|
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
appLoad({ getters, dispatch }) {
|
appLoad({ getters, dispatch }) {
|
||||||
@ -36,14 +30,7 @@ export default {
|
|||||||
dispatch("permMenu");
|
dispatch("permMenu");
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
dispatch("userInfo");
|
dispatch("userInfo");
|
||||||
// 设置上传配置
|
|
||||||
dispatch("setUpload");
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
setUpload({ state }) {
|
|
||||||
this.$service.common.uploadMode().then(res => {
|
|
||||||
state.upload = res;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
@ -58,8 +45,9 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 更新应用配置
|
// 更新应用配置
|
||||||
UPDATE_CONF(state, val) {
|
UPDATE_APP(state, val) {
|
||||||
deepMerge(state.conf, val);
|
deepMerge(state.info, val);
|
||||||
|
store.set("__app__", state.info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -82,7 +82,7 @@ export default {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 监测自定义菜单
|
// 监测自定义菜单
|
||||||
if (!getters.conf.customMenu) {
|
if (!getters.app.conf.customMenu) {
|
||||||
this.$service.common
|
this.$service.common
|
||||||
.permMenu()
|
.permMenu()
|
||||||
.then(res => {
|
.then(res => {
|
||||||
@ -118,7 +118,7 @@ export default {
|
|||||||
|
|
||||||
// 设置左侧菜单
|
// 设置左侧菜单
|
||||||
SET_MENU_LIST(state, index) {
|
SET_MENU_LIST(state, index) {
|
||||||
const { showAMenu } = this.getters.conf;
|
const { showAMenu } = this.getters.app.conf;
|
||||||
|
|
||||||
if (isEmpty(index)) {
|
if (isEmpty(index)) {
|
||||||
index = state.index;
|
index = state.index;
|
||||||
|
459
src/cool/modules/task/components/cron/base.js
Normal file
459
src/cool/modules/task/components/cron/base.js
Normal file
@ -0,0 +1,459 @@
|
|||||||
|
/**
|
||||||
|
* 表单项基础类, 所有输入组件都继承Base
|
||||||
|
* @module $ui/components/my-form/src/Base
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { FormItem } from "element-ui";
|
||||||
|
import { setStyle } from "element-ui/lib/utils/dom";
|
||||||
|
import { addResizeListener, removeResizeListener } from "element-ui/lib/utils/resize-event";
|
||||||
|
|
||||||
|
const _get = require("lodash/get");
|
||||||
|
const _set = require("lodash/set");
|
||||||
|
const _isEqual = require("lodash/isEqual");
|
||||||
|
const _cloneDeep = require("lodash/cloneDeep");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 深拷贝
|
||||||
|
* @param {*} value 要深拷贝的值
|
||||||
|
* @return {*} 返回拷贝后的值
|
||||||
|
*/
|
||||||
|
export function cloneDeep(value) {
|
||||||
|
return _cloneDeep(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断两个对象是否相等
|
||||||
|
* @param {*} object 对象1
|
||||||
|
* @param {*} other 对象2
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
export function isEqual(object, other) {
|
||||||
|
return _isEqual(object, other);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 插槽
|
||||||
|
* @member slots
|
||||||
|
* @property {string} before 输入组件前面的内容,仅当父组件是MyForm有效
|
||||||
|
* @property {string} after 输入组件后面的内容,仅当父组件是MyForm有效
|
||||||
|
* @property {string} label 定义字段的label内容,仅当父组件是MyForm有效
|
||||||
|
* @property {string} error 作用域插槽,定义验证错误提示内容,仅当父组件是MyForm有效
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
inject: {
|
||||||
|
myForm: {
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
FormItem
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 属性参数
|
||||||
|
* @member props
|
||||||
|
* @property {string} [name] 表单域 model 字段名称, 等价于 el-form-item 的 prop 参数
|
||||||
|
* @property {string} [width] 宽度,css属性,支持像素,百分比和表达式,也可以在MyForm中统一设置itemWidth
|
||||||
|
* @property {object} [props] 输入组件参数对象,即 element 组件的参数
|
||||||
|
* @property {Array} [options] 选项数据,数据优先顺序,options > loader > form.dictMap > form.loader
|
||||||
|
* @property {Object} [keyMap] 选项数据对象属性名称映射, 默认:{id, parentId, label, value}
|
||||||
|
* @property {boolean} [collapsible] 可收起
|
||||||
|
* @property {boolean} [stopEnterEvent] 阻止回车事件冒泡
|
||||||
|
* @property {string} [depend] 依赖字段名称
|
||||||
|
* @property {*} [dependValue] 依赖字段的值,即依赖字段的值等于该值才会显示
|
||||||
|
* @property {string} [cascade] 级联的上级字段名称,需要与loader配合加载数据
|
||||||
|
* @property {Function} [loader] 加载数据函数,必须返回Promise
|
||||||
|
* @property {string} [dict] 字典名称,只是标识,需要与loader配合 或 表单的dictMap加载数据
|
||||||
|
* @property {boolean} [disabled] 禁用
|
||||||
|
* @property {boolean} [readonly] 只读
|
||||||
|
* @property {string} [placeholder] 占位文本
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
props: {
|
||||||
|
// 表单域 model 字段名称
|
||||||
|
name: String,
|
||||||
|
// 宽度,支持像素,百分比和表达式
|
||||||
|
width: String,
|
||||||
|
// 输入组件参数对象
|
||||||
|
props: Object,
|
||||||
|
// 选项数据,数据优先顺序,options > loader > form.dictMap > form.loader
|
||||||
|
options: Array,
|
||||||
|
// 选项数据对象属性名称映射
|
||||||
|
keyMap: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {
|
||||||
|
id: "id",
|
||||||
|
label: "label",
|
||||||
|
value: "value",
|
||||||
|
disabled: "disabled",
|
||||||
|
parentId: "parentId"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 可折叠
|
||||||
|
collapsible: Boolean,
|
||||||
|
|
||||||
|
// 阻止回车事件冒泡
|
||||||
|
stopEnterEvent: Boolean,
|
||||||
|
|
||||||
|
// 依赖字段名称
|
||||||
|
depend: String,
|
||||||
|
|
||||||
|
// 依赖字段的值,即依赖字段的值等于该值才会显示
|
||||||
|
dependValue: [String, Number, Boolean, Object, Array, Function],
|
||||||
|
|
||||||
|
// 级联的上级字段名称,需要与loader配合加载数据
|
||||||
|
cascade: String,
|
||||||
|
|
||||||
|
// 加载数据函数,必须返回Promise
|
||||||
|
loader: Function,
|
||||||
|
|
||||||
|
// 字典名称,只是标识,需要与loader配合 或 表单的dictMap加载数据
|
||||||
|
dict: String,
|
||||||
|
|
||||||
|
// 禁用
|
||||||
|
disabled: Boolean,
|
||||||
|
// 只读
|
||||||
|
readonly: Boolean,
|
||||||
|
|
||||||
|
// 占位文本
|
||||||
|
placeholder: String,
|
||||||
|
|
||||||
|
// 尺寸
|
||||||
|
size: String
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 级联的值缓存
|
||||||
|
cascadeValue: null,
|
||||||
|
// 当前选项数据
|
||||||
|
currentOptions: [],
|
||||||
|
|
||||||
|
// 正在调用loader
|
||||||
|
loading: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 如果有name参数,并且是MyForm的子组件,即与MyForm的currentModel作双向绑定
|
||||||
|
// 否则与组件自身的value作双向绑定
|
||||||
|
fieldValue: {
|
||||||
|
get() {
|
||||||
|
if (this.name && this.myForm) {
|
||||||
|
const { currentModel } = this.myForm;
|
||||||
|
return _get(currentModel, this.name, this.getDefaultValue());
|
||||||
|
} else {
|
||||||
|
return this.value || this.getDefaultValue();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
if (this.name && this.myForm) {
|
||||||
|
const { currentModel } = this.myForm;
|
||||||
|
const model = cloneDeep(currentModel);
|
||||||
|
_set(model, this.name, val);
|
||||||
|
if (!isEqual(currentModel, model)) {
|
||||||
|
this.myForm.currentModel[this.name] = model[this.name];
|
||||||
|
this.myForm.currentModel = model;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$emit("input", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 字段域的宽度
|
||||||
|
itemWidth() {
|
||||||
|
// 优先取自身设置的宽度,没有就取父组件设置的公共设置宽度
|
||||||
|
return (
|
||||||
|
this.width || (this.myForm && this.myForm.itemWidth ? this.myForm.itemWidth : null)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
// 字段域样式
|
||||||
|
itemStyle() {
|
||||||
|
return {
|
||||||
|
width: this.itemWidth
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// 输入框组件参数
|
||||||
|
innerProps() {
|
||||||
|
return {
|
||||||
|
disabled: this.disabled,
|
||||||
|
readonly: this.readonly,
|
||||||
|
placeholder: this.placeholder,
|
||||||
|
size: this.size,
|
||||||
|
...this.props
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
itemWidth: {
|
||||||
|
immediate: true,
|
||||||
|
handler() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.setContentWidth();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"myForm.currentCollapsed"(val) {
|
||||||
|
const { resetCollapsed, model } = this.myForm;
|
||||||
|
// 收起时重置表单项值
|
||||||
|
if (val && resetCollapsed && model && this.collapsible) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// this.fieldValue = this.myForm.model[this.name]
|
||||||
|
this.fieldValue = _get(this.myForm.model, this.name, this.getDefaultValue());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 开启了折叠功能
|
||||||
|
if (this.collapsible) {
|
||||||
|
// 折叠时先要清除事件句柄,因为原先的dom即将发生改变
|
||||||
|
if (val) {
|
||||||
|
removeResizeListener(this.$el, this.setContentWidth);
|
||||||
|
} else {
|
||||||
|
// 如果没有加载过选项数据,触发加载函数
|
||||||
|
if (!this.currentOptions || this.currentOptions.length === 0) {
|
||||||
|
this.loadOptions(this.myForm.currentModel, this);
|
||||||
|
}
|
||||||
|
// 展开时,待DOM生成后,重新注册事件句柄
|
||||||
|
this.$nextTick(() => {
|
||||||
|
addResizeListener(this.$el, this.setContentWidth);
|
||||||
|
this.setContentWidth();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// options 为了提高性能,不设置deep
|
||||||
|
options: {
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
this.currentOptions = cloneDeep(val) || [];
|
||||||
|
// options改变后,会触发表单验证,这里需要清楚验证错误信息
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.clearValidate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取表单项的默认值,不同组件有不同的默认值,可在具体的组件重写这个函数
|
||||||
|
getDefaultValue() {
|
||||||
|
return "";
|
||||||
|
},
|
||||||
|
// 重置字段
|
||||||
|
resetField() {
|
||||||
|
this.$refs.elItem && this.$refs.elItem.resetField();
|
||||||
|
},
|
||||||
|
// 清除验证错误信息
|
||||||
|
clearValidate() {
|
||||||
|
this.$refs.elItem && this.$refs.elItem.clearValidate();
|
||||||
|
},
|
||||||
|
isCollapsed() {
|
||||||
|
if (!this.myForm) return false;
|
||||||
|
|
||||||
|
const { collapsible, currentCollapsed } = this.myForm;
|
||||||
|
// 是否已收起
|
||||||
|
return collapsible && currentCollapsed && this.collapsible;
|
||||||
|
},
|
||||||
|
isMatchDepend() {
|
||||||
|
// 没有设置依赖,即忽略,当已匹配处理
|
||||||
|
if (!this.depend || !this.myForm) return true;
|
||||||
|
const model = this.myForm.currentModel;
|
||||||
|
// 依赖不支持 按路径查找
|
||||||
|
const value = model[this.depend];
|
||||||
|
let isMatch = true;
|
||||||
|
// 如果 dependValue 是函数,执行回调函数返回布尔值
|
||||||
|
if (typeof this.dependValue === "function") {
|
||||||
|
isMatch = this.dependValue(value, model, this);
|
||||||
|
} else {
|
||||||
|
// 以上都不符合,即检验 dependValue 与 currentModel中的依赖属性是否一致
|
||||||
|
isMatch = isEqual(this.dependValue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除依赖不符合字段的值
|
||||||
|
if (!isMatch && this.name && model[this.name]) {
|
||||||
|
this.fieldValue = this.getDefaultValue();
|
||||||
|
delete model[this.name];
|
||||||
|
}
|
||||||
|
return isMatch;
|
||||||
|
},
|
||||||
|
// 传递给输入组件的插槽
|
||||||
|
createSlots(slots = []) {
|
||||||
|
return slots.map(name => {
|
||||||
|
return <template slot={name}>{this.$slots[name]}</template>;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 渲染输入组件
|
||||||
|
renderComponent(vnode) {
|
||||||
|
// 如果组件不是MyForm的子组件,不需要包裹Item组件
|
||||||
|
if (!this.myForm) {
|
||||||
|
return vnode;
|
||||||
|
}
|
||||||
|
// el-form-item 作用域插槽
|
||||||
|
const scopedSlots = this.$scopedSlots.error
|
||||||
|
? {
|
||||||
|
error: props => (
|
||||||
|
<div class="el-form-item__error my-from__custom-error">
|
||||||
|
{this.$scopedSlots.error(props)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// 是否已收起
|
||||||
|
const collapsed = this.isCollapsed();
|
||||||
|
// 是否符合依赖项
|
||||||
|
const isMatched = this.isMatchDepend();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<transition name={this.myForm.collapseEffect}>
|
||||||
|
{!collapsed && isMatched ? (
|
||||||
|
<FormItem
|
||||||
|
ref="elItem"
|
||||||
|
class="my-form-item"
|
||||||
|
{...{
|
||||||
|
props: this.$attrs,
|
||||||
|
scopedSlots: scopedSlots,
|
||||||
|
style: this.itemStyle
|
||||||
|
}}
|
||||||
|
// 停止回车键事件冒泡
|
||||||
|
nativeOnKeyup={this.stopEvent}
|
||||||
|
// el-form-item 的prop用name代替
|
||||||
|
prop={this.name}>
|
||||||
|
{// label 插槽
|
||||||
|
this.$slots.label ? (
|
||||||
|
<template slot="label">{this.$slots.label}</template>
|
||||||
|
) : null}
|
||||||
|
{this.$slots.before}
|
||||||
|
{vnode}
|
||||||
|
{this.$slots.after}
|
||||||
|
</FormItem>
|
||||||
|
) : (
|
||||||
|
// Vue组件必须要有一个根DOM,创建一个隐藏占位元素
|
||||||
|
<div style={{ display: "none" }}>{this.name}</div>
|
||||||
|
)}
|
||||||
|
</transition>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
// 继承输入组件暴露的方法
|
||||||
|
extendMethods(ref, names = []) {
|
||||||
|
if (!ref) return;
|
||||||
|
|
||||||
|
names.forEach(name => {
|
||||||
|
// 子组件的方法加到实例
|
||||||
|
this[name] = (...args) => {
|
||||||
|
ref[name].apply(ref, args);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 设置el-form-item内部的内容区宽度
|
||||||
|
setContentWidth() {
|
||||||
|
// 字段域没有设置宽度,默认自适应,不需要处理
|
||||||
|
if (!this.itemWidth || !this.$el) return;
|
||||||
|
const content = this.$el.querySelector(".el-form-item__content");
|
||||||
|
const label = this.$el.querySelector(".el-form-item__label");
|
||||||
|
if (content) {
|
||||||
|
const rect = label ? label.getBoundingClientRect() : { width: 0 };
|
||||||
|
const itemWidth = this.$el.getBoundingClientRect().width;
|
||||||
|
const contentWidth = itemWidth - rect.width;
|
||||||
|
setStyle(content, { width: `${contentWidth}px` });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 阻止回车事件冒泡
|
||||||
|
stopEvent(e) {
|
||||||
|
if (this.stopEnterEvent) {
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 加载选项数据
|
||||||
|
loadOptions(model) {
|
||||||
|
// 已收起的,不需要处理
|
||||||
|
if (this.isCollapsed()) return;
|
||||||
|
|
||||||
|
// 如果不符合依赖,不处理
|
||||||
|
if (!this.isMatchDepend()) return;
|
||||||
|
|
||||||
|
// 数据优先顺序,options > loader > form.dictMap > form.loader
|
||||||
|
if (this.options) {
|
||||||
|
this.currentOptions = cloneDeep(this.options);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.loader) {
|
||||||
|
this.loading = true;
|
||||||
|
this.loader(model, this)
|
||||||
|
.then(res => {
|
||||||
|
this.currentOptions = cloneDeep(res);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无form容器,终止
|
||||||
|
if (!this.myForm) return;
|
||||||
|
|
||||||
|
if (this.dict) {
|
||||||
|
const { dictMap } = this.myForm;
|
||||||
|
const options = (dictMap || {})[this.dict];
|
||||||
|
// 建立与表单的字典数据引用
|
||||||
|
if (options) {
|
||||||
|
this.currentOptions = options;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.myForm.loader) {
|
||||||
|
this.loading = true;
|
||||||
|
this.myForm
|
||||||
|
.loader(model, this)
|
||||||
|
.then(res => {
|
||||||
|
this.currentOptions = cloneDeep(res);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 响应currentModel改变处理级联加载数据
|
||||||
|
handleWatch(model) {
|
||||||
|
// 级联上级的值
|
||||||
|
const val = model[this.cascade];
|
||||||
|
// 与上次的值不一致即重新获取数据
|
||||||
|
if (!isEqual(this.cascadeValue, val)) {
|
||||||
|
this.fieldValue = this.getDefaultValue();
|
||||||
|
this.cascadeValue = val;
|
||||||
|
this.loadOptions(model);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 绑定级联
|
||||||
|
bindCascade() {
|
||||||
|
if (this.cascade && this.myForm) {
|
||||||
|
const model = this.myForm.currentModel;
|
||||||
|
this.cascadeValue = model[this.cascade];
|
||||||
|
this.unwatch = this.$watch("myForm.currentModel", this.handleWatch, { deep: true });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 销毁级联事件句柄
|
||||||
|
unbindCascade() {
|
||||||
|
this.unwatch && this.unwatch();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
addResizeListener(this.$el, this.setContentWidth);
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
let model = null;
|
||||||
|
if (this.myForm) {
|
||||||
|
this.myForm.addItem(this);
|
||||||
|
model = this.myForm.currentModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loadOptions(model, this);
|
||||||
|
this.bindCascade();
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
removeResizeListener(this.$el, this.setContentWidth);
|
||||||
|
this.unbindCascade();
|
||||||
|
if (this.myForm) {
|
||||||
|
this.myForm.removeItem(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
54
src/cool/modules/task/components/cron/cn.js
Normal file
54
src/cool/modules/task/components/cron/cn.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
export default {
|
||||||
|
Seconds: {
|
||||||
|
name: "秒",
|
||||||
|
every: "每一秒钟",
|
||||||
|
interval: ["每隔", "秒执行 从", "秒开始"],
|
||||||
|
specific: "具体秒数(可多选)",
|
||||||
|
cycle: ["周期从", "到", "秒"]
|
||||||
|
},
|
||||||
|
Minutes: {
|
||||||
|
name: "分",
|
||||||
|
every: "每一分钟",
|
||||||
|
interval: ["每隔", "分执行 从", "分开始"],
|
||||||
|
specific: "具体分钟数(可多选)",
|
||||||
|
cycle: ["周期从", "到", "分"]
|
||||||
|
},
|
||||||
|
Hours: {
|
||||||
|
name: "时",
|
||||||
|
every: "每一小时",
|
||||||
|
interval: ["每隔", "小时执行 从", "小时开始"],
|
||||||
|
specific: "具体小时数(可多选)",
|
||||||
|
cycle: ["周期从", "到", "小时"]
|
||||||
|
},
|
||||||
|
Day: {
|
||||||
|
name: "天",
|
||||||
|
every: "每一天",
|
||||||
|
intervalWeek: ["每隔", "周执行 从", "开始"],
|
||||||
|
intervalDay: ["每隔", "天执行 从", "天开始"],
|
||||||
|
specificWeek: "具体星期几(可多选)",
|
||||||
|
specificDay: "具体天数(可多选)",
|
||||||
|
lastDay: "在这个月的最后一天",
|
||||||
|
lastWeekday: "在这个月的最后一个工作日",
|
||||||
|
lastWeek: ["在这个月的最后一个"],
|
||||||
|
beforeEndMonth: ["在本月底前", "天"],
|
||||||
|
nearestWeekday: ["最近的工作日(周一至周五)至本月", "日"],
|
||||||
|
someWeekday: ["在这个月的第", "个"]
|
||||||
|
},
|
||||||
|
Week: ["天", "一", "二", "三", "四", "五", "六"].map(val => "星期" + val),
|
||||||
|
Month: {
|
||||||
|
name: "月",
|
||||||
|
every: "每一月",
|
||||||
|
interval: ["每隔", "月执行 从", "月开始"],
|
||||||
|
specific: "具体月数(可多选)",
|
||||||
|
cycle: ["从", "到", "月之间的每个月"]
|
||||||
|
},
|
||||||
|
Year: {
|
||||||
|
name: "年",
|
||||||
|
every: "每一年",
|
||||||
|
interval: ["每隔", "年执行 从", "年开始"],
|
||||||
|
specific: "具体年份(可多选)",
|
||||||
|
cycle: ["从", "到", "年之间的每一年"]
|
||||||
|
},
|
||||||
|
Save: "保存",
|
||||||
|
Close: "关闭"
|
||||||
|
};
|
774
src/cool/modules/task/components/cron/cron.vue
Normal file
774
src/cool/modules/task/components/cron/cron.vue
Normal file
@ -0,0 +1,774 @@
|
|||||||
|
<template>
|
||||||
|
<div class="vue-cron">
|
||||||
|
<el-tabs type="border-card">
|
||||||
|
<el-tab-pane>
|
||||||
|
<span slot="label"><i class="el-icon-date"></i> {{ text.Seconds.name }}</span>
|
||||||
|
<div class="tabBody">
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="second.cronEvery" label="1">{{
|
||||||
|
text.Seconds.every
|
||||||
|
}}</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="second.cronEvery" label="2"
|
||||||
|
>{{ text.Seconds.interval[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="second.incrementIncrement"
|
||||||
|
:min="1"
|
||||||
|
:max="60"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Seconds.interval[1] || "" }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="second.incrementStart"
|
||||||
|
:min="0"
|
||||||
|
:max="59"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Seconds.interval[2] || "" }}
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio class="long" v-model="second.cronEvery" label="3"
|
||||||
|
>{{ text.Seconds.specific }}
|
||||||
|
<el-select size="small" multiple v-model="second.specificSpecific">
|
||||||
|
<el-option v-for="val in 60" :key="val" :value="val - 1">{{
|
||||||
|
val - 1
|
||||||
|
}}</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="second.cronEvery" label="4"
|
||||||
|
>{{ text.Seconds.cycle[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="second.rangeStart"
|
||||||
|
:min="1"
|
||||||
|
:max="60"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Seconds.cycle[1] || "" }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="second.rangeEnd"
|
||||||
|
:min="0"
|
||||||
|
:max="59"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Seconds.cycle[2] || "" }}
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane>
|
||||||
|
<span slot="label"><i class="el-icon-date"></i> {{ text.Minutes.name }}</span>
|
||||||
|
<div class="tabBody">
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="minute.cronEvery" label="1">{{
|
||||||
|
text.Minutes.every
|
||||||
|
}}</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="minute.cronEvery" label="2"
|
||||||
|
>{{ text.Minutes.interval[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="minute.incrementIncrement"
|
||||||
|
:min="1"
|
||||||
|
:max="60"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Minutes.interval[1] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="minute.incrementStart"
|
||||||
|
:min="0"
|
||||||
|
:max="59"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Minutes.interval[2] || "" }}
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio class="long" v-model="minute.cronEvery" label="3"
|
||||||
|
>{{ text.Minutes.specific }}
|
||||||
|
<el-select size="small" multiple v-model="minute.specificSpecific">
|
||||||
|
<el-option v-for="val in 60" :key="val" :value="val - 1">{{
|
||||||
|
val - 1
|
||||||
|
}}</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="minute.cronEvery" label="4"
|
||||||
|
>{{ text.Minutes.cycle[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="minute.rangeStart"
|
||||||
|
:min="1"
|
||||||
|
:max="60"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Minutes.cycle[1] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="minute.rangeEnd"
|
||||||
|
:min="0"
|
||||||
|
:max="59"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Minutes.cycle[2] }}
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane>
|
||||||
|
<span slot="label"><i class="el-icon-date"></i> {{ text.Hours.name }}</span>
|
||||||
|
<div class="tabBody">
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="hour.cronEvery" label="1">{{
|
||||||
|
text.Hours.every
|
||||||
|
}}</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="hour.cronEvery" label="2"
|
||||||
|
>{{ text.Hours.interval[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="hour.incrementIncrement"
|
||||||
|
:min="0"
|
||||||
|
:max="23"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Hours.interval[1] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="hour.incrementStart"
|
||||||
|
:min="0"
|
||||||
|
:max="23"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Hours.interval[2] }}
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio class="long" v-model="hour.cronEvery" label="3"
|
||||||
|
>{{ text.Hours.specific }}
|
||||||
|
<el-select size="small" multiple v-model="hour.specificSpecific">
|
||||||
|
<el-option v-for="val in 24" :key="val" :value="val - 1">{{
|
||||||
|
val - 1
|
||||||
|
}}</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="hour.cronEvery" label="4"
|
||||||
|
>{{ text.Hours.cycle[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="hour.rangeStart"
|
||||||
|
:min="0"
|
||||||
|
:max="23"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Hours.cycle[1] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="hour.rangeEnd"
|
||||||
|
:min="0"
|
||||||
|
:max="23"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Hours.cycle[2] }}
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane>
|
||||||
|
<span slot="label"><i class="el-icon-date"></i> {{ text.Day.name }}</span>
|
||||||
|
<div class="tabBody">
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="day.cronEvery" label="1">{{ text.Day.every }}</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="day.cronEvery" label="2"
|
||||||
|
>{{ text.Day.intervalWeek[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="week.incrementIncrement"
|
||||||
|
:min="1"
|
||||||
|
:max="7"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Day.intervalWeek[1] }}
|
||||||
|
<el-select size="small" v-model="week.incrementStart">
|
||||||
|
<el-option
|
||||||
|
v-for="val in 7"
|
||||||
|
:key="val"
|
||||||
|
:label="text.Week[val - 1]"
|
||||||
|
:value="val"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
{{ text.Day.intervalWeek[2] }}
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="day.cronEvery" label="3"
|
||||||
|
>{{ text.Day.intervalDay[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="day.incrementIncrement"
|
||||||
|
:min="1"
|
||||||
|
:max="31"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Day.intervalDay[1] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="day.incrementStart"
|
||||||
|
:min="1"
|
||||||
|
:max="31"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Day.intervalDay[2] }}
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio class="long" v-model="day.cronEvery" label="4"
|
||||||
|
>{{ text.Day.specificWeek }}
|
||||||
|
<el-select size="small" multiple v-model="week.specificSpecific">
|
||||||
|
<el-option
|
||||||
|
v-for="val in 7"
|
||||||
|
:key="val"
|
||||||
|
:label="text.Week[val - 1]"
|
||||||
|
:value="
|
||||||
|
['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'][val - 1]
|
||||||
|
"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio class="long" v-model="day.cronEvery" label="5"
|
||||||
|
>{{ text.Day.specificDay }}
|
||||||
|
<el-select size="small" multiple v-model="day.specificSpecific">
|
||||||
|
<el-option v-for="val in 31" :key="val" :value="val">{{
|
||||||
|
val
|
||||||
|
}}</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="day.cronEvery" label="6">{{
|
||||||
|
text.Day.lastDay
|
||||||
|
}}</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="day.cronEvery" label="7">{{
|
||||||
|
text.Day.lastWeekday
|
||||||
|
}}</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="day.cronEvery" label="8"
|
||||||
|
>{{ text.Day.lastWeek[0] }}
|
||||||
|
<el-select size="small" v-model="day.cronLastSpecificDomDay">
|
||||||
|
<el-option
|
||||||
|
v-for="val in 7"
|
||||||
|
:key="val"
|
||||||
|
:label="text.Week[val - 1]"
|
||||||
|
:value="val"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
{{ text.Day.lastWeek[1] || "" }}
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="day.cronEvery" label="9">
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="day.cronDaysBeforeEomMinus"
|
||||||
|
:min="1"
|
||||||
|
:max="31"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Day.beforeEndMonth[0] }}
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="day.cronEvery" label="10"
|
||||||
|
>{{ text.Day.nearestWeekday[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="day.cronDaysNearestWeekday"
|
||||||
|
:min="1"
|
||||||
|
:max="31"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Day.nearestWeekday[1] }}
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="day.cronEvery" label="11"
|
||||||
|
>{{ text.Day.someWeekday[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="week.cronNthDayNth"
|
||||||
|
:min="1"
|
||||||
|
:max="5"
|
||||||
|
></el-input-number>
|
||||||
|
<el-select
|
||||||
|
size="small"
|
||||||
|
v-model="week.cronNthDayDay"
|
||||||
|
style="margin-left: 5px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="val in 7"
|
||||||
|
:key="val"
|
||||||
|
:label="text.Week[val - 1]"
|
||||||
|
:value="val"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
{{ text.Day.someWeekday[1] }}
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane>
|
||||||
|
<span slot="label"><i class="el-icon-date"></i> {{ text.Month.name }}</span>
|
||||||
|
<div class="tabBody">
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="month.cronEvery" label="1">{{
|
||||||
|
text.Month.every
|
||||||
|
}}</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="month.cronEvery" label="2"
|
||||||
|
>{{ text.Month.interval[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="month.incrementIncrement"
|
||||||
|
:min="0"
|
||||||
|
:max="12"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Month.interval[1] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="month.incrementStart"
|
||||||
|
:min="0"
|
||||||
|
:max="12"
|
||||||
|
></el-input-number>
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio class="long" v-model="month.cronEvery" label="3"
|
||||||
|
>{{ text.Month.specific }}
|
||||||
|
<el-select size="small" multiple v-model="month.specificSpecific">
|
||||||
|
<el-option
|
||||||
|
v-for="val in 12"
|
||||||
|
:key="val"
|
||||||
|
:label="val"
|
||||||
|
:value="val"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="month.cronEvery" label="4"
|
||||||
|
>{{ text.Month.cycle[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="month.rangeStart"
|
||||||
|
:min="1"
|
||||||
|
:max="12"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Month.cycle[1] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="month.rangeEnd"
|
||||||
|
:min="1"
|
||||||
|
:max="12"
|
||||||
|
></el-input-number>
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane v-if="showYear || false">
|
||||||
|
<span slot="label"><i class="el-icon-date"></i> {{ text.Year.name }}</span>
|
||||||
|
<div class="tabBody">
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="year.cronEvery" label="1">{{
|
||||||
|
text.Year.every
|
||||||
|
}}</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="year.cronEvery" label="2"
|
||||||
|
>{{ text.Year.interval[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="year.incrementIncrement"
|
||||||
|
:min="1"
|
||||||
|
:max="99"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Year.interval[1] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="year.incrementStart"
|
||||||
|
:min="2018"
|
||||||
|
:max="2118"
|
||||||
|
></el-input-number>
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio class="long" v-model="year.cronEvery" label="3"
|
||||||
|
>{{ text.Year.specific }}
|
||||||
|
<el-select
|
||||||
|
size="small"
|
||||||
|
filterable
|
||||||
|
multiple
|
||||||
|
v-model="year.specificSpecific"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="val in 100"
|
||||||
|
:key="val"
|
||||||
|
:label="2017 + val"
|
||||||
|
:value="2017 + val"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-radio v-model="year.cronEvery" label="4"
|
||||||
|
>{{ text.Year.cycle[0] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="year.rangeStart"
|
||||||
|
:min="2018"
|
||||||
|
:max="2118"
|
||||||
|
></el-input-number>
|
||||||
|
{{ text.Year.cycle[1] }}
|
||||||
|
<el-input-number
|
||||||
|
size="small"
|
||||||
|
v-model="year.rangeEnd"
|
||||||
|
:min="2018"
|
||||||
|
:max="2118"
|
||||||
|
></el-input-number>
|
||||||
|
</el-radio>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
<div class="bottom">
|
||||||
|
<!-- <span class="value">{{this.cron}}</span> -->
|
||||||
|
<el-button type="primary" @click="change">{{ text.Save }}</el-button>
|
||||||
|
<el-button type="primary" @click="close">{{ text.Close }}</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Language from "./cn";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "vue-cron",
|
||||||
|
|
||||||
|
props: ["data", "i18n", "showYear"],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
second: {
|
||||||
|
cronEvery: "",
|
||||||
|
incrementStart: "3",
|
||||||
|
incrementIncrement: "5",
|
||||||
|
rangeStart: "",
|
||||||
|
rangeEnd: "",
|
||||||
|
specificSpecific: []
|
||||||
|
},
|
||||||
|
minute: {
|
||||||
|
cronEvery: "",
|
||||||
|
incrementStart: "3",
|
||||||
|
incrementIncrement: "5",
|
||||||
|
rangeStart: "",
|
||||||
|
rangeEnd: "",
|
||||||
|
specificSpecific: []
|
||||||
|
},
|
||||||
|
hour: {
|
||||||
|
cronEvery: "",
|
||||||
|
incrementStart: "3",
|
||||||
|
incrementIncrement: "5",
|
||||||
|
rangeStart: "",
|
||||||
|
rangeEnd: "",
|
||||||
|
specificSpecific: []
|
||||||
|
},
|
||||||
|
day: {
|
||||||
|
cronEvery: "",
|
||||||
|
incrementStart: "1",
|
||||||
|
incrementIncrement: "1",
|
||||||
|
rangeStart: "",
|
||||||
|
rangeEnd: "",
|
||||||
|
specificSpecific: [],
|
||||||
|
cronLastSpecificDomDay: 1,
|
||||||
|
cronDaysBeforeEomMinus: "",
|
||||||
|
cronDaysNearestWeekday: ""
|
||||||
|
},
|
||||||
|
week: {
|
||||||
|
cronEvery: "",
|
||||||
|
incrementStart: "1",
|
||||||
|
incrementIncrement: "1",
|
||||||
|
specificSpecific: [],
|
||||||
|
cronNthDayDay: 1,
|
||||||
|
cronNthDayNth: "1"
|
||||||
|
},
|
||||||
|
month: {
|
||||||
|
cronEvery: "",
|
||||||
|
incrementStart: "3",
|
||||||
|
incrementIncrement: "5",
|
||||||
|
rangeStart: "",
|
||||||
|
rangeEnd: "",
|
||||||
|
specificSpecific: []
|
||||||
|
},
|
||||||
|
year: {
|
||||||
|
cronEvery: "",
|
||||||
|
incrementStart: "2017",
|
||||||
|
incrementIncrement: "1",
|
||||||
|
rangeStart: "",
|
||||||
|
rangeEnd: "",
|
||||||
|
specificSpecific: []
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
second: "",
|
||||||
|
minute: "",
|
||||||
|
hour: "",
|
||||||
|
day: "",
|
||||||
|
month: "",
|
||||||
|
Week: "",
|
||||||
|
year: ""
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
data() {
|
||||||
|
this.rest(this.$data);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
text() {
|
||||||
|
return Language;
|
||||||
|
},
|
||||||
|
secondsText() {
|
||||||
|
let seconds = "";
|
||||||
|
const cronEvery = this.second.cronEvery;
|
||||||
|
switch (cronEvery.toString()) {
|
||||||
|
case "1":
|
||||||
|
seconds = "*";
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
seconds = this.second.incrementStart + "/" + this.second.incrementIncrement;
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
this.second.specificSpecific.forEach(val => {
|
||||||
|
seconds += val + ",";
|
||||||
|
});
|
||||||
|
seconds = seconds.slice(0, -1);
|
||||||
|
break;
|
||||||
|
case "4":
|
||||||
|
seconds = this.second.rangeStart + "-" + this.second.rangeEnd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return seconds;
|
||||||
|
},
|
||||||
|
minutesText() {
|
||||||
|
let minutes = "";
|
||||||
|
const cronEvery = this.minute.cronEvery;
|
||||||
|
switch (cronEvery.toString()) {
|
||||||
|
case "1":
|
||||||
|
minutes = "*";
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
minutes = this.minute.incrementStart + "/" + this.minute.incrementIncrement;
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
this.minute.specificSpecific.forEach(val => {
|
||||||
|
minutes += val + ",";
|
||||||
|
});
|
||||||
|
minutes = minutes.slice(0, -1);
|
||||||
|
break;
|
||||||
|
case "4":
|
||||||
|
minutes = this.minute.rangeStart + "-" + this.minute.rangeEnd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return minutes;
|
||||||
|
},
|
||||||
|
hoursText() {
|
||||||
|
let hours = "";
|
||||||
|
const cronEvery = this.hour.cronEvery;
|
||||||
|
switch (cronEvery.toString()) {
|
||||||
|
case "1":
|
||||||
|
hours = "*";
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
hours = this.hour.incrementStart + "/" + this.hour.incrementIncrement;
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
this.hour.specificSpecific.forEach(val => {
|
||||||
|
hours += val + ",";
|
||||||
|
});
|
||||||
|
hours = hours.slice(0, -1);
|
||||||
|
break;
|
||||||
|
case "4":
|
||||||
|
hours = this.hour.rangeStart + "-" + this.hour.rangeEnd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return hours;
|
||||||
|
},
|
||||||
|
daysText() {
|
||||||
|
let days = "";
|
||||||
|
const cronEvery = this.day.cronEvery;
|
||||||
|
switch (cronEvery.toString()) {
|
||||||
|
case "1":
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
case "4":
|
||||||
|
case "11":
|
||||||
|
days = "?";
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
days = this.day.incrementStart + "/" + this.day.incrementIncrement;
|
||||||
|
break;
|
||||||
|
case "5":
|
||||||
|
this.day.specificSpecific.forEach(val => {
|
||||||
|
days += val + ",";
|
||||||
|
});
|
||||||
|
days = days.slice(0, -1);
|
||||||
|
break;
|
||||||
|
case "6":
|
||||||
|
days = "L";
|
||||||
|
break;
|
||||||
|
case "7":
|
||||||
|
days = "LW";
|
||||||
|
break;
|
||||||
|
case "8":
|
||||||
|
days = this.day.cronLastSpecificDomDay + "L";
|
||||||
|
break;
|
||||||
|
case "9":
|
||||||
|
days = "L-" + this.day.cronDaysBeforeEomMinus;
|
||||||
|
break;
|
||||||
|
case "10":
|
||||||
|
days = this.day.cronDaysNearestWeekday + "W";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return days;
|
||||||
|
},
|
||||||
|
weeksText() {
|
||||||
|
let weeks = "";
|
||||||
|
const cronEvery = this.day.cronEvery;
|
||||||
|
switch (cronEvery.toString()) {
|
||||||
|
case "1":
|
||||||
|
case "3":
|
||||||
|
case "5":
|
||||||
|
weeks = "?";
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
weeks = this.week.incrementStart + "/" + this.week.incrementIncrement;
|
||||||
|
break;
|
||||||
|
case "4":
|
||||||
|
this.week.specificSpecific.forEach(val => {
|
||||||
|
weeks += val + ",";
|
||||||
|
});
|
||||||
|
weeks = weeks.slice(0, -1);
|
||||||
|
break;
|
||||||
|
case "6":
|
||||||
|
case "7":
|
||||||
|
case "8":
|
||||||
|
case "9":
|
||||||
|
case "10":
|
||||||
|
weeks = "?";
|
||||||
|
break;
|
||||||
|
case "11":
|
||||||
|
weeks = this.week.cronNthDayDay + "#" + this.week.cronNthDayNth;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return weeks;
|
||||||
|
},
|
||||||
|
monthsText() {
|
||||||
|
let months = "";
|
||||||
|
const cronEvery = this.month.cronEvery;
|
||||||
|
switch (cronEvery.toString()) {
|
||||||
|
case "1":
|
||||||
|
months = "*";
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
months = this.month.incrementStart + "/" + this.month.incrementIncrement;
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
this.month.specificSpecific.forEach(val => {
|
||||||
|
months += val + ",";
|
||||||
|
});
|
||||||
|
months = months.slice(0, -1);
|
||||||
|
break;
|
||||||
|
case "4":
|
||||||
|
months = this.month.rangeStart + "-" + this.month.rangeEnd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return months;
|
||||||
|
},
|
||||||
|
yearsText() {
|
||||||
|
let years = "";
|
||||||
|
const cronEvery = this.year.cronEvery;
|
||||||
|
switch (cronEvery.toString()) {
|
||||||
|
case "1":
|
||||||
|
years = "*";
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
years = this.year.incrementStart + "/" + this.year.incrementIncrement;
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
this.year.specificSpecific.forEach(val => {
|
||||||
|
years += val + ",";
|
||||||
|
});
|
||||||
|
years = years.slice(0, -1);
|
||||||
|
break;
|
||||||
|
case "4":
|
||||||
|
years = this.year.rangeStart + "-" + this.year.rangeEnd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return years;
|
||||||
|
},
|
||||||
|
cron() {
|
||||||
|
return `${this.secondsText || "*"} ${this.minutesText || "*"} ${this.hoursText ||
|
||||||
|
"*"} ${this.daysText || "*"} ${this.monthsText || "*"} ${this.weeksText || "?"} ${
|
||||||
|
this.showYear ? this.yearsText || "*" : ""
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
getValue() {
|
||||||
|
return this.cron;
|
||||||
|
},
|
||||||
|
change() {
|
||||||
|
this.$emit("change", this.cron);
|
||||||
|
this.close();
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
this.$emit("close");
|
||||||
|
},
|
||||||
|
rest(data) {
|
||||||
|
for (const i in data) {
|
||||||
|
if (data[i] instanceof Object) {
|
||||||
|
this.rest(data[i]);
|
||||||
|
} else {
|
||||||
|
switch (typeof data[i]) {
|
||||||
|
case "object":
|
||||||
|
data[i] = [];
|
||||||
|
break;
|
||||||
|
case "string":
|
||||||
|
data[i] = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.bottom {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.tabBody /deep/ .el-row {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vue-cron /deep/ .el-tabs {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
</style>
|
80
src/cool/modules/task/components/cron/index.js
Normal file
80
src/cool/modules/task/components/cron/index.js
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import Cron from "./cron";
|
||||||
|
import Base from "./base";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "cl-cron",
|
||||||
|
|
||||||
|
mixins: [Base],
|
||||||
|
|
||||||
|
components: {
|
||||||
|
Cron
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
value: String,
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: "请输入定时策略"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
cronPopover: false,
|
||||||
|
cron: ""
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
cron: {
|
||||||
|
handler(val) {
|
||||||
|
this.fieldValue = val;
|
||||||
|
this.$emit("change", val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
this.cron = val;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fieldValue: {
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
this.cron = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
changeCron(val) {
|
||||||
|
this.cron = val;
|
||||||
|
},
|
||||||
|
hidePopover() {
|
||||||
|
this.cronPopover = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const vnode = (
|
||||||
|
<el-popover vModel={this.cronPopover} disabled={this.disabled || this.readonly}>
|
||||||
|
<Cron
|
||||||
|
{...{
|
||||||
|
props: { i18n: "cn" },
|
||||||
|
on: {
|
||||||
|
change: this.changeCron,
|
||||||
|
close: this.hidePopover
|
||||||
|
}
|
||||||
|
}}></Cron>
|
||||||
|
<el-input
|
||||||
|
slot="reference"
|
||||||
|
clearable={true}
|
||||||
|
disabled={this.disabled}
|
||||||
|
readonly={this.readonly}
|
||||||
|
vModel={this.cron}
|
||||||
|
placeholder={this.placeholder}></el-input>
|
||||||
|
</el-popover>
|
||||||
|
);
|
||||||
|
return this.renderComponent(vnode);
|
||||||
|
}
|
||||||
|
};
|
@ -200,6 +200,7 @@
|
|||||||
import draggable from "vuedraggable";
|
import draggable from "vuedraggable";
|
||||||
import { checkPerm } from "@/cool/modules/base";
|
import { checkPerm } from "@/cool/modules/base";
|
||||||
import { Form, ContextMenu } from "cl-admin-crud";
|
import { Form, ContextMenu } from "cl-admin-crud";
|
||||||
|
import Cron from "../components/cron";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "system-task",
|
name: "system-task",
|
||||||
@ -467,12 +468,7 @@ export default {
|
|||||||
return scope.taskType == 1;
|
return scope.taskType == 1;
|
||||||
},
|
},
|
||||||
value: info.cron,
|
value: info.cron,
|
||||||
component: {
|
component: Cron,
|
||||||
name: "el-input",
|
|
||||||
attrs: {
|
|
||||||
placeholder: "* * * * * *"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
rules: {
|
rules: {
|
||||||
required: true,
|
required: true,
|
||||||
message: "cron不能为空"
|
message: "cron不能为空"
|
||||||
|
5
src/cool/modules/theme/components/index.js
Normal file
5
src/cool/modules/theme/components/index.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import Theme from "./theme";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
Theme
|
||||||
|
};
|
285
src/cool/modules/theme/components/theme.vue
Normal file
285
src/cool/modules/theme/components/theme.vue
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
<template>
|
||||||
|
<div class="cl-theme">
|
||||||
|
<li @click="open">
|
||||||
|
<icon-svg :size="18" name="icon-theme"></icon-svg>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<!-- 系统设置 -->
|
||||||
|
<el-drawer title="系统设置" :visible.sync="drawer.visible" size="300px">
|
||||||
|
<div class="cl-theme__color is-card">
|
||||||
|
<p>主题</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<el-tooltip
|
||||||
|
v-for="(item, name) in thems"
|
||||||
|
:key="name"
|
||||||
|
:content="item.label"
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
:style="{
|
||||||
|
backgroundColor: item.color
|
||||||
|
}"
|
||||||
|
@click="setTheme(item)"
|
||||||
|
>
|
||||||
|
<i class="el-icon-check" v-if="item.color == app.theme.color"></i>
|
||||||
|
</li>
|
||||||
|
</el-tooltip>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="cl-theme__switch is-card">
|
||||||
|
<p>内容区域</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<span>显示一级菜单栏</span>
|
||||||
|
<el-switch size="mini" v-model="app.conf.showAMenu"></el-switch>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span>显示路由导航栏</span>
|
||||||
|
<el-switch size="mini" v-model="app.conf.showRouteNav"></el-switch>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span>显示页面进程栏</span>
|
||||||
|
<el-switch size="mini" v-model="app.conf.showProcess"></el-switch>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="cl-theme__tips">
|
||||||
|
<el-alert
|
||||||
|
type="warning"
|
||||||
|
:closable="false"
|
||||||
|
show-icon
|
||||||
|
title="手动修改配置文件可设置为默认主题、布局。"
|
||||||
|
></el-alert>
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
round
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
style="width: 100%"
|
||||||
|
:disabled="!app.theme.url"
|
||||||
|
@click="openDesc"
|
||||||
|
>修改说明</el-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
|
||||||
|
<!-- 修改说明 -->
|
||||||
|
<cl-dialog
|
||||||
|
:visible.sync="desc.visible"
|
||||||
|
title="修改说明"
|
||||||
|
width="800px"
|
||||||
|
:props="{
|
||||||
|
'append-to-body': true
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<ul class="cl-theme__desc">
|
||||||
|
<li>
|
||||||
|
<p class="cl-theme__desc-label">修改主题色:</p>
|
||||||
|
<cl-codemirror v-model="desc.color"></cl-codemirror>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<p class="cl-theme__desc-label">修改应用配置:</p>
|
||||||
|
<cl-codemirror v-model="desc.conf"></cl-codemirror>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</cl-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from "vuex";
|
||||||
|
import { isDev } from "@/config/env";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "cl-theme",
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
drawer: {
|
||||||
|
visible: false
|
||||||
|
},
|
||||||
|
desc: {
|
||||||
|
visible: false,
|
||||||
|
color: "",
|
||||||
|
conf: ""
|
||||||
|
},
|
||||||
|
thems: [
|
||||||
|
{
|
||||||
|
label: "钴蓝(默认)",
|
||||||
|
name: "blue",
|
||||||
|
color: "#4165d7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "极黑",
|
||||||
|
name: "black",
|
||||||
|
color: "#2f3447"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "果绿色",
|
||||||
|
name: "green",
|
||||||
|
color: "#51C21A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "酱紫色",
|
||||||
|
name: "purple",
|
||||||
|
color: "#d0378d"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
isDev
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
...mapGetters(["app", "modules"])
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
app: {
|
||||||
|
deep: true,
|
||||||
|
handler() {
|
||||||
|
this.$store.commit("UPDATE_APP", this.app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
open() {
|
||||||
|
this.drawer.visible = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.drawer.visible = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 设置主题
|
||||||
|
setTheme({ name, color, label }) {
|
||||||
|
this.$message.success(`切换主题:${label}`);
|
||||||
|
|
||||||
|
const theme = document.getElementById("theme-style");
|
||||||
|
const style = theme || document.createElement("link");
|
||||||
|
|
||||||
|
style.href = `${this.modules.theme.options.sourceUrl || "/theme/"}${name}.css`;
|
||||||
|
|
||||||
|
if (!theme) {
|
||||||
|
style.type = "text/css";
|
||||||
|
style.rel = "stylesheet";
|
||||||
|
style.id = "theme-style";
|
||||||
|
|
||||||
|
document
|
||||||
|
.getElementsByTagName("head")
|
||||||
|
.item(0)
|
||||||
|
.appendChild(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置主题色和路径
|
||||||
|
this.app.theme.color = color;
|
||||||
|
this.app.theme.url = style.href;
|
||||||
|
|
||||||
|
// 设置 css 变量
|
||||||
|
document.getElementsByTagName("body")[0].style.setProperty("--color-primary", color);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 打开修改说明
|
||||||
|
openDesc() {
|
||||||
|
this.desc.visible = true;
|
||||||
|
|
||||||
|
this.desc.color = `
|
||||||
|
// src/assets/css/common.scss
|
||||||
|
$primary: ${this.app.theme.color};
|
||||||
|
`;
|
||||||
|
|
||||||
|
this.desc.conf = `
|
||||||
|
// src/config/env.js
|
||||||
|
export const app = {
|
||||||
|
conf: ${JSON.stringify(this.app.conf)},
|
||||||
|
thems: {
|
||||||
|
url: "${this.app.theme.url}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.cl-theme {
|
||||||
|
.is-card {
|
||||||
|
padding: 20px 0;
|
||||||
|
margin: 0 20px 20px 20px;
|
||||||
|
border-bottom: 1px solid #f7f7f7;
|
||||||
|
|
||||||
|
& > p {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__switch {
|
||||||
|
ul {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
height: 40px;
|
||||||
|
list-style: none;
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__color {
|
||||||
|
ul {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
|
li {
|
||||||
|
list-style: none;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-right: 10px;
|
||||||
|
text-align: center;
|
||||||
|
color: #fff;
|
||||||
|
line-height: 20px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__tips {
|
||||||
|
padding: 10px 20px;
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__desc {
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
&-label {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
list-style: none;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
3
src/cool/modules/theme/index.js
Normal file
3
src/cool/modules/theme/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import components from "./components";
|
||||||
|
|
||||||
|
export default { components };
|
@ -32,8 +32,6 @@
|
|||||||
:http-request="action ? undefined : httpRequest"
|
:http-request="action ? undefined : httpRequest"
|
||||||
:on-remove="_onRemove"
|
:on-remove="_onRemove"
|
||||||
:on-preview="_onPreview"
|
:on-preview="_onPreview"
|
||||||
:on-success="_onSuccess"
|
|
||||||
:on-error="onError"
|
|
||||||
:on-progress="onProgress"
|
:on-progress="onProgress"
|
||||||
:on-change="onChange"
|
:on-change="onChange"
|
||||||
:on-exceed="onExceed"
|
:on-exceed="onExceed"
|
||||||
@ -188,7 +186,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(["token", "modules", "upload"]),
|
...mapGetters(["token", "modules"]),
|
||||||
|
|
||||||
conf() {
|
conf() {
|
||||||
return this.modules.upload.options;
|
return this.modules.upload.options;
|
||||||
@ -418,9 +416,9 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 重设上传请求
|
// 重设上传请求
|
||||||
httpRequest(req) {
|
async httpRequest(req) {
|
||||||
const isRename = isEmpty(this.rename) ? this.conf.rename : this.rename;
|
const isRename = isEmpty(this.rename) ? this.conf.rename : this.rename;
|
||||||
const { mode } = this.upload;
|
const mode = await this.uploadMode();
|
||||||
|
|
||||||
// 多种上传请求
|
// 多种上传请求
|
||||||
const upload = file => {
|
const upload = file => {
|
||||||
@ -509,6 +507,11 @@ export default {
|
|||||||
.done(() => {
|
.done(() => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 上传模式
|
||||||
|
uploadMode() {
|
||||||
|
return this.$service.common.uploadMode().then(res => res.mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<topbar></topbar>
|
<topbar></topbar>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="page-layout__process" v-if="conf.showProcess">
|
<div class="page-layout__process" v-if="app.conf.showProcess">
|
||||||
<cl-process />
|
<cl-process />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(["menuCollapse", "conf", "browser"]),
|
...mapGetters(["menuCollapse", "app", "browser"]),
|
||||||
|
|
||||||
isKeepAlive() {
|
isKeepAlive() {
|
||||||
return isEmpty(this.$route.meta.keepAlive) ? true : this.$route.meta.keepAlive;
|
return isEmpty(this.$route.meta.keepAlive) ? true : this.$route.meta.keepAlive;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div class="app-slider">
|
<div class="app-slider">
|
||||||
<div class="app-slider__logo" @click="toHome">
|
<div class="app-slider__logo" @click="toHome">
|
||||||
<img src="@/assets/icon/logo/silder-simple.png" />
|
<img src="@/assets/icon/logo/silder-simple.png" />
|
||||||
<span v-if="!menuCollapse || browser.isMobile">{{ appInfo.name }}</span>
|
<span v-if="!menuCollapse || browser.isMobile">{{ app.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="app-slider__menu">
|
<div class="app-slider__menu">
|
||||||
@ -16,7 +16,7 @@ import { mapGetters } from "vuex";
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(["menuCollapse", "browser", "appInfo"])
|
...mapGetters(["menuCollapse", "browser", "app"])
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 一级菜单 -->
|
<!-- 一级菜单 -->
|
||||||
<div class="app-topbar__menu" v-if="conf.showAMenu">
|
<div class="app-topbar__menu" v-if="app.conf.showAMenu">
|
||||||
<cl-menu-topbar />
|
<cl-menu-topbar />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 路由导航 -->
|
<!-- 路由导航 -->
|
||||||
<div class="app-topbar__route-nav" v-if="conf.showRouteNav">
|
<div class="app-topbar__route-nav" v-if="app.conf.showRouteNav">
|
||||||
<cl-route-nav />
|
<cl-route-nav />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ import { href } from "cl-admin/utils";
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(["userInfo", "menuCollapse", "conf", "modules"])
|
...mapGetters(["userInfo", "menuCollapse", "app", "modules"])
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -13,7 +13,7 @@ const PROXY_LIST = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
"/ap": {
|
"/ap": {
|
||||||
target: "https://admin.cn.utools.club",
|
target: "https://admin.cool-js.cool",
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
pathRewrite: {
|
pathRewrite: {
|
||||||
"^/ap": ""
|
"^/ap": ""
|
||||||
|
Loading…
Reference in New Issue
Block a user