diff --git a/packages/ui/certd-client/src/locales/i18n.ts b/packages/ui/certd-client/src/locales/i18n.ts index 63210113..ec966bcb 100644 --- a/packages/ui/certd-client/src/locales/i18n.ts +++ b/packages/ui/certd-client/src/locales/i18n.ts @@ -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; diff --git a/packages/ui/certd-client/src/locales/index.ts b/packages/ui/certd-client/src/locales/index.ts index 3ae503d0..2cfd2164 100644 --- a/packages/ui/certd-client/src/locales/index.ts +++ b/packages/ui/certd-client/src/locales/index.ts @@ -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"; diff --git a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/use.tsx b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/use.tsx index a02dbfc8..f1edd6c4 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/use.tsx +++ b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/use.tsx @@ -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 ( - - ); - }, - }, - 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 ( + + ); + }, + }, + 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, + }; } diff --git a/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx b/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx index 3a82cd4d..d0a900c5 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx @@ -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,471 +13,474 @@ 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 router = useRouter(); + const lastResRef = ref(); - const { openAddCertdPipelineDialog } = useCertPipelineCreator(); - const { openUploadCreateDialog } = useCertUpload(); + const { t } = useI18n(); - const pageRequest = async (query: UserPageQuery): Promise => { - return await api.GetList(query); - }; - const editRequest = async ({ form, row }: EditReq) => { - form.id = row.id; - const res = await api.UpdateObj(form); - lastResRef.value = res; - return res; - }; - const delRequest = async ({ row }: DelReq) => { - return await api.DelObj(row.id); - }; + const { openAddCertdPipelineDialog } = useCertPipelineCreator(); + const { openUploadCreateDialog } = useCertUpload(); - const addRequest = async ({ form }: AddReq) => { - if (form.content == null) { - form.content = JSON.stringify({ - title: form.title, - }); - } else { - //复制的流水线 - delete form.status; - delete form.lastHistoryTime; - delete form.lastVars; - delete form.createTime; - delete form.id; - let pipeline = JSON.parse(form.content); - pipeline.title = form.title; - pipeline = setRunnableIds(pipeline); - form.content = JSON.stringify(pipeline); - } + const pageRequest = async (query: UserPageQuery): Promise => { + return await api.GetList(query); + }; + const editRequest = async ({ form, row }: EditReq) => { + form.id = row.id; + const res = await api.UpdateObj(form); + lastResRef.value = res; + return res; + }; + const delRequest = async ({ row }: DelReq) => { + return await api.DelObj(row.id); + }; - const res = await api.AddObj(form); - lastResRef.value = res; - return res; - }; + const addRequest = async ({ form }: AddReq) => { + if (form.content == null) { + form.content = JSON.stringify({ + title: form.title, + }); + } else { + //复制的流水线 + delete form.status; + delete form.lastHistoryTime; + delete form.lastVars; + delete form.createTime; + delete form.id; + let pipeline = JSON.parse(form.content); + pipeline.title = form.title; + pipeline = setRunnableIds(pipeline); + form.content = JSON.stringify(pipeline); + } - const { viewCert, downloadCert } = useCertViewer(); - const userStore = useUserStore(); - const settingStore = useSettingStore(); + const res = await api.AddObj(form); + lastResRef.value = res; + return res; + }; - function onDialogOpen(opt: any) { - const searchForm = crudExpose.getSearchValidatedFormData(); - opt.initialForm = { - ...opt.initialForm, - groupId: searchForm.groupId, - }; - } + const { viewCert, downloadCert } = useCertViewer(); + const userStore = useUserStore(); + const settingStore = useSettingStore(); - return { - crudOptions: { - request: { - pageRequest, - addRequest, - editRequest, - delRequest, - }, - settings: { - plugins: { - //行选择插件,内置插件 - rowSelection: { - //是否启用本插件 - enabled: true, - order: -2, - //合并在用户配置crudOptions之前还是之后 - before: true, - props: { - multiple: true, - crossPage: false, - selectedRowKeys, - onSelectedChanged(selected) { - console.log("已选择变化:", selected); - }, - }, - }, - }, - }, - actionbar: { - buttons: { - add: { - order: 5, - icon: "ion:ios-add-circle-outline", - text: t("certd.customPipeline"), - }, - addCertd: { - order: 1, - text: t("certd.createCertdPipeline"), - type: "primary", - icon: "ion:ios-add-circle-outline", - click() { - const searchForm = crudExpose.getSearchValidatedFormData(); - const defaultGroupId = searchForm.groupId; - openAddCertdPipelineDialog({ defaultGroupId }); - }, - }, - uploadCert: { - order: 2, - text: t("certd.commercialCertHosting"), - type: "primary", - tooltip: { - slots: { - title() { - return ( - - ); - }, - }, - }, - icon: "ion:cloud-upload-outline", - click() { - const searchForm = crudExpose.getSearchValidatedFormData(); - openUploadCreateDialog({ defaultGroupId: searchForm.groupId }); - }, - }, - }, - }, - form: { - afterSubmit({ form, res, mode }) { - if (mode === "add") { - router.push({ path: "/certd/pipeline/detail", query: { id: res.id, editMode: "true" } }); - } - }, - wrapper: { - onOpen: onDialogOpen, - }, - }, - table: { - scroll: { x: 1500 }, - remove: { - confirmTitle: t("certd.table.confirmDeleteTitle"), - confirmMessage: t("certd.table.confirmDeleteMessage"), - }, - }, - tabs: { - name: "groupId", - show: true, - }, - rowHandle: { - width: 200, - fixed: "right", - dropdown: { - show: true, - }, - buttons: { - play: { - order: -999, - title: t("certd.play.runPipeline"), - tooltip: { title: t("certd.play.runPipeline") }, - type: "link", - icon: "ant-design:play-circle-outlined", - click({ row }) { - Modal.confirm({ - title: t("certd.play.confirm"), - content: t("certd.play.confirmTrigger"), - async onOk() { - await api.Trigger(row.id); - notification.success({ message: t("certd.play.pipelineStarted") }); - }, - }); - }, - }, - view: { - show: false, - click({ row }) { - router.push({ path: "/certd/pipeline/detail", query: { id: row.id, editMode: "false" } }); - }, - }, - copy: { - click: async context => { - settingStore.checkPlus(); - const { ui } = useUi(); - // @ts-ignore - let row = context[ui.tableColumn.row]; - row = cloneDeep(row); - row.title = row.title + "_copy"; - await crudExpose.openCopy({ - row: row, - index: context.index, - }); - }, - class: "need-plus", - }, - config: { - order: 1, - title: t("certd.actions.editPipeline"), - type: "link", - dropdown: true, - icon: "ant-design:edit-outlined", - click({ row }) { - router.push({ path: "/certd/pipeline/detail", query: { id: row.id, editMode: "true" } }); - }, - }, - edit: { - order: 2, - title: t("certd.actions.editConfigGroup"), - icon: "ant-design:setting-outlined", - dropdown: true, - }, - viewCert: { - order: 3, - title: t("certd.actions.viewCertificate"), - tooltip: { title: t("certd.actions.viewCertificate") }, - type: "link", - icon: "ph:certificate", - async click({ row }) { - await viewCert(row.id); - }, - }, - download: { - order: 4, - type: "link", - title: t("certd.actions.downloadCertificate"), - tooltip: { title: t("certd.actions.downloadCertificate") }, - icon: "ant-design:download-outlined", - async click({ row }) { - await downloadCert(row.id); - }, - }, - remove: { - order: 5, - dropdown: true, - }, - }, - }, - columns: { - id: { - title: "ID", - key: "id", - type: "number", - search: { - show: true, - }, - column: { - width: 100, - }, - form: { - show: false, - }, - }, - userId: { - title: t("certd.fields.userId"), - type: "number", - search: { - show: computed(() => { - return userStore.isAdmin && settingStore.sysPublic.managerOtherUserPipeline; - }), - }, - form: { - show: false, - }, - column: { - show: computed(() => { - return userStore.isAdmin && settingStore.sysPublic.managerOtherUserPipeline; - }), - width: 100, - }, - }, - title: { - title: t("certd.fields.pipelineName"), - type: "link", - search: { - show: true, - title: t("certd.fields.keyword"), - component: { - name: "a-input", - }, - }, - form: { - rules: [{ required: true, message: t("certd.fields.required") }], - }, - column: { - width: 350, - ellipsis: true, - sorter: true, - showTitle: true, - cellRender: ({ row, value }) => { - return {value}; - }, - }, - }, - content: { - title: t("certd.fields.pipelineContent"), - form: { show: false }, - column: { - show: false, - }, - valueBuilder({ row }) { - if (row.content) { - row.content = JSON.parse(row.content); - const pipeline = row.content; - let stepCount = 0; - eachStages(pipeline.stages, (item, runnableType) => { - if (runnableType === "step") { - stepCount++; - } - }); - row._stepCount = stepCount; - if (pipeline.triggers) { - row._triggerCount = pipeline.triggers?.length > 0 ? pipeline.triggers.length : "-"; - } - } - }, - valueResolve({ row }) { - if (row.content) { - row.content = JSON.stringify(row.content); - } - }, - }, - _triggerCount: { - title: t("certd.fields.scheduledTaskCount"), - type: "number", - column: { - align: "center", - width: 100, - }, - form: { - show: false, - }, - }, - _stepCount: { - title: t("certd.fields.deployTaskCount"), - type: "number", - form: { show: false }, - column: { - align: "center", - width: 100, - }, - }, - lastVars: { - title: t("certd.fields.remainingValidity"), - type: "number", - form: { - show: false, - }, - column: { - cellRender({ row }) { - if (!row.lastVars?.certExpiresTime) { - return "-"; - } - const leftDays = dayjs(row.lastVars.certExpiresTime).diff(dayjs(), "day"); - const color = leftDays < 20 ? "red" : "#389e0d"; - const percent = (leftDays / 90) * 100; - return `${leftDays} 天`} />; - }, - width: 150, - }, - }, - "lastVars.certExpiresTime": { - title: t("certd.fields.expiryTime"), - search: { - show: false, - }, - type: "datetime", - form: { - show: false, - }, - column: { - sorter: false, - width: 150, - align: "center", - }, - }, - status: { - title: t("certd.fields.status"), - type: "dict-select", - search: { - show: true, - }, - dict: dict({ - data: statusUtil.getOptions(), - }), - form: { - show: false, - }, - column: { - sorter: true, - width: 120, - align: "center", - }, - }, - lastHistoryTime: { - title: t("certd.fields.lastRun"), - type: "datetime", - form: { - show: false, - }, - column: { - sorter: true, - width: 150, - align: "center", - }, - }, - disabled: { - title: t("certd.fields.enabled"), - type: "dict-switch", - dict: dict({ - data: [ - { value: false, label: t("certd.fields.enabledLabel") }, - { value: true, label: t("certd.fields.disabledLabel") }, - ], - }), - form: { - value: false, - show: false, - }, - column: { - sorter: true, - width: 80, - align: "center", - component: { - name: "fs-dict-switch", - vModel: "checked", - }, - async valueChange({ row, key, value }) { - return await api.UpdateObj({ - id: row.id, - disabled: row[key], - }); - }, - }, - }, - groupId: { - title: t("certd.fields.group"), - type: "dict-select", - search: { - show: true, - }, - dict: groupDictRef, - form: { - component: { - name: GroupSelector, - vModel: "modelValue", - }, - }, - column: { - width: 130, - align: "center", - component: { - color: "auto", - }, - sorter: true, - }, - }, - type: { - title: t("certd.fields.type"), - type: "dict-select", - search: { - show: true, - }, - dict: dict({ - data: [ - { value: "cert", label: t("certd.types.certApply") }, - { value: "cert_upload", label: t("certd.types.certUpload") }, - { value: "custom", label: t("certd.types.custom") }, + function onDialogOpen(opt: any) { + const searchForm = crudExpose.getSearchValidatedFormData(); + opt.initialForm = { + ...opt.initialForm, + groupId: searchForm.groupId, + }; + } + + return { + crudOptions: { + request: { + pageRequest, + addRequest, + editRequest, + delRequest, + }, + settings: { + plugins: { + //行选择插件,内置插件 + rowSelection: { + //是否启用本插件 + enabled: true, + order: -2, + //合并在用户配置crudOptions之前还是之后 + before: true, + props: { + multiple: true, + crossPage: false, + selectedRowKeys, + onSelectedChanged(selected) { + console.log("已选择变化:", selected); + }, + }, + }, + }, + }, + actionbar: { + buttons: { + add: { + order: 5, + icon: "ion:ios-add-circle-outline", + text: t("certd.customPipeline"), + }, + addCertd: { + order: 1, + text: t("certd.createCertdPipeline"), + type: "primary", + icon: "ion:ios-add-circle-outline", + click() { + const searchForm = crudExpose.getSearchValidatedFormData(); + const defaultGroupId = searchForm.groupId; + openAddCertdPipelineDialog({ defaultGroupId }); + }, + }, + uploadCert: { + order: 2, + text: t("certd.commercialCertHosting"), + type: "primary", + tooltip: { + slots: { + title() { + return ( +
    +
  • {t("certd.tooltip.manualUploadOwnCert")}
  • +
  • {t("certd.tooltip.noAutoApplyCommercialCert")}
  • +
  • {t("certd.tooltip.manualUploadOnUpdate")}
  • +
