Merge branch 'v2-dev' of https://github.com/certd/certd into v2-dev

This commit is contained in:
xiaojunnuo
2026-03-12 18:11:09 +08:00
56 changed files with 587 additions and 151 deletions

View File

@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
### Bug Fixes
* 修复企业管理模式下切换用户登录后丢失项目列表的bug ([d23c8b4](https://github.com/certd/certd/commit/d23c8b4a2a5f5ab17822c6ee1d4108ac7280b9d1))
### Performance Improvements
* 支持迁移个人数据到企业项目中 ([c6ca832](https://github.com/certd/certd/commit/c6ca83273779ed84de1b23b5e477063af043d015))
* install tip ([853fdc7](https://github.com/certd/certd/commit/853fdc70a263b62d75c9ff3970607e6bf1c1593b))
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
### Bug Fixes

View File

@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
### Bug Fixes
* 修复企业管理模式下切换用户登录后丢失项目列表的bug ([d23c8b4](https://github.com/certd/certd/commit/d23c8b4a2a5f5ab17822c6ee1d4108ac7280b9d1))
### Performance Improvements
* 支持迁移个人数据到企业项目中 ([c6ca832](https://github.com/certd/certd/commit/c6ca83273779ed84de1b23b5e477063af043d015))
* install tip ([853fdc7](https://github.com/certd/certd/commit/853fdc70a263b62d75c9ff3970607e6bf1c1593b))
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
### Bug Fixes

View File

@@ -9,5 +9,5 @@
}
},
"npmClient": "pnpm",
"version": "1.39.0"
"version": "1.39.1"
}

View File

@@ -37,6 +37,7 @@
"docs:preview": "vitepress preview docs",
"pub": "echo 1",
"dev": "pnpm run -r --parallel compile ",
"pub_all":"pnpm run -r --parallel pub ",
"release": "time /t >trigger/release.trigger && git add trigger/release.trigger && git commit -m \"build: release\" && git push",
"publish_to_atomgit": "node --experimental-json-modules ./scripts/publish-atomgit.js",
"publish_to_gitee": "node --experimental-json-modules ./scripts/publish-gitee.js",

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/publishlab/node-acme-client/compare/v1.39.0...v1.39.1) (2026-03-09)
**Note:** Version bump only for package @certd/acme-client
# [1.39.0](https://github.com/publishlab/node-acme-client/compare/v1.38.12...v1.39.0) (2026-03-07)
**Note:** Version bump only for package @certd/acme-client

View File

@@ -3,7 +3,7 @@
"description": "Simple and unopinionated ACME client",
"private": false,
"author": "nmorsman",
"version": "1.39.0",
"version": "1.39.1",
"type": "module",
"module": "scr/index.js",
"main": "src/index.js",
@@ -18,7 +18,7 @@
"types"
],
"dependencies": {
"@certd/basic": "^1.39.0",
"@certd/basic": "^1.39.1",
"@peculiar/x509": "^1.11.0",
"asn1js": "^3.0.5",
"axios": "^1.9.0",
@@ -70,5 +70,5 @@
"bugs": {
"url": "https://github.com/publishlab/node-acme-client/issues"
},
"gitHead": "3bb29abe32c311e1cf840f97d485d1147411992a"
"gitHead": "590ff67fcb40ff8ba0f7b2a9592b51d9fb54a2ef"
}

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
**Note:** Version bump only for package @certd/basic
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
### Bug Fixes

View File

@@ -1 +1 @@
01:15
23:44

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/basic",
"private": false,
"version": "1.39.0",
"version": "1.39.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -47,5 +47,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "3bb29abe32c311e1cf840f97d485d1147411992a"
"gitHead": "590ff67fcb40ff8ba0f7b2a9592b51d9fb54a2ef"
}

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
**Note:** Version bump only for package @certd/pipeline
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
**Note:** Version bump only for package @certd/pipeline

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/pipeline",
"private": false,
"version": "1.39.0",
"version": "1.39.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -18,8 +18,8 @@
"compile": "tsc --skipLibCheck --watch"
},
"dependencies": {
"@certd/basic": "^1.39.0",
"@certd/plus-core": "^1.39.0",
"@certd/basic": "^1.39.1",
"@certd/plus-core": "^1.39.1",
"dayjs": "^1.11.7",
"lodash-es": "^4.17.21",
"reflect-metadata": "^0.1.13"
@@ -45,5 +45,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "3bb29abe32c311e1cf840f97d485d1147411992a"
"gitHead": "590ff67fcb40ff8ba0f7b2a9592b51d9fb54a2ef"
}

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
**Note:** Version bump only for package @certd/lib-huawei
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
**Note:** Version bump only for package @certd/lib-huawei

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/lib-huawei",
"private": false,
"version": "1.39.0",
"version": "1.39.1",
"main": "./dist/bundle.js",
"module": "./dist/bundle.js",
"types": "./dist/d/index.d.ts",
@@ -24,5 +24,5 @@
"prettier": "^2.8.8",
"tslib": "^2.8.1"
},
"gitHead": "3bb29abe32c311e1cf840f97d485d1147411992a"
"gitHead": "590ff67fcb40ff8ba0f7b2a9592b51d9fb54a2ef"
}

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
**Note:** Version bump only for package @certd/lib-iframe
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
**Note:** Version bump only for package @certd/lib-iframe

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/lib-iframe",
"private": false,
"version": "1.39.0",
"version": "1.39.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -31,5 +31,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "3bb29abe32c311e1cf840f97d485d1147411992a"
"gitHead": "590ff67fcb40ff8ba0f7b2a9592b51d9fb54a2ef"
}

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
**Note:** Version bump only for package @certd/jdcloud
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
**Note:** Version bump only for package @certd/jdcloud

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/jdcloud",
"version": "1.39.0",
"version": "1.39.1",
"description": "jdcloud openApi sdk",
"main": "./dist/bundle.js",
"module": "./dist/bundle.js",
@@ -56,5 +56,5 @@
"fetch"
]
},
"gitHead": "3bb29abe32c311e1cf840f97d485d1147411992a"
"gitHead": "590ff67fcb40ff8ba0f7b2a9592b51d9fb54a2ef"
}

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
**Note:** Version bump only for package @certd/lib-k8s
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
**Note:** Version bump only for package @certd/lib-k8s

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/lib-k8s",
"private": false,
"version": "1.39.0",
"version": "1.39.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -17,7 +17,7 @@
"pub": "npm publish"
},
"dependencies": {
"@certd/basic": "^1.39.0",
"@certd/basic": "^1.39.1",
"@kubernetes/client-node": "0.21.0"
},
"devDependencies": {
@@ -32,5 +32,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "3bb29abe32c311e1cf840f97d485d1147411992a"
"gitHead": "590ff67fcb40ff8ba0f7b2a9592b51d9fb54a2ef"
}

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
**Note:** Version bump only for package @certd/lib-server
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
### Performance Improvements

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/lib-server",
"version": "1.39.0",
"version": "1.39.1",
"description": "midway with flyway, sql upgrade way ",
"private": false,
"type": "module",
@@ -28,11 +28,11 @@
],
"license": "AGPL",
"dependencies": {
"@certd/acme-client": "^1.39.0",
"@certd/basic": "^1.39.0",
"@certd/pipeline": "^1.39.0",
"@certd/plugin-lib": "^1.39.0",
"@certd/plus-core": "^1.39.0",
"@certd/acme-client": "^1.39.1",
"@certd/basic": "^1.39.1",
"@certd/pipeline": "^1.39.1",
"@certd/plugin-lib": "^1.39.1",
"@certd/plus-core": "^1.39.1",
"@midwayjs/cache": "3.14.0",
"@midwayjs/core": "3.20.11",
"@midwayjs/i18n": "3.20.13",
@@ -64,5 +64,5 @@
"typeorm": "^0.3.11",
"typescript": "^5.4.2"
},
"gitHead": "3bb29abe32c311e1cf840f97d485d1147411992a"
"gitHead": "590ff67fcb40ff8ba0f7b2a9592b51d9fb54a2ef"
}

