Compare commits
151 Commits
v1.38.3
...
c8e193e70d
| Author | SHA1 | Date | |
|---|---|---|---|
| c8e193e70d | |||
| 35859ffc3f | |||
| 0d81ada5a8 | |||
| b68cf0fb45 | |||
| 9ed2078e92 | |||
| 1f002159e2 | |||
| 5bc690fcd9 | |||
| bab9adce24 | |||
| e47eddaa85 | |||
| 8ef1f2e395 | |||
| 7626eecbf6 | |||
| 49afa75929 | |||
| 5c5265ede2 | |||
| 42d61d8089 | |||
| 01eb50078e | |||
| eef021f472 | |||
| 6f3fd785e7 | |||
| 7cd8a645a8 | |||
| 9671348dc1 | |||
| 7a3e68d656 | |||
| 42c7ec2f75 | |||
| 32c3ce5c98 | |||
| e55a3a82fc | |||
| 305da86f97 | |||
| c23d1d11b5 | |||
| a3cabd5f36 | |||
| 66ac4716f2 | |||
| 3cd1aaeb03 | |||
| 4eb940ffe7 | |||
| 61800b23e2 | |||
| 0283662931 | |||
| 8387fe0d5b | |||
| b91548eef4 | |||
| 1195417b97 | |||
| 8c2dfa9140 | |||
| a3fbfe0bff | |||
| e7e54bc19e | |||
| 9fb980599f | |||
| 9642df2d9d | |||
| 8919a3937a | |||
| 5032030f8d | |||
| b30cb5d7dc | |||
| 7113c4622b | |||
| bd8caff0b7 | |||
| 519bf3184a | |||
| 79c77ce3a3 | |||
| 2f40f795ee | |||
| 02f89a9c9d | |||
| d286c040a5 | |||
| 99f5b8ebc1 | |||
| 9ac33f9b9b | |||
| 6ab1fcaf89 | |||
| 8d57063e9d | |||
| 104d646c7c | |||
| 9ddbf79d9e | |||
| a9ec4c5c28 | |||
| 914d860197 | |||
| 23b3e5c731 | |||
| cdf04c2402 | |||
| 3535e44337 | |||
| 0b245d3885 | |||
| 4fda6cbcde | |||
| 2bbba897ec | |||
| 0cfb94b0ba | |||
| 3f7ac93932 | |||
| 96c36b4f6a | |||
| febd6d32cf | |||
| cbd8699801 | |||
| 74400aacc6 | |||
| 9f55c3605a | |||
| 8d61e8179f | |||
| f250889c3e | |||
| 00f67d86d6 | |||
| 5b580d2a17 | |||
| 083dd7d1a3 | |||
| 03bd4755ce | |||
| 29d37075dd | |||
| f311bac580 | |||
| beb7a4c992 | |||
| 4d86fb319b | |||
| 5ea4f46de7 | |||
| 1d8d5251ae | |||
| 54c8217808 | |||
| ba623903e0 | |||
| 907af3ae18 | |||
| 24ae8a6b66 | |||
| 1646a5cdd2 | |||
| 814f17d10b | |||
| 40fe105903 | |||
| 42a347d8b1 | |||
| 5450e5dac4 | |||
| 1368259a1e | |||
| 81a495f267 | |||
| 693a4a6633 | |||
| 82786c580a | |||
| e19743f705 | |||
| 9166a57930 | |||
| bd511f97cb | |||
| 560bf40e4b | |||
| 4f4652c1cd | |||
| 60e13c2a1d | |||
| 1fe0dc4d16 | |||
| 181a1e3c0a | |||
| 6bba771856 | |||
| 921f1f42fb | |||
| eeb1f27fa4 | |||
| 9ce21ad152 | |||
| c036929cfe | |||
| 21591a3a89 | |||
| a2e9a41a7e | |||
| 0902349130 | |||
| f900db8e10 | |||
| 0fa9b344e0 | |||
| f48ef3d17b | |||
| 40801d0a06 | |||
| c6ccf1cf21 | |||
| d311992983 | |||
| b4babbe2c7 | |||
| 0719f4c99e | |||
| eb5de15033 | |||
| b229486d3b | |||
| 33b8d3e219 | |||
| 230256793f | |||
| 540ef96745 | |||
| 1baf30a671 | |||
| 5e93840e48 | |||
| 73a5908039 | |||
| 8429148273 | |||
| 17f40e2180 | |||
| 0345b12379 | |||
| 163b0de874 | |||
| 1661caed05 | |||
| 1089aeab9e | |||
| 1a0d3eeb1b | |||
| c27636529d | |||
| ac85488245 | |||
| 433e98b645 | |||
| 873654669e | |||
| 8b96f218d5 | |||
| 52cbff0e15 | |||
| 32de8d9ccb | |||
| e06da886f7 | |||
| cdd5ad3a8e | |||
| 9bee0e460b | |||
| 60c8ace443 | |||
| 933aaeaf25 | |||
| ca43c77525 | |||
| b204182c13 | |||
| dfb4165a12 | |||
| 26a54cd228 | |||
| e229f14121 |
@@ -30,4 +30,5 @@ test/**/*.js
|
|||||||
/packages/ui/certd-server/data/keys.yaml
|
/packages/ui/certd-server/data/keys.yaml
|
||||||
/packages/pro/
|
/packages/pro/
|
||||||
test.js
|
test.js
|
||||||
.history
|
.history
|
||||||
|
/logs
|
||||||
@@ -16,5 +16,9 @@
|
|||||||
},
|
},
|
||||||
"[less]": {
|
"[less]": {
|
||||||
"editor.defaultFormatter": "vscode.css-language-features"
|
"editor.defaultFormatter": "vscode.css-language-features"
|
||||||
}
|
},
|
||||||
|
"scm.repositories.visible": 9,
|
||||||
|
"scm.repositories.explorer": false,
|
||||||
|
"scm.repositories.selectionMode": "multiple",
|
||||||
|
"scm.repositories.sortOrder": "discovery time"
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,124 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/certd/certd/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复1panel2.1.0新版本测试失败的问题 ([8ef1f2e](https://github.com/certd/certd/commit/8ef1f2e395ea5969a95f55535e6c16a65e2b463b))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化登陆页面的黑暗模式 ([e47edda](https://github.com/certd/certd/commit/e47eddaa858f8fffe7a40dfbd14e8cda1dcba4ac))
|
||||||
|
* 支持自定义发件人名称,格式:名称<邮箱> ([bab9adc](https://github.com/certd/certd/commit/bab9adce240108d4291eedc67e04abc4a01019e0))
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/certd/certd/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复1panel 请求失败的bug ([0283662](https://github.com/certd/certd/commit/0283662931ff47d6b5d49f91a30c4a002fe1d108))
|
||||||
|
* 修复阿里云dcdn使用上传到cas的id引用错误的bug ([61800b2](https://github.com/certd/certd/commit/61800b23e2be324169990810d1176c18decabb23))
|
||||||
|
* 修复保存站点监控dns设置,偶尔无法保存成功的bug ([8387fe0](https://github.com/certd/certd/commit/8387fe0d5b2e77b8c2788a10791e5389d97a3e41))
|
||||||
|
* 修复任务步骤标题过长导致错位的问题 ([9fb9805](https://github.com/certd/certd/commit/9fb980599f96ccbf61bd46019411db2f13c70e57))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 421 支持3次重试 ([b91548e](https://github.com/certd/certd/commit/b91548eef4c24faa822d3a40f1f6a77b41d274e4))
|
||||||
|
* 备份支持scp上传 ([66ac471](https://github.com/certd/certd/commit/66ac4716f2565d7ee827461b625397ae21599451))
|
||||||
|
* 监控设置支持逗号分割 ([c23d1d1](https://github.com/certd/certd/commit/c23d1d11b58a6cdfe431a7e8abbd5d955146c38d))
|
||||||
|
* 列表中支持下次执行时间显示 ([a3cabd5](https://github.com/certd/certd/commit/a3cabd5f36ed41225ad418098596e9b2c44e31a1))
|
||||||
|
* 模版编辑页面,hover反色过亮问题优化 ([e55a3a8](https://github.com/certd/certd/commit/e55a3a82fc6939b940f0c3be4529d74a625f6f4e))
|
||||||
|
* 群晖支持刷新登录有效期 ([42c7ec2](https://github.com/certd/certd/commit/42c7ec2f75947e2b8298d6605d4dbcd441aacd51))
|
||||||
|
* 所有授权增加测试按钮 ([7a3e68d](https://github.com/certd/certd/commit/7a3e68d656c1dcdcd814b69891bd2c2c6fe3098a))
|
||||||
|
* 新网互联支持查询域名列表 ([e7e54bc](https://github.com/certd/certd/commit/e7e54bc19e3a734913a93a94e25db3bb06d2ab0f))
|
||||||
|
* 优化京东云报错详情显示 ([1195417](https://github.com/certd/certd/commit/1195417b9714d2fcb540e43c0a20809b7ee2052b))
|
||||||
|
* 优化网络测试页面,夜间模式显示效果 ([305da86](https://github.com/certd/certd/commit/305da86f97d918374819ecd6c50685f09b94ea59))
|
||||||
|
* 增加部署证书到certd本身插件 ([3cd1aae](https://github.com/certd/certd/commit/3cd1aaeb035f8af79714030889b2b4dc259b700e))
|
||||||
|
* 支持next-terminal ([6f3fd78](https://github.com/certd/certd/commit/6f3fd785e77a33c72bdf4115dc5d498e677d1863))
|
||||||
|
* 主题默认跟随系统颜色(自动切换深色浅色模式) ([32c3ce5](https://github.com/certd/certd/commit/32c3ce5c9868569523901a9a939ca5b535ec3277))
|
||||||
|
* http校验方式支持scp上传 ([4eb940f](https://github.com/certd/certd/commit/4eb940ffe765a0330331bc6af8396315e36d4e4a))
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/certd/certd/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复部署到openwrt错误的bug ([9ac33f9](https://github.com/certd/certd/commit/9ac33f9b9ba7727fcbbd320dd866bc048cbb3d72))
|
||||||
|
* 修复新版本上传到阿里云cas后,其他依赖任务无法部署的bug ([99f5b8e](https://github.com/certd/certd/commit/99f5b8ebc1c64798ceb42042ad71cf71e967beb0))
|
||||||
|
* esxi部署失败的bug ([6ab1fca](https://github.com/certd/certd/commit/6ab1fcaf894f7ce343af4b5bf4b0d67438df6618))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 修改sql升级语句,兼容mysql5.7 ([02f89a9](https://github.com/certd/certd/commit/02f89a9c9d77850437285844670aed441e5953c3))
|
||||||
|
* 已登录状态访问登录页面自动跳转到首页 ([bd8caff](https://github.com/certd/certd/commit/bd8caff0b754cb13530cf0f1644b33e29fde5d01))
|
||||||
|
* 优化access授权支持remote-auto-complete ([2f40f79](https://github.com/certd/certd/commit/2f40f795ee6131132d3fab2601f92a567bbdc4b7))
|
||||||
|
* access 插件支持remote-select等配置 ([d286c04](https://github.com/certd/certd/commit/d286c040a5232dcca829945734affead3ee08b3c))
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/certd/certd/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 双重验证显示secret ([febd6d3](https://github.com/certd/certd/commit/febd6d32cfe6d89ccecf26bf15141df7c456e5c6))
|
||||||
|
* 优化申请证书最大超时时长 ([00f67d8](https://github.com/certd/certd/commit/00f67d86d68f4f83cfafe2fbfeb4af0d86f9d20e))
|
||||||
|
* 支持设置默认的证书申请地址的反向代理 ([0cfb94b](https://github.com/certd/certd/commit/0cfb94b0ba6a6dc3bb0d0a81a1912068a4e6b6b6))
|
||||||
|
* 子域名托管域名支持配置通配符 ([3f7ac93](https://github.com/certd/certd/commit/3f7ac939326b0c7ec013a7534b6c0e58fb3e8cb4))
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复有域名记录时,域名输入框无法关闭的bug ([54c8217](https://github.com/certd/certd/commit/54c8217808453b121abf646b004596f28932509f))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* eab从更多参数中挪到外面 ([5ea4f46](https://github.com/certd/certd/commit/5ea4f46de7ae403a7a16e9488dc1d9c7523d019a))
|
||||||
|
* 第三方登录支持Microsoft ([beb7a4c](https://github.com/certd/certd/commit/beb7a4c99277262bb9681c5594cfcd3e36c52074))
|
||||||
|
* 优化zerossl申请证书稳定性 ([4d86fb3](https://github.com/certd/certd/commit/4d86fb319b81dbf6fa6485982105725b1b066593))
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复新网找错域名的bug ([bd511f9](https://github.com/certd/certd/commit/bd511f97cb7fbdcaeff7ac899f0460a5c7b41826))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 当域名管理中没有域名时,创建流水线时不展开域名选择框 ([9166a57](https://github.com/certd/certd/commit/9166a579301a60750f0b72b6a42b0c8d730695fd))
|
||||||
|
* count tip ([e19743f](https://github.com/certd/certd/commit/e19743f70553700f1f91bff76f87370f749dd247))
|
||||||
|
* oauth支持github 和google, 修复头像显示问题 ([693a4a6](https://github.com/certd/certd/commit/693a4a663385ced3176286bf4b5f3566da83d90e))
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 阿里云esa查询证书限制接口无效,改成配置证书数量上限检查方式进行清理 ([2302567](https://github.com/certd/certd/commit/230256793f8ad87ef8a0738c37108bf7b5ab9853))
|
||||||
|
* 某些情况下登陆页面没有显示重置密码文档链接的问题 ([40801d0](https://github.com/certd/certd/commit/40801d0a0668c77adb57fae42b4b6615b198a88d))
|
||||||
|
* 修复部署到火山引擎vod,获取域名列表为空的bug ([0719f4c](https://github.com/certd/certd/commit/0719f4c99e9198544d03431107b53652e076e881))
|
||||||
|
* 修复litessl new-nonce报428的bug ([540ef96](https://github.com/certd/certd/commit/540ef967457a7871637cfdb5012ed1fa3261757b))
|
||||||
|
* 修复oidc配置取消后获取登出地址失败后无法列出oauth列表的bug ([eb5de15](https://github.com/certd/certd/commit/eb5de150332fd914c56b812c3ba2c2445f902bb7))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 将重置密码的日志挪到启动成功之后,方便查看 ([0fa9b34](https://github.com/certd/certd/commit/0fa9b344e08cf355aee7a7566f061cc5d95dc374))
|
||||||
|
* 支持绑定两个url地址 ([a2e9a41](https://github.com/certd/certd/commit/a2e9a41a7e712395c0e3ee6fe55b370aa1fc1f12))
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/certd/certd/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复1:: 形式的ipv6校验失败的bug ([8b96f21](https://github.com/certd/certd/commit/8b96f218d5284033f10c186c0ce18e4c16d8e9b2))
|
||||||
|
* 修复阿里云esa超过免费配额之后无法部署证书的bug,改成删除最旧的那张证书 ([32de8d9](https://github.com/certd/certd/commit/32de8d9ccb08d26414adbdde950d7cd405dc344a))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 当ip证书天数太小时,自动调整更新天数,避免每次运行都重新申请ip证书 ([433e98b](https://github.com/certd/certd/commit/433e98b6450fa7d0491151f159e432bf3dfe4feb))
|
||||||
|
* 首页证书数量支持点击跳转 ([52cbff0](https://github.com/certd/certd/commit/52cbff0e15329aecd3edcf81315fb7ceab9ec290))
|
||||||
|
* 修复旧版本流水线数据发送通知标题为空的bug ([9bee0e4](https://github.com/certd/certd/commit/9bee0e460bfebe8db76742b80b2d52854392f4de))
|
||||||
|
* 验证码支持 Cloudflare Turnstile ,谨慎启用,国内被墙了 ([ca43c77](https://github.com/certd/certd/commit/ca43c775250154def63c4acd96d65dc95d1c0c2b))
|
||||||
|
* 优化证书未过期时的任务日志提示 ([ac85488](https://github.com/certd/certd/commit/ac85488245197694560aad7df9425ca215ef7ff7))
|
||||||
|
* 支持部署到阿里云GA ([1a0d3ee](https://github.com/certd/certd/commit/1a0d3eeb1b0b5ce08f05af84b6161e00c1fe1815))
|
||||||
|
* 支持部署到华为elb ([60c8ace](https://github.com/certd/certd/commit/60c8ace443e848155d3ce12e95b84766a4610d3a))
|
||||||
|
* 支持部署到AcePanel ([1661cae](https://github.com/certd/certd/commit/1661caed05e3413dc3e2b14ce62b75aa03ad90e0))
|
||||||
|
|
||||||
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -41,9 +41,7 @@ Certd® 是一个免费的全自动证书管理系统,让你的网站证书永
|
|||||||
* **多语言支持**: 中英双语切换
|
* **多语言支持**: 中英双语切换
|
||||||
* **无忧升级**: 版本向下兼容
|
* **无忧升级**: 版本向下兼容
|
||||||
|
|
||||||
|

|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
## 二、在线体验
|
## 二、在线体验
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ services:
|
|||||||
# - certd_typeorm_dataSource_default_password=yourpasswd # 密码
|
# - certd_typeorm_dataSource_default_password=yourpasswd # 密码
|
||||||
# - certd_typeorm_dataSource_default_database=certd # 数据库名
|
# - certd_typeorm_dataSource_default_database=certd # 数据库名
|
||||||
|
|
||||||
# #↓↓↓↓ ----------------------------- 使用mysql数据库,需要提前创建数据库 charset=utf8mb4, collation=utf8mb4_bin
|
# #↓↓↓↓ ----------------------------- 使用mysql8数据库,需要提前创建数据库 charset=utf8mb4, collation=utf8mb4_bin
|
||||||
# - certd_flyway_scriptDir=./db/migration-mysql # 升级脚本目录
|
# - certd_flyway_scriptDir=./db/migration-mysql # 升级脚本目录
|
||||||
# - certd_typeorm_dataSource_default_type=mysql # 数据库类型, 或者 mariadb
|
# - certd_typeorm_dataSource_default_type=mysql # 数据库类型, 或者 mariadb
|
||||||
# - certd_typeorm_dataSource_default_host=localhost # 数据库地址
|
# - certd_typeorm_dataSource_default_host=localhost # 数据库地址
|
||||||
|
|||||||
@@ -3,6 +3,148 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/certd/certd/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复1panel2.1.0新版本测试失败的问题 ([8ef1f2e](https://github.com/certd/certd/commit/8ef1f2e395ea5969a95f55535e6c16a65e2b463b))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化登陆页面的黑暗模式 ([e47edda](https://github.com/certd/certd/commit/e47eddaa858f8fffe7a40dfbd14e8cda1dcba4ac))
|
||||||
|
* 支持自定义发件人名称,格式:名称<邮箱> ([bab9adc](https://github.com/certd/certd/commit/bab9adce240108d4291eedc67e04abc4a01019e0))
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/certd/certd/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复1panel 请求失败的bug ([0283662](https://github.com/certd/certd/commit/0283662931ff47d6b5d49f91a30c4a002fe1d108))
|
||||||
|
* 修复阿里云dcdn使用上传到cas的id引用错误的bug ([61800b2](https://github.com/certd/certd/commit/61800b23e2be324169990810d1176c18decabb23))
|
||||||
|
* 修复保存站点监控dns设置,偶尔无法保存成功的bug ([8387fe0](https://github.com/certd/certd/commit/8387fe0d5b2e77b8c2788a10791e5389d97a3e41))
|
||||||
|
* 修复任务步骤标题过长导致错位的问题 ([9fb9805](https://github.com/certd/certd/commit/9fb980599f96ccbf61bd46019411db2f13c70e57))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 421 支持3次重试 ([b91548e](https://github.com/certd/certd/commit/b91548eef4c24faa822d3a40f1f6a77b41d274e4))
|
||||||
|
* 备份支持scp上传 ([66ac471](https://github.com/certd/certd/commit/66ac4716f2565d7ee827461b625397ae21599451))
|
||||||
|
* 监控设置支持逗号分割 ([c23d1d1](https://github.com/certd/certd/commit/c23d1d11b58a6cdfe431a7e8abbd5d955146c38d))
|
||||||
|
* 列表中支持下次执行时间显示 ([a3cabd5](https://github.com/certd/certd/commit/a3cabd5f36ed41225ad418098596e9b2c44e31a1))
|
||||||
|
* 模版编辑页面,hover反色过亮问题优化 ([e55a3a8](https://github.com/certd/certd/commit/e55a3a82fc6939b940f0c3be4529d74a625f6f4e))
|
||||||
|
* 群晖支持刷新登录有效期 ([42c7ec2](https://github.com/certd/certd/commit/42c7ec2f75947e2b8298d6605d4dbcd441aacd51))
|
||||||
|
* 所有授权增加测试按钮 ([7a3e68d](https://github.com/certd/certd/commit/7a3e68d656c1dcdcd814b69891bd2c2c6fe3098a))
|
||||||
|
* 新网互联支持查询域名列表 ([e7e54bc](https://github.com/certd/certd/commit/e7e54bc19e3a734913a93a94e25db3bb06d2ab0f))
|
||||||
|
* 优化京东云报错详情显示 ([1195417](https://github.com/certd/certd/commit/1195417b9714d2fcb540e43c0a20809b7ee2052b))
|
||||||
|
* 优化网络测试页面,夜间模式显示效果 ([305da86](https://github.com/certd/certd/commit/305da86f97d918374819ecd6c50685f09b94ea59))
|
||||||
|
* 增加部署证书到certd本身插件 ([3cd1aae](https://github.com/certd/certd/commit/3cd1aaeb035f8af79714030889b2b4dc259b700e))
|
||||||
|
* 支持next-terminal ([6f3fd78](https://github.com/certd/certd/commit/6f3fd785e77a33c72bdf4115dc5d498e677d1863))
|
||||||
|
* 主题默认跟随系统颜色(自动切换深色浅色模式) ([32c3ce5](https://github.com/certd/certd/commit/32c3ce5c9868569523901a9a939ca5b535ec3277))
|
||||||
|
* http校验方式支持scp上传 ([4eb940f](https://github.com/certd/certd/commit/4eb940ffe765a0330331bc6af8396315e36d4e4a))
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/certd/certd/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复部署到openwrt错误的bug ([9ac33f9](https://github.com/certd/certd/commit/9ac33f9b9ba7727fcbbd320dd866bc048cbb3d72))
|
||||||
|
* 修复新版本上传到阿里云cas后,其他依赖任务无法部署的bug ([99f5b8e](https://github.com/certd/certd/commit/99f5b8ebc1c64798ceb42042ad71cf71e967beb0))
|
||||||
|
* esxi部署失败的bug ([6ab1fca](https://github.com/certd/certd/commit/6ab1fcaf894f7ce343af4b5bf4b0d67438df6618))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 修改sql升级语句,兼容mysql5.7 ([02f89a9](https://github.com/certd/certd/commit/02f89a9c9d77850437285844670aed441e5953c3))
|
||||||
|
* 已登录状态访问登录页面自动跳转到首页 ([bd8caff](https://github.com/certd/certd/commit/bd8caff0b754cb13530cf0f1644b33e29fde5d01))
|
||||||
|
* 优化access授权支持remote-auto-complete ([2f40f79](https://github.com/certd/certd/commit/2f40f795ee6131132d3fab2601f92a567bbdc4b7))
|
||||||
|
* access 插件支持remote-select等配置 ([d286c04](https://github.com/certd/certd/commit/d286c040a5232dcca829945734affead3ee08b3c))
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/certd/certd/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 双重验证显示secret ([febd6d3](https://github.com/certd/certd/commit/febd6d32cfe6d89ccecf26bf15141df7c456e5c6))
|
||||||
|
* 优化申请证书最大超时时长 ([00f67d8](https://github.com/certd/certd/commit/00f67d86d68f4f83cfafe2fbfeb4af0d86f9d20e))
|
||||||
|
* 支持设置默认的证书申请地址的反向代理 ([0cfb94b](https://github.com/certd/certd/commit/0cfb94b0ba6a6dc3bb0d0a81a1912068a4e6b6b6))
|
||||||
|
* 子域名托管域名支持配置通配符 ([3f7ac93](https://github.com/certd/certd/commit/3f7ac939326b0c7ec013a7534b6c0e58fb3e8cb4))
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复有域名记录时,域名输入框无法关闭的bug ([54c8217](https://github.com/certd/certd/commit/54c8217808453b121abf646b004596f28932509f))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* eab从更多参数中挪到外面 ([5ea4f46](https://github.com/certd/certd/commit/5ea4f46de7ae403a7a16e9488dc1d9c7523d019a))
|
||||||
|
* 第三方登录支持Microsoft ([beb7a4c](https://github.com/certd/certd/commit/beb7a4c99277262bb9681c5594cfcd3e36c52074))
|
||||||
|
* 优化zerossl申请证书稳定性 ([4d86fb3](https://github.com/certd/certd/commit/4d86fb319b81dbf6fa6485982105725b1b066593))
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复新网找错域名的bug ([bd511f9](https://github.com/certd/certd/commit/bd511f97cb7fbdcaeff7ac899f0460a5c7b41826))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 当域名管理中没有域名时,创建流水线时不展开域名选择框 ([9166a57](https://github.com/certd/certd/commit/9166a579301a60750f0b72b6a42b0c8d730695fd))
|
||||||
|
* count tip ([e19743f](https://github.com/certd/certd/commit/e19743f70553700f1f91bff76f87370f749dd247))
|
||||||
|
* oauth支持github 和google, 修复头像显示问题 ([693a4a6](https://github.com/certd/certd/commit/693a4a663385ced3176286bf4b5f3566da83d90e))
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 阿里云esa查询证书限制接口无效,改成配置证书数量上限检查方式进行清理 ([2302567](https://github.com/certd/certd/commit/230256793f8ad87ef8a0738c37108bf7b5ab9853))
|
||||||
|
* 某些情况下登陆页面没有显示重置密码文档链接的问题 ([40801d0](https://github.com/certd/certd/commit/40801d0a0668c77adb57fae42b4b6615b198a88d))
|
||||||
|
* 修复部署到火山引擎vod,获取域名列表为空的bug ([0719f4c](https://github.com/certd/certd/commit/0719f4c99e9198544d03431107b53652e076e881))
|
||||||
|
* 修复litessl new-nonce报428的bug ([540ef96](https://github.com/certd/certd/commit/540ef967457a7871637cfdb5012ed1fa3261757b))
|
||||||
|
* 修复oidc配置取消后获取登出地址失败后无法列出oauth列表的bug ([eb5de15](https://github.com/certd/certd/commit/eb5de150332fd914c56b812c3ba2c2445f902bb7))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 将重置密码的日志挪到启动成功之后,方便查看 ([0fa9b34](https://github.com/certd/certd/commit/0fa9b344e08cf355aee7a7566f061cc5d95dc374))
|
||||||
|
* 支持绑定两个url地址 ([a2e9a41](https://github.com/certd/certd/commit/a2e9a41a7e712395c0e3ee6fe55b370aa1fc1f12))
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/certd/certd/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复1:: 形式的ipv6校验失败的bug ([8b96f21](https://github.com/certd/certd/commit/8b96f218d5284033f10c186c0ce18e4c16d8e9b2))
|
||||||
|
* 修复阿里云esa超过免费配额之后无法部署证书的bug,改成删除最旧的那张证书 ([32de8d9](https://github.com/certd/certd/commit/32de8d9ccb08d26414adbdde950d7cd405dc344a))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 当ip证书天数太小时,自动调整更新天数,避免每次运行都重新申请ip证书 ([433e98b](https://github.com/certd/certd/commit/433e98b6450fa7d0491151f159e432bf3dfe4feb))
|
||||||
|
* 首页证书数量支持点击跳转 ([52cbff0](https://github.com/certd/certd/commit/52cbff0e15329aecd3edcf81315fb7ceab9ec290))
|
||||||
|
* 修复旧版本流水线数据发送通知标题为空的bug ([9bee0e4](https://github.com/certd/certd/commit/9bee0e460bfebe8db76742b80b2d52854392f4de))
|
||||||
|
* 验证码支持 Cloudflare Turnstile ,谨慎启用,国内被墙了 ([ca43c77](https://github.com/certd/certd/commit/ca43c775250154def63c4acd96d65dc95d1c0c2b))
|
||||||
|
* 优化证书未过期时的任务日志提示 ([ac85488](https://github.com/certd/certd/commit/ac85488245197694560aad7df9425ca215ef7ff7))
|
||||||
|
* 支持部署到阿里云GA ([1a0d3ee](https://github.com/certd/certd/commit/1a0d3eeb1b0b5ce08f05af84b6161e00c1fe1815))
|
||||||
|
* 支持部署到华为elb ([60c8ace](https://github.com/certd/certd/commit/60c8ace443e848155d3ce12e95b84766a4610d3a))
|
||||||
|
* 支持部署到AcePanel ([1661cae](https://github.com/certd/certd/commit/1661caed05e3413dc3e2b14ce62b75aa03ad90e0))
|
||||||
|
|
||||||
|
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 当通知配置被删除时,使用默认通知配置进行发送 ([5398300](https://github.com/certd/certd/commit/53983002b6553a929b72e2c70a26809a9f306e89))
|
||||||
|
* 站点检查多个ip连接超时的报错显示不出来的bug ([33b284a](https://github.com/certd/certd/commit/33b284afc0ae6391658d573e32b1ce7765e51cb2))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 部署插件支持ucloud alb ([640950d](https://github.com/certd/certd/commit/640950d4c847c72cae2986e3c2cae10d52a67fdf))
|
||||||
|
* 多个dns 提供商支持导入域名 ([d3c0914](https://github.com/certd/certd/commit/d3c0914ac16db8ac77f9c60285bb20cfab7a3cb0))
|
||||||
|
* 首次使用提示新手教程按钮 ([e054c8f](https://github.com/certd/certd/commit/e054c8fc55063fd96548f1c19049070524a63411))
|
||||||
|
* 输入证书域名时,支持点击导入域名 ([40be424](https://github.com/certd/certd/commit/40be42406c6fd5de11f594fc6913178d9e7d8943))
|
||||||
|
* 所有的dnsprovider 支持导入域名列表 ([9f21b1a](https://github.com/certd/certd/commit/9f21b1a09797d7dab253e4416c538b55fb8f4488))
|
||||||
|
* 优化首页统计数据,饼图替换成证书数量统计 ([9fa1c2e](https://github.com/certd/certd/commit/9fa1c2eb3e55ef630333ae24284aa8b54e3414b6))
|
||||||
|
* 优化首页图标 ([998de0f](https://github.com/certd/certd/commit/998de0f9a031339b019aa7a09e61e994664a8047))
|
||||||
|
* 域名导入任务进度条 ([7058d5c](https://github.com/certd/certd/commit/7058d5cb935cab8c75b98493ed497a22dbe70883))
|
||||||
|
* 站点监控,检查状态挪到前面显示 ([48f1bf0](https://github.com/certd/certd/commit/48f1bf091869b87dd17feaca5efd8680ef741582))
|
||||||
|
* 证书仓库页面增加到期状态查询条件 ([58c3d70](https://github.com/certd/certd/commit/58c3d7087bb66358d896a741e12005f690b2bd5e))
|
||||||
|
* 证书流水线创建域名输入框支持获取域名数据进行选择 ([1d5b1c2](https://github.com/certd/certd/commit/1d5b1c239cf350920eb2eb9fd293af74ef412853))
|
||||||
|
* 支持导入51dns域名 ([7eb9694](https://github.com/certd/certd/commit/7eb96942214aed0dfc9c3c5a669374da67052c49))
|
||||||
|
* ucloud支持部署到alb ([78004bd](https://github.com/certd/certd/commit/78004bdfb552a3b83298fa09d518ca282a529d90))
|
||||||
|
* ucloud支持部署到ulb(alb、clb统一成一个) ([c408687](https://github.com/certd/certd/commit/c408687af7669afe733b5506720ca795555acdce))
|
||||||
|
|
||||||
## [1.38.2](https://github.com/certd/certd/compare/v1.38.1...v1.38.2) (2026-01-22)
|
## [1.38.2](https://github.com/certd/certd/compare/v1.38.1...v1.38.2) (2026-01-22)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"notice": "永久专业版上线,新用户立减50,升级到最新版点击下方“立即赞助”按钮前往获取",
|
||||||
|
"plus": {
|
||||||
|
"name": "专业版",
|
||||||
|
"price": "89.9",
|
||||||
|
"price3": "199",
|
||||||
|
"tooltip": "开源需要您的赞助支持",
|
||||||
|
"priceText":"¥89.9/年",
|
||||||
|
"discountText":"永久专业版50优惠券立即领取"
|
||||||
|
},
|
||||||
|
"comm": {
|
||||||
|
"name": "商业版",
|
||||||
|
"price": "399",
|
||||||
|
"price3": "899",
|
||||||
|
"tooltip": "3年优惠300",
|
||||||
|
"priceText":"¥399/年",
|
||||||
|
"discountText":"¥899/3年(3年优惠300)"
|
||||||
|
},
|
||||||
|
"app":{
|
||||||
|
"minVersion":"1.36.0",
|
||||||
|
"minVersionTip":"版本过低,为了您的数据安全,请尽快升级"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,62 +14,64 @@
|
|||||||
| 10.| **baota授权** | |
|
| 10.| **baota授权** | |
|
||||||
| 11.| **天翼云授权** | |
|
| 11.| **天翼云授权** | |
|
||||||
| 12.| **51dns授权** | |
|
| 12.| **51dns授权** | |
|
||||||
| 13.| **SFTP授权** | |
|
| 13.| **AcePanel授权** | |
|
||||||
| 14.| **阿里云OSS授权** | 包含地域和Bucket |
|
| 14.| **SFTP授权** | |
|
||||||
| 15.| **APISIX授权** | |
|
| 15.| **阿里云OSS授权** | 包含地域和Bucket |
|
||||||
| 16.| **亚马逊云aws授权** | |
|
| 16.| **APISIX授权** | |
|
||||||
| 17.| **亚马逊云科技(国区)授权** | |
|
| 17.| **亚马逊云aws授权** | |
|
||||||
| 18.| **CacheFly** | CacheFly |
|
| 18.| **亚马逊云科技(国区)授权** | |
|
||||||
| 19.| **EAB授权** | ZeroSSL证书申请需要EAB授权 |
|
| 19.| **CacheFly** | CacheFly |
|
||||||
| 20.| **google cloud** | 谷歌云授权 |
|
| 20.| **EAB授权** | ZeroSSL证书申请需要EAB授权 |
|
||||||
| 21.| **cloudflare授权** | |
|
| 21.| **google cloud** | 谷歌云授权 |
|
||||||
| 22.| **中国移动CND授权** | |
|
| 22.| **cloudflare授权** | |
|
||||||
| 23.| **授权插件示例** | 这是一个示例授权插件,用于演示如何实现一个授权插件 |
|
| 23.| **中国移动CND授权** | |
|
||||||
| 24.| **dns.la授权** | |
|
| 24.| **授权插件示例** | 这是一个示例授权插件,用于演示如何实现一个授权插件 |
|
||||||
| 25.| **多吉云** | |
|
| 25.| **dns.la授权** | |
|
||||||
| 26.| **Dokploy授权** | |
|
| 26.| **多吉云** | |
|
||||||
| 27.| **farcdn授权** | |
|
| 27.| **Dokploy授权** | |
|
||||||
| 28.| **FlexCDN授权** | |
|
| 28.| **farcdn授权** | |
|
||||||
| 29.| **Gcore** | Gcore |
|
| 29.| **FlexCDN授权** | |
|
||||||
| 30.| **Github授权** | |
|
| 30.| **Gcore** | Gcore |
|
||||||
| 31.| **godaddy授权** | |
|
| 31.| **Github授权** | |
|
||||||
| 32.| **金山云授权** | |
|
| 32.| **godaddy授权** | |
|
||||||
| 33.| **FTP授权** | |
|
| 33.| **金山云授权** | |
|
||||||
| 34.| **七牛OSS授权** | |
|
| 34.| **FTP授权** | |
|
||||||
| 35.| **腾讯云COS授权** | 腾讯云对象存储授权,包含地域和存储桶 |
|
| 35.| **七牛OSS授权** | |
|
||||||
| 36.| **s3/minio授权** | S3/minio oss授权 |
|
| 36.| **腾讯云COS授权** | 腾讯云对象存储授权,包含地域和存储桶 |
|
||||||
| 37.| **namesilo授权** | |
|
| 37.| **s3/minio授权** | S3/minio oss授权 |
|
||||||
| 38.| **1panel授权** | 账号和密码 |
|
| 38.| **namesilo授权** | |
|
||||||
| 39.| **支付宝** | |
|
| 39.| **Next Terminal 授权** | 用于访问 Next Terminal API 的授权配置 |
|
||||||
| 40.| **白山云授权** | |
|
| 40.| **1panel授权** | 账号和密码 |
|
||||||
| 41.| **宝塔云WAF授权** | 用于连接和管理宝塔云WAF服务的授权配置 |
|
| 41.| **支付宝** | |
|
||||||
| 42.| **cdnfly授权** | |
|
| 42.| **白山云授权** | |
|
||||||
| 43.| **k8s授权** | |
|
| 43.| **宝塔云WAF授权** | 用于连接和管理宝塔云WAF服务的授权配置 |
|
||||||
| 44.| **括彩云cdn授权** | 括彩云CDN,每月免费30G,[注册即领](https://kuocaicdn.com/register?code=8mn536rrzfbf8) |
|
| 44.| **cdnfly授权** | |
|
||||||
| 45.| **LeCDN授权** | |
|
| 45.| **k8s授权** | |
|
||||||
| 46.| **lucky** | |
|
| 46.| **括彩云cdn授权** | 括彩云CDN,每月免费30G,[注册即领](https://kuocaicdn.com/register?code=8mn536rrzfbf8) |
|
||||||
| 47.| **猫云授权** | |
|
| 47.| **LeCDN授权** | |
|
||||||
| 48.| **plesk授权** | |
|
| 48.| **lucky** | |
|
||||||
| 49.| **长亭雷池授权** | |
|
| 49.| **猫云授权** | |
|
||||||
| 50.| **群晖登录授权** | |
|
| 50.| **plesk授权** | |
|
||||||
| 51.| **uniCloud** | unicloud授权 |
|
| 51.| **长亭雷池授权** | |
|
||||||
| 52.| **微信支付** | |
|
| 52.| **群晖登录授权** | |
|
||||||
| 53.| **易盾rcdn授权** | 易盾CDN,每月免费30G,[注册即领](https://rhcdn.yiduncdn.com/register?code=8mn536rrzfbf8) |
|
| 53.| **uniCloud** | unicloud授权 |
|
||||||
| 54.| **易发云短信** | sms.yfyidc.cn/ |
|
| 54.| **微信支付** | |
|
||||||
| 55.| **易盾DCDN授权** | https://user.yiduncdn.com |
|
| 55.| **易盾rcdn授权** | 易盾CDN,每月免费30G,[注册即领](https://rhcdn.yiduncdn.com/register?code=8mn536rrzfbf8) |
|
||||||
| 56.| **易支付** | |
|
| 56.| **易发云短信** | sms.yfyidc.cn/ |
|
||||||
| 57.| **proxmox** | |
|
| 57.| **易盾DCDN授权** | https://user.yiduncdn.com |
|
||||||
| 58.| **UCloud授权** | 优刻得授权 |
|
| 58.| **易支付** | |
|
||||||
| 59.| **又拍云** | |
|
| 59.| **proxmox** | |
|
||||||
| 60.| **网宿授权** | |
|
| 60.| **UCloud授权** | 优刻得授权 |
|
||||||
| 61.| **西部数码授权** | |
|
| 61.| **又拍云** | |
|
||||||
| 62.| **我爱云授权** | 我爱云CDN |
|
| 62.| **网宿授权** | |
|
||||||
| 63.| **新网授权(代理方式)** | |
|
| 63.| **西部数码授权** | |
|
||||||
| 64.| **新网授权** | |
|
| 64.| **我爱云授权** | 我爱云CDN |
|
||||||
| 65.| **新网互联授权** | 仅支持代理账号,ip需要加入白名单 |
|
| 65.| **新网授权(代理方式)** | |
|
||||||
| 66.| **Zenlayer授权** | Zenlayer授权 |
|
| 66.| **新网授权** | |
|
||||||
| 67.| **GoEdge授权** | |
|
| 67.| **新网互联授权** | 仅支持代理账号,ip需要加入白名单 |
|
||||||
| 68.| **雨云授权** | https://app.rainyun.com/ |
|
| 68.| **Zenlayer授权** | Zenlayer授权 |
|
||||||
|
| 69.| **GoEdge授权** | |
|
||||||
|
| 70.| **雨云授权** | https://app.rainyun.com/ |
|
||||||
|
|
||||||
<style module>
|
<style module>
|
||||||
table th:first-of-type {
|
table th:first-of-type {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
# 任务插件
|
# 任务插件
|
||||||
共 `118` 款任务插件
|
共 `125` 款任务插件
|
||||||
## 1. 证书申请
|
## 1. 证书申请
|
||||||
|
|
||||||
| 序号 | 名称 | 说明 |
|
| 序号 | 名称 | 说明 |
|
||||||
|-----|-----|-----|
|
|-----|-----|-----|
|
||||||
| 1.| **证书申请(JS版)** | 免费通配符域名证书申请,支持多个域名打到同一个证书上 |
|
| 1.| **证书申请(JS版)** | 免费通配符域名证书申请,支持多个域名打到同一个证书上 |
|
||||||
| 2.| **商用证书托管** | 手动上传自定义证书后,自动部署(每次证书有更新,都需要手动上传一次) |
|
| 2.| **已有证书托管** | 手动上传自定义证书后,自动部署(每次证书有更新,都需要手动上传一次) |
|
||||||
| 3.| **获取阿里云订阅证书** | 从阿里云拉取订阅模式的商用证书 |
|
| 3.| **获取阿里云订阅证书** | 从阿里云拉取订阅模式的商用证书 |
|
||||||
| 4.| **证书申请(Lego)** | 支持海量DNS解析提供商,推荐使用,一样的免费通配符域名证书申请,支持多个域名打到同一个证书上 |
|
| 4.| **证书申请(Lego)** | 支持海量DNS解析提供商,推荐使用,一样的免费通配符域名证书申请,支持多个域名打到同一个证书上 |
|
||||||
## 2. 主机
|
## 2. 主机
|
||||||
@@ -53,26 +53,30 @@
|
|||||||
|
|
||||||
| 序号 | 名称 | 说明 |
|
| 序号 | 名称 | 说明 |
|
||||||
|-----|-----|-----|
|
|-----|-----|-----|
|
||||||
| 1.| **Dokploy-部署server证书** | 自动更新Dokploy server证书 |
|
| 1.| **AcePanel-部署到网站** | 上传证书并部署到指定网站 |
|
||||||
| 2.| **飞牛NAS-部署证书** | |
|
| 2.| **AcePanel-面板证书** | 部署AcePanel面板证书 |
|
||||||
| 3.| **1Panel-部署面板证书** | 更新1Panel的面板证书 |
|
| 3.| **Dokploy-部署server证书** | 自动更新Dokploy server证书 |
|
||||||
| 4.| **1Panel-更新证书** | 更新1Panel的证书,包括面板证书和站点证书 |
|
| 4.| **飞牛NAS-部署证书** | |
|
||||||
| 5.| **宝塔-删除过期证书** | 删除证书夹中过期证书 |
|
| 5.| **NextTerminal-更新证书** | 更新 Next Terminal 证书 |
|
||||||
| 6.| **宝塔-WAF证书部署** | 部署宝塔云WAF/aaWAF |
|
| 6.| **1Panel-部署面板证书** | 更新1Panel的面板证书 |
|
||||||
| 7.| **宝塔-面板证书部署** | 部署宝塔面板本身的ssl证书 |
|
| 7.| **1Panel-更新站点证书** | 更新1Panel的站点证书 |
|
||||||
| 8.| **宝塔win-网站证书部署** | 部署到Windows版宝塔管理的站点的ssl证书 |
|
| 8.| **宝塔-删除过期证书** | 删除证书夹中过期证书 |
|
||||||
| 9.| **宝塔-网站证书部署** | 部署宝塔管理的站点的ssl证书,目前支持宝塔网站站点、docker站点等。本插件也支持aaPanel。 |
|
| 9.| **宝塔-WAF证书部署** | 部署宝塔云WAF/aaWAF |
|
||||||
| 10.| **K8S-Apply自定义yaml** | apply自定义yaml到k8s |
|
| 10.| **宝塔-面板证书部署** | 部署宝塔面板本身的ssl证书 |
|
||||||
| 11.| **K8S-Ingress 证书部署** | 部署证书到k8s的Ingress |
|
| 11.| **宝塔win-网站证书部署** | 部署到Windows版宝塔管理的站点的ssl证书 |
|
||||||
| 12.| **K8S-部署证书到Secret** | 部署证书到k8s的secret |
|
| 12.| **宝塔-网站证书部署** | 部署宝塔管理的站点的ssl证书,目前支持宝塔网站站点、docker站点等。本插件也支持aaPanel。 |
|
||||||
| 13.| **lucky-更新Lucky证书** | |
|
| 13.| **K8S-Apply自定义yaml** | apply自定义yaml到k8s |
|
||||||
| 14.| **Plesk-部署Plesk网站证书** | |
|
| 14.| **K8S-Ingress 证书部署** | 部署证书到k8s的Ingress |
|
||||||
| 15.| **Plesk-更新证书** | 不会创建新证书记录,直接更新旧的证书 |
|
| 15.| **K8S-部署证书到Secret** | 部署证书到k8s的secret |
|
||||||
| 16.| **雷池-更新证书** | 更新长亭雷池WAF的证书 |
|
| 16.| **lucky-更新Lucky证书** | |
|
||||||
| 17.| **群晖-部署证书到群晖面板** | Synology,支持6.x以上版本 |
|
| 17.| **Plesk-部署Plesk网站证书** | |
|
||||||
| 18.| **uniCloud-部署到服务空间** | 部署到服务空间 |
|
| 18.| **Plesk-更新证书** | 不会创建新证书记录,直接更新旧的证书 |
|
||||||
| 19.| **Proxmox-上传证书到Proxmox** | |
|
| 19.| **雷池-更新证书(支持控制台和防护应用)** | 更新长亭雷池WAF的证书,支持更新控制台和防护应用的证书。 |
|
||||||
| 20.| **威联通-部署证书到威联通** | 部署证书到qnap |
|
| 20.| **群晖-部署证书到群晖面板** | Synology,支持6.x以上版本 |
|
||||||
|
| 21.| **群晖-刷新OTP登录有效期** | 群晖登录状态可能30天失效,需要在失效之前登录一次,刷新有效期,您可以将其放在“部署到群晖面板”任务之后 |
|
||||||
|
| 22.| **uniCloud-部署到服务空间** | 部署到服务空间 |
|
||||||
|
| 23.| **Proxmox-上传证书到Proxmox** | |
|
||||||
|
| 24.| **威联通-部署证书到威联通** | 部署证书到qnap |
|
||||||
## 5. 阿里云
|
## 5. 阿里云
|
||||||
|
|
||||||
| 序号 | 名称 | 说明 |
|
| 序号 | 名称 | 说明 |
|
||||||
@@ -86,19 +90,21 @@
|
|||||||
| 7.| **阿里云-部署证书至DCDN** | 依赖证书申请前置任务,自动部署域名证书至阿里云DCDN |
|
| 7.| **阿里云-部署证书至DCDN** | 依赖证书申请前置任务,自动部署域名证书至阿里云DCDN |
|
||||||
| 8.| **阿里云-部署至ESA** | 部署证书到阿里云ESA(边缘安全加速),自动删除过期证书 |
|
| 8.| **阿里云-部署至ESA** | 部署证书到阿里云ESA(边缘安全加速),自动删除过期证书 |
|
||||||
| 9.| **阿里云-部署至阿里云FC(3.0)** | 部署证书到阿里云函数计算(FC3.0) |
|
| 9.| **阿里云-部署至阿里云FC(3.0)** | 部署证书到阿里云函数计算(FC3.0) |
|
||||||
| 10.| **阿里云-部署至NLB(网络负载均衡)** | NLB,网络负载均衡,更新监听器的默认证书 |
|
| 10.| **阿里云-部署至GA** | 部署证书到阿里云GA(全球加速),支持更新默认证书和扩展证书 |
|
||||||
| 11.| **阿里云-部署证书至OSS** | 部署域名证书至阿里云OSS自定义域名,不是上传到阿里云oss |
|
| 11.| **阿里云-部署至NLB(网络负载均衡)** | NLB,网络负载均衡,更新监听器的默认证书 |
|
||||||
| 12.| **阿里云-部署至CLB(传统负载均衡)** | 部署证书到阿里云CLB(传统负载均衡) |
|
| 12.| **阿里云-部署证书至OSS** | 部署域名证书至阿里云OSS自定义域名,不是上传到阿里云oss |
|
||||||
| 13.| **阿里云-部署至VOD** | 部署证书到阿里云视频点播(vod) |
|
| 13.| **阿里云-部署至CLB(传统负载均衡)** | 部署证书到阿里云CLB(传统负载均衡) |
|
||||||
| 14.| **阿里云-部署至阿里云WAF** | 部署证书到阿里云WAF |
|
| 14.| **阿里云-部署至VOD** | 部署证书到阿里云视频点播(vod) |
|
||||||
| 15.| **阿里云-上传证书到CAS** | 上传证书到阿里云证书管理服务(CAS),如果不想在阿里云上同一份证书上传多次,可以把此任务作为前置任务,其他阿里云任务证书那一项选择此任务的输出 |
|
| 15.| **阿里云-部署至阿里云WAF** | 部署证书到阿里云WAF |
|
||||||
|
| 16.| **阿里云-上传证书到CAS** | 上传证书到阿里云证书管理服务(CAS),如果不想在阿里云上同一份证书上传多次,可以把此任务作为前置任务,其他阿里云任务证书那一项选择此任务的输出 |
|
||||||
## 6. 华为云
|
## 6. 华为云
|
||||||
|
|
||||||
| 序号 | 名称 | 说明 |
|
| 序号 | 名称 | 说明 |
|
||||||
|-----|-----|-----|
|
|-----|-----|-----|
|
||||||
| 1.| **华为云-部署证书至CDN** | |
|
| 1.| **华为云-部署证书至CDN** | |
|
||||||
| 2.| **华为云-部署证书至OBS** | |
|
| 2.| **华为云-部署证书至ELB负载均衡** | |
|
||||||
| 3.| **华为云-上传证书至CCM** | 上传证书到华为云云证书管理(CCM) |
|
| 3.| **华为云-部署证书至OBS** | |
|
||||||
|
| 4.| **华为云-上传证书至CCM** | 上传证书到华为云云证书管理(CCM) |
|
||||||
## 7. 腾讯云
|
## 7. 腾讯云
|
||||||
|
|
||||||
| 序号 | 名称 | 说明 |
|
| 序号 | 名称 | 说明 |
|
||||||
@@ -178,7 +184,8 @@
|
|||||||
|-----|-----|-----|
|
|-----|-----|-----|
|
||||||
| 1.| **数据库备份** | 【仅管理员可用】仅支持备份SQLite数据库 |
|
| 1.| **数据库备份** | 【仅管理员可用】仅支持备份SQLite数据库 |
|
||||||
| 2.| **重启 Certd** | 【仅管理员可用】 重启 certd的https服务,用于更新 Certd 的 ssl 证书 |
|
| 2.| **重启 Certd** | 【仅管理员可用】 重启 certd的https服务,用于更新 Certd 的 ssl 证书 |
|
||||||
| 3.| **自定义js脚本** | 【仅管理员】运行自定义js脚本执行 |
|
| 3.| **部署证书到Certd本身** | 【仅管理员可用】 部署证书到 certd的https服务,用于更新 Certd 的 ssl 证书,建议将此任务放在流水线的最后一步 |
|
||||||
|
| 4.| **自定义js脚本** | 【仅管理员】运行自定义js脚本执行 |
|
||||||
|
|
||||||
<style module>
|
<style module>
|
||||||
table th:first-of-type {
|
table th:first-of-type {
|
||||||
|
|||||||
@@ -52,3 +52,11 @@ service:
|
|||||||
3. DNS 有其他平台申请过的_acme-challenge记录,删除即可
|
3. DNS 有其他平台申请过的_acme-challenge记录,删除即可
|
||||||
|
|
||||||
|
|
||||||
|
## 7. DNS problem: NXDOMAIN looking up TXT for _acme-challenge.xxx
|
||||||
|
`
|
||||||
|
DNS problem: NXDOMAIN looking up TXT for _acme-challenge.xxxxx - check that a DNS record exists for this domain
|
||||||
|
`
|
||||||
|
证书颁发机构向域名ns查询TXT验证记录失败,有以下几种可能
|
||||||
|
1、域名的ns服务器修改成别的了,但申请证书时的DNS提供商选择错误(检查确认,配置正确的DNS提供商)
|
||||||
|
2、证书颁发机构与ns域名服务器之间访问不通,无法查询到TXT记录(尝试更换证书颁发机构)
|
||||||
|
3、ns服务商解析值生效慢(尝试修改证书申请任务里面的等待生效时长600-1000s)
|
||||||
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 28 KiB |
@@ -16,21 +16,11 @@ CERTD_HTTPS_port=7002
|
|||||||
|
|
||||||
参考Certd顶部的创建证书流水线教程
|
参考Certd顶部的创建证书流水线教程
|
||||||
|
|
||||||
### 2、配置复制到本机任务
|
### 2、配置部署证书到certd任务
|
||||||
将证书复制到certd的证书安装位置
|
|
||||||
证书路径:`ssl/cert.crt`
|
|
||||||
私钥路径:`ssl/cert.key`
|
|
||||||
|
|
||||||

|

|
||||||

|
|
||||||
|
|
||||||
### 3、配置重启Certd任务
|
### 3、配置定时任务
|
||||||
重启certd的https server,让证书生效
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 4、配置定时任务
|
|
||||||
每天定时执行,最终效果如下
|
每天定时执行,最终效果如下
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -9,5 +9,5 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npmClient": "pnpm",
|
"npmClient": "pnpm",
|
||||||
"version": "1.38.3"
|
"version": "1.38.11"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,45 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/publishlab/node-acme-client/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/publishlab/node-acme-client/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/publishlab/node-acme-client/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/publishlab/node-acme-client/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化申请证书最大超时时长 ([00f67d8](https://github.com/publishlab/node-acme-client/commit/00f67d86d68f4f83cfafe2fbfeb4af0d86f9d20e))
|
||||||
|
* 支持设置默认的证书申请地址的反向代理 ([0cfb94b](https://github.com/publishlab/node-acme-client/commit/0cfb94b0ba6a6dc3bb0d0a81a1912068a4e6b6b6))
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/publishlab/node-acme-client/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化zerossl申请证书稳定性 ([4d86fb3](https://github.com/publishlab/node-acme-client/commit/4d86fb319b81dbf6fa6485982105725b1b066593))
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/publishlab/node-acme-client/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/publishlab/node-acme-client/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复litessl new-nonce报428的bug ([540ef96](https://github.com/publishlab/node-acme-client/commit/540ef967457a7871637cfdb5012ed1fa3261757b))
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/publishlab/node-acme-client/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
## [1.38.3](https://github.com/publishlab/node-acme-client/compare/v1.38.2...v1.38.3) (2026-01-28)
|
## [1.38.3](https://github.com/publishlab/node-acme-client/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/acme-client
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"description": "Simple and unopinionated ACME client",
|
"description": "Simple and unopinionated ACME client",
|
||||||
"private": false,
|
"private": false,
|
||||||
"author": "nmorsman",
|
"author": "nmorsman",
|
||||||
"version": "1.38.3",
|
"version": "1.38.11",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"module": "scr/index.js",
|
"module": "scr/index.js",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
"types"
|
"types"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/basic": "^1.38.3",
|
"@certd/basic": "^1.38.11",
|
||||||
"@peculiar/x509": "^1.11.0",
|
"@peculiar/x509": "^1.11.0",
|
||||||
"asn1js": "^3.0.5",
|
"asn1js": "^3.0.5",
|
||||||
"axios": "^1.9.0",
|
"axios": "^1.9.0",
|
||||||
@@ -70,5 +70,5 @@
|
|||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/publishlab/node-acme-client/issues"
|
"url": "https://github.com/publishlab/node-acme-client/issues"
|
||||||
},
|
},
|
||||||
"gitHead": "f92dc6a1ad103de9cc184da3b84096943906cb59"
|
"gitHead": "1f002159e2a3c73fb5e00341a344effa07d6f653"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,9 @@ class AcmeClient {
|
|||||||
max: this.opts.backoffMax,
|
max: this.opts.backoffMax,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.http = new HttpClient(this.opts.directoryUrl, this.opts.accountKey, this.opts.externalAccountBinding, this.opts.urlMapping, opts.logger);
|
const cacheNonce = true
|
||||||
|
// const cacheNonce = this.sslProvider === 'litessl';
|
||||||
|
this.http = new HttpClient(this.opts.directoryUrl, this.opts.accountKey, this.opts.externalAccountBinding, this.opts.urlMapping, opts.logger, cacheNonce);
|
||||||
this.api = new AcmeApi(this.http, this.opts.accountUrl);
|
this.api = new AcmeApi(this.http, this.opts.accountUrl);
|
||||||
this.logger = opts.logger;
|
this.logger = opts.logger;
|
||||||
}
|
}
|
||||||
@@ -598,8 +600,11 @@ class AcmeClient {
|
|||||||
throw new Error(`[${d}] Unexpected item status: ${resp.data.status}`);
|
throw new Error(`[${d}] Unexpected item status: ${resp.data.status}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.log(`[${d}] Waiting for valid status (等待valid状态): ${item.url}`, this.backoffOpts);
|
this.log(`[${d}] Waiting for valid status (等待valid状态): ${item.url}`, JSON.stringify(this.backoffOpts));
|
||||||
return util.retry(verifyFn, this.backoffOpts);
|
const log = (...args)=>{
|
||||||
|
this.logger.info(...args)
|
||||||
|
}
|
||||||
|
return util.retry(verifyFn, this.backoffOpts,log);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { getJwk } from './crypto/index.js';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class HttpClient {
|
class HttpClient {
|
||||||
constructor(directoryUrl, accountKey, externalAccountBinding = {}, urlMapping = {},logger) {
|
constructor(directoryUrl, accountKey, externalAccountBinding = {}, urlMapping = {}, logger, cacheNonce= false) {
|
||||||
this.directoryUrl = directoryUrl;
|
this.directoryUrl = directoryUrl;
|
||||||
this.accountKey = accountKey;
|
this.accountKey = accountKey;
|
||||||
this.externalAccountBinding = externalAccountBinding;
|
this.externalAccountBinding = externalAccountBinding;
|
||||||
@@ -31,7 +31,34 @@ class HttpClient {
|
|||||||
this.directoryMaxAge = 86400;
|
this.directoryMaxAge = 86400;
|
||||||
this.directoryTimestamp = 0;
|
this.directoryTimestamp = 0;
|
||||||
this.urlMapping = urlMapping;
|
this.urlMapping = urlMapping;
|
||||||
this.log = logger? logger.info.bind(logger) : log;
|
this.log = logger ? logger.info.bind(logger) : log;
|
||||||
|
this.nonces = [];
|
||||||
|
this.cacheNonce = cacheNonce;
|
||||||
|
}
|
||||||
|
|
||||||
|
pushNonce(nonce) {
|
||||||
|
if (!this.cacheNonce || !nonce) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.nonces.push({
|
||||||
|
nonce,
|
||||||
|
expires: Date.now() + 30*1000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
popNonce() {
|
||||||
|
while (true) {
|
||||||
|
if (this.nonces.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const item = this.nonces.shift();
|
||||||
|
if (!item) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (item.expires < Date.now()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return item.nonce;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,8 +74,9 @@ class HttpClient {
|
|||||||
if (this.urlMapping && this.urlMapping.enabled && this.urlMapping.mappings) {
|
if (this.urlMapping && this.urlMapping.enabled && this.urlMapping.mappings) {
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
for (const key in this.urlMapping.mappings) {
|
for (const key in this.urlMapping.mappings) {
|
||||||
|
const value = this.urlMapping.mappings[key];
|
||||||
if (url.includes(key)) {
|
if (url.includes(key)) {
|
||||||
const newUrl = url.replace(key, this.urlMapping.mappings[key]);
|
const newUrl = url.replace(key, value);
|
||||||
this.log(`use reverse proxy: ${newUrl}`);
|
this.log(`use reverse proxy: ${newUrl}`);
|
||||||
url = newUrl;
|
url = newUrl;
|
||||||
}
|
}
|
||||||
@@ -70,6 +98,13 @@ class HttpClient {
|
|||||||
const resp = await axios.request(opts);
|
const resp = await axios.request(opts);
|
||||||
|
|
||||||
this.log(`RESP ${resp.status} ${method} ${url}`);
|
this.log(`RESP ${resp.status} ${method} ${url}`);
|
||||||
|
|
||||||
|
const nonce = resp.headers['replay-nonce'];
|
||||||
|
if (nonce) {
|
||||||
|
//如果有nonce
|
||||||
|
this.pushNonce(nonce);
|
||||||
|
}
|
||||||
|
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,6 +162,13 @@ class HttpClient {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
async getNonce() {
|
async getNonce() {
|
||||||
|
|
||||||
|
//尝试从队列中pop一个nonce
|
||||||
|
const nonce = this.popNonce();
|
||||||
|
if (nonce) {
|
||||||
|
return nonce;
|
||||||
|
}
|
||||||
|
|
||||||
const url = await this.getResourceUrl('newNonce');
|
const url = await this.getResourceUrl('newNonce');
|
||||||
const resp = await this.request(url, 'head');
|
const resp = await this.request(url, 'head');
|
||||||
|
|
||||||
@@ -134,7 +176,11 @@ class HttpClient {
|
|||||||
throw new Error('Failed to get nonce from ACME provider');
|
throw new Error('Failed to get nonce from ACME provider');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.cacheNonce) {
|
||||||
|
return this.popNonce();
|
||||||
|
}
|
||||||
return resp.headers['replay-nonce'];
|
return resp.headers['replay-nonce'];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,7 +194,7 @@ class HttpClient {
|
|||||||
const dir = await this.getDirectory();
|
const dir = await this.getDirectory();
|
||||||
|
|
||||||
if (!dir[resource]) {
|
if (!dir[resource]) {
|
||||||
throw new Error(`Unable to locate API resource URL in ACME directory: "${resource}"`);
|
throw new Error(`Unable to locate API resource URL in ACME directory: "${resource}",获取ACME接口地址信息失败,可能网络不稳定或该证书颁发机构服务器崩溃,目录地址:${this.directoryUrl},请测试地址是否可以正常访问并显示json格式的URL地址列表`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dir[resource];
|
return dir[resource];
|
||||||
|
|||||||
@@ -57,6 +57,32 @@ export function getDirectoryUrl(opts) {
|
|||||||
return list.production
|
return list.production
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function getAllSslProviderDomains() {
|
||||||
|
const list = Object.values(directory).map((item) => {
|
||||||
|
let url = item.production.replace('https://', '')
|
||||||
|
url = url.substring(0, url.indexOf('/'))
|
||||||
|
return url
|
||||||
|
})
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
let sslProviderReverseProxies = {}
|
||||||
|
|
||||||
|
function initSslProviderReverseProxies() {
|
||||||
|
for (const sslProvider of getAllSslProviderDomains()) {
|
||||||
|
sslProviderReverseProxies[sslProvider] = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initSslProviderReverseProxies()
|
||||||
|
|
||||||
|
export function getSslProviderReverseProxies() {
|
||||||
|
return sslProviderReverseProxies
|
||||||
|
}
|
||||||
|
export function setSslProviderReverseProxies(reverseProxies) {
|
||||||
|
Object.assign(sslProviderReverseProxies, reverseProxies)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crypto
|
* Crypto
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -52,11 +52,17 @@ async function retryPromise(fn, attempts, backoff, logger = log) {
|
|||||||
let aborted = false;
|
let aborted = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await fn(() => { aborted = true; });
|
const setAbort = () => { aborted = true; }
|
||||||
|
const data = await fn(setAbort);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (aborted || ((backoff.attempts + 1) >= attempts)) {
|
if (aborted){
|
||||||
|
logger(`用户取消重试`);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
if ( ((backoff.attempts + 1) >= attempts)) {
|
||||||
|
logger(`重试次数超过${attempts}次`);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,9 @@ export const directory: {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function getDirectoryUrl(opts:{sslProvider:string, pkType: string}): string;
|
export function getDirectoryUrl(opts:{sslProvider:string, pkType: string}): string;
|
||||||
|
export function getAllSslProviderDomains(): string[];
|
||||||
|
export function getSslProviderReverseProxies(): Record<string, string>;
|
||||||
|
export function setSslProviderReverseProxies(reverseProxies: Record<string, string>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crypto
|
* Crypto
|
||||||
|
|||||||
@@ -3,6 +3,49 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/certd/certd/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/certd/certd/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 421 支持3次重试 ([b91548e](https://github.com/certd/certd/commit/b91548eef4c24faa822d3a40f1f6a77b41d274e4))
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/certd/certd/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* esxi部署失败的bug ([6ab1fca](https://github.com/certd/certd/commit/6ab1fcaf894f7ce343af4b5bf4b0d67438df6618))
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/certd/certd/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/basic
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/certd/certd/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复1:: 形式的ipv6校验失败的bug ([8b96f21](https://github.com/certd/certd/commit/8b96f218d5284033f10c186c0ce18e4c16d8e9b2))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持部署到阿里云GA ([1a0d3ee](https://github.com/certd/certd/commit/1a0d3eeb1b0b5ce08f05af84b6161e00c1fe1815))
|
||||||
|
* 支持部署到华为elb ([60c8ace](https://github.com/certd/certd/commit/60c8ace443e848155d3ce12e95b84766a4610d3a))
|
||||||
|
|
||||||
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
00:57
|
23:40
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/basic",
|
"name": "@certd/basic",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.38.3",
|
"version": "1.38.11",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -47,5 +47,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "f92dc6a1ad103de9cc184da3b84096943906cb59"
|
"gitHead": "1f002159e2a3c73fb5e00341a344effa07d6f653"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,8 +58,13 @@ function isIpv6(d: string) {
|
|||||||
if (!d) {
|
if (!d) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const isIPv6Regex = /^([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{1,4}$|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4})$/gm;
|
try {
|
||||||
return isIPv6Regex.test(d);
|
// 尝试构造URL,用IPv6作为hostname
|
||||||
|
new URL(`http://[${d}]`);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isIp(d: string) {
|
function isIp(d: string) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export function resetLogConfigure() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
resetLogConfigure();
|
resetLogConfigure();
|
||||||
export const logger = log4js.getLogger("default");
|
export const logger: ILogger = log4js.getLogger("default") as any;
|
||||||
|
|
||||||
export function resetLogFilePath(filePath: string) {
|
export function resetLogFilePath(filePath: string) {
|
||||||
logFilePath = filePath;
|
logFilePath = filePath;
|
||||||
@@ -77,6 +77,8 @@ export type ILogger = {
|
|||||||
fatal(message: any, ...args: any[]): void;
|
fatal(message: any, ...args: any[]): void;
|
||||||
|
|
||||||
mark(message: any, ...args: any[]): void;
|
mark(message: any, ...args: any[]): void;
|
||||||
|
|
||||||
|
addSecret(secret: string): void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const locale = Intl.DateTimeFormat().resolvedOptions().locale;
|
const locale = Intl.DateTimeFormat().resolvedOptions().locale;
|
||||||
@@ -106,10 +108,14 @@ export class PipelineLogger implements ILogger {
|
|||||||
|
|
||||||
constructor(name: string, write: (text: string) => void) {
|
constructor(name: string, write: (text: string) => void) {
|
||||||
this.customWriter = write;
|
this.customWriter = write;
|
||||||
|
//@ts-ignore
|
||||||
this.logger = log4js.getLogger(name);
|
this.logger = log4js.getLogger(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
addSecret(secret: string) {
|
addSecret(secret: string) {
|
||||||
|
if (!secret) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this._secrets.push(secret);
|
this._secrets.push(secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import * as _ from 'lodash-es';
|
import * as _ from "lodash-es";
|
||||||
function isUnMergeable(srcValue: any) {
|
function isUnMergeable(srcValue: any) {
|
||||||
return srcValue != null && srcValue instanceof UnMergeable;
|
return srcValue != null && srcValue instanceof UnMergeable;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import * as https from "node:https";
|
|||||||
import { merge } from "lodash-es";
|
import { merge } from "lodash-es";
|
||||||
import { safePromise } from "./util.promise.js";
|
import { safePromise } from "./util.promise.js";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
import sleep from "./util.sleep.js";
|
||||||
const errorMap: Record<string, string> = {
|
const errorMap: Record<string, string> = {
|
||||||
"ssl3_get_record:wrong version number": "http协议错误,服务端要求http协议,请检查是否使用了https请求",
|
"ssl3_get_record:wrong version number": "http协议错误,服务端要求http协议,请检查是否使用了https请求",
|
||||||
"getaddrinfo EAI_AGAIN": "无法解析域名,请检查网络连接或dns配置,更换docker-compose.yaml中dns配置",
|
"getaddrinfo EAI_AGAIN": "无法解析域名,请检查网络连接或dns配置,更换docker-compose.yaml中dns配置",
|
||||||
@@ -148,6 +148,16 @@ export function createAxiosService({ logger }: { logger: ILogger }) {
|
|||||||
// });
|
// });
|
||||||
// config.httpsAgent = agent;
|
// config.httpsAgent = agent;
|
||||||
config.proxy = false; //必须 否则还会走一层代理,
|
config.proxy = false; //必须 否则还会走一层代理,
|
||||||
|
|
||||||
|
config.retry = merge(
|
||||||
|
{
|
||||||
|
status: [421],
|
||||||
|
count: 0,
|
||||||
|
max: 3,
|
||||||
|
delay: 1000,
|
||||||
|
},
|
||||||
|
config.retry
|
||||||
|
);
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
(error: Error) => {
|
(error: Error) => {
|
||||||
@@ -175,51 +185,58 @@ export function createAxiosService({ logger }: { logger: ILogger }) {
|
|||||||
}
|
}
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
(error: any) => {
|
async (error: any) => {
|
||||||
const status = error.response?.status;
|
const status = error.response?.status;
|
||||||
|
let message = "";
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 400:
|
case 400:
|
||||||
error.message = "请求错误";
|
message = "请求错误";
|
||||||
break;
|
break;
|
||||||
case 401:
|
case 401:
|
||||||
error.message = "认证/登录失败";
|
message = "认证/登录失败";
|
||||||
break;
|
break;
|
||||||
case 403:
|
case 403:
|
||||||
error.message = "拒绝访问";
|
message = "拒绝访问";
|
||||||
break;
|
break;
|
||||||
case 404:
|
case 404:
|
||||||
error.message = `请求地址出错`;
|
message = `请求地址出错`;
|
||||||
break;
|
break;
|
||||||
case 408:
|
case 408:
|
||||||
error.message = "请求超时";
|
message = "请求超时";
|
||||||
break;
|
break;
|
||||||
case 500:
|
case 500:
|
||||||
error.message = "服务器内部错误";
|
message = "服务器内部错误";
|
||||||
break;
|
break;
|
||||||
case 501:
|
case 501:
|
||||||
error.message = "服务未实现";
|
message = "服务未实现";
|
||||||
break;
|
break;
|
||||||
case 502:
|
case 502:
|
||||||
error.message = "网关错误";
|
message = "网关错误";
|
||||||
break;
|
break;
|
||||||
case 503:
|
case 503:
|
||||||
error.message = "服务不可用";
|
message = "服务不可用";
|
||||||
break;
|
break;
|
||||||
case 504:
|
case 504:
|
||||||
error.message = "网关超时";
|
message = "网关超时";
|
||||||
break;
|
break;
|
||||||
case 505:
|
case 505:
|
||||||
error.message = "HTTP版本不受支持";
|
message = "HTTP版本不受支持";
|
||||||
break;
|
break;
|
||||||
case 302:
|
case 302:
|
||||||
//重定向
|
//重定向
|
||||||
return Promise.resolve(error.response);
|
return Promise.resolve(error.response);
|
||||||
|
case 421:
|
||||||
|
message = "源站请求超时";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (status) {
|
||||||
|
message += ` [${status}] `;
|
||||||
|
}
|
||||||
|
|
||||||
const errorCode = error.code;
|
const errorCode = error.code;
|
||||||
let errorMessage = null;
|
let errorMessage = "";
|
||||||
if (errorCode === "ECONNABORTED") {
|
if (errorCode === "ECONNABORTED") {
|
||||||
errorMessage = "请求连接终止";
|
errorMessage = "请求连接终止";
|
||||||
} else if (errorCode === "ETIMEDOUT") {
|
} else if (errorCode === "ETIMEDOUT") {
|
||||||
@@ -231,14 +248,17 @@ export function createAxiosService({ logger }: { logger: ILogger }) {
|
|||||||
} else if (errorCode === "ENOTFOUND") {
|
} else if (errorCode === "ENOTFOUND") {
|
||||||
errorMessage = "请求地址不存在";
|
errorMessage = "请求地址不存在";
|
||||||
}
|
}
|
||||||
if (errorMessage) {
|
if (errorCode) {
|
||||||
if (error.message) {
|
errorMessage += ` [${errorCode}] `;
|
||||||
errorMessage += `,${error.message}`;
|
|
||||||
}
|
|
||||||
error.message = errorMessage;
|
|
||||||
}
|
}
|
||||||
|
if (message) {
|
||||||
logger.error(`请求出错:${errorMessage} status:${error.response?.status || error.code},statusText:${error.response?.statusText || error.code},url:${error.config?.url},method:${error.config?.method}。`);
|
errorMessage += `,${message}`;
|
||||||
|
}
|
||||||
|
if (error.message) {
|
||||||
|
errorMessage += `(${error.message})`;
|
||||||
|
}
|
||||||
|
error.message = errorMessage;
|
||||||
|
logger.error(`请求出错:${errorMessage} status:${status},statusText:${error.response?.statusText || error.code},url:${error.config?.url},method:${error.config?.method}。`);
|
||||||
logger.error("返回数据:", JSON.stringify(error.response?.data));
|
logger.error("返回数据:", JSON.stringify(error.response?.data));
|
||||||
if (error.response?.data) {
|
if (error.response?.data) {
|
||||||
const message = error.response.data.message || error.response.data.msg || error.response.data.error;
|
const message = error.response.data.message || error.response.data.msg || error.response.data.error;
|
||||||
@@ -249,6 +269,22 @@ export function createAxiosService({ logger }: { logger: ILogger }) {
|
|||||||
if (error instanceof AggregateError) {
|
if (error instanceof AggregateError) {
|
||||||
logger.error("AggregateError", error);
|
logger.error("AggregateError", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const originalRequest = error.config || {};
|
||||||
|
logger.info(`config`, originalRequest);
|
||||||
|
const retry = originalRequest.retry || {};
|
||||||
|
if (retry.status && retry.status.includes(status)) {
|
||||||
|
if (retry.max > 0 && retry.count < retry.max) {
|
||||||
|
// 重试次数增加
|
||||||
|
retry.count++;
|
||||||
|
const delay = retry.delay * retry.count;
|
||||||
|
logger.error(`status=${status},重试次数${retry.count},将在${delay}ms后重试,请求地址:${originalRequest.url}`);
|
||||||
|
await sleep(delay);
|
||||||
|
return service.request(originalRequest); // 重试请求
|
||||||
|
}
|
||||||
|
logger.error(`重试超过最大次数${retry.max},请求失败:${originalRequest.url}`);
|
||||||
|
}
|
||||||
|
|
||||||
const err = new HttpError(error);
|
const err = new HttpError(error);
|
||||||
if (error.response?.config?.logParams === false) {
|
if (error.response?.config?.logParams === false) {
|
||||||
delete err.request?.params;
|
delete err.request?.params;
|
||||||
|
|||||||
@@ -1,8 +1,17 @@
|
|||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
export const stringUtils = {
|
export const stringUtils = {
|
||||||
maxLength(str?: string, length = 100) {
|
maxLength(str?: string, length = 100) {
|
||||||
if (str) {
|
if (str) {
|
||||||
return str.length > length ? str.slice(0, length) + '...' : str;
|
return str.length > length ? str.slice(0, length) + "..." : str;
|
||||||
}
|
}
|
||||||
return '';
|
return "";
|
||||||
|
},
|
||||||
|
|
||||||
|
appendTimeSuffix(str?: string) {
|
||||||
|
if (str) {
|
||||||
|
return `${str}-${dayjs().format("YYYYMMDDHHmmssSSS")}`;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,6 +13,19 @@
|
|||||||
|
|
||||||
// await testLocker();
|
// await testLocker();
|
||||||
|
|
||||||
import { domainUtils } from "./dist/utils/util.domain.js";
|
// import { domainUtils } from "./dist/utils/util.domain.js";
|
||||||
|
|
||||||
console.log(domainUtils.isIpv6("::0:0:0:FFFF:129.144.52.38"));
|
// console.log(domainUtils.isIpv6("::0:0:0:FFFF:129.144.52.38"));
|
||||||
|
|
||||||
|
// import { http } from "./dist/utils/util.request.js";
|
||||||
|
|
||||||
|
// http
|
||||||
|
// .request({
|
||||||
|
// url: "https://www.baidu.com/234234/3333",
|
||||||
|
// retry: {
|
||||||
|
// status: [404],
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
// .then(res => {
|
||||||
|
// console.log(res.data);
|
||||||
|
// });
|
||||||
|
|||||||
@@ -3,6 +3,47 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/certd/certd/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/certd/certd/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复1panel 请求失败的bug ([0283662](https://github.com/certd/certd/commit/0283662931ff47d6b5d49f91a30c4a002fe1d108))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 所有授权增加测试按钮 ([7a3e68d](https://github.com/certd/certd/commit/7a3e68d656c1dcdcd814b69891bd2c2c6fe3098a))
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/certd/certd/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/certd/certd/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/certd/certd/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 修复旧版本流水线数据发送通知标题为空的bug ([9bee0e4](https://github.com/certd/certd/commit/9bee0e460bfebe8db76742b80b2d52854392f4de))
|
||||||
|
* 支持部署到阿里云GA ([1a0d3ee](https://github.com/certd/certd/commit/1a0d3eeb1b0b5ce08f05af84b6161e00c1fe1815))
|
||||||
|
|
||||||
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/pipeline
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/pipeline",
|
"name": "@certd/pipeline",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.38.3",
|
"version": "1.38.11",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -18,8 +18,8 @@
|
|||||||
"compile": "tsc --skipLibCheck --watch"
|
"compile": "tsc --skipLibCheck --watch"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/basic": "^1.38.3",
|
"@certd/basic": "^1.38.11",
|
||||||
"@certd/plus-core": "^1.38.3",
|
"@certd/plus-core": "^1.38.11",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"reflect-metadata": "^0.1.13"
|
"reflect-metadata": "^0.1.13"
|
||||||
@@ -45,5 +45,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "f92dc6a1ad103de9cc184da3b84096943906cb59"
|
"gitHead": "1f002159e2a3c73fb5e00341a344effa07d6f653"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import { HttpClient, ILogger, utils } from "@certd/basic";
|
|||||||
import * as _ from "lodash-es";
|
import * as _ from "lodash-es";
|
||||||
import { PluginRequestHandleReq } from "../plugin/index.js";
|
import { PluginRequestHandleReq } from "../plugin/index.js";
|
||||||
|
|
||||||
export type AccessRequestHandleReqInput<T = any> = {
|
// export type AccessRequestHandleReqInput<T = any> = {
|
||||||
id?: number;
|
// id?: number;
|
||||||
title?: string;
|
// title?: string;
|
||||||
access: T;
|
// access: T;
|
||||||
};
|
// };
|
||||||
|
|
||||||
export type AccessRequestHandleReq<T = any> = PluginRequestHandleReq<AccessRequestHandleReqInput<T>>;
|
export type AccessRequestHandleReq<T = any> = PluginRequestHandleReq<T>;
|
||||||
|
|
||||||
export type AccessInputDefine = FormItemProps & {
|
export type AccessInputDefine = FormItemProps & {
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
@@ -465,6 +465,8 @@ export class Executor {
|
|||||||
|
|
||||||
templateData.errors = errors;
|
templateData.errors = errors;
|
||||||
templateData.pipelineResult = pipelineResult;
|
templateData.pipelineResult = pipelineResult;
|
||||||
|
templateData.title = subject;
|
||||||
|
templateData.content = content;
|
||||||
|
|
||||||
for (const notification of this.pipeline.notifications) {
|
for (const notification of this.pipeline.notifications) {
|
||||||
if (!notification.when.includes(when)) {
|
if (!notification.when.includes(when)) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export type PluginRequestHandleReq<T = any> = {
|
|||||||
action: string;
|
action: string;
|
||||||
input: T;
|
input: T;
|
||||||
data: any;
|
data: any;
|
||||||
|
record: { id: number; type: string; title: string };
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserInfo = {
|
export type UserInfo = {
|
||||||
@@ -249,10 +250,7 @@ export abstract class AbstractTaskPlugin implements ITaskPlugin {
|
|||||||
abstract execute(): Promise<void | string>;
|
abstract execute(): Promise<void | string>;
|
||||||
|
|
||||||
appendTimeSuffix(name?: string) {
|
appendTimeSuffix(name?: string) {
|
||||||
if (name == null) {
|
return utils.string.appendTimeSuffix(name);
|
||||||
name = "certd";
|
|
||||||
}
|
|
||||||
return name + "_" + dayjs().format("YYYYMMDDHHmmssSSS");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildCertName(domain: string, prefix = "") {
|
buildCertName(domain: string, prefix = "") {
|
||||||
@@ -297,6 +295,18 @@ export abstract class AbstractTaskPlugin implements ITaskPlugin {
|
|||||||
getStepIdFromRefInput(ref = ".") {
|
getStepIdFromRefInput(ref = ".") {
|
||||||
return ref.split(".")[1];
|
return ref.split(".")[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildDomainGroupOptions(options: any[], domains: string[]) {
|
||||||
|
return utils.options.buildGroupOptions(options, domains);
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastStatus(): Runnable {
|
||||||
|
return this.ctx.lastStatus || ({} as any);
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastOutput(key: string) {
|
||||||
|
return this.getLastStatus().status?.output?.[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type OutputVO = {
|
export type OutputVO = {
|
||||||
|
|||||||
@@ -3,6 +3,38 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/certd/certd/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/certd/certd/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/certd/certd/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/certd/certd/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/certd/certd/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/lib-huawei
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/lib-huawei",
|
"name": "@certd/lib-huawei",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.38.3",
|
"version": "1.38.11",
|
||||||
"main": "./dist/bundle.js",
|
"main": "./dist/bundle.js",
|
||||||
"module": "./dist/bundle.js",
|
"module": "./dist/bundle.js",
|
||||||
"types": "./dist/d/index.d.ts",
|
"types": "./dist/d/index.d.ts",
|
||||||
@@ -24,5 +24,5 @@
|
|||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"tslib": "^2.8.1"
|
"tslib": "^2.8.1"
|
||||||
},
|
},
|
||||||
"gitHead": "f92dc6a1ad103de9cc184da3b84096943906cb59"
|
"gitHead": "1f002159e2a3c73fb5e00341a344effa07d6f653"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,38 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/certd/certd/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/certd/certd/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/certd/certd/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/certd/certd/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/certd/certd/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|
||||||
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/lib-iframe
|
**Note:** Version bump only for package @certd/lib-iframe
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/lib-iframe",
|
"name": "@certd/lib-iframe",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.38.3",
|
"version": "1.38.11",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -31,5 +31,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "f92dc6a1ad103de9cc184da3b84096943906cb59"
|
"gitHead": "1f002159e2a3c73fb5e00341a344effa07d6f653"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,38 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/certd/certd/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/jdcloud
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/certd/certd/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/jdcloud
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/certd/certd/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/jdcloud
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/certd/certd/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/jdcloud
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/jdcloud
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/jdcloud
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/jdcloud
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/certd/certd/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/jdcloud
|
||||||
|
|
||||||
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/jdcloud
|
**Note:** Version bump only for package @certd/jdcloud
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/jdcloud",
|
"name": "@certd/jdcloud",
|
||||||
"version": "1.38.3",
|
"version": "1.38.11",
|
||||||
"description": "jdcloud openApi sdk",
|
"description": "jdcloud openApi sdk",
|
||||||
"main": "./dist/bundle.js",
|
"main": "./dist/bundle.js",
|
||||||
"module": "./dist/bundle.js",
|
"module": "./dist/bundle.js",
|
||||||
@@ -56,5 +56,5 @@
|
|||||||
"fetch"
|
"fetch"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"gitHead": "f92dc6a1ad103de9cc184da3b84096943906cb59"
|
"gitHead": "1f002159e2a3c73fb5e00341a344effa07d6f653"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,38 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/certd/certd/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/certd/certd/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/certd/certd/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/certd/certd/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/certd/certd/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/lib-k8s
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/lib-k8s",
|
"name": "@certd/lib-k8s",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.38.3",
|
"version": "1.38.11",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
"pub": "npm publish"
|
"pub": "npm publish"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/basic": "^1.38.3",
|
"@certd/basic": "^1.38.11",
|
||||||
"@kubernetes/client-node": "0.21.0"
|
"@kubernetes/client-node": "0.21.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -32,5 +32,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "f92dc6a1ad103de9cc184da3b84096943906cb59"
|
"gitHead": "1f002159e2a3c73fb5e00341a344effa07d6f653"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,42 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/certd/certd/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-server
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/certd/certd/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-server
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/certd/certd/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-server
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/certd/certd/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持设置默认的证书申请地址的反向代理 ([0cfb94b](https://github.com/certd/certd/commit/0cfb94b0ba6a6dc3bb0d0a81a1912068a4e6b6b6))
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-server
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-server
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持绑定两个url地址 ([a2e9a41](https://github.com/certd/certd/commit/a2e9a41a7e712395c0e3ee6fe55b370aa1fc1f12))
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/certd/certd/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-server
|
||||||
|
|
||||||
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
### Performance Improvements
|
### Performance Improvements
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/lib-server",
|
"name": "@certd/lib-server",
|
||||||
"version": "1.38.3",
|
"version": "1.38.11",
|
||||||
"description": "midway with flyway, sql upgrade way ",
|
"description": "midway with flyway, sql upgrade way ",
|
||||||
"private": false,
|
"private": false,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -28,11 +28,11 @@
|
|||||||
],
|
],
|
||||||
"license": "AGPL",
|
"license": "AGPL",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/acme-client": "^1.38.3",
|
"@certd/acme-client": "^1.38.11",
|
||||||
"@certd/basic": "^1.38.3",
|
"@certd/basic": "^1.38.11",
|
||||||
"@certd/pipeline": "^1.38.3",
|
"@certd/pipeline": "^1.38.11",
|
||||||
"@certd/plugin-lib": "^1.38.3",
|
"@certd/plugin-lib": "^1.38.11",
|
||||||
"@certd/plus-core": "^1.38.3",
|
"@certd/plus-core": "^1.38.11",
|
||||||
"@midwayjs/cache": "3.14.0",
|
"@midwayjs/cache": "3.14.0",
|
||||||
"@midwayjs/core": "3.20.11",
|
"@midwayjs/core": "3.20.11",
|
||||||
"@midwayjs/i18n": "3.20.13",
|
"@midwayjs/i18n": "3.20.13",
|
||||||
@@ -64,5 +64,5 @@
|
|||||||
"typeorm": "^0.3.11",
|
"typeorm": "^0.3.11",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "f92dc6a1ad103de9cc184da3b84096943906cb59"
|
"gitHead": "1f002159e2a3c73fb5e00341a344effa07d6f653"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export class PlusService {
|
|||||||
|
|
||||||
const subjectId = installInfo.siteId;
|
const subjectId = installInfo.siteId;
|
||||||
const bindUrl = installInfo.bindUrl;
|
const bindUrl = installInfo.bindUrl;
|
||||||
|
const bindUrl2 = installInfo.bindUrl2;
|
||||||
const installTime = installInfo.installTime;
|
const installTime = installInfo.installTime;
|
||||||
const saveLicense = async (license: string) => {
|
const saveLicense = async (license: string) => {
|
||||||
let licenseInfo: SysLicenseInfo = await this.sysSettingsService.getSetting(SysLicenseInfo);
|
let licenseInfo: SysLicenseInfo = await this.sysSettingsService.getSetting(SysLicenseInfo);
|
||||||
@@ -30,7 +31,7 @@ export class PlusService {
|
|||||||
await this.sysSettingsService.saveSetting(licenseInfo);
|
await this.sysSettingsService.saveSetting(licenseInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
return new PlusRequestService({ subjectId, bindUrl, installTime, saveLicense });
|
return new PlusRequestService({ subjectId, bindUrl, bindUrl2, installTime, saveLicense });
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSubjectId() {
|
async getSubjectId() {
|
||||||
@@ -53,9 +54,9 @@ export class PlusService {
|
|||||||
await plusRequestService.verify({ license: licenseInfo.license });
|
await plusRequestService.verify({ license: licenseInfo.license });
|
||||||
}
|
}
|
||||||
|
|
||||||
async bindUrl(url: string) {
|
async bindUrl(url: string, url2?:string) {
|
||||||
const plusRequestService = await this.getPlusRequestService();
|
const plusRequestService = await this.getPlusRequestService();
|
||||||
const res = await plusRequestService.bindUrl(url);
|
const res = await plusRequestService.bindUrl(url,url2);
|
||||||
this.plusRequestService = null;
|
this.plusRequestService = null;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -150,6 +151,12 @@ export class PlusService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getTodayOrderCount () {
|
||||||
|
await this.register();
|
||||||
|
const plusRequestService = await this.getPlusRequestService();
|
||||||
|
return await plusRequestService.getOrderCount()
|
||||||
|
}
|
||||||
|
|
||||||
async requestWithToken(config: HttpRequestConfig) {
|
async requestWithToken(config: HttpRequestConfig) {
|
||||||
const plusRequestService = await this.getPlusRequestService();
|
const plusRequestService = await this.getPlusRequestService();
|
||||||
const token = await this.getAccessToken();
|
const token = await this.getAccessToken();
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ export class SysPrivateSettings extends BaseSettings {
|
|||||||
|
|
||||||
httpsProxy? = '';
|
httpsProxy? = '';
|
||||||
httpProxy? = '';
|
httpProxy? = '';
|
||||||
|
|
||||||
|
reverseProxies?: Record<string, string> = {};
|
||||||
|
|
||||||
dnsResultOrder? = '';
|
dnsResultOrder? = '';
|
||||||
commonCnameEnabled?: boolean = true;
|
commonCnameEnabled?: boolean = true;
|
||||||
|
|
||||||
@@ -107,6 +110,7 @@ export class SysInstallInfo extends BaseSettings {
|
|||||||
siteId?: string;
|
siteId?: string;
|
||||||
bindUserId?: number;
|
bindUserId?: number;
|
||||||
bindUrl?: string;
|
bindUrl?: string;
|
||||||
|
bindUrl2?: string;
|
||||||
accountServerBaseUrl?: string;
|
accountServerBaseUrl?: string;
|
||||||
appKey?: string;
|
appKey?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { Repository } from 'typeorm';
|
|||||||
import { SysSettingsEntity } from '../entity/sys-settings.js';
|
import { SysSettingsEntity } from '../entity/sys-settings.js';
|
||||||
import { BaseSettings, SysInstallInfo, SysPrivateSettings, SysPublicSettings, SysSecret, SysSecretBackup } from './models.js';
|
import { BaseSettings, SysInstallInfo, SysPrivateSettings, SysPublicSettings, SysSecret, SysSecretBackup } from './models.js';
|
||||||
|
|
||||||
import { BaseService } from '../../../basic/index.js';
|
import { getAllSslProviderDomains, setSslProviderReverseProxies } from '@certd/acme-client';
|
||||||
import { cache, logger, setGlobalProxy } from '@certd/basic';
|
import { cache, logger, mergeUtils, setGlobalProxy } from '@certd/basic';
|
||||||
import * as dns from 'node:dns';
|
import * as dns from 'node:dns';
|
||||||
import {mergeUtils} from "@certd/basic";
|
import { BaseService } from '../../../basic/index.js';
|
||||||
import { executorQueue } from '../../basic/service/executor-queue.js';
|
import { executorQueue } from '../../basic/service/executor-queue.js';
|
||||||
const {merge} = mergeUtils;
|
const {merge} = mergeUtils;
|
||||||
/**
|
/**
|
||||||
@@ -120,7 +120,14 @@ export class SysSettingsService extends BaseService<SysSettingsEntity> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getPrivateSettings(): Promise<SysPrivateSettings> {
|
async getPrivateSettings(): Promise<SysPrivateSettings> {
|
||||||
return await this.getSetting(SysPrivateSettings);
|
const res = await this.getSetting<SysPrivateSettings>(SysPrivateSettings);
|
||||||
|
const sslProviderDomains = getAllSslProviderDomains();
|
||||||
|
for (const domain of sslProviderDomains) {
|
||||||
|
if (!res.reverseProxies[domain]) {
|
||||||
|
res.reverseProxies[domain] = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
async savePrivateSettings(bean: SysPrivateSettings) {
|
async savePrivateSettings(bean: SysPrivateSettings) {
|
||||||
@@ -145,6 +152,8 @@ export class SysSettingsService extends BaseService<SysSettingsEntity> {
|
|||||||
if (bean.pipelineMaxRunningCount){
|
if (bean.pipelineMaxRunningCount){
|
||||||
executorQueue.setMaxRunningCount(bean.pipelineMaxRunningCount);
|
executorQueue.setMaxRunningCount(bean.pipelineMaxRunningCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setSslProviderReverseProxies(bean.reverseProxies);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateByKey(key: string, setting: any) {
|
async updateByKey(key: string, setting: any) {
|
||||||
|
|||||||
@@ -3,6 +3,40 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/certd/certd/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/certd/certd/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/certd/certd/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 修改sql升级语句,兼容mysql5.7 ([02f89a9](https://github.com/certd/certd/commit/02f89a9c9d77850437285844670aed441e5953c3))
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/certd/certd/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/certd/certd/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/midway-flyway-js",
|
"name": "@certd/midway-flyway-js",
|
||||||
"version": "1.38.3",
|
"version": "1.38.11",
|
||||||
"description": "midway with flyway, sql upgrade way ",
|
"description": "midway with flyway, sql upgrade way ",
|
||||||
"private": false,
|
"private": false,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -46,5 +46,5 @@
|
|||||||
"typeorm": "^0.3.11",
|
"typeorm": "^0.3.11",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "f92dc6a1ad103de9cc184da3b84096943906cb59"
|
"gitHead": "1f002159e2a3c73fb5e00341a344effa07d6f653"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,12 @@ const DefaultLogger = {
|
|||||||
console.error(args);
|
console.error(args);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let customLogger:any = null;
|
||||||
|
export function setFlywayLogger (logger: any) {
|
||||||
|
customLogger = logger;
|
||||||
|
};
|
||||||
|
|
||||||
export class Flyway {
|
export class Flyway {
|
||||||
scriptDir;
|
scriptDir;
|
||||||
flywayTableName;
|
flywayTableName;
|
||||||
@@ -43,7 +49,7 @@ export class Flyway {
|
|||||||
this.flywayTableName = opts.flywayTableName ?? 'flyway_history';
|
this.flywayTableName = opts.flywayTableName ?? 'flyway_history';
|
||||||
this.baseline = opts.baseline ?? false;
|
this.baseline = opts.baseline ?? false;
|
||||||
this.allowHashNotMatch = opts.allowHashNotMatch ?? false;
|
this.allowHashNotMatch = opts.allowHashNotMatch ?? false;
|
||||||
this.logger = opts.logger || DefaultLogger;
|
this.logger = customLogger || opts.logger || DefaultLogger;
|
||||||
this.connection = opts.connection;
|
this.connection = opts.connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// src/index.ts
|
|
||||||
export { FlywayConfiguration as Configuration } from './configuration.js';
|
export { FlywayConfiguration as Configuration } from './configuration.js';
|
||||||
// eslint-disable-next-line node/no-unpublished-import
|
export { Flyway, setFlywayLogger } from './flyway.js';
|
||||||
export { Flyway } from './flyway.js';
|
|
||||||
// eslint-disable-next-line node/no-unpublished-import
|
|
||||||
export { FlywayHistory } from './entity.js';
|
export { FlywayHistory } from './entity.js';
|
||||||
|
|||||||
@@ -3,6 +3,40 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/certd/certd/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/certd/certd/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/certd/certd/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/certd/certd/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* eab从更多参数中挪到外面 ([5ea4f46](https://github.com/certd/certd/commit/5ea4f46de7ae403a7a16e9488dc1d9c7523d019a))
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/certd/certd/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|
||||||
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
**Note:** Version bump only for package @certd/plugin-cert
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/plugin-cert",
|
"name": "@certd/plugin-cert",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.38.3",
|
"version": "1.38.11",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
@@ -17,10 +17,10 @@
|
|||||||
"compile": "tsc --skipLibCheck --watch"
|
"compile": "tsc --skipLibCheck --watch"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/acme-client": "^1.38.3",
|
"@certd/acme-client": "^1.38.11",
|
||||||
"@certd/basic": "^1.38.3",
|
"@certd/basic": "^1.38.11",
|
||||||
"@certd/pipeline": "^1.38.3",
|
"@certd/pipeline": "^1.38.11",
|
||||||
"@certd/plugin-lib": "^1.38.3",
|
"@certd/plugin-lib": "^1.38.11",
|
||||||
"psl": "^1.9.0",
|
"psl": "^1.9.0",
|
||||||
"punycode.js": "^2.3.1"
|
"punycode.js": "^2.3.1"
|
||||||
},
|
},
|
||||||
@@ -38,5 +38,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "f92dc6a1ad103de9cc184da3b84096943906cb59"
|
"gitHead": "1f002159e2a3c73fb5e00341a344effa07d6f653"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from "@certd/plugin-lib";
|
export * from "@certd/plugin-lib";
|
||||||
|
|||||||
@@ -3,6 +3,38 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/certd/certd/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-lib
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/certd/certd/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-lib
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/certd/certd/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-lib
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/certd/certd/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-lib
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-lib
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-lib
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-lib
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/certd/certd/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-lib
|
||||||
|
|
||||||
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
### Performance Improvements
|
### Performance Improvements
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/plugin-lib",
|
"name": "@certd/plugin-lib",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.38.3",
|
"version": "1.38.11",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
@@ -22,10 +22,10 @@
|
|||||||
"@alicloud/pop-core": "^1.7.10",
|
"@alicloud/pop-core": "^1.7.10",
|
||||||
"@alicloud/tea-util": "^1.4.11",
|
"@alicloud/tea-util": "^1.4.11",
|
||||||
"@aws-sdk/client-s3": "^3.964.0",
|
"@aws-sdk/client-s3": "^3.964.0",
|
||||||
"@certd/acme-client": "^1.38.3",
|
"@certd/acme-client": "^1.38.11",
|
||||||
"@certd/basic": "^1.38.3",
|
"@certd/basic": "^1.38.11",
|
||||||
"@certd/pipeline": "^1.38.3",
|
"@certd/pipeline": "^1.38.11",
|
||||||
"@certd/plus-core": "^1.38.3",
|
"@certd/plus-core": "^1.38.11",
|
||||||
"@kubernetes/client-node": "0.21.0",
|
"@kubernetes/client-node": "0.21.0",
|
||||||
"ali-oss": "^6.22.0",
|
"ali-oss": "^6.22.0",
|
||||||
"basic-ftp": "^5.0.5",
|
"basic-ftp": "^5.0.5",
|
||||||
@@ -57,5 +57,5 @@
|
|||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
},
|
},
|
||||||
"gitHead": "f92dc6a1ad103de9cc184da3b84096943906cb59"
|
"gitHead": "1f002159e2a3c73fb5e00341a344effa07d6f653"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ export interface IDnsProvider<T = any> {
|
|||||||
|
|
||||||
export interface ISubDomainsGetter {
|
export interface ISubDomainsGetter {
|
||||||
getSubDomains(): Promise<string[]>;
|
getSubDomains(): Promise<string[]>;
|
||||||
|
hasSubDomain(domain: string): Promise<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDomainParser {
|
export interface IDomainParser {
|
||||||
|
|||||||
@@ -38,20 +38,28 @@ export class DomainParser implements IDomainParser {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const subDomains = await this.subDomainsGetter.getSubDomains();
|
//检查是否有子域名托管
|
||||||
if (subDomains && subDomains.length > 0) {
|
const subDomain = await this.subDomainsGetter.hasSubDomain(fullDomain);
|
||||||
const fullDomainDot = "." + fullDomain;
|
if (subDomain) {
|
||||||
for (const subDomain of subDomains) {
|
utils.cache.set(cacheKey, subDomain, {
|
||||||
if (fullDomainDot.endsWith("." + subDomain)) {
|
ttl: 60 * 1000,
|
||||||
//找到子域名托管
|
});
|
||||||
utils.cache.set(cacheKey, subDomain, {
|
this.logger.info(`获取到托管域名:${fullDomain}->${subDomain}`);
|
||||||
ttl: 60 * 1000,
|
return subDomain;
|
||||||
});
|
|
||||||
this.logger.info(`获取到子域名托管域名:${fullDomain}->${subDomain}`);
|
|
||||||
return subDomain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// if (subDomains && subDomains.length > 0) {
|
||||||
|
// const fullDomainDot = "." + fullDomain;
|
||||||
|
// for (const subDomain of subDomains) {
|
||||||
|
// if (fullDomainDot.endsWith("." + subDomain)) {
|
||||||
|
// //找到子域名托管
|
||||||
|
// utils.cache.set(cacheKey, subDomain, {
|
||||||
|
// ttl: 60 * 1000,
|
||||||
|
// });
|
||||||
|
// this.logger.info(`获取到子域名托管域名:${fullDomain}->${subDomain}`);
|
||||||
|
// return subDomain;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
const res = this.parseDomainByPsl(fullDomain);
|
const res = this.parseDomainByPsl(fullDomain);
|
||||||
this.logger.info(`从psl获取主域名:${fullDomain}->${res}`);
|
this.logger.info(`从psl获取主域名:${fullDomain}->${res}`);
|
||||||
|
|||||||
@@ -3,6 +3,88 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.38.11](https://github.com/certd/certd/compare/v1.38.10...v1.38.11) (2026-02-16)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 优化登陆页面的黑暗模式 ([e47edda](https://github.com/certd/certd/commit/e47eddaa858f8fffe7a40dfbd14e8cda1dcba4ac))
|
||||||
|
* 支持自定义发件人名称,格式:名称<邮箱> ([bab9adc](https://github.com/certd/certd/commit/bab9adce240108d4291eedc67e04abc4a01019e0))
|
||||||
|
|
||||||
|
## [1.38.10](https://github.com/certd/certd/compare/v1.38.9...v1.38.10) (2026-02-15)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复1panel 请求失败的bug ([0283662](https://github.com/certd/certd/commit/0283662931ff47d6b5d49f91a30c4a002fe1d108))
|
||||||
|
* 修复保存站点监控dns设置,偶尔无法保存成功的bug ([8387fe0](https://github.com/certd/certd/commit/8387fe0d5b2e77b8c2788a10791e5389d97a3e41))
|
||||||
|
* 修复任务步骤标题过长导致错位的问题 ([9fb9805](https://github.com/certd/certd/commit/9fb980599f96ccbf61bd46019411db2f13c70e57))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 监控设置支持逗号分割 ([c23d1d1](https://github.com/certd/certd/commit/c23d1d11b58a6cdfe431a7e8abbd5d955146c38d))
|
||||||
|
* 列表中支持下次执行时间显示 ([a3cabd5](https://github.com/certd/certd/commit/a3cabd5f36ed41225ad418098596e9b2c44e31a1))
|
||||||
|
* 模版编辑页面,hover反色过亮问题优化 ([e55a3a8](https://github.com/certd/certd/commit/e55a3a82fc6939b940f0c3be4529d74a625f6f4e))
|
||||||
|
* 所有授权增加测试按钮 ([7a3e68d](https://github.com/certd/certd/commit/7a3e68d656c1dcdcd814b69891bd2c2c6fe3098a))
|
||||||
|
* 优化网络测试页面,夜间模式显示效果 ([305da86](https://github.com/certd/certd/commit/305da86f97d918374819ecd6c50685f09b94ea59))
|
||||||
|
* 支持next-terminal ([6f3fd78](https://github.com/certd/certd/commit/6f3fd785e77a33c72bdf4115dc5d498e677d1863))
|
||||||
|
* 主题默认跟随系统颜色(自动切换深色浅色模式) ([32c3ce5](https://github.com/certd/certd/commit/32c3ce5c9868569523901a9a939ca5b535ec3277))
|
||||||
|
* http校验方式支持scp上传 ([4eb940f](https://github.com/certd/certd/commit/4eb940ffe765a0330331bc6af8396315e36d4e4a))
|
||||||
|
|
||||||
|
## [1.38.9](https://github.com/certd/certd/compare/v1.38.8...v1.38.9) (2026-02-09)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 已登录状态访问登录页面自动跳转到首页 ([bd8caff](https://github.com/certd/certd/commit/bd8caff0b754cb13530cf0f1644b33e29fde5d01))
|
||||||
|
* 优化access授权支持remote-auto-complete ([2f40f79](https://github.com/certd/certd/commit/2f40f795ee6131132d3fab2601f92a567bbdc4b7))
|
||||||
|
* access 插件支持remote-select等配置 ([d286c04](https://github.com/certd/certd/commit/d286c040a5232dcca829945734affead3ee08b3c))
|
||||||
|
|
||||||
|
## [1.38.8](https://github.com/certd/certd/compare/v1.38.7...v1.38.8) (2026-02-06)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 双重验证显示secret ([febd6d3](https://github.com/certd/certd/commit/febd6d32cfe6d89ccecf26bf15141df7c456e5c6))
|
||||||
|
* 支持设置默认的证书申请地址的反向代理 ([0cfb94b](https://github.com/certd/certd/commit/0cfb94b0ba6a6dc3bb0d0a81a1912068a4e6b6b6))
|
||||||
|
* 子域名托管域名支持配置通配符 ([3f7ac93](https://github.com/certd/certd/commit/3f7ac939326b0c7ec013a7534b6c0e58fb3e8cb4))
|
||||||
|
|
||||||
|
## [1.38.7](https://github.com/certd/certd/compare/v1.38.6...v1.38.7) (2026-02-05)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复有域名记录时,域名输入框无法关闭的bug ([54c8217](https://github.com/certd/certd/commit/54c8217808453b121abf646b004596f28932509f))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* eab从更多参数中挪到外面 ([5ea4f46](https://github.com/certd/certd/commit/5ea4f46de7ae403a7a16e9488dc1d9c7523d019a))
|
||||||
|
|
||||||
|
## [1.38.6](https://github.com/certd/certd/compare/v1.38.5...v1.38.6) (2026-02-04)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 当域名管理中没有域名时,创建流水线时不展开域名选择框 ([9166a57](https://github.com/certd/certd/commit/9166a579301a60750f0b72b6a42b0c8d730695fd))
|
||||||
|
* count tip ([e19743f](https://github.com/certd/certd/commit/e19743f70553700f1f91bff76f87370f749dd247))
|
||||||
|
* oauth支持github 和google, 修复头像显示问题 ([693a4a6](https://github.com/certd/certd/commit/693a4a663385ced3176286bf4b5f3566da83d90e))
|
||||||
|
|
||||||
|
## [1.38.5](https://github.com/certd/certd/compare/v1.38.4...v1.38.5) (2026-02-02)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 某些情况下登陆页面没有显示重置密码文档链接的问题 ([40801d0](https://github.com/certd/certd/commit/40801d0a0668c77adb57fae42b4b6615b198a88d))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 支持绑定两个url地址 ([a2e9a41](https://github.com/certd/certd/commit/a2e9a41a7e712395c0e3ee6fe55b370aa1fc1f12))
|
||||||
|
|
||||||
|
## [1.38.4](https://github.com/certd/certd/compare/v1.38.3...v1.38.4) (2026-01-31)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复1:: 形式的ipv6校验失败的bug ([8b96f21](https://github.com/certd/certd/commit/8b96f218d5284033f10c186c0ce18e4c16d8e9b2))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 首页证书数量支持点击跳转 ([52cbff0](https://github.com/certd/certd/commit/52cbff0e15329aecd3edcf81315fb7ceab9ec290))
|
||||||
|
* 验证码支持 Cloudflare Turnstile ,谨慎启用,国内被墙了 ([ca43c77](https://github.com/certd/certd/commit/ca43c775250154def63c4acd96d65dc95d1c0c2b))
|
||||||
|
* 优化证书未过期时的任务日志提示 ([ac85488](https://github.com/certd/certd/commit/ac85488245197694560aad7df9425ca215ef7ff7))
|
||||||
|
|
||||||
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
## [1.38.3](https://github.com/certd/certd/compare/v1.38.2...v1.38.3) (2026-01-28)
|
||||||
|
|
||||||
### Performance Improvements
|
### Performance Improvements
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/ui-client",
|
"name": "@certd/ui-client",
|
||||||
"version": "1.38.3",
|
"version": "1.38.11",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --open",
|
"dev": "vite --open",
|
||||||
@@ -106,8 +106,8 @@
|
|||||||
"zod-defaults": "^0.1.3"
|
"zod-defaults": "^0.1.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@certd/lib-iframe": "^1.38.3",
|
"@certd/lib-iframe": "^1.38.11",
|
||||||
"@certd/pipeline": "^1.38.3",
|
"@certd/pipeline": "^1.38.11",
|
||||||
"@rollup/plugin-commonjs": "^25.0.7",
|
"@rollup/plugin-commonjs": "^25.0.7",
|
||||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||||
"@types/chai": "^4.3.12",
|
"@types/chai": "^4.3.12",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
width="500" height="500" viewBox="0 0 500.000000 500.000000"
|
width="500" height="500" viewBox="0 0 500.000000 500.000000"
|
||||||
>
|
>
|
||||||
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
|
<path fill="#333" d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
|
||||||
transform="translate(70, 76) scale(6,6)"
|
transform="translate(70, 76) scale(6,6)"
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 397 B After Width: | Height: | Size: 409 B |
|
After Width: | Height: | Size: 5.4 KiB |
@@ -8,19 +8,23 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, provide, ref } from "vue";
|
import { computed, provide, Ref, ref } from "vue";
|
||||||
import { preferences, usePreferences } from "/@/vben/preferences";
|
import { preferences, usePreferences } from "/@/vben/preferences";
|
||||||
import { useAntdDesignTokens } from "/@/vben/hooks";
|
import { useAntdDesignTokens } from "/@/vben/hooks";
|
||||||
import { Modal, theme } from "ant-design-vue";
|
import { Modal, theme } from "ant-design-vue";
|
||||||
import AConfigProvider from "ant-design-vue/es/config-provider";
|
import AConfigProvider from "ant-design-vue/es/config-provider";
|
||||||
import { antdvLocale } from "./locales/antdv";
|
import { antdvLocale } from "./locales/antdv";
|
||||||
import { setI18nLanguage } from "/@/locales";
|
import { setI18nLanguage } from "/@/locales";
|
||||||
|
import { mitter } from "./utils/util.mitt";
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "App",
|
name: "App",
|
||||||
});
|
});
|
||||||
|
|
||||||
const [modal, contextHolder] = Modal.useModal();
|
const [modal, contextHolder] = Modal.useModal();
|
||||||
provide("modal", modal);
|
provide("modal", modal);
|
||||||
|
mitter.on("getModal", (event: any) => {
|
||||||
|
event.ModalRef = modal;
|
||||||
|
});
|
||||||
|
|
||||||
const locale = preferences.app.locale;
|
const locale = preferences.app.locale;
|
||||||
setI18nLanguage(locale);
|
setI18nLanguage(locale);
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
<template>
|
||||||
|
<div class="cf-turnstile">
|
||||||
|
<div id="turnstile-container" class="cf-turnstile-container" :data-sitekey="siteKeyRef"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { nextTick, onMounted, onUnmounted, ref, watch } from "vue";
|
||||||
|
|
||||||
|
import { loadScript } from "vue-plugin-load-script";
|
||||||
|
const loaded = ref(false);
|
||||||
|
async function loadCaptchaScript() {
|
||||||
|
await loadScript("https://challenges.cloudflare.com/turnstile/v0/api.js");
|
||||||
|
loaded.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "CfTurnstileCaptcha",
|
||||||
|
});
|
||||||
|
const emit = defineEmits(["update:modelValue", "change"]);
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue: any;
|
||||||
|
captchaGet: () => Promise<any>;
|
||||||
|
}>();
|
||||||
|
const captchaRef = ref(null);
|
||||||
|
const siteKeyRef = ref("");
|
||||||
|
const widgetIdRef = ref(null);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadCaptchaScript();
|
||||||
|
await nextTick();
|
||||||
|
const { siteKey } = await props.captchaGet();
|
||||||
|
siteKeyRef.value = siteKey; //这里确定是string类型
|
||||||
|
//@ts-ignore
|
||||||
|
const widgetId = turnstile.render("#turnstile-container", {
|
||||||
|
sitekey: siteKey,
|
||||||
|
size: "flexible",
|
||||||
|
callback: function (token: string) {
|
||||||
|
console.log("turnstile success:", token);
|
||||||
|
emitChange({
|
||||||
|
token: token,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
widgetIdRef.value = widgetId;
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
//@ts-ignore
|
||||||
|
if (turnstile && widgetIdRef.value) {
|
||||||
|
//@ts-ignore
|
||||||
|
turnstile.remove(widgetIdRef.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function checkExpired() {
|
||||||
|
//@ts-ignore
|
||||||
|
if (turnstile && widgetIdRef.value) {
|
||||||
|
//@ts-ignore
|
||||||
|
return turnstile.isExpired(widgetIdRef.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function emitChange(value: any) {
|
||||||
|
emit("update:modelValue", value);
|
||||||
|
emit("change", value);
|
||||||
|
}
|
||||||
|
function reset() {
|
||||||
|
// 重置验证码
|
||||||
|
//@ts-ignore
|
||||||
|
if (turnstile && widgetIdRef.value) {
|
||||||
|
//@ts-ignore
|
||||||
|
turnstile.reset(widgetIdRef.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => {
|
||||||
|
return props.modelValue;
|
||||||
|
},
|
||||||
|
value => {
|
||||||
|
if (value == null) {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
reset,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="less">
|
||||||
|
.cf-turnstile-container {
|
||||||
|
iframe {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -11,8 +11,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineEmits, defineExpose, defineProps, ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { nanoid } from "nanoid";
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: any;
|
modelValue: any;
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, defineProps, defineEmits, ref, onUnmounted, Ref, watch } from "vue";
|
|
||||||
import { notification } from "ant-design-vue";
|
import { notification } from "ant-design-vue";
|
||||||
|
import { ref, Ref, watch } from "vue";
|
||||||
|
|
||||||
import { loadScript } from "vue-plugin-load-script";
|
import { loadScript } from "vue-plugin-load-script";
|
||||||
const loaded = ref(false);
|
const loaded = ref(false);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
||||||
import { ref, inject } from "vue";
|
import { ref, inject } from "vue";
|
||||||
import { Form } from "ant-design-vue";
|
import { Form } from "ant-design-vue";
|
||||||
|
import { getInputFromForm } from "./utils";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "ApiTest",
|
name: "ApiTest",
|
||||||
@@ -45,13 +46,15 @@ const doTest = async () => {
|
|||||||
message.value = "";
|
message.value = "";
|
||||||
hasError.value = false;
|
hasError.value = false;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
const { input, record } = getInputFromForm(form, pluginType);
|
||||||
try {
|
try {
|
||||||
const res = await doRequest(
|
const res = await doRequest(
|
||||||
{
|
{
|
||||||
type: pluginType,
|
type: pluginType,
|
||||||
typeName: form.type,
|
typeName: form.type,
|
||||||
action: props.action,
|
action: props.action,
|
||||||
input: pluginType === "plugin" ? form.input : form,
|
input,
|
||||||
|
record,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onError(err: any) {
|
onError(err: any) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<div class="flex flex-row">
|
<div class="flex flex-row">
|
||||||
<a-select
|
<a-select
|
||||||
class="domain-select-input"
|
class="domain-select-input"
|
||||||
|
:popup-class-name="popupClassName"
|
||||||
:dropdown-style="dropdownStyle"
|
:dropdown-style="dropdownStyle"
|
||||||
show-search
|
show-search
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
@@ -55,11 +56,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, defineComponent, ref, Ref, useAttrs } from "vue";
|
import { computed, defineComponent, onMounted, ref, Ref, useAttrs } from "vue";
|
||||||
import { request } from "/@/api/service";
|
|
||||||
import { Dicts } from "../lib/dicts";
|
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { useDomainImport, useDomainImportManage } from "/@/views/certd/cert/domain/use";
|
import { Dicts } from "../lib/dicts";
|
||||||
|
import { request } from "/@/api/service";
|
||||||
|
import { openRouteInNewWindow } from "/@/vben/utils";
|
||||||
|
import { useDomainImportManage } from "/@/views/certd/cert/domain/use";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "DomainSelector",
|
name: "DomainSelector",
|
||||||
@@ -89,6 +91,15 @@ const emit = defineEmits<{
|
|||||||
|
|
||||||
const attrs = useAttrs();
|
const attrs = useAttrs();
|
||||||
|
|
||||||
|
const hasOptions: Ref = ref(null);
|
||||||
|
|
||||||
|
const popupClassName = computed(() => {
|
||||||
|
if (!hasOptions.value) {
|
||||||
|
return "hidden-important";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
|
||||||
const searchKeyRef = ref("");
|
const searchKeyRef = ref("");
|
||||||
const optionsRef = ref([]);
|
const optionsRef = ref([]);
|
||||||
const message = ref("");
|
const message = ref("");
|
||||||
@@ -142,6 +153,14 @@ const getOptions = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
optionsRef.value = options;
|
optionsRef.value = options;
|
||||||
|
if (hasOptions.value == null) {
|
||||||
|
//初始设置一次
|
||||||
|
if (options.length > 0) {
|
||||||
|
hasOptions.value = true;
|
||||||
|
} else {
|
||||||
|
hasOptions.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
pagerRef.value.total = list.length;
|
pagerRef.value.total = list.length;
|
||||||
if (props.pager) {
|
if (props.pager) {
|
||||||
if (res.total != null) {
|
if (res.total != null) {
|
||||||
@@ -190,7 +209,7 @@ const router = useRouter();
|
|||||||
function openDomainManager(e: any) {
|
function openDomainManager(e: any) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
// router.push("/certd/cert/domain");
|
// router.push("/certd/cert/domain");
|
||||||
window.open(`${window.location.origin}/#/certd/cert/domain`);
|
openRouteInNewWindow("/certd/cert/domain");
|
||||||
}
|
}
|
||||||
|
|
||||||
const openDomainImportManageDialog = useDomainImportManage();
|
const openDomainImportManageDialog = useDomainImportManage();
|
||||||
@@ -204,6 +223,10 @@ function openDomainImportDialog() {
|
|||||||
const dropdownStyle = ref({
|
const dropdownStyle = ref({
|
||||||
zIndex: 2000,
|
zIndex: 2000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
refreshOptions();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less"></style>
|
<style lang="less"></style>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="params-show">
|
<div class="params-show">
|
||||||
<a-tag type="primary" color="green" v-for="item of params" :key="item.value" class="item">
|
<a-tag v-for="item of params" :key="item.value" type="primary" color="green" class="item">
|
||||||
<span class="label">{{ item.label }}=</span>
|
<span class="label">{{ item.label }}=</span>
|
||||||
<fs-copyable :modelValue="`\$\{${item.value}\}`" :button="{show:false}" :inline="true"></fs-copyable>
|
<fs-copyable :model-value="`\$\{${item.value}\}`" :button="{ show: false }" :inline="true"></fs-copyable>
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
||||||
import { defineComponent, inject, ref, useAttrs, watch, Ref } from "vue";
|
import { defineComponent, inject, ref, useAttrs, watch, Ref } from "vue";
|
||||||
import { PluginDefine } from "@certd/pipeline";
|
import { PluginDefine } from "@certd/pipeline";
|
||||||
|
import { getInputFromForm } from "./utils";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "RemoteAutoComplete",
|
name: "RemoteAutoComplete",
|
||||||
@@ -23,7 +24,7 @@ defineOptions({
|
|||||||
|
|
||||||
const props = defineProps<
|
const props = defineProps<
|
||||||
{
|
{
|
||||||
watches: string[];
|
watches?: string[];
|
||||||
} & ComponentPropsType
|
} & ComponentPropsType
|
||||||
>();
|
>();
|
||||||
|
|
||||||
@@ -63,15 +64,14 @@ const getOptions = async () => {
|
|||||||
}
|
}
|
||||||
const pluginType = getPluginType();
|
const pluginType = getPluginType();
|
||||||
const { form } = getScope();
|
const { form } = getScope();
|
||||||
const input = (pluginType === "plugin" ? form?.input : form) || {};
|
const { input, record } = getInputFromForm(form, pluginType);
|
||||||
|
|
||||||
for (let key in define.input) {
|
for (let key in define.input) {
|
||||||
const inWatches = props.watches?.includes(key);
|
const inWatches = props.watches?.includes(key);
|
||||||
const inputDefine = define.input[key];
|
const inputDefine = define.input[key];
|
||||||
if (inWatches && inputDefine.required) {
|
if (inWatches && inputDefine.required) {
|
||||||
const value = input[key];
|
const value = input[key];
|
||||||
if (value == null || value === "") {
|
if (value == null || value === "") {
|
||||||
console.log("remote-select required", key);
|
console.log("remote-auto-complete required", key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,6 +88,7 @@ const getOptions = async () => {
|
|||||||
action: props.action,
|
action: props.action,
|
||||||
input,
|
input,
|
||||||
data: {},
|
data: {},
|
||||||
|
record,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onError(err: any) {
|
onError(err: any) {
|
||||||
@@ -129,12 +130,14 @@ watch(
|
|||||||
() => {
|
() => {
|
||||||
const pluginType = getPluginType();
|
const pluginType = getPluginType();
|
||||||
const { form, key } = getScope();
|
const { form, key } = getScope();
|
||||||
const input = (pluginType === "plugin" ? form?.input : form) || {};
|
const { input, record } = getInputFromForm(form, pluginType);
|
||||||
const watches = {};
|
const watches: any = {};
|
||||||
for (const key of props.watches) {
|
if (props.watches && props.watches.length > 0) {
|
||||||
//@ts-ignore
|
for (const key of props.watches) {
|
||||||
watches[key] = input[key];
|
watches[key] = input[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
form: watches,
|
form: watches,
|
||||||
key,
|
key,
|
||||||
@@ -144,6 +147,9 @@ watch(
|
|||||||
const { form } = value;
|
const { form } = value;
|
||||||
const oldForm: any = oldValue?.form;
|
const oldForm: any = oldValue?.form;
|
||||||
let changed = oldForm == null || optionsRef.value.length == 0;
|
let changed = oldForm == null || optionsRef.value.length == 0;
|
||||||
|
if (!props.watches || props.watches.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (const key of props.watches) {
|
for (const key of props.watches) {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
if (oldForm && form[key] != oldForm[key]) {
|
if (oldForm && form[key] != oldForm[key]) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { doRequest } from "/@/components/plugins/lib";
|
|||||||
import { inject, ref, useAttrs } from "vue";
|
import { inject, ref, useAttrs } from "vue";
|
||||||
import { useFormWrapper } from "@fast-crud/fast-crud";
|
import { useFormWrapper } from "@fast-crud/fast-crud";
|
||||||
import { notification } from "ant-design-vue";
|
import { notification } from "ant-design-vue";
|
||||||
|
import { getInputFromForm } from "./utils";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "RemoteInput",
|
name: "RemoteInput",
|
||||||
@@ -71,15 +72,18 @@ const doPluginFormSubmit = async (data: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const pluginType = getPluginType();
|
const pluginType = getPluginType();
|
||||||
const { form } = getScope();
|
const { form } = getScope();
|
||||||
|
const { input, record } = getInputFromForm(form, pluginType);
|
||||||
const res = await doRequest({
|
const res = await doRequest({
|
||||||
type: pluginType,
|
type: pluginType,
|
||||||
typeName: form.type,
|
typeName: form.type,
|
||||||
action: props.action,
|
action: props.action,
|
||||||
input: pluginType === "plugin" ? form.input : form,
|
input,
|
||||||
data: data,
|
data: data,
|
||||||
|
record,
|
||||||
});
|
});
|
||||||
//获取返回值 填入到input中
|
//获取返回值 填入到input中
|
||||||
emit("update:modelValue", res);
|
emit("update:modelValue", res);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
||||||
import { defineComponent, inject, ref, useAttrs, watch, Ref } from "vue";
|
import { defineComponent, inject, ref, useAttrs, watch, Ref } from "vue";
|
||||||
import { PluginDefine } from "@certd/pipeline";
|
import { PluginDefine } from "@certd/pipeline";
|
||||||
|
import { getInputFromForm } from "./utils";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "RemoteSelect",
|
name: "RemoteSelect",
|
||||||
@@ -57,7 +58,7 @@ const VNodes = defineComponent({
|
|||||||
|
|
||||||
const props = defineProps<
|
const props = defineProps<
|
||||||
{
|
{
|
||||||
watches: string[];
|
watches?: string[];
|
||||||
search?: boolean;
|
search?: boolean;
|
||||||
pager?: boolean;
|
pager?: boolean;
|
||||||
} & ComponentPropsType
|
} & ComponentPropsType
|
||||||
@@ -104,7 +105,7 @@ const getOptions = async () => {
|
|||||||
}
|
}
|
||||||
const pluginType = getPluginType();
|
const pluginType = getPluginType();
|
||||||
const { form } = getScope();
|
const { form } = getScope();
|
||||||
const input = (pluginType === "plugin" ? form?.input : form) || {};
|
const { input, record } = getInputFromForm(form, pluginType);
|
||||||
|
|
||||||
for (let key in define.input) {
|
for (let key in define.input) {
|
||||||
const inWatches = props.watches?.includes(key);
|
const inWatches = props.watches?.includes(key);
|
||||||
@@ -130,6 +131,7 @@ const getOptions = async () => {
|
|||||||
typeName: form.type,
|
typeName: form.type,
|
||||||
action: props.action,
|
action: props.action,
|
||||||
input,
|
input,
|
||||||
|
record,
|
||||||
data: {
|
data: {
|
||||||
searchKey: props.search ? searchKeyRef.value : "",
|
searchKey: props.search ? searchKeyRef.value : "",
|
||||||
pageNo,
|
pageNo,
|
||||||
@@ -200,12 +202,14 @@ watch(
|
|||||||
() => {
|
() => {
|
||||||
const pluginType = getPluginType();
|
const pluginType = getPluginType();
|
||||||
const { form, key } = getScope();
|
const { form, key } = getScope();
|
||||||
const input = (pluginType === "plugin" ? form?.input : form) || {};
|
const { input, record } = getInputFromForm(form, pluginType);
|
||||||
const watches = {};
|
const watches: any = {};
|
||||||
for (const key of props.watches) {
|
if (props.watches && props.watches.length > 0) {
|
||||||
//@ts-ignore
|
for (const key of props.watches) {
|
||||||
watches[key] = input[key];
|
watches[key] = input[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
form: watches,
|
form: watches,
|
||||||
key,
|
key,
|
||||||
@@ -215,11 +219,12 @@ watch(
|
|||||||
const { form } = value;
|
const { form } = value;
|
||||||
const oldForm: any = oldValue?.form;
|
const oldForm: any = oldValue?.form;
|
||||||
let changed = oldForm == null || optionsRef.value.length == 0;
|
let changed = oldForm == null || optionsRef.value.length == 0;
|
||||||
for (const key of props.watches) {
|
if (props.watches && props.watches.length > 0) {
|
||||||
//@ts-ignore
|
for (const key of props.watches) {
|
||||||
if (oldForm && form[key] != oldForm[key]) {
|
if (oldForm && form[key] != oldForm[key]) {
|
||||||
changed = true;
|
changed = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
||||||
import { defineComponent, inject, ref, useAttrs, watch, Ref } from "vue";
|
import { defineComponent, inject, ref, useAttrs, watch, Ref } from "vue";
|
||||||
import { PluginDefine } from "@certd/pipeline";
|
import { PluginDefine } from "@certd/pipeline";
|
||||||
|
import { getInputFromForm } from "./utils";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "RemoteTreeSelect",
|
name: "RemoteTreeSelect",
|
||||||
@@ -67,7 +68,7 @@ const getOptions = async () => {
|
|||||||
}
|
}
|
||||||
const pluginType = getPluginType();
|
const pluginType = getPluginType();
|
||||||
const { form } = getScope();
|
const { form } = getScope();
|
||||||
const input = (pluginType === "plugin" ? form?.input : form) || {};
|
const { input, record } = getInputFromForm(form, pluginType);
|
||||||
|
|
||||||
for (let key in define.input) {
|
for (let key in define.input) {
|
||||||
const inWatches = props.watches?.includes(key);
|
const inWatches = props.watches?.includes(key);
|
||||||
@@ -98,6 +99,7 @@ const getOptions = async () => {
|
|||||||
pageNo,
|
pageNo,
|
||||||
pageSize,
|
pageSize,
|
||||||
},
|
},
|
||||||
|
record,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onError(err: any) {
|
onError(err: any) {
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { cloneDeep } from "lodash-es";
|
||||||
|
|
||||||
|
export function getInputFromForm(form: any, pluginType: string) {
|
||||||
|
form = cloneDeep(form);
|
||||||
|
let input: any = {};
|
||||||
|
const record: any = form;
|
||||||
|
if (pluginType === "plugin") {
|
||||||
|
input = form?.input || {};
|
||||||
|
delete form.input;
|
||||||
|
} else if (pluginType === "access") {
|
||||||
|
input = form?.access || {};
|
||||||
|
delete form.access;
|
||||||
|
} else if (pluginType === "notification") {
|
||||||
|
input = form?.body || {};
|
||||||
|
delete form.body;
|
||||||
|
} else if (pluginType === "addon") {
|
||||||
|
input = form?.body || {};
|
||||||
|
delete form.body;
|
||||||
|
} else {
|
||||||
|
throw new Error(`pluginType ${pluginType} not support`);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
input,
|
||||||
|
record,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ export const Dicts = {
|
|||||||
uploaderTypeDict: dict({
|
uploaderTypeDict: dict({
|
||||||
data: [
|
data: [
|
||||||
{ label: "SFTP", value: "sftp" },
|
{ label: "SFTP", value: "sftp" },
|
||||||
|
{ label: "SCP", value: "scp" },
|
||||||
{ label: "FTP", value: "ftp" },
|
{ label: "FTP", value: "ftp" },
|
||||||
{ label: "阿里云OSS", value: "alioss" },
|
{ label: "阿里云OSS", value: "alioss" },
|
||||||
{ label: "腾讯云COS", value: "tencentcos" },
|
{ label: "腾讯云COS", value: "tencentcos" },
|
||||||
|
|||||||
@@ -12,11 +12,12 @@ export type RequestHandleReq<T = any> = {
|
|||||||
action: string;
|
action: string;
|
||||||
data?: any;
|
data?: any;
|
||||||
input: T;
|
input: T;
|
||||||
|
record?: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function doRequest(req: RequestHandleReq, opts: any = {}) {
|
export async function doRequest(req: RequestHandleReq, opts: any = {}) {
|
||||||
const url = `/pi/handle/${req.type}`;
|
const url = `/pi/handle/${req.type}`;
|
||||||
const { typeName, action, data, input } = req;
|
const { typeName, action, data, input, record } = req;
|
||||||
const res = await request({
|
const res = await request({
|
||||||
url,
|
url,
|
||||||
method: "post",
|
method: "post",
|
||||||
@@ -25,6 +26,7 @@ export async function doRequest(req: RequestHandleReq, opts: any = {}) {
|
|||||||
action,
|
action,
|
||||||
data,
|
data,
|
||||||
input,
|
input,
|
||||||
|
record,
|
||||||
},
|
},
|
||||||
...opts,
|
...opts,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,3 +15,10 @@ export async function getVipTrial(vipType: string) {
|
|||||||
data: { vipType },
|
data: { vipType },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getTodayVipOrderCount() {
|
||||||
|
return await request({
|
||||||
|
url: "/sys/plus/getTodayVipOrderCount",
|
||||||
|
method: "post",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,16 +14,20 @@
|
|||||||
<script lang="tsx" setup>
|
<script lang="tsx" setup>
|
||||||
import { message, Modal } from "ant-design-vue";
|
import { message, Modal } from "ant-design-vue";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { computed, onMounted, reactive, ref } from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import * as api from "./api";
|
import * as api from "./api";
|
||||||
import { useSettingStore } from "/@/store/settings";
|
import { useSettingStore } from "/src/store/settings/index";
|
||||||
import { useUserStore } from "/@/store/user";
|
import { useUserStore } from "/@/store/user";
|
||||||
import { env } from "/@/utils/util.env";
|
import { env } from "/@/utils/util.env";
|
||||||
import { mitter } from "/@/utils/util.mitt";
|
import { mitter } from "/@/utils/util.mitt";
|
||||||
|
import VipModalContent from "./vip-modal-content.vue";
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "VipButton",
|
||||||
|
});
|
||||||
const settingStore = useSettingStore();
|
const settingStore = useSettingStore();
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@@ -39,6 +43,7 @@ type Text = {
|
|||||||
};
|
};
|
||||||
const text = computed<Text>(() => {
|
const text = computed<Text>(() => {
|
||||||
const vipLabel = settingStore.vipLabel;
|
const vipLabel = settingStore.vipLabel;
|
||||||
|
const plusMessage = settingStore.plusInfo?.message;
|
||||||
const map = {
|
const map = {
|
||||||
isComm: {
|
isComm: {
|
||||||
comm: {
|
comm: {
|
||||||
@@ -91,7 +96,7 @@ const text = computed<Text>(() => {
|
|||||||
},
|
},
|
||||||
nav: {
|
nav: {
|
||||||
name: t("vip.free.nav.name"),
|
name: t("vip.free.nav.name"),
|
||||||
title: t("vip.free.nav.title"),
|
title: plusMessage || t("vip.free.nav.title"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -113,58 +118,16 @@ const expireTime = computed(() => {
|
|||||||
|
|
||||||
const expiredDays = computed(() => {
|
const expiredDays = computed(() => {
|
||||||
if (settingStore.plusInfo?.isPlus && !settingStore.isPlus) {
|
if (settingStore.plusInfo?.isPlus && !settingStore.isPlus) {
|
||||||
//已过期多少天
|
|
||||||
const days = dayjs().diff(dayjs(settingStore.plusInfo.expireTime), "day");
|
const days = dayjs().diff(dayjs(settingStore.plusInfo.expireTime), "day");
|
||||||
return `${settingStore.vipLabel}已过期${days}天`;
|
return `${settingStore.vipLabel}已过期${days}天`;
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
|
|
||||||
const formState = reactive({
|
|
||||||
code: "",
|
|
||||||
inviteCode: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
async function doActive() {
|
|
||||||
if (!formState.code) {
|
|
||||||
message.error(t("vip.enterCode"));
|
|
||||||
throw new Error(t("vip.enterCode"));
|
|
||||||
}
|
|
||||||
const res = await api.doActive(formState);
|
|
||||||
if (res) {
|
|
||||||
await settingStore.init();
|
|
||||||
const vipLabel = settingStore.vipLabel;
|
|
||||||
Modal.success({
|
|
||||||
title: t("vip.successTitle"),
|
|
||||||
content: t("vip.successContent", {
|
|
||||||
vipLabel,
|
|
||||||
expireDate: dayjs(settingStore.plusInfo.expireTime).format("YYYY-MM-DD"),
|
|
||||||
}),
|
|
||||||
onOk() {
|
|
||||||
if (!(settingStore.installInfo.bindUserId > 0)) {
|
|
||||||
Modal.confirm({
|
|
||||||
title: t("vip.bindAccountTitle"),
|
|
||||||
content: t("vip.bindAccountContent"),
|
|
||||||
onOk() {
|
|
||||||
router.push("/sys/account");
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const computedSiteId = computed(() => settingStore.installInfo?.siteId);
|
|
||||||
const [modal, contextHolder] = Modal.useModal();
|
const [modal, contextHolder] = Modal.useModal();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
function goAccount() {
|
|
||||||
Modal.destroyAll();
|
|
||||||
router.push("/sys/account");
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getVipTrial(vipType = "plus") {
|
async function getVipTrial(vipType = "plus") {
|
||||||
const res = await api.getVipTrial(vipType);
|
const res = await api.getVipTrial(vipType);
|
||||||
message.success(t("vip.congratulations_vip_trial", { duration: res.duration }));
|
message.success(t("vip.congratulations_vip_trial", { duration: res.duration }));
|
||||||
@@ -198,27 +161,30 @@ function openStarModal(vipType: string) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Modal.destroyAll();
|
Modal.destroyAll();
|
||||||
const goGithub = () => {
|
|
||||||
window.open("https://github.com/certd/certd/");
|
|
||||||
};
|
|
||||||
|
|
||||||
modal.confirm({
|
openTrialModal(vipType);
|
||||||
title: t("vip.get_7_day_pro_trial"),
|
|
||||||
okText: t("vip.star_now"),
|
// const goGithub = () => {
|
||||||
onOk() {
|
// window.open("https://github.com/certd/certd/");
|
||||||
goGithub();
|
// };
|
||||||
openTrialModal(vipType);
|
|
||||||
},
|
// modal.confirm({
|
||||||
width: 600,
|
// title: t("vip.get_7_day_pro_trial"),
|
||||||
content: () => {
|
// okText: t("vip.star_now"),
|
||||||
return (
|
// onOk() {
|
||||||
<div class="flex mt-10 mb-10">
|
// goGithub();
|
||||||
<div>{t("vip.please_help_star")}</div>
|
// openTrialModal(vipType);
|
||||||
<img class="ml-5" src="https://img.shields.io/github/stars/certd/certd?logo=github" />
|
// },
|
||||||
</div>
|
// width: 600,
|
||||||
);
|
// content: () => {
|
||||||
},
|
// return (
|
||||||
});
|
// <div class="flex mt-10 mb-10">
|
||||||
|
// <div>{t("vip.please_help_star")}</div>
|
||||||
|
// <img class="ml-5" src="https://img.shields.io/github/stars/certd/certd?logo=github" />
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
function openUpgrade() {
|
function openUpgrade() {
|
||||||
@@ -253,6 +219,7 @@ function openUpgrade() {
|
|||||||
throw new Error(t("vip.already_perpetual_plus"));
|
throw new Error(t("vip.already_perpetual_plus"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function goBuyPlusPage() {
|
function goBuyPlusPage() {
|
||||||
checkPerpetualPlus();
|
checkPerpetualPlus();
|
||||||
if (settingStore.isComm) {
|
if (settingStore.isComm) {
|
||||||
@@ -264,6 +231,7 @@ function openUpgrade() {
|
|||||||
}
|
}
|
||||||
window.open(goBuyUrl);
|
window.open(goBuyUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
function goBuyCommPage() {
|
function goBuyCommPage() {
|
||||||
checkPerpetualPlus();
|
checkPerpetualPlus();
|
||||||
if (settingStore.isPlus && !settingStore.isComm) {
|
if (settingStore.isPlus && !settingStore.isComm) {
|
||||||
@@ -278,75 +246,6 @@ function openUpgrade() {
|
|||||||
}
|
}
|
||||||
window.open(goBuyCommUrl);
|
window.open(goBuyCommUrl);
|
||||||
}
|
}
|
||||||
const vipTypeDefine = {
|
|
||||||
free: {
|
|
||||||
title: t("vip.basic_edition"),
|
|
||||||
desc: t("vip.community_free_version"),
|
|
||||||
type: "free",
|
|
||||||
icon: "lucide:package-open",
|
|
||||||
privilege: [t("vip.unlimited_certificate_application"), t("vip.unlimited_domain_count"), t("vip.unlimited_certificate_pipelines"), t("vip.common_deployment_plugins"), t("vip.email_webhook_notifications")],
|
|
||||||
},
|
|
||||||
plus: {
|
|
||||||
title: t("vip.professional_edition"),
|
|
||||||
desc: t("vip.open_source_support"),
|
|
||||||
type: "plus",
|
|
||||||
privilege: [t("vip.vip_group_priority"), t("vip.unlimited_site_certificate_monitoring"), t("vip.more_notification_methods"), t("vip.plugins_fully_open")],
|
|
||||||
trial: {
|
|
||||||
title: t("vip.click_to_get_7_day_trial"),
|
|
||||||
click: () => {
|
|
||||||
openStarModal("plus");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
icon: "stash:thumb-up",
|
|
||||||
priceText: productInfo.plus.priceText || `¥${productInfo.plus.price}/${t("vip.years")}`,
|
|
||||||
discountText: productInfo.plus.discountText || `¥${productInfo.plus.price3}/3${t("vip.years")}`,
|
|
||||||
tooltip: productInfo.plus.tooltip,
|
|
||||||
get() {
|
|
||||||
return (
|
|
||||||
<a-tooltip title={t("vip.afdian_support_vip")}>
|
|
||||||
<a-button size="small" type="primary" onClick={goBuyPlusPage}>
|
|
||||||
{t("vip.get_after_support")}
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
comm: {
|
|
||||||
title: t("vip.business_edition"),
|
|
||||||
desc: t("vip.commercial_license"),
|
|
||||||
type: "comm",
|
|
||||||
icon: "vaadin:handshake",
|
|
||||||
privilege: [t("vip.all_pro_privileges"), t("vip.allow_commercial_use_modify_logo_title"), t("vip.data_statistics"), t("vip.plugin_management"), t("vip.unlimited_multi_users"), t("vip.support_user_payment")],
|
|
||||||
priceText: productInfo.comm.priceText || `¥${productInfo.comm.price}/${t("vip.years")}`,
|
|
||||||
discountText: productInfo.comm.discountText || `¥${productInfo.comm.price3}/3${t("vip.years")}`,
|
|
||||||
tooltip: productInfo.comm.tooltip,
|
|
||||||
trial: {
|
|
||||||
title: t("vip.click_to_get_7_day_trial"),
|
|
||||||
click: () => {
|
|
||||||
openStarModal("comm");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
get() {
|
|
||||||
return (
|
|
||||||
<a-button size="small" type="primary" onClick={goBuyCommPage}>
|
|
||||||
{t("vip.buy")}
|
|
||||||
</a-button>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const manualActiveFlag = ref();
|
|
||||||
function showManualActivation() {
|
|
||||||
manualActiveFlag.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function goBindAccount() {
|
|
||||||
modalRef?.destroy();
|
|
||||||
router.push({
|
|
||||||
path: "/sys/account",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const modalRef = modal.success({
|
const modalRef = modal.success({
|
||||||
title,
|
title,
|
||||||
class: "vip-modal",
|
class: "vip-modal",
|
||||||
@@ -354,119 +253,7 @@ function openUpgrade() {
|
|||||||
okText: t("vip.close"),
|
okText: t("vip.close"),
|
||||||
width: 1100,
|
width: 1100,
|
||||||
content: () => {
|
content: () => {
|
||||||
let manualActiveBlock: any = "";
|
return <VipModalContent placeholder={placeholder} isPlus={isPlus} productInfo={productInfo} goBuyPlusPage={goBuyPlusPage} goBuyCommPage={goBuyCommPage} openStarModal={openStarModal} modalRef={modalRef} />;
|
||||||
if (manualActiveFlag.value) {
|
|
||||||
manualActiveBlock = (
|
|
||||||
<div>
|
|
||||||
<div class="mt-10">
|
|
||||||
<a-input-search class="w-2/6" v-model:value={formState.code} placeholder={placeholder} enter-button={t("vip.activate")} onSearch={doActive}></a-input-search>
|
|
||||||
</div>
|
|
||||||
<div class="mt-10">
|
|
||||||
{t("vip.activation_code_one_use")}
|
|
||||||
<a onClick={goAccount}>{t("vip.bind_account")}</a>,{t("vip.transfer_vip")}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const vipLabel = settingStore.vipLabel;
|
|
||||||
let plusInfo: any = "";
|
|
||||||
if (isPlus) {
|
|
||||||
plusInfo = (
|
|
||||||
<div class="mt-10 flex flex-col md:flex-row ">
|
|
||||||
<span class="mr-2">
|
|
||||||
{t("vip.current")} {vipLabel} {t("vip.activated_expire_time")} {settingStore.expiresText}
|
|
||||||
</span>
|
|
||||||
<a href="https://app.handfree.work/subject/#/page/detail/1" target="_blank">
|
|
||||||
{t("vip.learn_more")}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const slots = [];
|
|
||||||
for (const key in vipTypeDefine) {
|
|
||||||
// @ts-ignore
|
|
||||||
const item = vipTypeDefine[key];
|
|
||||||
const vipBlockClass = `vip-block ${key === settingStore.plusInfo.vipType ? "current" : ""}`;
|
|
||||||
slots.push(
|
|
||||||
<div class="w-full md:w-1/3 mb-4 p-5">
|
|
||||||
<div class={vipBlockClass}>
|
|
||||||
<h3 class="block-header ">
|
|
||||||
<span class="flex-o">{item.title}</span>
|
|
||||||
{item.trial && (
|
|
||||||
<span class="trial">
|
|
||||||
<a-tooltip title={item.trial.message}>
|
|
||||||
<a onClick={item.trial.click}>{item.trial.title}</a>
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</h3>
|
|
||||||
<div style="color:green" class="flex-o">
|
|
||||||
<fs-icon icon={item.icon} class="fs-16 flex-o" />
|
|
||||||
{item.desc}
|
|
||||||
</div>
|
|
||||||
<ul class="flex-1 privilege">
|
|
||||||
{item.privilege.map((p: string) => (
|
|
||||||
<li class="flex-baseline">
|
|
||||||
<fs-icon class="color-green" icon="ion:checkmark-sharp" />
|
|
||||||
{p}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
<div class="footer flex-between flex-vc">
|
|
||||||
<div class="price-show">
|
|
||||||
{item.priceText && (
|
|
||||||
<span class="flex">
|
|
||||||
<span class="-text">{item.priceText}</span>
|
|
||||||
<a-tooltip class="ml-5" title={item.discountText}>
|
|
||||||
<fs-icon class="pointer color-red" icon="ic:outline-discount"></fs-icon>
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{!item.priceText && (
|
|
||||||
<span>
|
|
||||||
<span class="price-text">{t("vip.freee")}</span>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div class="get-show">{item.get && <div>{item.get()}</div>}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div class="mt-10 mb-10 vip-active-modal">
|
|
||||||
{productInfo.notice && (
|
|
||||||
<div class="mb-10">
|
|
||||||
<a-alert type="error" message={productInfo.notice}></a-alert>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div class="vip-type-vs">
|
|
||||||
<a-row gutter={20}>{slots}</a-row>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<a href="https://certd.docmirror.cn/guide/donate/#相关问题" target="_blank">
|
|
||||||
{t("vip.question")}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="mt-10">
|
|
||||||
<div class=" w-100 flex-col md:flex-row ">
|
|
||||||
<span>{t("vip.site_id")}:</span>
|
|
||||||
<fs-copyable v-model={computedSiteId.value} class="mr-2"></fs-copyable>
|
|
||||||
<a onClick={goBindAccount}>{t("vip.not_effective")}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{plusInfo}
|
|
||||||
<div class="mt-10 ">
|
|
||||||
<span class="mr-2">{t("vip.have_activation_code")}</span>
|
|
||||||
<span>
|
|
||||||
<a onClick={showManualActivation}>{t("vip.manual_activation")}</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="mt-10">{manualActiveBlock}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -502,69 +289,4 @@ onMounted(() => {
|
|||||||
.text {
|
.text {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vip-active-modal {
|
|
||||||
.vip-block {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 10px;
|
|
||||||
border: 1px solid #eee;
|
|
||||||
border-radius: 5px;
|
|
||||||
height: 275px;
|
|
||||||
line-height: 24px;
|
|
||||||
|
|
||||||
.privilege {
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
//background-color: rgba(250, 237, 167, 0.79);
|
|
||||||
&.current {
|
|
||||||
border-color: green;
|
|
||||||
}
|
|
||||||
|
|
||||||
.block-header {
|
|
||||||
padding: 0px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.trial {
|
|
||||||
font-size: 12px;
|
|
||||||
font-wight: 400;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
padding-top: 5px;
|
|
||||||
margin-top: 0px;
|
|
||||||
border-top: 1px solid #eee;
|
|
||||||
|
|
||||||
.price-text {
|
|
||||||
font-size: 18px;
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
list-style-type: unset;
|
|
||||||
margin-left: 0px;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.color-green {
|
|
||||||
color: green;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vip-type-vs {
|
|
||||||
.privilege {
|
|
||||||
.fs-icon {
|
|
||||||
color: green;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fs-icon {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,434 @@
|
|||||||
|
<template>
|
||||||
|
<div class="mt-10 vip-active-modal">
|
||||||
|
<div v-if="todayOrderCount.enabled" class="order-count hidden md:flex">
|
||||||
|
<div v-for="(stage, index) in todayOrderCount.stages" :key="index" class="status-item" :class="{ 'status-show': TodayVipOrderCountRef.current === index }">
|
||||||
|
<div class="background">
|
||||||
|
<img :src="stage.bg" alt="" />
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col order-count-text weight-bold">
|
||||||
|
<div class="count-text ml-4 flex items-center">
|
||||||
|
<fs-icon icon="noto:fire" class="fs-20 mr-2"></fs-icon>
|
||||||
|
<template v-if="stage.vipTotal > 0">
|
||||||
|
<span> 已有 </span>
|
||||||
|
<span class="count-number color-red font-bold text-2xl ml-1 mr-1"> {{ stage.vipTotal }} </span> 位小伙伴赞助,
|
||||||
|
<span>
|
||||||
|
{{ stage.title }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<span> 今日赞助 </span>
|
||||||
|
<span class="count-number color-red font-bold text-2xl ml-1 mr-1"> {{ stage.orderCount }} </span> 人,
|
||||||
|
<span>
|
||||||
|
{{ stage.title }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="productInfo.notice" class="mt-10">
|
||||||
|
<a-alert type="error" :message="productInfo.notice"></a-alert>
|
||||||
|
</div>
|
||||||
|
<div class="vip-type-vs mt-10">
|
||||||
|
<a-row :gutter="20">
|
||||||
|
<div v-for="(item, key) in vipTypeDefine" :key="key" class="w-full md:w-1/3 mb-4 p-5">
|
||||||
|
<div :class="`vip-block ${key === settingStore.plusInfo.vipType ? 'current' : ''}`">
|
||||||
|
<h3 class="block-header">
|
||||||
|
<span class="flex-o">{{ item.title }}</span>
|
||||||
|
<span v-if="item.trial" class="trial">
|
||||||
|
<a-tooltip :title="item.trial.message">
|
||||||
|
<a @click="item.trial.click">{{ item.trial.title }}</a>
|
||||||
|
</a-tooltip>
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
<div style="color: green" class="flex-o">
|
||||||
|
<fs-icon :icon="item.icon" class="fs-16 flex-o" />
|
||||||
|
{{ item.desc }}
|
||||||
|
</div>
|
||||||
|
<ul class="flex-1 privilege">
|
||||||
|
<li v-for="p in item.privilege" :key="p" class="flex-baseline">
|
||||||
|
<fs-icon class="color-green" icon="ion:checkmark-sharp" />
|
||||||
|
{{ p }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="footer flex-between flex-vc">
|
||||||
|
<div class="price-show">
|
||||||
|
<span v-if="item.priceText" class="flex">
|
||||||
|
<span class="-text">{{ item.priceText }}</span>
|
||||||
|
<a-tooltip class="ml-5" :title="item.discountText">
|
||||||
|
<fs-icon class="pointer color-red" icon="ic:outline-discount"></fs-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
<span class="price-text">{{ t("vip.freee") }}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="get-show">
|
||||||
|
<template v-if="item.type === 'plus'">
|
||||||
|
<a-tooltip :title="t('vip.afdian_support_vip')">
|
||||||
|
<a-button size="small" type="primary" @click="goBuyPlusPage">
|
||||||
|
{{ t("vip.get_after_support") }}
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="item.type === 'comm'">
|
||||||
|
<a-button size="small" type="primary" @click="goBuyCommPage">
|
||||||
|
{{ t("vip.buy") }}
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-row>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="https://certd.docmirror.cn/guide/donate/#相关问题" target="_blank">
|
||||||
|
{{ t("vip.question") }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="mt-10">
|
||||||
|
<div class="w-100 flex-col md:flex-row">
|
||||||
|
<span>{{ t("vip.site_id") }}:</span>
|
||||||
|
<fs-copyable v-model="computedSiteId" class="mr-2"></fs-copyable>
|
||||||
|
<a @click="goBindAccount">{{ t("vip.not_effective") }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="isPlus" class="mt-10 flex flex-col md:flex-row">
|
||||||
|
<span class="mr-2"> {{ t("vip.current") }} {{ vipLabel }} {{ t("vip.activated_expire_time") }} {{ settingStore.expiresText }} </span>
|
||||||
|
<a href="https://app.handfree.work/subject/#/page/detail/1" target="_blank">
|
||||||
|
{{ t("vip.learn_more") }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="mt-10">
|
||||||
|
<span class="mr-2">{{ t("vip.have_activation_code") }}</span>
|
||||||
|
<span>
|
||||||
|
<a @click="showManualActivation">{{ t("vip.manual_activation") }}</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="manualActiveFlag" class="mt-10">
|
||||||
|
<div class="mt-10">
|
||||||
|
<a-input-search v-model:value="formState.code" class="w-2/6" :placeholder="placeholder" :enter-button="t('vip.activate')" @search="doActive"></a-input-search>
|
||||||
|
</div>
|
||||||
|
<div class="mt-10">
|
||||||
|
{{ t("vip.activation_code_one_use") }}
|
||||||
|
<a @click="goAccount">{{ t("vip.bind_account") }}</a
|
||||||
|
>,{{ t("vip.transfer_vip") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { message, Modal } from "ant-design-vue";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { computed, nextTick, onMounted, onUnmounted, reactive, Ref, ref } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import * as api from "./api";
|
||||||
|
import { useSettingStore } from "/@/store/settings";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const router = useRouter();
|
||||||
|
const settingStore = useSettingStore();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
placeholder: string;
|
||||||
|
isPlus: boolean;
|
||||||
|
productInfo: any;
|
||||||
|
goBuyPlusPage: () => void;
|
||||||
|
goBuyCommPage: () => void;
|
||||||
|
openStarModal: (vipType: string) => void;
|
||||||
|
modalRef: any;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const formState = reactive({
|
||||||
|
code: "",
|
||||||
|
inviteCode: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
async function doActive() {
|
||||||
|
if (!formState.code) {
|
||||||
|
message.error(t("vip.enterCode"));
|
||||||
|
throw new Error(t("vip.enterCode"));
|
||||||
|
}
|
||||||
|
const res = await api.doActive(formState);
|
||||||
|
if (res) {
|
||||||
|
await settingStore.init();
|
||||||
|
const vipLabel = settingStore.vipLabel;
|
||||||
|
Modal.success({
|
||||||
|
title: t("vip.successTitle"),
|
||||||
|
content: t("vip.successContent", {
|
||||||
|
vipLabel,
|
||||||
|
expireDate: dayjs(settingStore.plusInfo.expireTime).format("YYYY-MM-DD"),
|
||||||
|
}),
|
||||||
|
onOk() {
|
||||||
|
if (!(settingStore.installInfo.bindUserId > 0)) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: t("vip.bindAccountTitle"),
|
||||||
|
content: t("vip.bindAccountContent"),
|
||||||
|
onOk() {
|
||||||
|
router.push("/sys/account");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const vipLabel = computed(() => settingStore.vipLabel);
|
||||||
|
const computedSiteId = computed(() => settingStore.installInfo?.siteId);
|
||||||
|
|
||||||
|
const manualActiveFlag = ref(false);
|
||||||
|
|
||||||
|
function showManualActivation() {
|
||||||
|
manualActiveFlag.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function goAccount() {
|
||||||
|
props.modalRef?.destroy();
|
||||||
|
router.push("/sys/account");
|
||||||
|
}
|
||||||
|
|
||||||
|
function goBindAccount() {
|
||||||
|
props.modalRef?.destroy();
|
||||||
|
router.push({
|
||||||
|
path: "/sys/account",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const vipTypeDefine: any = {
|
||||||
|
free: {
|
||||||
|
title: t("vip.basic_edition"),
|
||||||
|
desc: t("vip.community_free_version"),
|
||||||
|
type: "free",
|
||||||
|
icon: "lucide:package-open",
|
||||||
|
privilege: [t("vip.unlimited_certificate_application"), t("vip.unlimited_domain_count"), t("vip.unlimited_certificate_pipelines"), t("vip.common_deployment_plugins"), t("vip.email_webhook_notifications")],
|
||||||
|
},
|
||||||
|
plus: {
|
||||||
|
title: t("vip.professional_edition"),
|
||||||
|
desc: t("vip.open_source_support"),
|
||||||
|
type: "plus",
|
||||||
|
privilege: [t("vip.vip_group_priority"), t("vip.unlimited_site_certificate_monitoring"), t("vip.more_notification_methods"), t("vip.plugins_fully_open")],
|
||||||
|
trial: {
|
||||||
|
title: t("vip.click_to_get_7_day_trial"),
|
||||||
|
click: () => {
|
||||||
|
props.openStarModal("plus");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
icon: "stash:thumb-up",
|
||||||
|
priceText: props.productInfo.plus.priceText || `¥${props.productInfo.plus.price}/${t("vip.years")}`,
|
||||||
|
discountText: props.productInfo.plus.discountText || `¥${props.productInfo.plus.price3}/3${t("vip.years")}`,
|
||||||
|
tooltip: props.productInfo.plus.tooltip,
|
||||||
|
},
|
||||||
|
comm: {
|
||||||
|
title: t("vip.business_edition"),
|
||||||
|
desc: t("vip.commercial_license"),
|
||||||
|
type: "comm",
|
||||||
|
icon: "vaadin:handshake",
|
||||||
|
privilege: [t("vip.all_pro_privileges"), t("vip.allow_commercial_use_modify_logo_title"), t("vip.data_statistics"), t("vip.plugin_management"), t("vip.unlimited_multi_users"), t("vip.support_user_payment")],
|
||||||
|
priceText: props.productInfo.comm.priceText || `¥${props.productInfo.comm.price}/${t("vip.years")}`,
|
||||||
|
discountText: props.productInfo.comm.discountText || `¥${props.productInfo.comm.price3}/3${t("vip.years")}`,
|
||||||
|
tooltip: props.productInfo.comm.tooltip,
|
||||||
|
trial: {
|
||||||
|
title: t("vip.click_to_get_7_day_trial"),
|
||||||
|
click: () => {
|
||||||
|
props.openStarModal("comm");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const TodayVipOrderCountRef: Ref = ref({ enabled: false, current: 0, stages: [] });
|
||||||
|
|
||||||
|
async function getTodayVipOrderCount() {
|
||||||
|
const res = await api.getTodayVipOrderCount();
|
||||||
|
if (res) {
|
||||||
|
TodayVipOrderCountRef.value = res;
|
||||||
|
TodayVipOrderCountRef.value.current = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const todayOrderCount = computed(() => {
|
||||||
|
const countInfo = TodayVipOrderCountRef.value;
|
||||||
|
const enabled = countInfo?.enabled || false;
|
||||||
|
const orderCount = countInfo?.orderCount || 0;
|
||||||
|
for (const stage of countInfo?.stages) {
|
||||||
|
stage.orderCount = stage.countGe || 0;
|
||||||
|
}
|
||||||
|
const lastStage = countInfo?.stages?.[countInfo?.stages?.length - 1] || {};
|
||||||
|
lastStage.orderCount = orderCount;
|
||||||
|
|
||||||
|
const stages: any = [];
|
||||||
|
stages.push({
|
||||||
|
title: countInfo.title,
|
||||||
|
vipTotal: countInfo?.vipTotal || 0,
|
||||||
|
orderCount: orderCount,
|
||||||
|
bg: lastStage.bg,
|
||||||
|
});
|
||||||
|
if (lastStage.orderCount > 0) {
|
||||||
|
stages.push(lastStage);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
enabled: enabled,
|
||||||
|
stages: stages,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
async function scrollOrderCount() {
|
||||||
|
const stages = todayOrderCount.value.stages;
|
||||||
|
if (stages.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let index = 0;
|
||||||
|
const doScroll = () => {
|
||||||
|
TodayVipOrderCountRef.value.current = index;
|
||||||
|
index++;
|
||||||
|
if (index >= stages.length) {
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
doScroll();
|
||||||
|
scrollOrderCountIntervalRef.value = setInterval(doScroll, 7000);
|
||||||
|
}
|
||||||
|
|
||||||
|
const scrollOrderCountIntervalRef: Ref = ref(null);
|
||||||
|
onMounted(async () => {
|
||||||
|
await getTodayVipOrderCount();
|
||||||
|
await nextTick();
|
||||||
|
await scrollOrderCount();
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearInterval(scrollOrderCountIntervalRef.value);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.vip-active-modal {
|
||||||
|
.order-count {
|
||||||
|
height: 80px;
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid #fee2c5;
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
|
.background {
|
||||||
|
border: 0px;
|
||||||
|
border-radius: 5px;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-count-text {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 2;
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
/* 左至右渐变*/
|
||||||
|
background: linear-gradient(to right, rgba(255, 217, 167, 0.5), rgba(255, 255, 255, 0));
|
||||||
|
|
||||||
|
.count-text {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #ff6600;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.count-number {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-item {
|
||||||
|
opacity: 0;
|
||||||
|
transition: all 0.7s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-show {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vip-block {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
border-radius: 5px;
|
||||||
|
height: 275px;
|
||||||
|
line-height: 24px;
|
||||||
|
|
||||||
|
.privilege {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.current {
|
||||||
|
border-color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block-header {
|
||||||
|
padding: 0px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.trial {
|
||||||
|
font-size: 12px;
|
||||||
|
font-wight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
padding-top: 5px;
|
||||||
|
margin-top: 0px;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
|
||||||
|
.price-text {
|
||||||
|
font-size: 18px;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style-type: unset;
|
||||||
|
margin-left: 0px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-green {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vip-type-vs {
|
||||||
|
.privilege {
|
||||||
|
.fs-icon {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-icon {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -35,7 +35,13 @@ const menus = computed(() => [
|
|||||||
|
|
||||||
const avatar = computed(() => {
|
const avatar = computed(() => {
|
||||||
const avt = userStore.getUserInfo?.avatar;
|
const avt = userStore.getUserInfo?.avatar;
|
||||||
return avt ? `/api/basic/file/download?key=${avt}` : "";
|
if (!avt) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (avt.startsWith("http")) {
|
||||||
|
return avt;
|
||||||
|
}
|
||||||
|
return `/api/basic/file/download?key=${avt}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
async function handleLogout() {
|
async function handleLogout() {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="userLayout" :class="['user-layout-wrapper']">
|
<div id="userLayout" :class="['user-layout-wrapper']">
|
||||||
<div class="login-container flex justify-start">
|
<div class="login-container flex justify-start dark:background-[#141414]">
|
||||||
<div class="user-layout-content flex-col justify-start">
|
<div class="user-layout-content flex-col justify-start">
|
||||||
<div class="top flex flex-col items-center justify-start">
|
<div class="top flex flex-col items-center justify-start">
|
||||||
<div class="header flex flex-row items-center">
|
<div class="header flex flex-row items-center">
|
||||||
@@ -59,6 +59,14 @@ const sysPublic: Ref<SysPublicSetting> = computed(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
.dark {
|
||||||
|
.login-container {
|
||||||
|
background: #141414 !important;
|
||||||
|
.desc {
|
||||||
|
color: rgba(227, 227, 227, 0.45) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#userLayout.user-layout-wrapper {
|
#userLayout.user-layout-wrapper {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ export default {
|
|||||||
updateTime: "Update Time",
|
updateTime: "Update Time",
|
||||||
triggerType: "Trigger Type",
|
triggerType: "Trigger Type",
|
||||||
pipelineId: "Pipeline Id",
|
pipelineId: "Pipeline Id",
|
||||||
|
nextRunTime: "Next Run Time",
|
||||||
},
|
},
|
||||||
|
|
||||||
pi: {
|
pi: {
|
||||||
@@ -511,6 +512,7 @@ export default {
|
|||||||
selectRecordFirst: "Please select records first",
|
selectRecordFirst: "Please select records first",
|
||||||
subdomainHosted: "Hosted Subdomain",
|
subdomainHosted: "Hosted Subdomain",
|
||||||
subdomainHelpText: "If you don't understand what subdomain hosting is,Do not set it randomly, as it may result in the inability to apply for the certificate. please refer to the documentation ",
|
subdomainHelpText: "If you don't understand what subdomain hosting is,Do not set it randomly, as it may result in the inability to apply for the certificate. please refer to the documentation ",
|
||||||
|
subdomainHelpSupportStart: "Supports * wildcard, indicating that all subdomains of the domain are hosted (free subdomains)",
|
||||||
subdomainManagement: "Subdomain Management",
|
subdomainManagement: "Subdomain Management",
|
||||||
isDisabled: "Is Disabled",
|
isDisabled: "Is Disabled",
|
||||||
enabled: "Enabled",
|
enabled: "Enabled",
|
||||||
@@ -688,6 +690,7 @@ export default {
|
|||||||
password: "Password",
|
password: "Password",
|
||||||
pleaseEnterPassword: "Please enter password",
|
pleaseEnterPassword: "Please enter password",
|
||||||
qqEmailAuthCodeHelper: "If using QQ email, get an authorization code in QQ email settings as the password",
|
qqEmailAuthCodeHelper: "If using QQ email, get an authorization code in QQ email settings as the password",
|
||||||
|
senderEmailHelper: "You can use the format: Name<Email> to set the sender name, e.g.: autossl<certd@example.com>",
|
||||||
senderEmail: "Sender Email",
|
senderEmail: "Sender Email",
|
||||||
pleaseEnterSenderEmail: "Please enter sender email",
|
pleaseEnterSenderEmail: "Please enter sender email",
|
||||||
useSsl: "Use SSL",
|
useSsl: "Use SSL",
|
||||||
@@ -784,6 +787,7 @@ export default {
|
|||||||
captchaSetting: "Captcha Setting",
|
captchaSetting: "Captcha Setting",
|
||||||
pipelineSetting: "Pipeline Settings",
|
pipelineSetting: "Pipeline Settings",
|
||||||
oauthSetting: "OAuth2 Settings",
|
oauthSetting: "OAuth2 Settings",
|
||||||
|
networkSetting: "Network Settings",
|
||||||
|
|
||||||
showRunStrategy: "Show RunStrategy",
|
showRunStrategy: "Show RunStrategy",
|
||||||
showRunStrategyHelper: "Allow modify the run strategy of the task",
|
showRunStrategyHelper: "Allow modify the run strategy of the task",
|
||||||
@@ -835,6 +839,11 @@ export default {
|
|||||||
notice: "System Notice",
|
notice: "System Notice",
|
||||||
noticeHelper: "System notice, will be displayed on the login page",
|
noticeHelper: "System notice, will be displayed on the login page",
|
||||||
noticePlaceholder: "System notice",
|
noticePlaceholder: "System notice",
|
||||||
|
|
||||||
|
reverseProxy: "Reverse Proxy List",
|
||||||
|
reverseProxyHelper: "Reverse proxy for ACME address, used when applying for certificate",
|
||||||
|
reverseProxyPlaceholder: "http://le.px.handfree.work",
|
||||||
|
reverseProxyEmpty: "No reverse proxy list configured",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
modal: {
|
modal: {
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ export default {
|
|||||||
},
|
},
|
||||||
customPipeline: "自定义流水线",
|
customPipeline: "自定义流水线",
|
||||||
createCertdPipeline: "创建证书流水线",
|
createCertdPipeline: "创建证书流水线",
|
||||||
commercialCertHosting: "商用证书托管",
|
commercialCertHosting: "已有证书托管",
|
||||||
tooltip: {
|
tooltip: {
|
||||||
manualUploadOwnCert: "手动上传自有证书,执行自动部署",
|
manualUploadOwnCert: "手动上传自有证书,执行自动部署",
|
||||||
noAutoApplyCommercialCert: "并不能自动申请商业证书",
|
noAutoApplyCommercialCert: "并不能自动申请商业证书",
|
||||||
@@ -167,6 +167,7 @@ export default {
|
|||||||
updateTime: "更新时间",
|
updateTime: "更新时间",
|
||||||
triggerType: "触发类型",
|
triggerType: "触发类型",
|
||||||
pipelineId: "流水线Id",
|
pipelineId: "流水线Id",
|
||||||
|
nextRunTime: "下次运行时间",
|
||||||
},
|
},
|
||||||
pi: {
|
pi: {
|
||||||
validTime: "流水线有效期",
|
validTime: "流水线有效期",
|
||||||
@@ -521,6 +522,7 @@ export default {
|
|||||||
selectRecordFirst: "请先勾选记录",
|
selectRecordFirst: "请先勾选记录",
|
||||||
subdomainHosted: "托管的子域名",
|
subdomainHosted: "托管的子域名",
|
||||||
subdomainHelpText: "如果您不理解什么是子域托管,请不要随意设置(可能导致证书无法申请,以前设置过的cname记录也需要重新配置),可以参考文档",
|
subdomainHelpText: "如果您不理解什么是子域托管,请不要随意设置(可能导致证书无法申请,以前设置过的cname记录也需要重新配置),可以参考文档",
|
||||||
|
subdomainHelpSupportStart: "支持*号通配符,表示该域名下的子域名都是托管的(免费子域名)",
|
||||||
subdomainManagement: "子域管理",
|
subdomainManagement: "子域管理",
|
||||||
isDisabled: "是否禁用",
|
isDisabled: "是否禁用",
|
||||||
enabled: "启用",
|
enabled: "启用",
|
||||||
@@ -699,6 +701,7 @@ export default {
|
|||||||
password: "密码",
|
password: "密码",
|
||||||
pleaseEnterPassword: "请输入密码",
|
pleaseEnterPassword: "请输入密码",
|
||||||
qqEmailAuthCodeHelper: "如果是qq邮箱,需要到qq邮箱的设置里面申请授权码作为密码",
|
qqEmailAuthCodeHelper: "如果是qq邮箱,需要到qq邮箱的设置里面申请授权码作为密码",
|
||||||
|
senderEmailHelper: "您可以使用 名称<邮箱> 的格式,来修改发件人名称,例如: autossl<certd@example.com>",
|
||||||
senderEmail: "发件邮箱",
|
senderEmail: "发件邮箱",
|
||||||
pleaseEnterSenderEmail: "请输入发件邮箱",
|
pleaseEnterSenderEmail: "请输入发件邮箱",
|
||||||
useSsl: "是否ssl",
|
useSsl: "是否ssl",
|
||||||
@@ -791,6 +794,7 @@ export default {
|
|||||||
captchaSetting: "验证码设置",
|
captchaSetting: "验证码设置",
|
||||||
pipelineSetting: "流水线设置",
|
pipelineSetting: "流水线设置",
|
||||||
oauthSetting: "第三方登录",
|
oauthSetting: "第三方登录",
|
||||||
|
networkSetting: "网络设置",
|
||||||
|
|
||||||
showRunStrategy: "显示运行策略选择",
|
showRunStrategy: "显示运行策略选择",
|
||||||
showRunStrategyHelper: "任务设置中是否允许选择运行策略",
|
showRunStrategyHelper: "任务设置中是否允许选择运行策略",
|
||||||
@@ -850,6 +854,11 @@ export default {
|
|||||||
notice: "系统公告",
|
notice: "系统公告",
|
||||||
noticeHelper: "系统公告,将在首页显示",
|
noticeHelper: "系统公告,将在首页显示",
|
||||||
noticePlaceholder: "系统公告",
|
noticePlaceholder: "系统公告",
|
||||||
|
|
||||||
|
reverseProxy: "反向代理列表",
|
||||||
|
reverseProxyHelper: "证书颁发机构ACME地址的反向代理,在申请证书时自动使用",
|
||||||
|
reverseProxyPlaceholder: "http://le.px.handfree.work",
|
||||||
|
reverseProxyEmpty: "未配置反向代理",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
modal: {
|
modal: {
|
||||||
|
|||||||
@@ -4,8 +4,16 @@ function isIpv6(d: string) {
|
|||||||
if (!d) {
|
if (!d) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const isIPv6Regex = /^([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{1,4}$|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4})$/gm;
|
// const isIPv6Regex = /^([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{1,4}$|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4})$/gm;
|
||||||
return isIPv6Regex.test(d);
|
// return isIPv6Regex.test(d);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 尝试构造URL,用IPv6作为hostname
|
||||||
|
new URL(`http://[${d}]`);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function isIpv4(d: string) {
|
function isIpv4(d: string) {
|
||||||
if (!d) {
|
if (!d) {
|
||||||
|
|||||||
@@ -101,6 +101,14 @@ function setupAccessGuard(router: Router) {
|
|||||||
return r.meta?.auth || r.meta?.permission;
|
return r.meta?.auth || r.meta?.permission;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (to.path === LOGIN_PATH && accessStore.accessToken) {
|
||||||
|
return {
|
||||||
|
path: DEFAULT_HOME_PATH,
|
||||||
|
// 携带当前跳转的页面,登录后重新跳转该页面
|
||||||
|
replace: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (!needAuth) {
|
if (!needAuth) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export type PlusInfo = {
|
|||||||
expireTime?: number;
|
expireTime?: number;
|
||||||
isPlus: boolean;
|
isPlus: boolean;
|
||||||
isComm?: boolean;
|
isComm?: boolean;
|
||||||
|
message?: string;
|
||||||
};
|
};
|
||||||
export type SysPublicSetting = {
|
export type SysPublicSetting = {
|
||||||
registerEnabled?: boolean;
|
registerEnabled?: boolean;
|
||||||
@@ -92,6 +93,7 @@ export type SuiteSetting = {
|
|||||||
export type SysPrivateSetting = {
|
export type SysPrivateSetting = {
|
||||||
httpProxy?: string;
|
httpProxy?: string;
|
||||||
httpsProxy?: string;
|
httpsProxy?: string;
|
||||||
|
reverseProxies?: any;
|
||||||
dnsResultOrder?: string;
|
dnsResultOrder?: string;
|
||||||
commonCnameEnabled?: boolean;
|
commonCnameEnabled?: boolean;
|
||||||
// 同一个用户同时最大运行流水线数量
|
// 同一个用户同时最大运行流水线数量
|
||||||
@@ -107,6 +109,8 @@ export type SysPrivateSetting = {
|
|||||||
};
|
};
|
||||||
export type SysInstallInfo = {
|
export type SysInstallInfo = {
|
||||||
siteId: string;
|
siteId: string;
|
||||||
|
bindUrl?: string;
|
||||||
|
bindUrl2?: string;
|
||||||
};
|
};
|
||||||
export type MenuItem = {
|
export type MenuItem = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Modal, notification } from "ant-design-vue";
|
import { notification } from "ant-design-vue";
|
||||||
import * as basicApi from "./api.basic";
|
import * as basicApi from "./api.basic";
|
||||||
import { AppInfo, HeaderMenus, PlusInfo, SiteEnv, SiteInfo, SuiteSetting, SysInstallInfo, SysPublicSetting } from "./api.basic";
|
import { AppInfo, HeaderMenus, PlusInfo, SiteEnv, SiteInfo, SuiteSetting, SysInstallInfo, SysPublicSetting } from "./api.basic";
|
||||||
import { useUserStore } from "../user";
|
import { useUserStore } from "../user";
|
||||||
@@ -20,6 +20,7 @@ export interface SettingState {
|
|||||||
installTime?: number;
|
installTime?: number;
|
||||||
bindUserId?: number;
|
bindUserId?: number;
|
||||||
bindUrl?: string;
|
bindUrl?: string;
|
||||||
|
bindUrl2?: string;
|
||||||
accountServerBaseUrl?: string;
|
accountServerBaseUrl?: string;
|
||||||
appKey?: string;
|
appKey?: string;
|
||||||
};
|
};
|
||||||
@@ -153,9 +154,11 @@ export const useSettingStore = defineStore({
|
|||||||
if (this.plusInfo?.expireTime === -1) {
|
if (this.plusInfo?.expireTime === -1) {
|
||||||
return "永久";
|
return "永久";
|
||||||
}
|
}
|
||||||
|
//@ts-ignore
|
||||||
return dayjs(this.plusInfo?.expireTime).format("YYYY-MM-DD");
|
return dayjs(this.plusInfo?.expireTime).format("YYYY-MM-DD");
|
||||||
},
|
},
|
||||||
isForever() {
|
isForever() {
|
||||||
|
//@ts-ignore
|
||||||
return this.isPlus && this.plusInfo?.expireTime === -1;
|
return this.isPlus && this.plusInfo?.expireTime === -1;
|
||||||
},
|
},
|
||||||
vipLabel(): string {
|
vipLabel(): string {
|
||||||
@@ -251,9 +254,17 @@ export const useSettingStore = defineStore({
|
|||||||
url = url.split("#")[0];
|
url = url.split("#")[0];
|
||||||
return url;
|
return url;
|
||||||
},
|
},
|
||||||
async doBindUrl() {
|
async doBindUrl(key: string = "url") {
|
||||||
const url = this.getBaseUrl();
|
const url = this.installInfo.bindUrl;
|
||||||
await basicApi.bindUrl({ url });
|
const url2 = this.installInfo.bindUrl2;
|
||||||
|
|
||||||
|
const thisUrl = this.getBaseUrl();
|
||||||
|
const form = {
|
||||||
|
url,
|
||||||
|
url2,
|
||||||
|
[key]: thisUrl,
|
||||||
|
};
|
||||||
|
await basicApi.bindUrl(form);
|
||||||
await this.loadSysSettings();
|
await this.loadSysSettings();
|
||||||
},
|
},
|
||||||
async checkUrlBound() {
|
async checkUrlBound() {
|
||||||
@@ -262,24 +273,64 @@ export const useSettingStore = defineStore({
|
|||||||
if (!userStore.isAdmin) {
|
if (!userStore.isAdmin) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const event: any = { ModalRef: null };
|
||||||
|
mitter.emit("getModal", event);
|
||||||
|
const Modal = event.ModalRef;
|
||||||
|
let modalRef: any = null;
|
||||||
const bindUrl = this.installInfo.bindUrl;
|
const bindUrl = this.installInfo.bindUrl;
|
||||||
|
const bindUrl2 = this.installInfo.bindUrl2;
|
||||||
|
|
||||||
|
const doBindRequest = async (key: string) => {
|
||||||
|
await this.doBindUrl(key);
|
||||||
|
if (modalRef) {
|
||||||
|
modalRef.destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (!bindUrl) {
|
if (!bindUrl) {
|
||||||
//绑定url
|
//绑定url
|
||||||
await this.doBindUrl();
|
await this.doBindUrl("url");
|
||||||
} else {
|
} else {
|
||||||
//检查当前url 是否与绑定的url一致
|
//检查当前url 是否与绑定的url一致
|
||||||
const url = window.location.href;
|
const url = window.location.href;
|
||||||
if (!url.startsWith(bindUrl)) {
|
if (!url.startsWith(bindUrl) && !url.startsWith(bindUrl2)) {
|
||||||
Modal.confirm({
|
modalRef = Modal.warning({
|
||||||
title: "URL地址有变化",
|
title: "URL地址未绑定,是否绑定此地址?",
|
||||||
content: "以后都用这个新地址访问本系统吗?",
|
width: 500,
|
||||||
onOk: async () => {
|
keyboard: false,
|
||||||
await this.doBindUrl();
|
content: () => {
|
||||||
|
return (
|
||||||
|
<div class="p-4">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span>
|
||||||
|
绑定地址1:
|
||||||
|
<a-tag color="green">{bindUrl || "未占用"}</a-tag>
|
||||||
|
</span>
|
||||||
|
<a-button type="primary" onClick={() => doBindRequest("url")}>
|
||||||
|
绑定到地址1
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between mt-3">
|
||||||
|
<span>
|
||||||
|
绑定地址2:
|
||||||
|
<a-tag color="green">{bindUrl2 || "未占用"}</a-tag>
|
||||||
|
</span>
|
||||||
|
<a-button type="primary" onClick={() => doBindRequest("url2")}>
|
||||||
|
绑定到地址2
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
},
|
},
|
||||||
okText: "是的,继续",
|
onOk: async () => {
|
||||||
cancelText: "不是,回到原来的地址",
|
// await this.doBindUrl();
|
||||||
|
window.location.href = bindUrl;
|
||||||
|
},
|
||||||
|
okButtonProps: {
|
||||||
|
danger: true,
|
||||||
|
},
|
||||||
|
okText: "不,回到原来的地址",
|
||||||
|
cancelText: "不,回到原来的地址",
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
window.location.href = bindUrl;
|
window.location.href = bindUrl;
|
||||||
},
|
},
|
||||||
@@ -117,3 +117,4 @@ span.fs-icon-svg {
|
|||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
@import "./fix-windicss.less";
|
@import "./fix-windicss.less";
|
||||||
@import "./antdv4.less";
|
@import "./antdv4.less";
|
||||||
@import "./certd.less";
|
@import "./certd.less";
|
||||||
|
@import "./dark.less";
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
@@ -320,10 +321,25 @@ h6 {
|
|||||||
font-size: 16px !important;
|
font-size: 16px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fs-18 {
|
||||||
|
font-size: 18px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fs-20 {
|
||||||
|
font-size: 20px !important;
|
||||||
|
}
|
||||||
|
.fs-24 {
|
||||||
|
font-size: 24px !important;
|
||||||
|
}
|
||||||
|
.fs-26 {
|
||||||
|
font-size: 26px !important;
|
||||||
|
}
|
||||||
.fs-28 {
|
.fs-28 {
|
||||||
font-size: 28px !important;
|
font-size: 28px !important;
|
||||||
}
|
}
|
||||||
|
.fs-32 {
|
||||||
|
font-size: 32px !important;
|
||||||
|
}
|
||||||
.w-50\% {
|
.w-50\% {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
@@ -357,6 +373,13 @@ h6 {
|
|||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
|
&.cd-table-none-border {
|
||||||
|
border: 0 !important;
|
||||||
|
td, th {
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.fs-loading {
|
.fs-loading {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
@@ -455,4 +478,16 @@ h6 {
|
|||||||
background: #ffecb3;
|
background: #ffecb3;
|
||||||
color: #f57c00;
|
color: #f57c00;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-tag{
|
||||||
|
.fs-icon{
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.hidden-important {
|
||||||
|
display: none !important;
|
||||||
|
visibility: hidden !important;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
.dark{
|
||||||
|
.fs-page-header{
|
||||||
|
.title {
|
||||||
|
color: #d5d5d5 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,8 +18,8 @@
|
|||||||
-webkit-border-radius: 4em;
|
-webkit-border-radius: 4em;
|
||||||
-moz-border-radius: 4em;
|
-moz-border-radius: 4em;
|
||||||
border-radius: 4em;
|
border-radius: 4em;
|
||||||
background-color: #b3b3b3;
|
background-color: #757575;
|
||||||
box-shadow: 0px 1px 1px #eee inset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb:hover {
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import type { RouteRecordNormalized } from "vue-router";
|
import type { RouteRecordNormalized } from "vue-router";
|
||||||
|
|
||||||
import { useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
|
|
||||||
import { isHttpUrl, openRouteInNewWindow, openWindow } from "../../../utils";
|
import { isHttpUrl, openRouteInNewWindow, openWindow } from "../../../utils";
|
||||||
|
|
||||||
function useNavigation() {
|
function useNavigation() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const route1 = useRoute();
|
||||||
const routes = router.getRoutes();
|
const routes = router.getRoutes();
|
||||||
|
|
||||||
const routeMetaMap = new Map<string, RouteRecordNormalized>();
|
const routeMetaMap = new Map<string, RouteRecordNormalized>();
|
||||||
@@ -15,6 +16,9 @@ function useNavigation() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const navigation = async (path: string) => {
|
const navigation = async (path: string) => {
|
||||||
|
if (route1.path === path) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const route = routeMetaMap.get(path);
|
const route = routeMetaMap.get(path);
|
||||||
const { openInNewWindow = false, query = {} as any } = route?.meta ?? {};
|
const { openInNewWindow = false, query = {} as any } = route?.meta ?? {};
|
||||||
if (isHttpUrl(path)) {
|
if (isHttpUrl(path)) {
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ const defaultPreferences: Preferences = {
|
|||||||
colorPrimary: "hsl(212 100% 45%)",
|
colorPrimary: "hsl(212 100% 45%)",
|
||||||
colorSuccess: "hsl(144 57% 58%)",
|
colorSuccess: "hsl(144 57% 58%)",
|
||||||
colorWarning: "hsl(42 84% 61%)",
|
colorWarning: "hsl(42 84% 61%)",
|
||||||
mode: "light",
|
mode: "auto",
|
||||||
radius: "0.5",
|
radius: "0.5",
|
||||||
semiDarkHeader: false,
|
semiDarkHeader: false,
|
||||||
semiDarkSidebar: false,
|
semiDarkSidebar: false,
|
||||||
|
|||||||
@@ -27,8 +27,12 @@ function openWindow(url: string, options: OpenWindowOptions = {}): void {
|
|||||||
*/
|
*/
|
||||||
function openRouteInNewWindow(path: string) {
|
function openRouteInNewWindow(path: string) {
|
||||||
const { hash, origin } = location;
|
const { hash, origin } = location;
|
||||||
|
let pathname = location.pathname;
|
||||||
|
if (pathname.endsWith("/")) {
|
||||||
|
pathname = pathname.slice(0, -1);
|
||||||
|
}
|
||||||
const fullPath = path.startsWith("/") ? path : `/${path}`;
|
const fullPath = path.startsWith("/") ? path : `/${path}`;
|
||||||
const url = `${origin}${hash ? "/#" : ""}${fullPath}`;
|
const url = `${origin}${pathname}${hash ? "/#" : ""}${fullPath}`;
|
||||||
openWindow(url, { target: "_blank" });
|
openWindow(url, { target: "_blank" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
|
|||||||
provide("get:plugin:type", () => {
|
provide("get:plugin:type", () => {
|
||||||
return "access";
|
return "access";
|
||||||
});
|
});
|
||||||
|
provide("getCurrentPluginDefine", () => {
|
||||||
|
return currentDefine;
|
||||||
|
});
|
||||||
const AccessTypeDictRef = dict({
|
const AccessTypeDictRef = dict({
|
||||||
url: "/pi/access/accessTypeDict",
|
url: "/pi/access/accessTypeDict",
|
||||||
});
|
});
|
||||||
@@ -64,7 +67,10 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
|
|||||||
set(form, key, column.value);
|
set(form, key, column.value);
|
||||||
}
|
}
|
||||||
//字段配置赋值
|
//字段配置赋值
|
||||||
columnsRef.value[key] = column;
|
if (columnsRef.value) {
|
||||||
|
columnsRef.value[key] = column;
|
||||||
|
}
|
||||||
|
|
||||||
console.log("form", columnsRef.value);
|
console.log("form", columnsRef.value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import { ColumnCompositionProps, compute, dict } from "@fast-crud/fast-crud";
|
import { ColumnCompositionProps, compute, dict } from "@fast-crud/fast-crud";
|
||||||
|
import { Modal } from "ant-design-vue";
|
||||||
|
import { forEach, get, merge, set } from "lodash-es";
|
||||||
import { computed, provide, ref, toRef } from "vue";
|
import { computed, provide, ref, toRef } from "vue";
|
||||||
import { useReference } from "/@/use/use-refrence";
|
import { useReference } from "/@/use/use-refrence";
|
||||||
import { forEach, get, merge, set } from "lodash-es";
|
|
||||||
import { Modal } from "ant-design-vue";
|
|
||||||
import { mitter } from "/@/utils/util.mitt";
|
import { mitter } from "/@/utils/util.mitt";
|
||||||
import { useI18n } from "/src/locales";
|
|
||||||
import * as pipelineApi from "/@/views/certd/pipeline/api";
|
|
||||||
import { getAddonTypeDefine } from "/@/views/certd/addon/api";
|
import { getAddonTypeDefine } from "/@/views/certd/addon/api";
|
||||||
|
import { useI18n } from "/src/locales";
|
||||||
|
|
||||||
export function addonProvide(api: any) {
|
export function addonProvide(api: any) {
|
||||||
provide("addonApi", api);
|
provide("addonApi", api);
|
||||||
@@ -30,6 +29,10 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any, a
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
provide("getCurrentPluginDefine", () => {
|
||||||
|
return currentDefine;
|
||||||
|
});
|
||||||
|
|
||||||
function buildDefineFields(define: any, form: any, mode: string) {
|
function buildDefineFields(define: any, form: any, mode: string) {
|
||||||
const formWrapperRef = crudExpose.getFormWrapperRef();
|
const formWrapperRef = crudExpose.getFormWrapperRef();
|
||||||
const columnsRef = toRef(formWrapperRef.formOptions, "columns");
|
const columnsRef = toRef(formWrapperRef.formOptions, "columns");
|
||||||
|
|||||||