From eb46f8c7764142a9a79efe4525954cd7c010a283 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Wed, 4 Feb 2026 15:49:01 +0800 Subject: [PATCH 01/62] =?UTF-8?q?chore:=20=E4=BC=81=E4=B8=9A=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E6=A8=A1=E5=BC=8F=E5=88=9D=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/system/settings/service/models.ts | 2 + .../src/user/access/entity/access.ts | 3 + .../lib-server/src/user/addon/entity/addon.ts | 3 + .../src/locales/langs/en-US/certd.ts | 4 ++ .../src/locales/langs/zh-CN/certd.ts | 4 ++ .../src/store/settings/api.basic.ts | 3 + .../src/views/sys/settings/index.vue | 5 ++ .../src/views/sys/settings/tabs/base.vue | 6 +- .../src/views/sys/settings/tabs/mode.vue | 67 +++++++++++++++++++ .../db/migration/v10038__admin_mode.sql | 53 +++++++++++++++ .../src/modules/monitor/entity/cert-info.ts | 3 + .../src/modules/monitor/entity/site-info.ts | 3 + .../src/modules/monitor/entity/site-ip.ts | 2 + .../src/modules/open/entity/open-key.ts | 3 + .../modules/pipeline/entity/history-log.ts | 3 + .../src/modules/pipeline/entity/history.ts | 4 ++ .../modules/pipeline/entity/notification.ts | 3 + .../modules/pipeline/entity/pipeline-group.ts | 3 + .../src/modules/pipeline/entity/pipeline.ts | 3 + .../src/modules/pipeline/entity/storage.ts | 3 + .../src/modules/pipeline/entity/template.ts | 3 + .../src/modules/sys/audit/entity/audit-log.ts | 43 ++++++++++++ .../sys/enterprise/entity/project-user.ts | 31 +++++++++ .../modules/sys/enterprise/entity/project.ts | 31 +++++++++ 24 files changed, 285 insertions(+), 3 deletions(-) create mode 100644 packages/ui/certd-client/src/views/sys/settings/tabs/mode.vue create mode 100644 packages/ui/certd-server/db/migration/v10038__admin_mode.sql create mode 100644 packages/ui/certd-server/src/modules/sys/audit/entity/audit-log.ts create mode 100644 packages/ui/certd-server/src/modules/sys/enterprise/entity/project-user.ts create mode 100644 packages/ui/certd-server/src/modules/sys/enterprise/entity/project.ts diff --git a/packages/libs/lib-server/src/system/settings/service/models.ts b/packages/libs/lib-server/src/system/settings/service/models.ts index 1b9a8128d..69eb81a6f 100644 --- a/packages/libs/lib-server/src/system/settings/service/models.ts +++ b/packages/libs/lib-server/src/system/settings/service/models.ts @@ -65,6 +65,8 @@ export class SysPublicSettings extends BaseSettings { }> = {}; notice?: string; + + adminMode?: "enterprise" | "saas" = "saas"; } export class SysPrivateSettings extends BaseSettings { diff --git a/packages/libs/lib-server/src/user/access/entity/access.ts b/packages/libs/lib-server/src/user/access/entity/access.ts index d69128c72..fd635719e 100644 --- a/packages/libs/lib-server/src/user/access/entity/access.ts +++ b/packages/libs/lib-server/src/user/access/entity/access.ts @@ -21,6 +21,9 @@ export class AccessEntity { @Column({ name: 'encrypt_setting', comment: '已加密设置', length: 10240, nullable: true }) encryptSetting: string; + @Column({ name: 'project_id', comment: '项目id' }) + projectId: number; + @Column({ name: 'create_time', comment: '创建时间', diff --git a/packages/libs/lib-server/src/user/addon/entity/addon.ts b/packages/libs/lib-server/src/user/addon/entity/addon.ts index 4d16fb43b..438de2237 100644 --- a/packages/libs/lib-server/src/user/addon/entity/addon.ts +++ b/packages/libs/lib-server/src/user/addon/entity/addon.ts @@ -28,6 +28,9 @@ export class AddonEntity { @Column({ name: 'is_default', comment: '是否默认', nullable: false, default: false }) isDefault: boolean; + @Column({ name: 'project_id', comment: '项目id' }) + projectId: number; + @Column({ name: 'create_time', diff --git a/packages/ui/certd-client/src/locales/langs/en-US/certd.ts b/packages/ui/certd-client/src/locales/langs/en-US/certd.ts index b1daa1bf4..96d6a2323 100644 --- a/packages/ui/certd-client/src/locales/langs/en-US/certd.ts +++ b/packages/ui/certd-client/src/locales/langs/en-US/certd.ts @@ -861,4 +861,8 @@ export default { select: "Select", placeholder: "select please", }, + adminMode: { + enterpriseMode: "Enterprise Mode", + saasMode: "SaaS Mode", + }, }; diff --git a/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts b/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts index d12f92ff6..34d78c3dd 100644 --- a/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts +++ b/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts @@ -876,4 +876,8 @@ export default { select: "选择", placeholder: "请选择", }, + adminMode: { + enterpriseMode: "企业模式", + saasMode: "SaaS模式", + }, }; diff --git a/packages/ui/certd-client/src/store/settings/api.basic.ts b/packages/ui/certd-client/src/store/settings/api.basic.ts index 48a0012fb..57003d3fb 100644 --- a/packages/ui/certd-client/src/store/settings/api.basic.ts +++ b/packages/ui/certd-client/src/store/settings/api.basic.ts @@ -86,6 +86,9 @@ export type SysPublicSetting = { >; // 系统通知 notice?: string; + + // 管理员模式 + adminMode?: "enterprise" | "saas"; }; export type SuiteSetting = { enabled?: boolean; diff --git a/packages/ui/certd-client/src/views/sys/settings/index.vue b/packages/ui/certd-client/src/views/sys/settings/index.vue index 962d75c8d..6c62109f5 100644 --- a/packages/ui/certd-client/src/views/sys/settings/index.vue +++ b/packages/ui/certd-client/src/views/sys/settings/index.vue @@ -26,6 +26,9 @@ + + + @@ -39,6 +42,8 @@ import SettingSafe from "/@/views/sys/settings/tabs/safe.vue"; import SettingCaptcha from "/@/views/sys/settings/tabs/captcha.vue"; import SettingPipeline from "/@/views/sys/settings/tabs/pipeline.vue"; import SettingOauth from "/@/views/sys/settings/tabs/oauth.vue"; +import SettingMode from "/@/views/sys/settings/tabs/mode.vue"; + import { useRoute, useRouter } from "vue-router"; import { ref } from "vue"; import { useSettingStore } from "/@/store/settings"; diff --git a/packages/ui/certd-client/src/views/sys/settings/tabs/base.vue b/packages/ui/certd-client/src/views/sys/settings/tabs/base.vue index 4b2b92189..9ff248372 100644 --- a/packages/ui/certd-client/src/views/sys/settings/tabs/base.vue +++ b/packages/ui/certd-client/src/views/sys/settings/tabs/base.vue @@ -34,7 +34,9 @@ {{ t("certd.ipv4Priority") }} {{ t("certd.ipv6Priority") }} -
{{ t("certd.dualStackNetworkHelper") }}, {{ t("certd.helpDocLink") }}
+
+ {{ t("certd.dualStackNetworkHelper") }}, {{ t("certd.helpDocLink") }} +
@@ -68,8 +70,6 @@ import { useSettingStore } from "/@/store/settings"; import { notification } from "ant-design-vue"; import { util } from "/@/utils"; import { useI18n } from "/src/locales"; -import AddonSelector from "../../../certd/addon/addon-selector/index.vue"; -import CaptchaInput from "/@/components/captcha/captcha-input.vue"; const { t } = useI18n(); defineOptions({ diff --git a/packages/ui/certd-client/src/views/sys/settings/tabs/mode.vue b/packages/ui/certd-client/src/views/sys/settings/tabs/mode.vue new file mode 100644 index 000000000..4bd95d147 --- /dev/null +++ b/packages/ui/certd-client/src/views/sys/settings/tabs/mode.vue @@ -0,0 +1,67 @@ + + + + diff --git a/packages/ui/certd-server/db/migration/v10038__admin_mode.sql b/packages/ui/certd-server/db/migration/v10038__admin_mode.sql new file mode 100644 index 000000000..0e5249168 --- /dev/null +++ b/packages/ui/certd-server/db/migration/v10038__admin_mode.sql @@ -0,0 +1,53 @@ + +CREATE TABLE "cd_project" +( + "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, + "user_id" integer NOT NULL, + "name" varchar(512) NOT NULL, + "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_project_user_id" ON "cd_project" ("user_id"); +INSERT INTO cd_project (id, user_id, "name", "disabled") VALUES (1, 0, 'default', false); + + +ALTER TABLE cd_cert_info ADD COLUMN project_id integer; +CREATE INDEX "index_cert_project_id" ON "cd_cert_info" ("project_id"); + +ALTER TABLE cd_site_info ADD COLUMN project_id integer; +CREATE INDEX "index_site_project_id" ON "cd_site_info" ("project_id"); + +ALTER TABLE cd_site_ip ADD COLUMN project_id integer; +CREATE INDEX "index_site_ip_project_id" ON "cd_site_ip" ("project_id"); + +ALTER TABLE cd_open_key ADD COLUMN project_id integer; +CREATE INDEX "index_open_key_project_id" ON "cd_open_key" ("project_id"); + +ALTER TABLE cd_access ADD COLUMN project_id integer; +CREATE INDEX "index_access_project_id" ON "cd_access" ("project_id"); + +ALTER TABLE cd_addon ADD COLUMN project_id integer; +CREATE INDEX "index_addon_project_id" ON "cd_addon" ("project_id"); + +ALTER TABLE pi_pipeline ADD COLUMN project_id integer; +CREATE INDEX "index_pipeline_project_id" ON "cd_pipeline" ("project_id"); + +ALTER TABLE pi_pipeline_group ADD COLUMN project_id integer; +CREATE INDEX "index_pipeline_group_project_id" ON "cd_pipeline_group" ("project_id"); + +ALTER TABLE pi_storage ADD COLUMN project_id integer; +CREATE INDEX "index_storage_project_id" ON "cd_storage" ("project_id"); + +ALTER TABLE pi_notification ADD COLUMN project_id integer; +CREATE INDEX "index_notification_project_id" ON "cd_notification" ("project_id"); + +ALTER TABLE pi_history ADD COLUMN project_id integer; +CREATE INDEX "index_history_project_id" ON "cd_history" ("project_id"); + +ALTER TABLE pi_history_log ADD COLUMN project_id integer; +CREATE INDEX "index_history_log_project_id" ON "cd_history_log" ("project_id"); + + diff --git a/packages/ui/certd-server/src/modules/monitor/entity/cert-info.ts b/packages/ui/certd-server/src/modules/monitor/entity/cert-info.ts index 807489c91..1f1234ffb 100644 --- a/packages/ui/certd-server/src/modules/monitor/entity/cert-info.ts +++ b/packages/ui/certd-server/src/modules/monitor/entity/cert-info.ts @@ -42,6 +42,9 @@ export class CertInfoEntity { @Column({ name: 'cert_file', comment: '证书下载' }) certFile: string; + @Column({ name: 'project_id', comment: '项目id' }) + projectId: number; + @Column({ name: 'create_time', comment: '创建时间', diff --git a/packages/ui/certd-server/src/modules/monitor/entity/site-info.ts b/packages/ui/certd-server/src/modules/monitor/entity/site-info.ts index 298ffe193..4535f49b3 100644 --- a/packages/ui/certd-server/src/modules/monitor/entity/site-info.ts +++ b/packages/ui/certd-server/src/modules/monitor/entity/site-info.ts @@ -71,6 +71,9 @@ export class SiteInfoEntity { @Column({ name: 'group_id', comment: '分组id' }) groupId: number; + @Column({ name: 'project_id', comment: '项目id' }) + projectId: number; + @Column({ name: 'create_time', comment: '创建时间', default: () => 'CURRENT_TIMESTAMP' }) createTime: Date; @Column({ name: 'update_time', comment: '修改时间', default: () => 'CURRENT_TIMESTAMP' }) diff --git a/packages/ui/certd-server/src/modules/monitor/entity/site-ip.ts b/packages/ui/certd-server/src/modules/monitor/entity/site-ip.ts index 3cfa50c3f..91887f815 100644 --- a/packages/ui/certd-server/src/modules/monitor/entity/site-ip.ts +++ b/packages/ui/certd-server/src/modules/monitor/entity/site-ip.ts @@ -33,6 +33,8 @@ export class SiteIpEntity { remark: string; @Column({ name: "disabled", comment: "禁用启用" }) disabled: boolean; + @Column({ name: 'project_id', comment: '项目id' }) + projectId: number; @Column({ name: 'create_time', comment: '创建时间', default: () => 'CURRENT_TIMESTAMP' }) createTime: Date; diff --git a/packages/ui/certd-server/src/modules/open/entity/open-key.ts b/packages/ui/certd-server/src/modules/open/entity/open-key.ts index 6c774ce3d..1e8fe0614 100644 --- a/packages/ui/certd-server/src/modules/open/entity/open-key.ts +++ b/packages/ui/certd-server/src/modules/open/entity/open-key.ts @@ -17,6 +17,9 @@ export class OpenKeyEntity { @Column({ name: 'scope', comment: '权限范围' }) scope: string; // open 仅开放接口、 user 用户所有权限 + @Column({ name: 'project_id', comment: '项目id' }) + projectId: number; + @Column({ name: 'create_time', comment: '创建时间', default: () => 'CURRENT_TIMESTAMP' }) createTime: Date; diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/history-log.ts b/packages/ui/certd-server/src/modules/pipeline/entity/history-log.ts index bdeeeeaf9..0f2425b88 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/history-log.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/history-log.ts @@ -25,6 +25,9 @@ export class HistoryLogEntity { @Column({ comment: '日志内容', length: 40960, nullable: true }) logs: string; + @Column({ name: 'project_id', comment: '项目id' }) + projectId: number; + @Column({ name: 'create_time', comment: '创建时间', diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/history.ts b/packages/ui/certd-server/src/modules/pipeline/entity/history.ts index 6461b28f2..5fb7aa2b7 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/history.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/history.ts @@ -26,6 +26,9 @@ export class HistoryEntity { }) endTime: Date; + @Column({ name: 'project_id', comment: '项目id' }) + projectId: number; + @Column({ name: 'create_time', comment: '创建时间', @@ -38,6 +41,7 @@ export class HistoryEntity { default: () => 'CURRENT_TIMESTAMP', }) updateTime: Date; + pipelineTitle: string; diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/notification.ts b/packages/ui/certd-server/src/modules/pipeline/entity/notification.ts index 555c4e884..e66404150 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/notification.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/notification.ts @@ -20,6 +20,9 @@ export class NotificationEntity { @Column({ name: 'is_default', comment: '是否默认' }) isDefault: boolean; + @Column({ name: 'project_id', comment: '项目id' }) + projectId: number; + @Column({ name: 'create_time', comment: '创建时间', diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/pipeline-group.ts b/packages/ui/certd-server/src/modules/pipeline/entity/pipeline-group.ts index 8ee07ed7d..31d1003cc 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/pipeline-group.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/pipeline-group.ts @@ -17,6 +17,9 @@ export class PipelineGroupEntity { @Column({ name: 'favorite', comment: '收藏' }) favorite: boolean; + @Column({ name: 'project_id', comment: '项目id' }) + projectId: number; + @Column({ name: 'create_time', comment: '创建时间', diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/pipeline.ts b/packages/ui/certd-server/src/modules/pipeline/entity/pipeline.ts index 4f1d0d4be..168b77b49 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/pipeline.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/pipeline.ts @@ -61,6 +61,9 @@ export class PipelineEntity { @Column({name: 'order', comment: '排序', nullable: true,}) order: number; + @Column({ name: 'project_id', comment: '项目id' }) + projectId: number; + @Column({name: 'create_time',comment: '创建时间', default: () => 'CURRENT_TIMESTAMP',}) createTime: Date; @Column({ diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/storage.ts b/packages/ui/certd-server/src/modules/pipeline/entity/storage.ts index d01eb9bf2..aa87e1d15 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/storage.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/storage.ts @@ -23,6 +23,9 @@ export class StorageEntity { @Column({ comment: 'value', length: 40960, nullable: true }) value: string; + @Column({ name: 'project_id', comment: '项目id' }) + projectId: number; + @Column({ name: 'create_time', comment: '创建时间', diff --git a/packages/ui/certd-server/src/modules/pipeline/entity/template.ts b/packages/ui/certd-server/src/modules/pipeline/entity/template.ts index 418d09101..bb31b641f 100644 --- a/packages/ui/certd-server/src/modules/pipeline/entity/template.ts +++ b/packages/ui/certd-server/src/modules/pipeline/entity/template.ts @@ -39,6 +39,9 @@ export class TemplateEntity { }) order: number; + @Column({ name: 'project_id', comment: '项目id' }) + projectId: number; + @Column({ name: 'create_time', comment: '创建时间', diff --git a/packages/ui/certd-server/src/modules/sys/audit/entity/audit-log.ts b/packages/ui/certd-server/src/modules/sys/audit/entity/audit-log.ts new file mode 100644 index 000000000..3e5361240 --- /dev/null +++ b/packages/ui/certd-server/src/modules/sys/audit/entity/audit-log.ts @@ -0,0 +1,43 @@ +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; + +/** + */ +@Entity('cd_audit_log') +export class AuditLogEntity { + @PrimaryGeneratedColumn() + id: number; + + @Column({ name: 'user_id', comment: 'UserId' }) + userId: number; + + @Column({ name: 'user_name', comment: '用户名' }) + userName: string; + + @Column({ name: 'project_id', comment: 'ProjectId' }) + projectId: number; + + @Column({ name: 'project_name', comment: '项目名称' }) + projectName: string; + + @Column({ name: 'action', comment: '操作' }) + action: string; + + @Column({ name: 'content', comment: '内容' }) + content: string; + + @Column({ name: 'ip_address', comment: 'IP地址' }) + ipAddress: string; + + @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/sys/enterprise/entity/project-user.ts b/packages/ui/certd-server/src/modules/sys/enterprise/entity/project-user.ts new file mode 100644 index 000000000..c58bf5ccd --- /dev/null +++ b/packages/ui/certd-server/src/modules/sys/enterprise/entity/project-user.ts @@ -0,0 +1,31 @@ +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; + +/** + */ +@Entity('cd_project_user') +export class ProjectUserEntity { + @PrimaryGeneratedColumn() + id: number; + + @Column({ name: 'user_id', comment: 'UserId' }) + userId: number; + + @Column({ name: 'project_id', comment: 'ProjectId' }) + projectId: number; + + @Column({ name: 'permission', comment: '权限' }) + permission: string; // read / write + + @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/sys/enterprise/entity/project.ts b/packages/ui/certd-server/src/modules/sys/enterprise/entity/project.ts new file mode 100644 index 000000000..f41dce77d --- /dev/null +++ b/packages/ui/certd-server/src/modules/sys/enterprise/entity/project.ts @@ -0,0 +1,31 @@ +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; + +/** + */ +@Entity('cd_project') +export class ProjectEntity { + @PrimaryGeneratedColumn() + id: number; + + @Column({ name: 'user_id', comment: 'UserId' }) + userId: number; + + @Column({ name: 'name', comment: '项目名称' }) + name: string; + + @Column({ name: 'disabled', comment: '禁用' }) + disabled: boolean; + + @Column({ + name: 'create_time', + comment: '创建时间', + default: () => 'CURRENT_TIMESTAMP', + }) + createTime: Date; + @Column({ + name: 'update_time', + comment: '修改时间', + default: () => 'CURRENT_TIMESTAMP', + }) + updateTime: Date; +} From bb0afe1fa7b0fc52fde051d24fbe6be69d52f4cc Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Wed, 4 Feb 2026 17:01:08 +0800 Subject: [PATCH 02/62] =?UTF-8?q?perf:=20=E5=BD=93=E5=9F=9F=E5=90=8D?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E4=B8=AD=E6=B2=A1=E6=9C=89=E5=9F=9F=E5=90=8D?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E5=88=9B=E5=BB=BA=E6=B5=81=E6=B0=B4=E7=BA=BF?= =?UTF-8?q?=E6=97=B6=E4=B8=8D=E5=B1=95=E5=BC=80=E5=9F=9F=E5=90=8D=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugins/common/domain-selector.vue | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/ui/certd-client/src/components/plugins/common/domain-selector.vue b/packages/ui/certd-client/src/components/plugins/common/domain-selector.vue index 7a331e0be..d6fdbf598 100644 --- a/packages/ui/certd-client/src/components/plugins/common/domain-selector.vue +++ b/packages/ui/certd-client/src/components/plugins/common/domain-selector.vue @@ -9,6 +9,7 @@ :options="optionsRef" :value="value" v-bind="attrs" + :open="openProp" @click="onClick" @update:value="emit('update:value', $event)" > @@ -56,11 +57,11 @@ + diff --git a/packages/ui/certd-client/src/views/sys/enterprise/project/api.ts b/packages/ui/certd-client/src/views/sys/enterprise/project/api.ts new file mode 100644 index 000000000..f71795b3c --- /dev/null +++ b/packages/ui/certd-client/src/views/sys/enterprise/project/api.ts @@ -0,0 +1,75 @@ +import { request } from "/src/api/service"; + +const apiPrefix = "/sys/project/provider"; + +export async function GetList(query: any) { + return await request({ + url: apiPrefix + "/page", + method: "post", + data: query, + }); +} + +export async function AddObj(obj: any) { + return await request({ + url: apiPrefix + "/add", + method: "post", + data: obj, + }); +} + +export async function UpdateObj(obj: any) { + return await request({ + url: apiPrefix + "/update", + method: "post", + data: obj, + }); +} + +export async function DelObj(id: any) { + return await request({ + url: apiPrefix + "/delete", + method: "post", + params: { id }, + }); +} + +export async function GetObj(id: any) { + return await request({ + url: apiPrefix + "/info", + method: "post", + params: { id }, + }); +} + +export async function GetDetail(id: any) { + return await request({ + url: apiPrefix + "/detail", + method: "post", + params: { id }, + }); +} + +export async function DeleteBatch(ids: any[]) { + return await request({ + url: apiPrefix + "/deleteByIds", + method: "post", + data: { ids }, + }); +} + +export async function SetDefault(id: any) { + return await request({ + url: apiPrefix + "/setDefault", + method: "post", + data: { id }, + }); +} + +export async function SetDisabled(id: any, disabled: boolean) { + return await request({ + url: apiPrefix + "/setDisabled", + method: "post", + data: { id, disabled }, + }); +} diff --git a/packages/ui/certd-client/src/views/sys/enterprise/project/crud.tsx b/packages/ui/certd-client/src/views/sys/enterprise/project/crud.tsx new file mode 100644 index 000000000..025a168bb --- /dev/null +++ b/packages/ui/certd-client/src/views/sys/enterprise/project/crud.tsx @@ -0,0 +1,254 @@ +import * as api from "./api"; +import { useI18n } from "/src/locales"; +import { computed, Ref, ref } from "vue"; +import { useRouter } from "vue-router"; +import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud"; +import { useUserStore } from "/@/store/user"; +import { useSettingStore } from "/@/store/settings"; +import { Modal } from "ant-design-vue"; + +export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet { + const router = useRouter(); + 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); + return res; + }; + const delRequest = async ({ row }: DelReq) => { + return await api.DelObj(row.id); + }; + + const addRequest = async ({ form }: AddReq) => { + const res = await api.AddObj(form); + return res; + }; + + const userStore = useUserStore(); + const settingStore = useSettingStore(); + const selectedRowKeys: Ref = ref([]); + context.selectedRowKeys = selectedRowKeys; + + return { + crudOptions: { + settings: { + plugins: { + //这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并 + rowSelection: { + enabled: true, + order: -2, + before: true, + // handle: (pluginProps,useCrudProps)=>CrudOptions, + props: { + multiple: true, + crossPage: true, + selectedRowKeys, + }, + }, + }, + }, + request: { + pageRequest, + addRequest, + editRequest, + delRequest, + }, + rowHandle: { + minWidth: 200, + fixed: "right", + }, + columns: { + id: { + title: "ID", + key: "id", + type: "number", + column: { + width: 100, + }, + form: { + show: false, + }, + }, + domain: { + title: t("certd.cnameDomain"), + type: "text", + editForm: { + component: { + disabled: true, + }, + }, + search: { + show: true, + }, + form: { + component: { + placeholder: t("certd.cnameDomainPlaceholder"), + }, + helper: t("certd.cnameDomainHelper"), + rules: [ + { required: true, message: t("certd.requiredField") }, + { pattern: /^[^*]+$/, message: t("certd.cnameDomainPattern") }, + ], + }, + column: { + width: 200, + }, + }, + dnsProviderType: { + title: t("certd.dnsProvider"), + type: "dict-select", + search: { + show: true, + }, + dict: dict({ + url: "pi/dnsProvider/list", + value: "key", + label: "title", + }), + form: { + rules: [{ required: true, message: t("certd.requiredField") }], + }, + column: { + width: 150, + component: { + color: "auto", + }, + }, + }, + accessId: { + title: t("certd.dnsProviderAuthorization"), + type: "dict-select", + dict: dict({ + url: "/pi/access/list", + value: "id", + label: "name", + }), + form: { + component: { + name: "access-selector", + vModel: "modelValue", + type: compute(({ form }) => { + return form.dnsProviderType; + }), + }, + rules: [{ required: true, message: t("certd.requiredField") }], + }, + column: { + width: 150, + component: { + color: "auto", + }, + }, + }, + isDefault: { + title: t("certd.isDefault"), + type: "dict-switch", + dict: dict({ + data: [ + { label: t("certd.yes"), value: true, color: "success" }, + { label: t("certd.no"), value: false, color: "default" }, + ], + }), + form: { + value: false, + rules: [{ required: true, message: t("certd.selectIsDefault") }], + }, + column: { + align: "center", + width: 100, + }, + }, + setDefault: { + title: t("certd.setDefault"), + type: "text", + form: { + show: false, + }, + column: { + width: 100, + align: "center", + conditionalRenderDisabled: true, + cellRender: ({ row }) => { + if (row.isDefault) { + return; + } + const onClick = async () => { + Modal.confirm({ + title: t("certd.prompt"), + content: t("certd.confirmSetDefault"), + onOk: async () => { + await api.SetDefault(row.id); + await crudExpose.doRefresh(); + }, + }); + }; + + return ( + + {t("certd.setAsDefault")} + + ); + }, + }, + }, + disabled: { + title: t("certd.disabled"), + type: "dict-switch", + dict: dict({ + data: [ + { label: t("certd.enabled"), value: false, color: "success" }, + { label: t("certd.disabledLabel"), value: true, color: "error" }, + ], + }), + form: { + value: false, + }, + column: { + width: 100, + component: { + title: t("certd.clickToToggle"), + on: { + async click({ value, row }) { + Modal.confirm({ + title: t("certd.prompt"), + content: t("certd.confirmToggleStatus", { action: !value ? t("certd.disable") : t("certd.enable") }), + onOk: async () => { + await api.SetDisabled(row.id, !value); + await crudExpose.doRefresh(); + }, + }); + }, + }, + }, + }, + }, + createTime: { + title: t("certd.createTime"), + type: "datetime", + form: { + show: false, + }, + column: { + sorter: true, + width: 160, + align: "center", + }, + }, + updateTime: { + title: t("certd.updateTime"), + type: "datetime", + form: { + show: false, + }, + column: { + show: true, + width: 160, + }, + }, + }, + }, + }; +} diff --git a/packages/ui/certd-client/src/views/sys/enterprise/project/index.vue b/packages/ui/certd-client/src/views/sys/enterprise/project/index.vue new file mode 100644 index 000000000..e1f2427df --- /dev/null +++ b/packages/ui/certd-client/src/views/sys/enterprise/project/index.vue @@ -0,0 +1,65 @@ + + + + diff --git a/packages/ui/certd-server/src/controller/sys/enterprise/project-controller.ts b/packages/ui/certd-server/src/controller/sys/enterprise/project-controller.ts new file mode 100644 index 000000000..eaf8f01ab --- /dev/null +++ b/packages/ui/certd-server/src/controller/sys/enterprise/project-controller.ts @@ -0,0 +1,70 @@ +import { CrudController, SysSettingsService } from "@certd/lib-server"; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { ProjectService } from "../../../modules/sys/enterprise/service/project-service.js"; +import { ProjectEntity } from "../../../modules/sys/enterprise/entity/project.js"; +import { merge } from "lodash-es"; + +/** + */ +@Provide() +@Controller("/api/sys/enterprise/project") +export class SysProjectController extends CrudController { + @Inject() + service: ProjectService; + + @Inject() + sysSettingsService: SysSettingsService; + + getService() { + return this.service; + } + + @Post("/page", { summary: "sys:settings:view" }) + async page(@Body(ALL) body: any) { + body.query = body.query ?? {}; + return await super.page(body); + } + + @Post("/list", { summary: "sys:settings:view" }) + async list(@Body(ALL) body: any) { + return super.list(body); + } + + @Post("/add", { summary: "sys:settings:edit" }) + async add(@Body(ALL) bean: any) { + const def: any = { + isDefault: false, + disabled: false, + }; + merge(bean, def); + bean.userId = this.getUserId(); + return super.add(bean); + } + + @Post("/update", { summary: "sys:settings:edit" }) + async update(@Body(ALL) bean: any) { + bean.userId = this.getUserId(); + return super.update(bean); + } + + @Post("/info", { summary: "sys:settings:view" }) + async info(@Query("id") id: number) { + return super.info(id); + } + + @Post("/delete", { summary: "sys:settings:edit" }) + async delete(@Query("id") id: number) { + return super.delete(id); + } + + @Post("/deleteByIds", { summary: "sys:settings:edit" }) + async deleteByIds(@Body("ids") ids: number[]) { + const res = await this.service.delete(ids); + return this.ok(res); + } + @Post("/setDisabled", { summary: "sys:settings:edit" }) + async setDisabled(@Body("id") id: number, @Body("disabled") disabled: boolean) { + await this.service.setDisabled(id, disabled); + return this.ok(); + } +} diff --git a/packages/ui/certd-server/src/controller/sys/enterprise/project-user-controller.ts b/packages/ui/certd-server/src/controller/sys/enterprise/project-user-controller.ts new file mode 100644 index 000000000..cbe0f7c2a --- /dev/null +++ b/packages/ui/certd-server/src/controller/sys/enterprise/project-user-controller.ts @@ -0,0 +1,65 @@ +import { CrudController, SysSettingsService } from "@certd/lib-server"; +import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; +import { ProjectUserEntity } from "../../../modules/sys/enterprise/entity/project-user.js"; +import { ProjectUserService } from "../../../modules/sys/enterprise/service/project-user-service.js"; +import { merge } from "lodash-es"; + +/** + */ +@Provide() +@Controller("/api/sys/enterprise/projectUser") +export class SysProjectUserController extends CrudController { + @Inject() + service: ProjectUserService; + + @Inject() + sysSettingsService: SysSettingsService; + + getService() { + return this.service; + } + + @Post("/page", { summary: "sys:settings:view" }) + async page(@Body(ALL) body: any) { + body.query = body.query ?? {}; + return await super.page(body); + } + + @Post("/list", { summary: "sys:settings:view" }) + async list(@Body(ALL) body: any) { + return super.list(body); + } + + @Post("/add", { summary: "sys:settings:edit" }) + async add(@Body(ALL) bean: any) { + const def: any = { + isDefault: false, + disabled: false, + }; + merge(bean, def); + bean.userId = this.getUserId(); + return super.add(bean); + } + + @Post("/update", { summary: "sys:settings:edit" }) + async update(@Body(ALL) bean: any) { + bean.userId = this.getUserId(); + return super.update(bean); + } + + @Post("/info", { summary: "sys:settings:view" }) + async info(@Query("id") id: number) { + return super.info(id); + } + + @Post("/delete", { summary: "sys:settings:edit" }) + async delete(@Query("id") id: number) { + return super.delete(id); + } + + @Post("/deleteByIds", { summary: "sys:settings:edit" }) + async deleteByIds(@Body("ids") ids: number[]) { + const res = await this.service.delete(ids); + return this.ok(res); + } +} diff --git a/packages/ui/certd-server/src/modules/pipeline/service/sub-domain-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/sub-domain-service.ts index 5f98e55ab..5b37a5841 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/sub-domain-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/sub-domain-service.ts @@ -54,7 +54,6 @@ export class SubDomainService extends BaseService { throw new Error('域名已存在'); } return await super.add(bean) - } } diff --git a/packages/ui/certd-server/src/modules/sys/audit/entity/audit-log.ts b/packages/ui/certd-server/src/modules/sys/enterprise/entity/audit-log.ts similarity index 100% rename from packages/ui/certd-server/src/modules/sys/audit/entity/audit-log.ts rename to packages/ui/certd-server/src/modules/sys/enterprise/entity/audit-log.ts diff --git a/packages/ui/certd-server/src/modules/sys/enterprise/service/project-service.ts b/packages/ui/certd-server/src/modules/sys/enterprise/service/project-service.ts new file mode 100644 index 000000000..11b7aa9e8 --- /dev/null +++ b/packages/ui/certd-server/src/modules/sys/enterprise/service/project-service.ts @@ -0,0 +1,59 @@ +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 { ProjectEntity } from '../entity/project.js'; + +@Provide() +@Scope(ScopeEnum.Request, { allowDowngrade: true }) +export class ProjectService extends BaseService { + @InjectEntityModel(ProjectEntity) + repository: Repository; + + + @Inject() + sysSettingsService: SysSettingsService; + + //@ts-ignore + getRepository() { + return this.repository; + } + + async add(bean: ProjectEntity) { + const {name} = bean; + if (!name) { + throw new Error('项目名称不能为空'); + } + const exist = await this.repository.findOne({ + where: { + name, + userId:0, + }, + }); + if (exist) { + throw new Error('项目名称已存在'); + } + bean.userId = 0 + bean.disabled = false + return await super.add(bean) + } + + async setDisabled(id: number, disabled: boolean) { + const project = await this.repository.findOne({ + where: { + id, + userId:0, + }, + }); + if (!project) { + throw new Error('项目不存在'); + } + await this.repository.update({ + userId:0, + }, { + disabled, + }); + project.disabled = disabled; + await this.repository.save(project); + } +} diff --git a/packages/ui/certd-server/src/modules/sys/enterprise/service/project-user-service.ts b/packages/ui/certd-server/src/modules/sys/enterprise/service/project-user-service.ts new file mode 100644 index 000000000..e5729a010 --- /dev/null +++ b/packages/ui/certd-server/src/modules/sys/enterprise/service/project-user-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 { ProjectUserEntity } from '../entity/project-user.js'; + +@Provide() +@Scope(ScopeEnum.Request, { allowDowngrade: true }) +export class ProjectUserService extends BaseService { + @InjectEntityModel(ProjectUserEntity) + repository: Repository; + + @Inject() + sysSettingsService: SysSettingsService; + + //@ts-ignore + getRepository() { + return this.repository; + } + + async add(bean: ProjectUserEntity) { + const {projectId, userId} = bean; + if (!projectId) { + throw new Error('项目ID不能为空'); + } + if (!userId) { + throw new Error('用户ID不能为空'); + } + const exist = await this.repository.findOne({ + where: { + projectId, + userId, + }, + }); + if (exist) { + throw new Error('项目用户已存在'); + } + return await super.add(bean) + } + +} From 6ddc23e2aa025c10263e9e62f3ce6304fde68130 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Wed, 4 Feb 2026 18:54:00 +0800 Subject: [PATCH 04/62] chore: project member --- .../src/locales/langs/zh-CN/certd.ts | 3 + .../src/router/source/modules/sys.ts | 8 +- .../src/views/sys/enterprise/project/api.ts | 11 +- .../src/views/sys/enterprise/project/crud.tsx | 117 +------------ .../views/sys/enterprise/project/index.vue | 10 +- .../sys/enterprise/project/member/api.ts | 67 ++++++++ .../sys/enterprise/project/member/crud.tsx | 155 ++++++++++++++++++ .../sys/enterprise/project/member/index.vue | 54 ++++++ .../sys/authority/user-controller.ts | 19 ++- ...roller.ts => project-member-controller.ts} | 10 +- .../{project-user.ts => project-member.ts} | 6 +- ...r-service.ts => project-member-service.ts} | 10 +- 12 files changed, 323 insertions(+), 147 deletions(-) create mode 100644 packages/ui/certd-client/src/views/sys/enterprise/project/member/api.ts create mode 100644 packages/ui/certd-client/src/views/sys/enterprise/project/member/crud.tsx create mode 100644 packages/ui/certd-client/src/views/sys/enterprise/project/member/index.vue rename packages/ui/certd-server/src/controller/sys/enterprise/{project-user-controller.ts => project-member-controller.ts} (79%) rename packages/ui/certd-server/src/modules/sys/enterprise/entity/{project-user.ts => project-member.ts} (84%) rename packages/ui/certd-server/src/modules/sys/enterprise/service/{project-user-service.ts => project-member-service.ts} (74%) diff --git a/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts b/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts index 58a37f091..d6c4123db 100644 --- a/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts +++ b/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts @@ -883,4 +883,7 @@ export default { enterpriseMode: "企业模式", saasMode: "SaaS模式", }, + ent: { + projectName: "项目名称", + }, }; diff --git a/packages/ui/certd-client/src/router/source/modules/sys.ts b/packages/ui/certd-client/src/router/source/modules/sys.ts index 85357a6de..4cd71b0ce 100644 --- a/packages/ui/certd-client/src/router/source/modules/sys.ts +++ b/packages/ui/certd-client/src/router/source/modules/sys.ts @@ -215,10 +215,10 @@ export const sysResources = [ }, }, { - title: "certd.sysResources.projectUserManager", - name: "ProjectUserManager", - path: "/sys/enterprise/project/user", - component: "/sys/enterprise/project/user/index.vue", + title: "certd.sysResources.projectMemberManager", + name: "ProjectMemberManager", + path: "/sys/enterprise/project/member", + component: "/sys/enterprise/project/member/index.vue", meta: { isMenu: false, show: true, diff --git a/packages/ui/certd-client/src/views/sys/enterprise/project/api.ts b/packages/ui/certd-client/src/views/sys/enterprise/project/api.ts index f71795b3c..85cff52ac 100644 --- a/packages/ui/certd-client/src/views/sys/enterprise/project/api.ts +++ b/packages/ui/certd-client/src/views/sys/enterprise/project/api.ts @@ -1,6 +1,7 @@ import { request } from "/src/api/service"; -const apiPrefix = "/sys/project/provider"; +const apiPrefix = "/sys/enterprise/project"; +const userApiPrefix = "/sys/authority/user"; export async function GetList(query: any) { return await request({ @@ -58,14 +59,6 @@ export async function DeleteBatch(ids: any[]) { }); } -export async function SetDefault(id: any) { - return await request({ - url: apiPrefix + "/setDefault", - method: "post", - data: { id }, - }); -} - export async function SetDisabled(id: any, disabled: boolean) { return await request({ url: apiPrefix + "/setDisabled", diff --git a/packages/ui/certd-client/src/views/sys/enterprise/project/crud.tsx b/packages/ui/certd-client/src/views/sys/enterprise/project/crud.tsx index 025a168bb..e6d4dcb61 100644 --- a/packages/ui/certd-client/src/views/sys/enterprise/project/crud.tsx +++ b/packages/ui/certd-client/src/views/sys/enterprise/project/crud.tsx @@ -72,128 +72,21 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat show: false, }, }, - domain: { - title: t("certd.cnameDomain"), + name: { + title: t("certd.ent.projectName"), type: "text", - editForm: { - component: { - disabled: true, - }, - }, search: { show: true, }, form: { - component: { - placeholder: t("certd.cnameDomainPlaceholder"), - }, - helper: t("certd.cnameDomainHelper"), - rules: [ - { required: true, message: t("certd.requiredField") }, - { pattern: /^[^*]+$/, message: t("certd.cnameDomainPattern") }, - ], + component: {}, + helper: t("certd.ent.projectNameHelper"), + rules: [{ required: true, message: t("certd.requiredField") }], }, column: { width: 200, }, }, - dnsProviderType: { - title: t("certd.dnsProvider"), - type: "dict-select", - search: { - show: true, - }, - dict: dict({ - url: "pi/dnsProvider/list", - value: "key", - label: "title", - }), - form: { - rules: [{ required: true, message: t("certd.requiredField") }], - }, - column: { - width: 150, - component: { - color: "auto", - }, - }, - }, - accessId: { - title: t("certd.dnsProviderAuthorization"), - type: "dict-select", - dict: dict({ - url: "/pi/access/list", - value: "id", - label: "name", - }), - form: { - component: { - name: "access-selector", - vModel: "modelValue", - type: compute(({ form }) => { - return form.dnsProviderType; - }), - }, - rules: [{ required: true, message: t("certd.requiredField") }], - }, - column: { - width: 150, - component: { - color: "auto", - }, - }, - }, - isDefault: { - title: t("certd.isDefault"), - type: "dict-switch", - dict: dict({ - data: [ - { label: t("certd.yes"), value: true, color: "success" }, - { label: t("certd.no"), value: false, color: "default" }, - ], - }), - form: { - value: false, - rules: [{ required: true, message: t("certd.selectIsDefault") }], - }, - column: { - align: "center", - width: 100, - }, - }, - setDefault: { - title: t("certd.setDefault"), - type: "text", - form: { - show: false, - }, - column: { - width: 100, - align: "center", - conditionalRenderDisabled: true, - cellRender: ({ row }) => { - if (row.isDefault) { - return; - } - const onClick = async () => { - Modal.confirm({ - title: t("certd.prompt"), - content: t("certd.confirmSetDefault"), - onOk: async () => { - await api.SetDefault(row.id); - await crudExpose.doRefresh(); - }, - }); - }; - - return ( - - {t("certd.setAsDefault")} - - ); - }, - }, - }, disabled: { title: t("certd.disabled"), type: "dict-switch", diff --git a/packages/ui/certd-client/src/views/sys/enterprise/project/index.vue b/packages/ui/certd-client/src/views/sys/enterprise/project/index.vue index e1f2427df..0022b28a1 100644 --- a/packages/ui/certd-client/src/views/sys/enterprise/project/index.vue +++ b/packages/ui/certd-client/src/views/sys/enterprise/project/index.vue @@ -2,13 +2,7 @@ @@ -32,7 +26,7 @@ import { useI18n } from "/src/locales"; const { t } = useI18n(); defineOptions({ - name: "CnameProvider", + name: "ProjectManager", }); const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions }); diff --git a/packages/ui/certd-client/src/views/sys/enterprise/project/member/api.ts b/packages/ui/certd-client/src/views/sys/enterprise/project/member/api.ts new file mode 100644 index 000000000..bff9f6adf --- /dev/null +++ b/packages/ui/certd-client/src/views/sys/enterprise/project/member/api.ts @@ -0,0 +1,67 @@ +import { request } from "/src/api/service"; + +const apiPrefix = "/sys/enterprise/projectMember"; +const userApiPrefix = "/sys/authority/user"; +export async function GetList(query: any) { + return await request({ + url: apiPrefix + "/page", + method: "post", + data: query, + }); +} + +export async function AddObj(obj: any) { + return await request({ + url: apiPrefix + "/add", + method: "post", + data: obj, + }); +} + +export async function UpdateObj(obj: any) { + return await request({ + url: apiPrefix + "/update", + method: "post", + data: obj, + }); +} + +export async function DelObj(id: any) { + return await request({ + url: apiPrefix + "/delete", + method: "post", + params: { id }, + }); +} + +export async function GetObj(id: any) { + return await request({ + url: apiPrefix + "/info", + method: "post", + params: { id }, + }); +} + +export async function GetDetail(id: any) { + return await request({ + url: apiPrefix + "/detail", + method: "post", + params: { id }, + }); +} + +export async function DeleteBatch(ids: any[]) { + return await request({ + url: apiPrefix + "/deleteByIds", + method: "post", + data: { ids }, + }); +} + +export async function GetUserSimpleByIds(query: any) { + return await request({ + url: userApiPrefix + "/getSimpleByIds", + method: "post", + data: query, + }); +} diff --git a/packages/ui/certd-client/src/views/sys/enterprise/project/member/crud.tsx b/packages/ui/certd-client/src/views/sys/enterprise/project/member/crud.tsx new file mode 100644 index 000000000..07144fadd --- /dev/null +++ b/packages/ui/certd-client/src/views/sys/enterprise/project/member/crud.tsx @@ -0,0 +1,155 @@ +import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud"; +import { Modal } from "ant-design-vue"; +import { Ref, ref } from "vue"; +import { useRouter } from "vue-router"; +import * as api from "./api"; +import { useSettingStore } from "/@/store/settings"; +import { useUserStore } from "/@/store/user"; +import { useI18n } from "/src/locales"; + +export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet { + const router = useRouter(); + 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); + return res; + }; + const delRequest = async ({ row }: DelReq) => { + return await api.DelObj(row.id); + }; + + const addRequest = async ({ form }: AddReq) => { + const res = await api.AddObj(form); + return res; + }; + + const userStore = useUserStore(); + const settingStore = useSettingStore(); + const selectedRowKeys: Ref = ref([]); + context.selectedRowKeys = selectedRowKeys; + + return { + crudOptions: { + settings: { + plugins: { + //这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并 + rowSelection: { + enabled: true, + order: -2, + before: true, + // handle: (pluginProps,useCrudProps)=>CrudOptions, + props: { + multiple: true, + crossPage: true, + selectedRowKeys, + }, + }, + }, + }, + request: { + pageRequest, + addRequest, + editRequest, + delRequest, + }, + rowHandle: { + minWidth: 200, + fixed: "right", + }, + columns: { + id: { + title: "ID", + key: "id", + type: "number", + column: { + width: 100, + }, + form: { + show: false, + }, + }, + projectId: { + title: "项目ID", + type: "text", + search: { + show: false, + }, + form: { + show: false, + }, + column: { + width: 200, + show: false, + }, + }, + userId: { + title: "用户ID", + type: "dict-select", + dict: dict({ + url: "/sys/authority/user/getSimpleUsers", + value: "id", + label: "nickName", + labelBuilder: (item: any) => item.nickName || item.username || item.phoneCode + item.mobile, + }), + search: { + show: false, + }, + form: { + show: false, + }, + column: { + width: 200, + show: false, + }, + }, + permission: { + title: t("certd.ent.projectPermission"), + type: "dict-select", + dict: dict({ + data: [ + { label: t("certd.read"), value: "read", color: "cyan" }, + { label: t("certd.write"), value: "write", color: "blue" }, + { label: t("certd.admin"), value: "admin", color: "green" }, + ], + }), + search: { + show: true, + }, + form: { + show: true, + }, + column: { + width: 200, + }, + }, + createTime: { + title: t("certd.createTime"), + type: "datetime", + form: { + show: false, + }, + column: { + sorter: true, + width: 160, + align: "center", + }, + }, + updateTime: { + title: t("certd.updateTime"), + type: "datetime", + form: { + show: false, + }, + column: { + show: true, + width: 160, + }, + }, + }, + }, + }; +} diff --git a/packages/ui/certd-client/src/views/sys/enterprise/project/member/index.vue b/packages/ui/certd-client/src/views/sys/enterprise/project/member/index.vue new file mode 100644 index 000000000..c632d1211 --- /dev/null +++ b/packages/ui/certd-client/src/views/sys/enterprise/project/member/index.vue @@ -0,0 +1,54 @@ + + + + diff --git a/packages/ui/certd-server/src/controller/sys/authority/user-controller.ts b/packages/ui/certd-server/src/controller/sys/authority/user-controller.ts index ccd5da62e..c37ed60a6 100644 --- a/packages/ui/certd-server/src/controller/sys/authority/user-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/authority/user-controller.ts @@ -28,7 +28,7 @@ export class UserController extends CrudController { return this.service; } - @Post('/getSimpleUserByIds', {summary: 'sys:auth:user:add'}) + @Post('/getSimpleUserByIds', {summary: 'sys:auth:user:view'}) async getSimpleUserByIds(@Body('ids') ids: number[]) { const users = await this.service.find({ select: { @@ -46,6 +46,21 @@ export class UserController extends CrudController { return this.ok(users); } + + @Post('/getSimpleUsers', {summary: 'sys:auth:user:view'}) + async getSimpleUsers() { + const users = await this.service.find({ + select: { + id: true, + username: true, + nickName: true, + mobile: true, + phoneCode: true, + }, + }); + return this.ok(users); + } + @Post('/page', {summary: 'sys:auth:user:view'}) async page( @Body(ALL) @@ -153,4 +168,6 @@ export class UserController extends CrudController { } + + } diff --git a/packages/ui/certd-server/src/controller/sys/enterprise/project-user-controller.ts b/packages/ui/certd-server/src/controller/sys/enterprise/project-member-controller.ts similarity index 79% rename from packages/ui/certd-server/src/controller/sys/enterprise/project-user-controller.ts rename to packages/ui/certd-server/src/controller/sys/enterprise/project-member-controller.ts index cbe0f7c2a..794600728 100644 --- a/packages/ui/certd-server/src/controller/sys/enterprise/project-user-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/enterprise/project-member-controller.ts @@ -1,16 +1,16 @@ import { CrudController, SysSettingsService } from "@certd/lib-server"; import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core"; -import { ProjectUserEntity } from "../../../modules/sys/enterprise/entity/project-user.js"; -import { ProjectUserService } from "../../../modules/sys/enterprise/service/project-user-service.js"; +import { ProjectMemberEntity } from "../../../modules/sys/enterprise/entity/project-member.js"; +import { ProjectMemberService } from "../../../modules/sys/enterprise/service/project-member-service.js"; import { merge } from "lodash-es"; /** */ @Provide() -@Controller("/api/sys/enterprise/projectUser") -export class SysProjectUserController extends CrudController { +@Controller("/api/sys/enterprise/projectMember") +export class SysProjectMemberController extends CrudController { @Inject() - service: ProjectUserService; + service: ProjectMemberService; @Inject() sysSettingsService: SysSettingsService; diff --git a/packages/ui/certd-server/src/modules/sys/enterprise/entity/project-user.ts b/packages/ui/certd-server/src/modules/sys/enterprise/entity/project-member.ts similarity index 84% rename from packages/ui/certd-server/src/modules/sys/enterprise/entity/project-user.ts rename to packages/ui/certd-server/src/modules/sys/enterprise/entity/project-member.ts index c58bf5ccd..b0fb8a60d 100644 --- a/packages/ui/certd-server/src/modules/sys/enterprise/entity/project-user.ts +++ b/packages/ui/certd-server/src/modules/sys/enterprise/entity/project-member.ts @@ -2,8 +2,8 @@ import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; /** */ -@Entity('cd_project_user') -export class ProjectUserEntity { +@Entity('cd_project_member') +export class ProjectMemberEntity { @PrimaryGeneratedColumn() id: number; @@ -14,7 +14,7 @@ export class ProjectUserEntity { projectId: number; @Column({ name: 'permission', comment: '权限' }) - permission: string; // read / write + permission: string; // read / write / admin @Column({ name: 'create_time', diff --git a/packages/ui/certd-server/src/modules/sys/enterprise/service/project-user-service.ts b/packages/ui/certd-server/src/modules/sys/enterprise/service/project-member-service.ts similarity index 74% rename from packages/ui/certd-server/src/modules/sys/enterprise/service/project-user-service.ts rename to packages/ui/certd-server/src/modules/sys/enterprise/service/project-member-service.ts index e5729a010..74953946d 100644 --- a/packages/ui/certd-server/src/modules/sys/enterprise/service/project-user-service.ts +++ b/packages/ui/certd-server/src/modules/sys/enterprise/service/project-member-service.ts @@ -2,13 +2,13 @@ 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 { ProjectUserEntity } from '../entity/project-user.js'; +import { ProjectMemberEntity } from '../entity/project-member.js'; @Provide() @Scope(ScopeEnum.Request, { allowDowngrade: true }) -export class ProjectUserService extends BaseService { - @InjectEntityModel(ProjectUserEntity) - repository: Repository; +export class ProjectMemberService extends BaseService { + @InjectEntityModel(ProjectMemberEntity) + repository: Repository; @Inject() sysSettingsService: SysSettingsService; @@ -18,7 +18,7 @@ export class ProjectUserService extends BaseService { return this.repository; } - async add(bean: ProjectUserEntity) { + async add(bean: ProjectMemberEntity) { const {projectId, userId} = bean; if (!projectId) { throw new Error('项目ID不能为空'); From 8d8304e85962f37fa932129b38a36fa31d4a0e52 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Wed, 4 Feb 2026 19:03:03 +0800 Subject: [PATCH 05/62] chore: 1 --- .../sys/enterprise/project/member/index.vue | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/ui/certd-client/src/views/sys/enterprise/project/member/index.vue b/packages/ui/certd-client/src/views/sys/enterprise/project/member/index.vue index c632d1211..12a6ad684 100644 --- a/packages/ui/certd-client/src/views/sys/enterprise/project/member/index.vue +++ b/packages/ui/certd-client/src/views/sys/enterprise/project/member/index.vue @@ -1,5 +1,13 @@ + + diff --git a/packages/ui/certd-client/src/views/sys/settings/tabs/mode.vue b/packages/ui/certd-client/src/views/sys/settings/tabs/mode.vue index c23734319..5ba3f39b2 100644 --- a/packages/ui/certd-client/src/views/sys/settings/tabs/mode.vue +++ b/packages/ui/certd-client/src/views/sys/settings/tabs/mode.vue @@ -2,7 +2,12 @@
- +
+ + +
+
SaaS模式:每个用户管理自己的流水线和授权资源,独立使用。
+
企业模式:企业内部员工使用,通过项目合作管理流水线证书和授权资源。
@@ -30,14 +35,14 @@ defineOptions({ const adminModeDict = dict({ data: [ - { - label: t("certd.sys.setting.enterpriseMode"), - value: "enterprise", - }, { label: t("certd.sys.setting.saasMode"), value: "saas", }, + { + label: t("certd.sys.setting.enterpriseMode"), + value: "enterprise", + }, ], }); From 5b5b48fc061db1bca51e4768810d2caf02af973b Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Sat, 28 Feb 2026 18:30:04 +0800 Subject: [PATCH 41/62] chore: admin mode setting --- .../views/sys/enterprise/project/index.vue | 2 +- .../views/sys/enterprise/project/intro.vue | 19 +++++++++++++++---- .../src/views/sys/settings/tabs/mode.vue | 6 ++++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/packages/ui/certd-client/src/views/sys/enterprise/project/index.vue b/packages/ui/certd-client/src/views/sys/enterprise/project/index.vue index f89d92e85..b953b8b71 100644 --- a/packages/ui/certd-client/src/views/sys/enterprise/project/index.vue +++ b/packages/ui/certd-client/src/views/sys/enterprise/project/index.vue @@ -12,7 +12,7 @@ - + diff --git a/packages/ui/certd-client/src/views/sys/enterprise/project/intro.vue b/packages/ui/certd-client/src/views/sys/enterprise/project/intro.vue index c8bd57d0b..8e8e55f2e 100644 --- a/packages/ui/certd-client/src/views/sys/enterprise/project/intro.vue +++ b/packages/ui/certd-client/src/views/sys/enterprise/project/intro.vue @@ -1,8 +1,8 @@