diff --git a/packages/core/pipeline/src/core/executor.ts b/packages/core/pipeline/src/core/executor.ts index adb60bec1..9e9c0ffbe 100644 --- a/packages/core/pipeline/src/core/executor.ts +++ b/packages/core/pipeline/src/core/executor.ts @@ -307,13 +307,15 @@ export class Executor { //更新pipeline vars if (Object.keys(instance._result.pipelineVars).length > 0) { // 判断 pipelineVars 有值时更新 - const vars = await this.pipelineContext.getObj("vars"); + let vars = await this.pipelineContext.getObj("vars"); + vars = vars || {}; merge(vars, instance._result.pipelineVars); await this.pipelineContext.setObj("vars", vars); } if (Object.keys(instance._result.pipelinePrivateVars).length > 0) { // 判断 pipelineVars 有值时更新 - const vars = await this.pipelineContext.getObj("privateVars"); + let vars = await this.pipelineContext.getObj("privateVars"); + vars = vars || {}; merge(vars, instance._result.pipelinePrivateVars); await this.pipelineContext.setObj("privateVars", vars); } diff --git a/packages/core/pipeline/src/core/run-history.ts b/packages/core/pipeline/src/core/run-history.ts index dbf3e6881..b4a69e7ad 100644 --- a/packages/core/pipeline/src/core/run-history.ts +++ b/packages/core/pipeline/src/core/run-history.ts @@ -38,7 +38,7 @@ export class RunHistory { start(runnable: Runnable): HistoryResult { const now = new Date().getTime(); this.logs[runnable.id] = []; - this._loggers[runnable.id] = buildLogger((text) => { + this._loggers[runnable.id] = buildLogger((text: string) => { this.logs[runnable.id].push(text); }); const status: HistoryResult = { diff --git a/packages/plugins/plugin-cert/src/plugin/cert-plugin/index.ts b/packages/plugins/plugin-cert/src/plugin/cert-plugin/index.ts index 0681f53d9..32161a2a0 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/index.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/index.ts @@ -166,7 +166,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin { mergeScript: ` return { show: ctx.compute(({form})=>{ - return (form.sslProvider === 'zerossl' || !form.zerosslCommonEabAccessId) || (form.sslProvider === 'google' && !form.googleCommonEabAccessId) + return (form.sslProvider === 'zerossl' && !form.zerosslCommonEabAccessId) || (form.sslProvider === 'google' && !form.googleCommonEabAccessId) }) } `, diff --git a/packages/ui/certd-client/src/App.vue b/packages/ui/certd-client/src/App.vue index 8357be321..d1e432ab4 100644 --- a/packages/ui/certd-client/src/App.vue +++ b/packages/ui/certd-client/src/App.vue @@ -1,12 +1,13 @@ + - diff --git a/packages/ui/certd-client/src/components/plugins/synology/device-id-getter.vue b/packages/ui/certd-client/src/components/plugins/synology/device-id-getter.vue index e80dc8893..7215365d7 100644 --- a/packages/ui/certd-client/src/components/plugins/synology/device-id-getter.vue +++ b/packages/ui/certd-client/src/components/plugins/synology/device-id-getter.vue @@ -43,7 +43,6 @@ async function loginWithOTPCode(otpCode: string) { const [modal, contextHolder] = Modal.useModal(); async function getDeviceId() { //打开对话框 - modal.confirm({ title: "请输入OTP验证码", maskClosable: true, diff --git a/packages/ui/certd-client/src/style/common.less b/packages/ui/certd-client/src/style/common.less index 8835d6f7c..13d8b97c0 100644 --- a/packages/ui/certd-client/src/style/common.less +++ b/packages/ui/certd-client/src/style/common.less @@ -213,6 +213,7 @@ h1, h2, h3, h4, h5, h6 { .fs-copyable { + display: inline-flex; .text { flex: 1 } diff --git a/packages/ui/certd-client/src/use/use-modal.ts b/packages/ui/certd-client/src/use/use-modal.ts new file mode 100644 index 000000000..bdf5751be --- /dev/null +++ b/packages/ui/certd-client/src/use/use-modal.ts @@ -0,0 +1,7 @@ +import { inject } from "vue"; +import type { ModalStaticFunctions } from "ant-design-vue/es/modal/confirm"; +import { ModalFuncWithRef } from "ant-design-vue/es/modal/useModal"; + +export function useModal(): ModalStaticFunctions { + return inject("modal"); +} diff --git a/packages/ui/certd-client/src/views/certd/pipeline/cert-view.vue b/packages/ui/certd-client/src/views/certd/pipeline/cert-view.vue new file mode 100644 index 000000000..518ffa16d --- /dev/null +++ b/packages/ui/certd-client/src/views/certd/pipeline/cert-view.vue @@ -0,0 +1,50 @@ + + + + + + + + + {{ item.name }}({{ item.fileName }}) + + 复制 + + + + + + + + + + + + + + + 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 df99df5a3..5578b23a3 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/pipeline/crud.tsx @@ -11,7 +11,9 @@ import { useUserStore } from "/@/store/modules/user"; import dayjs from "dayjs"; import { useSettingStore } from "/@/store/modules/settings"; import _ from "lodash-es"; - +import { useModal } from "/@/use/use-modal"; +import CertView from "./cert-view.vue"; +import { eachRunnable, eachStages } from "./utils"; export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOptionsProps): CreateCrudOptionsRet { const router = useRouter(); const { t } = useI18n(); @@ -149,6 +151,7 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp }); } + const model = useModal(); const viewCert = async (row: any) => { const cert = await api.GetCert(row.id); if (!cert) { @@ -156,34 +159,20 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp return; } - Modal.success({ + model.success({ title: "查看证书", maskClosable: true, okText: "关闭", + width: 800, content: () => { - return ( - - - fullchain.pem - {cert.crt} - - - private.pem - {cert.key} - - - 中间证书.pem - {cert.ic} - - - ); + return ; } }); }; const downloadCert = async (row: any) => { const files = await api.GetFiles(row.id); - Modal.success({ + model.success({ title: "文件下载", maskClosable: true, okText: "↑↑↑ 点击上面链接下载", @@ -198,11 +187,6 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp {file.filename} - - - 直接查看证书 - - ); } @@ -253,7 +237,7 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp buttons: { play: { order: -999, - title: null, + title: "运行流水线", type: "link", icon: "ant-design:play-circle-outlined", click({ row }) { @@ -268,6 +252,7 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp } }, view: { + show: false, click({ row }) { router.push({ path: "/certd/pipeline/detail", query: { id: row.id, editMode: "false" } }); } @@ -289,7 +274,7 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp }, config: { order: 1, - title: null, + title: "修改流水线内容", type: "link", icon: "ant-design:edit-outlined", click({ row }) { @@ -298,12 +283,22 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp }, edit: { order: 2, + title: "修改流水线运行配置", icon: "ant-design:setting-outlined" }, - download: { + viewCert: { order: 3, - title: null, + title: "查看证书", type: "link", + icon: "ph:certificate", + async click({ row }) { + viewCert(row); + } + }, + download: { + order: 4, + type: "link", + title: "下载证书", icon: "ant-design:download-outlined", async click({ row }) { downloadCert(row); @@ -373,32 +368,53 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp } }, content: { - title: "定时任务数", - type: "number", + title: "流水线内容", + form: { show: false }, column: { - align: "center", - width: 100, - cellRender({ value }) { - if (value && value.triggers) { - return value.triggers?.length > 0 ? value.triggers.length : "-"; - } - return "-"; - } + 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: "定时任务数", + type: "number", + column: { + align: "center", + width: 100 }, form: { show: false } }, + _stepCount: { + title: "部署任务数", + type: "number", + form: { show: false }, + column: { + align: "center", + width: 100 + } + }, lastVars: { title: "到期剩余", type: "number", @@ -418,18 +434,6 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp width: 150 } }, - lastHistoryTime: { - title: "最后运行", - type: "datetime", - form: { - show: false - }, - column: { - sorter: true, - width: 150, - align: "center" - } - }, status: { title: "状态", type: "dict-select", @@ -445,7 +449,18 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp align: "center" } }, - + lastHistoryTime: { + title: "最后运行", + type: "datetime", + form: { + show: false + }, + column: { + sorter: true, + width: 150, + align: "center" + } + }, disabled: { title: "启用", type: "dict-switch", diff --git a/packages/ui/certd-client/src/views/certd/pipeline/utils.ts b/packages/ui/certd-client/src/views/certd/pipeline/utils.ts new file mode 100644 index 000000000..6d0477f0a --- /dev/null +++ b/packages/ui/certd-client/src/views/certd/pipeline/utils.ts @@ -0,0 +1,15 @@ +import { forEach } from "lodash-es"; + +export function eachStages(list: any[], exec: (item: any, runnableType: string) => void, runnableType: string = "stage") { + if (!list || list.length <= 0) { + return; + } + forEach(list, (item) => { + exec(item, runnableType); + if (runnableType === "stage") { + eachStages(item.tasks, exec, "task"); + } else if (runnableType === "task") { + eachStages(item.steps, exec, "step"); + } + }); +} diff --git a/packages/ui/certd-server/src/controller/pipeline/cert-controller.ts b/packages/ui/certd-server/src/controller/pipeline/cert-controller.ts index 4f5186eea..2196eef8d 100644 --- a/packages/ui/certd-server/src/controller/pipeline/cert-controller.ts +++ b/packages/ui/certd-server/src/controller/pipeline/cert-controller.ts @@ -15,7 +15,7 @@ export class CertController extends BaseController { async getCert(@Query('id') id: number) { const userId = this.getUserId(); await this.pipelineService.checkUserId(id, userId); - const privateVars = this.storeService.getPipelinePrivateVars(id); - return this.ok(privateVars); + const privateVars = await this.storeService.getPipelinePrivateVars(id); + return this.ok(privateVars.cert); } } diff --git a/packages/ui/certd-server/src/modules/pipeline/service/storage-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/storage-service.ts index e77880235..0f5c77b42 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/storage-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/storage-service.ts @@ -60,12 +60,17 @@ export class StorageService extends BaseService { if (pipelineId == null) { throw new Error('pipelineId 不能为空'); } - return await this.repository.find({ + const res = await this.repository.findOne({ where: { scope: 'pipeline', namespace: pipelineId + '', key: 'privateVars', }, }); + if (!res) { + return {}; + } + const value = JSON.parse(res.value); + return value.value; } } diff --git a/packages/ui/certd-server/src/plugins/plugin-host/plugin/host-shell-execute/index.ts b/packages/ui/certd-server/src/plugins/plugin-host/plugin/host-shell-execute/index.ts index 0683c7b23..e64798cc0 100644 --- a/packages/ui/certd-server/src/plugins/plugin-host/plugin/host-shell-execute/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-host/plugin/host-shell-execute/index.ts @@ -31,6 +31,7 @@ export class HostShellExecutePlugin extends AbstractTaskPlugin { name: 'a-textarea', vModel: 'value', rows: 6, + placeholder: 'systemctl restart nginx', }, helper: '注意:如果目标主机是windows,且终端是cmd,系统会自动将多行命令通过“&&”连接成一行', required: true,