mirror of https://github.com/certd/certd
chore: 模版导入式创建流水线
parent
37e6548246
commit
04422a4637
|
@ -133,5 +133,12 @@ async function loadLocaleMessages(lang: SupportedLanguagesType) {
|
|||
|
||||
return setI18nLanguage(lang);
|
||||
}
|
||||
|
||||
export function useI18n() {
|
||||
return {
|
||||
t: i18n.global.t,
|
||||
locale: i18n.global.locale,
|
||||
};
|
||||
}
|
||||
export { i18n, loadLocaleMessages, loadLocalesMap, loadLocalesMapFromDir, setupI18n, setI18nLanguage };
|
||||
export default i18n;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { i18n, loadLocaleMessages, loadLocalesMap, loadLocalesMapFromDir, setupI18n, setI18nLanguage } from "./i18n";
|
||||
import { i18n, loadLocaleMessages, loadLocalesMap, loadLocalesMapFromDir, setupI18n, setI18nLanguage, useI18n } from "./i18n";
|
||||
|
||||
const $t = i18n.global.t;
|
||||
const $te = i18n.global.te;
|
||||
|
||||
export { $t, $te, i18n, loadLocaleMessages, loadLocalesMap, loadLocalesMapFromDir, setupI18n, setI18nLanguage };
|
||||
export { $t, $te, i18n, loadLocaleMessages, loadLocalesMap, loadLocalesMapFromDir, setupI18n, setI18nLanguage, useI18n };
|
||||
export { type ImportLocaleFn, type LocaleSetupOptions, type SupportedLanguagesType } from "./typing";
|
||||
// export type { CompileError } from "@intlify/core-base";
|
||||
|
||||
export { useI18n } from "vue-i18n";
|
||||
// export { useI18n } from "vue-i18n";
|
||||
|
||||
export type { Locale } from "vue-i18n";
|
||||
|
|
|
@ -11,8 +11,7 @@ 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";
|
||||
|
||||
import { useI18n } from "/src/locales";
|
||||
|
||||
export function fillPipelineByDefaultForm(pipeline: any, form: any) {
|
||||
const triggers = [];
|
||||
|
@ -34,241 +33,240 @@ export function fillPipelineByDefaultForm(pipeline: any, form: any) {
|
|||
}
|
||||
|
||||
export function setRunnableIds(pipeline: any) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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 { t } = useI18n();
|
||||
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: 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,
|
||||
},
|
||||
}
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const certPlugins = [];
|
||||
for (const plugin of certPluginGroup.plugins) {
|
||||
const detail: any = await pluginStore.getPluginDefine(plugin.name);
|
||||
certPlugins.push(detail);
|
||||
}
|
||||
return certPlugins;
|
||||
}
|
||||
async function openAddCertdPipelineDialog(req: { defaultGroupId?: number }) {
|
||||
//检查是否流水线数量超出限制
|
||||
await checkPipelineLimit();
|
||||
|
||||
async function openAddCertdPipelineDialog(req: { defaultGroupId?: number }) {
|
||||
//检查是否流水线数量超出限制
|
||||
await checkPipelineLimit();
|
||||
const wrapperRef = ref();
|
||||
function getFormData() {
|
||||
if (!wrapperRef.value) {
|
||||
return null;
|
||||
}
|
||||
return wrapperRef.value.getFormData();
|
||||
}
|
||||
|
||||
const wrapperRef = ref();
|
||||
function getFormData() {
|
||||
if (!wrapperRef.value) {
|
||||
return null;
|
||||
}
|
||||
return wrapperRef.value.getFormData();
|
||||
}
|
||||
|
||||
async function doSubmit({ form }: any) {
|
||||
// const certDetail = readCertDetail(form.cert.crt);
|
||||
// 添加certd pipeline
|
||||
const pluginInput = omit(form, ["triggerCron", "notification", "notificationTarget", "certApplyPlugin", "groupId"]);
|
||||
async function doSubmit({ form }: any) {
|
||||
// const certDetail = readCertDetail(form.cert.crt);
|
||||
// 添加certd pipeline
|
||||
const pluginInput = omit(form, ["triggerCron", "notification", "notificationTarget", "certApplyPlugin", "groupId"]);
|
||||
let pipeline: any = {
|
||||
title: form.domains[0] + "证书自动化",
|
||||
runnableType: "pipeline",
|
||||
|
@ -301,38 +299,38 @@ export function useCertPipelineCreator() {
|
|||
],
|
||||
};
|
||||
|
||||
pipeline = fillPipelineByDefaultForm(pipeline, form);
|
||||
pipeline = fillPipelineByDefaultForm(pipeline, form);
|
||||
|
||||
pipeline = setRunnableIds(pipeline);
|
||||
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;
|
||||
}
|
||||
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,
|
||||
};
|
||||
return {
|
||||
openAddCertdPipelineDialog,
|
||||
};
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -22,7 +22,6 @@
|
|||
</fs-page>
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onActivated, onMounted, ref } from "vue";
|
||||
import { dict, useFs } from "@fast-crud/fast-crud";
|
||||
|
|
|
@ -77,27 +77,27 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
buttons: {
|
||||
edit: { show: false },
|
||||
copy: { show: false },
|
||||
use: {
|
||||
text: null,
|
||||
title: "使用此模版创建流水线",
|
||||
icon: "ion:duplicate-outline",
|
||||
click({ row }) {
|
||||
openCreateFromTemplateDialog({
|
||||
templateId: row.id,
|
||||
onCreated: ({ id }) => {
|
||||
router.push({ path: "/certd/pipeline/detail", query: { id, editMode: true } });
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
import: {
|
||||
text: null,
|
||||
title: "批量导入创建",
|
||||
icon: "ion:duplicate",
|
||||
click({ row }) {
|
||||
router.push({ path: "/certd/pipeline/template/import", query: { templateId: row.id } });
|
||||
},
|
||||
},
|
||||
// use: {
|
||||
// text: null,
|
||||
// title: "使用此模版创建流水线",
|
||||
// icon: "ion:duplicate-outline",
|
||||
// click({ row }) {
|
||||
// openCreateFromTemplateDialog({
|
||||
// templateId: row.id,
|
||||
// onCreated: ({ id }) => {
|
||||
// router.push({ path: "/certd/pipeline/detail", query: { id, editMode: "true" } });
|
||||
// },
|
||||
// });
|
||||
// },
|
||||
// },
|
||||
// import: {
|
||||
// text: null,
|
||||
// title: "批量导入创建",
|
||||
// icon: "ion:duplicate",
|
||||
// click({ row }) {
|
||||
// router.push({ path: "/certd/pipeline/template/import", query: { templateId: row.id } });
|
||||
// },
|
||||
// },
|
||||
},
|
||||
},
|
||||
columns: {
|
||||
|
@ -124,11 +124,19 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
search: {
|
||||
show: true,
|
||||
},
|
||||
form: {
|
||||
rules: [{ required: true, message: "请输入模版名称" }],
|
||||
},
|
||||
column: {
|
||||
width: 400,
|
||||
sorter: true,
|
||||
cellRender({ row, value }) {
|
||||
return <router-link to={{ path: "/certd/pipeline/template/edit", query: { templateId: row.id } }}>{value}</router-link>;
|
||||
return (
|
||||
<router-link class={"flex items-center"} to={{ path: "/certd/pipeline/template/edit", query: { templateId: row.id } }}>
|
||||
<fs-icon icon={"ion:create-outline"}></fs-icon>
|
||||
<span class={"ml-5"}> {value}</span>
|
||||
</router-link>
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -182,6 +190,46 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
},
|
||||
},
|
||||
},
|
||||
useCreate: {
|
||||
title: "使用此模版",
|
||||
form: { show: false },
|
||||
column: {
|
||||
conditionalRender: false,
|
||||
width: 400,
|
||||
cellRender({ row }) {
|
||||
function create() {
|
||||
openCreateFromTemplateDialog({
|
||||
templateId: row.id,
|
||||
onCreated: ({ id }) => {
|
||||
router.push({ path: "/certd/pipeline/detail", query: { id, editMode: "true" } });
|
||||
},
|
||||
});
|
||||
}
|
||||
return (
|
||||
<a class={"flex items-center"} onClick={create}>
|
||||
<fs-icon icon={"ion:duplicate-outline"}></fs-icon>
|
||||
<span class={"ml-5"}>创建单个流水线</span>
|
||||
</a>
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
useImport: {
|
||||
title: "使用此模版",
|
||||
form: { show: false },
|
||||
column: {
|
||||
conditionalRender: false,
|
||||
width: 400,
|
||||
cellRender({ row }) {
|
||||
return (
|
||||
<router-link class={"flex items-center"} to={{ path: "/certd/pipeline/template/import", query: { templateId: row.id } }}>
|
||||
<fs-icon icon={"ion:duplicate"}></fs-icon>
|
||||
<span class={"ml-5"}>批量创建流水线</span>
|
||||
</router-link>
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -112,7 +112,9 @@ async function getTemplateDetail() {
|
|||
}
|
||||
const res = await templateApi.GetDetail(parseInt(templateId));
|
||||
detail.value = res;
|
||||
templateProps.value = JSON.parse(res.template.content ?? "{input:{}}");
|
||||
if (res.template.content) {
|
||||
templateProps.value = JSON.parse(res.template.content);
|
||||
}
|
||||
}
|
||||
|
||||
const pluginStore = usePluginStore();
|
||||
|
|
|
@ -20,8 +20,8 @@ import { templateApi } from "../api";
|
|||
import { createFormOptions } from "/@/views/certd/pipeline/template/import/form";
|
||||
import { cloneDeep } from "lodash-es";
|
||||
import { fillPipelineByDefaultForm } from "/@/views/certd/pipeline/certd-form/use";
|
||||
import { eachSteps } from "/@/views/certd/pipeline/utils";
|
||||
|
||||
import { createPipelineByTemplate } from "/@/views/certd/pipeline/template/use";
|
||||
import { notification, Modal } from "ant-design-vue";
|
||||
const route = useRoute();
|
||||
const templateId = route.query.templateId as string;
|
||||
|
||||
|
@ -59,44 +59,44 @@ async function doImport() {
|
|||
|
||||
const importTableRef = formRef.value.getComponentRef("templateProps");
|
||||
|
||||
const templateList = importTableRef.value.getData();
|
||||
const templateList = importTableRef.getData();
|
||||
|
||||
for (let i = 0; i < templateList.length; i++) {
|
||||
const tempInputs = templateList[i];
|
||||
const title = tempInputs.title;
|
||||
delete tempInputs.title;
|
||||
const progress = ref({ total: templateList.length, current: 0 });
|
||||
async function requestImport() {
|
||||
for (let i = 0; i < templateList.length; i++) {
|
||||
const tempInputs = templateList[i];
|
||||
const title = tempInputs.title;
|
||||
delete tempInputs.title;
|
||||
|
||||
let newPipeline = cloneDeep(detail.value.pipeline);
|
||||
newPipeline = fillPipelineByDefaultForm(newPipeline, form);
|
||||
//填充模版参数
|
||||
const steps: any = {};
|
||||
eachSteps(newPipeline, (step: any) => {
|
||||
steps[step.id] = step;
|
||||
});
|
||||
let newPipeline = cloneDeep(detail.value.pipeline);
|
||||
newPipeline = fillPipelineByDefaultForm(newPipeline, form);
|
||||
|
||||
for (const inputKey in tempInputs) {
|
||||
const [stepId, key] = inputKey.split(".");
|
||||
const step = steps[stepId];
|
||||
if (step) {
|
||||
step.input[key] = tempInputs[inputKey];
|
||||
}
|
||||
await createPipelineByTemplate({
|
||||
templateId: parseInt(templateId),
|
||||
templateForm: tempInputs,
|
||||
pipeline: newPipeline,
|
||||
title: title,
|
||||
groupId: form.groupId,
|
||||
});
|
||||
progress.value.current = progress.value.current + 1;
|
||||
}
|
||||
|
||||
newPipeline.title = title;
|
||||
const groupId = form.groupId;
|
||||
|
||||
await templateApi.CreatePipelineByTemplate({
|
||||
title,
|
||||
content: JSON.stringify(newPipeline),
|
||||
keepHistoryCount: 30,
|
||||
groupId,
|
||||
templateId: parseInt(templateId),
|
||||
pipeline: {
|
||||
title: form.title,
|
||||
templateProps: templateList,
|
||||
},
|
||||
notification.success({
|
||||
message: "导入完成",
|
||||
});
|
||||
|
||||
importTableRef.clear();
|
||||
}
|
||||
requestImport();
|
||||
Modal.info({
|
||||
title: "导入中",
|
||||
content() {
|
||||
return (
|
||||
<div>
|
||||
当前导入进度: {progress.value.current} / {progress.value.total}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -91,7 +91,10 @@ onMounted(async () => {
|
|||
await pluginStore.init();
|
||||
await nextTick();
|
||||
const steps = getStepsMap(props.detail.pipeline);
|
||||
templateProps.value = JSON.parse(props.detail.template?.content ?? "{input:{}}");
|
||||
if (props.detail.template?.content) {
|
||||
templateProps.value = JSON.parse(props.detail.template?.content);
|
||||
}
|
||||
|
||||
appendCrudOptions({ ...buildColumns(steps) });
|
||||
crudBinding.value.data = [];
|
||||
await crudExpose.editable.enable({ mode: "row" });
|
||||
|
@ -101,6 +104,9 @@ defineExpose({
|
|||
getData() {
|
||||
return crudBinding.value.data;
|
||||
},
|
||||
clear() {
|
||||
crudBinding.value.data = [];
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -67,6 +67,34 @@ export function createExtraColumns() {
|
|||
};
|
||||
}
|
||||
|
||||
export async function createPipelineByTemplate(opts: { templateId: number; title: string; groupId?: string; pipeline: any; templateForm: any; keepHistoryCount?: number }) {
|
||||
const { title, groupId, pipeline, templateForm, keepHistoryCount, templateId } = opts;
|
||||
//填充模版参数
|
||||
const steps: any = {};
|
||||
eachSteps(pipeline, (step: any) => {
|
||||
steps[step.id] = step;
|
||||
});
|
||||
|
||||
for (const stepId in templateForm) {
|
||||
const step = steps[stepId];
|
||||
const tempStep = templateForm[stepId];
|
||||
if (step) {
|
||||
for (const key in tempStep) {
|
||||
step.input[key] = tempStep[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pipeline.title = title;
|
||||
return await templateApi.CreatePipelineByTemplate({
|
||||
title,
|
||||
content: JSON.stringify(pipeline),
|
||||
keepHistoryCount: keepHistoryCount ?? 30,
|
||||
groupId,
|
||||
templateId,
|
||||
});
|
||||
}
|
||||
|
||||
export function useTemplate() {
|
||||
const { openCrudFormDialog } = useFormWrapper();
|
||||
|
||||
|
@ -102,28 +130,12 @@ export function useTemplate() {
|
|||
let newPipeline = cloneDeep(pipeline);
|
||||
newPipeline = fillPipelineByDefaultForm(newPipeline, form);
|
||||
//填充模版参数
|
||||
const steps: any = {};
|
||||
eachSteps(newPipeline, (step: any) => {
|
||||
steps[step.id] = step;
|
||||
});
|
||||
|
||||
for (const inputKey in tempInputs) {
|
||||
const [stepId, key] = inputKey.split(".");
|
||||
const step = steps[stepId];
|
||||
if (step) {
|
||||
step.input[key] = tempInputs[inputKey];
|
||||
}
|
||||
}
|
||||
|
||||
const title = form.title;
|
||||
newPipeline.title = title;
|
||||
const groupId = form.groupId;
|
||||
const { id } = await templateApi.CreatePipelineByTemplate({
|
||||
title,
|
||||
content: JSON.stringify(newPipeline),
|
||||
keepHistoryCount: 30,
|
||||
groupId,
|
||||
const { id } = await createPipelineByTemplate({
|
||||
templateId: detail.template.id,
|
||||
templateForm: tempInputs,
|
||||
pipeline: newPipeline,
|
||||
title: form.title,
|
||||
groupId: form.groupId,
|
||||
});
|
||||
if (req.onCreated) {
|
||||
req.onCreated({ id });
|
||||
|
|
Loading…
Reference in New Issue