Commit f73bbf52 authored by 陈浩玮's avatar 陈浩玮

Merge branch 'feature/shuiluo' into 'master'

feat: 完成菜单组件管理

See merge request product/kim3-web-vue/starter-web-vue!22
parents 9cc3fe98 e7671869
VUE_APP_PUBLIC_PATH=/ VUE_APP_PUBLIC_PATH=/
VUE_APP_NAME=Admin VUE_APP_NAME=Karote
VUE_APP_ROUTES_KEY=admin.routes VUE_APP_ROUTES_KEY=admin.routes
VUE_APP_PERMISSIONS_KEY=admin.permissions VUE_APP_PERMISSIONS_KEY=admin.permissions
VUE_APP_ROLES_KEY=admin.roles VUE_APP_ROLES_KEY=admin.roles
......
import { request, METHOD } from '@/utils'; import { request, METHOD } from '@/utils';
export * from './menu'; export * from './menu';
export * from './system'; export * from './system';
export * from './task';
export function getUserDetailInfoApi() { export function getUserDetailInfoApi() {
return request('/api/v1/detail', METHOD.GET); return request('/api/v1/detail', METHOD.GET);
......
...@@ -35,3 +35,11 @@ export function getRoleApi(id) { ...@@ -35,3 +35,11 @@ export function getRoleApi(id) {
export function updateRoleApi(data) { export function updateRoleApi(data) {
return putReq('/api/v1/roles', data); return putReq('/api/v1/roles', data);
} }
export function getMenuComponentApi(id) {
return getReq(`/api/v1/menus/${id}/components`);
}
export function addMenuComponentApi(id, data) {
return postReq(`/api/v1/menus/${id}/components`, data);
}
import { postReq, putReq } from '@/utils';
export function addTaskApi(data) {
return postReq('/api/v1/schedules', data);
}
export function updateTaskApi(data) {
return putReq('/api/v1/schedules', data);
}
<template> <template>
<div class="components-input-demo-presuffix"> <div class="components-input-demo-presuffix">
<a-input :placeholder="placeholder" :value="cron" @input="handleinput"> <a-input :placeholder="placeholder" :value="cron" @input="handleinput" :disabled="disabled">
<a-icon slot="prefix" type="schedule" title="corn控件" @click="openModal" /> <a-icon slot="prefix" type="schedule" title="corn控件" @click="openModal" />
<a-icon v-if="cron" slot="suffix" type="close-circle" @click="handleEmpty" title="清空" /> <a-icon v-if="cron" slot="suffix" type="close-circle" @click="handleEmpty" title="清空" />
</a-input> </a-input>
<AntCron ref="innerVueCron" :data="afterCron" @ok="handleOK"></AntCron> <AntCron ref="innerVueCron" :data="afterCron" @ok="handleOK"></AntCron>
</div> </div>
</template> </template>
<script> <script>
import AntCron from "./AntCron"; import AntCron from './AntCron';
import { replaceWeekName } from "./validator"; import { replaceWeekName } from './validator';
export default { export default {
name: "ACron", name: 'ACron',
components: { components: {
AntCron AntCron,
},
props: {
value: {
required: false,
type: String,
default: ""
}, },
placeholder: { props: {
required: false, value: {
type: String, required: false,
default: "" type: String,
} default: '',
}, },
data() { placeholder: {
return { required: false,
cron: this.value, type: String,
afterCron: "" default: '',
}; },
}, disabled: Boolean,
watch: {
value(val) {
this.cron = val;
}, },
cron(val) { data() {
console.log(replaceWeekName(val)); return {
this.afterCron = replaceWeekName(val); cron: this.value,
console.log(val); afterCron: '',
this.$emit("input", val); };
}
},
methods: {
openModal() {
this.$refs.innerVueCron.show();
}, },
handleOK(val) { watch: {
this.cron = val; value(val) {
this.$emit("change", this.cron); this.cron = val;
},
cron(val) {
console.log(replaceWeekName(val));
this.afterCron = replaceWeekName(val);
console.log(val);
this.$emit('input', val);
},
}, },
handleinput(evt) { methods: {
this.cron = evt.target.value; openModal() {
if (this.cron !== "") { if (this.disabled) return;
this.$emit("change", this.cron); this.$refs.innerVueCron.show();
} else { },
this.$emit("change", undefined); handleOK(val) {
} this.cron = val;
this.$emit('change', this.cron);
},
handleinput(evt) {
this.cron = evt.target.value;
if (this.cron !== '') {
this.$emit('change', this.cron);
} else {
this.$emit('change', undefined);
}
},
handleEmpty() {
if (this.disabled) return;
this.handleOK('');
},
},
model: {
prop: 'value',
event: 'change',
}, },
handleEmpty() {
this.handleOK("");
}
},
model: {
prop: "value",
event: "change"
}
}; };
</script> </script>
<style scoped> <style scoped>
.components-input-demo-presuffix .anticon-close-circle { .components-input-demo-presuffix .anticon-close-circle {
cursor: pointer; cursor: pointer;
color: #ccc; color: #ccc;
transition: color 0.3s; transition: color 0.3s;
font-size: 12px; font-size: 12px;
} }
.components-input-demo-presuffix .anticon-close-circle:hover { .components-input-demo-presuffix .anticon-close-circle:hover {
color: #f5222d; color: #f5222d;
} }
.components-input-demo-presuffix .anticon-close-circle:active { .components-input-demo-presuffix .anticon-close-circle:active {
color: #666; color: #666;
} }
</style> </style>
\ No newline at end of file
<template> <template>
<a-modal <a-modal
title="corn表达式" title="corn表达式"
:width="modalWidth" :width="modalWidth"
:visible="visible" :visible="visible"
:confirmLoading="confirmLoading" :confirmLoading="confirmLoading"
@ok="handleSubmit" @ok="handleSubmit"
@cancel="close" @cancel="close"
cancelText="关闭" cancelText="关闭"
> :getContainer="getContainer"
<div class="card-container"> >
<a-tabs type="card"> <div class="card-container">
<a-tab-pane key="1" type="card"> <a-tabs type="card">
<span slot="tab"> <a-tab-pane key="1" type="card">
<a-icon type="schedule" /> <span slot="tab"> <a-icon type="schedule" /></span>
</span> <a-radio-group v-model="result.second.cronEvery">
<a-radio-group v-model="result.second.cronEvery"> <a-row>
<a-row> <a-radio value="1">每一秒钟</a-radio>
<a-radio value="1">每一秒钟</a-radio> </a-row>
</a-row> <a-row>
<a-row> <a-radio value="2">
<a-radio value="2"> 每隔
每隔 <a-input-number
<a-input-number size="small"
size="small" v-model="result.second.incrementIncrement"
v-model="result.second.incrementIncrement" :min="1"
:min="1" :max="60"
:max="60" ></a-input-number
></a-input-number>秒执行 从 >秒执行 从
<a-input-number <a-input-number
size="small" size="small"
v-model="result.second.incrementStart" v-model="result.second.incrementStart"
:min="0" :min="0"
:max="59" :max="59"
></a-input-number>秒开始 ></a-input-number
</a-radio> >秒开始
</a-row> </a-radio>
<a-row> </a-row>
<a-radio value="3">具体秒数(可多选)</a-radio> <a-row>
<a-select <a-radio value="3">具体秒数(可多选)</a-radio>
style="width:354px;" <a-select
size="small" style="width:354px;"
mode="multiple" size="small"
v-model="result.second.specificSpecific" mode="multiple"
> v-model="result.second.specificSpecific"
<a-select-option v-for="(val,index) in 60" :key="index" :value="index">{{ index }}</a-select-option> >
</a-select> <a-select-option v-for="(val, index) in 60" :key="index" :value="index">{{
</a-row> index
<a-row> }}</a-select-option>
<a-radio value="4"> </a-select>
周期从 </a-row>
<a-input-number size="small" v-model="result.second.rangeStart" :min="1" :max="60"></a-input-number> <a-row>
<a-input-number size="small" v-model="result.second.rangeEnd" :min="0" :max="59"></a-input-number> <a-radio value="4">
</a-radio> 周期从
</a-row> <a-input-number
</a-radio-group> size="small"
</a-tab-pane> v-model="result.second.rangeStart"
<a-tab-pane key="2"> :min="1"
<span slot="tab"> :max="60"
<a-icon type="schedule" /> ></a-input-number
</span> >
<div class="tabBody"> <a-input-number
<a-radio-group v-model="result.minute.cronEvery"> size="small"
<a-row> v-model="result.second.rangeEnd"
<a-radio value="1">每一分钟</a-radio> :min="0"
</a-row> :max="59"
<a-row> ></a-input-number
<a-radio value="2"> >
每隔 </a-radio>
<a-input-number </a-row>
size="small" </a-radio-group>
v-model="result.minute.incrementIncrement" </a-tab-pane>
:min="1" <a-tab-pane key="2">
:max="60" <span slot="tab"> <a-icon type="schedule" /></span>
></a-input-number>分执行 从 <div class="tabBody">
<a-input-number <a-radio-group v-model="result.minute.cronEvery">
size="small" <a-row>
v-model="result.minute.incrementStart" <a-radio value="1">每一分钟</a-radio>
:min="0" </a-row>
:max="59" <a-row>
></a-input-number>分开始 <a-radio value="2">
</a-radio> 每隔
</a-row> <a-input-number
<a-row> size="small"
<a-radio value="3">具体分钟数(可多选)</a-radio> v-model="result.minute.incrementIncrement"
<a-select :min="1"
style="width:340px;" :max="60"
size="small" ></a-input-number
mode="multiple" >分执行 从
v-model="result.minute.specificSpecific" <a-input-number
> size="small"
<a-select-option v-model="result.minute.incrementStart"
v-for="(val,index) in Array(60)" :min="0"
:key="index" :max="59"
:value="index" ></a-input-number
>{{ index }}</a-select-option> >分开始
</a-select> </a-radio>
</a-row> </a-row>
<a-row> <a-row>
<a-radio value="4"> <a-radio value="3">具体分钟数(可多选)</a-radio>
周期从 <a-select
<a-input-number style="width:340px;"
size="small" size="small"
v-model="result.minute.rangeStart" mode="multiple"
:min="1" v-model="result.minute.specificSpecific"
:max="60" >
></a-input-number> <a-select-option
<a-input-number size="small" v-model="result.minute.rangeEnd" :min="0" :max="59"></a-input-number> v-for="(val, index) in Array(60)"
</a-radio> :key="index"
</a-row> :value="index"
</a-radio-group> >{{ index }}</a-select-option
</div> >
</a-tab-pane> </a-select>
<a-tab-pane key="3"> </a-row>
<span slot="tab"> <a-row>
<a-icon type="schedule" /> <a-radio value="4">
</span> 周期从
<div class="tabBody"> <a-input-number
<a-radio-group v-model="result.hour.cronEvery"> size="small"
<a-row> v-model="result.minute.rangeStart"
<a-radio value="1">每一小时</a-radio> :min="1"
</a-row> :max="60"
<a-row> ></a-input-number
<a-radio value="2"> >
每隔 <a-input-number
<a-input-number size="small"
size="small" v-model="result.minute.rangeEnd"
v-model="result.hour.incrementIncrement" :min="0"
:min="0" :max="59"
:max="23" ></a-input-number
></a-input-number>小时执行 从 >
<a-input-number </a-radio>
size="small" </a-row>
v-model="result.hour.incrementStart" </a-radio-group>
:min="0" </div>
:max="23" </a-tab-pane>
></a-input-number>小时开始 <a-tab-pane key="3">
</a-radio> <span slot="tab"> <a-icon type="schedule" /></span>
</a-row> <div class="tabBody">
<a-row> <a-radio-group v-model="result.hour.cronEvery">
<a-radio class="long" value="3">具体小时数(可多选)</a-radio> <a-row>
<a-select <a-radio value="1">每一小时</a-radio>
style="width:340px;" </a-row>
size="small" <a-row>
mode="multiple" <a-radio value="2">
v-model="result.hour.specificSpecific" 每隔
> <a-input-number
<a-select-option v-for="(val,index) in Array(24)" :key="index">{{ index }}</a-select-option> size="small"
</a-select> v-model="result.hour.incrementIncrement"
</a-row> :min="0"
<a-row> :max="23"
<a-radio value="4"> ></a-input-number
周期从 >小时执行 从
<a-input-number size="small" v-model="result.hour.rangeStart" :min="0" :max="23"></a-input-number> <a-input-number
<a-input-number size="small" v-model="result.hour.rangeEnd" :min="0" :max="23"></a-input-number>小时 size="small"
</a-radio> v-model="result.hour.incrementStart"
</a-row> :min="0"
</a-radio-group> :max="23"
</div> ></a-input-number
</a-tab-pane> >小时开始
<a-tab-pane key="4"> </a-radio>
<span slot="tab"> </a-row>
<a-icon type="schedule" /> <a-row>
</span> <a-radio class="long" value="3">具体小时数(可多选)</a-radio>
<div class="tabBody"> <a-select
<a-radio-group v-model="result.day.cronEvery"> style="width:340px;"
<a-row> size="small"
<a-radio value="1">每一天</a-radio> mode="multiple"
</a-row> v-model="result.hour.specificSpecific"
<a-row> >
<a-radio value="2"> <a-select-option v-for="(val, index) in Array(24)" :key="index">{{
每隔 index
<a-input-number }}</a-select-option>
size="small" </a-select>
v-model="result.week.incrementIncrement" </a-row>
:min="1" <a-row>
:max="7" <a-radio value="4">
></a-input-number>周执行 从 周期从
<a-select size="small" v-model="result.week.incrementStart"> <a-input-number
<a-select-option size="small"
v-for="(val,index) in Array(7)" v-model="result.hour.rangeStart"
:key="index" :min="0"
:value="index-1" :max="23"
>{{ weekDays[index-1] }}</a-select-option> ></a-input-number
</a-select>开始 >
</a-radio> <a-input-number
</a-row> size="small"
<a-row> v-model="result.hour.rangeEnd"
<a-radio value="3"> :min="0"
每隔 :max="23"
<a-input-number ></a-input-number
size="small" >小时
v-model="result.day.incrementIncrement" </a-radio>
:min="1" </a-row>
:max="31" </a-radio-group>
></a-input-number>天执行 从 </div>
<a-input-number </a-tab-pane>
size="small" <a-tab-pane key="4">
v-model="result.day.incrementStart" <span slot="tab"> <a-icon type="schedule" /></span>
:min="1" <div class="tabBody">
:max="31" <a-radio-group v-model="result.day.cronEvery">
></a-input-number>日开始 <a-row>
</a-radio> <a-radio value="1">每一天</a-radio>
</a-row> </a-row>
<a-row> <a-row>
<a-radio class="long" value="4">具体星期几(可多选)</a-radio> <a-radio value="2">
<a-select 每隔
style="width:340px;" <a-input-number
size="small" size="small"
mode="multiple" v-model="result.week.incrementIncrement"
v-model="result.week.specificSpecific" :min="1"
> :max="7"
<a-select-option ></a-input-number
v-for="(val,index) in Array(7)" >周执行 从
:key="index" <a-select size="small" v-model="result.week.incrementStart">
:value="index-1" <a-select-option
>{{ weekDays[index-1] }}</a-select-option> v-for="(val, index) in Array(7)"
</a-select> :key="index"
</a-row> :value="index - 1"
<a-row> >{{ weekDays[index - 1] }}</a-select-option
<a-radio class="long" value="5">具体天数(可多选)</a-radio> > </a-select
<a-select >开始
style="width:354px;" </a-radio>
size="small" </a-row>
mode="multiple" <a-row>
v-model="result.day.specificSpecific" <a-radio value="3">
> 每隔
<a-select-option <a-input-number
v-for="(val,index) in Array(31)" size="small"
:key="index" v-model="result.day.incrementIncrement"
:value="index+1" :min="1"
>{{ index+1 }}</a-select-option> :max="31"
</a-select> ></a-input-number
</a-row> >天执行 从
<a-row> <a-input-number
<a-radio value="6">在这个月的最后一天</a-radio> size="small"
</a-row> v-model="result.day.incrementStart"
<a-row> :min="1"
<a-radio value="7">在这个月的最后一个工作日</a-radio> :max="31"
</a-row> ></a-input-number
<a-row> >日开始
<a-radio value="8"> </a-radio>
在这个月的最后一个 </a-row>
<a-select size="small" v-model="result.day.cronLastSpecificDomDay"> <a-row>
<a-select-option <a-radio class="long" value="4">具体星期几(可多选)</a-radio>
v-for="(val,index) in Array(7)" <a-select
:key="index" style="width:340px;"
:value="index+1" size="small"
>{{ weekDays[index] }}</a-select-option> mode="multiple"
</a-select> v-model="result.week.specificSpecific"
</a-radio> >
</a-row> <a-select-option
<a-row> v-for="(val, index) in Array(7)"
<a-radio value="9"> :key="index"
在本月底前 :value="index - 1"
<a-input-number >{{ weekDays[index - 1] }}</a-select-option
size="small" >
v-model="result.day.cronDaysBeforeEomMinus" </a-select>
:min="1" </a-row>
:max="31" <a-row>
></a-input-number> <a-radio class="long" value="5">具体天数(可多选)</a-radio>
</a-radio> <a-select
</a-row> style="width:354px;"
<a-row> size="small"
<a-radio value="10"> mode="multiple"
最近的工作日(周一至周五)至本月 v-model="result.day.specificSpecific"
<a-input-number >
size="small" <a-select-option
v-model="result.day.cronDaysNearestWeekday" v-for="(val, index) in Array(31)"
:min="1" :key="index"
:max="31" :value="index + 1"
></a-input-number> >{{ index + 1 }}</a-select-option
</a-radio> >
</a-row> </a-select>
<a-row> </a-row>
<a-radio value="11"> <a-row>
在这个月的第 <a-radio value="6">在这个月的最后一天</a-radio>
<a-input-number </a-row>
size="small" <a-row>
v-model="result.week.cronNthDayNth" <a-radio value="7">在这个月的最后一个工作日</a-radio>
:min="1" </a-row>
:max="5" <a-row>
></a-input-number> <a-radio value="8">
<a-select size="small" v-model="result.week.cronNthDayDay"> 在这个月的最后一个
<a-select-option <a-select size="small" v-model="result.day.cronLastSpecificDomDay">
v-for="(val,index) in Array(7)" <a-select-option
:key="index" v-for="(val, index) in Array(7)"
:value="index" :key="index"
>{{ weekDays[index] }}</a-select-option> :value="index + 1"
</a-select> >{{ weekDays[index] }}</a-select-option
</a-radio> >
</a-row> </a-select>
</a-radio-group> </a-radio>
</div> </a-row>
</a-tab-pane> <a-row>
<a-tab-pane key="5"> <a-radio value="9">
<span slot="tab"> 在本月底前
<a-icon type="schedule" /> <a-input-number
</span> size="small"
<div class="tabBody"> v-model="result.day.cronDaysBeforeEomMinus"
<a-radio-group v-model="result.month.cronEvery"> :min="1"
<a-row> :max="31"
<a-radio value="1">每一月</a-radio> ></a-input-number
</a-row> >
<a-row> </a-radio>
<a-radio value="2"> </a-row>
每隔 <a-row>
<a-input-number <a-radio value="10">
size="small" 最近的工作日(周一至周五)至本月
v-model="result.month.incrementIncrement" <a-input-number
:min="0" size="small"
:max="12" v-model="result.day.cronDaysNearestWeekday"
></a-input-number>月执行 从 :min="1"
<a-input-number :max="31"
size="small" ></a-input-number
v-model="result.month.incrementStart" >
:min="0" </a-radio>
:max="12" </a-row>
></a-input-number>月开始 <a-row>
</a-radio> <a-radio value="11">
</a-row> 在这个月的第
<a-row> <a-input-number
<a-radio class="long" value="3">具体月数(可多选)</a-radio> size="small"
<a-select v-model="result.week.cronNthDayNth"
style="width:354px;" :min="1"
size="small" :max="5"
filterable ></a-input-number
mode="multiple" >
v-model="result.month.specificSpecific" <a-select size="small" v-model="result.week.cronNthDayDay">
> <a-select-option
<a-select-option v-for="(val, index) in Array(7)"
v-for="(val,index) in Array(12)" :key="index"
:key="index" :value="index"
:value="index+1" >{{ weekDays[index] }}</a-select-option
>{{ index+1 }}</a-select-option> >
</a-select> </a-select>
</a-row> </a-radio>
<a-row> </a-row>
<a-radio value="4"> </a-radio-group>
</div>
<a-input-number size="small" v-model="result.month.rangeStart" :min="1" :max="12"></a-input-number> </a-tab-pane>
<a-input-number size="small" v-model="result.month.rangeEnd" :min="1" :max="12"></a-input-number>月之间的每个月 <a-tab-pane key="5">
</a-radio> <span slot="tab"> <a-icon type="schedule" /></span>
</a-row> <div class="tabBody">
</a-radio-group> <a-radio-group v-model="result.month.cronEvery">
</div> <a-row>
</a-tab-pane> <a-radio value="1">每一月</a-radio>
<a-tab-pane key="6"> </a-row>
<span slot="tab"> <a-row>
<a-icon type="schedule" /> <a-radio value="2">
</span> 每隔
<div class="tabBody"> <a-input-number
<a-radio-group v-model="result.year.cronEvery"> size="small"
<a-row> v-model="result.month.incrementIncrement"
<a-radio value="1">每一年</a-radio> :min="0"
</a-row> :max="12"
<a-row> ></a-input-number
<a-radio value="2"> >月执行 从
每隔 <a-input-number
<a-input-number size="small"
size="small" v-model="result.month.incrementStart"
v-model="result.year.incrementIncrement" :min="0"
:min="1" :max="12"
:max="99" ></a-input-number
></a-input-number>年执行 从 >月开始
<a-input-number </a-radio>
size="small" </a-row>
v-model="result.year.incrementStart" <a-row>
:min="curYear" <a-radio class="long" value="3">具体月数(可多选)</a-radio>
:max="curYear+100" <a-select
></a-input-number>年开始 style="width:354px;"
</a-radio> size="small"
</a-row> filterable
<a-row> mode="multiple"
<a-radio class="long" value="3">具体年份(可多选)</a-radio> v-model="result.month.specificSpecific"
<a-select >
style="width:354px;" <a-select-option
size="small" v-for="(val, index) in Array(12)"
filterable :key="index"
mode="multiple" :value="index + 1"
v-model="result.year.specificSpecific" >{{ index + 1 }}</a-select-option
> >
<a-select-option </a-select>
v-for="(val,index) in Array(100)" </a-row>
:key="index" <a-row>
:value="curYear+index-1" <a-radio value="4">
>{{ curYear+index-1 }}</a-select-option>
</a-select> <a-input-number
</a-row> size="small"
<a-row> v-model="result.month.rangeStart"
<a-radio value="4"> :min="1"
:max="12"
<a-input-number ></a-input-number
size="small" >
v-model="result.year.rangeStart" <a-input-number
:min="curYear" size="small"
:max="curYear+100" v-model="result.month.rangeEnd"
></a-input-number> :min="1"
<a-input-number :max="12"
size="small" ></a-input-number
v-model="result.year.rangeEnd" >月之间的每个月
:min="curYear" </a-radio>
:max="curYear+100" </a-row>
></a-input-number>年之间的每一年 </a-radio-group>
</a-radio> </div>
</a-row> </a-tab-pane>
</a-radio-group> <a-tab-pane key="6">
</div> <span slot="tab"> <a-icon type="schedule" /></span>
</a-tab-pane> <div class="tabBody">
</a-tabs> <a-radio-group v-model="result.year.cronEvery">
<div class="bottom"> <a-row>
<span class="value">{{this.cron }}</span> <a-radio value="1">每一年</a-radio>
</div> </a-row>
</div> <a-row>
</a-modal> <a-radio value="2">
每隔
<a-input-number
size="small"
v-model="result.year.incrementIncrement"
:min="1"
:max="99"
></a-input-number
>年执行 从
<a-input-number
size="small"
v-model="result.year.incrementStart"
:min="curYear"
:max="curYear + 100"
></a-input-number
>年开始
</a-radio>
</a-row>
<a-row>
<a-radio class="long" value="3">具体年份(可多选)</a-radio>
<a-select
style="width:354px;"
size="small"
filterable
mode="multiple"
v-model="result.year.specificSpecific"
>
<a-select-option
v-for="(val, index) in Array(100)"
:key="index"
:value="curYear + index - 1"
>{{ curYear + index - 1 }}</a-select-option
>
</a-select>
</a-row>
<a-row>
<a-radio value="4">
<a-input-number
size="small"
v-model="result.year.rangeStart"
:min="curYear"
:max="curYear + 100"
></a-input-number
>
<a-input-number
size="small"
v-model="result.year.rangeEnd"
:min="curYear"
:max="curYear + 100"
></a-input-number
>年之间的每一年
</a-radio>
</a-row>
</a-radio-group>
</div>
</a-tab-pane>
</a-tabs>
<div class="bottom">
<span class="value">{{ this.cron }}</span>
</div>
</div>
</a-modal>
</template> </template>
<script> <script>
const now = new Date(); const now = new Date();
const curYear = now.getFullYear(); const curYear = now.getFullYear();
export default { export default {
name: "AntCron", name: 'AntCron',
props: ["data"], props: ['data'],
data() { data() {
return { return {
curYear, curYear,
visible: false, visible: false,
confirmLoading: false, confirmLoading: false,
size: "large", size: 'large',
weekDays: ["", "", "", "", "", "", ""].map( weekDays: ['', '', '', '', '', '', ''].map(val => '星期' + val),
val => "星期" + val result: {
), second: {},
result: { minute: {},
second: {}, hour: {},
minute: {}, day: {},
hour: {}, week: {},
day: {}, month: {},
week: {}, year: {},
month: {}, },
year: {} defaultValue: {
}, second: {
defaultValue: { cronEvery: '',
second: { incrementStart: 3,
cronEvery: "", incrementIncrement: 5,
incrementStart: 3, rangeStart: 1,
incrementIncrement: 5, rangeEnd: 0,
rangeStart: 1, specificSpecific: [],
rangeEnd: 0, },
specificSpecific: [] minute: {
cronEvery: '',
incrementStart: 3,
incrementIncrement: 5,
rangeStart: 1,
rangeEnd: '0',
specificSpecific: [],
},
hour: {
cronEvery: '',
incrementStart: 3,
incrementIncrement: 5,
rangeStart: '0',
rangeEnd: '0',
specificSpecific: [],
},
day: {
cronEvery: '',
incrementStart: 1,
incrementIncrement: '1',
rangeStart: '',
rangeEnd: '',
specificSpecific: [],
cronLastSpecificDomDay: 1,
cronDaysBeforeEomMinus: 1,
cronDaysNearestWeekday: 1,
},
week: {
cronEvery: '',
incrementStart: 1,
incrementIncrement: 1,
specificSpecific: [],
cronNthDayDay: 1,
cronNthDayNth: 1,
},
month: {
cronEvery: '',
incrementStart: 3,
incrementIncrement: 5,
rangeStart: 1,
rangeEnd: 1,
specificSpecific: [],
},
year: {
cronEvery: '',
incrementStart: curYear,
incrementIncrement: 1,
rangeStart: curYear,
rangeEnd: curYear,
specificSpecific: [],
},
label: '',
},
};
},
computed: {
modalWidth() {
return 608;
}, },
minute: { secondsText() {
cronEvery: "", let seconds = '';
incrementStart: 3, let cronEvery = this.result.second.cronEvery || '';
incrementIncrement: 5, switch (cronEvery.toString()) {
rangeStart: 1, case '1':
rangeEnd: "0", seconds = '*';
specificSpecific: [] break;
case '2':
seconds = this.result.second.incrementStart + '/' + this.result.second.incrementIncrement;
break;
case '3':
this.result.second.specificSpecific.map(val => {
seconds += val + ',';
});
seconds = seconds.slice(0, -1);
break;
case '4':
seconds = this.result.second.rangeStart + '-' + this.result.second.rangeEnd;
break;
}
return seconds;
}, },
hour: { minutesText() {
cronEvery: "", let minutes = '';
incrementStart: 3, let cronEvery = this.result.minute.cronEvery || '';
incrementIncrement: 5, switch (cronEvery.toString()) {
rangeStart: "0", case '1':
rangeEnd: "0", minutes = '*';
specificSpecific: [] break;
case '2':
minutes = this.result.minute.incrementStart + '/' + this.result.minute.incrementIncrement;
break;
case '3':
this.result.minute.specificSpecific.map(val => {
minutes += val + ',';
});
minutes = minutes.slice(0, -1);
break;
case '4':
minutes = this.result.minute.rangeStart + '-' + this.result.minute.rangeEnd;
break;
}
return minutes;
}, },
day: { hoursText() {
cronEvery: "", let hours = '';
incrementStart: 1, let cronEvery = this.result.hour.cronEvery || '';
incrementIncrement: "1", switch (cronEvery.toString()) {
rangeStart: "", case '1':
rangeEnd: "", hours = '*';
specificSpecific: [], break;
cronLastSpecificDomDay: 1, case '2':
cronDaysBeforeEomMinus: 1, hours = this.result.hour.incrementStart + '/' + this.result.hour.incrementIncrement;
cronDaysNearestWeekday: 1 break;
case '3':
this.result.hour.specificSpecific.map(val => {
hours += val + ',';
});
hours = hours.slice(0, -1);
break;
case '4':
hours = this.result.hour.rangeStart + '-' + this.result.hour.rangeEnd;
break;
}
return hours;
}, },
week: { daysText() {
cronEvery: "", let days = '';
incrementStart: 1, let cronEvery = this.result.day.cronEvery || '';
incrementIncrement: 1, switch (cronEvery.toString()) {
specificSpecific: [], case '1':
cronNthDayDay: 1, break;
cronNthDayNth: 1 case '2':
case '4':
case '11':
days = '?';
break;
case '3':
days = this.result.day.incrementStart + '/' + this.result.day.incrementIncrement;
break;
case '5':
this.result.day.specificSpecific.map(val => {
days += val + ',';
});
days = days.slice(0, -1);
break;
case '6':
days = 'L';
break;
case '7':
days = 'LW';
break;
case '8':
days = this.result.day.cronLastSpecificDomDay + 'L';
break;
case '9':
days = 'L-' + this.result.day.cronDaysBeforeEomMinus;
break;
case '10':
days = this.result.day.cronDaysNearestWeekday + 'W';
break;
}
return days;
}, },
month: { weeksText() {
cronEvery: "", let weeks = '';
incrementStart: 3, let cronEvery = this.result.day.cronEvery || '';
incrementIncrement: 5, switch (cronEvery.toString()) {
rangeStart: 1, case '1':
rangeEnd: 1, case '3':
specificSpecific: [] case '5':
weeks = '?';
break;
case '2':
weeks = this.result.week.incrementStart + '/' + this.result.week.incrementIncrement;
break;
case '4':
this.result.week.specificSpecific.map(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.result.week.cronNthDayDay + '#' + this.result.week.cronNthDayNth;
break;
}
return weeks;
}, },
year: { monthsText() {
cronEvery: "", let months = '';
incrementStart: curYear, let cronEvery = this.result.month.cronEvery || '';
incrementIncrement: 1, switch (cronEvery.toString()) {
rangeStart: curYear, case '1':
rangeEnd: curYear, months = '*';
specificSpecific: [] break;
case '2':
months = this.result.month.incrementStart + '/' + this.result.month.incrementIncrement;
break;
case '3':
this.result.month.specificSpecific.map(val => {
months += val + ',';
});
months = months.slice(0, -1);
break;
case '4':
months = this.result.month.rangeStart + '-' + this.result.month.rangeEnd;
break;
}
return months;
},
yearsText() {
let years = '';
let cronEvery = this.result.year.cronEvery || '';
switch (cronEvery.toString()) {
case '1':
years = '*';
break;
case '2':
years = this.result.year.incrementStart + '/' + this.result.year.incrementIncrement;
break;
case '3':
this.result.year.specificSpecific.map(val => {
years += val + ',';
});
years = years.slice(0, -1);
break;
case '4':
years = this.result.year.rangeStart + '-' + this.result.year.rangeEnd;
break;
}
return years;
},
cron() {
return `${this.secondsText || '*'} ${this.minutesText || '*'} ${this.hoursText || '*'} ${this
.daysText || '*'} ${this.monthsText || '*'} ${this.weeksText || '?'} ${this.yearsText ||
'*'}`;
}, },
label: ""
}
};
},
computed: {
modalWidth() {
return 608;
},
secondsText() {
let seconds = "";
let cronEvery = this.result.second.cronEvery || "";
switch (cronEvery.toString()) {
case "1":
seconds = "*";
break;
case "2":
seconds =
this.result.second.incrementStart +
"/" +
this.result.second.incrementIncrement;
break;
case "3":
this.result.second.specificSpecific.map(val => {
seconds += val + ",";
});
seconds = seconds.slice(0, -1);
break;
case "4":
seconds =
this.result.second.rangeStart + "-" + this.result.second.rangeEnd;
break;
}
return seconds;
},
minutesText() {
let minutes = "";
let cronEvery = this.result.minute.cronEvery || "";
switch (cronEvery.toString()) {
case "1":
minutes = "*";
break;
case "2":
minutes =
this.result.minute.incrementStart +
"/" +
this.result.minute.incrementIncrement;
break;
case "3":
this.result.minute.specificSpecific.map(val => {
minutes += val + ",";
});
minutes = minutes.slice(0, -1);
break;
case "4":
minutes =
this.result.minute.rangeStart + "-" + this.result.minute.rangeEnd;
break;
}
return minutes;
},
hoursText() {
let hours = "";
let cronEvery = this.result.hour.cronEvery || "";
switch (cronEvery.toString()) {
case "1":
hours = "*";
break;
case "2":
hours =
this.result.hour.incrementStart +
"/" +
this.result.hour.incrementIncrement;
break;
case "3":
this.result.hour.specificSpecific.map(val => {
hours += val + ",";
});
hours = hours.slice(0, -1);
break;
case "4":
hours = this.result.hour.rangeStart + "-" + this.result.hour.rangeEnd;
break;
}
return hours;
},
daysText() {
let days = "";
let cronEvery = this.result.day.cronEvery || "";
switch (cronEvery.toString()) {
case "1":
break;
case "2":
case "4":
case "11":
days = "?";
break;
case "3":
days =
this.result.day.incrementStart +
"/" +
this.result.day.incrementIncrement;
break;
case "5":
this.result.day.specificSpecific.map(val => {
days += val + ",";
});
days = days.slice(0, -1);
break;
case "6":
days = "L";
break;
case "7":
days = "LW";
break;
case "8":
days = this.result.day.cronLastSpecificDomDay + "L";
break;
case "9":
days = "L-" + this.result.day.cronDaysBeforeEomMinus;
break;
case "10":
days = this.result.day.cronDaysNearestWeekday + "W";
break;
}
return days;
},
weeksText() {
let weeks = "";
let cronEvery = this.result.day.cronEvery || "";
switch (cronEvery.toString()) {
case "1":
case "3":
case "5":
weeks = "?";
break;
case "2":
weeks =
this.result.week.incrementStart +
"/" +
this.result.week.incrementIncrement;
break;
case "4":
this.result.week.specificSpecific.map(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.result.week.cronNthDayDay +
"#" +
this.result.week.cronNthDayNth;
break;
}
return weeks;
},
monthsText() {
let months = "";
let cronEvery = this.result.month.cronEvery || "";
switch (cronEvery.toString()) {
case "1":
months = "*";
break;
case "2":
months =
this.result.month.incrementStart +
"/" +
this.result.month.incrementIncrement;
break;
case "3":
this.result.month.specificSpecific.map(val => {
months += val + ",";
});
months = months.slice(0, -1);
break;
case "4":
months =
this.result.month.rangeStart + "-" + this.result.month.rangeEnd;
break;
}
return months;
},
yearsText() {
let years = "";
let cronEvery = this.result.year.cronEvery || "";
switch (cronEvery.toString()) {
case "1":
years = "*";
break;
case "2":
years =
this.result.year.incrementStart +
"/" +
this.result.year.incrementIncrement;
break;
case "3":
this.result.year.specificSpecific.map(val => {
years += val + ",";
});
years = years.slice(0, -1);
break;
case "4":
years = this.result.year.rangeStart + "-" + this.result.year.rangeEnd;
break;
}
return years;
},
cron() {
return `${this.secondsText || "*"} ${this.minutesText || "*"} ${this
.hoursText || "*"} ${this.daysText || "*"} ${this.monthsText ||
"*"} ${this.weeksText || "?"} ${this.yearsText || "*"}`;
}
},
watch: {
visible: {
handler() {
let label = this.data;
if (label) {
label = label.trim();
const len = label.split(" ").length;
switch (true) {
case len > 0:
this.secondsReverseExp(label);
case len > 1:
this.minutesReverseExp(label);
case len > 2:
this.hoursReverseExp(label);
case len > 3:
this.daysReverseExp(label);
case len > 4:
this.daysReverseExp(label);
case len > 5:
this.monthsReverseExp(label);
case len > 6:
this.yearReverseExp(label);
}
} else {
this.result = JSON.parse(JSON.stringify(this.defaultValue));
}
}
}
},
methods: {
show() {
this.visible = true;
},
handleSubmit() {
this.$emit("ok", this.cron);
this.close();
this.visible = false;
},
close() {
this.visible = false;
},
secondsReverseExp(seconds) {
let val = seconds.split(" ")[0];
let second = {
cronEvery: "",
incrementStart: 3,
incrementIncrement: 5,
rangeStart: 1,
rangeEnd: 0,
specificSpecific: []
};
switch (true) {
case val.includes("*"):
second.cronEvery = "1";
break;
case val.includes("/"):
second.cronEvery = "2";
second.incrementStart = val.split("/")[0];
second.incrementIncrement = val.split("/")[1];
break;
case val.includes(","):
second.cronEvery = "3";
second.specificSpecific = val
.split(",")
.map(Number)
.sort();
break;
case val.includes("-"):
second.cronEvery = "4";
second.rangeStart = val.split("-")[0];
second.rangeEnd = val.split("-")[1];
break;
default:
second.cronEvery = "3";
second.specificSpecific = [val];
}
this.result.second = second;
},
minutesReverseExp(minutes) {
let val = minutes.split(" ")[1];
let minute = {
cronEvery: "",
incrementStart: 3,
incrementIncrement: 5,
rangeStart: 1,
rangeEnd: 0,
specificSpecific: []
};
switch (true) {
case val.includes("*"):
minute.cronEvery = "1";
break;
case val.includes("/"):
minute.cronEvery = "2";
minute.incrementStart = val.split("/")[0];
minute.incrementIncrement = val.split("/")[1];
break;
case val.includes(","):
minute.cronEvery = "3";
minute.specificSpecific = val
.split(",")
.map(Number)
.sort();
break;
case val.includes("-"):
minute.cronEvery = "4";
minute.rangeStart = val.split("-")[0];
minute.rangeEnd = val.split("-")[1];
break;
default:
minute.cronEvery = "3";
minute.specificSpecific = [val];
}
this.result.minute = minute;
}, },
hoursReverseExp(hours) { watch: {
let val = hours.split(" ")[2]; visible: {
let hour = { handler() {
cronEvery: "", let label = this.data;
incrementStart: 3, if (label) {
incrementIncrement: 5, label = label.trim();
rangeStart: 1, const len = label.split(' ').length;
rangeEnd: "0", switch (true) {
specificSpecific: [] case len > 0:
}; this.secondsReverseExp(label);
switch (true) { break;
case val.includes("*"): case len > 1:
hour.cronEvery = "1"; this.minutesReverseExp(label);
break; break;
case val.includes("/"): case len > 2:
hour.cronEvery = "2"; this.hoursReverseExp(label);
hour.incrementStart = val.split("/")[0]; break;
hour.incrementIncrement = val.split("/")[1];
break; case len > 3:
case val.includes(","): this.daysReverseExp(label);
hour.cronEvery = "3"; break;
hour.specificSpecific = val
.split(",") case len > 4:
.map(Number) this.daysReverseExp(label);
.sort(); break;
break;
case val.includes("-"): case len > 5:
hour.cronEvery = "4"; this.monthsReverseExp(label);
hour.rangeStart = val.split("-")[0]; break;
hour.rangeEnd = val.split("-")[1];
break; case len > 6:
default: this.yearReverseExp(label);
hour.cronEvery = "3"; }
hour.specificSpecific = [val]; } else {
} this.result = JSON.parse(JSON.stringify(this.defaultValue));
this.result.hour = hour; }
},
},
}, },
daysReverseExp(cron) { methods: {
let days = cron.split(" ")[3]; getContainer(e) {
let weeks = cron.split(" ")[5]; return window.document.body;
let day = { },
cronEvery: "", show() {
incrementStart: 1, this.visible = true;
incrementIncrement: 1, },
rangeStart: 1, handleSubmit() {
rangeEnd: 1, this.$emit('ok', this.cron);
specificSpecific: [], this.close();
cronLastSpecificDomDay: 1, this.visible = false;
cronDaysBeforeEomMinus: 1, },
cronDaysNearestWeekday: 1 close() {
}; this.visible = false;
let week = { },
cronEvery: "", secondsReverseExp(seconds) {
incrementStart: 1, let val = seconds.split(' ')[0];
incrementIncrement: 1, let second = {
specificSpecific: [], cronEvery: '',
cronNthDayDay: 1, incrementStart: 3,
cronNthDayNth: 1 incrementIncrement: 5,
}; rangeStart: 1,
if (!days.includes("?")) { rangeEnd: 0,
switch (true) { specificSpecific: [],
case days.includes("*"): };
day.cronEvery = "1"; switch (true) {
break; case val.includes('*'):
case days.includes("?"): second.cronEvery = '1';
break; break;
case days.includes("/"): case val.includes('/'):
day.cronEvery = "3"; second.cronEvery = '2';
day.incrementStart = days.split("/")[0]; second.incrementStart = val.split('/')[0];
day.incrementIncrement = days.split("/")[1]; second.incrementIncrement = val.split('/')[1];
break; break;
case days.includes(","): case val.includes(','):
day.cronEvery = "5"; second.cronEvery = '3';
day.specificSpecific = days second.specificSpecific = val
.split(",") .split(',')
.map(Number) .map(Number)
.sort(); .sort();
break; break;
case days.includes("LW"): case val.includes('-'):
day.cronEvery = "7"; second.cronEvery = '4';
break; second.rangeStart = val.split('-')[0];
case days.includes("L-"): second.rangeEnd = val.split('-')[1];
day.cronEvery = "9"; break;
day.cronDaysBeforeEomMinus = days.split("L-")[1]; default:
break; second.cronEvery = '3';
case days.includes("L"): second.specificSpecific = [val];
if (days.len == 1) { }
day.cronEvery = "6"; this.result.second = second;
day.cronLastSpecificDomDay = "1"; },
minutesReverseExp(minutes) {
let val = minutes.split(' ')[1];
let minute = {
cronEvery: '',
incrementStart: 3,
incrementIncrement: 5,
rangeStart: 1,
rangeEnd: 0,
specificSpecific: [],
};
switch (true) {
case val.includes('*'):
minute.cronEvery = '1';
break;
case val.includes('/'):
minute.cronEvery = '2';
minute.incrementStart = val.split('/')[0];
minute.incrementIncrement = val.split('/')[1];
break;
case val.includes(','):
minute.cronEvery = '3';
minute.specificSpecific = val
.split(',')
.map(Number)
.sort();
break;
case val.includes('-'):
minute.cronEvery = '4';
minute.rangeStart = val.split('-')[0];
minute.rangeEnd = val.split('-')[1];
break;
default:
minute.cronEvery = '3';
minute.specificSpecific = [val];
}
this.result.minute = minute;
},
hoursReverseExp(hours) {
let val = hours.split(' ')[2];
let hour = {
cronEvery: '',
incrementStart: 3,
incrementIncrement: 5,
rangeStart: 1,
rangeEnd: '0',
specificSpecific: [],
};
switch (true) {
case val.includes('*'):
hour.cronEvery = '1';
break;
case val.includes('/'):
hour.cronEvery = '2';
hour.incrementStart = val.split('/')[0];
hour.incrementIncrement = val.split('/')[1];
break;
case val.includes(','):
hour.cronEvery = '3';
hour.specificSpecific = val
.split(',')
.map(Number)
.sort();
break;
case val.includes('-'):
hour.cronEvery = '4';
hour.rangeStart = val.split('-')[0];
hour.rangeEnd = val.split('-')[1];
break;
default:
hour.cronEvery = '3';
hour.specificSpecific = [val];
}
this.result.hour = hour;
},
daysReverseExp(cron) {
let days = cron.split(' ')[3];
let weeks = cron.split(' ')[5];
let day = {
cronEvery: '',
incrementStart: 1,
incrementIncrement: 1,
rangeStart: 1,
rangeEnd: 1,
specificSpecific: [],
cronLastSpecificDomDay: 1,
cronDaysBeforeEomMinus: 1,
cronDaysNearestWeekday: 1,
};
let week = {
cronEvery: '',
incrementStart: 1,
incrementIncrement: 1,
specificSpecific: [],
cronNthDayDay: 1,
cronNthDayNth: 1,
};
if (!days.includes('?')) {
switch (true) {
case days.includes('*'):
day.cronEvery = '1';
break;
case days.includes('?'):
break;
case days.includes('/'):
day.cronEvery = '3';
day.incrementStart = days.split('/')[0];
day.incrementIncrement = days.split('/')[1];
break;
case days.includes(','):
day.cronEvery = '5';
day.specificSpecific = days
.split(',')
.map(Number)
.sort();
break;
case days.includes('LW'):
day.cronEvery = '7';
break;
case days.includes('L-'):
day.cronEvery = '9';
day.cronDaysBeforeEomMinus = days.split('L-')[1];
break;
case days.includes('L'):
if (days.len == 1) {
day.cronEvery = '6';
day.cronLastSpecificDomDay = '1';
} else {
day.cronEvery = '8';
day.cronLastSpecificDomDay = Number(days.split('L')[0]);
}
break;
case days.includes('W'):
day.cronEvery = '10';
day.cronDaysNearestWeekday = days.split('W')[0];
break;
default:
day.cronEvery = '5';
day.specificSpecific = [days];
}
} else { } else {
day.cronEvery = "8"; switch (true) {
day.cronLastSpecificDomDay = Number(days.split("L")[0]); case weeks.includes('/'):
day.cronEvery = '2';
week.incrementStart = parseInt(weeks.split('/')[0]);
week.incrementIncrement = parseInt(weeks.split('/')[1]);
break;
case weeks.includes(','):
day.cronEvery = '4';
week.specificSpecific = weeks
.split(',')
.map(Number)
.sort();
break;
case weeks.includes('#'):
day.cronEvery = '11';
week.cronNthDayDay = parseInt(weeks.split('#')[0]);
week.cronNthDayNth = parseInt(weeks.split('#')[1]);
break;
// case weeks.includes("-"):
// day.cronEvery = "11";
// week.cronNthDayDay = parseInt(weeks.split("#")[0]);
// week.cronNthDayNth = parseInt(weeks.split("#")[1]);
// break;
default:
day.cronEvery = '4';
week.cronEvery = '4';
week.specificSpecific = [parseInt(weeks)];
}
} }
break; this.result.day = day;
case days.includes("W"): this.result.week = week;
day.cronEvery = "10"; },
day.cronDaysNearestWeekday = days.split("W")[0]; monthsReverseExp(cron) {
break; let months = cron.split(' ')[4];
default: let month = {
day.cronEvery = "5"; cronEvery: '',
day.specificSpecific = [days]; incrementStart: 3,
} incrementIncrement: 5,
} else { rangeStart: 1,
switch (true) { rangeEnd: 1,
case weeks.includes("/"): specificSpecific: [],
day.cronEvery = "2"; };
week.incrementStart = parseInt(weeks.split("/")[0]); switch (true) {
week.incrementIncrement = parseInt(weeks.split("/")[1]); case months.includes('*'):
break; month.cronEvery = '1';
case weeks.includes(","): break;
day.cronEvery = "4"; case months.includes('/'):
week.specificSpecific = weeks month.cronEvery = '2';
.split(",") month.incrementStart = months.split('/')[0];
.map(Number) month.incrementIncrement = months.split('/')[1];
.sort(); break;
break; case months.includes(','):
case weeks.includes("#"): month.cronEvery = '3';
day.cronEvery = "11"; month.specificSpecific = months
week.cronNthDayDay = parseInt(weeks.split("#")[0]); .split(',')
week.cronNthDayNth = parseInt(weeks.split("#")[1]); .map(Number)
break; .sort();
// case weeks.includes("-"): break;
// day.cronEvery = "11"; case months.includes('-'):
// week.cronNthDayDay = parseInt(weeks.split("#")[0]); month.cronEvery = '4';
// week.cronNthDayNth = parseInt(weeks.split("#")[1]); month.rangeStart = months.split('-')[0];
// break; month.rangeEnd = months.split('-')[1];
default: break;
day.cronEvery = "4"; default:
week.cronEvery = "4"; month.cronEvery = '3';
week.specificSpecific = [parseInt(weeks)]; month.specificSpecific = [months];
} }
} this.result.month = month;
this.result.day = day; },
this.result.week = week; yearReverseExp(cron) {
}, let years = cron.split(' ')[6];
monthsReverseExp(cron) { let year = {
let months = cron.split(" ")[4]; cronEvery: '',
let month = { incrementStart: curYear,
cronEvery: "", incrementIncrement: 5,
incrementStart: 3, rangeStart: curYear,
incrementIncrement: 5, rangeEnd: curYear,
rangeStart: 1, specificSpecific: [],
rangeEnd: 1, };
specificSpecific: [] if (years !== undefined) {
}; switch (true) {
switch (true) { case years.includes('*'):
case months.includes("*"): year.cronEvery = '1';
month.cronEvery = "1"; break;
break; case years.includes('/'):
case months.includes("/"): year.cronEvery = '2';
month.cronEvery = "2"; year.incrementStart = years.split('/')[0];
month.incrementStart = months.split("/")[0]; year.incrementIncrement = years.split('/')[1];
month.incrementIncrement = months.split("/")[1]; break;
break; case years.includes(','):
case months.includes(","): year.cronEvery = '3';
month.cronEvery = "3"; year.specificSpecific = years
month.specificSpecific = months .split(',')
.split(",") .map(Number)
.map(Number) .sort();
.sort(); break;
break; case years.includes('-'):
case months.includes("-"): year.cronEvery = '4';
month.cronEvery = "4"; year.rangeStart = years.split('-')[0];
month.rangeStart = months.split("-")[0]; year.rangeEnd = years.split('-')[1];
month.rangeEnd = months.split("-")[1]; break;
break; default:
default: year.cronEvery = '3';
month.cronEvery = "3"; year.specificSpecific = [years];
month.specificSpecific = [months]; }
} } else {
this.result.month = month; year.cronEvery = '1';
}
this.result.year = year;
},
}, },
yearReverseExp(cron) {
let years = cron.split(" ")[6];
let year = {
cronEvery: "",
incrementStart: curYear,
incrementIncrement: 5,
rangeStart: curYear,
rangeEnd: curYear,
specificSpecific: []
};
if (years !== undefined) {
switch (true) {
case years.includes("*"):
year.cronEvery = "1";
break;
case years.includes("/"):
year.cronEvery = "2";
year.incrementStart = years.split("/")[0];
year.incrementIncrement = years.split("/")[1];
break;
case years.includes(","):
year.cronEvery = "3";
year.specificSpecific = years
.split(",")
.map(Number)
.sort();
break;
case years.includes("-"):
year.cronEvery = "4";
year.rangeStart = years.split("-")[0];
year.rangeEnd = years.split("-")[1];
break;
default:
year.cronEvery = "3";
year.specificSpecific = [years];
}
} else {
year.cronEvery = "1";
}
this.result.year = year;
}
}
}; };
</script> </script>
<style lang="scss"> <style lang="less">
.card-container { .card-container {
background: #fff; background: #fff;
overflow: hidden; overflow: hidden;
padding: 12px; padding: 12px;
position: relative; position: relative;
width: 100%; width: 100%;
.ant-tabs { .ant-tabs {
border: 1px solid #e6ebf5; border: 1px solid #e6ebf5;
padding: 0; padding: 0;
.ant-tabs-bar { .ant-tabs-bar {
margin: 0; margin: 0;
outline: none; outline: none;
border-bottom: none; border-bottom: none;
.ant-tabs-nav-container { .ant-tabs-nav-container {
margin: 0; margin: 0;
.ant-tabs-tab { .ant-tabs-tab {
padding: 0 24px !important; padding: 0 24px !important;
background-color: #f5f7fa !important; background-color: #f5f7fa !important;
margin-right: 0px !important; margin-right: 0px !important;
border-radius: 0; border-radius: 0;
line-height: 38px; line-height: 38px;
border: 1px solid transparent !important; border: 1px solid transparent !important;
border-bottom: 1px solid #e6ebf5 !important; border-bottom: 1px solid #e6ebf5 !important;
}
.ant-tabs-tab-active.ant-tabs-tab {
color: #409eff;
background-color: #fff !important;
border-right: 1px solid #e6ebf5 !important;
border-left: 1px solid #e6ebf5 !important;
border-bottom: 1px solid #fff !important;
font-weight: normal;
transition: none !important;
}
}
} }
.ant-tabs-tab-active.ant-tabs-tab { .ant-tabs-tabpane {
color: #409eff; padding: 15px;
background-color: #fff !important; .ant-row {
border-right: 1px solid #e6ebf5 !important; margin: 10px 0;
border-left: 1px solid #e6ebf5 !important; }
border-bottom: 1px solid #fff !important; .ant-select,
font-weight: normal; .ant-input-number {
transition: none !important; width: 100px;
}
} }
}
}
.ant-tabs-tabpane {
padding: 15px;
.ant-row {
margin: 10px 0;
}
.ant-select,
.ant-input-number {
width: 100px;
}
} }
}
} }
</style> </style>
<style lang="scss" scoped>
<style lang="less" scoped>
.container-widthEn { .container-widthEn {
width: 755px; width: 755px;
} }
.container-widthCn { .container-widthCn {
width: 608px; width: 608px;
} }
.language { .language {
text-align: center; text-align: center;
position: absolute; position: absolute;
right: 13px; right: 13px;
top: 13px; top: 13px;
border: 1px solid transparent; border: 1px solid transparent;
height: 40px; height: 40px;
line-height: 38px; line-height: 38px;
font-size: 16px; font-size: 16px;
color: #409eff; color: #409eff;
z-index: 1; z-index: 1;
background: #f5f7fa; background: #f5f7fa;
outline: none; outline: none;
width: 47px; width: 47px;
border-bottom: 1px solid #e6ebf5; border-bottom: 1px solid #e6ebf5;
border-radius: 0; border-radius: 0;
} }
.card-container { .card-container {
.bottom { .bottom {
display: flex; display: flex;
justify-content: center; justify-content: center;
padding: 10px 0 0 0; padding: 10px 0 0 0;
.cronButton { .cronButton {
margin: 0 10px; margin: 0 10px;
line-height: 40px; line-height: 40px;
}
} }
}
} }
.tabBody { .tabBody {
.a-row { .a-row {
margin: 10px 0; margin: 10px 0;
.long { .long {
.a-select { .a-select {
width: 354px; width: 354px;
} }
} }
.a-input-number { .a-input-number {
width: 110px; width: 110px;
}
} }
}
} }
</style> </style>
\ No newline at end of file
...@@ -20,15 +20,16 @@ export default { ...@@ -20,15 +20,16 @@ export default {
async submit() { async submit() {
await this.$refs.DrawerForm.validate(); await this.$refs.DrawerForm.validate();
if (this.isAdd) { if (this.isAdd) {
return this?.add(); return this.add();
} }
if (this.isEdit) { if (this.isEdit) {
return this?.edit(); return this.edit();
} }
}, },
setData(data, type) { setData(data, type) {
this.form = { ...data }; this.form = { ...data };
this.type = type; this.type = type;
console.log(data, type);
}, },
}, },
}; };
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
:onOk="btn.onOk" :onOk="btn.onOk"
:label="btn.label" :label="btn.label"
/> />
<a v-else @click="() => btn.click(row)">{{ btn.label }}</a> <a v-else @click="() => btn.click(row)" v-bind="btn.option">{{ btn.label }}</a>
<a-divider type="vertical" v-if="moreBtns.length || index !== basicBtns.length - 1" /> <a-divider type="vertical" v-if="moreBtns.length || index !== basicBtns.length - 1" />
</span> </span>
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
:onOk="btn.onOk" :onOk="btn.onOk"
:label="btn.label" :label="btn.label"
/> />
<a v-else @click="() => btn.click(row)">{{ btn.label }}</a> <a v-else @click="() => btn.click(row)" v-bind="btn.option">{{ btn.label }}</a>
</span> </span>
</a-space> </a-space>
</template> </template>
...@@ -77,10 +77,10 @@ export default { ...@@ -77,10 +77,10 @@ export default {
return url; return url;
}, },
init() { init() {
this.buttons.map((i) => { this.buttons.map(i => {
i.__hidden__ = i.isHidden && i.isHidden(this.row); i.__hidden__ = i.isHidden && i.isHidden(this.row);
}); });
this.buttonsArr = this.buttons.filter((i) => !i.__hidden__); this.buttonsArr = this.buttons.filter(i => !i.__hidden__);
}, },
}, },
}; };
......
...@@ -180,6 +180,7 @@ export default { ...@@ -180,6 +180,7 @@ export default {
this.addVisible = true; this.addVisible = true;
this.type = 0; this.type = 0;
this.noFooter = false; this.noFooter = false;
this.title = '新增';
}, },
addDrawerClose() { addDrawerClose() {
this.addVisible = false; this.addVisible = false;
......
...@@ -15,10 +15,14 @@ ...@@ -15,10 +15,14 @@
</div> </div>
</my-card> </my-card>
<my-card class="tw-mt-3"> <my-card>
<a-space class="tw-mb-2.5"> <a-space :class="{ 'tw-mb-2.5': !!$scopedSlots.search }">
<slot name="action" /> <a-button type="primary" v-if="addBtn" @click="addBtnClick">
{{ typeof addBtn === 'object' ? addBtn.text : '新增' }}
</a-button>
<slot name="operation" />
</a-space> </a-space>
<a-table <a-table
:data-source="data" :data-source="data"
:loading="loading" :loading="loading"
...@@ -27,8 +31,26 @@ ...@@ -27,8 +31,26 @@
@change="pageChange" @change="pageChange"
> >
<slot /> <slot />
<a-table-column title="操作" v-if="buttons">
<template #default="row">
<my-ac-btn :row="row" :buttons="buttons" />
</template>
</a-table-column>
</a-table> </a-table>
</my-card> </my-card>
<a-drawer
placement="right"
:visible="visible"
:drawerStyle="drawerStyle"
:bodyStyle="bodyStyle"
destroyOnClose
:width="600"
@close="hidden"
:maskClosable="false"
>
<slot name="drawer" :hidden="hidden" />
</a-drawer>
</div> </div>
</template> </template>
...@@ -43,6 +65,10 @@ const initQuery = { ...@@ -43,6 +65,10 @@ const initQuery = {
export default { export default {
props: { props: {
url: String, url: String,
addBtn: [Object, Boolean],
buttons: Array,
noPage: Boolean,
formatData: Function,
}, },
data() { data() {
...@@ -54,6 +80,17 @@ export default { ...@@ -54,6 +80,17 @@ export default {
queryForm: {}, queryForm: {},
loading: false, loading: false,
total: 0, total: 0,
visible: false,
title: '新增',
drawerStyle: {
display: 'flex',
flexDirection: 'column',
overflowY: 'hidden',
},
bodyStyle: {
flex: 1,
overflow: 'hidden',
},
}; };
}, },
...@@ -63,12 +100,14 @@ export default { ...@@ -63,12 +100,14 @@ export default {
computed: { computed: {
pagination() { pagination() {
return { return this.noPage
current: this.initQuery.pageNum, ? false
pageSize: this.initQuery.pageSize, : {
total: this.total, current: this.initQuery.pageNum,
showQuickJumper: true, pageSize: this.initQuery.pageSize,
}; total: this.total,
showQuickJumper: true,
};
}, },
}, },
...@@ -76,7 +115,7 @@ export default { ...@@ -76,7 +115,7 @@ export default {
async getData() { async getData() {
this.loading = true; this.loading = true;
try { try {
await this.getDataWithPage(); this.noPage ? await this.getDataNoPage() : await this.getDataWithPage();
} catch (error) { } catch (error) {
// todo // todo
} }
...@@ -90,10 +129,34 @@ export default { ...@@ -90,10 +129,34 @@ export default {
else this.data = res.records; else this.data = res.records;
}, },
async getDataNoPage() {
const res = await request(this.url, METHOD.GET, this.queryForm);
if (this.formatData) this.data = this.formatData(res);
else this.data = res;
},
pageChange(page) { pageChange(page) {
this.initQuery.pageNum = page.current; this.initQuery.pageNum = page.current;
this.getData(); this.getData();
}, },
hidden() {
this.visible = false;
},
show({ title } = {}) {
this.visible = true;
if (title) this.title = title;
},
reset() {
this.queryForm = {};
this.initQuery = { ...initQuery };
this.getData();
},
addBtnClick() {
const { click } = typeof this.addBtn === 'object' ? this.addBtn : {};
click && click();
this.visible = true;
},
}, },
}; };
</script> </script>
<template>
<div>
<Drawer />
<Table>
<template #search="query">
<slot name="search" :query="query" />
</template>
<slot name="table" />
</Table>
</div>
</template>
<script>
import Table from './table.vue';
import Drawer from './drawer.vue';
export default {
components: { Table, Drawer },
};
</script>
<template>
<div class="tw-flex tw-flex-col tw-h-full">
<div class="tw-overflow-y-hidden tw-flex-1">
<div class="tw-overflow-y-auto tw-h-full">
<slot />
</div>
</div>
<template>
<a-divider />
<a-space class="tw-justify-end">
<a-button @click="cancel">取消</a-button>
<slot name="footer">
<a-button type="primary" @click="ok" :loading="loading">确认</a-button>
</slot>
</a-space>
</template>
</div>
</template>
<script>
import { EMPTY_FUN } from '@/utils';
export default {
props: {
onOk: {
type: Function,
default: EMPTY_FUN,
},
onCancel: Function,
hidden: {
type: Function,
default: EMPTY_FUN,
},
},
data: () => ({
loading: false,
}),
methods: {
cancel() {
if (this.onCancel) this.onCancel();
this.hidden();
},
async ok() {
this.loading = true;
await this.onOk();
this.loading = false;
this.hidden();
},
},
};
</script>
// 全部的配置数据 // 全部的配置数据
const globalConfig = { const globalConfig = {
//支持语言
langs: [
{key: 'zh_CN', name: '简体中文', alias: '简体'},
{key: 'en_US', name: 'English', alias: 'English'}
],
//调色板 颜色 //调色板 颜色
palettes: ["#f5222d", "#fa541c", "#fadb14", "#3eaf7c", "#13c2c2", "#1890ff", "#722ed1", "#eb2f96"], palettes: ['#f5222d', '#fa541c', '#fadb14', '#3eaf7c', '#13c2c2', '#1890ff', '#722ed1', '#eb2f96'],
//tab出入动画效果 //tab出入动画效果
animates: { animates: {
preset: [ preset: [
//参考Animate.css 各种特效的css命名,default对应没有 direction的情况 //参考Animate.css 各种特效的css命名,default对应没有 direction的情况
{ name: "back", alias: "渐近", directions: ["Left", "Right"] }, { name: 'back', alias: '渐近', directions: ['Left', 'Right'] },
{ name: "bounce", alias: "弹跳", directions: ["Left", "Right", "Default"] }, { name: 'bounce', alias: '弹跳', directions: ['Left', 'Right', 'Default'] },
{ {
name: "fade", name: 'fade',
alias: "淡化", alias: '淡化',
directions: ["Left", "LeftBig", "Right", "RightBig", "Default"], directions: ['Left', 'LeftBig', 'Right', 'RightBig', 'Default'],
}, },
{ name: "lightSpeed", alias: "光速", directions: ["Left", "Right"] }, { name: 'lightSpeed', alias: '光速', directions: ['Left', 'Right'] },
{ name: "slide", alias: "滑动", directions: ["Left", "Right"] }, { name: 'slide', alias: '滑动', directions: ['Left', 'Right'] },
], ],
}, },
//当前主色调 + 3个功能颜色 + 3个模式菜单颜色 //当前主色调 + 3个功能颜色 + 3个模式菜单颜色
primary: { primary: {
color: "#3eaf7c", color: '#3eaf7c',
warning: "#faad14", warning: '#faad14',
success: "#52c41a", success: '#52c41a',
error: "#f5222d", error: '#f5222d',
light: { light: {
menuColors: ["#000c17", "#001529", "#002140"], menuColors: ['#000c17', '#001529', '#002140'],
}, },
dark: { dark: {
menuColors: ["#000c17", "#001529", "#002140"], menuColors: ['#000c17', '#001529', '#002140'],
}, },
night: { night: {
menuColors: ["#151515", "#1f1f1f", "#1e1e1e"], menuColors: ['#151515', '#1f1f1f', '#1e1e1e'],
}, },
}, },
//主题 //主题
theme: { theme: {
mode: { mode: {
DARK: "dark", DARK: 'dark',
LIGHT: "light", LIGHT: 'light',
NIGHT: "night", NIGHT: 'night',
}, },
dark: { dark: {
"layout-body-background": "#f0f2f5", 'layout-body-background': '#f0f2f5',
"body-background": "#fff", 'body-background': '#fff',
"component-background": "#fff", 'component-background': '#fff',
"heading-color": "rgba(0, 0, 0, 0.85)", 'heading-color': 'rgba(0, 0, 0, 0.85)',
"text-color": "rgba(0, 0, 0, 0.65)", 'text-color': 'rgba(0, 0, 0, 0.65)',
"text-color-inverse": "#fff", 'text-color-inverse': '#fff',
"text-color-secondary": "rgba(0, 0, 0, 0.45)", 'text-color-secondary': 'rgba(0, 0, 0, 0.45)',
"shadow-color": "rgba(0, 0, 0, 0.15)", 'shadow-color': 'rgba(0, 0, 0, 0.15)',
"border-color-split": "#f0f0f0", 'border-color-split': '#f0f0f0',
"background-color-light": "#fafafa", 'background-color-light': '#fafafa',
"background-color-base": "#f5f5f5", 'background-color-base': '#f5f5f5',
"table-selected-row-bg": "#fafafa", 'table-selected-row-bg': '#fafafa',
"table-expanded-row-bg": "#fbfbfb", 'table-expanded-row-bg': '#fbfbfb',
"checkbox-check-color": "#fff", 'checkbox-check-color': '#fff',
"disabled-color": "rgba(0, 0, 0, 0.25)", 'disabled-color': 'rgba(0, 0, 0, 0.25)',
"menu-dark-color": "rgba(254, 254, 254, 0.65)", 'menu-dark-color': 'rgba(254, 254, 254, 0.65)',
"menu-dark-highlight-color": "#fefefe", 'menu-dark-highlight-color': '#fefefe',
"menu-dark-arrow-color": "#fefefe", 'menu-dark-arrow-color': '#fefefe',
"btn-primary-color": "#fff", 'btn-primary-color': '#fff',
}, },
light: { light: {
"layout-body-background": "#f0f2f5", 'layout-body-background': '#f0f2f5',
"body-background": "#fff", 'body-background': '#fff',
"component-background": "#fff", 'component-background': '#fff',
"heading-color": "rgba(0, 0, 0, 0.85)", 'heading-color': 'rgba(0, 0, 0, 0.85)',
"text-color": "rgba(0, 0, 0, 0.65)", 'text-color': 'rgba(0, 0, 0, 0.65)',
"text-color-inverse": "#fff", 'text-color-inverse': '#fff',
"text-color-secondary": "rgba(0, 0, 0, 0.45)", 'text-color-secondary': 'rgba(0, 0, 0, 0.45)',
"shadow-color": "rgba(0, 0, 0, 0.15)", 'shadow-color': 'rgba(0, 0, 0, 0.15)',
"border-color-split": "#f0f0f0", 'border-color-split': '#f0f0f0',
"background-color-light": "#fafafa", 'background-color-light': '#fafafa',
"background-color-base": "#f5f5f5", 'background-color-base': '#f5f5f5',
"table-selected-row-bg": "#fafafa", 'table-selected-row-bg': '#fafafa',
"table-expanded-row-bg": "#fbfbfb", 'table-expanded-row-bg': '#fbfbfb',
"checkbox-check-color": "#fff", 'checkbox-check-color': '#fff',
"disabled-color": "rgba(0, 0, 0, 0.25)", 'disabled-color': 'rgba(0, 0, 0, 0.25)',
"menu-dark-color": "rgba(1, 1, 1, 0.65)", 'menu-dark-color': 'rgba(1, 1, 1, 0.65)',
"menu-dark-highlight-color": "#fefefe", 'menu-dark-highlight-color': '#fefefe',
"menu-dark-arrow-color": "#fefefe", 'menu-dark-arrow-color': '#fefefe',
"btn-primary-color": "#fff", 'btn-primary-color': '#fff',
}, },
night: { night: {
"layout-body-background": "#000", 'layout-body-background': '#000',
"body-background": "#141414", 'body-background': '#141414',
"component-background": "#141414", 'component-background': '#141414',
"heading-color": "rgba(255, 255, 255, 0.85)", 'heading-color': 'rgba(255, 255, 255, 0.85)',
"text-color": "rgba(255, 255, 255, 0.85)", 'text-color': 'rgba(255, 255, 255, 0.85)',
"text-color-inverse": "#141414", 'text-color-inverse': '#141414',
"text-color-secondary": "rgba(255, 255, 255, 0.45)", 'text-color-secondary': 'rgba(255, 255, 255, 0.45)',
"shadow-color": "rgba(255, 255, 255, 0.15)", 'shadow-color': 'rgba(255, 255, 255, 0.15)',
"border-color-split": "#303030", 'border-color-split': '#303030',
"background-color-light": "#ffffff0a", 'background-color-light': '#ffffff0a',
"background-color-base": "#2a2a2a", 'background-color-base': '#2a2a2a',
"table-selected-row-bg": "#ffffff0a", 'table-selected-row-bg': '#ffffff0a',
"table-expanded-row-bg": "#ffffff0b", 'table-expanded-row-bg': '#ffffff0b',
"checkbox-check-color": "#141414", 'checkbox-check-color': '#141414',
"disabled-color": "rgba(255, 255, 255, 0.25)", 'disabled-color': 'rgba(255, 255, 255, 0.25)',
"menu-dark-color": "rgba(254, 254, 254, 0.65)", 'menu-dark-color': 'rgba(254, 254, 254, 0.65)',
"menu-dark-highlight-color": "#fefefe", 'menu-dark-highlight-color': '#fefefe',
"menu-dark-arrow-color": "#fefefe", 'menu-dark-arrow-color': '#fefefe',
"btn-primary-color": "#141414", 'btn-primary-color': '#141414',
}, },
}, },
layout: { layout: {
SIDE: "side", SIDE: 'side',
HEAD: "head", HEAD: 'head',
}, },
}; };
module.exports = globalConfig; module.exports = globalConfig;
\ No newline at end of file
...@@ -8,17 +8,16 @@ import VueI18n from 'vue-i18n'; ...@@ -8,17 +8,16 @@ import VueI18n from 'vue-i18n';
import { accountModule, settingModule } from './pages/frame/store'; import { accountModule, settingModule } from './pages/frame/store';
import globalStore from '@/store'; import globalStore from '@/store';
import App from './App.vue'; import App from './App.vue';
import 'tailwindcss/tailwind.css';
import 'animate.css/source/animate.css';
import './theme/index.less';
import Plugins from './plugins'; import Plugins from './plugins';
import { loadRoutes, loadGuards, setAppOptions } from './utils/routerUtil'; import { loadRoutes, loadGuards, setAppOptions } from './utils/routerUtil';
import guards from './router/guards'; import guards from './router/guards';
import { loadResponseInterceptor } from './utils/requestUtil'; import { loadResponseInterceptor } from './utils/requestUtil';
import langUtils from '@/utils/langUtils';
import 'tailwindcss/tailwind.css';
import 'animate.css/source/animate.css';
import './theme/index.less';
// import '@/mock';
import 'moment/locale/zh-cn'; import 'moment/locale/zh-cn';
//设置为非生产提示 //设置为非生产提示
...@@ -40,13 +39,12 @@ const router = new Router(options); ...@@ -40,13 +39,12 @@ const router = new Router(options);
//装载vue-i18n控件 如果语言优先级 请直接修改这里localeLang和fallbackLang //装载vue-i18n控件 如果语言优先级 请直接修改这里localeLang和fallbackLang
Vue.use(VueI18n); Vue.use(VueI18n);
//defalt 'CN'
const localeLang = store.state.settingModule.lang; const localeLang = langUtils.get();
//default'EN'
const fallbackLang = store.state.settingModule.fallbackLang;
const i18n = new VueI18n({ const i18n = new VueI18n({
locale: localeLang, locale: localeLang,
fallbackLocale: fallbackLang, fallbackLocale: langUtils.fallbackLocale,
silentFallbackWarn: true, silentFallbackWarn: true,
}); });
......
<template> <template>
<a-dropdown class="lang header-item"> <a-dropdown class="lang header-item">
<div><a-icon type="global" /> {{ langAlias }}</div> <div><a-icon type="global" /> {{ langAlias }}</div>
<a-menu @click="val => setLang(val.key)" :selected-keys="[lang]" slot="overlay"> <a-menu @click="changeLang" :selected-keys="[lang]" slot="overlay">
<a-menu-item v-for="lang in langList" :key="lang.key"> <a-menu-item v-for="lang in langList" :key="lang.key">
{{ lang.key.toLowerCase() + ' ' + lang.name }} {{ lang.key.toLowerCase() + ' ' + lang.name }}
</a-menu-item> </a-menu-item>
...@@ -10,26 +10,28 @@ ...@@ -10,26 +10,28 @@
</template> </template>
<script> <script>
import { mapState, mapMutations } from 'vuex'; import langUtils from '@/utils/langUtils';
import { globalConfig } from '@/config';
export default { export default {
name: 'LayoutTopHeaderLang', name: 'LayoutTopHeaderLang',
data() { data() {
return { return {
langList: globalConfig.langs, langList: langUtils.langList,
lang: langUtils.get(),
}; };
}, },
computed: { computed: {
...mapState('settingModule', ['lang']),
langAlias() { langAlias() {
let lang = this.langList.find(item => item.key == this.lang); const lang = this.langList.find(item => item.key == this.lang);
return lang.alias; return lang.alias;
}, },
}, },
methods: { methods: {
...mapMutations('settingModule', ['setLang']), change(langKey) {
this.$i18n.locale = langKey;
this.lang = langKey;
langUtils.set(langKey);
},
}, },
}; };
</script> </script>
<template> <template>
<page-toggle-transition <router-view />
:disabled="animate.disabled"
:animate="animate.name"
:direction="animate.direction"
>
<router-view />
</page-toggle-transition>
</template> </template>
<script> <script>
import PageToggleTransition from '@/components/transition/PageToggleTransition.vue';
import { mapState } from 'vuex'; import { mapState } from 'vuex';
export default { export default {
name: 'BlankTemplateView', name: 'BlankTemplateView',
components: { PageToggleTransition },
computed: { computed: {
...mapState('settingModule', ['multiPage', 'animate']), ...mapState('settingModule', ['multiPage']),
}, },
}; };
</script> </script>
<template> <template>
<page-layout :desc="desc" :linkList="linkList"> <page-layout :desc="desc" :linkList="linkList">
<div v-if="this.extraImage && !isMobile" slot="extra" class="extraImg"> <div v-if="this.extraImage && !isMobile" slot="extra" :class="$style.extraImg">
<img :src="extraImage" /> <img :src="extraImage" />
</div> </div>
<page-toggle-transition :disabled="animate.disabled" :animate="animate.name" :direction="animate.direction"> <router-view ref="page" />
<router-view ref="page" />
</page-toggle-transition>
</page-layout> </page-layout>
</template> </template>
<script> <script>
import PageLayout from '../../layouts/PageLayout.vue'; import PageLayout from '../../layouts/PageLayout.vue';
import PageToggleTransition from '@/components/transition/PageToggleTransition';
import { mapState } from 'vuex'; import { mapState } from 'vuex';
export default { export default {
name: 'PageTemplateView', name: 'PageTemplateView',
components: { PageToggleTransition, PageLayout }, components: { PageLayout },
data() { data() {
return { return {
page: {}, page: {},
}; };
}, },
computed: { computed: {
...mapState('settingModule', ['isMobile', 'multiPage', 'animate']), ...mapState('settingModule', ['isMobile', 'multiPage']),
desc() { desc() {
return this.page.desc; return this.page.desc;
}, },
...@@ -43,7 +40,7 @@ export default { ...@@ -43,7 +40,7 @@ export default {
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" modle>
.extraImg { .extraImg {
margin-top: -60px; margin-top: -60px;
text-align: center; text-align: center;
......
...@@ -14,16 +14,10 @@ ...@@ -14,16 +14,10 @@
:class="['tabs-view-content', layout, pageWidth]" :class="['tabs-view-content', layout, pageWidth]"
:style="`margin-top: ${multiPage ? -20 : 0}px`" :style="`margin-top: ${multiPage ? -20 : 0}px`"
> >
<page-toggle-transition <a-keep-alive :exclude-keys="excludeKeys" v-if="multiPage && cachePage" v-model="clearCaches">
:disabled="animate.disabled" <router-view v-if="!refreshing" ref="tabContent" :key="$route.fullPath" />
:animate="animate.name" </a-keep-alive>
:direction="animate.direction" <router-view ref="tabContent" v-else-if="!refreshing" />
>
<a-keep-alive :exclude-keys="excludeKeys" v-if="multiPage && cachePage" v-model="clearCaches">
<router-view v-if="!refreshing" ref="tabContent" :key="$route.fullPath" />
</a-keep-alive>
<router-view ref="tabContent" v-else-if="!refreshing" />
</page-toggle-transition>
</div> </div>
</admin-layout> </admin-layout>
</template> </template>
...@@ -31,7 +25,6 @@ ...@@ -31,7 +25,6 @@
<script> <script>
import AdminLayout from '../../layouts/AdminLayout'; import AdminLayout from '../../layouts/AdminLayout';
import Contextmenu from '@/components/menu/Contextmenu.vue'; import Contextmenu from '@/components/menu/Contextmenu.vue';
import PageToggleTransition from '@/components/transition/PageToggleTransition';
import { mapState, mapMutations } from 'vuex'; import { mapState, mapMutations } from 'vuex';
import { getI18nKey } from '@/utils/routerUtil'; import { getI18nKey } from '@/utils/routerUtil';
import AKeepAlive from '@/components/cache/AKeepAlive'; import AKeepAlive from '@/components/cache/AKeepAlive';
...@@ -41,7 +34,7 @@ import templateI18n from './i18n'; ...@@ -41,7 +34,7 @@ import templateI18n from './i18n';
export default { export default {
name: 'TabsTemplateView', name: 'TabsTemplateView',
i18n: templateI18n, i18n: templateI18n,
components: { LayoutTabsHeader, PageToggleTransition, Contextmenu, AdminLayout, AKeepAlive }, components: { LayoutTabsHeader, Contextmenu, AdminLayout, AKeepAlive },
data() { data() {
return { return {
clearCaches: [], clearCaches: [],
...@@ -53,7 +46,7 @@ export default { ...@@ -53,7 +46,7 @@ export default {
}; };
}, },
computed: { computed: {
...mapState('settingModule', ['multiPage', 'cachePage', 'animate', 'layout', 'pageWidth']), ...mapState('settingModule', ['multiPage', 'cachePage', 'layout', 'pageWidth']),
menuItemList() { menuItemList() {
return [ return [
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
ref="table" ref="table"
> >
<template #drawer> <template #drawer>
<AddCom v-if="addCom" /> <AddCom v-if="addCom" :row="currentClickRow" ref="addCom" />
<Form ref="addForm" v-else /> <Form ref="addForm" v-else />
</template> </template>
...@@ -33,24 +33,30 @@ import AddCom from './add_com.vue'; ...@@ -33,24 +33,30 @@ import AddCom from './add_com.vue';
export default { export default {
data: vm => ({ data: vm => ({
addCom: false, addCom: false,
currentClickRow: null,
addBtn: { addBtn: {
text: '新建', text: '新建',
onOk() { onOk() {
return vm.$refs['addForm']?.submit(); return vm.addCom ? vm.$refs['addCom']?.submit() : vm.$refs['addForm']?.submit();
}, },
onCancel() { onCancel() {
vm.addCom = false; vm.addCom = false;
vm.currentClickRow = null;
}, },
}, },
sortOrder: 'ascend', sortOrder: 'ascend',
buttons: [ buttons: [
{ {
label: '新增组件', label: '新增组件',
click() { option: {
style: 'color: #ff4d4f',
},
click(row) {
vm.show(); vm.show();
vm.addCom = true; vm.addCom = true;
vm.currentClickRow = row;
}, },
isHidden: row => row.menuType === 'MENU', isHidden: row => row.menuType !== 'MENU',
}, },
{ label: '编辑', click: vm.edit }, { label: '编辑', click: vm.edit },
{ type: 'confirm', url: row => `/api/v1/menus/${row.menuId}`, after: vm.refreshTable }, { type: 'confirm', url: row => `/api/v1/menus/${row.menuId}`, after: vm.refreshTable },
...@@ -74,7 +80,7 @@ export default { ...@@ -74,7 +80,7 @@ export default {
}); });
}, },
show() { show() {
this.$refs['table'].show(); this.$refs['table'].show({ title: '菜单组件' });
}, },
}, },
}; };
......
<template> <template>
<h1>addCom</h1> <div>
<a-button type="primary" class="tw-mb-2" @click="add">新增</a-button>
<a-table :dataSource="components" :rowKey="getRowKey">
<a-table-column title="组件编码">
<template #default="row">
<span v-if="row.componentId">{{ row.componentCode }}</span>
<a-input v-else v-model="row.componentCode" />
</template>
</a-table-column>
<a-table-column title="组件名称">
<template #default="row">
<span v-if="row.componentId">{{ row.componentName }}</span>
<a-input v-else v-model="row.componentName" />
</template>
</a-table-column>
<a-table-column title="操作">
<template #default="row">
<a @click="() => del(row)">删除</a>
</template>
</a-table-column>
</a-table>
</div>
</template> </template>
<script>
import { getMenuComponentApi, addMenuComponentApi } from '@/api';
export default {
props: ['row'],
data: () => ({
components: [],
}),
mounted() {
this.getData();
},
methods: {
async getData() {
const { menuId } = this.row;
this.components = await getMenuComponentApi(menuId);
},
add() {
this.components.push({
componentCode: '',
componentName: '',
__key__: this.components.length,
});
},
del(row) {
this.components = this.components.filter(r => r !== row);
},
getRowKey(row) {
return row.__key__ ? row.__key__ : row.componentId;
},
submit() {
const { menuId } = this.row;
return addMenuComponentApi(
menuId,
this.components.map(i => {
delete i.__key__;
return i;
}),
);
},
},
};
</script>
<template> <template>
<a-form-model layout="vertical" :model="form" :rules="rules" ref="DrawerForm"> <a-form-model layout="vertical" :model="form" :rules="rules" ref="DrawerForm">
<a-form-model-item label="任务名称" prop="jobName"> <a-form-model-item label="任务名称" prop="taskName">
<a-input v-model="form.jobName" :disabled="isView" /> <a-input v-model="form.taskName" :disabled="isView" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="调度规则" prop="jobDescription"> <a-form-model-item label="调度规则" prop="taskRule">
<a-textarea v-model="form.jobDescription" :disabled="isView" :rows="4" /> <ACron v-model="form.taskRule" :disabled="isView" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="实现类" prop="jobDescription"> <a-form-model-item label="实现类" prop="implementClass">
<a-input v-model="form.jobDescription" :disabled="isView" /> <a-input v-model="form.implementClass" :disabled="isView" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="说明" prop="jobDescription"> <a-form-model-item label="说明" prop="remark">
<a-textarea v-model="form.jobDescription" :disabled="isView" :rows="4" /> <a-textarea v-model="form.remark" :disabled="isView" :rows="4" />
</a-form-model-item> </a-form-model-item>
</a-form-model> </a-form-model>
</template> </template>
<script> <script>
import JobsApi from '@/api/organization'; import { addTaskApi, updateTaskApi } from '@/api';
import FormMixin from '@/components/FormMixin'; import FormMixin from '@/components/FormMixin';
import ACron from '@/components/Acron/ACron.vue';
export default { export default {
components: { ACron },
props: ['row'],
mixins: [FormMixin], mixins: [FormMixin],
data() { data() {
return { return {
rules: { rules: {
jobName: [{ required: true, message: 'Please select Activity zone', trigger: 'change' }], taskName: [{ required: true }],
jobDescription: [ taskRule: [{ required: true }],
{ required: true, message: 'Please select Activity zone', trigger: 'change' },
],
}, },
}; };
}, },
methods: { methods: {
add() { add() {
return JobsApi.add({ ...this.form }); return addTaskApi({ ...this.form });
}, },
edit() { edit() {
return JobsApi.update({ ...this.form }); return updateTaskApi({ ...this.form });
}, },
}, },
}; };
......
<template> <template>
<my-table url="/api/v1/schedules" rowKey="taskId" :addBtn="addBtn" ref="table"> <my-table url="/api/v1/schedules" rowKey="taskId" :addBtn="addBtn" ref="table">
<template #drawer> <template #drawer>
<Form ref="form" /> <Form ref="form" :row="currentClickRow" />
</template> </template>
<a-table-column title="任务名称" data-index="taskName" /> <a-table-column title="任务名称" data-index="taskName" />
<a-table-column title="调度规则" data-index="taskRule" /> <a-table-column title="调度规则" data-index="taskRule" />
...@@ -23,7 +23,12 @@ export default { ...@@ -23,7 +23,12 @@ export default {
components: { ActionButton, Form }, components: { ActionButton, Form },
data() { data() {
return { return {
addBtn: {}, addBtn: {
onOk: () => {
return this.$refs.form.submit();
},
},
currentClickRow: null,
buttons: [ buttons: [
{ {
label: '查看', label: '查看',
...@@ -47,8 +52,9 @@ export default { ...@@ -47,8 +52,9 @@ export default {
type: 'confirm', type: 'confirm',
label: '失效', label: '失效',
title: '确认是否失效?', title: '确认是否失效?',
url: row => `/api/v1/schedules/${row.taskId}`, url: row => ({ url: `/api/v1/schedules/${row.taskId}/pause`, method: 'del' }),
after: () => this.refreshTable(), after: () => this.refreshTable(),
isHidden: row => row.isPaused === 1,
}, },
{ {
type: 'confirm', type: 'confirm',
......
<template>
<Wraper :onCancel="hidden" :hidden="hidden">
<h1>这是内容</h1>
</Wraper>
</template>
<script>
import Wraper from '@/components/table/wraper.vue';
export default {
components: { Wraper },
props: ['hidden'],
};
</script>
<template> <template>
<h1>TODO</h1> <Table url="/api/v1/logger/login" rowKey="logId" addBtn :actions="actions" ref="table">
<template #search="{query}">
<my-form-item label="开始时间">
<a-date-picker
class="tw-w-full"
show-time
v-model="query.startTime"
valueFormat="YYYY-MM-DD HH:mm:ss"
/>
</my-form-item>
</template>
<template #drawer="{hidden}">
<Form :hidden="hidden" />
</template>
<a-table-column title="用户Id" data-index="userId" />
<a-table-column title="登录用户" data-index="userName" />
<a-table-column title="登录IP" data-index="loginIp" />
<a-table-column title="事件类型" data-index="loginTypeName" />
<a-table-column title="事件状态" data-index="isSuccessName" />
<a-table-column title="登录时间" data-index="loginTime" />
<a-table-column title="说明" data-index="logResultContent" />
</Table>
</template> </template>
<script>
import Table from '@/components/table/table.vue';
import Form from './form.vue';
export default {
components: { Table, Form },
data: () => ({
addBtn: {
text: '新增',
},
actions: [],
}),
};
</script>
import { notification } from 'antd';
import { getLocale, history } from 'umi';
import config from '@/config';
import { clearLoginStatus, getLocaleText } from '@/utils';
import HttpRequest from './kim-request';
import store from 'store';
// const codeMessage = {
// 200: getLocaleText('kim.system.request.200'),
// 201: getLocaleText('kim.system.request.201'),
// 202: getLocaleText('kim.system.request.202'),
// 204: getLocaleText('kim.system.request.204'),
// 400: getLocaleText('kim.system.request.400'),
// 401: getLocaleText('kim.system.request.401'),
// 403: getLocaleText('kim.system.request.403'),
// 404: getLocaleText('kim.system.request.404'),
// 406: getLocaleText('kim.system.request.406'),
// 410: getLocaleText('kim.system.request.410'),
// 422: getLocaleText('kim.system.request.422'),
// 500: getLocaleText('kim.system.request.500'),
// 502: getLocaleText('kim.system.request.502'),
// 503: getLocaleText('kim.system.request.503'),
// 504: getLocaleText('kim.system.request.504'),
// };
const {
request: {
baseUrl,
apiPrefix,
resCodeKey,
resMessageKey,
successCode,
isThrowError = true,
authCodes = ['error.system.authc'],
},
} = config;
/**
* 组装url
* @param {url} url
* @param {{}} more
*/
const merge = (url: string, more: any) => {
if (more && more.apiPrefix && typeof more.apiPrefix === 'string') {
return `${config.apiPrefix}${url}`;
}
if (apiPrefix && typeof apiPrefix === 'string') {
return `${config.apiPrefix}${url}`;
}
return url;
};
const headers = () => ({
Authorization: store.get('token'),
'X-Access-Lang': getLocale().replace(/-/, '_'),
});
const axios = new HttpRequest({
baseUrl,
headers: headers || {},
});
/**
* 正常返回结果处理
* @param {返回请求数据} response
* @param {配置项} more
*/
const handleResponse = (response) => {
const { data } = response;
console.log('response', response);
//
if (`${data[resCodeKey]}` !== `${successCode}`) {
if (isThrowError) {
const errorMessage =
data[resMessageKey] || getLocaleText('kim.system.request.default.message');
let error = new Error();
error = { ...error, ...data };
error.code = data[resCodeKey];
error.message = errorMessage;
return Promise.reject(error);
}
}
// success
return data;
};
const handleError = (error, more) => {
const codeMessage = {
200: getLocaleText('kim.system.request.200'),
201: getLocaleText('kim.system.request.201'),
202: getLocaleText('kim.system.request.202'),
204: getLocaleText('kim.system.request.204'),
400: getLocaleText('kim.system.request.400'),
401: getLocaleText('kim.system.request.401'),
403: getLocaleText('kim.system.request.403'),
404: getLocaleText('kim.system.request.404'),
406: getLocaleText('kim.system.request.406'),
410: getLocaleText('kim.system.request.410'),
422: getLocaleText('kim.system.request.422'),
500: getLocaleText('kim.system.request.500'),
502: getLocaleText('kim.system.request.502'),
503: getLocaleText('kim.system.request.503'),
504: getLocaleText('kim.system.request.504'),
};
const { response } = error;
const options = { isThrowError, ...more };
// status
if (response && response.status) {
const errorText = codeMessage[response.status] || response.statusText;
const {
status,
config: { url },
} = response;
notification.error({
message: `${getLocaleText('kim.system.request.dialog.title')} ${status}`,
description: `${url}${errorText}`,
});
// 跳转到404页面
if (status >= 404 && status < 422) {
history.push('/exception/404');
}
if (status <= 504 && status >= 500) {
history.push('/exception/500');
}
// 跳转到登录页面 可能原因:token 失效
if (status === 403 && status === 401) {
clearLoginStatus();
history.push('/user/login');
}
} else {
// code
const { code, message } = error;
notification.error({
key: `notification_${code ? message : code}`,
message: getLocaleText('kim.system.request.dialog.title'),
description: message,
});
// 跳转到登录页面 可能原因:token 失效
if (authCodes && authCodes.includes(code)) {
// 清空相关信息
clearLoginStatus();
history.push('/user/login');
}
}
if (options.isThrowError) {
throw error;
} else {
return error;
}
};
export default function request(url, options = {}, more = {}, handle = false) {
let newOptions = options;
newOptions.url = url;
if (more.headers) {
newOptions = { ...options, headers: more.headers };
}
if (handle) {
return axios.request(newOptions);
}
return axios
.request(newOptions)
.then((response) => handleResponse(response, more))
.catch((error) => handleError(error, more));
}
/**
* get请求
* @param url
* @param data
* @param more
* @returns {AxiosPromise<any>|Promise<Promise<never> | 返回请求数据.data | *>}
*/
const get = (url, data, more = {}) => {
if (data?.current && !data?.pageNum) {
// eslint-disable-next-line no-param-reassign
data.pageNum = data.current;
}
return request(
`${merge(url, more)}`,
{
method: 'get', // default
params: data,
},
more,
);
};
/**
* post请求
* @param url
* @param data
* @param more
* @returns {AxiosPromise<any>|Promise<Promise<never> | 返回请求数据.data | *>}
*/
const post = (url, data, more = {}) =>
request(
`${merge(url, more)}`,
{
method: 'post', // default
data,
},
more,
);
/**
* put请求
* @param url
* @param data
* @param more
* @returns {AxiosPromise<any>|Promise<Promise<never> | 返回请求数据.data | *>}
*/
const put = (url, data, more = {}) =>
request(
`${merge(url, more)}`,
{
method: 'put', // default
data,
},
more,
);
/**
* delete请求
* @param url
* @param data
* @param more
* @returns {AxiosPromise<any>|Promise<Promise<never> | 返回请求数据.data | *>}
*/
const del = (url, data, more = {}) =>
request(
`${merge(url, more)}`,
{
method: 'delete', // default
data,
},
more,
);
/**
* patch请求
* @param url
* @param data
* @param more
* @returns {AxiosPromise<any>|Promise<Promise<never> | 返回请求数据.data | *>}
*/
const patch = (url, data, more = {}) =>
request(
`${merge(url, more)}`,
{
method: 'patch', // default
data,
...more,
},
more,
);
const downloadFile = (url, data, more = {}) => {
console.log('xiazai');
return request(
`${merge(url, more)}`,
{
method: 'get', // default
params: data,
responseType: 'blob',
},
more,
true,
).then((response) => {
return new Blob([response.data]);
});
};
const formDataUpload = (url, options, more = {}) => {
const formData = new FormData();
if (options) {
Object.keys(options).forEach((key) => {
formData.append(key, options[key]);
});
}
return post(`${merge(url, more)}`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
Authorization: store.get('token'),
},
...more,
}).then((res) => {
const { code } = res;
if (code === 'sys.success' && typeof options.onSuccess) {
return options.onSuccess(res);
}
return res;
});
};
/**
* 上传文件
* @param {url} url
* @param {data} data
* @param {type} type
* @param {more} more
*/
const uploadFile = (url, data, type = 'formData', more = {}) => {
if (type === 'formData') {
return formDataUpload(url, data, more);
}
return null;
};
export { request, get, post, put, del, patch, uploadFile, downloadFile };
const LANG_KEY = 'LANG_KEY'; const LANG_KEY = 'LANG_KEY';
// 假如 第一语言没有, 就使用这个配置的语言
const fallbackLocale = 'zh_CN';
// 支持的语言列表
const langList = [
{ key: 'zh_CN', name: '简体中文', alias: '简体' },
{ key: 'en_US', name: 'English', alias: 'English' },
];
function setLang(val) { function setLang(val) {
window.sessionStorage.setItem(LANG_KEY, val); window.localStorage.setItem(LANG_KEY, val);
} }
function getLang() { function getLang() {
return window.sessionStorage.getItem(LANG_KEY); return window.localStorage.getItem(LANG_KEY) || 'zh_CN';
} }
export default { export default {
get: getLang, get: getLang,
set: setLang, set: setLang,
fallbackLocale,
langList,
}; };
...@@ -21,7 +21,7 @@ function loadResponseInterceptor({ router }) { ...@@ -21,7 +21,7 @@ function loadResponseInterceptor({ router }) {
config.headers = { config.headers = {
...config.headers, ...config.headers,
Authorization: getToken(), Authorization: getToken(),
'X-Access-Lang': langUtil.get() || 'zh_CN', 'X-Access-Lang': langUtil.get(),
}; };
return config; return config;
}, },
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment