mirror of https://github.com/certd/certd
perf: 支持批量修改通知和定时
parent
73fa937f5c
commit
e11b3becfd
|
@ -52,7 +52,9 @@ export type Stage = Runnable & {
|
||||||
export type Trigger = {
|
export type Trigger = {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
cron: string;
|
props: {
|
||||||
|
cron: string;
|
||||||
|
};
|
||||||
type: string;
|
type: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,14 +80,13 @@ export type EmailOptions = {
|
||||||
receivers: string[];
|
receivers: string[];
|
||||||
};
|
};
|
||||||
export type NotificationWhen = "error" | "success" | "turnToSuccess" | "start";
|
export type NotificationWhen = "error" | "success" | "turnToSuccess" | "start";
|
||||||
export type NotificationType = "email" | "url";
|
export type NotificationType = "email" | "other";
|
||||||
export type Notification = {
|
export type Notification = {
|
||||||
type: NotificationType;
|
type: NotificationType;
|
||||||
when: NotificationWhen[];
|
when: NotificationWhen[];
|
||||||
options: EmailOptions;
|
options?: EmailOptions;
|
||||||
notificationId: number;
|
notificationId: number;
|
||||||
title: string;
|
title: string;
|
||||||
subType: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Pipeline = Runnable & {
|
export type Pipeline = Runnable & {
|
||||||
|
|
|
@ -84,6 +84,23 @@ export async function BatchUpdateGroup(pipelineIds: number[], groupId: number):
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function BatchUpdateTrigger(pipelineIds: number[], trigger: any): Promise<void> {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/batchUpdateTrigger",
|
||||||
|
method: "post",
|
||||||
|
data: { ids: pipelineIds, trigger },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function BatchUpdateNotificaiton(pipelineIds: number[], notification: any): Promise<void> {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/batchUpdateNotification",
|
||||||
|
method: "post",
|
||||||
|
data: { ids: pipelineIds, notification },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function BatchDelete(pipelineIds: number[]): Promise<void> {
|
export async function BatchDelete(pipelineIds: number[]): Promise<void> {
|
||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/batchDelete",
|
url: apiPrefix + "/batchDelete",
|
||||||
|
@ -99,6 +116,8 @@ export async function BatchRerun(pipelineIds: number[]): Promise<void> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export async function GetFiles(pipelineId: number) {
|
export async function GetFiles(pipelineId: number) {
|
||||||
return await request({
|
return await request({
|
||||||
url: historyApiPrefix + "/files",
|
url: historyApiPrefix + "/files",
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
<template>
|
||||||
|
<fs-button icon="mdi:format-list-group" type="link" text="修改通知" @click="openFormDialog"></fs-button>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import * as api from "../api";
|
||||||
|
import { useFormWrapper } from "@fast-crud/fast-crud";
|
||||||
|
import NotificationSelector from "/@/views/certd/notification/notification-selector/index.vue";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
selectedRowKeys: any[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
change: any;
|
||||||
|
}>();
|
||||||
|
async function batchUpdateRequest(form: any) {
|
||||||
|
/**
|
||||||
|
* type: NotificationType;
|
||||||
|
* when: NotificationWhen[];
|
||||||
|
* options?: EmailOptions;
|
||||||
|
* notificationId: number;
|
||||||
|
* title: string;
|
||||||
|
*/
|
||||||
|
await api.BatchUpdateNotificaiton(props.selectedRowKeys, {
|
||||||
|
type: "other",
|
||||||
|
title: form.title || "通知",
|
||||||
|
when: form.when,
|
||||||
|
notificationId: form.notificationId,
|
||||||
|
});
|
||||||
|
emit("change");
|
||||||
|
}
|
||||||
|
|
||||||
|
const { openCrudFormDialog } = useFormWrapper();
|
||||||
|
|
||||||
|
async function openFormDialog() {
|
||||||
|
const crudOptions: any = {
|
||||||
|
columns: {
|
||||||
|
when: {
|
||||||
|
title: "触发时机",
|
||||||
|
form: {
|
||||||
|
value: ["error", "turnToSuccess"],
|
||||||
|
component: {
|
||||||
|
name: "a-select",
|
||||||
|
vModel: "value",
|
||||||
|
mode: "multiple",
|
||||||
|
options: [
|
||||||
|
{ value: "start", label: "开始时" },
|
||||||
|
{ value: "success", label: "成功时" },
|
||||||
|
{ value: "turnToSuccess", label: "失败转成功时" },
|
||||||
|
{ value: "error", label: "失败时" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
helper: `建议仅选择'失败时'和'失败转成功'两种即可`,
|
||||||
|
rules: [{ required: true, message: "此项必填" }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
notificationId: {
|
||||||
|
title: "通知配置",
|
||||||
|
form: {
|
||||||
|
component: {
|
||||||
|
name: NotificationSelector,
|
||||||
|
on: {
|
||||||
|
selectedChange({ form, $event }: any) {
|
||||||
|
form.title = $event?.name || "通知";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
helper: "请选择通知方式",
|
||||||
|
rules: [{ required: true, message: "此项必填" }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
mode: "edit",
|
||||||
|
//@ts-ignore
|
||||||
|
async doSubmit({ form }) {
|
||||||
|
await batchUpdateRequest(form);
|
||||||
|
},
|
||||||
|
col: {
|
||||||
|
span: 22,
|
||||||
|
},
|
||||||
|
labelCol: {
|
||||||
|
style: {
|
||||||
|
width: "100px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wrapper: {
|
||||||
|
title: "批量修改通知",
|
||||||
|
width: 600,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as any;
|
||||||
|
await openCrudFormDialog({ crudOptions });
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,62 @@
|
||||||
|
<template>
|
||||||
|
<fs-button icon="mdi:format-list-group" type="link" text="修改定时" @click="openFormDialog"></fs-button>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import * as api from "../api";
|
||||||
|
import { useFormWrapper } from "@fast-crud/fast-crud";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
selectedRowKeys: any[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
change: any;
|
||||||
|
}>();
|
||||||
|
async function batchUpdateRequest(form: any) {
|
||||||
|
await api.BatchUpdateTrigger(props.selectedRowKeys, {
|
||||||
|
title: "定时触发",
|
||||||
|
type: "timer",
|
||||||
|
props: form.props,
|
||||||
|
});
|
||||||
|
emit("change");
|
||||||
|
}
|
||||||
|
|
||||||
|
const { openCrudFormDialog } = useFormWrapper();
|
||||||
|
|
||||||
|
async function openFormDialog() {
|
||||||
|
const crudOptions: any = {
|
||||||
|
columns: {
|
||||||
|
"props.cron": {
|
||||||
|
title: "定时",
|
||||||
|
form: {
|
||||||
|
component: {
|
||||||
|
name: "cron-editor",
|
||||||
|
vModel: "modelValue",
|
||||||
|
},
|
||||||
|
rules: [{ required: true, message: "请选择定时Cron" }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
mode: "edit",
|
||||||
|
//@ts-ignore
|
||||||
|
async doSubmit({ form }) {
|
||||||
|
await batchUpdateRequest(form);
|
||||||
|
},
|
||||||
|
col: {
|
||||||
|
span: 22,
|
||||||
|
},
|
||||||
|
labelCol: {
|
||||||
|
style: {
|
||||||
|
width: "100px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wrapper: {
|
||||||
|
title: "批量修改定时",
|
||||||
|
width: 600,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as any;
|
||||||
|
await openCrudFormDialog({ crudOptions });
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -7,9 +7,11 @@
|
||||||
<div v-if="selectedRowKeys.length > 0" class="batch-actions">
|
<div v-if="selectedRowKeys.length > 0" class="batch-actions">
|
||||||
<div class="batch-actions-inner">
|
<div class="batch-actions-inner">
|
||||||
<span> 已选择 {{ selectedRowKeys.length }} 项 </span>
|
<span> 已选择 {{ selectedRowKeys.length }} 项 </span>
|
||||||
<fs-button icon="ion:trash-outline" class="color-green" type="link" text="批量删除" @click="batchDelete"></fs-button>
|
<fs-button icon="ion:trash-outline" class="color-red" type="link" text="批量删除" @click="batchDelete"></fs-button>
|
||||||
<change-group class="color-green" :selected-row-keys="selectedRowKeys" @change="groupChanged"></change-group>
|
|
||||||
<fs-button icon="icon-park-outline:replay-music" class="need-plus" type="link" text="强制重新运行" @click="batchRerun"></fs-button>
|
<fs-button icon="icon-park-outline:replay-music" class="need-plus" type="link" text="强制重新运行" @click="batchRerun"></fs-button>
|
||||||
|
<change-group class="color-green" :selected-row-keys="selectedRowKeys" @change="batchFinished"></change-group>
|
||||||
|
<change-notification class="color-green" :selected-row-keys="selectedRowKeys" @change="batchFinished"></change-notification>
|
||||||
|
<change-trigger class="color-green" :selected-row-keys="selectedRowKeys" @change="batchFinished"></change-trigger>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template #actionbar-right> </template>
|
<template #actionbar-right> </template>
|
||||||
|
@ -26,8 +28,10 @@ import { dict, useFs } from "@fast-crud/fast-crud";
|
||||||
import createCrudOptions from "./crud";
|
import createCrudOptions from "./crud";
|
||||||
import PiCertdForm from "./certd-form/index.vue";
|
import PiCertdForm from "./certd-form/index.vue";
|
||||||
import ChangeGroup from "./components/change-group.vue";
|
import ChangeGroup from "./components/change-group.vue";
|
||||||
|
import ChangeTrigger from "./components/change-trigger.vue";
|
||||||
import { Modal, notification } from "ant-design-vue";
|
import { Modal, notification } from "ant-design-vue";
|
||||||
import * as api from "./api";
|
import * as api from "./api";
|
||||||
|
import ChangeNotification from "/@/views/certd/pipeline/components/change-notification.vue";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "PipelineManager",
|
name: "PipelineManager",
|
||||||
|
@ -55,7 +59,7 @@ onActivated(async () => {
|
||||||
await crudExpose.doRefresh();
|
await crudExpose.doRefresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
function groupChanged() {
|
function batchFinished() {
|
||||||
crudExpose.doRefresh();
|
crudExpose.doRefresh();
|
||||||
selectedRowKeys.value = [];
|
selectedRowKeys.value = [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,17 +24,17 @@
|
||||||
disabled: !editMode,
|
disabled: !editMode,
|
||||||
options: [
|
options: [
|
||||||
{ value: 'email', label: '邮件' },
|
{ value: 'email', label: '邮件' },
|
||||||
{ value: 'other', label: '其他通知方式' }
|
{ value: 'other', label: '其他通知方式' },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
rules: [{ required: true, message: '此项必填' }]
|
rules: [{ required: true, message: '此项必填' }],
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
<fs-form-item
|
<fs-form-item
|
||||||
v-model="currentNotification.when"
|
v-model="currentNotification.when"
|
||||||
:item="{
|
:item="{
|
||||||
title: '触发时机',
|
title: '触发时机',
|
||||||
key: 'type',
|
key: 'when',
|
||||||
value: ['error'],
|
value: ['error'],
|
||||||
component: {
|
component: {
|
||||||
name: 'a-select',
|
name: 'a-select',
|
||||||
|
@ -45,11 +45,11 @@
|
||||||
{ value: 'start', label: '开始时' },
|
{ value: 'start', label: '开始时' },
|
||||||
{ value: 'success', label: '成功时' },
|
{ value: 'success', label: '成功时' },
|
||||||
{ value: 'turnToSuccess', label: '失败转成功时' },
|
{ value: 'turnToSuccess', label: '失败转成功时' },
|
||||||
{ value: 'error', label: '失败时' }
|
{ value: 'error', label: '失败时' },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
helper: `建议仅选择'失败时'和'失败转成功'两种即可`,
|
helper: `建议仅选择'失败时'和'失败转成功'两种即可`,
|
||||||
rules: [{ required: true, message: '此项必填' }]
|
rules: [{ required: true, message: '此项必填' }],
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
<pi-notification-form-email v-if="currentNotification.type === 'email'" ref="optionsRef" v-model:options="currentNotification.options"></pi-notification-form-email>
|
<pi-notification-form-email v-if="currentNotification.type === 'email'" ref="optionsRef" v-model:options="currentNotification.options"></pi-notification-form-email>
|
||||||
|
@ -59,14 +59,14 @@
|
||||||
v-model="currentNotification.notificationId"
|
v-model="currentNotification.notificationId"
|
||||||
:item="{
|
:item="{
|
||||||
title: '通知配置',
|
title: '通知配置',
|
||||||
key: 'type',
|
key: 'notificationId',
|
||||||
component: {
|
component: {
|
||||||
disabled: !editMode,
|
disabled: !editMode,
|
||||||
name: NotificationSelector,
|
name: NotificationSelector,
|
||||||
onSelectedChange
|
onSelectedChange,
|
||||||
},
|
},
|
||||||
helper: '请选择通知方式',
|
helper: '请选择通知方式',
|
||||||
rules: [{ required: true, message: '此项必填' }]
|
rules: [{ required: true, message: '此项必填' }],
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
@ -96,8 +96,8 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
editMode: {
|
editMode: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
emits: ["update"],
|
emits: ["update"],
|
||||||
setup(props: any, context: any) {
|
setup(props: any, context: any) {
|
||||||
|
@ -118,23 +118,23 @@ export default {
|
||||||
{
|
{
|
||||||
type: "string",
|
type: "string",
|
||||||
required: true,
|
required: true,
|
||||||
message: "请选择类型"
|
message: "请选择类型",
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
when: [
|
when: [
|
||||||
{
|
{
|
||||||
type: "string",
|
type: "string",
|
||||||
required: true,
|
required: true,
|
||||||
message: "请选择通知时机"
|
message: "请选择通知时机",
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
notificationId: [
|
notificationId: [
|
||||||
{
|
{
|
||||||
type: "number",
|
type: "number",
|
||||||
required: true,
|
required: true,
|
||||||
message: "请选择通知配置"
|
message: "请选择通知配置",
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const notificationDrawerShow = () => {
|
const notificationDrawerShow = () => {
|
||||||
|
@ -195,7 +195,7 @@ export default {
|
||||||
async onOk() {
|
async onOk() {
|
||||||
callback.value("delete");
|
callback.value("delete");
|
||||||
notificationDrawerClose();
|
notificationDrawerClose();
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -222,21 +222,21 @@ export default {
|
||||||
notificationDelete,
|
notificationDelete,
|
||||||
rules,
|
rules,
|
||||||
blankFn,
|
blankFn,
|
||||||
optionsRef
|
optionsRef,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...useNotificationForm(),
|
...useNotificationForm(),
|
||||||
labelCol: { span: 6 },
|
labelCol: { span: 6 },
|
||||||
wrapperCol: { span: 16 }
|
wrapperCol: { span: 16 },
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
NotificationSelector() {
|
NotificationSelector() {
|
||||||
return NotificationSelector;
|
return NotificationSelector;
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<a-drawer
|
<a-drawer v-model:open="triggerDrawerVisible" placement="right" :closable="true" width="650px" class="pi-trigger-form" @after-open-change="triggerDrawerOnAfterVisibleChange">
|
||||||
v-model:open="triggerDrawerVisible"
|
|
||||||
placement="right"
|
|
||||||
:closable="true"
|
|
||||||
width="650px"
|
|
||||||
class="pi-trigger-form"
|
|
||||||
@after-open-change="triggerDrawerOnAfterVisibleChange"
|
|
||||||
>
|
|
||||||
<template #title>
|
<template #title>
|
||||||
<div>
|
<div>
|
||||||
编辑触发器
|
编辑触发器
|
||||||
|
@ -26,9 +19,9 @@
|
||||||
component: {
|
component: {
|
||||||
name: 'a-input',
|
name: 'a-input',
|
||||||
vModel: 'value',
|
vModel: 'value',
|
||||||
disabled: !editMode
|
disabled: !editMode,
|
||||||
},
|
},
|
||||||
rules: [{ required: true, message: '此项必填' }]
|
rules: [{ required: true, message: '此项必填' }],
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -42,9 +35,9 @@
|
||||||
name: 'a-select',
|
name: 'a-select',
|
||||||
vModel: 'value',
|
vModel: 'value',
|
||||||
disabled: !editMode,
|
disabled: !editMode,
|
||||||
options: [{ value: 'timer', label: '定时' }]
|
options: [{ value: 'timer', label: '定时' }],
|
||||||
},
|
},
|
||||||
rules: [{ required: true, message: '此项必填' }]
|
rules: [{ required: true, message: '此项必填' }],
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -56,10 +49,10 @@
|
||||||
component: {
|
component: {
|
||||||
disabled: !editMode,
|
disabled: !editMode,
|
||||||
name: 'cron-editor',
|
name: 'cron-editor',
|
||||||
vModel: 'modelValue'
|
vModel: 'modelValue',
|
||||||
},
|
},
|
||||||
helper: '点击上面的按钮,选择每天几点定时执行。\n建议设置为每天触发一次,证书未到期之前任务会跳过,不会重复执行',
|
helper: '点击上面的按钮,选择每天几点定时执行。\n建议设置为每天触发一次,证书未到期之前任务会跳过,不会重复执行',
|
||||||
rules: [{ required: true, message: '此项必填' }]
|
rules: [{ required: true, message: '此项必填' }],
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
@ -84,8 +77,8 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
editMode: {
|
editMode: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
emits: ["update"],
|
emits: ["update"],
|
||||||
setup(props, context) {
|
setup(props, context) {
|
||||||
|
@ -105,9 +98,9 @@ export default {
|
||||||
{
|
{
|
||||||
type: "string",
|
type: "string",
|
||||||
required: true,
|
required: true,
|
||||||
message: "请输入名称"
|
message: "请输入名称",
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const triggerDrawerShow = () => {
|
const triggerDrawerShow = () => {
|
||||||
|
@ -117,7 +110,7 @@ export default {
|
||||||
triggerDrawerVisible.value = false;
|
triggerDrawerVisible.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const triggerDrawerOnAfterVisibleChange = (val) => {
|
const triggerDrawerOnAfterVisibleChange = val => {
|
||||||
console.log("triggerDrawerOnAfterVisibleChange", val);
|
console.log("triggerDrawerOnAfterVisibleChange", val);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -128,7 +121,7 @@ export default {
|
||||||
triggerDrawerShow();
|
triggerDrawerShow();
|
||||||
};
|
};
|
||||||
|
|
||||||
const triggerAdd = (emit) => {
|
const triggerAdd = emit => {
|
||||||
mode.value = "add";
|
mode.value = "add";
|
||||||
const trigger = { id: nanoid(), title: "定时触发", type: "timer", props: {} };
|
const trigger = { id: nanoid(), title: "定时触发", type: "timer", props: {} };
|
||||||
triggerOpen(trigger, emit);
|
triggerOpen(trigger, emit);
|
||||||
|
@ -144,7 +137,7 @@ export default {
|
||||||
triggerOpen(trigger, emit);
|
triggerOpen(trigger, emit);
|
||||||
};
|
};
|
||||||
|
|
||||||
const triggerSave = async (e) => {
|
const triggerSave = async e => {
|
||||||
console.log("currentTriggerSave", currentTrigger.value);
|
console.log("currentTriggerSave", currentTrigger.value);
|
||||||
try {
|
try {
|
||||||
await triggerFormRef.value.validate();
|
await triggerFormRef.value.validate();
|
||||||
|
@ -164,7 +157,7 @@ export default {
|
||||||
async onOk() {
|
async onOk() {
|
||||||
callback.value("delete");
|
callback.value("delete");
|
||||||
triggerDrawerClose();
|
triggerDrawerClose();
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -185,16 +178,16 @@ export default {
|
||||||
triggerSave,
|
triggerSave,
|
||||||
triggerDelete,
|
triggerDelete,
|
||||||
rules,
|
rules,
|
||||||
blankFn
|
blankFn,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...useTriggerForm(),
|
...useTriggerForm(),
|
||||||
labelCol: { span: 6 },
|
labelCol: { span: 6 },
|
||||||
wrapperCol: { span: 16 }
|
wrapperCol: { span: 16 },
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,19 @@ export class PipelineController extends CrudController<PipelineService> {
|
||||||
return this.ok({});
|
return this.ok({});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Post('/batchUpdateTrigger', { summary: Constants.per.authOnly })
|
||||||
|
async batchUpdateTrigger(@Body('ids') ids: number[], @Body('trigger') trigger: any) {
|
||||||
|
await this.service.batchUpdateTrigger(ids, trigger, this.getUserId());
|
||||||
|
return this.ok({});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('/batchUpdateNotification', { summary: Constants.per.authOnly })
|
||||||
|
async batchUpdateNotification(@Body('ids') ids: number[], @Body('notification') notification: any) {
|
||||||
|
await this.service.batchUpdateNotifications(ids, notification, this.getUserId());
|
||||||
|
return this.ok({});
|
||||||
|
}
|
||||||
|
|
||||||
@Post('/batchRerun', { summary: Constants.per.authOnly })
|
@Post('/batchRerun', { summary: Constants.per.authOnly })
|
||||||
async batchRerun(@Body('ids') ids: number[]) {
|
async batchRerun(@Body('ids') ids: number[]) {
|
||||||
await this.service.batchRerun(ids, this.getUserId());
|
await this.service.batchRerun(ids, this.getUserId());
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {
|
||||||
Executor,
|
Executor,
|
||||||
IAccessService,
|
IAccessService,
|
||||||
ICnameProxyService,
|
ICnameProxyService,
|
||||||
INotificationService,
|
INotificationService, Notification,
|
||||||
Pipeline,
|
Pipeline,
|
||||||
ResultType,
|
ResultType,
|
||||||
RunHistory,
|
RunHistory,
|
||||||
|
@ -45,6 +45,7 @@ import {NotificationService} from "./notification-service.js";
|
||||||
import {UserSuiteEntity, UserSuiteService} from "@certd/commercial-core";
|
import {UserSuiteEntity, UserSuiteService} from "@certd/commercial-core";
|
||||||
import {CertInfoService} from "../../monitor/service/cert-info-service.js";
|
import {CertInfoService} from "../../monitor/service/cert-info-service.js";
|
||||||
import {TaskServiceBuilder} from "./task-service-getter.js";
|
import {TaskServiceBuilder} from "./task-service-getter.js";
|
||||||
|
import {nanoid} from "nanoid";
|
||||||
|
|
||||||
const runningTasks: Map<string | number, Executor> = new Map();
|
const runningTasks: Map<string | number, Executor> = new Map();
|
||||||
|
|
||||||
|
@ -149,8 +150,17 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
const info = await this.info(pipelineId);
|
const info = await this.info(pipelineId);
|
||||||
if (info && !info.disabled) {
|
if (info && !info.disabled) {
|
||||||
const pipeline = JSON.parse(info.content);
|
const pipeline = JSON.parse(info.content);
|
||||||
// 手动触发,不要await
|
this.registerTriggers(pipeline,false);
|
||||||
this.registerTriggers(pipeline);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async registerTrigger(info:PipelineEntity) {
|
||||||
|
if (info == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (info && !info.disabled) {
|
||||||
|
const pipeline = JSON.parse(info.content);
|
||||||
|
this.registerTriggers(pipeline,false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,10 +184,11 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
//修改
|
//修改
|
||||||
old = await this.info(bean.id);
|
old = await this.info(bean.id);
|
||||||
}
|
}
|
||||||
const pipeline = JSON.parse(bean.content || '{}');
|
|
||||||
RunnableCollection.initPipelineRunnableType(pipeline);
|
|
||||||
const isUpdate = bean.id > 0 && old != null;
|
const isUpdate = bean.id > 0 && old != null;
|
||||||
|
|
||||||
|
|
||||||
|
const pipeline = JSON.parse(bean.content || '{}');
|
||||||
|
RunnableCollection.initPipelineRunnableType(pipeline);
|
||||||
let domains = [];
|
let domains = [];
|
||||||
if (pipeline.stages) {
|
if (pipeline.stages) {
|
||||||
RunnableCollection.each(pipeline.stages, (runnable: any) => {
|
RunnableCollection.each(pipeline.stages, (runnable: any) => {
|
||||||
|
@ -199,22 +210,32 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
//如果是添加,先保存一下,获取到id,更新pipeline.id
|
//如果是添加,先保存一下,获取到id,更新pipeline.id
|
||||||
await this.addOrUpdate(bean);
|
await this.addOrUpdate(bean);
|
||||||
}
|
}
|
||||||
await this.clearTriggers(bean.id);
|
|
||||||
|
await this.doUpdatePipelineJson(bean, pipeline);
|
||||||
|
|
||||||
|
//保存域名信息到certInfo表
|
||||||
|
let fromType = 'pipeline';
|
||||||
|
if (bean.type === 'cert_upload') {
|
||||||
|
fromType = 'upload';
|
||||||
|
}
|
||||||
|
await this.certInfoService.updateDomains(pipeline.id, pipeline.userId || bean.userId, domains, fromType);
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新Pipeline, 包括trigger
|
||||||
|
* @param bean
|
||||||
|
* @param pipeline
|
||||||
|
*/
|
||||||
|
async doUpdatePipelineJson(bean: PipelineEntity, pipeline:Pipeline) {
|
||||||
|
await this.clearTriggers(bean);
|
||||||
if (pipeline.title) {
|
if (pipeline.title) {
|
||||||
bean.title = pipeline.title;
|
bean.title = pipeline.title;
|
||||||
}
|
}
|
||||||
pipeline.id = bean.id;
|
pipeline.id = bean.id;
|
||||||
bean.content = JSON.stringify(pipeline);
|
bean.content = JSON.stringify(pipeline);
|
||||||
await this.addOrUpdate(bean);
|
await this.addOrUpdate(bean);
|
||||||
await this.registerTriggerById(bean.id);
|
await this.registerTrigger(bean);
|
||||||
|
|
||||||
//保存域名信息到certInfo表
|
|
||||||
let fromType = 'pipeline';
|
|
||||||
if(bean.type === 'cert_upload') {
|
|
||||||
fromType = 'upload';
|
|
||||||
}
|
|
||||||
await this.certInfoService.updateDomains(pipeline.id, pipeline.userId || bean.userId, domains,fromType);
|
|
||||||
return bean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async checkMaxPipelineCount(bean: PipelineEntity, pipeline: Pipeline, domains: string[]) {
|
private async checkMaxPipelineCount(bean: PipelineEntity, pipeline: Pipeline, domains: string[]) {
|
||||||
|
@ -375,11 +396,16 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
await this.certInfoService.deleteByPipelineId(id);
|
await this.certInfoService.deleteByPipelineId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearTriggers(id: number) {
|
async clearTriggers(id: number | PipelineEntity) {
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const pipeline = await this.info(id);
|
let pipeline:PipelineEntity = null
|
||||||
|
if (typeof id === 'number') {
|
||||||
|
pipeline = await this.info(id);
|
||||||
|
}else{
|
||||||
|
pipeline = id
|
||||||
|
}
|
||||||
if (!pipeline) {
|
if (!pipeline) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -703,6 +729,58 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
{ groupId }
|
{ groupId }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async batchUpdateTrigger(ids: number[], trigger: any, userId: any){
|
||||||
|
|
||||||
|
const list = await this.find({
|
||||||
|
where:{
|
||||||
|
id: In(ids),
|
||||||
|
userId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const item of list) {
|
||||||
|
const pipeline = JSON.parse(item.content);
|
||||||
|
pipeline.triggers = [{
|
||||||
|
id: nanoid(),
|
||||||
|
title: '定时触发',
|
||||||
|
...trigger
|
||||||
|
}]
|
||||||
|
await this.doUpdatePipelineJson(item,pipeline)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async batchUpdateNotifications(ids: number[], notification: Notification, userId: any){
|
||||||
|
|
||||||
|
const list = await this.find({
|
||||||
|
where:{
|
||||||
|
id: In(ids),
|
||||||
|
userId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const item of list) {
|
||||||
|
const pipeline = JSON.parse(item.content);
|
||||||
|
pipeline.notifications = [{
|
||||||
|
id: nanoid(),
|
||||||
|
title: '通知',
|
||||||
|
/**
|
||||||
|
* type: NotificationType;
|
||||||
|
* when: NotificationWhen[];
|
||||||
|
* options: EmailOptions;
|
||||||
|
* notificationId: number;
|
||||||
|
* title: string;
|
||||||
|
* subType: string;
|
||||||
|
*/
|
||||||
|
type: "other",
|
||||||
|
...notification
|
||||||
|
}]
|
||||||
|
await this.doUpdatePipelineJson(item,pipeline)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async batchRerun(ids: number[], userId: any) {
|
async batchRerun(ids: number[], userId: any) {
|
||||||
if (!isPlus()){
|
if (!isPlus()){
|
||||||
throw new NeedVIPException("此功能需要升级专业版")
|
throw new NeedVIPException("此功能需要升级专业版")
|
||||||
|
|
Loading…
Reference in New Issue