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 = [];
|
||||
|
@ -233,8 +232,7 @@ export function useCertPipelineCreator() {
|
|||
},
|
||||
order: 9999,
|
||||
},
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as api from "./api";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { computed, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, useUi } from "@fast-crud/fast-crud";
|
||||
|
@ -14,11 +13,14 @@ import { setRunnableIds, useCertPipelineCreator } from "/@/views/certd/pipeline/
|
|||
import { useCertUpload } from "/@/views/certd/pipeline/cert-upload/use";
|
||||
import GroupSelector from "/@/views/certd/pipeline/group/group-selector.vue";
|
||||
import { useCertViewer } from "/@/views/certd/pipeline/use";
|
||||
import { useI18n } from "/src/locales";
|
||||
|
||||
export default function ({ crudExpose, context: { groupDictRef, selectedRowKeys } }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const router = useRouter();
|
||||
const lastResRef = ref();
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const { openAddCertdPipelineDialog } = useCertPipelineCreator();
|
||||
const { openUploadCreateDialog } = useCertUpload();
|
||||
|
||||
|
@ -367,7 +369,7 @@ export default function ({ crudExpose, context: { groupDictRef, selectedRowKeys
|
|||
const leftDays = dayjs(row.lastVars.certExpiresTime).diff(dayjs(), "day");
|
||||
const color = leftDays < 20 ? "red" : "#389e0d";
|
||||
const percent = (leftDays / 90) * 100;
|
||||
return <a-progress percent={percent} strokeColor={color} format={(percent) => `${leftDays} 天`} />;
|
||||
return <a-progress percent={percent} strokeColor={color} format={percent => `${leftDays} 天`} />;
|
||||
},
|
||||
width: 150,
|
||||
},
|
||||
|
@ -545,7 +547,6 @@ export default function ({ crudExpose, context: { groupDictRef, selectedRowKeys
|
|||
sorter: true,
|
||||
},
|
||||
},
|
||||
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -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,8 +59,10 @@ async function doImport() {
|
|||
|
||||
const importTableRef = formRef.value.getComponentRef("templateProps");
|
||||
|
||||
const templateList = importTableRef.value.getData();
|
||||
const templateList = importTableRef.getData();
|
||||
|
||||
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;
|
||||
|
@ -68,35 +70,33 @@ async function doImport() {
|
|||
|
||||
let newPipeline = cloneDeep(detail.value.pipeline);
|
||||
newPipeline = fillPipelineByDefaultForm(newPipeline, form);
|
||||
//填充模版参数
|
||||
const steps: any = {};
|
||||
eachSteps(newPipeline, (step: any) => {
|
||||
steps[step.id] = step;
|
||||
|
||||
await createPipelineByTemplate({
|
||||
templateId: parseInt(templateId),
|
||||
templateForm: tempInputs,
|
||||
pipeline: newPipeline,
|
||||
title: title,
|
||||
groupId: form.groupId,
|
||||
});
|
||||
progress.value.current = progress.value.current + 1;
|
||||
}
|
||||
notification.success({
|
||||
message: "导入完成",
|
||||
});
|
||||
|
||||
for (const inputKey in tempInputs) {
|
||||
const [stepId, key] = inputKey.split(".");
|
||||
const step = steps[stepId];
|
||||
if (step) {
|
||||
step.input[key] = tempInputs[inputKey];
|
||||
importTableRef.clear();
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
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