From 26b395110c3dda5f805e4eb1a2ee18a28546308e Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Thu, 19 Jun 2025 18:17:35 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E6=B5=81=E6=B0=B4=E7=BA=BF=E6=A8=A1?= =?UTF-8?q?=E7=89=88=E5=88=9D=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugins/plugin-lib/src/common/util.ts | 1 + .../src/router/source/modules/certd.ts | 18 +++ .../ui/certd-client/src/store/plugin/index.ts | 3 + .../ui/certd-client/src/style/common.less | 7 + .../src/views/certd/pipeline/template/api.ts | 59 ++++++++ .../views/certd/pipeline/template/crud.tsx | 113 +++++++++++++++ .../views/certd/pipeline/template/edit.vue | 135 ++++++++++++++++++ .../views/certd/pipeline/template/index.vue | 30 ++++ .../db/migration/v10026__template.sql | 15 ++ .../user/pipeline/template-controller.ts | 77 ++++++++++ .../src/modules/pipeline/entity/template.ts | 52 +++++++ .../pipeline/service/template-service.ts | 41 ++++++ .../plugin/deploy-to-cdn/index.ts | 1 + 13 files changed, 552 insertions(+) create mode 100644 packages/ui/certd-client/src/views/certd/pipeline/template/api.ts create mode 100644 packages/ui/certd-client/src/views/certd/pipeline/template/crud.tsx create mode 100644 packages/ui/certd-client/src/views/certd/pipeline/template/edit.vue create mode 100644 packages/ui/certd-client/src/views/certd/pipeline/template/index.vue create mode 100644 packages/ui/certd-server/db/migration/v10026__template.sql create mode 100644 packages/ui/certd-server/src/controller/user/pipeline/template-controller.ts create mode 100644 packages/ui/certd-server/src/modules/pipeline/entity/template.ts create mode 100644 packages/ui/certd-server/src/modules/pipeline/service/template-service.ts diff --git a/packages/plugins/plugin-lib/src/common/util.ts b/packages/plugins/plugin-lib/src/common/util.ts index beaf1585..f474226a 100644 --- a/packages/plugins/plugin-lib/src/common/util.ts +++ b/packages/plugins/plugin-lib/src/common/util.ts @@ -17,6 +17,7 @@ export function createCertDomainGetterInputDefine(opts?: { certInputKey?: string } } `, + template:false, required: true, }, opts?.props diff --git a/packages/ui/certd-client/src/router/source/modules/certd.ts b/packages/ui/certd-client/src/router/source/modules/certd.ts index 77b81e0a..7c93924d 100644 --- a/packages/ui/certd-client/src/router/source/modules/certd.ts +++ b/packages/ui/certd-client/src/router/source/modules/certd.ts @@ -32,6 +32,24 @@ export const certdResources = [ isMenu: false, }, }, + { + title: "流水线模版", + name: "PipelineTemplate", + path: "/certd/pipeline/template", + component: "/certd/pipeline/template/index.vue", + meta: { + isMenu: true, + }, + }, + { + title: "流水线模版编辑", + name: "PipelineTemplateEdit", + path: "/certd/pipeline/template/edit", + component: "/certd/pipeline/template/edit.vue", + meta: { + isMenu: false, + }, + }, { title: "执行历史记录", name: "PipelineHistory", diff --git a/packages/ui/certd-client/src/store/plugin/index.ts b/packages/ui/certd-client/src/store/plugin/index.ts index 842749ee..17de169b 100644 --- a/packages/ui/certd-client/src/store/plugin/index.ts +++ b/packages/ui/certd-client/src/store/plugin/index.ts @@ -157,5 +157,8 @@ export const usePluginStore = defineStore({ async getPluginConfig(query: any) { return await api.GetPluginConfig(query); }, + getPluginDefineSync(name: string) { + return this.group.get(name); + }, }, }); diff --git a/packages/ui/certd-client/src/style/common.less b/packages/ui/certd-client/src/style/common.less index f66261cb..27dbf9dc 100644 --- a/packages/ui/certd-client/src/style/common.less +++ b/packages/ui/certd-client/src/style/common.less @@ -300,4 +300,11 @@ h1, h2, h3, h4, h5, h6 { .ant-drawer-content-wrapper { max-width: 90vw; +} + + +.block-title{ + font-size: 14px; + padding:10px; + color : #6e6e6e; } \ No newline at end of file diff --git a/packages/ui/certd-client/src/views/certd/pipeline/template/api.ts b/packages/ui/certd-client/src/views/certd/pipeline/template/api.ts new file mode 100644 index 00000000..121351f3 --- /dev/null +++ b/packages/ui/certd-client/src/views/certd/pipeline/template/api.ts @@ -0,0 +1,59 @@ +import { request } from "/src/api/service"; +import { CertInfo } from "/@/views/certd/pipeline/api"; + +const apiPrefix = "/pi/template"; +export const templateApi = { + async GetList(query: any) { + return await request({ + url: apiPrefix + "/page", + method: "post", + data: query, + }); + }, + + async AddObj(obj: any) { + return await request({ + url: apiPrefix + "/add", + method: "post", + data: obj, + }); + }, + + async UpdateObj(obj: any) { + return await request({ + url: apiPrefix + "/update", + method: "post", + data: obj, + }); + }, + + async DelObj(id: number) { + return await request({ + url: apiPrefix + "/delete", + method: "post", + params: { id }, + }); + }, + + async GetObj(id: number) { + return await request({ + url: apiPrefix + "/info", + method: "post", + params: { id }, + }); + }, + + async GetDetail(id: number) { + return await request({ + url: apiPrefix + "/detail", + method: "post", + params: { id }, + }); + }, + async ListAll() { + return await request({ + url: apiPrefix + "/all", + method: "post", + }); + }, +}; diff --git a/packages/ui/certd-client/src/views/certd/pipeline/template/crud.tsx b/packages/ui/certd-client/src/views/certd/pipeline/template/crud.tsx new file mode 100644 index 00000000..1e101d2d --- /dev/null +++ b/packages/ui/certd-client/src/views/certd/pipeline/template/crud.tsx @@ -0,0 +1,113 @@ +// @ts-ignore +import { useI18n } from "vue-i18n"; +import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, useFormWrapper, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud"; +import { templateApi } from "./api"; +import { useRouter } from "vue-router"; +import { useModal } from "/@/use/use-modal"; + +export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet { + const api = templateApi; + const pageRequest = async (query: UserPageQuery): Promise => { + return await api.GetList(query); + }; + const editRequest = async (req: EditReq) => { + const { form, row } = req; + form.id = row.id; + const res = await api.UpdateObj(form); + return res; + }; + const delRequest = async (req: DelReq) => { + const { row } = req; + return await api.DelObj(row.id); + }; + + const addRequest = async (req: AddReq) => { + const { form } = req; + const res = await api.AddObj(form); + return res; + }; + const { openCrudFormDialog } = useFormWrapper(); + const router = useRouter(); + + const model = useModal(); + return { + crudOptions: { + request: { + pageRequest, + addRequest, + editRequest, + delRequest, + }, + form: { + labelCol: { + //固定label宽度 + span: null, + style: { + width: "100px", + }, + }, + col: { + span: 22, + }, + wrapper: { + width: 600, + }, + }, + actionbar: { + show: true, + buttons: { + add: { + text: "创建模版", + type: "primary", + show: true, + }, + }, + }, + rowHandle: { + // width: 100, + fixed: "right", + }, + columns: { + id: { + title: "ID", + key: "id", + type: "number", + search: { + show: false, + }, + column: { + width: 100, + editable: { + disabled: true, + }, + }, + form: { + show: false, + }, + }, + title: { + title: "模版名称", + type: "text", + search: { + show: true, + }, + column: { + width: 200, + sorter: true, + }, + }, + pipelineId: { + title: "流水线ID", + type: "text", + search: { + show: true, + }, + column: { + width: 200, + sorter: true, + }, + }, + }, + }, + }; +} diff --git a/packages/ui/certd-client/src/views/certd/pipeline/template/edit.vue b/packages/ui/certd-client/src/views/certd/pipeline/template/edit.vue new file mode 100644 index 00000000..d10e8deb --- /dev/null +++ b/packages/ui/certd-client/src/views/certd/pipeline/template/edit.vue @@ -0,0 +1,135 @@ + + + diff --git a/packages/ui/certd-client/src/views/certd/pipeline/template/index.vue b/packages/ui/certd-client/src/views/certd/pipeline/template/index.vue new file mode 100644 index 00000000..899cfa4a --- /dev/null +++ b/packages/ui/certd-client/src/views/certd/pipeline/template/index.vue @@ -0,0 +1,30 @@ + + + diff --git a/packages/ui/certd-server/db/migration/v10026__template.sql b/packages/ui/certd-server/db/migration/v10026__template.sql new file mode 100644 index 00000000..52a2129d --- /dev/null +++ b/packages/ui/certd-server/db/migration/v10026__template.sql @@ -0,0 +1,15 @@ +CREATE TABLE "pi_template" +( + "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, + "user_id" integer, + "pipeline_id" integer, + "title" varchar(1024), + "content" text, + "order" integer, + "disabled" boolean NOT NULL DEFAULT (false), + "create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP), + "update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP) +); + +CREATE INDEX "index_template_user_id" ON "pi_template" ("user_id"); +CREATE INDEX "index_template_pipeline_id" ON "pi_template" ("pipeline_id"); diff --git a/packages/ui/certd-server/src/controller/user/pipeline/template-controller.ts b/packages/ui/certd-server/src/controller/user/pipeline/template-controller.ts new file mode 100644 index 00000000..abe517c2 --- /dev/null +++ b/packages/ui/certd-server/src/controller/user/pipeline/template-controller.ts @@ -0,0 +1,77 @@ +import {ALL, Body, Controller, Inject, Post, Provide, Query} from '@midwayjs/core'; +import {Constants, CrudController} from '@certd/lib-server'; +import { TemplateService } from '../../../modules/pipeline/service/template-service.js'; + +/** + * 流水线模版 + */ +@Provide() +@Controller('/api/pi/template') +export class TemplateController extends CrudController { + @Inject() + service: TemplateService; + + getService() { + return this.service; + } + + + @Post('/page', { summary: Constants.per.authOnly }) + async page(@Body(ALL) body) { + body.query = body.query ?? {}; + delete body.query.userId; + const buildQuery = qb => { + qb.andWhere('user_id = :userId', { userId: this.getUserId() }); + }; + const res = await this.service.page({ + query: body.query, + page: body.page, + sort: body.sort, + buildQuery, + }); + return this.ok(res); + } + + @Post('/list', { summary: Constants.per.authOnly }) + async list(@Body(ALL) body) { + body.query = body.query ?? {}; + body.query.userId = this.getUserId(); + return super.list(body); + } + + @Post('/add', { summary: Constants.per.authOnly }) + async add(@Body(ALL) bean) { + bean.userId = this.getUserId(); + return super.add(bean); + } + + @Post('/update', { summary: Constants.per.authOnly }) + async update(@Body(ALL) bean) { + await this.service.checkUserId(bean.id, this.getUserId()); + delete bean.userId; + return super.update(bean); + } + @Post('/info', { summary: Constants.per.authOnly }) + async info(@Query('id') id: number) { + await this.service.checkUserId(id, this.getUserId()); + return super.info(id); + } + + @Post('/delete', { summary: Constants.per.authOnly }) + async delete(@Query('id') id: number) { + await this.service.checkUserId(id, this.getUserId()); + return super.delete(id); + } + + @Post('/batchDelete', { summary: Constants.per.authOnly }) + async batchDelete(@Body('ids') ids: number[]) { + await this.service.batchDelete(ids, this.getUserId()); + return this.ok({}); + } + + @Post('/detail', { summary: Constants.per.authOnly }) + async detail(@Query('id') id: number) { + const detail = await this.service.detail(id, this.getUserId()); + return this.ok(detail); + } +} diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/template.ts b/packages/ui/certd-server/src/modules/pipeline/entity/template.ts new file mode 100644 index 00000000..caf83ec5 --- /dev/null +++ b/packages/ui/certd-server/src/modules/pipeline/entity/template.ts @@ -0,0 +1,52 @@ +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; + + +export type PipelineTemplateType = { + input: { + [key: string]: { + value: string; + }; + } +} + + +@Entity('pi_template') +export class TemplateEntity { + @PrimaryGeneratedColumn() + id: number; + + @Column({ name: 'user_id', comment: '用户id' }) + userId: number; + + @Column({ name: 'pipeline_id', comment: '流水线id' }) + pipelineId: number; + + @Column({ name: 'title', comment: '标题' }) + title: string; + + @Column({ comment: '配置', length: 40960 }) + content: string; + + @Column({ comment: '启用/禁用', nullable: true, default: false }) + disabled: boolean; + + @Column({ + name: 'order', + comment: '排序', + nullable: true, + }) + order: number; + + @Column({ + name: 'create_time', + comment: '创建时间', + default: () => 'CURRENT_TIMESTAMP', + }) + createTime: Date; + @Column({ + name: 'update_time', + comment: '修改时间', + default: () => 'CURRENT_TIMESTAMP', + }) + updateTime: Date; +} diff --git a/packages/ui/certd-server/src/modules/pipeline/service/template-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/template-service.ts new file mode 100644 index 00000000..8ff8c143 --- /dev/null +++ b/packages/ui/certd-server/src/modules/pipeline/service/template-service.ts @@ -0,0 +1,41 @@ +import {Inject, Provide, Scope, ScopeEnum} from '@midwayjs/core'; +import {BaseService, SysSettingsService} from '@certd/lib-server'; +import {InjectEntityModel} from '@midwayjs/typeorm'; +import {Repository} from 'typeorm'; +import { TemplateEntity } from '../entity/template.js'; +import { PipelineService } from './pipeline-service.js'; + +@Provide() +@Scope(ScopeEnum.Request, { allowDowngrade: true }) +export class TemplateService extends BaseService { + @InjectEntityModel(TemplateEntity) + repository: Repository; + + @Inject() + pipelineService: PipelineService; + + @Inject() + sysSettingsService: SysSettingsService; + + //@ts-ignore + getRepository() { + return this.repository; + } + + async detail(id: number, userId: number) { + const info = await this.info(id) + if (!info) { + throw new Error('模板不存在'); + } + if (info.userId !== userId) { + throw new Error('无权限'); + } + const pipeline = await this.pipelineService.info(info.pipelineId); + + return { + template:info, + pipeline: JSON.parse(pipeline.content), + } + } +} + diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-cdn/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-cdn/index.ts index 154bc0c2..76f38f0c 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-cdn/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-cdn/index.ts @@ -38,6 +38,7 @@ export class DeployCertToAliyunCDN extends AbstractTaskPlugin { name: 'output-selector', from: [...CertApplyPluginNames, 'uploadCertToAliyun'], }, + template:false, required: true, }) cert!: string;