Compare commits

...
14 Commits
Author SHA1 Message Date
xiaojunnuo 14809127d6 v1.44.4 2026-09-12 19:23:35 +08:00
xiaojunnuo bd8b251d6e build: prepare to build 2026-09-12 19:17:14 +08:00
xiaojunnuo 5563abb13a fix: 修复证书插件配置无法打开的bug 2026-09-12 19:13:23 +08:00
xiaojunnuo 51e83e4c38 fix: 修复添加步骤会修改所有步骤标题的bug 2026-09-12 18:51:53 +08:00
xiaojunnuo 2b1a5296fe chore(certd-client): fix step form save data overwritten issue and add no payment tip
1. 修复步骤表单保存时因复用reactive对象导致已保存步骤被覆盖的问题,深拷贝currentStep后再传出
2. 新增无支付方式时显示暂不支持在线支付的提示
2026-09-12 18:49:24 +08:00
xiaojunnuo bded368cbb perf: 新增余额管理,管理员充值功能
1. 新增余额管理页面,支持用户余额查询与充值
2. 新增余额变更记录页面,查看用户余额明细
3. 补充多语言国际化文案
4. 修复免费订单显示文案为0元而非免费
5. 隐藏审核页面的操作按钮
6. 注释掉无用的堆日志启动代码
2026-09-12 16:06:53 +08:00
xiaojunnuo 6a649aaca0 perf(acme-account-access): AcmeAccount授权允许修改eab,重新生成account
修改了三处ACME账号表单的禁用判断条件,新增判断当editAccount为true时不禁用控件,允许在编辑已有账号时修改相关配置
2026-09-12 14:44:43 +08:00
xiaojunnuo e971145686 perf(ui): 商业版套餐购买不要求设置支付方式
1. 将套餐设置页面的"需要开启支付方式"提示改为"建议"
2. 新增支付方式为空且余额不足时的红色警告提示
3. 默认开启返利余额使用并修复支付字典加载异常处理
2026-09-12 14:28:52 +08:00
xiaojunnuo bbca449f94 Merge branch 'v2-dev' of https://github.com/certd/certd into v2-dev 2026-09-12 09:32:36 +08:00
xiaojunnuo e6852c2715 docs: 更新AGENTS.md编码规范说明
refactor(plugin-fastly): 简化多行API调用代码
refactor(plugin-serv
2026-09-11 19:01:29 +08:00
xiaojunnuo 47cb523307 chore(cloudflare): 优化权限说明的换行展示
修复Cloudflare插件的权限说明文本排版,将权限项用换行分开展示,提升可读性
2026-09-10 15:13:38 +08:00
xiaojunnuo cbf46b5c48 build: release 2026-09-07 00:07:49 +08:00
xiaojunnuo 7ed3105d97 build: publish 2026-09-06 23:51:23 +08:00
xiaojunnuo 61b945c08f build: trigger build image 2026-09-06 23:51:13 +08:00
55 changed files with 644 additions and 162 deletions
+1 -1
View File
@@ -75,7 +75,7 @@ Certd 是可私有化部署的 SSL/TLS 证书自动化管理平台,提供 Web
- 只有真正机械化的大批量替换、格式化或生成任务才考虑脚本/工具。若必须使用临时脚本,应放在临时目录并在同一个受控步骤内完成创建、执行、删除;不要把临时脚本落在仓库里跨多步工具调用执行。
- 不要主动运行 `pnpm install`;缺依赖、TTY、网络导致安装或测试失败时,停止尝试并说明环境问题。
- 优先沿用现有模块、插件、service、页面模式;不要为形式上的复用制造过度抽象。
- 代码可读性优先于短写法。尽量少用三元表达式,优先使用完整的 `if/else`;复杂条件、链式调用、内联对象和多层 helper 调用要拆成命名清晰的中间变量或小方法。
- 【重要重要重要】代码可读性优先于短写法。尽量少用三元表达式,优先使用完整的 `if/else`【其他技能与此条要求冲突的,以此条要求为准】;复杂条件、链式调用、内联对象和多层 helper 调用要拆成命名清晰的中间变量或小方法。
- 方法调用链不要直接塞进另一个方法参数;先用有意义的局部变量承接返回值,再传入下一步。
- 不要在单一表达式内嵌套分支、对象构造与方法调用。优先使用清晰的 `if/else` 分支;仅在确实能降低复杂度时才提取有意义的中间变量,避免为拆分而增加阅读跳转。
- 注释优先使用中文,尤其是业务规则、兼容逻辑、协议细节和隐藏风险;文件已有英文风格或引用外部术语时可保持一致。
+13
View File
@@ -3,6 +3,19 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
### Bug Fixes
* 修复添加步骤会修改所有步骤标题的bug ([51e83e4](https://github.com/certd/certd/commit/51e83e4c38f7f319314fdc38ef33cf5720b2dde0))
* 修复证书插件配置无法打开的bug ([5563abb](https://github.com/certd/certd/commit/5563abb13a62140f4dee668ab768cf4ff9371ddb))
### Performance Improvements
* 新增余额管理,管理员充值功能 ([bded368](https://github.com/certd/certd/commit/bded368cbb8974b6937ae260e448c25fae5c33ad))
* **acme-account-access:** AcmeAccount授权允许修改eab,重新生成account ([6a649aa](https://github.com/certd/certd/commit/6a649aaca083ccd3b517f7d676a58220aa33b37d))
* **ui:** 商业版套餐购买不要求设置支付方式 ([e971145](https://github.com/certd/certd/commit/e9711456860d7db40914a0c295534f7bca56f83c))
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
### Bug Fixes
+11
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.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
### Bug Fixes
* **plugin-service:** 修复同步自己开发的云端插件不显示已安装状态问题 ([dac94b6](https://github.com/certd/certd/commit/dac94b64f0ceb7176e2cf07ce220be0aa5ed98d2))
* **plugin:** 修复插件配置保存与加载的相关问题 ([bd94334](https://github.com/certd/certd/commit/bd9433478a43d5d64ce6370386d0fe0aaff07d2e))
### Performance Improvements
* **plugin:** add Fastly custom TLS certificates integration ([#797](https://github.com/certd/certd/issues/797)) [@szhu25](https://github.com/szhu25) ([2a2e963](https://github.com/certd/certd/commit/2a2e963914c4dfc192cbe0a4bbb9c115e626da01))
## [1.44.2](https://github.com/certd/certd/compare/v1.44.1...v1.44.2) (2026-09-03)
### Bug Fixes
+1 -1
View File
@@ -9,5 +9,5 @@
}
},
"npmClient": "pnpm",
"version": "1.44.3"
"version": "1.44.4"
}
+4
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.44.4](https://github.com/publishlab/node-acme-client/compare/v1.44.3...v1.44.4) (2026-09-12)
**Note:** Version bump only for package @certd/acme-client
## [1.44.3](https://github.com/publishlab/node-acme-client/compare/v1.44.2...v1.44.3) (2026-09-06)
**Note:** Version bump only for package @certd/acme-client
+3 -3
View File
@@ -3,7 +3,7 @@
"description": "Simple and unopinionated ACME client",
"private": false,
"author": "nmorsman",
"version": "1.44.3",
"version": "1.44.4",
"type": "module",
"module": "./dist/index.js",
"main": "./dist/index.js",
@@ -18,7 +18,7 @@
"types"
],
"dependencies": {
"@certd/basic": "^1.44.3",
"@certd/basic": "^1.44.4",
"@peculiar/x509": "^1.11.0",
"asn1js": "^3.0.5",
"axios": "^1.9.0",
@@ -76,5 +76,5 @@
"bugs": {
"url": "https://github.com/publishlab/node-acme-client/issues"
},
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
"gitHead": "cc60cd4cd1d914110be65284bcf16cd3c5a63b8d"
}
+4
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.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
**Note:** Version bump only for package @certd/basic
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
**Note:** Version bump only for package @certd/basic
+1 -1
View File
@@ -1 +1 @@
23:46
19:17
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@certd/basic",
"private": false,
"version": "1.44.3",
"version": "1.44.4",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -54,5 +54,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
"gitHead": "cc60cd4cd1d914110be65284bcf16cd3c5a63b8d"
}
+4
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.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
**Note:** Version bump only for package @certd/pipeline
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
**Note:** Version bump only for package @certd/pipeline
+4 -4
View File
@@ -1,7 +1,7 @@
{
"name": "@certd/pipeline",
"private": false,
"version": "1.44.3",
"version": "1.44.4",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -21,8 +21,8 @@
"lint": "eslint --fix --ext .ts src"
},
"dependencies": {
"@certd/basic": "^1.44.3",
"@certd/plus-core": "^1.44.3",
"@certd/basic": "^1.44.4",
"@certd/plus-core": "^1.44.4",
"dayjs": "^1.11.7",
"lodash-es": "^4.17.21",
"reflect-metadata": "^0.2.2"
@@ -51,5 +51,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
"gitHead": "cc60cd4cd1d914110be65284bcf16cd3c5a63b8d"
}
+4
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.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
**Note:** Version bump only for package @certd/lib-huawei
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
**Note:** Version bump only for package @certd/lib-huawei
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@certd/lib-huawei",
"private": false,
"version": "1.44.3",
"version": "1.44.4",
"main": "./dist/bundle.js",
"module": "./dist/bundle.js",
"types": "./dist/d/index.d.ts",
@@ -31,5 +31,5 @@
"prettier": "3.3.3",
"tslib": "^2.8.1"
},
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
"gitHead": "cc60cd4cd1d914110be65284bcf16cd3c5a63b8d"
}
+4
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.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
**Note:** Version bump only for package @certd/lib-iframe
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
**Note:** Version bump only for package @certd/lib-iframe
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@certd/lib-iframe",
"private": false,
"version": "1.44.3",
"version": "1.44.4",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -37,5 +37,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
"gitHead": "cc60cd4cd1d914110be65284bcf16cd3c5a63b8d"
}
+4
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.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
**Note:** Version bump only for package @certd/jdcloud
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
**Note:** Version bump only for package @certd/jdcloud
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@certd/jdcloud",
"version": "1.44.3",
"version": "1.44.4",
"description": "jdcloud openApi sdk",
"main": "./dist/bundle.js",
"module": "./dist/bundle.js",
@@ -63,5 +63,5 @@
"fetch"
]
},
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
"gitHead": "cc60cd4cd1d914110be65284bcf16cd3c5a63b8d"
}
+4
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.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
**Note:** Version bump only for package @certd/lib-k8s
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
**Note:** Version bump only for package @certd/lib-k8s
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "@certd/lib-k8s",
"private": false,
"version": "1.44.3",
"version": "1.44.4",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
@@ -21,7 +21,7 @@
"lint": "eslint --fix --ext .ts src"
},
"dependencies": {
"@certd/basic": "^1.44.3",
"@certd/basic": "^1.44.4",
"@kubernetes/client-node": "0.21.0"
},
"devDependencies": {
@@ -38,5 +38,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
"gitHead": "cc60cd4cd1d914110be65284bcf16cd3c5a63b8d"
}
+6
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.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
### Bug Fixes
* 修复证书插件配置无法打开的bug ([5563abb](https://github.com/certd/certd/commit/5563abb13a62140f4dee668ab768cf4ff9371ddb))
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
**Note:** Version bump only for package @certd/lib-server
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@certd/lib-server",
"version": "1.44.3",
"version": "1.44.4",
"description": "midway with flyway, sql upgrade way ",
"private": false,
"type": "module",
@@ -29,11 +29,11 @@
],
"license": "AGPL",
"dependencies": {
"@certd/acme-client": "^1.44.3",
"@certd/basic": "^1.44.3",
"@certd/pipeline": "^1.44.3",
"@certd/plugin-lib": "^1.44.3",
"@certd/plus-core": "^1.44.3",
"@certd/acme-client": "^1.44.4",
"@certd/basic": "^1.44.4",
"@certd/pipeline": "^1.44.4",
"@certd/plugin-lib": "^1.44.4",
"@certd/plus-core": "^1.44.4",
"@midwayjs/cache": "3.14.0",
"@midwayjs/core": "3.20.11",
"@midwayjs/i18n": "3.20.13",
@@ -69,5 +69,5 @@
"typeorm": "^0.3.20",
"typescript": "^5.4.2"
},
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
"gitHead": "cc60cd4cd1d914110be65284bcf16cd3c5a63b8d"
}
@@ -133,12 +133,12 @@ export class SysPrivateSettings extends BaseSettings {
// 内置项不在此配置 Directory URL:其端点由运行时按加密算法(pkType)通过 acme.getDirectoryUrl 获取,
// 例如 ZeroSSL、SSL.com 的 RSA 与 EC 证书使用不同的端点,写死单一 URL 会导致 EC 申请走错端点。
customAcmeProviders?: CustomAcmeProvider[] = [
{ sslProvider: "letsencrypt", title: "Let's Encrypt", directoryUrl: "", needEAB: false, builtIn: true },
{ sslProvider: "letsencrypt_staging", title: "Let's Encrypt测试环境", directoryUrl: "", needEAB: false, builtIn: true },
{ sslProvider: "letsencrypt", title: "Let's Encrypt(支持7天IP证书)", directoryUrl: "", needEAB: false, builtIn: true },
{ sslProvider: "google", title: "Google", directoryUrl: "", needEAB: true, builtIn: true },
{ sslProvider: "zerossl", title: "ZeroSSL", directoryUrl: "", needEAB: true, builtIn: true },
{ sslProvider: "litessl", title: "litessl", directoryUrl: "", needEAB: true, builtIn: true },
{ sslProvider: "litessl", title: "Litessl", directoryUrl: "", needEAB: true, builtIn: true },
{ sslProvider: "sslcom", title: "SSL.com", directoryUrl: "", needEAB: true, builtIn: true },
{ sslProvider: "letsencrypt_staging", title: "Let's Encrypt测试环境(只能生成测试证书)", directoryUrl: "", needEAB: false, builtIn: true },
];
removeSecret() {
@@ -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.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
**Note:** Version bump only for package @certd/midway-flyway-js
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
**Note:** Version bump only for package @certd/midway-flyway-js
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@certd/midway-flyway-js",
"version": "1.44.3",
"version": "1.44.4",
"description": "midway with flyway, sql upgrade way ",
"private": false,
"type": "module",
@@ -52,5 +52,5 @@
"typeorm": "^0.3.20",
"typescript": "^5.4.2"
},
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
"gitHead": "cc60cd4cd1d914110be65284bcf16cd3c5a63b8d"
}
@@ -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.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
**Note:** Version bump only for package @certd/plugin-cert
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
**Note:** Version bump only for package @certd/plugin-cert
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "@certd/plugin-cert",
"private": false,
"version": "1.44.3",
"version": "1.44.4",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -20,7 +20,7 @@
"lint": "eslint --fix --ext .ts src"
},
"dependencies": {
"@certd/plugin-lib": "^1.44.3"
"@certd/plugin-lib": "^1.44.4"
},
"devDependencies": {
"@types/chai": "^4.3.12",
@@ -38,5 +38,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
"gitHead": "cc60cd4cd1d914110be65284bcf16cd3c5a63b8d"
}
+4
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.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
**Note:** Version bump only for package @certd/plugin-lib
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
**Note:** Version bump only for package @certd/plugin-lib
+5 -5
View File
@@ -1,7 +1,7 @@
{
"name": "@certd/plugin-lib",
"private": false,
"version": "1.44.3",
"version": "1.44.4",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@@ -17,9 +17,9 @@
"lint": "eslint --fix --ext .ts src"
},
"dependencies": {
"@certd/acme-client": "^1.44.3",
"@certd/basic": "^1.44.3",
"@certd/pipeline": "^1.44.3",
"@certd/acme-client": "^1.44.4",
"@certd/basic": "^1.44.4",
"@certd/pipeline": "^1.44.4",
"dayjs": "^1.11.7",
"jszip": "^3.10.1",
"lodash-es": "^4.17.21",
@@ -45,5 +45,5 @@
"tslib": "^2.8.1",
"typescript": "^5.4.2"
},
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
"gitHead": "cc60cd4cd1d914110be65284bcf16cd3c5a63b8d"
}
+12
View File
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
### Bug Fixes
* 修复添加步骤会修改所有步骤标题的bug ([51e83e4](https://github.com/certd/certd/commit/51e83e4c38f7f319314fdc38ef33cf5720b2dde0))
* 修复证书插件配置无法打开的bug ([5563abb](https://github.com/certd/certd/commit/5563abb13a62140f4dee668ab768cf4ff9371ddb))
### Performance Improvements
* 新增余额管理,管理员充值功能 ([bded368](https://github.com/certd/certd/commit/bded368cbb8974b6937ae260e448c25fae5c33ad))
* **ui:** 商业版套餐购买不要求设置支付方式 ([e971145](https://github.com/certd/certd/commit/e9711456860d7db40914a0c295534f7bca56f83c))
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
### Bug Fixes
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@certd/ui-client",
"version": "1.44.3",
"version": "1.44.4",
"private": true,
"scripts": {
"dev": "vite --open",
@@ -104,8 +104,8 @@
"zod-defaults": "^0.1.3"
},
"devDependencies": {
"@certd/lib-iframe": "^1.44.3",
"@certd/pipeline": "^1.44.3",
"@certd/lib-iframe": "^1.44.4",
"@certd/pipeline": "^1.44.4",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"@types/chai": "^4.3.12",
@@ -53,6 +53,8 @@ export default {
suiteSetting: "Suite Settings",
orderManager: "Order Management",
userSuites: "User Suites",
balanceManager: "Balance Management",
balanceLog: "Balance Change Records",
inviteCommissionSetting: "Incentive Plan Settings",
inviteLevel: "Promotion Levels",
inviteUserLevel: "User Promotion Levels",
@@ -54,6 +54,8 @@ export default {
suiteSetting: "套餐设置",
orderManager: "订单管理",
userSuites: "用户套餐",
balanceManager: "余额管理",
balanceLog: "余额变更记录",
inviteCommissionSetting: "激励计划设置",
inviteLevel: "推广等级",
inviteUserLevel: "用户推广等级",
@@ -317,6 +317,34 @@ export const sysResources = [
keepAlive: true,
},
},
{
title: "certd.sysResources.balanceManager",
name: "SysWallet",
path: "/sys/suite/wallet",
component: "/sys/suite/wallet/index.vue",
meta: {
show: () => {
const settingStore = useSettingStore();
return settingStore.isComm;
},
icon: "ion:wallet-outline",
permission: "sys:settings:edit",
auth: true,
keepAlive: true,
},
},
{
title: "certd.sysResources.balanceLog",
name: "SysWalletLog",
path: "/sys/suite/wallet-log",
component: "/sys/suite/wallet/log/index.vue",
meta: {
isMenu: false,
permission: "sys:settings:view",
auth: true,
keepAlive: false,
},
},
{
title: "certd.sysResources.inviteCommissionSetting",
name: "SysInviteCommissionSetting",
@@ -26,6 +26,14 @@ export function fillPluginDefine(plugin: any) {
if (plugin.sysSetting?.metadata) {
merge(plugin.input, plugin.sysSetting.metadata?.input || {});
const keys = Object.keys(plugin.input);
for (const key of keys) {
//修复旧版本错误引入的key导致报错的问题 【多引入进了一个type=CertApply】
const column = plugin.input[key];
if (typeof column != "object") {
delete plugin.input[key];
}
}
// 应用选项映射
for (const key of Object.keys(plugin.input)) {
const inputDef = plugin.input[key];
@@ -51,10 +51,11 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
rowHandle: {
width: 120,
fixed: "right",
show: false,
buttons: {
view: { show: false },
edit: { show: false },
remove: { show: true },
remove: { show: false },
copy: { show: false },
},
},
@@ -280,7 +280,10 @@ function useStepForm() {
return;
}
callback.value("save", currentStep);
// currentStep 是复用同一份 reactive 对象,直接传给回调会被 task.steps 保存同一引用,
// 后续再次 stepOpen 会 delete 掉其属性,导致已保存的步骤(如第一个步骤)被覆盖。
// 这里深拷贝一份再传出,保证每个步骤是独立对象。
callback.value("save", cloneDeep(currentStep));
stepDrawerClose();
};
@@ -53,9 +53,14 @@
<div class="flex-o mt-5">
<span class="label">{{ $t("certd.order.paymentMethod") }}:</span>
<div v-if="durationSelected.price === 0 || expectedThirdPartyAmount === 0">{{ $t("certd.order.free") }}</div>
<div v-if="durationSelected.price === 0 || expectedThirdPartyAmount === 0">0元</div>
<div v-else-if="noPaymentMethod">当前仅支持余额支付</div>
<fs-dict-select v-else v-model:value="formRef.payType" :dict="paymentsDictRef" style="width: 200px"> </fs-dict-select>
</div>
<div v-if="showBalanceInsufficientTip" class="flex-o mt-5">
<span class="color-red">余额不足,请联系管理员,充值或设置套餐</span>
</div>
</div>
</a-modal>
</template>
@@ -88,12 +93,17 @@ async function open(opts: OrderModalOpenReq) {
formRef.value.productId = opts.product.id;
formRef.value.duration = opts.duration;
formRef.value.num = opts.num ?? 1;
formRef.value.useRebateBalance = false;
formRef.value.useRebateBalance = true;
try {
wallet.value = await GetWalletSummary();
} catch (e) {
wallet.value = { availableAmount: 0 };
}
try {
await paymentsDictRef.loadDict();
} catch (e) {
// 支付方式加载失败时按无可用支付方式处理
}
}
const paymentsDictRef = dict({
async getData() {
@@ -119,6 +129,23 @@ const expectedThirdPartyAmount = computed(() => {
return Math.max(0, (durationSelected.value?.price || 0) - expectedRebateAmount.value);
});
const noPaymentMethod = computed(() => {
return paymentsDictRef.data.length === 0;
});
const balanceInsufficient = computed(() => {
const price = durationSelected.value?.price || 0;
if (price <= 0) {
return false;
}
const availableAmount = wallet.value?.availableAmount || 0;
return availableAmount < price;
});
const showBalanceInsufficientTip = computed(() => {
return noPaymentMethod.value && balanceInsufficient.value;
});
function amountToYuan(amount: number) {
return util.amount.toYuan(amount || 0);
}
@@ -68,7 +68,7 @@ const labelCol = ref({
},
});
const wrapperCol = ref({ span: 16 });
const configForm: any = reactive({ type: props.plugin.fullName || props.plugin.name });
const configForm: any = reactive({});
const showDict = dict({
data: [
@@ -306,7 +306,6 @@ provide("get:scope", () => {
return getScope();
});
provide("get:plugin:type", () => {
debugger;
return props.plugin.pluginType;
});
</script>
@@ -3,7 +3,7 @@
<template #header>
<div class="title">
套餐设置
<span class="sub"> 需要<router-link :to="{ path: '/sys/settings', query: { tab: 'payment' } }">开启至少一种支付方式</router-link></span>
<span class="sub"> 建议<router-link :to="{ path: '/sys/settings', query: { tab: 'payment' } }">开启至少一种支付方式</router-link></span>
</div>
</template>
@@ -38,7 +38,7 @@
<a-form-item label=" " :colon="false">
<loading-button type="primary" html-type="button" :click="onClick">保存</loading-button>
<div class="helper">需要 <router-link :to="{ path: '/sys/settings', query: { tab: 'payment' } }">开启至少一种支付方式</router-link></div>
<div class="helper">建议 <router-link :to="{ path: '/sys/settings', query: { tab: 'payment' } }">开启至少一种支付方式</router-link></div>
</a-form-item>
</a-form>
</div>
@@ -0,0 +1,35 @@
import { request } from "/src/api/service";
const apiPrefix = "/sys/wallet";
export async function GetList(query: any) {
return await request({
url: apiPrefix + "/page",
method: "post",
data: query,
});
}
export async function Recharge(data: { userId: number; amount: number; remark?: string }) {
return await request({
url: apiPrefix + "/recharge",
method: "post",
data,
});
}
export async function GetWalletLogs(query: any) {
return await request({
url: apiPrefix + "/log/page",
method: "post",
data: query,
});
}
export async function GetSimpleUserByIds(ids: number[]) {
return await request({
url: "/sys/authority/user/getSimpleUserByIds",
method: "post",
data: { ids },
});
}
@@ -0,0 +1,193 @@
import { CreateCrudOptionsProps, CreateCrudOptionsRet, dict, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { notification } from "ant-design-vue";
import { useRouter } from "vue-router";
import { util } from "/@/utils";
import { useFormDialog } from "/@/use/use-dialog";
import createCrudOptionsUser from "/@/views/sys/authority/user/crud";
import PriceInput from "/@/views/sys/suite/product/price-input.vue";
import * as api from "./api";
export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const { openFormDialog } = useFormDialog();
const router = useRouter();
const userDict = dict({
async getNodesByValues(ids: number[]) {
return await api.GetSimpleUserByIds(ids);
},
value: "id",
label: "nickName",
});
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetList(query);
};
function moneyColumn(title: string) {
return {
title,
type: "number",
column: {
width: 120,
component: {
name: PriceInput,
vModel: "modelValue",
edit: false,
},
},
};
}
async function openRecharge(userId?: number) {
await openFormDialog({
title: "用户余额充值",
wrapper: { width: 520 },
initialForm: {
userId: userId ?? null,
amountYuan: null,
remark: "",
},
columns: {
userId: {
title: "用户",
type: "table-select",
dict: userDict,
form: {
col: { span: 24 },
rules: [{ required: true, message: "请选择用户" }],
component: {
disabled: userId != null,
crossPage: true,
multiple: false,
select: {
placeholder: "请选择用户",
},
createCrudOptions: createCrudOptionsUser,
},
},
},
amountYuan: {
title: "充值金额",
type: "number",
form: {
col: { span: 24 },
rules: [{ required: true, message: "请输入充值金额" }],
component: {
name: "a-input-number",
vModel: "value",
min: 0,
precision: 2,
addonAfter: "元",
style: { width: "100%" },
},
},
},
remark: {
title: "备注",
type: "text",
form: {
col: { span: 24 },
helper: "选填",
},
},
},
async onSubmit(form: any) {
await api.Recharge({
userId: form.userId,
amount: util.amount.toCent(form.amountYuan || 0),
remark: form.remark,
});
await crudExpose.doRefresh();
notification.success({ message: "充值成功" });
},
});
}
return {
crudOptions: {
request: {
pageRequest,
},
toolbar: { show: false },
actionbar: {
buttons: {
add: { show: false },
recharge: {
text: "余额充值",
type: "primary",
click: () => openRecharge(),
},
log: {
text: "余额变更记录",
type: "primary",
click: () => router.push("/sys/suite/wallet-log"),
},
},
},
rowHandle: {
width: 220,
fixed: "right",
buttons: {
view: { show: false },
edit: { show: false },
copy: { show: false },
remove: { show: false },
walletLog: {
text: "余额变更记录",
type: "link",
click: ({ row }) => router.push({ path: "/sys/suite/wallet-log", query: { userId: row.userId } }),
},
recharge: {
text: "充值",
type: "link",
click: ({ row }) => openRecharge(row.userId),
},
},
},
columns: {
id: {
title: "ID",
type: "number",
column: { width: 80 },
form: { show: false },
},
userId: {
title: "用户",
type: "table-select",
dict: userDict,
search: { show: true, col: { span: 3 } },
column: { width: 160 },
form: {
show: false,
component: {
crossPage: true,
multiple: false,
select: {
placeholder: "点击选择用户",
},
createCrudOptions: createCrudOptionsUser,
},
},
},
availableAmount: moneyColumn("可用余额"),
totalAmount: moneyColumn("总余额"),
frozenAmount: moneyColumn("冻结余额"),
totalIncomeAmount: moneyColumn("累计收入"),
totalConsumedAmount: moneyColumn("累计消费"),
totalWithdrawAmount: moneyColumn("累计提现"),
createTime: {
title: "创建时间",
type: "datetime",
form: { show: false },
column: { sorter: true, width: 160 },
},
updateTime: {
title: "更新时间",
type: "datetime",
form: { show: false },
column: { width: 160 },
},
},
},
};
}
@@ -0,0 +1,28 @@
<template>
<fs-page>
<template #header>
<div class="title">
余额管理
<span class="sub">管理用户余额,可给用户充值</span>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
</fs-page>
</template>
<script lang="ts" setup>
import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import { useMounted } from "/@/use/use-mounted";
defineOptions({
name: "SysWallet",
});
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions });
// 页面打开后获取列表数据
useMounted(async () => {
await crudExpose.doRefresh();
});
</script>
@@ -0,0 +1,100 @@
import { CreateCrudOptionsRet, dict, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
import { useRoute } from "vue-router";
import { util } from "/@/utils";
import createCrudOptionsUser from "/@/views/sys/authority/user/crud";
import * as api from "../api";
function moneyText(amount: number) {
const yuan = util.amount.toYuan(Math.abs(amount || 0));
if (amount < 0) {
return `-¥${yuan}`;
}
return `¥${yuan}`;
}
export default function (): CreateCrudOptionsRet {
const route = useRoute();
const userIdFromQuery = route.query.userId ? Number(route.query.userId) : undefined;
const userDict = dict({
async getNodesByValues(ids: number[]) {
return await api.GetSimpleUserByIds(ids);
},
value: "id",
label: "nickName",
});
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
return await api.GetWalletLogs(query);
};
return {
crudOptions: {
request: { pageRequest },
search: {
initialForm: { userId: userIdFromQuery },
},
actionbar: { show: false },
toolbar: { show: false },
rowHandle: { show: false },
columns: {
createTime: { title: "时间", type: "datetime", column: { width: 180 } },
userId: {
title: "用户",
type: "table-select",
dict: userDict,
search: { show: true, col: { span: 3 } },
column: { width: 160 },
form: {
show: false,
component: {
crossPage: true,
multiple: false,
select: { placeholder: "点击选择用户" },
createCrudOptions: createCrudOptionsUser,
},
},
},
type: {
title: "类型",
type: "dict-select",
dict: dict({
data: [
{ label: "收益入账", value: "income", color: "success" },
{ label: "余额抵扣", value: "consume", color: "default" },
{ label: "提现扣减", value: "withdraw", color: "warning" },
],
}),
search: { show: true, col: { span: 3 } },
column: { width: 120 },
},
amount: {
title: "变动金额",
type: "number",
column: {
width: 120,
cellRender({ value }) {
const amount = Number(value || 0);
return <span class={amount < 0 ? "text-green-500" : "text-red-500"}>{moneyText(amount)}</span>;
},
},
},
balanceAfter: {
title: "变动后余额",
type: "number",
column: {
width: 130,
cellRender({ value }) {
return <span class="text-red-500">{moneyText(Number(value || 0))}</span>;
},
},
},
remark: {
title: "备注",
type: "text",
column: { minWidth: 220 },
},
},
},
};
}
@@ -0,0 +1,45 @@
<template>
<fs-page>
<template #header>
<div class="title">
{{ pageTitle }}
<span class="sub">{{ pageSub }}</span>
</div>
</template>
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
</fs-page>
</template>
<script lang="ts" setup>
import { computed } from "vue";
import { useRoute } from "vue-router";
import { useFs } from "@fast-crud/fast-crud";
import createCrudOptions from "./crud";
import { useMounted } from "/@/use/use-mounted";
defineOptions({
name: "SysWalletLog",
});
const route = useRoute();
const isUserLog = computed(() => route.query.userId != null);
const pageTitle = computed(() => {
if (isUserLog.value) {
return "用户余额变更记录";
}
return "余额变更记录";
});
const pageSub = computed(() => {
if (isUserLog.value) {
return "查看该用户的余额变更明细";
}
return "查看所有用户的余额变更明细";
});
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions });
// 页面打开后获取列表数据
useMounted(async () => {
await crudExpose.doRefresh();
});
</script>
+7
View File
@@ -3,6 +3,13 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
### Performance Improvements
* 新增余额管理,管理员充值功能 ([bded368](https://github.com/certd/certd/commit/bded368cbb8974b6937ae260e448c25fae5c33ad))
* **acme-account-access:** AcmeAccount授权允许修改eab,重新生成account ([6a649aa](https://github.com/certd/certd/commit/6a649aaca083ccd3b517f7d676a58220aa33b37d))
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
### Bug Fixes
@@ -43,7 +43,7 @@ input:
return {
component: {
disabled: ctx.compute(({form})=> !!form.access?.account)
disabled: ctx.compute(({form})=> !!form.access?.account && !form.access?.editAccount)
}
}
@@ -85,7 +85,7 @@ input:
return form.access?._needEAB === true;
}),
component: {
disabled: ctx.compute(({form})=> !!form.access?.account)
disabled: ctx.compute(({form})=> !!form.access?.account && !form.access?.editAccount)
}
}
@@ -103,7 +103,7 @@ input:
return form.access?._needEAB === true;
}),
component: {
disabled: ctx.compute(({form})=> !!form.access?.account)
disabled: ctx.compute(({form})=> !!form.access?.account && !form.access?.editAccount)
}
}
@@ -9,7 +9,9 @@ input:
placeholder: api token,用户 API 令牌
helper: |-
前往 [获取API令牌](https://dash.cloudflare.com/profile/api-tokens),注意是令牌,不是密钥。
token权限必须包含:[Zone区域-Zone区域-Edit编辑], [Zone区域-DNS-Edit编辑]
token权限必须包含两条:
[Zone区域-Zone区域-Edit编辑]
[Zone区域-DNS-Edit编辑]
required: true
encrypt: true
proxy:
+14 -14
View File
@@ -1,6 +1,6 @@
{
"name": "@certd/ui-server",
"version": "1.44.3",
"version": "1.44.4",
"description": "fast-server base midway",
"private": true,
"type": "module",
@@ -43,20 +43,20 @@
"lint1": "eslint --fix --ext .ts src"
},
"dependencies": {
"@certd/acme-client": "^1.44.3",
"@certd/basic": "^1.44.3",
"@certd/commercial-core": "^1.44.3",
"@certd/acme-client": "^1.44.4",
"@certd/basic": "^1.44.4",
"@certd/commercial-core": "^1.44.4",
"@certd/cv4pve-api-javascript": "^8.4.2",
"@certd/jdcloud": "^1.44.3",
"@certd/lib-huawei": "^1.44.3",
"@certd/lib-k8s": "^1.44.3",
"@certd/lib-server": "^1.44.3",
"@certd/midway-flyway-js": "^1.44.3",
"@certd/pipeline": "^1.44.3",
"@certd/plugin-cert": "^1.44.3",
"@certd/plugin-lib": "^1.44.3",
"@certd/plugin-plus": "^1.44.3",
"@certd/plus-core": "^1.44.3",
"@certd/jdcloud": "^1.44.4",
"@certd/lib-huawei": "^1.44.4",
"@certd/lib-k8s": "^1.44.4",
"@certd/lib-server": "^1.44.4",
"@certd/midway-flyway-js": "^1.44.4",
"@certd/pipeline": "^1.44.4",
"@certd/plugin-cert": "^1.44.4",
"@certd/plugin-lib": "^1.44.4",
"@certd/plugin-plus": "^1.44.4",
"@certd/plus-core": "^1.44.4",
"@koa/cors": "^5.0.0",
"@midwayjs/bootstrap": "3.20.11",
"@midwayjs/cache": "3.14.0",
@@ -45,6 +45,7 @@ process.on("uncaughtException", error => {
// setInterval(log, 200);
// log()
// }
// startHeapLog();
@Configuration({
@@ -659,26 +659,6 @@ export class PluginService extends BaseService<PluginEntity> {
return this.builtInPluginService.getByType(type);
}
/**
* 表单可能直接提交对象形式的 dependPlugins(KvInput),落库前统一序列化为 YAML 字符串。
*/
// private normalizeDependPluginsParam(param: any) {
// if (param.dependPlugins && typeof param.dependPlugins === "object" && !Array.isArray(param.dependPlugins)) {
// param.dependPlugins = toDependPluginsYaml(param.dependPlugins);
// }
// }
// private normalizePluginYamlParam(param: any, field: "extra" | "dependPlugins") {
// const value = param[field];
// if (value && typeof value === "object" && !Array.isArray(value)) {
// param[field] = yaml.dump(value, {
// lineWidth: -1,
// noRefs: true,
// sortKeys: false,
// });
// }
// }
private normalizeStorePluginAuthor(plugin: Record<string, any>) {
const author = `${plugin.author || ""}`.trim();
plugin.author = author;
@@ -693,7 +673,6 @@ export class PluginService extends BaseService<PluginEntity> {
* @param param 数据
*/
async add(param: any) {
// this.normalizeDependPluginsParam(param);
param.type = normalizePluginSourceType(param.type);
if (param.type === "store") {
this.normalizeStorePluginAuthor(param);
@@ -849,7 +828,6 @@ export class PluginService extends BaseService<PluginEntity> {
private attachOnlineInstallState(list: PluginEntity[], bindUserId?: number) {
return list.map(item => {
const record = this.toOnlinePluginBean(item);
record.fullName = this.getOnlinePluginFullName(record);
record.upgradeAvailable = record.installed ? isOnlinePluginUpgradeAvailable(record.version, record.latest) : false;
record.editable = isAuthor(record, bindUserId);
return record;
@@ -903,6 +881,7 @@ export class PluginService extends BaseService<PluginEntity> {
} else {
storePlugin = await this.findOne({ where: { ...query, name: dependencyRef } });
}
if (storePlugin) {
return {
plugin: storePlugin,
@@ -1084,7 +1063,6 @@ export class PluginService extends BaseService<PluginEntity> {
override: true,
type: "store",
});
// await this.refreshOnlinePluginDownloadCount(res.fullName || fullName, res.plugin?.downloadCount);
return {
...importRes,
fullName: res.fullName || fullName,
@@ -1295,21 +1273,6 @@ export class PluginService extends BaseService<PluginEntity> {
await this.sysSettingsService.saveSetting(setting);
}
// private async refreshOnlinePluginDownloadCount(fullName: string, downloadCount?: number) {
// if (!fullName || downloadCount == null) {
// return;
// }
// await this.updateWhere(
// {
// type: "store",
// fullName,
// },
// {
// downloadCount,
// }
// );
// }
async unRegisterById(id: any) {
const item = await this.info(id);
if (!item) {
@@ -1354,19 +1317,11 @@ export class PluginService extends BaseService<PluginEntity> {
if (!param?.id) {
throw new Error("id 不能为空");
}
// this.normalizePluginYamlParam(param, "extra");
// this.normalizeDependPluginsParam(param);
await this.unRegisterById(param.id);
const res = await super.update(param);
await this.registerById(param.id);
return res;
}
async compile(code: string) {
const ts = await import("typescript");
return ts.transpileModule(code, {
compilerOptions: { module: ts.ModuleKind.ESNext },
}).outputText;
}
async importer(modulePath: string) {
if (!modulePath) {
@@ -1406,7 +1361,6 @@ export class PluginService extends BaseService<PluginEntity> {
const plugin = info[0];
try {
const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor;
// const script = await this.compile(plugin.content);
const script = plugin.content;
const getPluginClass = new AsyncFunction("_ctx", script);
const importer = this.importer.bind(this);
@@ -1651,26 +1605,6 @@ export class PluginService extends BaseService<PluginEntity> {
);
}
isNewVersion(version: string, latestVersion: string) {
if (!latestVersion) {
return false;
}
if (latestVersion === version) {
return false;
}
//分段比较
const current = version.split(".");
const latest = latestVersion.split(".");
for (let i = 0; i < current.length; i++) {
if (parseInt(latest[i]) > parseInt(current[i])) {
return true;
} else if (parseInt(latest[i]) < parseInt(current[i])) {
return false;
}
}
return false;
}
async getPluginDefine(name: string) {
return pluginRegistry.getDefine(name);
}
@@ -74,7 +74,7 @@ export class AcmeAccountAccess extends BaseAccess {
mergeScript: `
return {
component: {
disabled: ctx.compute(({form})=> !!form.access?.account)
disabled: ctx.compute(({form})=> !!form.access?.account && !form.access?.editAccount)
}
}
`,
@@ -116,7 +116,7 @@ export class AcmeAccountAccess extends BaseAccess {
return form.access?._needEAB === true;
}),
component: {
disabled: ctx.compute(({form})=> !!form.access?.account)
disabled: ctx.compute(({form})=> !!form.access?.account && !form.access?.editAccount)
}
}
`,
@@ -137,7 +137,7 @@ export class AcmeAccountAccess extends BaseAccess {
return form.access?._needEAB === true;
}),
component: {
disabled: ctx.compute(({form})=> !!form.access?.account)
disabled: ctx.compute(({form})=> !!form.access?.account && !form.access?.editAccount)
}
}
`,
@@ -19,7 +19,7 @@ export class CloudflareAccess extends BaseAccess {
component: {
placeholder: "api token,用户 API 令牌",
},
helper: "前往 [获取API令牌](https://dash.cloudflare.com/profile/api-tokens),注意是令牌,不是密钥。\n token权限必须包含:[Zone区域-Zone区域-Edit编辑], [Zone区域-DNS-Edit编辑]",
helper: "前往 [获取API令牌](https://dash.cloudflare.com/profile/api-tokens),注意是令牌,不是密钥。\n token权限必须包含两条:\n[Zone区域-Zone区域-Edit编辑]\n[Zone区域-DNS-Edit编辑]",
required: true,
encrypt: true,
})
@@ -212,10 +212,7 @@ export class FastlyAccess extends BaseAccess {
this.ctx.logger.info(`Fastly 已存在相同证书,复用 certId: ${existingId}`);
return existingId;
}
throw new Error(
`Fastly 证书已存在:${message}。` +
"该证书可能此前已上传。请在【Fastly-上传证书到Fastly】任务中填写该证书ID以走更新(PATCH)流程。"
);
throw new Error(`Fastly 证书已存在:${message}。` + "该证书可能此前已上传。请在【Fastly-上传证书到Fastly】任务中填写该证书ID以走更新(PATCH)流程。");
}
}
@@ -286,11 +283,7 @@ export class FastlyAccess extends BaseAccess {
private async findActivation(configurationId: string, domainId: string): Promise<any | undefined> {
// encodeURIComponent 按规范保留 `*`,但 Fastly 过滤条件要求通配符编码为 `%2A`。
const encodedDomainId = encodeURIComponent(domainId).replace(/\*/g, "%2A");
const body = await this.doRequestApi(
`/tls/activations?filter[tls_domain.id]=${encodedDomainId}&page[size]=100`,
null,
"get"
);
const body = await this.doRequestApi(`/tls/activations?filter[tls_domain.id]=${encodedDomainId}&page[size]=100`, null, "get");
const items: any[] = Array.isArray(body?.data) ? body.data : [];
if (items.length === 0) {
return undefined;
@@ -308,11 +301,7 @@ export class FastlyAccess extends BaseAccess {
private async ensurePrivateKey(keyPem: string, name?: string): Promise<string> {
this.ctx.logger.info("开始上传私钥到 Fastly...");
try {
const keyRes = await this.doRequestApi(
"/tls/private_keys",
{ data: { type: "tls_private_key", attributes: { key: keyPem, ...(name && { name }) } } },
"post"
);
const keyRes = await this.doRequestApi("/tls/private_keys", { data: { type: "tls_private_key", attributes: { key: keyPem, ...(name && { name }) } } }, "post");
const id = keyRes?.data?.id;
if (!id) {
throw new Error("Fastly 私钥上传失败,未获取到 private key ID");
@@ -337,11 +326,7 @@ export class FastlyAccess extends BaseAccess {
return matched[0].id;
}
}
throw new Error(
`Fastly 私钥已存在但无法确定其ID:${message}。` +
"请在【Fastly-上传证书到Fastly】任务中填写已有证书ID以走更新(PATCH)流程," +
"或在 Fastly 控制台删除该孤立私钥后重试。"
);
throw new Error(`Fastly 私钥已存在但无法确定其ID:${message}。` + "请在【Fastly-上传证书到Fastly】任务中填写已有证书ID以走更新(PATCH)流程," + "或在 Fastly 控制台删除该孤立私钥后重试。");
}
}
+1 -1
View File
@@ -1 +1 @@
22:05
23:51
+1 -1
View File
@@ -1 +1 @@
22:16
00:07