View File

@@ -88,6 +88,10 @@ export class SysPrivateSettings extends BaseSettings {
pipelineMaxRunningCount?: number;
environmentVars?: string = '';
sms?: {
type?: string;
config?: any;

View File

@@ -11,6 +11,8 @@ import { BaseService, setAdminMode } from '../../../basic/index.js';
import { executorQueue } from '../../basic/service/executor-queue.js';
import { isComm } from '@certd/plus-core';
const { merge } = mergeUtils;
let lastSaveEnvVars = {};
/**
* 设置
*/
@@ -117,12 +119,12 @@ export class SysSettingsService extends BaseService<SysSettingsEntity> {
}
async savePublicSettings(bean: SysPublicSettings) {
if(isComm()){
if(bean.adminMode === 'enterprise'){
if (isComm()) {
if (bean.adminMode === 'enterprise') {
throw new Error("商业版不支持使用企业管理模式")
}
}
await this.saveSetting(bean);
//让设置生效
await this.reloadPublicSettings();
@@ -173,6 +175,44 @@ export class SysSettingsService extends BaseService<SysSettingsEntity> {
}
setSslProviderReverseProxies(privateSetting.reverseProxies);
//加载环境变量
this.setEnvironmentVars(privateSetting.environmentVars);
}
setEnvironmentVars(vars: string) {
const envVars = {}
if (typeof vars !== 'string') {
vars = ""
}
vars.split('\n').forEach(line => {
line = line.trim();
if (!line || line.startsWith('#')) {
return
}
const arr = line.split("#")
if (arr.length > 0) {
line = arr[0].trim();
}
if (!line.includes("=")) {
return
}
const [key, value] = line.split('=');
if (key && value) {
envVars[key.trim()] = value.trim();
}
});
//先删除旧环境变量
if (lastSaveEnvVars) {
for (const key in lastSaveEnvVars) {
delete process.env[key];
}
}
merge(process.env, envVars);
lastSaveEnvVars = envVars;
}
async updateByKey(key: string, setting: any) {

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
**Note:** Version bump only for package @certd/midway-flyway-js
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
**Note:** Version bump only for package @certd/midway-flyway-js

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/midway-flyway-js",
"version": "1.39.0",
"version": "1.39.1",
"description": "midway with flyway, sql upgrade way ",
"private": false,
"type": "module",
@@ -46,5 +46,5 @@
"typeorm": "^0.3.11",
"typescript": "^5.4.2"
},
"gitHead": "3bb29abe32c311e1cf840f97d485d1147411992a"
"gitHead": "590ff67fcb40ff8ba0f7b2a9592b51d9fb54a2ef"
}

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
**Note:** Version bump only for package @certd/plugin-cert
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
**Note:** Version bump only for package @certd/plugin-cert

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/plugin-cert",
"private": false,
"version": "1.39.0",
"version": "1.39.1",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -17,10 +17,10 @@
"compile": "tsc --skipLibCheck --watch"
},
"dependencies": {
"@certd/acme-client": "^1.39.0",
"@certd/basic": "^1.39.0",
"@certd/pipeline": "^1.39.0",
"@certd/plugin-lib": "^1.39.0",
"@certd/acme-client": "^1.39.1",
"@certd/basic": "^1.39.1",
"@certd/pipeline": "^1.39.1",
"@certd/plugin-lib": "^1.39.1",
"psl": "^1.9.0",
"punycode.js": "^2.3.1"
},
@@ -38,5 +38,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "3bb29abe32c311e1cf840f97d485d1147411992a"
"gitHead": "590ff67fcb40ff8ba0f7b2a9592b51d9fb54a2ef"
}

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
**Note:** Version bump only for package @certd/plugin-lib
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
**Note:** Version bump only for package @certd/plugin-lib

View File

@@ -1,7 +1,7 @@
{
"name": "@certd/plugin-lib",
"private": false,
"version": "1.39.0",
"version": "1.39.1",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -22,10 +22,10 @@
"@alicloud/pop-core": "^1.7.10",
"@alicloud/tea-util": "^1.4.11",
"@aws-sdk/client-s3": "^3.964.0",
"@certd/acme-client": "^1.39.0",
"@certd/basic": "^1.39.0",
"@certd/pipeline": "^1.39.0",
"@certd/plus-core": "^1.39.0",
"@certd/acme-client": "^1.39.1",
"@certd/basic": "^1.39.1",
"@certd/pipeline": "^1.39.1",
"@certd/plus-core": "^1.39.1",
"@kubernetes/client-node": "0.21.0",
"ali-oss": "^6.22.0",
"basic-ftp": "^5.0.5",
@@ -57,5 +57,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "3bb29abe32c311e1cf840f97d485d1147411992a"
"gitHead": "590ff67fcb40ff8ba0f7b2a9592b51d9fb54a2ef"
}

View File

@@ -38,6 +38,10 @@ COPY ./patch/ssh2/*.js /app/node_modules/.pnpm/node_modules/ssh2/lib/protocol/
ENV LEGO_VERSION=4.30.1
ENV LEGO_DOWNLOAD_DIR=/app/tools/lego
ENV ALIYUN_CLIENT_CONNECT_TIMEOUT=10000
ENV ALIYUN_CLIENT_READ_TIMEOUT=20000
RUN mkdir -p $LEGO_DOWNLOAD_DIR
# 根据架构下载不同的文件

View File

@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
### Bug Fixes
* 修复企业管理模式下切换用户登录后丢失项目列表的bug ([d23c8b4](https://github.com/certd/certd/commit/d23c8b4a2a5f5ab17822c6ee1d4108ac7280b9d1))
### Performance Improvements
* 支持迁移个人数据到企业项目中 ([c6ca832](https://github.com/certd/certd/commit/c6ca83273779ed84de1b23b5e477063af043d015))
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/ui-client",
"version": "1.39.0",
"version": "1.39.1",
"private": true,
"scripts": {
"dev": "vite --open",
@@ -106,8 +106,8 @@
"zod-defaults": "^0.1.3"
},
"devDependencies": {
"@certd/lib-iframe": "^1.39.0",
"@certd/pipeline": "^1.39.0",
"@certd/lib-iframe": "^1.39.1",
"@certd/pipeline": "^1.39.1",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"@types/chai": "^4.3.12",

View File

@@ -1,7 +1,7 @@
<template>
<div class="remote-select">
<div class="flex flex-row">
<a-select class="remote-select-input" show-search :filter-option="filterOption" :options="optionsRef" :value="value" v-bind="attrs" @click="onClick" @update:value="emit('update:value', $event)">
<a-select class="remote-select-input" show-search mode="tags" :filter-option="filterOption" :options="optionsRef" :value="value" v-bind="attrs" @click="onClick" @update:value="updateValue($event)">
<template #dropdownRender="{ menuNode: menu }">
<template v-if="search">
<div class="flex w-full" style="padding: 4px 8px">
@@ -61,6 +61,7 @@ const props = defineProps<
watches?: string[];
search?: boolean;
pager?: boolean;
multi?: boolean;
} & ComponentPropsType
>();
@@ -68,6 +69,15 @@ const emit = defineEmits<{
"update:value": any;
}>();
function updateValue(value: any) {
if (props.multi) {
emit("update:value", value);
} else {
const last = value?.[value.length - 1];
emit("update:value", last);
}
}
const attrs = useAttrs();
const getCurrentPluginDefine: any = inject("getCurrentPluginDefine", () => {
@@ -80,6 +90,7 @@ const getPluginType: any = inject("get:plugin:type", () => {
return "plugin";
});
debugger;
const searchKeyRef = ref("");
const optionsRef = ref([]);
const message = ref("");

View File

@@ -789,6 +789,8 @@ export default {
reverseProxyHelper: "Reverse proxy for ACME address, used when applying for certificate",
reverseProxyPlaceholder: "http://le.px.handfree.work",
reverseProxyEmpty: "No reverse proxy list configured",
environmentVars: "Environment Variables",
environmentVarsHelper: "configure the runtime environment variables, one per line, format: KEY=VALUE",
},
},
modal: {

View File

@@ -800,6 +800,8 @@ export default {
reverseProxyHelper: "证书颁发机构ACME地址的反向代理在申请证书时自动使用",
reverseProxyPlaceholder: "http://le.px.handfree.work",
reverseProxyEmpty: "未配置反向代理",
environmentVars: "环境变量",
environmentVarsHelper: "配置运行时环境变量每行一个格式KEY=VALUE",
},
},
modal: {

View File

@@ -127,6 +127,21 @@ export const certdResources = [
keepAlive: true,
},
},
{
title: "certd.sysResources.currentProject",
name: "ProjectMemberManager",
path: "/certd/project/detail",
component: "/certd/project/detail/index.vue",
meta: {
show: () => {
const projectStore = useProjectStore();
return projectStore.isEnterprise;
},
isMenu: true,
icon: "ion:apps",
auth: true,
},
},
{
title: "certd.settings",
name: "MineSetting",
@@ -263,21 +278,6 @@ export const certdResources = [
isMenu: true,
},
},
{
title: "certd.sysResources.projectMemberManager",
name: "ProjectMemberManager",
path: "/certd/project/detail",
component: "/certd/project/detail/index.vue",
meta: {
show: () => {
const projectStore = useProjectStore();
return projectStore.isEnterprise;
},
isMenu: true,
icon: "ion:apps",
auth: true,
},
},
],
},
{

View File

@@ -101,6 +101,8 @@ export type SysPrivateSetting = {
commonCnameEnabled?: boolean;
// 同一个用户同时最大运行流水线数量
pipelineMaxRunningCount?: number;
// 环境变量
environmentVars?: string;
sms?: {
type?: string;

View File

@@ -1,4 +1,5 @@
import { useFormWrapper } from "@fast-crud/fast-crud";
import { merge } from "lodash-es";
export type FormOptionReq = {
title: string;
@@ -7,6 +8,7 @@ export type FormOptionReq = {
body?: any;
initialForm?: any;
zIndex?: number;
wrapper?: any;
};
export function useFormDialog() {
@@ -14,19 +16,23 @@ export function useFormDialog() {
async function openFormDialog(req: FormOptionReq) {
function createCrudOptions() {
const warpper = merge(
{
zIndex: req.zIndex,
title: req.title,
saveRemind: false,
slots: {
"form-body-top": req.body,
},
},
req.wrapper
);
return {
crudOptions: {
columns: req.columns,
form: {
initialForm: req.initialForm,
wrapper: {
zIndex: req.zIndex,
title: req.title,
saveRemind: false,
slots: {
"form-body-top": req.body,
},
},
wrapper: warpper,
async afterSubmit() {},
async doSubmit({ form }: any) {
if (req.onSubmit) {

View File

@@ -1,5 +1,5 @@
import * as _ from "lodash-es";
import { asyncCompute, compute } from "@fast-crud/fast-crud";
import { merge } from "lodash-es";
import { computed } from "vue";
export type MergeScriptContext = {
@@ -18,7 +18,7 @@ export function useReference(formItem: any) {
const script = formItem.mergeScript;
const func = new Function("ctx", script);
const merged = func(ctx);
_.merge(formItem, merged);
merge(formItem, merged);
delete formItem.mergeScript;
}

View File

@@ -6,7 +6,7 @@ import { useRouter } from "vue-router";
import { compute, CreateCrudOptionsRet, dict, useFormWrapper } from "@fast-crud/fast-crud";
import NotificationSelector from "/@/views/certd/notification/notification-selector/index.vue";
import { useReference } from "/@/use/use-refrence";
import { computed, ref } from "vue";
import { computed, provide, Ref, ref } from "vue";
import * as api from "../api";
import { PluginGroup, usePluginStore } from "/@/store/plugin";
import { createNotificationApi } from "/@/views/certd/notification/api";
@@ -89,9 +89,10 @@ export function useCertPipelineCreator() {
const inputs: any = {};
const moreParams = [];
const doSubmit = req.doSubmit;
for (const inputKey in req.certPlugin.input) {
const certPlugin = req.certPlugin;
for (const inputKey in certPlugin.input) {
// inputs[inputKey].form.show = true;
const inputDefine = cloneDeep(req.certPlugin.input[inputKey]);
const inputDefine = cloneDeep(certPlugin.input[inputKey]);
if (inputDefine.maybeNeed) {
moreParams.push(inputKey);
}
@@ -103,7 +104,6 @@ export function useCertPipelineCreator() {
},
};
}
const pluginStore = usePluginStore();
const randomHour = Math.floor(Math.random() * 6);
const randomMin = Math.floor(Math.random() * 60);
@@ -322,7 +322,7 @@ export function useCertPipelineCreator() {
return certPlugins;
}
async function openAddCertdPipelineDialog(req: { pluginName: string; defaultGroupId?: number; title?: string }) {
async function openAddCertdPipelineDialog(req: { pluginName: string; defaultGroupId?: number; title?: string; currentPluginRef: Ref<any> }) {
//检查是否流水线数量超出限制
await checkPipelineLimit();
@@ -393,6 +393,8 @@ export function useCertPipelineCreator() {
message.error("该证书申请插件不存在");
return;
}
req.currentPluginRef.value = certPlugin;
const { crudOptions } = createCrudOptions({
certPlugin,
doSubmit,

View File

@@ -52,7 +52,7 @@
</template>
<script lang="ts" setup>
import { computed, onActivated, onMounted, ref } from "vue";
import { computed, onActivated, onMounted, provide, ref } from "vue";
import { dict, useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import ChangeGroup from "./components/change-group.vue";
@@ -69,6 +69,7 @@ import { groupDictRef } from "./group/dicts";
import { useCertPipelineCreator } from "./certd-form/use";
import { useRouter } from "vue-router";
import { useCrudPermission } from "/@/plugin/permission";
import CertdForm from "./certd-form/certd-form.vue";
defineOptions({
name: "PipelineManager",
@@ -79,11 +80,17 @@ const context: any = {
selectedRowKeys,
};
const router = useRouter();
const { openAddCertdPipelineDialog } = useCertPipelineCreator();
function onActionbarMoreItemClick(req: { key: string; item: any }) {
openCertApplyDialog({ key: req.key, title: req.item?.title });
}
const certdFormRef = ref<typeof CertdForm>();
const currentPluginRef = ref();
provide("getCurrentPluginDefine", () => {
return currentPluginRef.value;
});
const addMorePipelineBtns = computed(() => {
return [
{ key: "CertApplyGetFormAliyun", title: t("certd.pipelinePage.aliyunSubscriptionPipeline"), icon: "svg:icon-aliyun" },
@@ -92,6 +99,7 @@ const addMorePipelineBtns = computed(() => {
{ key: "BatchAddPipeline", title: t("certd.pipelinePage.batchAddPipeline"), icon: "ion:duplicate" },
];
});
const { openAddCertdPipelineDialog } = useCertPipelineCreator();
function openCertApplyDialog(req: { key: string; title: string }) {
if (req.key === "AddPipeline") {
crudExpose.openAdd({});
@@ -104,7 +112,7 @@ function openCertApplyDialog(req: { key: string; title: string }) {
const searchForm = crudExpose.getSearchValidatedFormData();
const defaultGroupId = searchForm.groupId;
openAddCertdPipelineDialog({ pluginName: req.key, defaultGroupId, title: req.title });
openAddCertdPipelineDialog({ pluginName: req.key, defaultGroupId, title: req.title, currentPluginRef });
}
context.openCertApplyDialog = openCertApplyDialog;
context.permission = { isProjectPermission: true };

View File

@@ -294,13 +294,9 @@ function useStepForm() {
currentStep.value.input[key] = pluginSysConfig.sysSetting?.input[key];
}
}
console.log("currentStepTypeChanged:", currentStep.value);
console.log("currentStepPlugin:", currentPlugin.value);
};
const stepSave = async (e: any) => {
console.log("currentStepSave", currentStep.value);
try {
await stepFormRef.value.validate();
} catch (e) {

View File

@@ -73,3 +73,17 @@ export async function ApproveJoin(form: any) {
data: form,
});
}
export async function GetSelfResources() {
return await request({
url: "/enterprise/transfer/selfResources",
method: "post",
});
}
export async function TransferResources() {
return await request({
url: "/enterprise/transfer/doTransfer",
method: "post",
});
}

View File

@@ -9,8 +9,12 @@
<fs-values-format :model-value="project.permission" :dict="projectPermissionDict"></fs-values-format>
<a-divider type="vertical"></a-divider>
<fs-values-format :model-value="project.status" :dict="projectMemberStatusDict"></fs-values-format> -->
<a-divider type="vertical"></a-divider>
<a-button class="mr-5" type="primary" @click="openTransferDialog">个人数据迁移</a-button>
<a-button v-if="userStore.isAdmin" type="primary" @click="goProjectManager">{{ t("certd.project.projectManage") }}</a-button>
</span>
</div>
<div class="more"></div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding">
<template #pagination-left>
@@ -29,11 +33,13 @@ import createCrudOptions from "./crud";
import { message, Modal } from "ant-design-vue";
import { DeleteBatch } from "./api";
import { useI18n } from "/src/locales";
import { useRoute } from "vue-router";
import { useRoute, useRouter } from "vue-router";
import { useProjectStore } from "/@/store/project";
import { request } from "/@/api/service";
import { useDicts } from "../../dicts";
import { useCrudPermission } from "/@/plugin/permission";
import { useUserStore } from "/@/store/user";
import { useTransfer } from "./use";
const { t } = useI18n();
@@ -49,6 +55,14 @@ if (!projectId) {
projectId = projectStore.currentProject?.id;
}
const router = useRouter();
const userStore = useUserStore();
function goProjectManager() {
router.push(`/sys/enterprise/project`);
}
const { openTransferDialog } = useTransfer();
const { projectPermissionDict, projectMemberStatusDict, userDict } = useDicts();
const project: Ref<any> = ref({});

View File

@@ -1,46 +0,0 @@
import { dict } from "@fast-crud/fast-crud";
import { useDicts } from "../../dicts";
import { useFormDialog } from "/@/use/use-dialog";
export function useApprove() {
const { openFormDialog } = useFormDialog();
const { projectPermissionDict, projectMemberStatusDict, userDict } = useDicts();
function openApproveDialog({ id, permission, onSubmit }: { id: any; permission: any; onSubmit: any }) {
openFormDialog({
title: "审批加入申请",
columns: {
permission: {
title: "成员权限",
type: "dict-select",
dict: projectPermissionDict,
},
status: {
title: "审批结果",
type: "dict-radio",
dict: dict({
data: [
{
label: "通过",
value: "approved",
},
{
label: "拒绝",
value: "rejected",
},
],
}),
},
},
onSubmit: onSubmit,
initialForm: {
id: id,
permission: permission,
status: "approved",
},
});
}
return {
openApproveDialog,
};
}

View File

@@ -0,0 +1,134 @@
import { dict } from "@fast-crud/fast-crud";
import { useDicts } from "../../dicts";
import { useFormDialog } from "/@/use/use-dialog";
import * as api from "./api";
import { useProjectStore } from "/@/store/project";
import { message, Modal } from "ant-design-vue";
import { Ref, ref } from "vue";
export function useApprove() {
const { openFormDialog } = useFormDialog();
const { projectPermissionDict, projectMemberStatusDict, userDict } = useDicts();
function openApproveDialog({ id, permission, onSubmit }: { id: any; permission: any; onSubmit: any }) {
openFormDialog({
title: "审批加入申请",
columns: {
permission: {
title: "成员权限",
type: "dict-select",
dict: projectPermissionDict,
},
status: {
title: "审批结果",
type: "dict-radio",
dict: dict({
data: [
{
label: "通过",
value: "approved",
},
{
label: "拒绝",
value: "rejected",
},
],
}),
},
},
onSubmit: onSubmit,
initialForm: {
id: id,
permission: permission,
status: "approved",
},
});
}
return {
openApproveDialog,
};
}
export function useTransfer() {
const { openFormDialog } = useFormDialog();
async function doTransfer() {
Modal.confirm({
title: "请确认",
content: () => (
<div>
<p></p>
<p class="text-red-500"></p>
</div>
),
okText: "确认",
okType: "primary",
onOk: async () => {
await api.TransferResources();
message.success("迁移成功");
await loadMyResources();
},
});
}
const selfResources: Ref = ref({});
const projectStore = useProjectStore();
async function loadMyResources() {
selfResources.value = await api.GetSelfResources();
}
async function openTransferDialog() {
await loadMyResources();
openFormDialog({
title: "迁移我的个人资源到当前企业项目",
wrapper: {
buttons: {
ok: {
show: false,
},
reset: {
show: false,
},
},
},
body() {
return (
<div class="p-8">
<div class="flex flex-row items-center justify-evenly w-full">
<div>
<h3 class="text-lg font-bold"></h3>
<div class="mt-4">
<p>线{selfResources.value.pipeline}</p>
<p>线{selfResources.value.history}</p>
<p>线{selfResources.value.historyLog}</p>
<p>线{selfResources.value.pipelineGroup}</p>
<p>{selfResources.value.storage}</p>
<p>{selfResources.value.certInfo}</p>
<p>{selfResources.value.access}</p>
<p>{selfResources.value.siteMonitor}</p>
<p>{selfResources.value.notification}</p>
<p>{selfResources.value.group}</p>
<p>线{selfResources.value.template}</p>
<p>{selfResources.value.domain}</p>
<p>{selfResources.value.subdomain}</p>
<p>cname记录{selfResources.value.cnameRecord}</p>
</div>
</div>
<div class="text-2xl font-bold"> </div>
<div>"{projectStore.currentProject?.name}"</div>
</div>
<div class="flex flex-row items-center justify-center w-full">
<a-button type="primary" onClick={doTransfer}>
</a-button>
</div>
</div>
);
},
});
}
return {
openTransferDialog,
};
}

View File

@@ -7,6 +7,7 @@ import * as api from "./api";
import { useSettingStore } from "/@/store/settings";
import { useUserStore } from "/@/store/user";
import { useI18n } from "/src/locales";
import { useProjectStore } from "/@/store/project";
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const router = useRouter();
@@ -29,6 +30,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
};
const userStore = useUserStore();
const projectStore = useProjectStore();
const settingStore = useSettingStore();
const selectedRowKeys: Ref<any[]> = ref([]);
context.selectedRowKeys = selectedRowKeys;
@@ -61,6 +63,12 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
minWidth: 200,
fixed: "right",
},
form: {
onSuccess: async () => {
await projectStore.reload();
crudExpose?.doRefresh();
},
},
columns: {
id: {
title: "ID",

View File

@@ -14,6 +14,11 @@
<div class="helper">{{ t("certd.httpsProxyHelper") }}</div>
</a-form-item>
<a-form-item :label="t('certd.sys.setting.environmentVars')" :name="['private', 'environmentVars']">
<a-textarea v-model:value="formState.private.environmentVars" :placeholder="environmentVarsExample" rows="4" />
<div class="helper">{{ t("certd.sys.setting.environmentVarsHelper") }}</div>
</a-form-item>
<a-form-item :label="t('certd.dualStackNetwork')" :name="['private', 'dnsResultOrder']">
<a-select v-model:value="formState.private.dnsResultOrder">
<a-select-option value="verbatim">{{ t("certd.default") }}</a-select-option>
@@ -55,6 +60,11 @@ defineOptions({
name: "SettingNetwork",
});
const environmentVarsExample = ref(
`ALIYUN_CLIENT_CONNECT_TIMEOUT=16000 #连接超时,单位毫秒
ALIYUN_CLIENT_READ_TIMEOUT=16000 #读取数据超时,单位毫秒`
);
const formState = reactive<Partial<SysSettings>>({
public: {},
private: {},

View File

@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.1](https://github.com/certd/certd/compare/v1.39.0...v1.39.1) (2026-03-09)
### Performance Improvements
* 支持迁移个人数据到企业项目中 ([c6ca832](https://github.com/certd/certd/commit/c6ca83273779ed84de1b23b5e477063af043d015))
# [1.39.0](https://github.com/certd/certd/compare/v1.38.12...v1.39.0) (2026-03-07)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/ui-server",
"version": "1.39.0",
"version": "1.39.1",
"description": "fast-server base midway",
"private": true,
"type": "module",
@@ -50,20 +50,20 @@
"@aws-sdk/client-route-53": "^3.964.0",
"@aws-sdk/client-s3": "^3.964.0",
"@aws-sdk/client-sts": "^3.990.0",
"@certd/acme-client": "^1.39.0",
"@certd/basic": "^1.39.0",
"@certd/commercial-core": "^1.39.0",
"@certd/acme-client": "^1.39.1",
"@certd/basic": "^1.39.1",
"@certd/commercial-core": "^1.39.1",
"@certd/cv4pve-api-javascript": "^8.4.2",
"@certd/jdcloud": "^1.39.0",
"@certd/lib-huawei": "^1.39.0",
"@certd/lib-k8s": "^1.39.0",
"@certd/lib-server": "^1.39.0",
"@certd/midway-flyway-js": "^1.39.0",
"@certd/pipeline": "^1.39.0",
"@certd/plugin-cert": "^1.39.0",
"@certd/plugin-lib": "^1.39.0",
"@certd/plugin-plus": "^1.39.0",
"@certd/plus-core": "^1.39.0",
"@certd/jdcloud": "^1.39.1",
"@certd/lib-huawei": "^1.39.1",
"@certd/lib-k8s": "^1.39.1",
"@certd/lib-server": "^1.39.1",
"@certd/midway-flyway-js": "^1.39.1",
"@certd/pipeline": "^1.39.1",
"@certd/plugin-cert": "^1.39.1",
"@certd/plugin-lib": "^1.39.1",
"@certd/plugin-plus": "^1.39.1",
"@certd/plus-core": "^1.39.1",
"@google-cloud/publicca": "^1.3.0",
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.185",
"@huaweicloud/huaweicloud-sdk-core": "^3.1.185",

View File

@@ -0,0 +1,42 @@
import { BaseController, Constants } from '@certd/lib-server';
import { Controller, Inject, Post, Provide } from '@midwayjs/core';
import { TransferService } from '../../../modules/sys/enterprise/service/transfer-service.js';
/**
*/
@Provide()
@Controller('/api/enterprise/transfer')
export class TransferController extends BaseController {
@Inject()
service: TransferService;
getService(): TransferService {
return this.service;
}
/**
* 我自己的资源
* @param body
* @returns
*/
@Post('/selfResources', { summary: Constants.per.authOnly })
async selfResources() {
const userId = this.getUserId();
const res = await this.service.getUserResources(userId);
return this.ok(res);
}
/**
* 迁移项目
* @param body
* @returns
*/
@Post('/doTransfer', { summary: Constants.per.authOnly })
async doTransfer() {
const {projectId} = await this.getProjectUserIdRead();
const userId = this.getUserId();
await this.service.transferAll(userId,projectId);
return this.ok();
}
}

View File

@@ -16,6 +16,7 @@ import {SiteIpService} from "./site-ip-service.js";
import {SiteIpEntity} from "../entity/site-ip.js";
import {Cron} from "../../cron/cron.js";
import { dnsContainer } from "./dns-custom.js";
import { merge } from "lodash-es";
@Provide()
@Scope(ScopeEnum.Request, {allowDowngrade: true})
@@ -164,6 +165,8 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
await this.update(updateData);
const setting = await this.userSettingsService.getSetting<UserSiteMonitorSetting>(site.userId,site.projectId, UserSiteMonitorSetting)
merge(site,updateData)
//检查ip
await this.checkAllIp(site,retryTimes,setting);

View File

@@ -0,0 +1,93 @@
import { isEnterprise } from "@certd/lib-server";
import { ApplicationContext, IMidwayContainer, Provide, Scope, ScopeEnum } from "@midwayjs/core";
@Provide()
@Scope(ScopeEnum.Request, { allowDowngrade: true })
export class TransferService {
@ApplicationContext()
appCtx: IMidwayContainer;
async getServices() {
const getService = async (key: string) => {
return await this.appCtx.getAsync(key);
}
const serviceNames = [
"pipeline",
"certInfo",
"siteInfo",
"domain",
"cnameRecord",
"group",
"pipelineGroup",
"notification",
"subDomain",
"template",
"openKey",
"siteIp",
"access",
"history",
"historyLog",
"storage",
]
const services: any = {}
for (const key of serviceNames) {
services[key] = await getService(`${key}Service`);
}
return services;
}
/**
* 获取用户资源
* @param userId
* @returns
*/
async getUserResources(userId: number) {
const query = {
userId,
}
const services = await this.getServices();
const counts: any = {}
let totalCount = 0;
for (const key of Object.keys(services)) {
const count = await services[key].repository.count({ where: query });
counts[key] = count;
totalCount += count;
}
return {
...counts,
totalCount,
}
}
async transferAll(userId: number, projectId: number) {
if (!isEnterprise()) {
throw new Error('当前非企业模式,不支持资源迁移到项目');
}
if (projectId === 0) {
throw new Error('项目ID不能为0');
}
if (userId == null) {
throw new Error('用户ID不能为空');
}
const query = {
userId,
}
const services = await this.getServices();
for (const key of Object.keys(services)) {
await services[key].repository.update(query, {
userId: -1,
projectId,
});
}
}
}

View File

@@ -1,4 +1,4 @@
import { IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
import { IsTaskPlugin, Pager, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
import { AliyunAccess } from "../../../../plugin-lib/aliyun/access/index.js";
import { CertApplyBasePlugin } from "../base.js";
import { CertReader, createRemoteSelectInputDefine } from "@certd/plugin-lib";
@@ -34,8 +34,9 @@ export class CertApplyGetFormAliyunPlugin extends CertApplyBasePlugin {
helper: "订阅模式的证书订单Id",
typeName: "CertApplyGetFormAliyun",
component: {
name: "RemoteAutoComplete",
name: "RemoteSelect",
vModel: "value",
pager: true,
},
action: CertApplyGetFormAliyunPlugin.prototype.onGetOrderList.name,
})
@@ -126,6 +127,7 @@ export class CertApplyGetFormAliyunPlugin extends CertApplyBasePlugin {
const client = await access.getClient("cas.aliyuncs.com");
const pager = new Pager(req)
const res = await client.doRequest({
// 接口名称
action: "ListUserCertificateOrder",
@@ -139,12 +141,14 @@ export class CertApplyGetFormAliyunPlugin extends CertApplyBasePlugin {
data: {
query: {
Status: "ISSUED",
CurrentPage: pager.pageNo,
ShowSize : pager.pageSize,
},
},
});
const list = res?.CertificateOrderList || [];
if (!list || list.length === 0) {
throw new Error("没有找到已签发的证书订单");
return []
}
return list.map((item: any) => {

View File

@@ -1 +1 @@
01:18
00:03

View File

@@ -1 +1 @@
01:57
00:21