mirror of
https://github.com/certd/certd.git
synced 2026-05-15 20:47:31 +08:00
Other translations
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,53 +1,61 @@
|
||||
<template>
|
||||
<fs-page>
|
||||
<template #header>
|
||||
<div class="title flex items-center">
|
||||
站点证书监控
|
||||
<div class="sub flex-1">
|
||||
<div>
|
||||
每天0点,检查网站证书的过期时间,到期前10天时将发出提醒(使用默认通知渠道);
|
||||
<router-link to="/certd/monitor/setting">站点监控设置</router-link>
|
||||
</div>
|
||||
<div class="flex items-center">基础版限制1条,专业版以上无限制,当前<vip-button class="ml-5" mode="nav"></vip-button></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="more">
|
||||
<a-button type="primary" @click="checkAll">检查全部</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
||||
</fs-page>
|
||||
<fs-page>
|
||||
<template #header>
|
||||
<div class="title flex items-center">
|
||||
{{ t("certd.monitor.title") }}
|
||||
<div class="sub flex-1">
|
||||
<div>
|
||||
{{ t("certd.monitor.description") }}
|
||||
<router-link to="/certd/monitor/setting">{{ t("certd.monitor.settingLink") }}</router-link>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
{{ t("certd.monitor.limitInfo") }}
|
||||
<vip-button class="ml-5" mode="nav"></vip-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="more">
|
||||
<a-button type="primary" @click="checkAll">{{ t("certd.monitor.checkAll") }}</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onActivated, onMounted } from "vue";
|
||||
import { useFs } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "./crud";
|
||||
import { siteInfoApi } from "./api";
|
||||
import { Modal, notification } from "ant-design-vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
defineOptions({
|
||||
name: "SiteCertMonitor",
|
||||
name: "SiteCertMonitor",
|
||||
});
|
||||
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: {} });
|
||||
function checkAll() {
|
||||
Modal.confirm({
|
||||
title: "确认",
|
||||
content: "确认触发检查全部站点证书吗?",
|
||||
onOk: async () => {
|
||||
await siteInfoApi.CheckAll();
|
||||
notification.success({
|
||||
message: "检查任务已提交",
|
||||
description: "请稍后刷新页面查看结果",
|
||||
});
|
||||
},
|
||||
});
|
||||
Modal.confirm({
|
||||
title: t("certd.monitor.confirmTitle"), // "确认"
|
||||
content: t("certd.monitor.confirmContent"), // "确认触发检查全部站点证书吗?"
|
||||
onOk: async () => {
|
||||
await siteInfoApi.CheckAll();
|
||||
notification.success({
|
||||
message: t("certd.monitor.checkSubmitted"), // "检查任务已提交"
|
||||
description: t("certd.monitor.pleaseRefresh"), // "请稍后刷新页面查看结果"
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 页面打开后获取列表数据
|
||||
onMounted(() => {
|
||||
crudExpose.doRefresh();
|
||||
crudExpose.doRefresh();
|
||||
});
|
||||
onActivated(() => {
|
||||
crudExpose.doRefresh();
|
||||
crudExpose.doRefresh();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,41 +1,44 @@
|
||||
import { useFormWrapper } from "@fast-crud/fast-crud";
|
||||
import { siteInfoApi } from "./api";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
export function useSiteImport() {
|
||||
const { openCrudFormDialog } = useFormWrapper();
|
||||
const { t } = useI18n();
|
||||
const { openCrudFormDialog } = useFormWrapper();
|
||||
|
||||
async function openSiteImportDialog(opts: { afterSubmit: any }) {
|
||||
const { afterSubmit } = opts;
|
||||
await openCrudFormDialog<any>({
|
||||
crudOptions: {
|
||||
columns: {
|
||||
text: {
|
||||
type: "textarea",
|
||||
title: "域名列表",
|
||||
form: {
|
||||
helper: "格式【域名:端口:名称】,一行一个,其中端口、名称可以省略\n比如:\nwww.baidu.com:443:百度\nwww.taobao.com::淘宝\nwww.google.com",
|
||||
rules: [{ required: true, message: "请输入要导入的域名" }],
|
||||
component: {
|
||||
placeholder: "www.baidu.com:443:百度\nwww.taobao.com::淘宝\nwww.google.com\n",
|
||||
rows: 8,
|
||||
},
|
||||
col: {
|
||||
span: 24,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
form: {
|
||||
async doSubmit({ form }) {
|
||||
return siteInfoApi.Import(form);
|
||||
},
|
||||
afterSubmit,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
async function openSiteImportDialog(opts: { afterSubmit: any }) {
|
||||
const { afterSubmit } = opts;
|
||||
await openCrudFormDialog<any>({
|
||||
crudOptions: {
|
||||
columns: {
|
||||
text: {
|
||||
type: "textarea",
|
||||
title: t("certd.domainList.title"), // 域名列表
|
||||
form: {
|
||||
helper: t("certd.domainList.helper"),
|
||||
rules: [{ required: true, message: t("certd.domainList.required") }],
|
||||
component: {
|
||||
placeholder: t("certd.domainList.placeholder"),
|
||||
rows: 8,
|
||||
},
|
||||
col: {
|
||||
span: 24,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
return {
|
||||
openSiteImportDialog,
|
||||
};
|
||||
form: {
|
||||
async doSubmit({ form }) {
|
||||
return siteInfoApi.Import(form);
|
||||
},
|
||||
afterSubmit,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
openSiteImportDialog,
|
||||
};
|
||||
}
|
||||
|
||||
+87
-93
@@ -1,36 +1,26 @@
|
||||
<template>
|
||||
<div class="notification-selector">
|
||||
<div class="flex-o w-100">
|
||||
<fs-dict-select class="flex-1" :value="modelValue" :dict="optionsDictRef" :disabled="disabled" :render-label="renderLabel" :slots="selectSlots" :allow-clear="true" v-bind="select" @update:value="onChange" />
|
||||
<fs-table-select
|
||||
ref="tableSelectRef"
|
||||
class="flex-0"
|
||||
:model-value="modelValue"
|
||||
:dict="optionsDictRef"
|
||||
:create-crud-options="createCrudOptions"
|
||||
:crud-options-override="{
|
||||
search: { show: false },
|
||||
table: {
|
||||
scroll: {
|
||||
x: 540,
|
||||
},
|
||||
},
|
||||
}"
|
||||
:show-current="false"
|
||||
:show-select="false"
|
||||
:dialog="{ width: 960 }"
|
||||
:destroy-on-close="false"
|
||||
height="400px"
|
||||
v-bind="tableSelect"
|
||||
@update:model-value="onChange"
|
||||
@dialog-closed="doRefresh"
|
||||
>
|
||||
<template #default="scope">
|
||||
<fs-button class="ml-5" :disabled="disabled" :size="size" type="primary" icon="ant-design:edit-outlined" @click="scope.open"></fs-button>
|
||||
</template>
|
||||
</fs-table-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="notification-selector">
|
||||
<div class="flex-o w-100">
|
||||
<fs-dict-select class="flex-1" :value="modelValue" :dict="optionsDictRef" :disabled="disabled"
|
||||
:render-label="renderLabel" :slots="selectSlots" :allow-clear="true" v-bind="select"
|
||||
@update:value="onChange" />
|
||||
<fs-table-select ref="tableSelectRef" class="flex-0" :model-value="modelValue" :dict="optionsDictRef"
|
||||
:create-crud-options="createCrudOptions" :crud-options-override="{
|
||||
search: { show: false },
|
||||
table: {
|
||||
scroll: {
|
||||
x: 540,
|
||||
},
|
||||
},
|
||||
}" :show-current="false" :show-select="false" :dialog="{ width: 960 }" :destroy-on-close="false" height="400px"
|
||||
v-bind="tableSelect" @update:model-value="onChange" @dialog-closed="doRefresh">
|
||||
<template #default="scope">
|
||||
<fs-button class="ml-5" :disabled="disabled" :size="size" type="primary"
|
||||
icon="ant-design:edit-outlined" @click="scope.open"></fs-button>
|
||||
</template>
|
||||
</fs-table-select>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="tsx" setup>
|
||||
@@ -41,23 +31,26 @@ import { dict } from "@fast-crud/fast-crud";
|
||||
import createCrudOptions from "../crud";
|
||||
import { notificationProvide } from "/@/views/certd/notification/common";
|
||||
import { useUserStore } from "/@/store/user";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
defineOptions({
|
||||
name: "NotificationSelector",
|
||||
name: "NotificationSelector",
|
||||
});
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue?: number | string | number[] | string[];
|
||||
type?: string;
|
||||
placeholder?: string;
|
||||
size?: string;
|
||||
disabled?: boolean;
|
||||
select?: any;
|
||||
tableSelect?: any;
|
||||
modelValue?: number | string | number[] | string[];
|
||||
type?: string;
|
||||
placeholder?: string;
|
||||
size?: string;
|
||||
disabled?: boolean;
|
||||
select?: any;
|
||||
tableSelect?: any;
|
||||
}>();
|
||||
|
||||
const onChange = async (value: number) => {
|
||||
await emitValue(value);
|
||||
await emitValue(value);
|
||||
};
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "selectedChange", "change"]);
|
||||
@@ -76,89 +69,90 @@ notificationProvide(api);
|
||||
// loadNotificationTypes();
|
||||
const tableSelectRef = ref();
|
||||
const optionsDictRef = dict({
|
||||
url: "/pi/notification/options",
|
||||
value: "id",
|
||||
label: "name",
|
||||
onReady: ({ dict }) => {
|
||||
const data = [
|
||||
{
|
||||
id: 0,
|
||||
name: "使用默认通知",
|
||||
icon: "ion:notifications",
|
||||
},
|
||||
...dict.data,
|
||||
];
|
||||
dict.setData(data);
|
||||
},
|
||||
url: "/pi/notification/options",
|
||||
value: "id",
|
||||
label: "name",
|
||||
onReady: ({ dict }) => {
|
||||
const data = [
|
||||
{
|
||||
id: 0,
|
||||
name: t("certd.notificationDefault"),
|
||||
icon: "ion:notifications",
|
||||
},
|
||||
...dict.data,
|
||||
];
|
||||
dict.setData(data);
|
||||
},
|
||||
});
|
||||
|
||||
const renderLabel = (option: any) => {
|
||||
return <span>{option.name}</span>;
|
||||
return <span>{option.name}</span>;
|
||||
};
|
||||
|
||||
async function openTableSelectDialog() {
|
||||
selectOpened.value = false;
|
||||
await tableSelectRef.value.open({});
|
||||
await tableSelectRef.value.crudExpose.openAdd({});
|
||||
selectOpened.value = false;
|
||||
await tableSelectRef.value.open({});
|
||||
await tableSelectRef.value.crudExpose.openAdd({});
|
||||
}
|
||||
|
||||
const selectOpened = ref(false);
|
||||
const selectSlots = ref({
|
||||
dropdownRender({ menuNode, props }: any) {
|
||||
const res = [];
|
||||
res.push(menuNode);
|
||||
// res.push(<a-divider style="margin: 4px 0" />);
|
||||
// res.push(<a-space style="padding: 4px 8px" />);
|
||||
// res.push(<fs-button class="w-100" type="text" icon="plus-outlined" text="新建通知渠道" onClick={openTableSelectDialog}></fs-button>);
|
||||
return res;
|
||||
},
|
||||
dropdownRender({ menuNode, props }: any) {
|
||||
const res = [];
|
||||
res.push(menuNode);
|
||||
// res.push(<a-divider style="margin: 4px 0" />);
|
||||
// res.push(<a-space style="padding: 4px 8px" />);
|
||||
// res.push(<fs-button class="w-100" type="text" icon="plus-outlined" text="新建通知渠道" onClick={openTableSelectDialog}></fs-button>);
|
||||
return res;
|
||||
},
|
||||
});
|
||||
|
||||
const target: Ref<any> = ref({});
|
||||
|
||||
function clear() {
|
||||
if (props.disabled) {
|
||||
return;
|
||||
}
|
||||
emitValue(null);
|
||||
if (props.disabled) {
|
||||
return;
|
||||
}
|
||||
emitValue(null);
|
||||
}
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
async function emitValue(value: any) {
|
||||
// target.value = optionsDictRef.dataMap[value];
|
||||
const userId = userStore.userInfo.id;
|
||||
if (pipeline?.value && pipeline.value.userId !== userId) {
|
||||
message.error("对不起,您不能修改他人流水线的通知");
|
||||
return;
|
||||
}
|
||||
emit("change", value);
|
||||
emit("update:modelValue", value);
|
||||
// target.value = optionsDictRef.dataMap[value];
|
||||
const userId = userStore.userInfo.id;
|
||||
if (pipeline?.value && pipeline.value.userId !== userId) {
|
||||
message.error("对不起,您不能修改他人流水线的通知");
|
||||
return;
|
||||
}
|
||||
emit("change", value);
|
||||
emit("update:modelValue", value);
|
||||
}
|
||||
|
||||
watch(
|
||||
() => {
|
||||
return props.modelValue;
|
||||
},
|
||||
async value => {
|
||||
await optionsDictRef.loadDict();
|
||||
//@ts-ignore
|
||||
target.value = optionsDictRef.dataMap[value];
|
||||
emit("selectedChange", target.value);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
() => {
|
||||
return props.modelValue;
|
||||
},
|
||||
async value => {
|
||||
await optionsDictRef.loadDict();
|
||||
//@ts-ignore
|
||||
target.value = optionsDictRef.dataMap[value];
|
||||
emit("selectedChange", target.value);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
//当不在pipeline中编辑时,可能为空
|
||||
const pipeline = inject("pipeline", null);
|
||||
|
||||
async function doRefresh() {
|
||||
await optionsDictRef.reloadDict();
|
||||
await optionsDictRef.reloadDict();
|
||||
}
|
||||
</script>
|
||||
<style lang="less">
|
||||
.notification-selector {
|
||||
width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -11,323 +11,328 @@ import * as api from "../api";
|
||||
import { PluginGroup, usePluginStore } from "/@/store/plugin";
|
||||
import { createNotificationApi } from "/@/views/certd/notification/api";
|
||||
import GroupSelector from "../group/group-selector.vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
|
||||
export function setRunnableIds(pipeline: any) {
|
||||
const idMap: any = {};
|
||||
function createId(oldId: any) {
|
||||
if (oldId == null) {
|
||||
return nanoid();
|
||||
}
|
||||
const newId = nanoid();
|
||||
idMap[oldId] = newId;
|
||||
return newId;
|
||||
}
|
||||
if (pipeline.stages) {
|
||||
for (const stage of pipeline.stages) {
|
||||
stage.id = createId(stage.id);
|
||||
if (stage.tasks) {
|
||||
for (const task of stage.tasks) {
|
||||
task.id = createId(task.id);
|
||||
if (task.steps) {
|
||||
for (const step of task.steps) {
|
||||
step.id = createId(step.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const { t } = useI18n();
|
||||
const idMap: any = {};
|
||||
function createId(oldId: any) {
|
||||
if (oldId == null) {
|
||||
return nanoid();
|
||||
}
|
||||
const newId = nanoid();
|
||||
idMap[oldId] = newId;
|
||||
return newId;
|
||||
}
|
||||
if (pipeline.stages) {
|
||||
for (const stage of pipeline.stages) {
|
||||
stage.id = createId(stage.id);
|
||||
if (stage.tasks) {
|
||||
for (const task of stage.tasks) {
|
||||
task.id = createId(task.id);
|
||||
if (task.steps) {
|
||||
for (const step of task.steps) {
|
||||
step.id = createId(step.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const trigger of pipeline.triggers) {
|
||||
trigger.id = nanoid();
|
||||
}
|
||||
for (const notification of pipeline.notifications) {
|
||||
notification.id = nanoid();
|
||||
}
|
||||
for (const trigger of pipeline.triggers) {
|
||||
trigger.id = nanoid();
|
||||
}
|
||||
for (const notification of pipeline.notifications) {
|
||||
notification.id = nanoid();
|
||||
}
|
||||
|
||||
let content = JSON.stringify(pipeline);
|
||||
for (const key in idMap) {
|
||||
content = content.replaceAll(key, idMap[key]);
|
||||
}
|
||||
return JSON.parse(content);
|
||||
let content = JSON.stringify(pipeline);
|
||||
for (const key in idMap) {
|
||||
content = content.replaceAll(key, idMap[key]);
|
||||
}
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
export function useCertPipelineCreator() {
|
||||
const { openCrudFormDialog } = useFormWrapper();
|
||||
const { t } = useI18n();
|
||||
const { openCrudFormDialog } = useFormWrapper();
|
||||
|
||||
const pluginStore = usePluginStore();
|
||||
const router = useRouter();
|
||||
const pluginStore = usePluginStore();
|
||||
const router = useRouter();
|
||||
|
||||
function createCrudOptions(certPlugins: any[], getFormData: any, doSubmit: any): CreateCrudOptionsRet {
|
||||
const inputs: any = {};
|
||||
const moreParams = [];
|
||||
for (const plugin of certPlugins) {
|
||||
for (const inputKey in plugin.input) {
|
||||
if (inputs[inputKey]) {
|
||||
//如果两个插件有的字段,直接显示
|
||||
inputs[inputKey].form.show = true;
|
||||
continue;
|
||||
}
|
||||
const inputDefine = cloneDeep(plugin.input[inputKey]);
|
||||
if (!inputDefine.required && !inputDefine.maybeNeed) {
|
||||
moreParams.push(inputKey);
|
||||
// continue;
|
||||
}
|
||||
useReference(inputDefine);
|
||||
inputs[inputKey] = {
|
||||
title: inputDefine.title,
|
||||
form: {
|
||||
...inputDefine,
|
||||
show: compute(ctx => {
|
||||
const form = getFormData();
|
||||
if (!form) {
|
||||
return false;
|
||||
}
|
||||
function createCrudOptions(certPlugins: any[], getFormData: any, doSubmit: any): CreateCrudOptionsRet {
|
||||
const inputs: any = {};
|
||||
const moreParams = [];
|
||||
for (const plugin of certPlugins) {
|
||||
for (const inputKey in plugin.input) {
|
||||
if (inputs[inputKey]) {
|
||||
//如果两个插件有的字段,直接显示
|
||||
inputs[inputKey].form.show = true;
|
||||
continue;
|
||||
}
|
||||
const inputDefine = cloneDeep(plugin.input[inputKey]);
|
||||
if (!inputDefine.required && !inputDefine.maybeNeed) {
|
||||
moreParams.push(inputKey);
|
||||
// continue;
|
||||
}
|
||||
useReference(inputDefine);
|
||||
inputs[inputKey] = {
|
||||
title: inputDefine.title,
|
||||
form: {
|
||||
...inputDefine,
|
||||
show: compute(ctx => {
|
||||
const form = getFormData();
|
||||
if (!form) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let inputDefineShow = true;
|
||||
if (inputDefine.show != null) {
|
||||
const computeShow = inputDefine.show as any;
|
||||
if (computeShow === false) {
|
||||
inputDefineShow = false;
|
||||
} else if (computeShow && computeShow.computeFn) {
|
||||
inputDefineShow = computeShow.computeFn({ form });
|
||||
}
|
||||
}
|
||||
return form?.certApplyPlugin === plugin.name && inputDefineShow;
|
||||
}),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
let inputDefineShow = true;
|
||||
if (inputDefine.show != null) {
|
||||
const computeShow = inputDefine.show as any;
|
||||
if (computeShow === false) {
|
||||
inputDefineShow = false;
|
||||
} else if (computeShow && computeShow.computeFn) {
|
||||
inputDefineShow = computeShow.computeFn({ form });
|
||||
}
|
||||
}
|
||||
return form?.certApplyPlugin === plugin.name && inputDefineShow;
|
||||
}),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const pluginStore = usePluginStore();
|
||||
const randomHour = Math.floor(Math.random() * 6);
|
||||
const randomMin = Math.floor(Math.random() * 60);
|
||||
const pluginStore = usePluginStore();
|
||||
const randomHour = Math.floor(Math.random() * 6);
|
||||
const randomMin = Math.floor(Math.random() * 60);
|
||||
|
||||
const groupDictRef = dict({
|
||||
url: "/pi/pipeline/group/all",
|
||||
value: "id",
|
||||
label: "name",
|
||||
});
|
||||
const groupDictRef = dict({
|
||||
url: "/pi/pipeline/group/all",
|
||||
value: "id",
|
||||
label: "name",
|
||||
});
|
||||
|
||||
return {
|
||||
crudOptions: {
|
||||
form: {
|
||||
doSubmit,
|
||||
wrapper: {
|
||||
width: 1350,
|
||||
saveRemind: false,
|
||||
title: "创建证书流水线",
|
||||
},
|
||||
group: {
|
||||
groups: {
|
||||
more: {
|
||||
header: "更多参数",
|
||||
columns: moreParams,
|
||||
collapsed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
columns: {
|
||||
certApplyPlugin: {
|
||||
title: "证书申请插件",
|
||||
type: "dict-select",
|
||||
dict: dict({
|
||||
data: [
|
||||
{ value: "CertApply", label: "JS-ACME" },
|
||||
{ value: "CertApplyLego", label: "Lego-ACME" },
|
||||
],
|
||||
}),
|
||||
form: {
|
||||
order: 0,
|
||||
value: "CertApply",
|
||||
helper: {
|
||||
render: () => {
|
||||
return (
|
||||
<ul>
|
||||
<li>JS-ACME:使用简单方便,功能强大【推荐】</li>
|
||||
<li>Lego-ACME:基于Lego实现,支持海量DNS提供商,熟悉LEGO的用户可以使用</li>
|
||||
</ul>
|
||||
);
|
||||
},
|
||||
},
|
||||
valueChange: {
|
||||
handle: async ({ form, value }) => {
|
||||
const config = await pluginStore.getPluginConfig({
|
||||
name: value,
|
||||
type: "builtIn",
|
||||
});
|
||||
if (config.sysSetting?.input) {
|
||||
merge(form, config.sysSetting.input);
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
...inputs,
|
||||
triggerCron: {
|
||||
title: "定时触发",
|
||||
type: "text",
|
||||
form: {
|
||||
value: `0 ${randomMin} ${randomHour} * * *`,
|
||||
component: {
|
||||
name: "cron-editor",
|
||||
vModel: "modelValue",
|
||||
placeholder: "0 0 4 * * *",
|
||||
},
|
||||
helper: "点击上面的按钮,选择每天几点定时执行。\n建议设置为每天触发一次,证书未到期之前任务会跳过,不会重复执行",
|
||||
order: 100,
|
||||
},
|
||||
},
|
||||
notification: {
|
||||
title: "失败通知",
|
||||
type: "text",
|
||||
form: {
|
||||
value: 0,
|
||||
component: {
|
||||
name: NotificationSelector,
|
||||
vModel: "modelValue",
|
||||
on: {
|
||||
selectedChange({ $event, form }) {
|
||||
form.notificationTarget = $event;
|
||||
},
|
||||
},
|
||||
},
|
||||
order: 101,
|
||||
helper: "任务执行失败实时提醒",
|
||||
},
|
||||
},
|
||||
groupId: {
|
||||
title: "流水线分组",
|
||||
type: "dict-select",
|
||||
dict: groupDictRef,
|
||||
form: {
|
||||
component: {
|
||||
name: GroupSelector,
|
||||
vModel: "modelValue",
|
||||
},
|
||||
order: 9999,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
crudOptions: {
|
||||
form: {
|
||||
doSubmit,
|
||||
wrapper: {
|
||||
width: 1350,
|
||||
saveRemind: false,
|
||||
title: t("certd.pipelineForm.createTitle"),
|
||||
},
|
||||
group: {
|
||||
groups: {
|
||||
more: {
|
||||
header: t("certd.pipelineForm.moreParams"),
|
||||
columns: moreParams,
|
||||
collapsed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
columns: {
|
||||
certApplyPlugin: {
|
||||
title: t("certd.plugin.selectTitle"),
|
||||
type: "dict-select",
|
||||
dict: dict({
|
||||
data: [
|
||||
{ value: "CertApply", label: "JS-ACME" },
|
||||
{ value: "CertApplyLego", label: "Lego-ACME" },
|
||||
],
|
||||
}),
|
||||
form: {
|
||||
order: 0,
|
||||
value: "CertApply",
|
||||
helper: {
|
||||
render: () => {
|
||||
return (
|
||||
<ul>
|
||||
<li>{t("certd.plugin.jsAcme")}</li>
|
||||
<li>{t("certd.plugin.legoAcme")}</li>
|
||||
</ul>
|
||||
);
|
||||
},
|
||||
},
|
||||
valueChange: {
|
||||
handle: async ({ form, value }) => {
|
||||
const config = await pluginStore.getPluginConfig({
|
||||
name: value,
|
||||
type: "builtIn",
|
||||
});
|
||||
if (config.sysSetting?.input) {
|
||||
merge(form, config.sysSetting.input);
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
...inputs,
|
||||
triggerCron: {
|
||||
title: t("certd.pipelineForm.triggerCronTitle"),
|
||||
type: "text",
|
||||
form: {
|
||||
value: `0 ${randomMin} ${randomHour} * * *`,
|
||||
component: {
|
||||
name: "cron-editor",
|
||||
vModel: "modelValue",
|
||||
placeholder: "0 0 4 * * *",
|
||||
},
|
||||
helper: t("certd.pipelineForm.triggerCronHelper"),
|
||||
order: 100,
|
||||
},
|
||||
},
|
||||
notification: {
|
||||
title: t("certd.pipelineForm.notificationTitle"),
|
||||
type: "text",
|
||||
form: {
|
||||
value: 0,
|
||||
component: {
|
||||
name: NotificationSelector,
|
||||
vModel: "modelValue",
|
||||
on: {
|
||||
selectedChange({ $event, form }) {
|
||||
form.notificationTarget = $event;
|
||||
},
|
||||
},
|
||||
},
|
||||
order: 101,
|
||||
helper: t("certd.pipelineForm.notificationHelper"),
|
||||
},
|
||||
},
|
||||
groupId: {
|
||||
title: t("certd.pipelineForm.groupIdTitle"),
|
||||
type: "dict-select",
|
||||
dict: groupDictRef,
|
||||
form: {
|
||||
component: {
|
||||
name: GroupSelector,
|
||||
vModel: "modelValue",
|
||||
},
|
||||
order: 9999,
|
||||
},
|
||||
}
|
||||
|
||||
async function getCertPlugins() {
|
||||
const pluginGroup = await pluginStore.getGroups();
|
||||
const pluginGroups: { [key: string]: PluginGroup } = pluginGroup.groups;
|
||||
const certPluginGroup = pluginGroups.cert;
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const certPlugins = [];
|
||||
for (const plugin of certPluginGroup.plugins) {
|
||||
const detail: any = await pluginStore.getPluginDefine(plugin.name);
|
||||
certPlugins.push(detail);
|
||||
}
|
||||
return certPlugins;
|
||||
}
|
||||
async function getCertPlugins() {
|
||||
const pluginGroup = await pluginStore.getGroups();
|
||||
const pluginGroups: { [key: string]: PluginGroup } = pluginGroup.groups;
|
||||
const certPluginGroup = pluginGroups.cert;
|
||||
|
||||
async function openAddCertdPipelineDialog(req: { defaultGroupId?: number }) {
|
||||
//检查是否流水线数量超出限制
|
||||
await checkPipelineLimit();
|
||||
const certPlugins = [];
|
||||
for (const plugin of certPluginGroup.plugins) {
|
||||
const detail: any = await pluginStore.getPluginDefine(plugin.name);
|
||||
certPlugins.push(detail);
|
||||
}
|
||||
return certPlugins;
|
||||
}
|
||||
|
||||
const wrapperRef = ref();
|
||||
function getFormData() {
|
||||
if (!wrapperRef.value) {
|
||||
return null;
|
||||
}
|
||||
return wrapperRef.value.getFormData();
|
||||
}
|
||||
async function openAddCertdPipelineDialog(req: { defaultGroupId?: number }) {
|
||||
//检查是否流水线数量超出限制
|
||||
await checkPipelineLimit();
|
||||
|
||||
async function doSubmit({ form }: any) {
|
||||
// const certDetail = readCertDetail(form.cert.crt);
|
||||
// 添加certd pipeline
|
||||
const triggers = [];
|
||||
if (form.triggerCron) {
|
||||
triggers.push({ title: "定时触发", type: "timer", props: { cron: form.triggerCron } });
|
||||
}
|
||||
const notifications = [];
|
||||
if (form.notification != null) {
|
||||
notifications.push({
|
||||
type: "custom",
|
||||
when: ["error", "turnToSuccess", "success"],
|
||||
notificationId: form.notification,
|
||||
title: form.notificationTarget?.name || "自定义通知",
|
||||
});
|
||||
}
|
||||
const pluginInput = omit(form, ["triggerCron", "notification", "notificationTarget", "certApplyPlugin", "groupId"]);
|
||||
let pipeline = {
|
||||
title: form.domains[0] + "证书自动化",
|
||||
runnableType: "pipeline",
|
||||
stages: [
|
||||
{
|
||||
title: "证书申请阶段",
|
||||
maxTaskCount: 1,
|
||||
runnableType: "stage",
|
||||
tasks: [
|
||||
{
|
||||
title: "证书申请任务",
|
||||
runnableType: "task",
|
||||
steps: [
|
||||
{
|
||||
title: "申请证书",
|
||||
runnableType: "step",
|
||||
input: {
|
||||
renewDays: 35,
|
||||
...pluginInput,
|
||||
},
|
||||
strategy: {
|
||||
runStrategy: 0, // 正常执行
|
||||
},
|
||||
type: form.certApplyPlugin,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
triggers,
|
||||
notifications,
|
||||
};
|
||||
pipeline = setRunnableIds(pipeline);
|
||||
const wrapperRef = ref();
|
||||
function getFormData() {
|
||||
if (!wrapperRef.value) {
|
||||
return null;
|
||||
}
|
||||
return wrapperRef.value.getFormData();
|
||||
}
|
||||
|
||||
/**
|
||||
* // cert: 证书; backup: 备份; custom:自定义;
|
||||
* type: string;
|
||||
* // custom: 自定义; monitor: 监控;
|
||||
* from: string;
|
||||
*/
|
||||
const groupId = form.groupId;
|
||||
const id = await api.Save({
|
||||
title: pipeline.title,
|
||||
content: JSON.stringify(pipeline),
|
||||
keepHistoryCount: 30,
|
||||
type: "cert",
|
||||
groupId,
|
||||
});
|
||||
if (form.email) {
|
||||
try {
|
||||
//创建一个默认的邮件通知
|
||||
const notificationApi = createNotificationApi();
|
||||
await notificationApi.GetOrCreateDefault({ email: form.email });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
message.success("创建成功,请添加证书部署任务");
|
||||
router.push({ path: "/certd/pipeline/detail", query: { id, editMode: "true" } });
|
||||
}
|
||||
const certPlugins = await getCertPlugins();
|
||||
const { crudOptions } = createCrudOptions(certPlugins, getFormData, doSubmit);
|
||||
//@ts-ignore
|
||||
crudOptions.columns.groupId.form.value = req.defaultGroupId || undefined;
|
||||
const wrapper = await openCrudFormDialog({ crudOptions });
|
||||
wrapperRef.value = wrapper;
|
||||
}
|
||||
async function doSubmit({ form }: any) {
|
||||
// const certDetail = readCertDetail(form.cert.crt);
|
||||
// 添加certd pipeline
|
||||
const triggers = [];
|
||||
if (form.triggerCron) {
|
||||
triggers.push({ title: "定时触发", type: "timer", props: { cron: form.triggerCron } });
|
||||
}
|
||||
const notifications = [];
|
||||
if (form.notification != null) {
|
||||
notifications.push({
|
||||
type: "custom",
|
||||
when: ["error", "turnToSuccess", "success"],
|
||||
notificationId: form.notification,
|
||||
title: form.notificationTarget?.name || "自定义通知",
|
||||
});
|
||||
}
|
||||
const pluginInput = omit(form, ["triggerCron", "notification", "notificationTarget", "certApplyPlugin", "groupId"]);
|
||||
let pipeline = {
|
||||
title: form.domains[0] + "证书自动化",
|
||||
runnableType: "pipeline",
|
||||
stages: [
|
||||
{
|
||||
title: "证书申请阶段",
|
||||
maxTaskCount: 1,
|
||||
runnableType: "stage",
|
||||
tasks: [
|
||||
{
|
||||
title: "证书申请任务",
|
||||
runnableType: "task",
|
||||
steps: [
|
||||
{
|
||||
title: "申请证书",
|
||||
runnableType: "step",
|
||||
input: {
|
||||
renewDays: 35,
|
||||
...pluginInput,
|
||||
},
|
||||
strategy: {
|
||||
runStrategy: 0, // 正常执行
|
||||
},
|
||||
type: form.certApplyPlugin,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
triggers,
|
||||
notifications,
|
||||
};
|
||||
pipeline = setRunnableIds(pipeline);
|
||||
|
||||
return {
|
||||
openAddCertdPipelineDialog,
|
||||
};
|
||||
/**
|
||||
* // cert: 证书; backup: 备份; custom:自定义;
|
||||
* type: string;
|
||||
* // custom: 自定义; monitor: 监控;
|
||||
* from: string;
|
||||
*/
|
||||
const groupId = form.groupId;
|
||||
const id = await api.Save({
|
||||
title: pipeline.title,
|
||||
content: JSON.stringify(pipeline),
|
||||
keepHistoryCount: 30,
|
||||
type: "cert",
|
||||
groupId,
|
||||
});
|
||||
if (form.email) {
|
||||
try {
|
||||
//创建一个默认的邮件通知
|
||||
const notificationApi = createNotificationApi();
|
||||
await notificationApi.GetOrCreateDefault({ email: form.email });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
message.success("创建成功,请添加证书部署任务");
|
||||
router.push({ path: "/certd/pipeline/detail", query: { id, editMode: "true" } });
|
||||
}
|
||||
const certPlugins = await getCertPlugins();
|
||||
const { crudOptions } = createCrudOptions(certPlugins, getFormData, doSubmit);
|
||||
//@ts-ignore
|
||||
crudOptions.columns.groupId.form.value = req.defaultGroupId || undefined;
|
||||
const wrapper = await openCrudFormDialog({ crudOptions });
|
||||
wrapperRef.value = wrapper;
|
||||
}
|
||||
|
||||
return {
|
||||
openAddCertdPipelineDialog,
|
||||
};
|
||||
}
|
||||
|
||||
+40
-39
@@ -1,36 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<fs-form-item
|
||||
v-model="optionsFormState.receivers"
|
||||
:item="{
|
||||
title: '收件邮箱',
|
||||
key: 'type',
|
||||
component: {
|
||||
name: 'a-select',
|
||||
vModel: 'value',
|
||||
mode: 'tags',
|
||||
open: false
|
||||
},
|
||||
helper: '输入你的收件邮箱地址,支持多个邮箱',
|
||||
rules: [{ required: true, message: '此项必填' }]
|
||||
}"
|
||||
/>
|
||||
<div>
|
||||
<fs-form-item v-model="optionsFormState.receivers" :item="{
|
||||
title: t('certd.email.title'),
|
||||
key: 'type',
|
||||
component: {
|
||||
name: 'a-select',
|
||||
vModel: 'value',
|
||||
mode: 'tags',
|
||||
open: false
|
||||
},
|
||||
helper: t('certd.email.helper'),
|
||||
rules: [{ required: true, message: t('certd.email.required') }]
|
||||
}" />
|
||||
|
||||
<a-alert v-if="!settingStore.isPlus" class="m-1" type="info">
|
||||
<template #message> 还没有配置邮件服务器?<router-link :to="{ path: '/sys/settings/email' }">现在就去</router-link> </template>
|
||||
</a-alert>
|
||||
</div>
|
||||
<a-alert v-if="!settingStore.isPlus" class="m-1" type="info">
|
||||
<template #message> 还没有配置邮件服务器?<router-link :to="{ path: '/sys/settings/email' }">现在就去</router-link>
|
||||
</template>
|
||||
</a-alert>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { Ref, ref, watch } from "vue";
|
||||
import { useUserStore } from "/@/store/user";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = defineProps({
|
||||
options: {
|
||||
type: Object as PropType<any>,
|
||||
default: () => {}
|
||||
}
|
||||
options: {
|
||||
type: Object as PropType<any>,
|
||||
default: () => { }
|
||||
}
|
||||
});
|
||||
|
||||
const settingStore = useSettingStore();
|
||||
@@ -38,30 +39,30 @@ const settingStore = useSettingStore();
|
||||
const optionsFormState: Ref<any> = ref({});
|
||||
|
||||
watch(
|
||||
() => {
|
||||
return props.options;
|
||||
},
|
||||
() => {
|
||||
optionsFormState.value = {
|
||||
...props.options
|
||||
};
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
() => {
|
||||
return props.options;
|
||||
},
|
||||
() => {
|
||||
optionsFormState.value = {
|
||||
...props.options
|
||||
};
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
);
|
||||
|
||||
const emit = defineEmits(["change"]);
|
||||
function doEmit() {
|
||||
emit("change", { ...optionsFormState.value });
|
||||
emit("change", { ...optionsFormState.value });
|
||||
}
|
||||
|
||||
function getValue() {
|
||||
return { ...optionsFormState.value };
|
||||
return { ...optionsFormState.value };
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
doEmit,
|
||||
getValue
|
||||
doEmit,
|
||||
getValue
|
||||
});
|
||||
</script>
|
||||
|
||||
+163
-169
@@ -1,70 +1,65 @@
|
||||
<template>
|
||||
<a-drawer v-model:open="triggerDrawerVisible" placement="right" :closable="true" width="650px" class="pi-trigger-form" @after-open-change="triggerDrawerOnAfterVisibleChange">
|
||||
<template #title>
|
||||
<div>
|
||||
编辑触发器
|
||||
<a-button v-if="mode === 'edit'" @click="triggerDelete()">
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="currentTrigger">
|
||||
<pi-container>
|
||||
<a-form ref="triggerFormRef" class="trigger-form" :model="currentTrigger" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<fs-form-item
|
||||
v-model="currentTrigger.title"
|
||||
:item="{
|
||||
title: '触发器名称',
|
||||
key: 'title',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
disabled: !editMode,
|
||||
},
|
||||
rules: [{ required: true, message: '此项必填' }],
|
||||
}"
|
||||
/>
|
||||
<a-drawer v-model:open="triggerDrawerVisible" placement="right" :closable="true" width="650px"
|
||||
class="pi-trigger-form" @after-open-change="triggerDrawerOnAfterVisibleChange">
|
||||
<template #title>
|
||||
<div>
|
||||
编辑触发器
|
||||
<a-button v-if="mode === 'edit'" @click="triggerDelete()">
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="currentTrigger">
|
||||
<pi-container>
|
||||
<a-form ref="triggerFormRef" class="trigger-form" :model="currentTrigger" :label-col="labelCol"
|
||||
:wrapper-col="wrapperCol">
|
||||
<fs-form-item v-model="currentTrigger.title" :item="{
|
||||
title: '触发器名称',
|
||||
key: 'title',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
disabled: !editMode,
|
||||
},
|
||||
rules: [{ required: true, message: '此项必填' }],
|
||||
}" />
|
||||
|
||||
<fs-form-item
|
||||
v-model="currentTrigger.type"
|
||||
:item="{
|
||||
title: '类型',
|
||||
key: 'type',
|
||||
value: 'timer',
|
||||
component: {
|
||||
name: 'a-select',
|
||||
vModel: 'value',
|
||||
disabled: !editMode,
|
||||
options: [{ value: 'timer', label: '定时' }],
|
||||
},
|
||||
rules: [{ required: true, message: '此项必填' }],
|
||||
}"
|
||||
/>
|
||||
<fs-form-item v-model="currentTrigger.type" :item="{
|
||||
title: '类型',
|
||||
key: 'type',
|
||||
value: 'timer',
|
||||
component: {
|
||||
name: 'a-select',
|
||||
vModel: 'value',
|
||||
disabled: !editMode,
|
||||
options: [{ value: 'timer', label: '定时' }],
|
||||
},
|
||||
rules: [{ required: true, message: '此项必填' }],
|
||||
}" />
|
||||
|
||||
<fs-form-item
|
||||
v-model="currentTrigger.props.cron"
|
||||
:item="{
|
||||
title: '定时脚本',
|
||||
key: 'props.cron',
|
||||
component: {
|
||||
disabled: !editMode,
|
||||
name: 'cron-editor',
|
||||
vModel: 'modelValue',
|
||||
},
|
||||
helper: '点击上面的按钮,选择每天几点定时执行。\n建议设置为每天触发一次,证书未到期之前任务会跳过,不会重复执行',
|
||||
rules: [{ required: true, message: '此项必填' }],
|
||||
}"
|
||||
/>
|
||||
</a-form>
|
||||
<fs-form-item v-model="currentTrigger.props.cron" :item="{
|
||||
title: t('certd.cronForm.title'),
|
||||
key: 'props.cron',
|
||||
component: {
|
||||
disabled: !editMode,
|
||||
name: 'cron-editor',
|
||||
vModel: 'modelValue',
|
||||
},
|
||||
helper: t('certd.cronForm.helper'),
|
||||
rules: [{ required: true, message: t('certd.cronForm.required') }],
|
||||
}" />
|
||||
</a-form>
|
||||
|
||||
<template #footer>
|
||||
<a-form-item v-if="editMode" :wrapper-col="{ span: 14, offset: 4 }">
|
||||
<a-button type="primary" @click="triggerSave"> 确定 </a-button>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</pi-container>
|
||||
</template>
|
||||
</a-drawer>
|
||||
<template #footer>
|
||||
<a-form-item v-if="editMode" :wrapper-col="{ span: 14, offset: 4 }">
|
||||
<a-button type="primary" @click="triggerSave"> 确定 </a-button>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</pi-container>
|
||||
</template>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -73,125 +68,124 @@ import { inject, ref } from "vue";
|
||||
import * as _ from "lodash-es";
|
||||
import { nanoid } from "nanoid";
|
||||
export default {
|
||||
name: "PiTriggerForm",
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
emits: ["update"],
|
||||
setup(props, context) {
|
||||
/**
|
||||
* trigger drawer
|
||||
* @returns
|
||||
*/
|
||||
function useTriggerForm() {
|
||||
const mode = ref("add");
|
||||
const callback = ref();
|
||||
const currentTrigger = ref({ title: undefined, input: {} });
|
||||
const currentPlugin = ref({});
|
||||
const triggerFormRef = ref(null);
|
||||
const triggerDrawerVisible = ref(false);
|
||||
const rules = ref({
|
||||
name: [
|
||||
{
|
||||
type: "string",
|
||||
required: true,
|
||||
message: "请输入名称",
|
||||
},
|
||||
],
|
||||
});
|
||||
name: "PiTriggerForm",
|
||||
props: {
|
||||
editMode: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
emits: ["update"],
|
||||
setup(props, context) {
|
||||
/**
|
||||
* trigger drawer
|
||||
* @returns
|
||||
*/
|
||||
function useTriggerForm() {
|
||||
const mode = ref("add");
|
||||
const callback = ref();
|
||||
const currentTrigger = ref({ title: undefined, input: {} });
|
||||
const currentPlugin = ref({});
|
||||
const triggerFormRef = ref(null);
|
||||
const triggerDrawerVisible = ref(false);
|
||||
const rules = ref({
|
||||
name: [
|
||||
{
|
||||
type: "string",
|
||||
required: true,
|
||||
message: "请输入名称",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const triggerDrawerShow = () => {
|
||||
triggerDrawerVisible.value = true;
|
||||
};
|
||||
const triggerDrawerClose = () => {
|
||||
triggerDrawerVisible.value = false;
|
||||
};
|
||||
const triggerDrawerShow = () => {
|
||||
triggerDrawerVisible.value = true;
|
||||
};
|
||||
const triggerDrawerClose = () => {
|
||||
triggerDrawerVisible.value = false;
|
||||
};
|
||||
|
||||
const triggerDrawerOnAfterVisibleChange = val => {
|
||||
console.log("triggerDrawerOnAfterVisibleChange", val);
|
||||
};
|
||||
const triggerDrawerOnAfterVisibleChange = val => {
|
||||
console.log("triggerDrawerOnAfterVisibleChange", val);
|
||||
};
|
||||
|
||||
const triggerOpen = (trigger, emit) => {
|
||||
callback.value = emit;
|
||||
currentTrigger.value = _.cloneDeep(trigger);
|
||||
console.log("currentTriggerOpen", currentTrigger.value);
|
||||
triggerDrawerShow();
|
||||
};
|
||||
const triggerOpen = (trigger, emit) => {
|
||||
callback.value = emit;
|
||||
currentTrigger.value = _.cloneDeep(trigger);
|
||||
console.log("currentTriggerOpen", currentTrigger.value);
|
||||
triggerDrawerShow();
|
||||
};
|
||||
|
||||
const triggerAdd = emit => {
|
||||
mode.value = "add";
|
||||
const trigger = { id: nanoid(), title: "定时触发", type: "timer", props: {} };
|
||||
triggerOpen(trigger, emit);
|
||||
};
|
||||
const triggerAdd = emit => {
|
||||
mode.value = "add";
|
||||
const trigger = { id: nanoid(), title: "定时触发", type: "timer", props: {} };
|
||||
triggerOpen(trigger, emit);
|
||||
};
|
||||
|
||||
const triggerEdit = (trigger, emit) => {
|
||||
mode.value = "edit";
|
||||
triggerOpen(trigger, emit);
|
||||
};
|
||||
const triggerEdit = (trigger, emit) => {
|
||||
mode.value = "edit";
|
||||
triggerOpen(trigger, emit);
|
||||
};
|
||||
|
||||
const triggerView = (trigger, emit) => {
|
||||
mode.value = "view";
|
||||
triggerOpen(trigger, emit);
|
||||
};
|
||||
const triggerView = (trigger, emit) => {
|
||||
mode.value = "view";
|
||||
triggerOpen(trigger, emit);
|
||||
};
|
||||
|
||||
const triggerSave = async e => {
|
||||
console.log("currentTriggerSave", currentTrigger.value);
|
||||
try {
|
||||
await triggerFormRef.value.validate();
|
||||
} catch (e) {
|
||||
console.error("表单验证失败:", e);
|
||||
return;
|
||||
}
|
||||
const triggerSave = async e => {
|
||||
console.log("currentTriggerSave", currentTrigger.value);
|
||||
try {
|
||||
await triggerFormRef.value.validate();
|
||||
} catch (e) {
|
||||
console.error("表单验证失败:", e);
|
||||
return;
|
||||
}
|
||||
|
||||
callback.value("save", currentTrigger.value);
|
||||
triggerDrawerClose();
|
||||
};
|
||||
callback.value("save", currentTrigger.value);
|
||||
triggerDrawerClose();
|
||||
};
|
||||
|
||||
const triggerDelete = () => {
|
||||
Modal.confirm({
|
||||
title: "确认",
|
||||
content: `确定要删除此触发器吗?`,
|
||||
async onOk() {
|
||||
callback.value("delete");
|
||||
triggerDrawerClose();
|
||||
},
|
||||
});
|
||||
};
|
||||
const triggerDelete = () => {
|
||||
Modal.confirm({
|
||||
title: "确认",
|
||||
content: `确定要删除此触发器吗?`,
|
||||
async onOk() {
|
||||
callback.value("delete");
|
||||
triggerDrawerClose();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const blankFn = () => {
|
||||
return {};
|
||||
};
|
||||
return {
|
||||
triggerFormRef,
|
||||
mode,
|
||||
triggerAdd,
|
||||
triggerEdit,
|
||||
triggerView,
|
||||
triggerDrawerShow,
|
||||
triggerDrawerVisible,
|
||||
triggerDrawerOnAfterVisibleChange,
|
||||
currentTrigger,
|
||||
currentPlugin,
|
||||
triggerSave,
|
||||
triggerDelete,
|
||||
rules,
|
||||
blankFn,
|
||||
};
|
||||
}
|
||||
const blankFn = () => {
|
||||
return {};
|
||||
};
|
||||
return {
|
||||
triggerFormRef,
|
||||
mode,
|
||||
triggerAdd,
|
||||
triggerEdit,
|
||||
triggerView,
|
||||
triggerDrawerShow,
|
||||
triggerDrawerVisible,
|
||||
triggerDrawerOnAfterVisibleChange,
|
||||
currentTrigger,
|
||||
currentPlugin,
|
||||
triggerSave,
|
||||
triggerDelete,
|
||||
rules,
|
||||
blankFn,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...useTriggerForm(),
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
},
|
||||
return {
|
||||
...useTriggerForm(),
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.pi-trigger-form {
|
||||
}
|
||||
.pi-trigger-form {}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user