+ ); + }, + }, + }, + icon: "ion:cloud-upload-outline", + click() { + const searchForm = crudExpose.getSearchValidatedFormData(); + openUploadCreateDialog({ defaultGroupId: searchForm.groupId }); + }, + }, + }, + }, + form: { + afterSubmit({ form, res, mode }) { + if (mode === "add") { + router.push({ path: "/certd/pipeline/detail", query: { id: res.id, editMode: "true" } }); + } + }, + wrapper: { + onOpen: onDialogOpen, + }, + }, + table: { + scroll: { x: 1500 }, + remove: { + confirmTitle: t("certd.table.confirmDeleteTitle"), + confirmMessage: t("certd.table.confirmDeleteMessage"), + }, + }, + tabs: { + name: "groupId", + show: true, + }, + rowHandle: { + width: 200, + fixed: "right", + dropdown: { + show: true, + }, + buttons: { + play: { + order: -999, + title: t("certd.play.runPipeline"), + tooltip: { title: t("certd.play.runPipeline") }, + type: "link", + icon: "ant-design:play-circle-outlined", + click({ row }) { + Modal.confirm({ + title: t("certd.play.confirm"), + content: t("certd.play.confirmTrigger"), + async onOk() { + await api.Trigger(row.id); + notification.success({ message: t("certd.play.pipelineStarted") }); + }, + }); + }, + }, + view: { + show: false, + click({ row }) { + router.push({ path: "/certd/pipeline/detail", query: { id: row.id, editMode: "false" } }); + }, + }, + copy: { + click: async context => { + settingStore.checkPlus(); + const { ui } = useUi(); + // @ts-ignore + let row = context[ui.tableColumn.row]; + row = cloneDeep(row); + row.title = row.title + "_copy"; + await crudExpose.openCopy({ + row: row, + index: context.index, + }); + }, + class: "need-plus", + }, + config: { + order: 1, + title: t("certd.actions.editPipeline"), + type: "link", + dropdown: true, + icon: "ant-design:edit-outlined", + click({ row }) { + router.push({ path: "/certd/pipeline/detail", query: { id: row.id, editMode: "true" } }); + }, + }, + edit: { + order: 2, + title: t("certd.actions.editConfigGroup"), + icon: "ant-design:setting-outlined", + dropdown: true, + }, + viewCert: { + order: 3, + title: t("certd.actions.viewCertificate"), + tooltip: { title: t("certd.actions.viewCertificate") }, + type: "link", + icon: "ph:certificate", + async click({ row }) { + await viewCert(row.id); + }, + }, + download: { + order: 4, + type: "link", + title: t("certd.actions.downloadCertificate"), + tooltip: { title: t("certd.actions.downloadCertificate") }, + icon: "ant-design:download-outlined", + async click({ row }) { + await downloadCert(row.id); + }, + }, + remove: { + order: 5, + dropdown: true, + }, + }, + }, + columns: { + id: { + title: "ID", + key: "id", + type: "number", + search: { + show: true, + }, + column: { + width: 100, + }, + form: { + show: false, + }, + }, + userId: { + title: t("certd.fields.userId"), + type: "number", + search: { + show: computed(() => { + return userStore.isAdmin && settingStore.sysPublic.managerOtherUserPipeline; + }), + }, + form: { + show: false, + }, + column: { + show: computed(() => { + return userStore.isAdmin && settingStore.sysPublic.managerOtherUserPipeline; + }), + width: 100, + }, + }, + title: { + title: t("certd.fields.pipelineName"), + type: "link", + search: { + show: true, + title: t("certd.fields.keyword"), + component: { + name: "a-input", + }, + }, + form: { + rules: [{ required: true, message: t("certd.fields.required") }], + }, + column: { + width: 350, + ellipsis: true, + sorter: true, + showTitle: true, + cellRender: ({ row, value }) => { + return {value}; + }, + }, + }, + content: { + title: t("certd.fields.pipelineContent"), + form: { show: false }, + column: { + show: false, + }, + valueBuilder({ row }) { + if (row.content) { + row.content = JSON.parse(row.content); + const pipeline = row.content; + let stepCount = 0; + eachStages(pipeline.stages, (item, runnableType) => { + if (runnableType === "step") { + stepCount++; + } + }); + row._stepCount = stepCount; + if (pipeline.triggers) { + row._triggerCount = pipeline.triggers?.length > 0 ? pipeline.triggers.length : "-"; + } + } + }, + valueResolve({ row }) { + if (row.content) { + row.content = JSON.stringify(row.content); + } + }, + }, + _triggerCount: { + title: t("certd.fields.scheduledTaskCount"), + type: "number", + column: { + align: "center", + width: 100, + }, + form: { + show: false, + }, + }, + _stepCount: { + title: t("certd.fields.deployTaskCount"), + type: "number", + form: { show: false }, + column: { + align: "center", + width: 100, + }, + }, + lastVars: { + title: t("certd.fields.remainingValidity"), + type: "number", + form: { + show: false, + }, + column: { + cellRender({ row }) { + if (!row.lastVars?.certExpiresTime) { + return "-"; + } + const leftDays = dayjs(row.lastVars.certExpiresTime).diff(dayjs(), "day"); + const color = leftDays < 20 ? "red" : "#389e0d"; + const percent = (leftDays / 90) * 100; + return `${leftDays} 天`} />; + }, + width: 150, + }, + }, + "lastVars.certExpiresTime": { + title: t("certd.fields.expiryTime"), + search: { + show: false, + }, + type: "datetime", + form: { + show: false, + }, + column: { + sorter: false, + width: 150, + align: "center", + }, + }, + status: { + title: t("certd.fields.status"), + type: "dict-select", + search: { + show: true, + }, + dict: dict({ + data: statusUtil.getOptions(), + }), + form: { + show: false, + }, + column: { + sorter: true, + width: 120, + align: "center", + }, + }, + lastHistoryTime: { + title: t("certd.fields.lastRun"), + type: "datetime", + form: { + show: false, + }, + column: { + sorter: true, + width: 150, + align: "center", + }, + }, + disabled: { + title: t("certd.fields.enabled"), + type: "dict-switch", + dict: dict({ + data: [ + { value: false, label: t("certd.fields.enabledLabel") }, + { value: true, label: t("certd.fields.disabledLabel") }, + ], + }), + form: { + value: false, + show: false, + }, + column: { + sorter: true, + width: 80, + align: "center", + component: { + name: "fs-dict-switch", + vModel: "checked", + }, + async valueChange({ row, key, value }) { + return await api.UpdateObj({ + id: row.id, + disabled: row[key], + }); + }, + }, + }, + groupId: { + title: t("certd.fields.group"), + type: "dict-select", + search: { + show: true, + }, + dict: groupDictRef, + form: { + component: { + name: GroupSelector, + vModel: "modelValue", + }, + }, + column: { + width: 130, + align: "center", + component: { + color: "auto", + }, + sorter: true, + }, + }, + type: { + title: t("certd.fields.type"), + type: "dict-select", + search: { + show: true, + }, + dict: dict({ + data: [ + { value: "cert", label: t("certd.types.certApply") }, + { value: "cert_upload", label: t("certd.types.certUpload") }, + { value: "custom", label: t("certd.types.custom") }, { value: "template", label: "模版" }, ], }), @@ -498,55 +500,54 @@ export default function ({ crudExpose, context: { groupDictRef, selectedRowKeys }, order: { title: t("certd.fields.order"), - type: "number", - column: { - sorter: true, - align: "center", - width: 80, - }, - form: { - value: 0, - }, - }, - keepHistoryCount: { - title: t("certd.fields.keepHistoryCount"), - type: "number", - form: { - value: 20, - helper: t("certd.fields.keepHistoryHelper"), - }, - column: { - width: 130, - show: false, - sorter: true, - }, - }, - createTime: { - title: t("certd.fields.createTime"), - type: "datetime", - form: { - show: false, - }, - column: { - sorter: true, - width: 155, - align: "center", - }, - }, - updateTime: { - title: t("certd.fields.updateTime"), - type: "datetime", - form: { - show: false, - }, - column: { - width: 125, - show: false, - sorter: true, - }, - }, - - }, - }, - }; + type: "number", + column: { + sorter: true, + align: "center", + width: 80, + }, + form: { + value: 0, + }, + }, + keepHistoryCount: { + title: t("certd.fields.keepHistoryCount"), + type: "number", + form: { + value: 20, + helper: t("certd.fields.keepHistoryHelper"), + }, + column: { + width: 130, + show: false, + sorter: true, + }, + }, + createTime: { + title: t("certd.fields.createTime"), + type: "datetime", + form: { + show: false, + }, + column: { + sorter: true, + width: 155, + align: "center", + }, + }, + updateTime: { + title: t("certd.fields.updateTime"), + type: "datetime", + form: { + show: false, + }, + column: { + width: 125, + show: false, + sorter: true, + }, + }, + }, + }, + }; } diff --git a/packages/ui/certd-client/src/views/certd/pipeline/index.vue b/packages/ui/certd-client/src/views/certd/pipeline/index.vue index 01a77c1c..4e7e131d 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/index.vue +++ b/packages/ui/certd-client/src/views/certd/pipeline/index.vue @@ -22,7 +22,6 @@ - diff --git a/packages/ui/certd-client/src/views/certd/pipeline/template/import/table.vue b/packages/ui/certd-client/src/views/certd/pipeline/template/import/table.vue index 32bfc4f6..dd2a2943 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/template/import/table.vue +++ b/packages/ui/certd-client/src/views/certd/pipeline/template/import/table.vue @@ -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 = []; + }, }); diff --git a/packages/ui/certd-client/src/views/certd/pipeline/template/use.tsx b/packages/ui/certd-client/src/views/certd/pipeline/template/use.tsx index ab8fe4a9..a781bbb3 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/template/use.tsx +++ b/packages/ui/certd-client/src/views/certd/pipeline/template/use.tsx @@ -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 });