mirror of
https://gitee.com/yudaocode/yudao-ui-admin-vben.git
synced 2025-12-30 10:32:25 +00:00
feat: [bpm][antd] bpmn 设计器时间事件定义优化
This commit is contained in:
@@ -8,8 +8,10 @@ import {
|
||||
Input,
|
||||
InputNumber,
|
||||
Radio,
|
||||
TabPane,
|
||||
Tabs,
|
||||
} from 'ant-design-vue';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
@@ -41,7 +43,7 @@ const cronFieldList = [
|
||||
];
|
||||
const activeField = ref('second');
|
||||
const cronMode = ref({
|
||||
second: 'appoint',
|
||||
second: 'every',
|
||||
minute: 'every',
|
||||
hour: 'every',
|
||||
day: 'every',
|
||||
@@ -50,7 +52,7 @@ const cronMode = ref({
|
||||
year: 'every',
|
||||
});
|
||||
const cronAppoint = ref({
|
||||
second: ['00', '01'],
|
||||
second: [],
|
||||
minute: [],
|
||||
hour: [],
|
||||
day: [],
|
||||
@@ -107,103 +109,156 @@ watch(
|
||||
const isoStr = ref('');
|
||||
const repeat = ref(1);
|
||||
const isoDate = ref('');
|
||||
const durationUnits = [
|
||||
{ key: 'Y', label: '年', presets: [1, 2, 3, 4] },
|
||||
{ key: 'M', label: '月', presets: [1, 2, 3, 4] },
|
||||
{ key: 'D', label: '天', presets: [1, 2, 3, 4] },
|
||||
{ key: 'H', label: '时', presets: [4, 8, 12, 24] },
|
||||
{ key: 'm', label: '分', presets: [5, 10, 30, 50] },
|
||||
{ key: 'S', label: '秒', presets: [5, 10, 30, 50] },
|
||||
];
|
||||
const durationCustom = ref({ Y: '', M: '', D: '', H: '', m: '', S: '' });
|
||||
const isoDuration = ref('');
|
||||
function setDuration(type, val) {
|
||||
// 组装ISO 8601字符串
|
||||
let d = isoDuration.value;
|
||||
if (d.includes(type)) {
|
||||
d = d.replace(new RegExp(String.raw`\d+${type}`), val + type);
|
||||
} else {
|
||||
d += val + type;
|
||||
}
|
||||
isoDuration.value = d;
|
||||
|
||||
function setDuration(key, val) {
|
||||
durationCustom.value[key] = !val || Number.isNaN(val) ? '' : val;
|
||||
updateDurationStr();
|
||||
}
|
||||
|
||||
function updateDurationStr() {
|
||||
let str = 'P';
|
||||
str += durationCustom.value.Y ? `${durationCustom.value.Y}Y` : '';
|
||||
str += durationCustom.value.M ? `${durationCustom.value.M}M` : '';
|
||||
str += durationCustom.value.D ? `${durationCustom.value.D}D` : '';
|
||||
str +=
|
||||
durationCustom.value.H || durationCustom.value.m || durationCustom.value.S
|
||||
? 'T'
|
||||
: '';
|
||||
str += durationCustom.value.H ? `${durationCustom.value.H}H` : '';
|
||||
str += durationCustom.value.m ? `${durationCustom.value.m}M` : '';
|
||||
str += durationCustom.value.S ? `${durationCustom.value.S}S` : '';
|
||||
isoDuration.value = str === 'P' ? '' : str;
|
||||
updateIsoStr();
|
||||
}
|
||||
|
||||
function updateIsoStr() {
|
||||
let str = `R${repeat.value}`;
|
||||
if (isoDate.value)
|
||||
str += `/${
|
||||
if (isoDate.value) {
|
||||
const dateStr =
|
||||
typeof isoDate.value === 'string'
|
||||
? isoDate.value
|
||||
: new Date(isoDate.value).toISOString()
|
||||
}`;
|
||||
: isoDate.value.toISOString();
|
||||
str += `/${dateStr}`;
|
||||
}
|
||||
if (isoDuration.value) str += `/${isoDuration.value}`;
|
||||
isoStr.value = str;
|
||||
if (tab.value === 'iso') emit('change', isoStr.value);
|
||||
}
|
||||
watch([repeat, isoDate, isoDuration], updateIsoStr);
|
||||
watch([repeat, isoDate], updateIsoStr);
|
||||
watch(durationCustom, updateDurationStr, { deep: true });
|
||||
watch(
|
||||
() => props.value,
|
||||
(val) => {
|
||||
if (!val) return;
|
||||
if (tab.value === 'cron') cronStr.value = val;
|
||||
if (tab.value === 'iso') isoStr.value = val;
|
||||
// 自动检测格式:以R开头的是ISO 8601格式,否则是CRON表达式
|
||||
if (val.startsWith('R')) {
|
||||
tab.value = 'iso';
|
||||
isoStr.value = val;
|
||||
// 解析ISO格式:R{repeat}/{date}/{duration}
|
||||
const parts = val.split('/');
|
||||
if (parts[0]) {
|
||||
const repeatMatch = parts[0].match(/^R(\d+)$/);
|
||||
if (repeatMatch) repeat.value = Number.parseInt(repeatMatch[1], 10);
|
||||
}
|
||||
// 解析date部分(ISO 8601日期时间格式)
|
||||
const datePart = parts.find(
|
||||
(p) => p.includes('T') && !p.startsWith('P') && !p.startsWith('R'),
|
||||
);
|
||||
if (datePart) {
|
||||
isoDate.value = dayjs(datePart);
|
||||
}
|
||||
// 解析duration部分
|
||||
const durationPart = parts.find((p) => p.startsWith('P'));
|
||||
if (durationPart) {
|
||||
const match = durationPart.match(
|
||||
/^P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/,
|
||||
);
|
||||
if (match) {
|
||||
durationCustom.value.Y = match[1] || '';
|
||||
durationCustom.value.M = match[2] || '';
|
||||
durationCustom.value.D = match[3] || '';
|
||||
durationCustom.value.H = match[4] || '';
|
||||
durationCustom.value.m = match[5] || '';
|
||||
durationCustom.value.S = match[6] || '';
|
||||
isoDuration.value = durationPart;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tab.value = 'cron';
|
||||
cronStr.value = val;
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
<template>
|
||||
<Tabs v-model:active-key="tab">
|
||||
<Tabs.TabPane key="cron" tab="CRON表达式">
|
||||
<div style="margin-bottom: 10px">
|
||||
<TabPane key="cron" tab="CRON表达式">
|
||||
<div class="mb-2.5">
|
||||
<Input
|
||||
v-model:value="cronStr"
|
||||
readonly
|
||||
style="width: 400px; font-weight: bold"
|
||||
class="w-[400px] font-bold"
|
||||
key="cronStr"
|
||||
/>
|
||||
</div>
|
||||
<div style="display: flex; gap: 8px; margin-bottom: 8px">
|
||||
<div class="mb-2 flex gap-2">
|
||||
<Input
|
||||
v-model:value="fields.second"
|
||||
placeholder="秒"
|
||||
style="width: 80px"
|
||||
class="w-20"
|
||||
key="second"
|
||||
/>
|
||||
<Input
|
||||
v-model:value="fields.minute"
|
||||
placeholder="分"
|
||||
style="width: 80px"
|
||||
class="w-20"
|
||||
key="minute"
|
||||
/>
|
||||
<Input
|
||||
v-model:value="fields.hour"
|
||||
placeholder="时"
|
||||
style="width: 80px"
|
||||
class="w-20"
|
||||
key="hour"
|
||||
/>
|
||||
<Input
|
||||
v-model:value="fields.day"
|
||||
placeholder="天"
|
||||
style="width: 80px"
|
||||
class="w-20"
|
||||
key="day"
|
||||
/>
|
||||
<Input
|
||||
v-model:value="fields.month"
|
||||
placeholder="月"
|
||||
style="width: 80px"
|
||||
class="w-20"
|
||||
key="month"
|
||||
/>
|
||||
<Input
|
||||
v-model:value="fields.week"
|
||||
placeholder="周"
|
||||
style="width: 80px"
|
||||
class="w-20"
|
||||
key="week"
|
||||
/>
|
||||
<Input
|
||||
v-model:value="fields.year"
|
||||
placeholder="年"
|
||||
style="width: 80px"
|
||||
class="w-20"
|
||||
key="year"
|
||||
/>
|
||||
</div>
|
||||
<Tabs
|
||||
v-model:active-key="activeField"
|
||||
type="card"
|
||||
style="margin-bottom: 8px"
|
||||
>
|
||||
<Tabs v-model:active-key="activeField" type="card" class="mb-2">
|
||||
<Tabs.TabPane v-for="f in cronFieldList" :key="f.key" :tab="f.label">
|
||||
<div style="margin-bottom: 8px">
|
||||
<div class="mb-2">
|
||||
<Radio.Group
|
||||
v-model:value="cronMode[f.key]"
|
||||
:key="`radio-${f.key}`"
|
||||
@@ -218,7 +273,7 @@ watch(
|
||||
:min="f.min"
|
||||
:max="f.max"
|
||||
size="small"
|
||||
style="width: 60px"
|
||||
class="w-[60px]"
|
||||
:key="`range0-${f.key}`"
|
||||
/>
|
||||
到
|
||||
@@ -227,7 +282,7 @@ watch(
|
||||
:min="f.min"
|
||||
:max="f.max"
|
||||
size="small"
|
||||
style="width: 60px"
|
||||
class="w-[60px]"
|
||||
:key="`range1-${f.key}`"
|
||||
/>
|
||||
之间每{{ f.label }}
|
||||
@@ -239,7 +294,7 @@ watch(
|
||||
:min="f.min"
|
||||
:max="f.max"
|
||||
size="small"
|
||||
style="width: 60px"
|
||||
class="w-[60px]"
|
||||
:key="`step0-${f.key}`"
|
||||
/>
|
||||
开始每
|
||||
@@ -248,7 +303,7 @@ watch(
|
||||
:min="1"
|
||||
:max="f.max"
|
||||
size="small"
|
||||
style="width: 60px"
|
||||
class="w-[60px]"
|
||||
:key="`step1-${f.key}`"
|
||||
/>
|
||||
{{ f.label }}
|
||||
@@ -272,109 +327,64 @@ watch(
|
||||
</div>
|
||||
</Tabs.TabPane>
|
||||
</Tabs>
|
||||
</Tabs.TabPane>
|
||||
<Tabs.TabPane key="iso" title="标准格式" tab="iso-tab">
|
||||
<div style="margin-bottom: 10px">
|
||||
</TabPane>
|
||||
<TabPane key="iso" tab="标准格式">
|
||||
<div class="mb-2.5">
|
||||
<Input
|
||||
v-model:value="isoStr"
|
||||
placeholder="如R1/2025-05-21T21:59:54/P3DT30M30S"
|
||||
style="width: 400px; font-weight: bold"
|
||||
class="w-[400px] font-bold"
|
||||
key="isoStr"
|
||||
/>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px">
|
||||
<div class="mb-2.5">
|
||||
循环次数:<InputNumber
|
||||
v-model:value="repeat"
|
||||
:min="1"
|
||||
style="width: 100px"
|
||||
class="w-[100px]"
|
||||
key="repeat"
|
||||
/>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px">
|
||||
日期时间:<DatePicker
|
||||
<div class="mb-2.5">
|
||||
开始时间:<DatePicker
|
||||
v-model:value="isoDate"
|
||||
show-time
|
||||
placeholder="选择日期时间"
|
||||
style="width: 200px"
|
||||
placeholder="选择开始时间"
|
||||
class="w-[200px]"
|
||||
key="isoDate"
|
||||
/>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px">
|
||||
当前时长:<Input
|
||||
<div class="mb-2.5">
|
||||
间隔时长:<Input
|
||||
v-model:value="isoDuration"
|
||||
readonly
|
||||
placeholder="如P3DT30M30S"
|
||||
style="width: 200px"
|
||||
class="w-[200px]"
|
||||
key="isoDuration"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
秒:
|
||||
<Button
|
||||
v-for="s in [5, 10, 30, 50]"
|
||||
@click="setDuration('S', s)"
|
||||
:key="`sec-${s}`"
|
||||
>
|
||||
{{ s }}
|
||||
</Button>
|
||||
自定义
|
||||
</div>
|
||||
<div>
|
||||
分:
|
||||
<Button
|
||||
v-for="m in [5, 10, 30, 50]"
|
||||
@click="setDuration('M', m)"
|
||||
:key="`min-${m}`"
|
||||
>
|
||||
{{ m }}
|
||||
</Button>
|
||||
自定义
|
||||
</div>
|
||||
<div>
|
||||
小时:
|
||||
<Button
|
||||
v-for="h in [4, 8, 12, 24]"
|
||||
@click="setDuration('H', h)"
|
||||
:key="`hour-${h}`"
|
||||
>
|
||||
{{ h }}
|
||||
</Button>
|
||||
自定义
|
||||
</div>
|
||||
<div>
|
||||
天:
|
||||
<Button
|
||||
v-for="d in [1, 2, 3, 4]"
|
||||
@click="setDuration('D', d)"
|
||||
:key="`day-${d}`"
|
||||
>
|
||||
{{ d }}
|
||||
</Button>
|
||||
自定义
|
||||
</div>
|
||||
<div>
|
||||
月:
|
||||
<Button
|
||||
v-for="mo in [1, 2, 3, 4]"
|
||||
@click="setDuration('M', mo)"
|
||||
:key="`mon-${mo}`"
|
||||
>
|
||||
{{ mo }}
|
||||
</Button>
|
||||
自定义
|
||||
</div>
|
||||
<div>
|
||||
年:
|
||||
<Button
|
||||
v-for="y in [1, 2, 3, 4]"
|
||||
@click="setDuration('Y', y)"
|
||||
:key="`year-${y}`"
|
||||
>
|
||||
{{ y }}
|
||||
</Button>
|
||||
自定义
|
||||
<div v-for="unit in durationUnits" :key="unit.key" class="mb-2">
|
||||
<span>{{ unit.label }}:</span>
|
||||
<Button.Group>
|
||||
<Button
|
||||
v-for="val in unit.presets"
|
||||
:key="val"
|
||||
size="small"
|
||||
@click="setDuration(unit.key, val)"
|
||||
>
|
||||
{{ val }}
|
||||
</Button>
|
||||
<Input
|
||||
v-model:value="durationCustom[unit.key]"
|
||||
size="small"
|
||||
class="ml-2 w-[60px]"
|
||||
placeholder="自定义"
|
||||
@change="setDuration(unit.key, durationCustom[unit.key])"
|
||||
/>
|
||||
</Button.Group>
|
||||
</div>
|
||||
</div>
|
||||
</Tabs.TabPane>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</template>
|
||||
|
||||
@@ -68,14 +68,10 @@ watch(
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom: 10px">
|
||||
当前选择:<Input
|
||||
v-model:value="isoString"
|
||||
readonly
|
||||
style="width: 300px"
|
||||
/>
|
||||
<div class="mb-2.5">
|
||||
当前选择:<Input v-model:value="isoString" readonly class="w-[300px]" />
|
||||
</div>
|
||||
<div v-for="unit in units" :key="unit.key" style="margin-bottom: 8px">
|
||||
<div v-for="unit in units" :key="unit.key" class="mb-2">
|
||||
<span>{{ unit.label }}:</span>
|
||||
<Button.Group>
|
||||
<Button
|
||||
@@ -89,7 +85,7 @@ watch(
|
||||
<Input
|
||||
v-model:value="custom[unit.key]"
|
||||
size="small"
|
||||
style="width: 60px; margin-left: 8px"
|
||||
class="ml-2 w-[60px]"
|
||||
placeholder="自定义"
|
||||
@change="setUnit(unit.key, custom[unit.key])"
|
||||
/>
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
<script lang="ts" setup>
|
||||
import type { Dayjs } from 'dayjs';
|
||||
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
import { computed, nextTick, onMounted, ref, toRaw, watch } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { Button, DatePicker, Input, Modal, Tooltip } from 'ant-design-vue';
|
||||
import { Button, DatePicker, Input, Tooltip } from 'ant-design-vue';
|
||||
|
||||
import CycleConfig from './CycleConfig.vue';
|
||||
import DurationConfig from './DurationConfig.vue';
|
||||
@@ -20,13 +23,8 @@ const props = defineProps({
|
||||
const bpmnInstances = () => (window as any).bpmnInstances;
|
||||
const type: Ref<string> = ref('time');
|
||||
const condition: Ref<string> = ref('');
|
||||
const valid: Ref<boolean> = ref(true);
|
||||
const showDatePicker: Ref<boolean> = ref(false);
|
||||
const showDurationDialog: Ref<boolean> = ref(false);
|
||||
const showCycleDialog: Ref<boolean> = ref(false);
|
||||
const showHelp: Ref<boolean> = ref(false);
|
||||
const dateValue: Ref<Date | null> = ref(null);
|
||||
// const bpmnElement = ref(null);
|
||||
const valid: Ref<boolean> = ref(false);
|
||||
const dateValue = ref<Dayjs>();
|
||||
|
||||
const placeholder = computed<string>(() => {
|
||||
if (type.value === 'time') return '请输入时间';
|
||||
@@ -49,6 +47,9 @@ const helpHtml = computed<string>(() => {
|
||||
if (type.value === 'cycle') {
|
||||
return `支持CRON表达式(如0 0/30 * * * ?)或ISO 8601周期(如R3/PT10M)。`;
|
||||
}
|
||||
if (type.value === 'time') {
|
||||
return `支持ISO 8601格式的时间(如2024-12-12T12:12:12)`;
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
@@ -82,7 +83,6 @@ function setType(t: string) {
|
||||
// 输入校验
|
||||
watch([type, condition], () => {
|
||||
valid.value = validate();
|
||||
// updateNode() // 可以注释掉,避免频繁触发
|
||||
});
|
||||
|
||||
function validate(): boolean {
|
||||
@@ -93,46 +93,74 @@ function validate(): boolean {
|
||||
return /^P.*$/.test(condition.value);
|
||||
}
|
||||
if (type.value === 'cycle') {
|
||||
return /^(?:[0-9*/?, ]+|R\d*\/P.*)$/.test(condition.value);
|
||||
// 支持CRON表达式或ISO 8601周期格式:R{n}/P... 或 R{n}/{date}/P...
|
||||
return /^(?:[0-9*/?, ]+|R\d+(?:\/[^/]+)*\/P.*)$/.test(condition.value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 选择时间
|
||||
// 选择时间 Modal
|
||||
const [DateModal, dateModalApi] = useVbenModal({
|
||||
title: '选择时间',
|
||||
class: 'w-[400px]',
|
||||
onConfirm: onDateConfirm,
|
||||
});
|
||||
|
||||
function onDateChange(val: any) {
|
||||
dateValue.value = val;
|
||||
dateValue.value = val || undefined;
|
||||
}
|
||||
function onDateConfirm(): void {
|
||||
if (dateValue.value) {
|
||||
condition.value = new Date(dateValue.value).toISOString();
|
||||
showDatePicker.value = false;
|
||||
condition.value = dateValue.value.toISOString();
|
||||
dateModalApi.close();
|
||||
updateNode();
|
||||
}
|
||||
}
|
||||
|
||||
// 持续时长
|
||||
// 持续时长 Modal
|
||||
const [DurationModal, durationModalApi] = useVbenModal({
|
||||
title: '时间配置',
|
||||
class: 'w-[600px]',
|
||||
onConfirm: onDurationConfirm,
|
||||
});
|
||||
|
||||
function onDurationChange(val: string) {
|
||||
condition.value = val;
|
||||
}
|
||||
function onDurationConfirm(): void {
|
||||
showDurationDialog.value = false;
|
||||
durationModalApi.close();
|
||||
updateNode();
|
||||
}
|
||||
|
||||
// 循环
|
||||
// 循环配置 Modal
|
||||
const [CycleModal, cycleModalApi] = useVbenModal({
|
||||
title: '时间配置',
|
||||
class: 'w-[800px]',
|
||||
onConfirm: onCycleConfirm,
|
||||
});
|
||||
|
||||
function onCycleChange(val: string) {
|
||||
condition.value = val;
|
||||
}
|
||||
function onCycleConfirm(): void {
|
||||
showCycleDialog.value = false;
|
||||
cycleModalApi.close();
|
||||
updateNode();
|
||||
}
|
||||
|
||||
// 输入框聚焦时弹窗(可选)
|
||||
function handleInputFocus(): void {
|
||||
if (type.value === 'time') showDatePicker.value = true;
|
||||
if (type.value === 'duration') showDurationDialog.value = true;
|
||||
if (type.value === 'cycle') showCycleDialog.value = true;
|
||||
// 帮助说明 Modal
|
||||
const [HelpModal, helpModalApi] = useVbenModal({
|
||||
class: 'w-[600px]',
|
||||
title: '格式说明',
|
||||
showCancelButton: false,
|
||||
confirmText: '关闭',
|
||||
onConfirm: () => helpModalApi.close(),
|
||||
});
|
||||
|
||||
// 点击输入框时弹窗
|
||||
function handleInputClick(): void {
|
||||
if (type.value === 'time') dateModalApi.open();
|
||||
if (type.value === 'duration') durationModalApi.open();
|
||||
if (type.value === 'cycle') cycleModalApi.open();
|
||||
}
|
||||
|
||||
// 同步到节点
|
||||
@@ -210,8 +238,8 @@ watch(
|
||||
|
||||
<template>
|
||||
<div class="panel-tab__content">
|
||||
<div style="margin-top: 10px">
|
||||
<span>类型:</span>
|
||||
<div class="mt-2 flex items-center">
|
||||
<span class="w-14">类型:</span>
|
||||
<Button.Group>
|
||||
<Button
|
||||
size="small"
|
||||
@@ -238,17 +266,17 @@ watch(
|
||||
<IconifyIcon
|
||||
icon="ant-design:check-circle-filled"
|
||||
v-if="valid"
|
||||
style="margin-left: 8px; color: green"
|
||||
class="ml-2 text-green-500"
|
||||
/>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; margin-top: 10px">
|
||||
<span>条件:</span>
|
||||
<div class="mt-2 flex items-center gap-1">
|
||||
<span class="w-14">条件:</span>
|
||||
<Input
|
||||
v-model:value="condition"
|
||||
:placeholder="placeholder"
|
||||
class="w-[calc(100vw-25%)]"
|
||||
class="w-full"
|
||||
:readonly="type !== 'duration' && type !== 'cycle'"
|
||||
@focus="handleInputFocus"
|
||||
@click="handleInputClick"
|
||||
@blur="updateNode"
|
||||
>
|
||||
<template #suffix>
|
||||
@@ -262,13 +290,13 @@ watch(
|
||||
<IconifyIcon
|
||||
icon="ant-design:question-circle-filled"
|
||||
class="cursor-pointer text-[#409eff]"
|
||||
@click="showHelp = true"
|
||||
@click="helpModalApi.open()"
|
||||
/>
|
||||
</Tooltip>
|
||||
<Button
|
||||
v-if="type === 'time'"
|
||||
@click="showDatePicker = true"
|
||||
style="margin-left: 4px"
|
||||
@click="dateModalApi.open()"
|
||||
class="ml-1 flex items-center justify-center"
|
||||
shape="circle"
|
||||
size="small"
|
||||
>
|
||||
@@ -276,8 +304,8 @@ watch(
|
||||
</Button>
|
||||
<Button
|
||||
v-if="type === 'duration'"
|
||||
@click="showDurationDialog = true"
|
||||
style="margin-left: 4px"
|
||||
@click="durationModalApi.open()"
|
||||
class="ml-1 flex items-center justify-center"
|
||||
shape="circle"
|
||||
size="small"
|
||||
>
|
||||
@@ -285,8 +313,8 @@ watch(
|
||||
</Button>
|
||||
<Button
|
||||
v-if="type === 'cycle'"
|
||||
@click="showCycleDialog = true"
|
||||
style="margin-left: 4px"
|
||||
@click="cycleModalApi.open()"
|
||||
class="ml-1 flex items-center justify-center"
|
||||
shape="circle"
|
||||
size="small"
|
||||
>
|
||||
@@ -295,62 +323,32 @@ watch(
|
||||
</template>
|
||||
</Input>
|
||||
</div>
|
||||
|
||||
<!-- 时间选择器 -->
|
||||
<Modal
|
||||
v-model:open="showDatePicker"
|
||||
title="选择时间"
|
||||
width="400px"
|
||||
@cancel="showDatePicker = false"
|
||||
>
|
||||
<DateModal>
|
||||
<DatePicker
|
||||
v-model:value="dateValue"
|
||||
show-time
|
||||
placeholder="选择日期时间"
|
||||
style="width: 100%"
|
||||
class="w-full"
|
||||
@change="onDateChange"
|
||||
/>
|
||||
<template #footer>
|
||||
<Button @click="showDatePicker = false">取消</Button>
|
||||
<Button type="primary" @click="onDateConfirm">确定</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</DateModal>
|
||||
|
||||
<!-- 持续时长选择器 -->
|
||||
<Modal
|
||||
v-model:open="showDurationDialog"
|
||||
title="时间配置"
|
||||
width="600px"
|
||||
@cancel="showDurationDialog = false"
|
||||
>
|
||||
<DurationModal>
|
||||
<DurationConfig :value="condition" @change="onDurationChange" />
|
||||
<template #footer>
|
||||
<Button @click="showDurationDialog = false">取消</Button>
|
||||
<Button type="primary" @click="onDurationConfirm">确定</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</DurationModal>
|
||||
|
||||
<!-- 循环配置器 -->
|
||||
<Modal
|
||||
v-model:open="showCycleDialog"
|
||||
title="时间配置"
|
||||
width="800px"
|
||||
@cancel="showCycleDialog = false"
|
||||
>
|
||||
<CycleModal>
|
||||
<CycleConfig :value="condition" @change="onCycleChange" />
|
||||
<template #footer>
|
||||
<Button @click="showCycleDialog = false">取消</Button>
|
||||
<Button type="primary" @click="onCycleConfirm">确定</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</CycleModal>
|
||||
|
||||
<!-- 帮助说明 -->
|
||||
<Modal
|
||||
v-model:open="showHelp"
|
||||
title="格式说明"
|
||||
width="600px"
|
||||
@cancel="showHelp = false"
|
||||
>
|
||||
<HelpModal>
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<div v-html="helpHtml"></div>
|
||||
<template #footer>
|
||||
<Button @click="showHelp = false">关闭</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</HelpModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user