mirror of
https://github.com/certd/certd.git
synced 2026-10-14 01:46:00 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c98b974f7 | ||
|
|
e2aff952f9 | ||
|
|
9d9ae64aff | ||
|
|
22715a430e | ||
|
|
949a69f0dc | ||
|
|
53db97b6f2 | ||
|
|
cd2dcaa859 | ||
|
|
d0463abc26 | ||
|
|
8f1b38ad7d | ||
|
|
e11349b8cc | ||
|
|
2394cc6dd9 | ||
|
|
8209c3d6e1 | ||
|
|
3e001b8ba4 | ||
|
|
41ca198116 | ||
|
|
6eca5dad9b | ||
|
|
c285522500 | ||
|
|
b12f7c54d4 | ||
|
|
b055bbecfc | ||
|
|
a52a6ce8f6 | ||
|
|
fcbf1045fe | ||
|
|
f5cfe054b7 | ||
|
|
5ded5ff2b6 | ||
|
|
8d31346cd3 | ||
|
|
44b41b6a08 | ||
|
|
4420472f8f | ||
|
|
c4497a7018 | ||
|
|
03f1a7bd0e | ||
|
|
97d2b50074 | ||
|
|
2d0b85b305 | ||
|
|
28052c9387 | ||
|
|
c4277350bc | ||
|
|
97160373d6 | ||
|
|
0ce24618a1 | ||
|
|
f60e63fbaf | ||
|
|
2735feb330 | ||
|
|
b6381d79fc | ||
|
|
241b2e5584 | ||
|
|
bb1f232f41 | ||
|
|
f82d3a5fcc | ||
|
|
bbeaf617d1 | ||
|
|
ea7d14c289 | ||
|
|
3272a68ff6 | ||
|
|
b5715d99ff | ||
|
|
3f5ba14fde | ||
|
|
07f0d3b4d6 | ||
|
|
3dbbe72fc1 | ||
|
|
7f006d1359 | ||
|
|
d30f1c4785 | ||
|
|
96e0122b93 | ||
|
|
7786a87b21 | ||
|
|
34476ba14f | ||
|
|
4b942385a8 | ||
|
|
14809127d6 | ||
|
|
bd8b251d6e | ||
|
|
5563abb13a | ||
|
|
51e83e4c38 | ||
|
|
2b1a5296fe | ||
|
|
bded368cbb | ||
|
|
6a649aaca0 | ||
|
|
e971145686 | ||
|
|
bbca449f94 | ||
|
|
e6852c2715 | ||
|
|
47cb523307 | ||
|
|
cbf46b5c48 | ||
|
|
7ed3105d97 | ||
|
|
61b945c08f |
@@ -3,7 +3,7 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "版本号(如 v1.42.5)"
|
||||
description: "版本号(如 1.42.5)"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
|
||||
+2
-1
@@ -42,4 +42,5 @@ output/
|
||||
.uploads/
|
||||
.certd-plugin-history/
|
||||
.tmp
|
||||
.plugin-dev/
|
||||
.plugin-dev/
|
||||
.tmp_chunks/
|
||||
@@ -23,6 +23,8 @@ version: 1.0.0
|
||||
|
||||
- 配置插件的唯一标识、标题、图标和描述
|
||||
- 继承 `BaseAccess` 类
|
||||
- 插件默认文案使用中文;需要英文时,在注解参数对象中添加同级 `i18n: { "en-US": { ... } }`,不要写成 `metadata.i18n`。`define` 本身就是插件 metadata。
|
||||
- `i18n["en-US"]` 仅配置要翻译的展示字段,如 `title`、`desc`、`input`;输入字段可翻译 `title`、`helper`、组件展示文案和 `optionsMapping`。缺少英文翻译时回退默认中文。
|
||||
|
||||
3. **定义授权属性**
|
||||
|
||||
@@ -392,6 +394,66 @@ export class OAuthDemoAccess extends BaseAccess {
|
||||
}
|
||||
```
|
||||
|
||||
## 字段动态显隐(mergeScript)
|
||||
|
||||
多种鉴权方式共用一个授权时,用 `@AccessInput` 上的 `mergeScript` 按所选方式显隐字段:
|
||||
|
||||
```typescript
|
||||
@AccessInput({
|
||||
title: '鉴权方式',
|
||||
value: 'apikey',
|
||||
component: {
|
||||
name: 'a-select',
|
||||
vModel: 'value',
|
||||
options: [
|
||||
{ label: 'AccessKey签名', value: 'aksk' },
|
||||
{ label: 'ApiKey', value: 'apikey' },
|
||||
],
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
authType = 'apikey';
|
||||
|
||||
@AccessInput({
|
||||
title: 'accessKeyId',
|
||||
component: { name: 'a-input', vModel: 'value' },
|
||||
required: true,
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return !form.access.authType || form.access.authType === 'aksk';
|
||||
})
|
||||
}
|
||||
`,
|
||||
})
|
||||
accessKeyId = '';
|
||||
```
|
||||
|
||||
要点:
|
||||
|
||||
- `mergeScript` 返回的对象会深合并进本字段定义,可动态化的属性有 `show`、`required`、`helper`、
|
||||
`component` 下的属性(`options`、`placeholder` 等)以及 `component.on` 事件。
|
||||
- **动态判断必须写在 `ctx.compute(({form})=>{ ... })` 回调里**。`mergeScript` 本身在插件类
|
||||
定义阶段就被拼成字符串,那时表单还没打开,用参数在服务端判断字段值没有意义。
|
||||
- 授权表单字段值在 `form.access.xxx`(任务表单才是 `form.xxx`)。
|
||||
- 历史授权没有新字段,条件里要用 `!form.access.authType || ...` 兜底走旧逻辑,保证老授权还能编辑保存。
|
||||
- 联动其他字段用 `component.on` 事件回调,回调参数是 `{ form }`:
|
||||
|
||||
```typescript
|
||||
mergeScript: `
|
||||
return {
|
||||
component: {
|
||||
on: {
|
||||
selectedChange: (scope) => {
|
||||
const form = scope.form;
|
||||
form.acmeAccountAccessId = null;
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`,
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **插件命名**:插件名称应简洁明了,反映其功能。
|
||||
|
||||
@@ -9,7 +9,7 @@ description: 用于通过 Certd API 开发、修改、读取、保存和恢复
|
||||
|
||||
本 Skill 使用 Certd HTTP API,不使用 WebSocket,也不依赖浏览器传递代码草稿。
|
||||
|
||||
- 前端只生成包含需求、API 地址和认证 Token 的启动提示词。
|
||||
- 前端只生成包含需求、插件作者、API 地址和认证 Token 的启动提示词。
|
||||
- Agent 直接调用 Certd API 读取和保存插件 YAML。
|
||||
- Agent 的进度、日志和代码修改在 Codex/Trae 中查看。
|
||||
- 插件开发临时文件和修改历史统一保存在 Agent 工作区的 `.plugin-dev/` 下,不保存到浏览器或 Certd 后端。
|
||||
@@ -43,15 +43,13 @@ Certd 插件按来源分为三类:
|
||||
|
||||
## API 认证
|
||||
|
||||
提示词会提供 Certd API 地址和仅限 AI 插件开发接口的受限 Token。调用 API 时使用:
|
||||
提示词会提供 Certd API 地址和仅限 AI 插件开发接口的受限的短时效的 Token。调用 API 时使用:
|
||||
|
||||
```http
|
||||
Authorization: <token>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
不要把 Token 写入代码、历史摘要、日志、提交信息或插件 YAML。
|
||||
|
||||
所有 Certd API 请求统一使用 Node.js 的 `fetch`。不要使用 PowerShell 的 `Invoke-RestMethod`、`Invoke-WebRequest` 或 .NET HTTP 客户端发送插件 YAML/JSON;它们在 Windows 上可能造成中文乱码或使完整 YAML 导入请求长时间无响应。
|
||||
|
||||
Node 请求须直接读取 UTF-8 文件或在 Node 内构造 JSON,并使用 `JSON.stringify`:
|
||||
@@ -118,6 +116,7 @@ const response = await fetch(`${apiBase}/scoped/sys/ai/plugin/find`, {
|
||||
- 修改后保存修改摘要。
|
||||
- 恢复前再次备份当前版本。
|
||||
- 不上传历史文件,不保存 Token、证书、私钥或真实授权值。
|
||||
- 修改完一版后立即提交更新到certd,但不要发布到市场。
|
||||
|
||||
详细格式见 `references/local-history.md`。
|
||||
|
||||
@@ -125,6 +124,7 @@ const response = await fetch(`${apiBase}/scoped/sys/ai/plugin/find`, {
|
||||
|
||||
插件始终以完整 YAML 传递和保存,脚本源码放在顶层 `content` 字段。
|
||||
|
||||
- 新插件的 `author` 必须使用启动提示词中给出的插件作者,不要自行编造作者名;修改已有插件时保留原 `author`,不要改成其他作者。
|
||||
- 统一使用 `await _ctx.import(...)` 引用模块。
|
||||
- `"/@/..."` 表示以绝对路径引用 `server/src/` 下的模块。
|
||||
- 最后返回继承目标基类的 class。
|
||||
@@ -135,6 +135,28 @@ const response = await fetch(`${apiBase}/scoped/sys/ai/plugin/find`, {
|
||||
|
||||
需要字段格式时读取 `references/online-yaml-format.md`。
|
||||
需要组件示例时读取 `references/component-examples.md`。
|
||||
需要按其他字段动态显隐/必填/联动时读取 `references/merge-script.md`。
|
||||
|
||||
### 字段动态显隐(mergeScript)
|
||||
|
||||
字段定义支持 `mergeScript`:脚本 `return` 的对象会合并进本字段,用来做「选了 A 才显示 B」这类联动。
|
||||
|
||||
```yaml
|
||||
mergeScript: |2-
|
||||
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.access.authType === 'apikey';
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
- 动态逻辑必须写在 `ctx.compute(({form})=>{ ... })` 回调里;`mergeScript` 本身在插件类定义阶段就
|
||||
被拼成字符串,那时表单还没打开,用参数在 node 侧判断字段值没有任何意义。
|
||||
- 授权表单字段值在 `form.access.xxx`,任务表单字段值在 `form.xxx`。
|
||||
- 新增可选字段时要给历史数据兜底,例如 `!form.access.authType || form.access.authType === 'aksk'`。
|
||||
|
||||
完整用法(能力、可动态化的属性、事件联动、常见错误、验证方式)见 `references/merge-script.md`。
|
||||
|
||||
## 示例插件
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: DemoAccess
|
||||
icon: logos:airflow-icon
|
||||
title: Demo-授权插件示例 # 模块-插件名
|
||||
title: Demo-授权插件示例 # 格式:平台-功能 ,例如: 网宿-授权 ; 阿里云-授权 ; 天翼云-授权
|
||||
group: null
|
||||
desc: 这只是一个示例
|
||||
version: 1.0.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: DemoDeploy
|
||||
icon: logos:amp-icon
|
||||
title: Demo-部署插件示例 # 模块-插件名
|
||||
title: Demo-部署插件示例 # 格式:平台-功能 ,例如: 网宿-更新CDNpro证书 ; 阿里云-上传到CAS证书管理服务 ; 天翼云-更新CDN证书
|
||||
group: cdn
|
||||
desc: 这仅仅是一个示例
|
||||
version: 1.0.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: DemoDnsProvider
|
||||
icon: fa-solid:frog
|
||||
title: Demo-Dns提供商插件示例 # 模块-插件名
|
||||
title: Demo-Dns提供商插件示例 # 格式:平台-功能 ,例如: 阿里云-DNS提供商 ;腾讯云-DNS提供商
|
||||
desc: 这只是一个示例
|
||||
type: custom
|
||||
version: 1.0.0
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
# mergeScript 用法
|
||||
|
||||
来源:前端 `packages/ui/certd-client/src/use/use-refrence.tsx`,类型定义来自 `@fast-crud/fast-crud`。
|
||||
|
||||
`mergeScript` 用来让输入字段的定义**依赖当前表单里的其他字段值动态变化**,例如:
|
||||
选了某个鉴权方式才显示对应字段、切换类型后清空已选值、下拉选项跟着另一个字段变。
|
||||
|
||||
它写成字符串放在字段定义上(内置插件放在 `@AccessInput` / `@TaskInput` 里,在线插件放在 `input.<字段>` 下):
|
||||
|
||||
```ts
|
||||
@AccessInput({
|
||||
title: "API Key",
|
||||
component: { name: "a-input", vModel: "value" },
|
||||
mergeScript: `
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
//access里面 要用 form.access.[字段名]
|
||||
return form.access.authType === 'apikey';
|
||||
//deploy插件里面要用form.[字段名]
|
||||
return form.authType === 'apikey';
|
||||
})
|
||||
}
|
||||
`,
|
||||
})
|
||||
apiKey = "";
|
||||
```
|
||||
|
||||
## 执行时机
|
||||
|
||||
字段定义被前端加载时,对**每一个字段**执行一次:
|
||||
|
||||
```js
|
||||
const func = new Function('ctx', formItem.mergeScript);
|
||||
const merged = func(ctx); // 字段脚本只执行这一次
|
||||
merge(formItem, merged); // 返回值深合并进该字段的定义
|
||||
delete formItem.mergeScript; // 执行完就删掉,最终定义里不再有 mergeScript
|
||||
```
|
||||
|
||||
要点:
|
||||
|
||||
- 脚本体内**必须 `return` 一个对象**,返回的对象会深合并到本字段的定义上。
|
||||
- 脚本本身只在加载字段时跑一次,**拿不到、也不应该判断用户填了什么值**。
|
||||
- 真正的动态逻辑写在返回对象里的 `ctx.compute(...)` 回调中,由 fast-crud 在渲染时求值。
|
||||
|
||||
## ctx 提供的能力
|
||||
|
||||
| 能力 | 说明 |
|
||||
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `ctx.compute(fn)` | 最常用。返回一个响应式的计算值:`fn` 里读到的表单字段会被自动追踪,字段变化时重新计算,视图跟着刷新 |
|
||||
|
||||
`ctx.compute` 的回调参数是一个 context 对象,常用字段:
|
||||
|
||||
- `form`:当前表单数据。**这是唯一常用的一个**。
|
||||
- `row`:行数据。
|
||||
- `mode`:表单模式 `add` / `edit` / `view`。
|
||||
- `getComponentRef(key)`:取其他字段组件的 ref。
|
||||
|
||||
注意:Certd 在把 `form` 传进回调前做过一次兼容处理(`form.input || form.body || form`),
|
||||
所以两种表单取值路径不同:
|
||||
|
||||
- **授权(Access)表单**:字段值在 `form.access.xxx`(字段 key 会被加上 `access.` 前缀)。
|
||||
- **任务(Task)表单**:字段值直接是 `form.xxx`。
|
||||
|
||||
## 可以动态化的属性
|
||||
|
||||
返回的对象里,任何字段定义属性都可以用 `ctx.compute`,常用的有:
|
||||
|
||||
| 属性 | 用途 |
|
||||
| -------------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| `show` | 显隐(最常用) |
|
||||
| `required` | 动态必填,例如 `required: ctx.compute(({form}) => form.targetType === 'ingress')` |
|
||||
| `disabled` | 动态禁用,例如账号已创建后不允许再改:`disabled: ctx.compute(({form}) => !!form.access?.account)` |
|
||||
| `helper` | 动态帮助文案,回调里按条件 `return` 不同字符串 |
|
||||
| `value` | 动态默认值 |
|
||||
| `component` 下的属性 | 动态 `options`、`placeholder`、`inputKey`、`type`、`disabled` 等 |
|
||||
| `component.on` | 事件处理,见下面「联动」 |
|
||||
| `col` / `order` | 布局与排序 |
|
||||
|
||||
只写了一层 `show` 时最简形式就是本文开头的例子。
|
||||
|
||||
## 联动(监听事件并改动其他字段)
|
||||
|
||||
`component.on` 的事件回调**不**用 `ctx.compute` 包,它本身就是回调,参数是
|
||||
`{ form, $event, ... }`;`form` 同样做过 `form.input || form.body || form` 的兼容处理。
|
||||
事件名按组件而定,例如 `selectedChange`。
|
||||
|
||||
```ts
|
||||
mergeScript: `
|
||||
return {
|
||||
component: {
|
||||
on: {
|
||||
selectedChange: (scope) => {
|
||||
const form = scope.form;
|
||||
// 切换颁发机构后清空 ACME 账号,避免账号与机构不匹配
|
||||
form.acmeAccountAccessId = null;
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`,
|
||||
```
|
||||
|
||||
另一种写法是把回调也做成计算值(需要用到组件上配置的 `onSelectedChange` / `onChange` 属性):
|
||||
|
||||
```ts
|
||||
mergeScript: `
|
||||
return {
|
||||
component: {
|
||||
onSelectedChange: ctx.compute(({form}) => {
|
||||
return ($event) => {
|
||||
form.dnsProviderAccessType = $event.accessType;
|
||||
};
|
||||
}),
|
||||
},
|
||||
}
|
||||
`,
|
||||
```
|
||||
|
||||
两种写法都能用,优先参考同目录已有插件的写法,保持一致。
|
||||
|
||||
## 常见错误
|
||||
|
||||
- **不要用 node 侧变量决定条件**。`mergeScript` 是在插件类定义阶段(node 侧)拼出来的字符串,
|
||||
此时表单还没打开,拿不到任何用户输入;用参数拼条件等于把逻辑写死在服务端。
|
||||
条件必须原样落到 `ctx.compute` 回调里。
|
||||
- **不要用 `if` 直接判断字段值**。回调必须 `return` 一个值,写成
|
||||
`show: ctx.compute(({form}) => { if (...) { return true } })` 也可以,但不要漏掉 `return`。
|
||||
- **不要漏掉历史数据兼容**。新增可选字段时,历史数据里没有这个字段(值为 `undefined`),
|
||||
条件要按旧行为兜底,例如 `!form.access.authType || form.access.authType === 'aksk'`。
|
||||
- **不要访问 `form.access` 以外的路径**去读授权字段,也不要在授权表单里按任务表单的路径取值。
|
||||
- **不要依赖脚本执行时的副作用**(打印日志、改全局状态),它在每次打开表单时都会重新执行。
|
||||
|
||||
## YAML 写法(在线插件)
|
||||
|
||||
`mergeScript` 是含换行的脚本字符串,必须用 YAML 块标量:
|
||||
|
||||
```yaml
|
||||
input:
|
||||
apiKey:
|
||||
title: API Key
|
||||
component:
|
||||
name: a-input
|
||||
vModel: value
|
||||
mergeScript: |2-
|
||||
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return form.access.authType === 'apikey';
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
导出生成的缩进比较特殊(块标量内容统一缩进),**不要手工调整缩进**:
|
||||
用脚本生成 YAML,并保证导出后再导入内容一致。转换成 block scalar 时注意:
|
||||
|
||||
- `|` / `|2-` 等块标量不需要转义换行,不要把脚本写成带 `\n` 的单行。
|
||||
- 脚本里不要出现 `??` 这类容易被误判为乱码的写法,用显式 `if (x == null)` 代替。
|
||||
|
||||
## 验证方式
|
||||
|
||||
前端表单没法在插件开发流程里直接断言,可以在后端加一个 `src/**/*.test.ts`,
|
||||
按前端 `useReference` 的路径执行字段上的 `mergeScript`:
|
||||
|
||||
```ts
|
||||
const computedGetters = [];
|
||||
const ctx = {
|
||||
compute: getter => {
|
||||
computedGetters.push(getter);
|
||||
return getter;
|
||||
},
|
||||
asyncCompute: () => undefined,
|
||||
computed: () => undefined,
|
||||
};
|
||||
new Function('ctx', mergeScript)(ctx);
|
||||
// 用假的 form 求值,断言显隐结果
|
||||
const show = computedGetters[0]({ form: { access: { authType: 'apikey' } } });
|
||||
```
|
||||
|
||||
参考实现:`packages/ui/certd-server/src/plugins/plugin-wangsu/access-input.test.ts`。
|
||||
要点是断言「同一个 show 函数换 `authType` 结果会变」,证明显隐确实是运行时算的,
|
||||
而不是在 node 侧定死的。
|
||||
@@ -7,7 +7,7 @@
|
||||
```yaml
|
||||
name: DemoTask
|
||||
author: demo
|
||||
title: Demo 任务
|
||||
title: Demo-插件名称 # 格式:平台-功能 ,例如: 网宿-更新CDNpro证书 ; 阿里云-上传到CAS证书管理服务 ; 天翼云-更新CDN证书
|
||||
desc: 插件说明
|
||||
icon: clarity:plugin-line
|
||||
pluginType: task
|
||||
@@ -61,6 +61,8 @@ content: |
|
||||
### 编辑规则
|
||||
|
||||
- 修改已有插件时保留 `name`、`author`、`pluginType` 和已有兼容字段。
|
||||
- 新插件的 `author` 使用启动提示词中给出的插件作者,不要自行编造作者名;启动提示词未给出作者时先向用户确认。
|
||||
- `fullName` 由 `author/name` 组成,作者变化会导致插件身份变化,不要随意修改。
|
||||
- 只修改需求涉及的字段,避免删除未知的 YAML 字段。
|
||||
- 脚本过长时仍放在同一个 `content` block scalar 中。
|
||||
- 提交前检查 YAML 可解析、`content` 非空、版本和插件类型没有被意外修改。
|
||||
|
||||
@@ -57,4 +57,41 @@ return class DemoAccess extends BaseAccess {
|
||||
- `onTestRequest` 应调用实际 API 方法并在失败时抛出异常。
|
||||
- 对外 API 方法应统一处理分页、错误和返回字段。
|
||||
- 使用 `this.logger` 或框架提供的 logger,禁止 `console.log`。
|
||||
- 一般将API接口方法封装到Access中,其他plugin调用access的方法当做client sdk使用
|
||||
- 一般将API接口方法封装到Access中,其他plugin调用access的方法当做client sdk使用
|
||||
|
||||
## 字段动态显隐
|
||||
|
||||
多种鉴权方式(例如「ApiKey」和「AccessKey签名」)共用一个授权时,
|
||||
用字段上的 `mergeScript` 按所选方式显隐对应字段,只让用户看到当前方式需要的字段:
|
||||
|
||||
```yaml
|
||||
input:
|
||||
authType:
|
||||
title: 鉴权方式
|
||||
value: apikey
|
||||
component:
|
||||
name: a-select
|
||||
vModel: value
|
||||
options:
|
||||
- { label: AccessKey签名, value: aksk }
|
||||
- { label: ApiKey, value: apikey }
|
||||
accessKeyId:
|
||||
title: accessKeyId
|
||||
component:
|
||||
name: a-input
|
||||
vModel: value
|
||||
mergeScript: |2-
|
||||
|
||||
return {
|
||||
show: ctx.compute(({form})=>{
|
||||
return !form.access.authType || form.access.authType === 'aksk';
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
- 判断必须写在 `ctx.compute(({form})=>{ ... })` 回调里;脚本本身在插件定义阶段就拼好了,
|
||||
那时表单还没打开,用参数在服务端判断字段值没有意义。
|
||||
- 授权表单的字段值在 `form.access.xxx`(任务表单才是 `form.xxx`)。
|
||||
- 历史授权没有 `authType` 字段,条件里要用 `!form.access.authType || ...` 兜底走旧逻辑。
|
||||
|
||||
完整用法见父 Skill 的 `references/merge-script.md`。
|
||||
@@ -30,6 +30,8 @@ version: 1.0.0
|
||||
- 指定对应的云平台的 access 类型名称
|
||||
- 设置排序值(可选)
|
||||
- 继承 `AbstractDnsProvider` 类
|
||||
- 插件默认文案使用中文;需要英文时,在注解参数对象中添加同级 `i18n: { "en-US": { ... } }`,不要写成 `metadata.i18n`。`define` 本身就是插件 metadata。
|
||||
- `i18n["en-US"]` 仅配置要翻译的展示字段,如 `title`、`desc`、`input`;输入字段可翻译 `title`、`helper`、组件展示文案和 `optionsMapping`。缺少英文翻译时回退默认中文。
|
||||
|
||||
4. **实现 onInstance 方法**
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ version: 1.0.0
|
||||
- 设置插件分组
|
||||
- 配置默认策略(如 `SkipWhenSucceed`)
|
||||
- 确保类名与插件名称一致
|
||||
- 插件默认文案使用中文;需要英文时,在注解参数对象中添加同级 `i18n: { "en-US": { ... } }`,不要写成 `metadata.i18n`。`define` 本身就是插件 metadata。
|
||||
- `i18n["en-US"]` 仅配置要翻译的展示字段,如 `title`、`desc`、`group`、`input`、`output`;未配置的字段自动回退默认中文。不要翻译插件标识、组件类型、默认值或执行参数。
|
||||
|
||||
3. **定义任务输入参数**
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ Certd 是可私有化部署的 SSL/TLS 证书自动化管理平台,提供 Web
|
||||
- 只有真正机械化的大批量替换、格式化或生成任务才考虑脚本/工具。若必须使用临时脚本,应放在临时目录并在同一个受控步骤内完成创建、执行、删除;不要把临时脚本落在仓库里跨多步工具调用执行。
|
||||
- 不要主动运行 `pnpm install`;缺依赖、TTY、网络导致安装或测试失败时,停止尝试并说明环境问题。
|
||||
- 优先沿用现有模块、插件、service、页面模式;不要为形式上的复用制造过度抽象。
|
||||
- 代码可读性优先于短写法。尽量少用三元表达式,优先使用完整的 `if/else`;复杂条件、链式调用、内联对象和多层 helper 调用要拆成命名清晰的中间变量或小方法。
|
||||
- 【重要重要重要】代码可读性优先于短写法。尽量少用三元表达式,优先使用完整的 `if/else`【其他技能与此条要求冲突的,以此条要求为准】;复杂条件、链式调用、内联对象和多层 helper 调用要拆成命名清晰的中间变量或小方法。
|
||||
- 方法调用链不要直接塞进另一个方法参数;先用有意义的局部变量承接返回值,再传入下一步。
|
||||
- 不要在单一表达式内嵌套分支、对象构造与方法调用。优先使用清晰的 `if/else` 分支;仅在确实能降低复杂度时才提取有意义的中间变量,避免为拆分而增加阅读跳转。
|
||||
- 注释优先使用中文,尤其是业务规则、兼容逻辑、协议细节和隐藏风险;文件已有英文风格或引用外部术语时可保持一致。
|
||||
|
||||
@@ -3,6 +3,42 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/certd/certd/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* [BUG]使用天翼云CDN部署证书时无法匹配域名 ([bb1f232](https://github.com/certd/certd/commit/bb1f232f415c522851dede979f5d609dda844fd3))
|
||||
* 缺失运行时嵌套依赖时添加清除缓存提示 ([2d0b85b](https://github.com/certd/certd/commit/2d0b85b3054fc1aa82b3ab5db34a2a56308f71f2))
|
||||
* 支持google persist校验方式 ([97d2b50](https://github.com/certd/certd/commit/97d2b5007409ec79ea864d437c473a2f9b5dfae4))
|
||||
* **config:** 修复环境变量加载逻辑并更新配置文件 ([07f0d3b](https://github.com/certd/certd/commit/07f0d3b4d626628a0e3dfc7e5c52e8c4a98bad47))
|
||||
* **ctyun-cdn:** 修复天翼云CDN部署插件的域名选择问题 ([ea7d14c](https://github.com/certd/certd/commit/ea7d14c289b8720781bf101bfef59eac7bb03765))
|
||||
* **webhook:** 修复模版转义换行符,避免手动上传的证书报错 ([2735feb](https://github.com/certd/certd/commit/2735feb3302f8308708dafc8b295adcd4b91d7f0))
|
||||
|
||||
### Features
|
||||
|
||||
* **client:** 新增客户端管理功能 ([3dbbe72](https://github.com/certd/certd/commit/3dbbe72fc15c114ca6b5e8ff45cb21f258b80650))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 宝塔站点列表支持搜索和排序 ([4420472](https://github.com/certd/certd/commit/4420472f8fac272d30fb8ccb1cc2ee9763989001))
|
||||
* 网宿插件双鉴权支持 ([241b2e5](https://github.com/certd/certd/commit/241b2e55848471e61b5d2be0c87a7dc9a0d29557))
|
||||
* **monitor:** 站点证书监控支持手动选中触发检查 ([f60e63f](https://github.com/certd/certd/commit/f60e63fbaf00460d5050cd7705bd75d57dec202d))
|
||||
* **open-api:** openkey增加用途备注 ([bbeaf61](https://github.com/certd/certd/commit/bbeaf617d19750515f6eca51863e74e23bc1de50))
|
||||
* **tencent clb:** 修改所有CLB地域的endpoint为就近接入 ([c427735](https://github.com/certd/certd/commit/c4277350bcc8cf034cf4e76db2a6daa1842bc5d7))
|
||||
|
||||
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复添加步骤会修改所有步骤标题的bug ([51e83e4](https://github.com/certd/certd/commit/51e83e4c38f7f319314fdc38ef33cf5720b2dde0))
|
||||
* 修复证书插件配置无法打开的bug ([5563abb](https://github.com/certd/certd/commit/5563abb13a62140f4dee668ab768cf4ff9371ddb))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 新增余额管理,管理员充值功能 ([bded368](https://github.com/certd/certd/commit/bded368cbb8974b6937ae260e448c25fae5c33ad))
|
||||
* **acme-account-access:** AcmeAccount授权允许修改eab,重新生成account ([6a649aa](https://github.com/certd/certd/commit/6a649aaca083ccd3b517f7d676a58220aa33b37d))
|
||||
* **ui:** 商业版套餐购买不要求设置支付方式 ([e971145](https://github.com/certd/certd/commit/e9711456860d7db40914a0c295534f7bca56f83c))
|
||||
|
||||
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export default { setSuccess: "Settings saved", editTitle: "Edit Certificate Application Template", addTitle: "Add Certificate Application Template", name: "Template Name", default: "Default", setDefault: "Set as Default", disabled: "Disabled", createTime: "Created At", config: "Configuration" };
|
||||
@@ -3,6 +3,53 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/certd/certd/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* [BUG]使用天翼云CDN部署证书时无法匹配域名 ([bb1f232](https://github.com/certd/certd/commit/bb1f232f415c522851dede979f5d609dda844fd3))
|
||||
* 缺失运行时嵌套依赖时添加清除缓存提示 ([2d0b85b](https://github.com/certd/certd/commit/2d0b85b3054fc1aa82b3ab5db34a2a56308f71f2))
|
||||
* 支持google persist校验方式 ([97d2b50](https://github.com/certd/certd/commit/97d2b5007409ec79ea864d437c473a2f9b5dfae4))
|
||||
* **config:** 修复环境变量加载逻辑并更新配置文件 ([07f0d3b](https://github.com/certd/certd/commit/07f0d3b4d626628a0e3dfc7e5c52e8c4a98bad47))
|
||||
* **ctyun-cdn:** 修复天翼云CDN部署插件的域名选择问题 ([ea7d14c](https://github.com/certd/certd/commit/ea7d14c289b8720781bf101bfef59eac7bb03765))
|
||||
* **webhook:** 修复模版转义换行符,避免手动上传的证书报错 ([2735feb](https://github.com/certd/certd/commit/2735feb3302f8308708dafc8b295adcd4b91d7f0))
|
||||
|
||||
### Features
|
||||
|
||||
* **client:** 新增客户端管理功能 ([3dbbe72](https://github.com/certd/certd/commit/3dbbe72fc15c114ca6b5e8ff45cb21f258b80650))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 宝塔站点列表支持搜索和排序 ([4420472](https://github.com/certd/certd/commit/4420472f8fac272d30fb8ccb1cc2ee9763989001))
|
||||
* 网宿插件双鉴权支持 ([241b2e5](https://github.com/certd/certd/commit/241b2e55848471e61b5d2be0c87a7dc9a0d29557))
|
||||
* **monitor:** 站点证书监控支持手动选中触发检查 ([f60e63f](https://github.com/certd/certd/commit/f60e63fbaf00460d5050cd7705bd75d57dec202d))
|
||||
* **open-api:** openkey增加用途备注 ([bbeaf61](https://github.com/certd/certd/commit/bbeaf617d19750515f6eca51863e74e23bc1de50))
|
||||
* **tencent clb:** 修改所有CLB地域的endpoint为就近接入 ([c427735](https://github.com/certd/certd/commit/c4277350bcc8cf034cf4e76db2a6daa1842bc5d7))
|
||||
|
||||
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复添加步骤会修改所有步骤标题的bug ([51e83e4](https://github.com/certd/certd/commit/51e83e4c38f7f319314fdc38ef33cf5720b2dde0))
|
||||
* 修复证书插件配置无法打开的bug ([5563abb](https://github.com/certd/certd/commit/5563abb13a62140f4dee668ab768cf4ff9371ddb))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 新增余额管理,管理员充值功能 ([bded368](https://github.com/certd/certd/commit/bded368cbb8974b6937ae260e448c25fae5c33ad))
|
||||
* **acme-account-access:** AcmeAccount授权允许修改eab,重新生成account ([6a649aa](https://github.com/certd/certd/commit/6a649aaca083ccd3b517f7d676a58220aa33b37d))
|
||||
* **ui:** 商业版套餐购买不要求设置支付方式 ([e971145](https://github.com/certd/certd/commit/e9711456860d7db40914a0c295534f7bca56f83c))
|
||||
|
||||
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **plugin-service:** 修复同步自己开发的云端插件不显示已安装状态问题 ([dac94b6](https://github.com/certd/certd/commit/dac94b64f0ceb7176e2cf07ce220be0aa5ed98d2))
|
||||
* **plugin:** 修复插件配置保存与加载的相关问题 ([bd94334](https://github.com/certd/certd/commit/bd9433478a43d5d64ce6370386d0fe0aaff07d2e))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **plugin:** add Fastly custom TLS certificates integration ([#797](https://github.com/certd/certd/issues/797)) [@szhu25](https://github.com/szhu25) ([2a2e963](https://github.com/certd/certd/commit/2a2e963914c4dfc192cbe0a4bbb9c115e626da01))
|
||||
|
||||
## [1.44.2](https://github.com/certd/certd/compare/v1.44.1...v1.44.2) (2026-09-03)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
`Certd`默认启用https,监听7002端口
|
||||
如果你想关闭https,或者修改端口,可以在环境变量中配置
|
||||
```shell
|
||||
CERTD_HTTPS_ENABLE=true
|
||||
CERTD_HTTPS_port=7002
|
||||
certd_https_enabled=true
|
||||
certd_https_port=7002
|
||||
|
||||
```
|
||||
|
||||
|
||||
+1
-1
@@ -9,5 +9,5 @@
|
||||
}
|
||||
},
|
||||
"npmClient": "pnpm",
|
||||
"version": "1.44.3"
|
||||
"version": "1.45.0"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/publishlab/node-acme-client/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 支持google persist校验方式 ([97d2b50](https://github.com/publishlab/node-acme-client/commit/97d2b5007409ec79ea864d437c473a2f9b5dfae4))
|
||||
|
||||
## [1.44.4](https://github.com/publishlab/node-acme-client/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
## [1.44.3](https://github.com/publishlab/node-acme-client/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
**Note:** Version bump only for package @certd/acme-client
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "Simple and unopinionated ACME client",
|
||||
"private": false,
|
||||
"author": "nmorsman",
|
||||
"version": "1.44.3",
|
||||
"version": "1.45.0",
|
||||
"type": "module",
|
||||
"module": "./dist/index.js",
|
||||
"main": "./dist/index.js",
|
||||
@@ -18,7 +18,7 @@
|
||||
"types"
|
||||
],
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.44.3",
|
||||
"@certd/basic": "^1.45.0",
|
||||
"@peculiar/x509": "^1.11.0",
|
||||
"asn1js": "^3.0.5",
|
||||
"axios": "^1.9.0",
|
||||
@@ -27,6 +27,7 @@
|
||||
"https-proxy-agent": "^7.0.5",
|
||||
"lodash-es": "^4.17.21",
|
||||
"node-forge": "^1.3.1",
|
||||
"psl": "^1.15.0",
|
||||
"punycode.js": "^2.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -76,5 +77,5 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/publishlab/node-acme-client/issues"
|
||||
},
|
||||
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
|
||||
"gitHead": "fcbf1045fe3806fa1a0bebf5038a6f67aec283d0"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// @ts-ignore
|
||||
import psl from "psl";
|
||||
|
||||
export function getDnsPersistIssuer(directoryUrl?: string) {
|
||||
if (!directoryUrl) {
|
||||
return "letsencrypt.org";
|
||||
}
|
||||
|
||||
let directory: URL;
|
||||
try {
|
||||
directory = new URL(directoryUrl);
|
||||
} catch {
|
||||
throw new Error(`ACME Directory URL无效,无法生成DNS持久验证Issuer:${directoryUrl}`);
|
||||
}
|
||||
|
||||
const issuer = psl.get(directory.hostname);
|
||||
if (!issuer) {
|
||||
throw new Error(`无法从ACME Directory URL获取可注册主域名:${directory.hostname}`);
|
||||
}
|
||||
return issuer;
|
||||
}
|
||||
@@ -79,3 +79,4 @@ export * from './verify.js'
|
||||
export * from './error.js'
|
||||
|
||||
export * from './util.js'
|
||||
export * from './dns-persist.js'
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/certd/certd/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **webhook:** 修复模版转义换行符,避免手动上传的证书报错 ([2735feb](https://github.com/certd/certd/commit/2735feb3302f8308708dafc8b295adcd4b91d7f0))
|
||||
|
||||
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
**Note:** Version bump only for package @certd/basic
|
||||
|
||||
@@ -1 +1 @@
|
||||
23:46
|
||||
00:51
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/basic",
|
||||
"private": false,
|
||||
"version": "1.44.3",
|
||||
"version": "1.45.0",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -54,5 +54,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
|
||||
"gitHead": "fcbf1045fe3806fa1a0bebf5038a6f67aec283d0"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
import dayjs from "dayjs";
|
||||
|
||||
export const stringUtils = {
|
||||
replaceTemplate(target: string, body: Record<string, unknown>, urlEncode = false) {
|
||||
let bodyStr = target;
|
||||
for (const key of Object.keys(body)) {
|
||||
const rawValue = body[key] == null ? "" : String(body[key]);
|
||||
let value = urlEncode ? encodeURIComponent(rawValue) : rawValue;
|
||||
value = value.replace(/[\u0000-\u001f]/g, char => {
|
||||
const escapes: Record<string, string> = { "\b": "\\b", "\f": "\\f", "\n": "\\n", "\r": "\\r", "\t": "\\t" };
|
||||
return escapes[char] ?? `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}`;
|
||||
});
|
||||
bodyStr = bodyStr.replaceAll(`\${${key}}`, value);
|
||||
bodyStr = bodyStr.replaceAll(`{${key}}`, value);
|
||||
}
|
||||
return bodyStr;
|
||||
},
|
||||
|
||||
maxLength(str?: string, length = 100) {
|
||||
if (str) {
|
||||
return str.length > length ? str.slice(0, length) + "..." : str;
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/certd/certd/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 缺失运行时嵌套依赖时添加清除缓存提示 ([2d0b85b](https://github.com/certd/certd/commit/2d0b85b3054fc1aa82b3ab5db34a2a56308f71f2))
|
||||
|
||||
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
**Note:** Version bump only for package @certd/pipeline
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/pipeline",
|
||||
"private": false,
|
||||
"version": "1.44.3",
|
||||
"version": "1.45.0",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -21,8 +21,8 @@
|
||||
"lint": "eslint --fix --ext .ts src"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.44.3",
|
||||
"@certd/plus-core": "^1.44.3",
|
||||
"@certd/basic": "^1.45.0",
|
||||
"@certd/plus-core": "^1.45.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"lodash-es": "^4.17.21",
|
||||
"reflect-metadata": "^0.2.2"
|
||||
@@ -51,5 +51,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
|
||||
"gitHead": "fcbf1045fe3806fa1a0bebf5038a6f67aec283d0"
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ export type AccessInputDefine = FormItemProps & {
|
||||
encrypt?: boolean;
|
||||
};
|
||||
export type AccessDefine = Registrable & {
|
||||
i18n?: Record<string, any>;
|
||||
icon?: string;
|
||||
subtype?: string;
|
||||
dependPlugins?: Record<string, string>;
|
||||
|
||||
@@ -44,6 +44,7 @@ export type NotificationDefine = Registrable & {
|
||||
input?: {
|
||||
[key: string]: NotificationInputDefine;
|
||||
};
|
||||
i18n?: Record<string, any>;
|
||||
};
|
||||
|
||||
export type NotificationInstanceConfig = {
|
||||
|
||||
@@ -43,6 +43,7 @@ export type TaskInputDefine = {
|
||||
} & FormItemProps;
|
||||
|
||||
export type PluginDefine = Registrable & {
|
||||
i18n?: Record<string, any>;
|
||||
default?: any;
|
||||
group?: string;
|
||||
icon?: string;
|
||||
@@ -97,6 +98,7 @@ export type CertTargetItem = {
|
||||
|
||||
export type PipelineEvent<T = any> = {
|
||||
cert: T;
|
||||
certPassword?: string;
|
||||
runnableId: string;
|
||||
pipelineId: number;
|
||||
};
|
||||
|
||||
@@ -64,6 +64,28 @@ describe("RuntimeDepsService", () => {
|
||||
assert.equal(mod.value, 42);
|
||||
});
|
||||
|
||||
it("logs a cache clearing hint when a nested runtime dependency is missing", async () => {
|
||||
const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), "certd-runtime-deps-missing-nested-"));
|
||||
const packageDir = path.join(rootDir, "node_modules", "runtime-only");
|
||||
fs.mkdirSync(packageDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(rootDir, "package.json"), JSON.stringify({ name: "runtime-root", type: "module" }), "utf8");
|
||||
fs.writeFileSync(path.join(packageDir, "package.json"), JSON.stringify({ name: "runtime-only", main: "index.js" }), "utf8");
|
||||
fs.writeFileSync(path.join(packageDir, "index.js"), "module.exports = require('missing-nested');\n", "utf8");
|
||||
const logs: string[] = [];
|
||||
const logger = {
|
||||
info() {},
|
||||
warn() {},
|
||||
error(message: string, ...args: any[]) {
|
||||
logs.push([message, ...args.map(item => item?.message || String(item))].join(" "));
|
||||
},
|
||||
};
|
||||
const service = new RuntimeDepsService({ rootDir }, null);
|
||||
|
||||
await assert.rejects(() => service.importRuntime("runtime-only", logger));
|
||||
assert.ok(logs.some(message => message.includes("Cannot find module 'missing-nested'")));
|
||||
assert.ok(logs.some(message => message.includes("插件管理页面->清除缓存依赖->重启certd")));
|
||||
});
|
||||
|
||||
it("installs configured lazy dependency when import target is missing", async () => {
|
||||
const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), "certd-runtime-deps-lazy-"));
|
||||
const service = new RuntimeDepsService({ rootDir, lazyDependencies: { "lazy-pkg": "^1.2.3" } }, null);
|
||||
|
||||
@@ -251,6 +251,7 @@ export class RuntimeDepsService {
|
||||
}
|
||||
|
||||
let resolved: string;
|
||||
let fromRuntimeDeps = false;
|
||||
try {
|
||||
//尝试加载本项目依赖
|
||||
resolved = this.resolveProjectSpecifier(specifier).resolved;
|
||||
@@ -258,13 +259,22 @@ export class RuntimeDepsService {
|
||||
if (!this.isModuleNotFoundError(error)) {
|
||||
throw error;
|
||||
}
|
||||
fromRuntimeDeps = true;
|
||||
resolved = await this.resolveLazyOrInstallSpecifier(specifier, logger);
|
||||
}
|
||||
if (!resolved) {
|
||||
throw new Error(`依赖未安装成功: ${specifier}`);
|
||||
}
|
||||
|
||||
return await import(pathToFileURL(resolved).href);
|
||||
try {
|
||||
return await import(pathToFileURL(resolved).href);
|
||||
} catch (error: any) {
|
||||
if (fromRuntimeDeps && this.isModuleNotFoundError(error)) {
|
||||
logger.error?.("动态依赖加载失败:", error);
|
||||
logger.error?.("动态依赖加载失败,请前往插件管理页面->清除缓存依赖->重启certd后重试");
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
//动态获取模块解析
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/certd/certd/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-huawei
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-huawei",
|
||||
"private": false,
|
||||
"version": "1.44.3",
|
||||
"version": "1.45.0",
|
||||
"main": "./dist/bundle.js",
|
||||
"module": "./dist/bundle.js",
|
||||
"types": "./dist/d/index.d.ts",
|
||||
@@ -31,5 +31,5 @@
|
||||
"prettier": "3.3.3",
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
|
||||
"gitHead": "fcbf1045fe3806fa1a0bebf5038a6f67aec283d0"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/certd/certd/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-iframe
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-iframe",
|
||||
"private": false,
|
||||
"version": "1.44.3",
|
||||
"version": "1.45.0",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -37,5 +37,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
|
||||
"gitHead": "fcbf1045fe3806fa1a0bebf5038a6f67aec283d0"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/certd/certd/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
**Note:** Version bump only for package @certd/jdcloud
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/jdcloud",
|
||||
"version": "1.44.3",
|
||||
"version": "1.45.0",
|
||||
"description": "jdcloud openApi sdk",
|
||||
"main": "./dist/bundle.js",
|
||||
"module": "./dist/bundle.js",
|
||||
@@ -63,5 +63,5 @@
|
||||
"fetch"
|
||||
]
|
||||
},
|
||||
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
|
||||
"gitHead": "fcbf1045fe3806fa1a0bebf5038a6f67aec283d0"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/certd/certd/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-k8s
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/lib-k8s",
|
||||
"private": false,
|
||||
"version": "1.44.3",
|
||||
"version": "1.45.0",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -21,7 +21,7 @@
|
||||
"lint": "eslint --fix --ext .ts src"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/basic": "^1.44.3",
|
||||
"@certd/basic": "^1.45.0",
|
||||
"@kubernetes/client-node": "0.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -38,5 +38,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
|
||||
"gitHead": "fcbf1045fe3806fa1a0bebf5038a6f67aec283d0"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/certd/certd/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
### Features
|
||||
|
||||
* **client:** 新增客户端管理功能 ([3dbbe72](https://github.com/certd/certd/commit/3dbbe72fc15c114ca6b5e8ff45cb21f258b80650))
|
||||
|
||||
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复证书插件配置无法打开的bug ([5563abb](https://github.com/certd/certd/commit/5563abb13a62140f4dee668ab768cf4ff9371ddb))
|
||||
|
||||
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
**Note:** Version bump only for package @certd/lib-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/lib-server",
|
||||
"version": "1.44.3",
|
||||
"version": "1.45.0",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -29,11 +29,11 @@
|
||||
],
|
||||
"license": "AGPL",
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.44.3",
|
||||
"@certd/basic": "^1.44.3",
|
||||
"@certd/pipeline": "^1.44.3",
|
||||
"@certd/plugin-lib": "^1.44.3",
|
||||
"@certd/plus-core": "^1.44.3",
|
||||
"@certd/acme-client": "^1.45.0",
|
||||
"@certd/basic": "^1.45.0",
|
||||
"@certd/pipeline": "^1.45.0",
|
||||
"@certd/plugin-lib": "^1.45.0",
|
||||
"@certd/plus-core": "^1.45.0",
|
||||
"@midwayjs/cache": "3.14.0",
|
||||
"@midwayjs/core": "3.20.11",
|
||||
"@midwayjs/i18n": "3.20.13",
|
||||
@@ -69,5 +69,5 @@
|
||||
"typeorm": "^0.3.20",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
|
||||
"gitHead": "fcbf1045fe3806fa1a0bebf5038a6f67aec283d0"
|
||||
}
|
||||
|
||||
@@ -133,12 +133,12 @@ export class SysPrivateSettings extends BaseSettings {
|
||||
// 内置项不在此配置 Directory URL:其端点由运行时按加密算法(pkType)通过 acme.getDirectoryUrl 获取,
|
||||
// 例如 ZeroSSL、SSL.com 的 RSA 与 EC 证书使用不同的端点,写死单一 URL 会导致 EC 申请走错端点。
|
||||
customAcmeProviders?: CustomAcmeProvider[] = [
|
||||
{ sslProvider: "letsencrypt", title: "Let's Encrypt", directoryUrl: "", needEAB: false, builtIn: true },
|
||||
{ sslProvider: "letsencrypt_staging", title: "Let's Encrypt测试环境", directoryUrl: "", needEAB: false, builtIn: true },
|
||||
{ sslProvider: "letsencrypt", title: "Let's Encrypt(支持7天IP证书)", directoryUrl: "", needEAB: false, builtIn: true },
|
||||
{ sslProvider: "google", title: "Google", directoryUrl: "", needEAB: true, builtIn: true },
|
||||
{ sslProvider: "zerossl", title: "ZeroSSL", directoryUrl: "", needEAB: true, builtIn: true },
|
||||
{ sslProvider: "litessl", title: "litessl", directoryUrl: "", needEAB: true, builtIn: true },
|
||||
{ sslProvider: "litessl", title: "Litessl", directoryUrl: "", needEAB: true, builtIn: true },
|
||||
{ sslProvider: "sslcom", title: "SSL.com", directoryUrl: "", needEAB: true, builtIn: true },
|
||||
{ sslProvider: "letsencrypt_staging", title: "Let's Encrypt测试环境(只能生成测试证书)", directoryUrl: "", needEAB: false, builtIn: true },
|
||||
];
|
||||
|
||||
removeSecret() {
|
||||
|
||||
@@ -174,11 +174,11 @@ export class AccessService extends BaseService<AccessEntity> {
|
||||
throw new ValidateException("userId不能为空");
|
||||
}
|
||||
if (userId !== entity.userId) {
|
||||
throw new PermissionException("您对该Access授权无访问权限");
|
||||
throw new PermissionException(`您对该Access授权${entity.name}(${entity.id})无访问权限`);
|
||||
}
|
||||
}
|
||||
if (projectId != null && projectId !== entity.projectId) {
|
||||
throw new PermissionException("您对该Access授权无访问权限");
|
||||
throw new PermissionException(`您对该Access授权${entity.name}(${entity.id})无访问权限`);
|
||||
}
|
||||
|
||||
// const access = accessRegistry.get(entity.type);
|
||||
|
||||
@@ -26,6 +26,7 @@ export type AddonDefine = Registrable & {
|
||||
};
|
||||
showTest?: boolean;
|
||||
icon?: string;
|
||||
i18n?: Record<string, any>;
|
||||
};
|
||||
|
||||
export type AddonInstanceConfig = {
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/certd/certd/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/midway-flyway-js",
|
||||
"version": "1.44.3",
|
||||
"version": "1.45.0",
|
||||
"description": "midway with flyway, sql upgrade way ",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
@@ -52,5 +52,5 @@
|
||||
"typeorm": "^0.3.20",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
|
||||
"gitHead": "fcbf1045fe3806fa1a0bebf5038a6f67aec283d0"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/certd/certd/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-cert
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-cert",
|
||||
"private": false,
|
||||
"version": "1.44.3",
|
||||
"version": "1.45.0",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -20,7 +20,7 @@
|
||||
"lint": "eslint --fix --ext .ts src"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/plugin-lib": "^1.44.3"
|
||||
"@certd/plugin-lib": "^1.45.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.3.12",
|
||||
@@ -38,5 +38,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
|
||||
"gitHead": "fcbf1045fe3806fa1a0bebf5038a6f67aec283d0"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/certd/certd/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-lib
|
||||
|
||||
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-lib
|
||||
|
||||
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
**Note:** Version bump only for package @certd/plugin-lib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@certd/plugin-lib",
|
||||
"private": false,
|
||||
"version": "1.44.3",
|
||||
"version": "1.45.0",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -17,9 +17,9 @@
|
||||
"lint": "eslint --fix --ext .ts src"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/acme-client": "^1.44.3",
|
||||
"@certd/basic": "^1.44.3",
|
||||
"@certd/pipeline": "^1.44.3",
|
||||
"@certd/acme-client": "^1.45.0",
|
||||
"@certd/basic": "^1.45.0",
|
||||
"@certd/pipeline": "^1.45.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"jszip": "^3.10.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
@@ -45,5 +45,5 @@
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"gitHead": "67f3daae625ba734e7e390dd84acc9e3bc1930bc"
|
||||
"gitHead": "fcbf1045fe3806fa1a0bebf5038a6f67aec283d0"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { IAccess, IAccessService, IServiceGetter, PageRes, PageSearch, Registrab
|
||||
|
||||
export type DnsProviderDefine = Registrable & {
|
||||
accessType: string;
|
||||
i18n?: Record<string, any>;
|
||||
icon?: string;
|
||||
dependPlugins?: Record<string, string>;
|
||||
dependPackages?: Record<string, string>;
|
||||
|
||||
@@ -3,6 +3,29 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.45.0](https://github.com/certd/certd/compare/v1.44.4...v1.45.0) (2026-10-02)
|
||||
|
||||
### Features
|
||||
|
||||
* **client:** 新增客户端管理功能 ([3dbbe72](https://github.com/certd/certd/commit/3dbbe72fc15c114ca6b5e8ff45cb21f258b80650))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **monitor:** 站点证书监控支持手动选中触发检查 ([f60e63f](https://github.com/certd/certd/commit/f60e63fbaf00460d5050cd7705bd75d57dec202d))
|
||||
* **open-api:** openkey增加用途备注 ([bbeaf61](https://github.com/certd/certd/commit/bbeaf617d19750515f6eca51863e74e23bc1de50))
|
||||
|
||||
## [1.44.4](https://github.com/certd/certd/compare/v1.44.3...v1.44.4) (2026-09-12)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 修复添加步骤会修改所有步骤标题的bug ([51e83e4](https://github.com/certd/certd/commit/51e83e4c38f7f319314fdc38ef33cf5720b2dde0))
|
||||
* 修复证书插件配置无法打开的bug ([5563abb](https://github.com/certd/certd/commit/5563abb13a62140f4dee668ab768cf4ff9371ddb))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* 新增余额管理,管理员充值功能 ([bded368](https://github.com/certd/certd/commit/bded368cbb8974b6937ae260e448c25fae5c33ad))
|
||||
* **ui:** 商业版套餐购买不要求设置支付方式 ([e971145](https://github.com/certd/certd/commit/e9711456860d7db40914a0c295534f7bca56f83c))
|
||||
|
||||
## [1.44.3](https://github.com/certd/certd/compare/v1.44.2...v1.44.3) (2026-09-06)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -13,7 +13,7 @@ const { packages } = getPackagesSync(process.cwd());
|
||||
|
||||
const tailwindPackages = [];
|
||||
|
||||
packages.forEach((pkg) => {
|
||||
packages.forEach(pkg => {
|
||||
// apps目录下和 @vben-core/tailwind-ui 包需要使用到 tailwindcss ui
|
||||
// if (fs.existsSync(path.join(pkg.dir, 'tailwind.config.mjs'))) {
|
||||
tailwindPackages.push(pkg.dir);
|
||||
@@ -25,96 +25,96 @@ const shadcnUiColors = {
|
||||
DEFAULT: "hsl(var(--accent))",
|
||||
foreground: "hsl(var(--accent-foreground))",
|
||||
hover: "hsl(var(--accent-hover))",
|
||||
lighter: "has(val(--accent-lighter))"
|
||||
lighter: "has(val(--accent-lighter))",
|
||||
},
|
||||
background: {
|
||||
deep: "hsl(var(--background-deep))",
|
||||
DEFAULT: "hsl(var(--background))"
|
||||
DEFAULT: "hsl(var(--background))",
|
||||
},
|
||||
border: {
|
||||
DEFAULT: "hsl(var(--border))"
|
||||
DEFAULT: "hsl(var(--border))",
|
||||
},
|
||||
card: {
|
||||
DEFAULT: "hsl(var(--card))",
|
||||
foreground: "hsl(var(--card-foreground))"
|
||||
foreground: "hsl(var(--card-foreground))",
|
||||
},
|
||||
destructive: {
|
||||
...createColorsPalette("destructive"),
|
||||
DEFAULT: "hsl(var(--destructive))"
|
||||
DEFAULT: "hsl(var(--destructive))",
|
||||
},
|
||||
|
||||
foreground: {
|
||||
DEFAULT: "hsl(var(--foreground))"
|
||||
DEFAULT: "hsl(var(--foreground))",
|
||||
},
|
||||
|
||||
input: {
|
||||
background: "hsl(var(--input-background))",
|
||||
DEFAULT: "hsl(var(--input))"
|
||||
DEFAULT: "hsl(var(--input))",
|
||||
},
|
||||
muted: {
|
||||
DEFAULT: "hsl(var(--muted))",
|
||||
foreground: "hsl(var(--muted-foreground))"
|
||||
foreground: "hsl(var(--muted-foreground))",
|
||||
},
|
||||
popover: {
|
||||
DEFAULT: "hsl(var(--popover))",
|
||||
foreground: "hsl(var(--popover-foreground))"
|
||||
foreground: "hsl(var(--popover-foreground))",
|
||||
},
|
||||
primary: {
|
||||
...createColorsPalette("primary"),
|
||||
DEFAULT: "hsl(var(--primary))"
|
||||
DEFAULT: "hsl(var(--primary))",
|
||||
},
|
||||
|
||||
ring: "hsl(var(--ring))",
|
||||
secondary: {
|
||||
DEFAULT: "hsl(var(--secondary))",
|
||||
desc: "hsl(var(--secondary-desc))",
|
||||
foreground: "hsl(var(--secondary-foreground))"
|
||||
}
|
||||
foreground: "hsl(var(--secondary-foreground))",
|
||||
},
|
||||
};
|
||||
|
||||
const customColors = {
|
||||
green: {
|
||||
...createColorsPalette("green"),
|
||||
foreground: "hsl(var(--success-foreground))"
|
||||
foreground: "hsl(var(--success-foreground))",
|
||||
},
|
||||
header: {
|
||||
DEFAULT: "hsl(var(--header))"
|
||||
DEFAULT: "hsl(var(--header))",
|
||||
},
|
||||
heavy: {
|
||||
DEFAULT: "hsl(var(--heavy))",
|
||||
foreground: "hsl(var(--heavy-foreground))"
|
||||
foreground: "hsl(var(--heavy-foreground))",
|
||||
},
|
||||
main: {
|
||||
DEFAULT: "hsl(var(--main))"
|
||||
DEFAULT: "hsl(var(--main))",
|
||||
},
|
||||
overlay: {
|
||||
content: "hsl(var(--overlay-content))",
|
||||
DEFAULT: "hsl(var(--overlay))"
|
||||
DEFAULT: "hsl(var(--overlay))",
|
||||
},
|
||||
red: {
|
||||
...createColorsPalette("red"),
|
||||
foreground: "hsl(var(--destructive-foreground))"
|
||||
foreground: "hsl(var(--destructive-foreground))",
|
||||
},
|
||||
sidebar: {
|
||||
deep: "hsl(var(--sidebar-deep))",
|
||||
DEFAULT: "hsl(var(--sidebar))"
|
||||
DEFAULT: "hsl(var(--sidebar))",
|
||||
},
|
||||
success: {
|
||||
...createColorsPalette("success"),
|
||||
DEFAULT: "hsl(var(--success))"
|
||||
DEFAULT: "hsl(var(--success))",
|
||||
},
|
||||
warning: {
|
||||
...createColorsPalette("warning"),
|
||||
DEFAULT: "hsl(var(--warning))"
|
||||
DEFAULT: "hsl(var(--warning))",
|
||||
},
|
||||
yellow: {
|
||||
...createColorsPalette("yellow"),
|
||||
foreground: "hsl(var(--warning-foreground))"
|
||||
}
|
||||
foreground: "hsl(var(--warning-foreground))",
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
content: ["./index.html", ...tailwindPackages.map((item) => path.join(item, "src/**/*.{vue,js,ts,jsx,tsx,svelte,astro,html}"))],
|
||||
content: ["./index.html", ...tailwindPackages.map(item => path.join(item, "src/**/*.{vue,js,ts,jsx,tsx,svelte,astro,html}"))],
|
||||
darkMode: "selector",
|
||||
plugins: [animate, typographyPlugin, addDynamicIconSelectors(), enterAnimationPlugin],
|
||||
prefix: "",
|
||||
@@ -123,8 +123,8 @@ export default {
|
||||
center: true,
|
||||
padding: "2rem",
|
||||
screens: {
|
||||
"2xl": "1400px"
|
||||
}
|
||||
"2xl": "1400px",
|
||||
},
|
||||
},
|
||||
extend: {
|
||||
animation: {
|
||||
@@ -132,64 +132,67 @@ export default {
|
||||
"accordion-up": "accordion-up 0.2s ease-out",
|
||||
"collapsible-down": "collapsible-down 0.2s ease-in-out",
|
||||
"collapsible-up": "collapsible-up 0.2s ease-in-out",
|
||||
float: "float 5s linear 0ms infinite"
|
||||
float: "float 5s linear 0ms infinite",
|
||||
},
|
||||
flex: {
|
||||
2: "2 1 0%",
|
||||
},
|
||||
|
||||
animationDuration: {
|
||||
2000: "2000ms",
|
||||
3000: "3000ms"
|
||||
3000: "3000ms",
|
||||
},
|
||||
borderRadius: {
|
||||
lg: "var(--radius)",
|
||||
md: "calc(var(--radius) - 2px)",
|
||||
sm: "calc(var(--radius) - 4px)",
|
||||
xl: "calc(var(--radius) + 4px)"
|
||||
xl: "calc(var(--radius) + 4px)",
|
||||
},
|
||||
boxShadow: {
|
||||
float: `0 6px 16px 0 rgb(0 0 0 / 8%),
|
||||
0 3px 6px -4px rgb(0 0 0 / 12%),
|
||||
0 9px 28px 8px rgb(0 0 0 / 5%)`
|
||||
0 9px 28px 8px rgb(0 0 0 / 5%)`,
|
||||
},
|
||||
colors: {
|
||||
...customColors,
|
||||
...shadcnUiColors
|
||||
...shadcnUiColors,
|
||||
},
|
||||
fontFamily: {
|
||||
sans: [
|
||||
"var(--font-family)"
|
||||
"var(--font-family)",
|
||||
// ...defaultTheme.fontFamily.sans
|
||||
]
|
||||
],
|
||||
},
|
||||
keyframes: {
|
||||
"accordion-down": {
|
||||
from: { height: "0" },
|
||||
to: { height: "var(--radix-accordion-content-height)" }
|
||||
to: { height: "var(--radix-accordion-content-height)" },
|
||||
},
|
||||
"accordion-up": {
|
||||
from: { height: "var(--radix-accordion-content-height)" },
|
||||
to: { height: "0" }
|
||||
to: { height: "0" },
|
||||
},
|
||||
"collapsible-down": {
|
||||
from: { height: "0" },
|
||||
to: { height: "var(--radix-collapsible-content-height)" }
|
||||
to: { height: "var(--radix-collapsible-content-height)" },
|
||||
},
|
||||
"collapsible-up": {
|
||||
from: { height: "var(--radix-collapsible-content-height)" },
|
||||
to: { height: "0" }
|
||||
to: { height: "0" },
|
||||
},
|
||||
float: {
|
||||
"0%": { transform: "translateY(0)" },
|
||||
"50%": { transform: "translateY(-20px)" },
|
||||
"100%": { transform: "translateY(0)" }
|
||||
}
|
||||
"100%": { transform: "translateY(0)" },
|
||||
},
|
||||
},
|
||||
zIndex: {
|
||||
100: "100",
|
||||
1000: "1000"
|
||||
}
|
||||
}
|
||||
1000: "1000",
|
||||
},
|
||||
},
|
||||
},
|
||||
safelist: ["dark"]
|
||||
safelist: ["dark"],
|
||||
};
|
||||
|
||||
function createColorsPalette(name) {
|
||||
@@ -249,6 +252,6 @@ function createColorsPalette(name) {
|
||||
// 主色文本激活态
|
||||
"text-active": `hsl(var(--${name}-700))`,
|
||||
// 主色文本悬浮态
|
||||
"text-hover": `hsl(var(--${name}-600))`
|
||||
"text-hover": `hsl(var(--${name}-600))`,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,6 +10,6 @@ export default {
|
||||
"postcss-import": {},
|
||||
"postcss-preset-env": {},
|
||||
tailwindcss: { config },
|
||||
"tailwindcss/nesting": {}
|
||||
}
|
||||
"tailwindcss/nesting": {},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@certd/ui-client",
|
||||
"version": "1.44.3",
|
||||
"version": "1.45.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite --open",
|
||||
@@ -34,11 +34,11 @@
|
||||
"@aws-sdk/s3-request-presigner": "^3.964.0",
|
||||
"@certd/vue-js-cron-light": "^4.0.14",
|
||||
"@ctrl/tinycolor": "^4.1.0",
|
||||
"@fast-crud/editor-code": "^1.28.7",
|
||||
"@fast-crud/fast-crud": "^1.28.7",
|
||||
"@fast-crud/fast-extends": "^1.28.7",
|
||||
"@fast-crud/ui-antdv4": "^1.28.7",
|
||||
"@fast-crud/ui-interface": "^1.28.7",
|
||||
"@fast-crud/editor-code": "^1.29.0",
|
||||
"@fast-crud/fast-crud": "^1.29.0",
|
||||
"@fast-crud/fast-extends": "^1.29.0",
|
||||
"@fast-crud/ui-antdv4": "^1.29.0",
|
||||
"@fast-crud/ui-interface": "^1.29.0",
|
||||
"@iconify/tailwind": "^1.2.0",
|
||||
"@iconify/vue": "^4.1.1",
|
||||
"@manypkg/get-packages": "^2.2.2",
|
||||
@@ -104,8 +104,8 @@
|
||||
"zod-defaults": "^0.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@certd/lib-iframe": "^1.44.3",
|
||||
"@certd/pipeline": "^1.44.3",
|
||||
"@certd/lib-iframe": "^1.45.0",
|
||||
"@certd/pipeline": "^1.45.0",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@types/chai": "^4.3.12",
|
||||
|
||||
@@ -4,6 +4,7 @@ import { errorLog, errorCreate } from "./tools";
|
||||
import { env } from "/src/utils/util.env";
|
||||
import { useUserStore } from "/@/store/user";
|
||||
import { useProjectStore } from "../store/project";
|
||||
import { i18n } from "/@/locales";
|
||||
|
||||
export class CodeError extends Error {
|
||||
code: number;
|
||||
@@ -139,6 +140,7 @@ function createRequestFunction(service: any) {
|
||||
const configDefault: any = {
|
||||
headers: {
|
||||
"Content-Type": get(config, "headers.Content-Type", "application/json"),
|
||||
"Accept-Language": i18n.global.locale.value,
|
||||
} as any,
|
||||
timeout: 30000,
|
||||
baseURL: env.API,
|
||||
@@ -154,6 +156,10 @@ function createRequestFunction(service: any) {
|
||||
configDefault.headers.Authorization = token;
|
||||
}
|
||||
Object.assign(configDefault, config);
|
||||
configDefault.headers = {
|
||||
...configDefault.headers,
|
||||
"Accept-Language": i18n.global.locale.value,
|
||||
};
|
||||
|
||||
if (!configDefault.params.projectId && projectStore.isEnterprise && !config.url.startsWith("/sys") && !config.url.startsWith("http")) {
|
||||
configDefault.params.projectId = projectStore.currentProject?.id;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="flex captcha-image-input">
|
||||
<a-input :value="valueRef" :placeholder="t('certd.captcha.inputImageCode')" autocomplete="off" @update:value="onChange">
|
||||
<a-input :value="valueRef" :placeholder="t('certd.common.captcha.inputImageCode')" autocomplete="off" @update:value="onChange">
|
||||
<template #prefix>
|
||||
<fs-icon icon="ion:image-outline"></fs-icon>
|
||||
</template>
|
||||
</a-input>
|
||||
<div class="input-right pointer" :title="t('certd.captcha.refresh')">
|
||||
<div class="input-right pointer" :title="t('certd.common.captcha.refresh')">
|
||||
<img class="image-code" :src="imageCodeSrc" @click="resetImageCode" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<div class="sweep-animation"></div>
|
||||
<div class="box-content">
|
||||
<div class="box-icon">✓</div>
|
||||
<span v-if="modelValue == null" class="status-text">{{ t("certd.captcha.clickToVerify") }}</span>
|
||||
<span v-else class="status-text">{{ t("certd.captcha.verifySuccess") }}</span>
|
||||
<span v-if="modelValue == null" class="status-text">{{ t("certd.common.captcha.clickToVerify") }}</span>
|
||||
<span v-else class="status-text">{{ t("certd.common.captcha.verifySuccess") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -58,7 +58,7 @@ function callback(res: { ret: number; ticket: string; randstr: string; errorCode
|
||||
|
||||
if (res.errorCode && res.errorCode > 0) {
|
||||
notification.error({
|
||||
message: t("certd.captcha.verifyFailed", { message: res.errorMessage || res.errorCode }),
|
||||
message: t("certd.common.captcha.verifyFailed", { message: res.errorMessage || res.errorCode }),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -85,13 +85,13 @@ function loadErrorCallback(error: any) {
|
||||
// errorMessage: "jsload_error",
|
||||
// });
|
||||
notification.error({
|
||||
message: t("certd.captcha.loadFailed", { message: error?.message || error }),
|
||||
message: t("certd.common.captcha.loadFailed", { message: error?.message || error }),
|
||||
});
|
||||
}
|
||||
async function triggerCaptcha() {
|
||||
if (!loaded.value) {
|
||||
notification.error({
|
||||
message: t("certd.captcha.notLoaded"),
|
||||
message: t("certd.common.captcha.notLoaded"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
+7
-5
@@ -5,6 +5,7 @@
|
||||
<script lang="ts">
|
||||
import { ref } from "vue";
|
||||
import * as api from "./api";
|
||||
import { resolvePluginLocale } from "/@/store/plugin";
|
||||
|
||||
export default {
|
||||
name: "DnsProviderSelector",
|
||||
@@ -21,12 +22,13 @@ export default {
|
||||
async function onCreate() {
|
||||
const list = await api.GetList();
|
||||
const array: any[] = [];
|
||||
for (let item of list) {
|
||||
for (const item of list) {
|
||||
const localizedItem = resolvePluginLocale(item);
|
||||
array.push({
|
||||
value: item.name,
|
||||
label: item.title,
|
||||
icon: item.icon,
|
||||
accessType: item.accessType,
|
||||
value: localizedItem.name,
|
||||
label: localizedItem.title,
|
||||
icon: localizedItem.icon,
|
||||
accessType: localizedItem.accessType,
|
||||
});
|
||||
}
|
||||
options.value = array;
|
||||
|
||||
+11
-11
@@ -4,7 +4,7 @@
|
||||
<!-- <td class="domain">-->
|
||||
<!-- {{ props.domain }}-->
|
||||
<!-- </td>-->
|
||||
<td class="host-record" :title="t('certd.verifyPlan.domainTitle', { domain: props.domain })">
|
||||
<td class="host-record" :title="t('certd.certdomain.verifyPlan.domainTitle', { domain: props.domain })">
|
||||
<fs-copyable v-model="cnameRecord.hostRecord"></fs-copyable>
|
||||
</td>
|
||||
<td style="text-align: center">CNAME</td>
|
||||
@@ -17,18 +17,18 @@
|
||||
<a-tooltip v-if="cnameRecord.error" :title="cnameRecord.error">
|
||||
<fs-icon class="ml-5 color-red" icon="ion:warning-outline"></fs-icon>
|
||||
</a-tooltip>
|
||||
<a-tooltip v-if="cnameRecord.status === 'valid'" :title="t('certd.verifyPlan.resetStatusTooltip')">
|
||||
<a-tooltip v-if="cnameRecord.status === 'valid'" :title="t('certd.certdomain.verifyPlan.resetStatusTooltip')">
|
||||
<fs-icon class="ml-2 color-yellow text-md pointer" icon="solar:undo-left-square-bold" @click="resetStatus"></fs-icon>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
</td>
|
||||
<td class="center">
|
||||
<template v-if="cnameRecord.status !== 'valid'">
|
||||
<a-button type="primary" size="small" :loading="loading" @click="doVerify">{{ t("certd.verifyPlan.clickToValidate") }}</a-button>
|
||||
<a-button type="primary" size="small" :loading="loading" @click="doVerify">{{ t("certd.certdomain.verifyPlan.clickToValidate") }}</a-button>
|
||||
<cname-tip :record="cnameRecord"></cname-tip>
|
||||
</template>
|
||||
|
||||
<div v-else class="helper" :title="t('certd.verifyPlan.keepCnameTitle')">{{ t("certd.verifyPlan.keepCname") }}</div>
|
||||
<div v-else class="helper" :title="t('certd.certdomain.verifyPlan.keepCnameTitle')">{{ t("certd.certdomain.verifyPlan.keepCname") }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -46,11 +46,11 @@ import { utils } from "/@/utils/index.js";
|
||||
const { t } = useI18n();
|
||||
const statusDict = dict({
|
||||
data: [
|
||||
{ label: t("certd.verifyPlan.status.pendingCname"), value: "cname", color: "warning" },
|
||||
{ label: t("certd.verifyPlan.status.validating"), value: "validating", color: "blue" },
|
||||
{ label: t("certd.verifyPlan.status.valid"), value: "valid", color: "green" },
|
||||
{ label: t("certd.verifyPlan.status.failed"), value: "failed", color: "red" },
|
||||
{ label: t("certd.verifyPlan.status.timeout"), value: "timeout", color: "red" },
|
||||
{ label: t("certd.certdomain.verifyPlan.status.pendingCname"), value: "cname", color: "warning" },
|
||||
{ label: t("certd.certdomain.verifyPlan.status.validating"), value: "validating", color: "blue" },
|
||||
{ label: t("certd.certdomain.verifyPlan.status.valid"), value: "valid", color: "green" },
|
||||
{ label: t("certd.certdomain.verifyPlan.status.failed"), value: "failed", color: "red" },
|
||||
{ label: t("certd.certdomain.verifyPlan.status.timeout"), value: "timeout", color: "red" },
|
||||
],
|
||||
});
|
||||
|
||||
@@ -129,8 +129,8 @@ async function doVerify() {
|
||||
|
||||
async function resetStatus() {
|
||||
Modal.confirm({
|
||||
title: t("certd.verifyPlan.resetStatus"),
|
||||
content: t("certd.verifyPlan.confirmResetStatus"),
|
||||
title: t("certd.certdomain.verifyPlan.resetStatus"),
|
||||
content: t("certd.certdomain.verifyPlan.confirmResetStatus"),
|
||||
onOk: async () => {
|
||||
await api.ResetStatus(cnameRecord.value.id);
|
||||
await loadRecord();
|
||||
|
||||
+7
-7
@@ -2,17 +2,17 @@
|
||||
<a-tooltip :overlay-style="{ maxWidth: '400px' }">
|
||||
<template #title>
|
||||
<div>
|
||||
<div>{{ t("certd.verifyPlan.cnameTip.intro") }}</div>
|
||||
<div>{{ t("certd.verifyPlan.cnameTip.step1", { domain: record.domain }) }}</div>
|
||||
<div>{{ t("certd.verifyPlan.cnameTip.step2") }}</div>
|
||||
<div>{{ t("certd.verifyPlan.cnameTip.step3", { value: record.recordValue }) }}</div>
|
||||
<div>{{ t("certd.certdomain.verifyPlan.cnameTip.intro") }}</div>
|
||||
<div>{{ t("certd.certdomain.verifyPlan.cnameTip.step1", { domain: record.domain }) }}</div>
|
||||
<div>{{ t("certd.certdomain.verifyPlan.cnameTip.step2") }}</div>
|
||||
<div>{{ t("certd.certdomain.verifyPlan.cnameTip.step3", { value: record.recordValue }) }}</div>
|
||||
<div>
|
||||
{{ t("certd.verifyPlan.cnameTip.step4") }}
|
||||
{{ t("certd.certdomain.verifyPlan.cnameTip.step4") }}
|
||||
<fs-copyable :style="{ color: '#52c41a' }" :model-value="nslookupCmd"></fs-copyable>
|
||||
{{ t("certd.verifyPlan.cnameTip.or") }}
|
||||
{{ t("certd.certdomain.verifyPlan.cnameTip.or") }}
|
||||
<fs-copyable :style="{ color: '#52c41a' }" :model-value="digCmd"></fs-copyable>
|
||||
</div>
|
||||
<div>{{ t("certd.verifyPlan.cnameTip.step5") }}</div>
|
||||
<div>{{ t("certd.certdomain.verifyPlan.cnameTip.step5") }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<fs-icon class="ml-5 pointer" icon="mingcute:question-line"></fs-icon>
|
||||
|
||||
+5
-5
@@ -2,11 +2,11 @@
|
||||
<table class="cname-verify-plan">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="col-host">{{ t("certd.verifyPlan.hostRecord") }}</td>
|
||||
<td class="col-type center">{{ t("certd.verifyPlan.recordType") }}</td>
|
||||
<td class="col-value">{{ t("certd.verifyPlan.setCnameRecord") }}</td>
|
||||
<td class="col-status center">{{ t("certd.status") }}</td>
|
||||
<td class="col-action center">{{ t("certd.verifyPlan.operation") }}</td>
|
||||
<td class="col-host">{{ t("certd.certdomain.verifyPlan.hostRecord") }}</td>
|
||||
<td class="col-type center">{{ t("certd.certdomain.verifyPlan.recordType") }}</td>
|
||||
<td class="col-value">{{ t("certd.certdomain.verifyPlan.setCnameRecord") }}</td>
|
||||
<td class="col-status center">{{ t("certd.common.status") }}</td>
|
||||
<td class="col-action center">{{ t("certd.certdomain.verifyPlan.operation") }}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<template v-for="key in domains" :key="key">
|
||||
|
||||
+5
-5
@@ -2,10 +2,10 @@
|
||||
<table class="http-verify-plan">
|
||||
<thead>
|
||||
<tr>
|
||||
<td style="width: 160px">{{ t("certd.verifyPlan.websiteDomain") }}</td>
|
||||
<td style="width: 100px; text-align: center">{{ t("certd.verifyPlan.uploadMethod") }}</td>
|
||||
<td style="width: 150px">{{ t("certd.verifyPlan.uploadAccess") }}</td>
|
||||
<td style="width: 200px">{{ t("certd.verifyPlan.websiteRootPath") }}</td>
|
||||
<td style="width: 160px">{{ t("certd.certdomain.verifyPlan.websiteDomain") }}</td>
|
||||
<td style="width: 100px; text-align: center">{{ t("certd.certdomain.verifyPlan.uploadMethod") }}</td>
|
||||
<td style="width: 150px">{{ t("certd.certdomain.verifyPlan.uploadAccess") }}</td>
|
||||
<td style="width: 200px">{{ t("certd.certdomain.verifyPlan.websiteRootPath") }}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody v-if="records" class="http-record-body">
|
||||
@@ -21,7 +21,7 @@
|
||||
<access-selector v-model="item.httpUploaderAccess" :type="item.httpUploaderType" @change="onRecordChange"></access-selector>
|
||||
</td>
|
||||
<td>
|
||||
<a-input v-model:value="item.httpUploadRootDir" :placeholder="t('certd.verifyPlan.websiteRootPlaceholder')" @change="onRecordChange"></a-input>
|
||||
<a-input v-model:value="item.httpUploadRootDir" :placeholder="t('certd.certdomain.verifyPlan.websiteRootPlaceholder')" @change="onRecordChange"></a-input>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
+12
-12
@@ -5,7 +5,7 @@
|
||||
<div class="plan-box bg-white dark:bg-neutral-700">
|
||||
<div class="fullscreen-button pointer flex-center" @click="fullscreen = !fullscreen">
|
||||
<span v-if="!fullscreen" style="font-size: 10px" class="flex-center">
|
||||
{{ t("certd.verifyPlan.expandTip") }}
|
||||
{{ t("certd.certdomain.verifyPlan.expandTip") }}
|
||||
<fs-icon icon="ion:arrow-forward-outline"></fs-icon>
|
||||
</span>
|
||||
<fs-icon :icon="fullscreen ? 'material-symbols:fullscreen-exit' : 'material-symbols:fullscreen'"></fs-icon>
|
||||
@@ -13,9 +13,9 @@
|
||||
<table class="plan-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="min-width: 100px">{{ t("certd.verifyPlan.mainDomain") }}</th>
|
||||
<th>{{ t("certd.verifyPlan.challengeType") }}</th>
|
||||
<th>{{ t("certd.verifyPlan.challengePlan") }}</th>
|
||||
<th style="min-width: 100px">{{ t("certd.certdomain.verifyPlan.mainDomain") }}</th>
|
||||
<th>{{ t("certd.certdomain.verifyPlan.challengeType") }}</th>
|
||||
<th>{{ t("certd.certdomain.verifyPlan.challengePlan") }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -30,13 +30,13 @@
|
||||
<div class="plan">
|
||||
<div v-if="item.type === 'dns'" class="plan-dns">
|
||||
<div class="form-item">
|
||||
<span class="label">{{ t("certd.verifyPlan.dnsType") }}:</span>
|
||||
<span class="label">{{ t("certd.certdomain.verifyPlan.dnsType") }}:</span>
|
||||
<span class="input">
|
||||
<fs-dict-select
|
||||
v-model:value="item.dnsProviderType"
|
||||
size="small"
|
||||
:dict="dnsProviderTypeDict"
|
||||
:placeholder="t('certd.verifyPlan.dnsProvider')"
|
||||
:placeholder="t('certd.certdomain.verifyPlan.dnsProvider')"
|
||||
@change="onPlanChanged"
|
||||
@selected-change="onDnsProviderChange(item, $event)"
|
||||
></fs-dict-select>
|
||||
@@ -44,13 +44,13 @@
|
||||
</div>
|
||||
<a-divider type="vertical" />
|
||||
<div class="form-item">
|
||||
<span class="label">{{ t("certd.verifyPlan.dnsAccess") }}:</span>
|
||||
<span class="label">{{ t("certd.certdomain.verifyPlan.dnsAccess") }}:</span>
|
||||
<span class="input">
|
||||
<access-selector
|
||||
v-model="item.dnsProviderAccessId"
|
||||
size="small"
|
||||
:type="item.dnsProviderAccessType || item.dnsProviderType"
|
||||
:placeholder="t('certd.verifyPlan.pleaseSelect')"
|
||||
:placeholder="t('certd.certdomain.verifyPlan.pleaseSelect')"
|
||||
@change="onPlanChanged"
|
||||
></access-selector>
|
||||
</span>
|
||||
@@ -70,7 +70,7 @@
|
||||
</div>
|
||||
<div v-if="item.type === 'http'" class="plan-http">
|
||||
<http-verify-plan v-model="item.httpVerifyPlan" @change="onPlanChanged" />
|
||||
<div class="helper">{{ t("certd.verifyPlan.httpHelper") }}</div>
|
||||
<div class="helper">{{ t("certd.certdomain.verifyPlan.httpHelper") }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -105,7 +105,7 @@ const { t } = useI18n();
|
||||
|
||||
const challengeTypeOptions = ref<any[]>([
|
||||
{
|
||||
label: t("certd.verifyPlan.dnsChallenge"),
|
||||
label: t("certd.certdomain.verifyPlan.dnsChallenge"),
|
||||
value: "dns",
|
||||
},
|
||||
{
|
||||
@@ -113,11 +113,11 @@ const challengeTypeOptions = ref<any[]>([
|
||||
value: "dns-persist",
|
||||
},
|
||||
{
|
||||
label: t("certd.verifyPlan.cnameChallenge"),
|
||||
label: t("certd.certdomain.verifyPlan.cnameChallenge"),
|
||||
value: "cname",
|
||||
},
|
||||
{
|
||||
label: t("certd.verifyPlan.httpChallenge"),
|
||||
label: t("certd.certdomain.verifyPlan.httpChallenge"),
|
||||
value: "http",
|
||||
},
|
||||
]);
|
||||
|
||||
+6
-6
@@ -14,7 +14,7 @@ function checkDomainVerifyPlan(rule: any, value: DomainsVerifyPlanInput) {
|
||||
for (const subDomain of subDomains) {
|
||||
const plan = value[domain].cnameVerifyPlan[subDomain];
|
||||
if (plan.status !== "valid") {
|
||||
throw new Error($t("certd.verifyPlan.errors.cnameNotValid", { domain: subDomain }));
|
||||
throw new Error($t("certd.certdomain.verifyPlan.errors.cnameNotValid", { domain: subDomain }));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ function checkDomainVerifyPlan(rule: any, value: DomainsVerifyPlanInput) {
|
||||
for (const item of domains) {
|
||||
//如果有通配符域名则不允许使用http校验
|
||||
if (item.startsWith("*.")) {
|
||||
throw new Error($t("certd.verifyPlan.errors.wildcardNotSupportHttp", { domain: item }));
|
||||
throw new Error($t("certd.certdomain.verifyPlan.errors.wildcardNotSupportHttp", { domain: item }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,19 +32,19 @@ function checkDomainVerifyPlan(rule: any, value: DomainsVerifyPlanInput) {
|
||||
for (const subDomain of subDomains) {
|
||||
const plan = value[domain].httpVerifyPlan[subDomain];
|
||||
if (!plan.httpUploaderType) {
|
||||
throw new Error($t("certd.verifyPlan.errors.uploadMethodRequired", { domain: subDomain }));
|
||||
throw new Error($t("certd.certdomain.verifyPlan.errors.uploadMethodRequired", { domain: subDomain }));
|
||||
}
|
||||
if (!plan.httpUploaderAccess) {
|
||||
throw new Error($t("certd.verifyPlan.errors.uploadAccessRequired", { domain: subDomain }));
|
||||
throw new Error($t("certd.certdomain.verifyPlan.errors.uploadAccessRequired", { domain: subDomain }));
|
||||
}
|
||||
if (!plan.httpUploadRootDir) {
|
||||
throw new Error($t("certd.verifyPlan.errors.websiteRootRequired", { domain: subDomain }));
|
||||
throw new Error($t("certd.certdomain.verifyPlan.errors.websiteRootRequired", { domain: subDomain }));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (type === "dns") {
|
||||
if (!value[domain].dnsProviderType || !value[domain].dnsProviderAccessId) {
|
||||
throw new Error($t("certd.verifyPlan.errors.dnsProviderRequired", { domain }));
|
||||
throw new Error($t("certd.certdomain.verifyPlan.errors.dnsProviderRequired", { domain }));
|
||||
}
|
||||
} else if (type === "dns-persist") {
|
||||
const subDomains = Object.keys(value[domain].dnsPersistVerifyPlan || {});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="api-test">
|
||||
<div>
|
||||
<fs-button :loading="loading" type="primary" :text="t('certd.pluginCommon.test')" icon="ion:refresh-outline" @click="doTest"></fs-button>
|
||||
<fs-button :loading="loading" type="primary" :text="t('certd.common.pluginCommon.test')" icon="ion:refresh-outline" @click="doTest"></fs-button>
|
||||
</div>
|
||||
|
||||
<div class="helper" :class="{ error: hasError }">
|
||||
@@ -64,14 +64,14 @@ const doTest = async () => {
|
||||
{
|
||||
onError(err: any) {
|
||||
hasError.value = true;
|
||||
message.value = t("certd.pluginCommon.errorWithMessage", { message: err.message });
|
||||
message.value = t("certd.common.pluginCommon.errorWithMessage", { message: err.message });
|
||||
},
|
||||
showErrorNotify: false,
|
||||
}
|
||||
);
|
||||
message.value = t("certd.pluginCommon.testRequestSuccess");
|
||||
message.value = t("certd.common.pluginCommon.testRequestSuccess");
|
||||
if (res) {
|
||||
message.value += t("certd.pluginCommon.responseSuffix", { response: JSON.stringify(res) });
|
||||
message.value += t("certd.common.pluginCommon.responseSuffix", { response: JSON.stringify(res) });
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
|
||||
@@ -42,7 +42,7 @@ function findStepFromPipeline(targetStepId: string) {
|
||||
const errorRef = ref("");
|
||||
function getStepIdFromInputKey(inputKey: string) {
|
||||
if (!inputKey) {
|
||||
errorRef.value = t("certd.pluginCommon.selectCertFirst");
|
||||
errorRef.value = t("certd.common.pluginCommon.selectCertFirst");
|
||||
return;
|
||||
}
|
||||
return inputKey.split(".")[1];
|
||||
@@ -51,7 +51,7 @@ function getDomainFromPipeline(inputKey: string) {
|
||||
let targetStepId = getStepIdFromInputKey(inputKey);
|
||||
let certStep = findStepFromPipeline(targetStepId);
|
||||
if (!certStep) {
|
||||
errorRef.value = t("certd.pluginCommon.targetStepNotFound");
|
||||
errorRef.value = t("certd.common.pluginCommon.targetStepNotFound");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ function getDomainFromPipeline(inputKey: string) {
|
||||
targetStepId = getStepIdFromInputKey(firstLevelValue);
|
||||
certStep = findStepFromPipeline(targetStepId);
|
||||
if (!certStep) {
|
||||
errorRef.value = t("certd.pluginCommon.targetStepNotFound");
|
||||
errorRef.value = t("certd.common.pluginCommon.targetStepNotFound");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<div class="domain-select">
|
||||
<div class="flex flex-row">
|
||||
<a-select
|
||||
@@ -18,12 +18,12 @@
|
||||
<template v-if="search">
|
||||
<div class="flex w-full items-center justify-between flex-wrap" style="padding: 4px 8px">
|
||||
<div class="flex-1 flex flex-row items-center">
|
||||
<a-input ref="inputRef" v-model:value="searchKeyRef" class="flex-1" allow-clear :placeholder="t('certd.pluginCommon.domainSearchPlaceholder')" @keydown.enter="doSearch" />
|
||||
<fs-button type="primary" class="m-1" :loading="loading" icon="mingcute:search-2-line" @click="doSearch">{{ t("certd.pluginCommon.search") }}</fs-button>
|
||||
<a-input ref="inputRef" v-model:value="searchKeyRef" class="flex-1" allow-clear :placeholder="t('certd.common.pluginCommon.domainSearchPlaceholder')" @keydown.enter="doSearch" />
|
||||
<fs-button type="primary" class="m-1" :loading="loading" icon="mingcute:search-2-line" @click="doSearch">{{ t("certd.common.pluginCommon.search") }}</fs-button>
|
||||
</div>
|
||||
<div class="manager flex flex-row items-center">
|
||||
<fs-button type="primary" class="m-1" icon="mingcute:vip-1-line" @click="openDomainImportDialog">{{ t("certd.pluginCommon.importDomain") }}</fs-button>
|
||||
<fs-button class="m-1" type="primary" icon="carbon:gui-management" @click="openDomainManager">{{ t("certd.pluginCommon.manageDomain") }}</fs-button>
|
||||
<fs-button type="primary" class="m-1" icon="mingcute:vip-1-line" @click="openDomainImportDialog">{{ t("certd.common.pluginCommon.importDomain") }}</fs-button>
|
||||
<fs-button class="m-1" type="primary" icon="carbon:gui-management" @click="openDomainManager">{{ t("certd.common.pluginCommon.manageDomain") }}</fs-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="hasError" class="helper p-2" :class="{ error: hasError }">
|
||||
@@ -49,7 +49,7 @@
|
||||
</a-select>
|
||||
<div class="ml-5 flex flex-row items-center">
|
||||
<fs-button title="复制全部域名" icon="ion:copy-outline" class="domain-select-copy-icon mr-5" @click="copySelectedDomains" />
|
||||
<fs-button :loading="loading" :title="t('certd.pluginCommon.refreshMyDomains')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
<fs-button :loading="loading" :title="t('certd.common.pluginCommon.refreshMyDomains')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="helper" :class="{ error: hasError }">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<a-auto-complete class="remote-auto-complete-input" :filter-option="filterOption" :options="optionsRef" :value="value" v-bind="attrs" @click="onClick" @update:value="emit('update:value', $event)">
|
||||
</a-auto-complete>
|
||||
<div class="ml-5">
|
||||
<fs-button :loading="loading" :title="t('certd.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
<fs-button :loading="loading" :title="t('certd.common.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="helper" :class="{ error: hasError }">
|
||||
@@ -96,16 +96,16 @@ const getOptions = async () => {
|
||||
{
|
||||
onError(err: any) {
|
||||
hasError.value = true;
|
||||
message.value = t("certd.pluginCommon.getOptionsError", { message: err.message });
|
||||
message.value = t("certd.common.pluginCommon.getOptionsError", { message: err.message });
|
||||
},
|
||||
showErrorNotify: false,
|
||||
}
|
||||
);
|
||||
const list = res?.list || res || [];
|
||||
if (list.length > 0) {
|
||||
message.value = t("certd.pluginCommon.getDataSuccessSelect");
|
||||
message.value = t("certd.common.pluginCommon.getDataSuccessSelect");
|
||||
} else {
|
||||
message.value = t("certd.pluginCommon.getDataSuccessEmpty");
|
||||
message.value = t("certd.common.pluginCommon.getDataSuccessEmpty");
|
||||
}
|
||||
optionsRef.value = list;
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ async function openDialog() {
|
||||
saveRemind: false,
|
||||
},
|
||||
afterSubmit() {
|
||||
notification.success({ message: t("certd.operationSuccess") });
|
||||
notification.success({ message: t("certd.common.operationSuccess") });
|
||||
},
|
||||
async doSubmit({ form }: any) {
|
||||
return await doPluginFormSubmit(form);
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
<template #dropdownRender="{ menuNode: menu }">
|
||||
<template v-if="search">
|
||||
<div class="flex w-full" style="padding: 4px 8px">
|
||||
<a-input ref="inputRef" v-model:value="searchKeyRef" class="flex-1" allow-clear :placeholder="t('certd.pluginCommon.searchKeyword')" @keydown.enter="doSearch" />
|
||||
<a-input ref="inputRef" v-model:value="searchKeyRef" class="flex-1" allow-clear :placeholder="t('certd.common.pluginCommon.searchKeyword')" @keydown.enter="doSearch" />
|
||||
<a-button class="ml-2" :loading="loading" type="text" @click="doSearch">
|
||||
<template #icon>
|
||||
<search-outlined />
|
||||
</template>
|
||||
{{ t("certd.pluginCommon.search") }}
|
||||
{{ t("certd.common.pluginCommon.search") }}
|
||||
</a-button>
|
||||
</div>
|
||||
<div v-if="hasError" class="helper p-2" :class="{ error: hasError }">
|
||||
@@ -26,7 +26,7 @@
|
||||
</template>
|
||||
</a-select>
|
||||
<div class="ml-5 flex flex-row no-wrap">
|
||||
<fs-button :loading="loading" :title="t('certd.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
<fs-button :loading="loading" :title="t('certd.common.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
<UploadCert v-if="uploadCert" class="ml-5" v-bind="uploadCert" @submit="refreshOptions"></UploadCert>
|
||||
</div>
|
||||
</div>
|
||||
@@ -177,7 +177,7 @@ const getOptions = async () => {
|
||||
{
|
||||
onError(err: any) {
|
||||
hasError.value = true;
|
||||
message.value = t("certd.pluginCommon.getOptionsError", { message: err.message });
|
||||
message.value = t("certd.common.pluginCommon.getOptionsError", { message: err.message });
|
||||
optionsRef.value = [];
|
||||
},
|
||||
showErrorNotify: false,
|
||||
@@ -185,9 +185,9 @@ const getOptions = async () => {
|
||||
);
|
||||
let list = res?.list || res || [];
|
||||
if (list.length > 0) {
|
||||
message.value = t("certd.pluginCommon.getDataSuccessSelect");
|
||||
message.value = t("certd.common.pluginCommon.getDataSuccessSelect");
|
||||
} else {
|
||||
message.value = t("certd.pluginCommon.getDataSuccessEmpty");
|
||||
message.value = t("certd.common.pluginCommon.getDataSuccessEmpty");
|
||||
}
|
||||
list = list.map((item: any) => {
|
||||
return {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="flex flex-row">
|
||||
<a-tree-select class="remote-tree-select-input" :tree-data="optionsRef" :value="value" tree-checkable allow-clear v-bind="attrs" @click="onClick" @update:value="emit('update:value', $event)"> </a-tree-select>
|
||||
<div class="ml-5">
|
||||
<fs-button :loading="loading" :title="t('certd.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
<fs-button :loading="loading" :title="t('certd.common.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="helper" :class="{ error: hasError }">
|
||||
@@ -107,16 +107,16 @@ const getOptions = async () => {
|
||||
{
|
||||
onError(err: any) {
|
||||
hasError.value = true;
|
||||
message.value = t("certd.pluginCommon.getOptionsError", { message: err.message });
|
||||
message.value = t("certd.common.pluginCommon.getOptionsError", { message: err.message });
|
||||
},
|
||||
showErrorNotify: false,
|
||||
}
|
||||
);
|
||||
const list = res?.list || res || [];
|
||||
if (list.length > 0) {
|
||||
message.value = t("certd.pluginCommon.getDataSuccessSelect");
|
||||
message.value = t("certd.common.pluginCommon.getDataSuccessSelect");
|
||||
} else {
|
||||
message.value = t("certd.pluginCommon.getDataSuccessEmpty");
|
||||
message.value = t("certd.common.pluginCommon.getDataSuccessEmpty");
|
||||
}
|
||||
optionsRef.value = list;
|
||||
pagerRef.value.total = list.length;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="upload-cert">
|
||||
<fs-button v-model:loading="loading" type="primary" :text="t('certd.pluginCommon.upload')" v-bind="props.button" @click="openUploadCertDialog"></fs-button>
|
||||
<fs-button v-model:loading="loading" type="primary" :text="t('certd.common.pluginCommon.upload')" v-bind="props.button" @click="openUploadCertDialog"></fs-button>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
@@ -30,18 +30,18 @@ const getScope: any = inject("get:scope", () => {
|
||||
const getPluginType: any = inject("get:plugin:type", () => {
|
||||
return "plugin";
|
||||
});
|
||||
const title = computed(() => props.title || t("certd.pluginCommon.uploadCert"));
|
||||
const title = computed(() => props.title || t("certd.common.pluginCommon.uploadCert"));
|
||||
function openUploadCertDialog() {
|
||||
const columns = merge(
|
||||
{
|
||||
certName: {
|
||||
title: t("certd.pluginCommon.certName"),
|
||||
title: t("certd.common.pluginCommon.certName"),
|
||||
form: {
|
||||
component: {
|
||||
name: "a-input",
|
||||
vModel: "value",
|
||||
},
|
||||
helper: t("certd.pluginCommon.certNameHelper"),
|
||||
helper: t("certd.common.pluginCommon.certNameHelper"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -51,7 +51,7 @@ function openUploadCertDialog() {
|
||||
title: title.value,
|
||||
columns: {
|
||||
certName: {
|
||||
title: t("certd.pluginCommon.certName"),
|
||||
title: t("certd.common.pluginCommon.certName"),
|
||||
form: {
|
||||
component: {
|
||||
name: "a-input",
|
||||
@@ -86,7 +86,7 @@ function openUploadCertDialog() {
|
||||
showErrorNotify: true,
|
||||
}
|
||||
);
|
||||
notification.success({ message: t("certd.pluginCommon.uploadSuccess") });
|
||||
notification.success({ message: t("certd.common.pluginCommon.uploadSuccess") });
|
||||
emit("submit");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
|
||||
@@ -4,10 +4,10 @@ import { $t } from "/@/locales";
|
||||
function createChallengeTypeDict() {
|
||||
return dict({
|
||||
data: [
|
||||
{ value: "dns", label: $t("certd.verifyPlan.dnsChallenge"), color: "green" },
|
||||
{ value: "dns", label: $t("certd.certdomain.verifyPlan.dnsChallenge"), color: "green" },
|
||||
{ value: "dns-persist", label: "DNS持久验证", color: "cyan" },
|
||||
{ value: "cname", label: $t("certd.verifyPlan.cnameProxyChallenge"), color: "blue" },
|
||||
{ value: "http", label: $t("certd.verifyPlan.httpChallenge"), color: "yellow" },
|
||||
{ value: "cname", label: $t("certd.certdomain.verifyPlan.cnameProxyChallenge"), color: "blue" },
|
||||
{ value: "http", label: $t("certd.certdomain.verifyPlan.httpChallenge"), color: "yellow" },
|
||||
],
|
||||
});
|
||||
}
|
||||
@@ -18,11 +18,11 @@ function createUploaderTypeDict() {
|
||||
{ label: "SFTP", value: "sftp" },
|
||||
{ label: "SCP", value: "scp" },
|
||||
{ label: "FTP", value: "ftp" },
|
||||
{ label: $t("certd.verifyPlan.uploader.aliyunOss"), value: "alioss" },
|
||||
{ label: $t("certd.verifyPlan.uploader.tencentCos"), value: "tencentcos" },
|
||||
{ label: $t("certd.verifyPlan.uploader.qiniuOss"), value: "qiniuoss" },
|
||||
{ label: $t("certd.certdomain.verifyPlan.uploader.aliyunOss"), value: "alioss" },
|
||||
{ label: $t("certd.certdomain.verifyPlan.uploader.tencentCos"), value: "tencentcos" },
|
||||
{ label: $t("certd.certdomain.verifyPlan.uploader.qiniuOss"), value: "qiniuoss" },
|
||||
{ label: "S3/Minio", value: "s3" },
|
||||
{ label: $t("certd.verifyPlan.uploader.sshDeprecated"), value: "ssh", disabled: true },
|
||||
{ label: $t("certd.certdomain.verifyPlan.uploader.sshDeprecated"), value: "ssh", disabled: true },
|
||||
],
|
||||
});
|
||||
}
|
||||
@@ -30,8 +30,8 @@ function createUploaderTypeDict() {
|
||||
function createDomainFromTypeDict() {
|
||||
return dict({
|
||||
data: [
|
||||
{ value: "manual", label: $t("certd.verifyPlan.domainFrom.manual") },
|
||||
{ value: "auto", label: $t("certd.verifyPlan.domainFrom.auto") },
|
||||
{ value: "manual", label: $t("certd.certdomain.verifyPlan.domainFrom.manual") },
|
||||
{ value: "auto", label: $t("certd.certdomain.verifyPlan.domainFrom.auto") },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -33,11 +33,11 @@ const { t } = useI18n();
|
||||
<div class="tutorial-button pointer" @click="open">
|
||||
<template v-if="!slots.default">
|
||||
<fs-icon v-if="showIcon === false" icon="ant-design:question-circle-outlined" class="mr-0.5"></fs-icon>
|
||||
<div class="hidden md:block">{{ t("tutorial.title") }}</div>
|
||||
<div class="hidden md:block">{{ t("certd.tutorial.title") }}</div>
|
||||
</template>
|
||||
<slot></slot>
|
||||
<a-modal v-model:open="openedRef" class="tutorial-modal" width="90%">
|
||||
<template #title>{{ t("tutorial.title") }}</template>
|
||||
<template #title>{{ t("certd.tutorial.title") }}</template>
|
||||
<tutorial-steps v-if="openedRef" />
|
||||
<template #footer></template>
|
||||
</a-modal>
|
||||
|
||||
@@ -18,9 +18,9 @@ import { ref } from "vue";
|
||||
import { mitter } from "/@/utils/util.mitt";
|
||||
|
||||
const steps = ref<Step[]>([
|
||||
{ title: t("certd.steps.createPipeline"), icon: <fs-icon icon="tabler:circle-number-1-filled"></fs-icon> },
|
||||
{ title: t("certd.steps.addTask"), icon: <fs-icon icon="tabler:circle-number-2-filled"></fs-icon> },
|
||||
{ title: t("certd.steps.scheduledRun"), icon: <fs-icon icon="tabler:circle-number-3-filled"></fs-icon> },
|
||||
{ title: t("certd.tutorial.steps.createPipeline"), icon: <fs-icon icon="tabler:circle-number-1-filled"></fs-icon> },
|
||||
{ title: t("certd.tutorial.steps.addTask"), icon: <fs-icon icon="tabler:circle-number-2-filled"></fs-icon> },
|
||||
{ title: t("certd.tutorial.steps.scheduledRun"), icon: <fs-icon icon="tabler:circle-number-3-filled"></fs-icon> },
|
||||
]);
|
||||
|
||||
function goPipeline() {
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
</div>
|
||||
|
||||
<div class="flex-center actions">
|
||||
<fs-button class="m-10" icon="ion:arrow-back-outline" @click="prev()">{{ t("guide.buttons.prev") }}</fs-button>
|
||||
<fs-button class="m-10" type="primary" icon-right="ion:arrow-forward-outline" @click="next()">{{ t("guide.buttons.next") }}</fs-button>
|
||||
<fs-button class="m-10" icon="ion:arrow-back-outline" @click="prev()">{{ t("certd.guide.buttons.prev") }}</fs-button>
|
||||
<fs-button class="m-10" type="primary" icon-right="ion:arrow-forward-outline" @click="next()">{{ t("certd.guide.buttons.next") }}</fs-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -52,126 +52,126 @@ import { computed, nextTick, ref } from "vue";
|
||||
|
||||
const steps = ref<Step[]>([
|
||||
{
|
||||
title: t("guide.createCertPipeline.title"),
|
||||
description: t("guide.createCertPipeline.description"),
|
||||
title: t("certd.guide.createCertPipeline.title"),
|
||||
description: t("certd.guide.createCertPipeline.description"),
|
||||
items: [
|
||||
{
|
||||
title: t("guide.createCertPipeline.items.tutorialTitle"),
|
||||
descriptions: [t("guide.createCertPipeline.items.tutorialDesc1"), t("guide.createCertPipeline.items.tutorialDesc2")],
|
||||
title: t("certd.guide.createCertPipeline.items.tutorialTitle"),
|
||||
descriptions: [t("certd.guide.createCertPipeline.items.tutorialDesc1"), t("certd.guide.createCertPipeline.items.tutorialDesc2")],
|
||||
body: () => {
|
||||
return <SimpleSteps></SimpleSteps>;
|
||||
},
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/1-add.png",
|
||||
title: t("guide.createCertPipeline.items.createTitle"),
|
||||
descriptions: [t("guide.createCertPipeline.items.createDesc")],
|
||||
title: t("certd.guide.createCertPipeline.items.createTitle"),
|
||||
descriptions: [t("certd.guide.createCertPipeline.items.createDesc")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/3-add-success.png",
|
||||
title: t("guide.createCertPipeline.items.successTitle"),
|
||||
descriptions: [t("guide.createCertPipeline.items.successDesc")],
|
||||
title: t("certd.guide.createCertPipeline.items.successTitle"),
|
||||
descriptions: [t("certd.guide.createCertPipeline.items.successDesc")],
|
||||
},
|
||||
// {
|
||||
// title: t("guide.createCertPipeline.items.nextTitle"),
|
||||
// descriptions: [t("guide.createCertPipeline.items.nextDesc")],
|
||||
// title: t("certd.guide.createCertPipeline.items.nextTitle"),
|
||||
// descriptions: [t("certd.guide.createCertPipeline.items.nextDesc")],
|
||||
// },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: t("guide.addDeployTask.title"),
|
||||
description: t("guide.addDeployTask.description"),
|
||||
title: t("certd.guide.addDeployTask.title"),
|
||||
description: t("certd.guide.addDeployTask.description"),
|
||||
items: [
|
||||
{
|
||||
image: "/static/doc/images/5-1-add-host.png",
|
||||
title: t("guide.addDeployTask.items.addTaskTitle"),
|
||||
descriptions: [t("guide.addDeployTask.items.addTaskDesc1"), t("guide.addDeployTask.items.addTaskDesc2")],
|
||||
title: t("certd.guide.addDeployTask.items.addTaskTitle"),
|
||||
descriptions: [t("certd.guide.addDeployTask.items.addTaskDesc1"), t("certd.guide.addDeployTask.items.addTaskDesc2")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/5-2-add-host.png",
|
||||
title: t("guide.addDeployTask.items.fillParamsTitle"),
|
||||
descriptions: [t("guide.addDeployTask.items.fillParamsDesc1"), t("guide.addDeployTask.items.fillParamsDesc2")],
|
||||
title: t("certd.guide.addDeployTask.items.fillParamsTitle"),
|
||||
descriptions: [t("certd.guide.addDeployTask.items.fillParamsDesc1"), t("certd.guide.addDeployTask.items.fillParamsDesc2")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/5-3-add-host.png",
|
||||
title: t("guide.addDeployTask.items.activateCertTitle"),
|
||||
descriptions: [t("guide.addDeployTask.items.activateCertDesc1"), t("guide.addDeployTask.items.activateCertDesc2")],
|
||||
title: t("certd.guide.addDeployTask.items.activateCertTitle"),
|
||||
descriptions: [t("certd.guide.addDeployTask.items.activateCertDesc1"), t("certd.guide.addDeployTask.items.activateCertDesc2")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/5-4-add-host.png",
|
||||
title: t("guide.addDeployTask.items.taskSuccessTitle"),
|
||||
descriptions: [t("guide.addDeployTask.items.taskSuccessDesc")],
|
||||
title: t("certd.guide.addDeployTask.items.taskSuccessTitle"),
|
||||
descriptions: [t("certd.guide.addDeployTask.items.taskSuccessDesc")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/5-5-plugin-list.png",
|
||||
title: t("guide.addDeployTask.items.pluginsTitle"),
|
||||
descriptions: [t("guide.addDeployTask.items.pluginsDesc")],
|
||||
title: t("certd.guide.addDeployTask.items.pluginsTitle"),
|
||||
descriptions: [t("certd.guide.addDeployTask.items.pluginsDesc")],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: t("guide.runAndTestTask.runAndTestTitle"),
|
||||
description: t("guide.runAndTestTask.runAndTestDescription"),
|
||||
title: t("certd.guide.runAndTestTask.runAndTestTitle"),
|
||||
description: t("certd.guide.runAndTestTask.runAndTestDescription"),
|
||||
items: [
|
||||
{
|
||||
image: "/static/doc/images/9-start.png",
|
||||
title: t("guide.runAndTestTask.runTestOnce"),
|
||||
descriptions: [t("guide.runAndTestTask.clickManualTriggerToTest")],
|
||||
title: t("certd.guide.runAndTestTask.runTestOnce"),
|
||||
descriptions: [t("certd.guide.runAndTestTask.clickManualTriggerToTest")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/10-1-log.png",
|
||||
title: t("guide.runAndTestTask.viewLogs"),
|
||||
descriptions: [t("guide.runAndTestTask.clickTaskToViewStatusAndLogs")],
|
||||
title: t("certd.guide.runAndTestTask.viewLogs"),
|
||||
descriptions: [t("certd.guide.runAndTestTask.clickTaskToViewStatusAndLogs")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/11-1-error.png",
|
||||
title: t("guide.runAndTestTask.howToTroubleshootFailure"),
|
||||
descriptions: [t("guide.runAndTestTask.viewErrorLogs")],
|
||||
title: t("certd.guide.runAndTestTask.howToTroubleshootFailure"),
|
||||
descriptions: [t("certd.guide.runAndTestTask.viewErrorLogs")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/11-2-error.png",
|
||||
title: t("guide.runAndTestTask.howToTroubleshootFailure"),
|
||||
descriptions: [t("guide.runAndTestTask.viewErrorLogs"), t("guide.runAndTestTask.nginxContainerNotExistFix")],
|
||||
title: t("certd.guide.runAndTestTask.howToTroubleshootFailure"),
|
||||
descriptions: [t("certd.guide.runAndTestTask.viewErrorLogs"), t("certd.guide.runAndTestTask.nginxContainerNotExistFix")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/12-1-log-success.png",
|
||||
title: t("guide.runAndTestTask.executionSuccess"),
|
||||
descriptions: [t("guide.runAndTestTask.retryAfterFix")],
|
||||
title: t("certd.guide.runAndTestTask.executionSuccess"),
|
||||
descriptions: [t("certd.guide.runAndTestTask.retryAfterFix")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/12-2-skip-log.png",
|
||||
title: t("guide.runAndTestTask.autoSkipAfterSuccess"),
|
||||
descriptions: [t("guide.runAndTestTask.successSkipExplanation")],
|
||||
title: t("certd.guide.runAndTestTask.autoSkipAfterSuccess"),
|
||||
descriptions: [t("certd.guide.runAndTestTask.successSkipExplanation")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/13-1-result.png",
|
||||
title: t("guide.runAndTestTask.viewCertDeploymentSuccess"),
|
||||
descriptions: [t("guide.runAndTestTask.visitNginxToSeeCert")],
|
||||
title: t("certd.guide.runAndTestTask.viewCertDeploymentSuccess"),
|
||||
descriptions: [t("certd.guide.runAndTestTask.visitNginxToSeeCert")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/13-3-download.png",
|
||||
title: t("guide.runAndTestTask.downloadCertManualDeploy"),
|
||||
descriptions: [t("guide.runAndTestTask.downloadIfNoAutoDeployPlugin")],
|
||||
title: t("certd.guide.runAndTestTask.downloadCertManualDeploy"),
|
||||
descriptions: [t("certd.guide.runAndTestTask.downloadIfNoAutoDeployPlugin")],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: t("guide.scheduleAndEmailTask.title"),
|
||||
description: t("guide.scheduleAndEmailTask.description"),
|
||||
title: t("certd.guide.scheduleAndEmailTask.title"),
|
||||
description: t("certd.guide.scheduleAndEmailTask.description"),
|
||||
items: [
|
||||
{
|
||||
image: "/static/doc/images/14-timer.png",
|
||||
title: t("guide.scheduleAndEmailTask.setSchedule"),
|
||||
descriptions: [t("guide.scheduleAndEmailTask.pipelineSuccessThenSchedule"), t("guide.scheduleAndEmailTask.recommendDailyRun")],
|
||||
title: t("certd.guide.scheduleAndEmailTask.setSchedule"),
|
||||
descriptions: [t("certd.guide.scheduleAndEmailTask.pipelineSuccessThenSchedule"), t("certd.guide.scheduleAndEmailTask.recommendDailyRun")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/15-1-email.png",
|
||||
title: t("guide.scheduleAndEmailTask.setEmailNotification"),
|
||||
descriptions: [t("guide.scheduleAndEmailTask.suggestErrorAndRecoveryEmails")],
|
||||
title: t("certd.guide.scheduleAndEmailTask.setEmailNotification"),
|
||||
descriptions: [t("certd.guide.scheduleAndEmailTask.suggestErrorAndRecoveryEmails")],
|
||||
},
|
||||
{
|
||||
title: t("guide.scheduleAndEmailTask.tutorialEndTitle"),
|
||||
descriptions: [t("guide.scheduleAndEmailTask.thanksForWatching")],
|
||||
title: t("certd.guide.scheduleAndEmailTask.tutorialEndTitle"),
|
||||
descriptions: [t("certd.guide.scheduleAndEmailTask.thanksForWatching")],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -48,56 +48,56 @@ const text = computed<Text>(() => {
|
||||
const map = {
|
||||
isComm: {
|
||||
comm: {
|
||||
name: t("vip.comm.name", { vipLabel }),
|
||||
title: t("vip.comm.title", { expire: expireTime.value }),
|
||||
name: t("certd.vip.comm.name", { vipLabel }),
|
||||
title: t("certd.vip.comm.title", { expire: expireTime.value }),
|
||||
},
|
||||
button: {
|
||||
name: t("vip.comm.name", { vipLabel }),
|
||||
title: t("vip.comm.title", { expire: expireTime.value }),
|
||||
name: t("certd.vip.comm.name", { vipLabel }),
|
||||
title: t("certd.vip.comm.title", { expire: expireTime.value }),
|
||||
},
|
||||
icon: {
|
||||
name: "",
|
||||
title: t("vip.comm.name", { vipLabel }),
|
||||
title: t("certd.vip.comm.name", { vipLabel }),
|
||||
},
|
||||
nav: {
|
||||
name: t("vip.comm.nav", { vipLabel }),
|
||||
title: t("vip.comm.title", { expire: expireTime.value }),
|
||||
name: t("certd.vip.comm.nav", { vipLabel }),
|
||||
title: t("certd.vip.comm.title", { expire: expireTime.value }),
|
||||
},
|
||||
},
|
||||
isPlus: {
|
||||
comm: {
|
||||
name: t("vip.plus.name"),
|
||||
title: t("vip.plus.title"),
|
||||
name: t("certd.vip.plus.name"),
|
||||
title: t("certd.vip.plus.title"),
|
||||
},
|
||||
button: {
|
||||
name: t("vip.comm.name", { vipLabel }),
|
||||
title: t("vip.comm.title", { expire: expireTime.value }),
|
||||
name: t("certd.vip.comm.name", { vipLabel }),
|
||||
title: t("certd.vip.comm.title", { expire: expireTime.value }),
|
||||
},
|
||||
icon: {
|
||||
name: "",
|
||||
title: t("vip.comm.name", { vipLabel }),
|
||||
title: t("certd.vip.comm.name", { vipLabel }),
|
||||
},
|
||||
nav: {
|
||||
name: t("vip.comm.nav", { vipLabel }),
|
||||
title: t("vip.comm.title", { expire: expireTime.value }),
|
||||
name: t("certd.vip.comm.nav", { vipLabel }),
|
||||
title: t("certd.vip.comm.title", { expire: expireTime.value }),
|
||||
},
|
||||
},
|
||||
free: {
|
||||
comm: {
|
||||
name: t("vip.free.comm.name"),
|
||||
title: t("vip.free.comm.title"),
|
||||
name: t("certd.vip.free.comm.name"),
|
||||
title: t("certd.vip.free.comm.title"),
|
||||
},
|
||||
button: {
|
||||
name: t("vip.free.button.name"),
|
||||
title: t("vip.free.button.title"),
|
||||
name: t("certd.vip.free.button.name"),
|
||||
title: t("certd.vip.free.button.title"),
|
||||
},
|
||||
icon: {
|
||||
name: "",
|
||||
title: t("vip.free.button.name"),
|
||||
title: t("certd.vip.free.button.name"),
|
||||
},
|
||||
nav: {
|
||||
name: t("vip.free.nav.name"),
|
||||
title: plusMessage || t("vip.free.nav.title"),
|
||||
name: t("certd.vip.free.nav.name"),
|
||||
title: plusMessage || t("certd.vip.free.nav.title"),
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -131,7 +131,7 @@ const userStore = useUserStore();
|
||||
|
||||
async function getVipTrial(vipType = "plus") {
|
||||
const res = await api.getVipTrial(vipType);
|
||||
notification.success({ message: t("vip.congratulations_vip_trial", { duration: res.duration }) });
|
||||
notification.success({ message: t("certd.vip.congratulations_vip_trial", { duration: res.duration }) });
|
||||
await settingStore.init();
|
||||
}
|
||||
|
||||
@@ -139,8 +139,8 @@ function openTrialModal(vipType = "plus") {
|
||||
Modal.destroyAll();
|
||||
|
||||
modal.confirm({
|
||||
title: t("vip.trial_modal_title"),
|
||||
okText: t("vip.trial_modal_ok_text"),
|
||||
title: t("certd.vip.trial_modal_title"),
|
||||
okText: t("certd.vip.trial_modal_ok_text"),
|
||||
onOk() {
|
||||
getVipTrial(vipType);
|
||||
},
|
||||
@@ -148,8 +148,8 @@ function openTrialModal(vipType = "plus") {
|
||||
content: () => {
|
||||
return (
|
||||
<div class="flex-col mt-10 mb-10">
|
||||
<div>{t("vip.trial_modal_thanks")}</div>
|
||||
<div>{t("vip.trial_modal_click_confirm", { vipType })}</div>
|
||||
<div>{t("certd.vip.trial_modal_thanks")}</div>
|
||||
<div>{t("certd.vip.trial_modal_click_confirm", { vipType })}</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
@@ -158,7 +158,7 @@ function openTrialModal(vipType = "plus") {
|
||||
|
||||
function openStarModal(vipType: string) {
|
||||
if (settingStore.isPlus) {
|
||||
notification.error({ message: t("vip.already_vip") });
|
||||
notification.error({ message: t("certd.vip.already_vip") });
|
||||
return;
|
||||
}
|
||||
Modal.destroyAll();
|
||||
@@ -170,8 +170,8 @@ function openStarModal(vipType: string) {
|
||||
// };
|
||||
|
||||
// modal.confirm({
|
||||
// title: t("vip.get_7_day_pro_trial"),
|
||||
// okText: t("vip.star_now"),
|
||||
// title: t("certd.vip.get_7_day_pro_trial"),
|
||||
// okText: t("certd.vip.star_now"),
|
||||
// onOk() {
|
||||
// goGithub();
|
||||
// openTrialModal(vipType);
|
||||
@@ -180,7 +180,7 @@ function openStarModal(vipType: string) {
|
||||
// content: () => {
|
||||
// return (
|
||||
// <div class="flex mt-10 mb-10">
|
||||
// <div>{t("vip.please_help_star")}</div>
|
||||
// <div>{t("certd.vip.please_help_star")}</div>
|
||||
// <img class="ml-5" src="https://img.shields.io/github/stars/certd/certd?logo=github" />
|
||||
// </div>
|
||||
// );
|
||||
@@ -190,16 +190,16 @@ function openStarModal(vipType: string) {
|
||||
|
||||
function openUpgrade() {
|
||||
if (!userStore.isAdmin) {
|
||||
notification.info({ message: t("vip.admin_only_operation") });
|
||||
notification.info({ message: t("certd.vip.admin_only_operation") });
|
||||
return;
|
||||
}
|
||||
const placeholder = t("vip.enter_activation_code");
|
||||
const placeholder = t("certd.vip.enter_activation_code");
|
||||
const isPlus = settingStore.isPlus;
|
||||
let title = t("vip.activate_pro_business");
|
||||
let title = t("certd.vip.activate_pro_business");
|
||||
if (settingStore.isComm) {
|
||||
title = t("vip.renew_business");
|
||||
title = t("certd.vip.renew_business");
|
||||
} else if (settingStore.isPlus) {
|
||||
title = t("vip.renew_pro_upgrade_business");
|
||||
title = t("certd.vip.renew_pro_upgrade_business");
|
||||
}
|
||||
|
||||
// const goBuyUrl = "https://afdian.com/a/greper"
|
||||
@@ -214,10 +214,10 @@ function openUpgrade() {
|
||||
function checkPerpetualPlus() {
|
||||
if (settingStore.isPerpetual) {
|
||||
Modal.warn({
|
||||
title: t("vip.already_perpetual_plus"),
|
||||
okText: t("vip.confirm"),
|
||||
title: t("certd.vip.already_perpetual_plus"),
|
||||
okText: t("certd.vip.confirm"),
|
||||
});
|
||||
throw new Error(t("vip.already_perpetual_plus"));
|
||||
throw new Error(t("certd.vip.already_perpetual_plus"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,8 +225,8 @@ function openUpgrade() {
|
||||
checkPerpetualPlus();
|
||||
if (settingStore.isComm) {
|
||||
Modal.warn({
|
||||
title: t("vip.already_comm"),
|
||||
okText: t("vip.confirm"),
|
||||
title: t("certd.vip.already_comm"),
|
||||
okText: t("certd.vip.confirm"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -237,8 +237,8 @@ function openUpgrade() {
|
||||
checkPerpetualPlus();
|
||||
if (settingStore.isPlus && !settingStore.isComm) {
|
||||
Modal.confirm({
|
||||
title: t("vip.already_plus"),
|
||||
okText: t("vip.confirm"),
|
||||
title: t("certd.vip.already_plus"),
|
||||
okText: t("certd.vip.confirm"),
|
||||
onOk() {
|
||||
window.open(goBuyCommUrl);
|
||||
},
|
||||
@@ -251,7 +251,7 @@ function openUpgrade() {
|
||||
title,
|
||||
class: "vip-modal",
|
||||
maskClosable: true,
|
||||
okText: t("vip.close"),
|
||||
okText: t("certd.vip.close"),
|
||||
width: 1180,
|
||||
content: () => {
|
||||
return <VipModalContent placeholder={placeholder} isPlus={isPlus} productInfo={productInfo} goBuyPlusPage={goBuyPlusPage} goBuyCommPage={goBuyCommPage} openStarModal={openStarModal} modalRef={modalRef} />;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<span v-else>
|
||||
<span class="price-text">{{ t("vip.freee") }}</span>
|
||||
<span class="price-text">{{ t("certd.vip.freee") }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="get-show">
|
||||
@@ -44,15 +44,15 @@
|
||||
<span class="color-red"> {{ todayOrderCount.vipTotal }}</span>
|
||||
位伙伴支持
|
||||
</span>
|
||||
<a-tooltip :title="t('vip.afdian_support_vip')">
|
||||
<a-tooltip :title="t('certd.vip.afdian_support_vip')">
|
||||
<a-button size="small" type="primary" @click="goBuyPlusPage">
|
||||
{{ t("vip.get_after_support") }}
|
||||
{{ t("certd.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") }}
|
||||
{{ t("certd.vip.buy") }}
|
||||
</a-button>
|
||||
</template>
|
||||
</div>
|
||||
@@ -63,36 +63,36 @@
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://certd.docmirror.cn/guide/donate/#相关问题" target="_blank">
|
||||
{{ t("vip.question") }}
|
||||
{{ t("certd.vip.question") }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="mt-10">
|
||||
<div class="w-100 flex-col md:flex-row">
|
||||
<span>{{ t("vip.site_id") }}:</span>
|
||||
<span>{{ t("certd.vip.site_id") }}:</span>
|
||||
<fs-copyable v-model="computedSiteId" class="mr-2 inline-flex"></fs-copyable>
|
||||
<a @click="goBindAccount">{{ t("vip.not_effective") }}</a>
|
||||
<a @click="goBindAccount">{{ t("certd.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>
|
||||
<span class="mr-2"> {{ t("certd.vip.current") }} {{ vipLabel }} {{ t("certd.vip.activated_expire_time") }} {{ settingStore.expiresText }} </span>
|
||||
<a href="https://app.handfree.work/subject/#/page/detail/1" target="_blank">
|
||||
{{ t("vip.learn_more") }}
|
||||
{{ t("certd.vip.learn_more") }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="mt-10">
|
||||
<span class="mr-2">{{ t("vip.have_activation_code") }}</span>
|
||||
<span class="mr-2">{{ t("certd.vip.have_activation_code") }}</span>
|
||||
<span>
|
||||
<a @click="showManualActivation">{{ t("vip.manual_activation") }}</a>
|
||||
<a @click="showManualActivation">{{ t("certd.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>
|
||||
<a-input-search v-model:value="formState.code" class="w-2/6" :placeholder="placeholder" :enter-button="t('certd.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") }}
|
||||
{{ t("certd.vip.activation_code_one_use") }}
|
||||
<a @click="goAccount">{{ t("certd.vip.bind_account") }}</a
|
||||
>,{{ t("certd.vip.transfer_vip") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -128,24 +128,24 @@ const formState = reactive({
|
||||
|
||||
async function doActive() {
|
||||
if (!formState.code) {
|
||||
notification.error({ message: t("vip.enterCode") });
|
||||
throw new Error(t("vip.enterCode"));
|
||||
notification.error({ message: t("certd.vip.enterCode") });
|
||||
throw new Error(t("certd.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", {
|
||||
title: t("certd.vip.successTitle"),
|
||||
content: t("certd.vip.successContent", {
|
||||
vipLabel,
|
||||
expireDate: settingStore.plusInfo.expireTime === -1 ? t("vip.permanent") : dayjs(settingStore.plusInfo.expireTime).format("YYYY-MM-DD"),
|
||||
expireDate: settingStore.plusInfo.expireTime === -1 ? t("certd.vip.permanent") : dayjs(settingStore.plusInfo.expireTime).format("YYYY-MM-DD"),
|
||||
}),
|
||||
onOk() {
|
||||
if (!(settingStore.installInfo.bindUserId > 0)) {
|
||||
Modal.confirm({
|
||||
title: t("vip.bindAccountTitle"),
|
||||
content: t("vip.bindAccountContent"),
|
||||
title: t("certd.vip.bindAccountTitle"),
|
||||
content: t("certd.vip.bindAccountContent"),
|
||||
onOk() {
|
||||
router.push("/sys/account");
|
||||
},
|
||||
@@ -179,39 +179,39 @@ function goBindAccount() {
|
||||
|
||||
const vipTypeDefine: any = {
|
||||
free: {
|
||||
title: t("vip.basic_edition"),
|
||||
desc: t("vip.community_free_version"),
|
||||
title: t("certd.vip.basic_edition"),
|
||||
desc: t("certd.vip.community_free_version"),
|
||||
type: "free",
|
||||
icon: "lucide:package-open",
|
||||
privilege: t("vip.free_privilege").split("\n"),
|
||||
privilege: t("certd.vip.free_privilege").split("\n"),
|
||||
},
|
||||
plus: {
|
||||
title: t("vip.professional_edition"),
|
||||
desc: t("vip.open_source_support"),
|
||||
title: t("certd.vip.professional_edition"),
|
||||
desc: t("certd.vip.open_source_support"),
|
||||
type: "plus",
|
||||
privilege: t("vip.plus_privilege").split("\n"),
|
||||
privilege: t("certd.vip.plus_privilege").split("\n"),
|
||||
trial: {
|
||||
title: t("vip.click_to_get_7_day_trial"),
|
||||
title: t("certd.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")}`,
|
||||
priceText: props.productInfo.plus.priceText || `¥${props.productInfo.plus.price}/${t("certd.vip.years")}`,
|
||||
discountText: props.productInfo.plus.discountText || `¥${props.productInfo.plus.price3}/3${t("certd.vip.years")}`,
|
||||
tooltip: props.productInfo.plus.tooltip,
|
||||
},
|
||||
comm: {
|
||||
title: t("vip.business_edition"),
|
||||
desc: t("vip.commercial_license"),
|
||||
title: t("certd.vip.business_edition"),
|
||||
desc: t("certd.vip.commercial_license"),
|
||||
type: "comm",
|
||||
icon: "vaadin:handshake",
|
||||
privilege: t("vip.comm_privilege").split("\n"),
|
||||
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")}`,
|
||||
privilege: t("certd.vip.comm_privilege").split("\n"),
|
||||
priceText: props.productInfo.comm.priceText || `¥${props.productInfo.comm.price}/${t("certd.vip.years")}`,
|
||||
discountText: props.productInfo.comm.discountText || `¥${props.productInfo.comm.price3}/3${t("certd.vip.years")}`,
|
||||
tooltip: props.productInfo.comm.tooltip,
|
||||
trial: {
|
||||
title: t("vip.click_to_get_7_day_trial"),
|
||||
title: t("certd.vip.click_to_get_7_day_trial"),
|
||||
click: () => {
|
||||
props.openStarModal("comm");
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup>
|
||||
import { BasicLayout, LockScreen, UserDropdown } from "/@/vben/layouts";
|
||||
|
||||
import { computed, onErrorCaptured, onMounted, provide, ref } from "vue";
|
||||
@@ -23,14 +23,14 @@ const menus = computed(() => [
|
||||
router.push("/cert/mine/user-profile");
|
||||
},
|
||||
icon: "fa-solid:book",
|
||||
text: t("certd.accountInfo"),
|
||||
text: t("certd.mine.accountInfo"),
|
||||
},
|
||||
{
|
||||
handler: () => {
|
||||
router.push("/cert/mine/security");
|
||||
},
|
||||
icon: "fluent:shield-keyhole-16-regular",
|
||||
text: t("certd.securitySettings"),
|
||||
text: t("certd.mine.securitySettings"),
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -109,7 +109,7 @@ const projectStore = useProjectStore();
|
||||
<vip-button class="flex-center header-btn" mode="nav" />
|
||||
</div>
|
||||
<div v-if="!settingStore.isComm" class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full hidden md:block">
|
||||
<fs-button shape="circle" type="text" icon="clarity:host-solid-badged" :text="null" :tooltip="{ title: t('certd.client') }" @click="goCertdClient" />
|
||||
<fs-button shape="circle" type="text" icon="clarity:host-solid-badged" :text="null" :tooltip="{ title: t('certd.navigation.client') }" @click="goCertdClient" />
|
||||
</div>
|
||||
<div v-if="!settingStore.isComm" class="hover:bg-accent ml-1 mr-2 cursor-pointer rounded-full hidden md:block">
|
||||
<fs-button shape="circle" type="text" icon="ion:logo-github" :text="null" @click="goGithub" />
|
||||
|
||||
@@ -13,34 +13,54 @@ import notification from "./certd/notification";
|
||||
import addon from "./certd/addon";
|
||||
import suite from "./certd/suite";
|
||||
import project from "./certd/project";
|
||||
import syssettings from "./certd/sys-settings";
|
||||
import sysplugin from "./certd/sys-plugin";
|
||||
import sysauthority from "./certd/sys-authority";
|
||||
import syscname from "./certd/sys-cname";
|
||||
import settings from "./certd/sys-settings";
|
||||
import plugin from "./certd/sys-plugin";
|
||||
import authority from "./certd/sys-authority";
|
||||
import cnameSettings from "./certd/sys-cname";
|
||||
import tutorial from "./certd/tutorial";
|
||||
import cron from "./certd/cron";
|
||||
import client from "./certd/client";
|
||||
import wallet from "./certd/wallet";
|
||||
import nettest from "./certd/nettest";
|
||||
import audit from "./certd/audit";
|
||||
import applyTemplate from "./certd/apply-template";
|
||||
import dnsPersist from "./certd/dns-persist";
|
||||
import auth from "./certd/auth";
|
||||
import guide from "./certd/guide";
|
||||
import vip from "./certd/vip";
|
||||
|
||||
// Note: @ is reserved in locale messages; use {'@'} when needed.
|
||||
export default {
|
||||
...common,
|
||||
...navigation,
|
||||
...dashboard,
|
||||
...pipeline,
|
||||
...history,
|
||||
...monitor,
|
||||
...certdomain,
|
||||
...cname,
|
||||
...access,
|
||||
...open,
|
||||
...mine,
|
||||
...notification,
|
||||
...addon,
|
||||
...suite,
|
||||
...project,
|
||||
...syssettings,
|
||||
...sysplugin,
|
||||
...sysauthority,
|
||||
...syscname,
|
||||
...tutorial,
|
||||
...cron,
|
||||
common,
|
||||
navigation,
|
||||
dashboard,
|
||||
pipeline,
|
||||
history,
|
||||
monitor,
|
||||
certdomain,
|
||||
cname,
|
||||
access,
|
||||
open,
|
||||
mine,
|
||||
notification,
|
||||
addon,
|
||||
suite,
|
||||
project,
|
||||
sys: {
|
||||
settings,
|
||||
plugin,
|
||||
authority,
|
||||
cname: cnameSettings,
|
||||
},
|
||||
tutorial,
|
||||
cron,
|
||||
client,
|
||||
wallet,
|
||||
nettest,
|
||||
audit,
|
||||
applyTemplate,
|
||||
dnsPersist,
|
||||
auth,
|
||||
guide,
|
||||
vip,
|
||||
};
|
||||
|
||||
@@ -4,4 +4,11 @@ export default {
|
||||
nameHelper: "Fill in as you like, useful to distinguish when multiple authorizations of the same type exist",
|
||||
level: "Level",
|
||||
system: "System",
|
||||
select: "Select",
|
||||
selectProvider: "Select Authorization Provider",
|
||||
deleteConfirm: "If this authorization is already in use, pipelines may fail. Proceed with caution.",
|
||||
name: "Name",
|
||||
user: "User",
|
||||
type: "Type",
|
||||
selectType: "Please select a type",
|
||||
};
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
export default {
|
||||
setSuccess: "Settings saved",
|
||||
editTitle: "Edit Certificate Application Template",
|
||||
addTitle: "Add Certificate Application Template",
|
||||
name: "Template Name",
|
||||
default: "Default",
|
||||
setDefault: "Set as Default",
|
||||
disabled: "Disabled",
|
||||
createTime: "Created At",
|
||||
config: "Configuration",
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
export default {
|
||||
createTime: "Operation Time",
|
||||
type: "Operation Type",
|
||||
action: "Action",
|
||||
result: "Result",
|
||||
success: "Success",
|
||||
failed: "Failed",
|
||||
remark: "Remark",
|
||||
ipAddress: "IP Address",
|
||||
};
|
||||
+26
-54
@@ -1,58 +1,4 @@
|
||||
export default {
|
||||
welcomeBack: "Welcome Back",
|
||||
pageTitle: "Plug-and-play Admin system",
|
||||
pageDesc: "Efficient, versatile frontend template",
|
||||
loginSuccess: "Login Successful",
|
||||
loginSuccessDesc: "Welcome Back",
|
||||
loginSubtitle: "Enter your account details to manage your projects",
|
||||
selectAccount: "Quick Select Account",
|
||||
username: "Username",
|
||||
password: "Password",
|
||||
usernameTip: "Please enter username",
|
||||
passwordErrorTip: "Password is incorrect",
|
||||
passwordTip: "Please enter password",
|
||||
verifyRequiredTip: "Please complete the verification first",
|
||||
rememberMe: "Remember Me",
|
||||
createAnAccount: "Create an Account",
|
||||
createAccount: "Create Account",
|
||||
alreadyHaveAccount: "Already have an account?",
|
||||
accountTip: "Don't have an account?",
|
||||
signUp: "Sign Up",
|
||||
signUpSubtitle: "Make managing your applications simple and fun",
|
||||
confirmPassword: "Confirm Password",
|
||||
confirmPasswordTip: "The passwords do not match",
|
||||
agree: "I agree to",
|
||||
privacyPolicy: "Privacy-policy",
|
||||
terms: "Terms",
|
||||
agreeTip: "Please agree to the Privacy Policy and Terms",
|
||||
goToLogin: "Login instead",
|
||||
passwordStrength: "Use 8 or more characters with a mix of letters, numbers & symbols",
|
||||
forgetPassword: "Forget Password?",
|
||||
forgetPasswordSubtitle: "Enter your email and we'll send you instructions to reset your password",
|
||||
emailTip: "Please enter email",
|
||||
emailValidErrorTip: "The email format you entered is incorrect",
|
||||
sendResetLink: "Send Reset Link",
|
||||
email: "Email",
|
||||
qrcodeSubtitle: "Scan the QR code with your phone to login",
|
||||
qrcodePrompt: "Click 'Confirm' after scanning to complete login",
|
||||
qrcodeLogin: "QR Code Login",
|
||||
codeSubtitle: "Enter your phone number to start managing your project",
|
||||
code: "Security code",
|
||||
codeTip: "Security code required {0} characters",
|
||||
mobile: "Mobile",
|
||||
mobileLogin: "Mobile Login",
|
||||
mobileTip: "Please enter mobile number",
|
||||
mobileErrortip: "The phone number format is incorrect",
|
||||
sendCode: "Get Security code",
|
||||
sendText: "Resend in {0}s",
|
||||
thirdPartyLogin: "Or continue with",
|
||||
loginAgainTitle: "Please Log In Again",
|
||||
loginAgainSubTitle: "Your login session has expired. Please log in again to continue.",
|
||||
layout: {
|
||||
center: "Align Center",
|
||||
alignLeft: "Align Left",
|
||||
alignRight: "Align Right",
|
||||
},
|
||||
loginType: {
|
||||
password: "Password Login",
|
||||
sms: "Mobile Login",
|
||||
@@ -110,4 +56,30 @@ export default {
|
||||
userInfo: "User Info",
|
||||
securitySettingTip: "2FA Setting",
|
||||
securitySetting: "2FA Setting",
|
||||
register: {
|
||||
usernameTab: "Register with username",
|
||||
emailTab: "Register with email",
|
||||
mobileTab: "Register with mobile",
|
||||
username: "Username",
|
||||
email: "Email",
|
||||
password: "Password",
|
||||
confirmPassword: "Confirm Password",
|
||||
captcha: "Captcha",
|
||||
emailCode: "Email verification code",
|
||||
mobileLogin: "Go to mobile login (login to register)",
|
||||
inviteCode: "Invitation code",
|
||||
inviteCodeOptional: "Invitation code (optional)",
|
||||
submit: "Register",
|
||||
login: "Log In",
|
||||
noMethodEnabled: "No registration method is enabled",
|
||||
usernameRequired: "Please enter your username",
|
||||
emailRequired: "Please enter your email",
|
||||
emailInvalid: "Please enter a valid email address",
|
||||
passwordRequired: "Please enter your password",
|
||||
confirmPasswordRequired: "Please confirm your password",
|
||||
passwordMismatch: "The two passwords do not match",
|
||||
smsCodeRequired: "Please enter the SMS verification code",
|
||||
emailCodeRequired: "Please enter the email verification code",
|
||||
captchaRequired: "Please complete the captcha",
|
||||
},
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
export default {
|
||||
domain: {
|
||||
dnsPersistDescription: "Currently, only Google certificates support DNS persistent validation.",
|
||||
domainManager: "Domain Manager",
|
||||
domainDescription: "used to auto apply for certificate", //管理域名的校验方式,用于申请证书时自动选择验证方式
|
||||
domain: "Domain",
|
||||
@@ -19,6 +20,7 @@ export default {
|
||||
subdomainConfirmContent: "{domain} appears to be a subdomain. Only delegated subdomains and free second-level subdomains need to be maintained here. Otherwise certificate application may fail. Continue?",
|
||||
importFromProvider: "Import from Domain Provider",
|
||||
importFromResolveRecords: "Import from DNS Records",
|
||||
importFromResolveRecordsTooltip: "Import DNS records as monitoring sites",
|
||||
syncExpirationDate: "Sync Domain Expiration Time",
|
||||
syncTaskSubmitted: "Sync task submitted",
|
||||
syncExpirationProgress: "Sync Domain Expiration Progress",
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
export default {
|
||||
clientManager: "Client Manager",
|
||||
title: "Client Manager",
|
||||
description: "View online status and managed site count of connected Certd clients. Clients report a heartbeat every 10 minutes and are marked offline if no heartbeat arrives for 30 minutes.",
|
||||
plusRequired: "This feature requires the Pro edition",
|
||||
machineName: "Machine",
|
||||
clientId: "Client ID",
|
||||
version: "Version",
|
||||
os: "OS",
|
||||
status: "Status",
|
||||
online: "Online",
|
||||
offline: "Offline",
|
||||
siteCount: "Sites",
|
||||
httpsSiteCount: "HTTPS Sites",
|
||||
syncedSiteCount: "Synced",
|
||||
failedSiteCount: "Failed",
|
||||
lastHeartbeatAt: "Last Heartbeat",
|
||||
};
|
||||
@@ -1,4 +1,6 @@
|
||||
export default {
|
||||
required: "Required",
|
||||
no: "No",
|
||||
usera: "User",
|
||||
disabledSuccess: "Disabled successfully",
|
||||
app: {
|
||||
@@ -21,12 +23,18 @@ export default {
|
||||
add: "Generate New Key",
|
||||
edit: "Edit",
|
||||
deleteSuccess: "Delete successful",
|
||||
fastCrud: {
|
||||
view: "View",
|
||||
copy: "Copy",
|
||||
edit: "Edit",
|
||||
remove: "Delete",
|
||||
addSuccess: "Added successfully",
|
||||
saveSuccess: "Saved successfully",
|
||||
},
|
||||
saveSuccess: "Saved successfully",
|
||||
cancel: "Cancel",
|
||||
yes: "Yes",
|
||||
no: "No",
|
||||
all: "All",
|
||||
required: "This field is required",
|
||||
requiredField: "This field is required",
|
||||
fieldRequired: "This field is required",
|
||||
field_required: "This field is required",
|
||||
|
||||
@@ -1,50 +1,59 @@
|
||||
export default {
|
||||
dashboard: {
|
||||
greeting: "Hello, {name}, welcome to 【{site}】",
|
||||
latestVersion: "Latest version: {version}",
|
||||
validUntil: "Valid until:",
|
||||
tutorialTooltip: "Click to view detailed tutorial",
|
||||
tutorialText: "Only 3 steps to automatically apply and deploy certificates",
|
||||
alertMessage: "Certificates and credentials are sensitive. Do not use untrusted online Certd services or images. Always self-host and use official release channels:",
|
||||
helpDoc: "Help Docs",
|
||||
pipelineCount: "Number of Certificate Pipelines",
|
||||
noPipeline: "You have no certificate pipelines yet",
|
||||
enabledCount: "Enabled",
|
||||
disabledCount: "Disabled",
|
||||
certCount: "Number of Certificates",
|
||||
noCert: "You have no certificates yet",
|
||||
manageCert: "View Certificates",
|
||||
siteMonitorCount: "Number of Monitored Sites",
|
||||
siteAbnormalCount: "Abnormal",
|
||||
siteNormalCount: "Normal",
|
||||
manageSiteMonitor: "Manage Monitored Sites",
|
||||
domainCount: "Number of Domains",
|
||||
domainExpiringCount: "Expiring",
|
||||
domainExpiredCount: "Expired",
|
||||
domainNotExpiredCount: "Not Expired",
|
||||
manageDomain: "Manage Domains",
|
||||
certExpiringCount: "Soon-to-Expire",
|
||||
certExpiredCount: "Expired",
|
||||
certNoExpireCount: "Not Expired",
|
||||
createNow: "Create Now",
|
||||
managePipeline: "Manage Pipelines",
|
||||
pipelineStatus: "Pipeline Status",
|
||||
recentRun: "Recent Run Statistics",
|
||||
runCount: "Run Count",
|
||||
expiringCerts: "Soon-to-Expire Certificates",
|
||||
totalGeneratedCertCount: "Total Certificates Generated",
|
||||
singleDomainCertShortCount: "Single-domain",
|
||||
multiDomainCertShortCount: "Multi-domain",
|
||||
wildcardCertShortCount: "Wildcard",
|
||||
singleDomainCertCount: "Single-domain Certificates Generated",
|
||||
multiDomainCertCount: "Multi-domain Certificates Generated",
|
||||
wildcardCertCount: "Wildcard Certificates Generated",
|
||||
savedAmount: "Estimated savings",
|
||||
savedAmountRule: "Estimated at one quarter of Tencent Cloud's annual certificate prices: single-domain ¥532, multi-domain ¥912, and wildcard ¥2147. Actual savings may vary.",
|
||||
totalPipelineRuns: "Total Pipeline Runs",
|
||||
supportedTasks: "Overview of Supported Deployment Tasks",
|
||||
changeLog: "Change Log",
|
||||
stableRelease: "Stable",
|
||||
latestRelease: "Preview",
|
||||
},
|
||||
greeting: "Hello, {name}, welcome to 【{site}】",
|
||||
latestVersion: "Latest version: {version}",
|
||||
validUntil: "Valid until:",
|
||||
tutorialTooltip: "Click to view detailed tutorial",
|
||||
tutorialText: "Only 3 steps to automatically apply and deploy certificates",
|
||||
alertMessage: "Certificates and credentials are sensitive. Do not use untrusted online Certd services or images. Always self-host and use official release channels:",
|
||||
helpDoc: "Help Docs",
|
||||
pipelineCount: "Number of Certificate Pipelines",
|
||||
noPipeline: "You have no certificate pipelines yet",
|
||||
enabledCount: "Enabled",
|
||||
disabledCount: "Disabled",
|
||||
certCount: "Number of Certificates",
|
||||
noCert: "You have no certificates yet",
|
||||
manageCert: "View Certificates",
|
||||
siteMonitorCount: "Number of Monitored Sites",
|
||||
siteAbnormalCount: "Abnormal",
|
||||
siteNormalCount: "Normal",
|
||||
manageSiteMonitor: "Manage Monitored Sites",
|
||||
domainCount: "Number of Domains",
|
||||
domainExpiringCount: "Expiring",
|
||||
domainExpiredCount: "Expired",
|
||||
domainNotExpiredCount: "Not Expired",
|
||||
manageDomain: "Manage Domains",
|
||||
certExpiringCount: "Soon-to-Expire",
|
||||
certExpiredCount: "Expired",
|
||||
certNoExpireCount: "Not Expired",
|
||||
createNow: "Create Now",
|
||||
managePipeline: "Manage Pipelines",
|
||||
pipelineStatus: "Pipeline Status",
|
||||
recentRun: "Recent Run Statistics",
|
||||
runCount: "Run Count",
|
||||
expiringCerts: "Soon-to-Expire Certificates",
|
||||
totalGeneratedCertCount: "Total Certificates Generated",
|
||||
singleDomainCertShortCount: "Single-domain",
|
||||
multiDomainCertShortCount: "Multi-domain",
|
||||
wildcardCertShortCount: "Wildcard",
|
||||
singleDomainCertCount: "Single-domain Certificates Generated",
|
||||
multiDomainCertCount: "Multi-domain Certificates Generated",
|
||||
wildcardCertCount: "Wildcard Certificates Generated",
|
||||
savedAmount: "Estimated savings",
|
||||
savedAmountRule: "Estimated at one quarter of Tencent Cloud's annual certificate prices: single-domain ¥532, multi-domain ¥912, and wildcard ¥2147. Actual savings may vary.",
|
||||
totalPipelineRuns: "Total Pipeline Runs",
|
||||
supportedTasks: "Overview of Supported Deployment Tasks",
|
||||
supportedTasksHelper: "This list is for display only. Create a pipeline to use these tasks.",
|
||||
changeLog: "Change Log",
|
||||
stableRelease: "Stable",
|
||||
latestRelease: "Preview",
|
||||
consoleTitle: "Console",
|
||||
userTotal: "Total Users",
|
||||
manageUsers: "Manage Users",
|
||||
userGrowth: "User Growth",
|
||||
newUsers: "New Users",
|
||||
allPipelineTotal: "Total Pipelines",
|
||||
managePipelines: "Manage Pipelines",
|
||||
pipelineGrowth: "Pipeline Growth",
|
||||
newPipelines: "New Pipelines",
|
||||
recentRunTitle: "Recent Run Statistics",
|
||||
};
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
export default {
|
||||
pending: "Pending Setup",
|
||||
created: "Created",
|
||||
validating: "Validating",
|
||||
valid: "Valid",
|
||||
retry: "Retry",
|
||||
deleteTxtTip: "Delete the TXT record at the provider",
|
||||
accountUriMissing: "The ACME account authorization is missing accountUri. Please regenerate the account.",
|
||||
verifySuccess: "Validation succeeded",
|
||||
verifyFailed: "No matching TXT record found. Please try again later.",
|
||||
submitted: "Validation submitted",
|
||||
selectProviderAndAccess: "Select a DNS provider and authorization",
|
||||
txtCreated: "TXT record created",
|
||||
settingTitle: "Set DNS TXT Record",
|
||||
manualAdd: "Add Manually",
|
||||
autoAdd: "Add with Authorization",
|
||||
manualTip: "Add the following TXT record in your DNS console, then click OK to validate immediately.",
|
||||
autoTip: "Select a DNS provider and authorization. The system will create the TXT record and validate it in the background.",
|
||||
mainDomain: "Main Domain",
|
||||
txtHost: "TXT Host",
|
||||
txtValue: "TXT Value",
|
||||
provider: "DNS Provider",
|
||||
access: "DNS Authorization",
|
||||
};
|
||||
+2
@@ -7,6 +7,8 @@ export default {
|
||||
settingLink: "Site Monitoring Settings",
|
||||
limitInfo: "Basic edition limited to 1, professional and above unlimited, current",
|
||||
checkAll: "Check All",
|
||||
checkBatch: "Check Selected",
|
||||
batchCheckConfirm: "Check the {count} selected sites now?",
|
||||
checkNow: "Check Now",
|
||||
batchDelete: "Batch Delete",
|
||||
confirmTitle: "Confirm",
|
||||
@@ -1,4 +1,7 @@
|
||||
import monitorSite from "./monitor-site";
|
||||
|
||||
export default {
|
||||
...monitorSite,
|
||||
certificateRepo: {
|
||||
title: "Certificate Repository",
|
||||
sub: "Certificates generated from pipeline",
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
export default {
|
||||
home: "Home",
|
||||
login: "Login",
|
||||
register: "Register",
|
||||
forgotPassword: "Forgot Password",
|
||||
oauthCallback: "OAuth Callback",
|
||||
framework: {
|
||||
title: "Framework",
|
||||
home: "Home",
|
||||
@@ -13,10 +18,13 @@ export default {
|
||||
accessManager: "Access Management",
|
||||
dnsPersistRecord: "DNS Persist Records",
|
||||
certApplyTemplate: "Certificate Apply Templates",
|
||||
certApplyTemplateHelper: "Preset certificate application parameters. They are filled automatically when creating a pipeline (excluding domains and validation methods).",
|
||||
subDomain: "Subdomain Delegation Settings",
|
||||
pipelineGroup: "Pipeline Group Management",
|
||||
pipelineGroupHelper: "Manage pipeline groups",
|
||||
openKey: "Open API Key",
|
||||
notification: "Notification Settings",
|
||||
notificationHelper: "Manage notification configurations",
|
||||
siteMonitorSetting: "Site Monitor Settings",
|
||||
auditLog: "Audit Log",
|
||||
userSecurity: "Security Settings",
|
||||
@@ -25,6 +33,7 @@ export default {
|
||||
mySuite: "My Suite",
|
||||
suiteBuy: "Suite Purchase",
|
||||
myTrade: "My Orders",
|
||||
myWallet: "My Wallet",
|
||||
inviteCommission: "Incentive Plan",
|
||||
paymentReturn: "Payment Return",
|
||||
client: "Certd Client",
|
||||
@@ -48,11 +57,15 @@ export default {
|
||||
userManager: "User Management",
|
||||
userDataManager: "User Data Management",
|
||||
pipelineManager: "User Pipeline Management",
|
||||
pipelineManagerHelper: "Manage all users' pipelines",
|
||||
siteMonitorManager: "User Certificate Monitor",
|
||||
siteMonitorManagerHelper: "Manage all users' certificate monitors",
|
||||
suiteManager: "Suite Management",
|
||||
suiteSetting: "Suite Settings",
|
||||
orderManager: "Order Management",
|
||||
userSuites: "User Suites",
|
||||
balanceManager: "Balance Management",
|
||||
balanceLog: "Balance Change Records",
|
||||
inviteCommissionSetting: "Incentive Plan Settings",
|
||||
inviteLevel: "Promotion Levels",
|
||||
inviteUserLevel: "User Promotion Levels",
|
||||
@@ -70,6 +83,8 @@ export default {
|
||||
currentProject: "Current Project",
|
||||
projectMemberManager: "Project Member",
|
||||
auditLog: "Audit Log",
|
||||
auditLogHelper: "View all users' operation records",
|
||||
jobHistory: "Monitoring Execution History",
|
||||
domainMonitorSetting: "Domain Monitor Settings",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
export default {
|
||||
title: "Network Test",
|
||||
helper: "Test whether your server container network is working",
|
||||
customDomain: "Custom Domain Test",
|
||||
serverInfo: "Server Information",
|
||||
refresh: "Refresh",
|
||||
loading: "Loading...",
|
||||
fetchFailed: "Failed to fetch server information",
|
||||
noInfo: "No information",
|
||||
localIp: "Local IP",
|
||||
publicIp: "Public IP",
|
||||
dnsServer: "DNS Server",
|
||||
};
|
||||
@@ -3,6 +3,13 @@ export default {
|
||||
scopeOpenApiOnly: "Open API Only",
|
||||
scopeFullAccount: "Full Account Permissions",
|
||||
scopeHelper: "Open API only allows access to open APIs; full account permissions allow access to all APIs",
|
||||
keyRemark: "Key Purpose",
|
||||
keyRemarkHelper: "Describe the purpose of this key for easier identification",
|
||||
keyRemarkMaxChars: "Maximum 512 characters",
|
||||
returnCertPassword: "Return certificate password",
|
||||
returnCertPasswordHelper: "When enabled, the certificate password is included in Open API certificate responses. Keep this key secure.",
|
||||
yes: "Yes",
|
||||
no: "No",
|
||||
gen: {
|
||||
text: "API Test",
|
||||
title: "x-certd-token",
|
||||
|
||||
@@ -33,6 +33,10 @@ export default {
|
||||
pipelineStarted: "Pipeline has started running",
|
||||
},
|
||||
actions: {
|
||||
edit: "Edit",
|
||||
delete: "Delete",
|
||||
enable: "Enable",
|
||||
disable: "Disable",
|
||||
editPipeline: "Edit Pipeline",
|
||||
editConfigGroup: "Modify Configuration/Group",
|
||||
viewCertificate: "View Certificate",
|
||||
@@ -65,6 +69,145 @@ export default {
|
||||
legoAcme: "Lego-ACME: Based on Lego, supports a wide range of DNS providers, suitable for users familiar with Lego",
|
||||
aliyunOrder: "Aliyun-Order: Get certificate from Aliyun certificate order",
|
||||
},
|
||||
editor: {
|
||||
editTask: "Edit Task",
|
||||
editStep: "Edit Step",
|
||||
installedPlugins: "Installed Plugins",
|
||||
pluginMarket: "Plugin Market",
|
||||
searchPluginMarket: "Search plugin market",
|
||||
searchLocalPlugins: "Search local plugins",
|
||||
loadingPluginMarket: "Loading plugin market...",
|
||||
noPluginFound: "No plugins found",
|
||||
triggerManually: "Trigger Manually",
|
||||
triggerSource: "Trigger Source",
|
||||
scheduledTrigger: "Trigger Source (Scheduled)",
|
||||
webhookTrigger: "Trigger Source (Webhook)",
|
||||
certExpireTime: "Certificate expiration time: ",
|
||||
certExpired: "Certificate expired ",
|
||||
viewCertificate: "View Certificate",
|
||||
downloadCertificate: "Download Certificate",
|
||||
nextExecutionTime: "Next execution time: ",
|
||||
noTriggerSource: "No trigger source configured; it will not run automatically",
|
||||
validityPeriod: "Validity period: ",
|
||||
save: "Save",
|
||||
cancel: "Cancel",
|
||||
addStage: "New Stage",
|
||||
addTask: "Add Task",
|
||||
addAfterTask: "Add After-Task",
|
||||
addNotification: "Add Notification",
|
||||
notificationNotSet: "Notification not set",
|
||||
history: "Execution History",
|
||||
historyHint: "Click a task to view logs",
|
||||
taskName: "Task Name",
|
||||
taskSteps: "Task Steps",
|
||||
addStep: "Add Step",
|
||||
copy: "Copy",
|
||||
paste: "Paste",
|
||||
confirm: "Confirm",
|
||||
required: "This field is required",
|
||||
taskNeedsStep: "At least one step is required, or delete this task using the button beside the title",
|
||||
step: "Step",
|
||||
endStage: "End",
|
||||
confirmTitle: "Confirm",
|
||||
confirmManualRun: "Are you sure you want to trigger the run manually?",
|
||||
taskLog: "Task Log",
|
||||
noLogs: "No logs (this node was not triggered or has no log records for this run)",
|
||||
aiAnalyze: "AI Analysis",
|
||||
rerun: "Rerun",
|
||||
downloadLogs: "Download Logs",
|
||||
close: "Close",
|
||||
batchEditSteps: "Batch Edit Steps",
|
||||
selectAllSteps: "Select All Steps",
|
||||
batchEnableSteps: "Batch Enable Steps",
|
||||
batchDisableSteps: "Batch Disable Steps",
|
||||
batchDeleteSteps: "Batch Delete Steps",
|
||||
exitBatchEdit: "Exit Batch Edit",
|
||||
stepsSerialHelper: "Steps run sequentially. If an earlier step fails, later steps will not run.",
|
||||
current: "Current",
|
||||
view: "View",
|
||||
confirmCancel: "Confirm Cancellation",
|
||||
confirmCancelTask: "Cancel this task?",
|
||||
taskCanceled: "Task canceled successfully",
|
||||
selectAllTasks: "Select all tasks",
|
||||
batchEnableTasks: "Enable tasks in batch",
|
||||
batchDisableTasks: "Disable tasks in batch",
|
||||
batchDeleteTasks: "Delete tasks in batch",
|
||||
exitBatchEditTasks: "Exit batch edit",
|
||||
editStageTitle: "Edit stage title",
|
||||
batchEditTasks: "Edit tasks in batch",
|
||||
dragSort: "Drag to reorder",
|
||||
forceRerun: "Force rerun this step",
|
||||
resizeStage: "Drag to resize stage",
|
||||
afterLabel: "After-task",
|
||||
notificationLabel: "Notification",
|
||||
unsavedLeave: "This pipeline is not saved. Leave anyway?",
|
||||
newPipeline: "New Pipeline",
|
||||
newTask: "New Task",
|
||||
newStage: "New Stage",
|
||||
stageSuffix: " Stage",
|
||||
saveBeforeRunTitle: "Save before running the pipeline",
|
||||
saveBeforeRunContent: "Save it first?",
|
||||
runUnsupported: "Running is not supported yet",
|
||||
addStageAndTask: "Please add a stage and task first",
|
||||
prerequisiteMissing: "The prerequisite output step {param} for {step} does not exist or is disabled",
|
||||
selectPlugin: "Select plugin",
|
||||
searchPlugin: "Search plugins",
|
||||
searchResults: "Search results",
|
||||
plusPluginRequired: "This plugin requires Certd Professional",
|
||||
immediateRun: "Run immediately",
|
||||
immediateRunHelper: "Run the pipeline immediately after saving",
|
||||
operationSuccess: "Operation successful",
|
||||
regenerate: "Regenerate",
|
||||
webhookHelper: "Supports POST and GET requests (each pipeline has a unique Webhook URL)",
|
||||
regenerateWebhookTitle: "Regenerate the Webhook URL?",
|
||||
regenerateWebhookContent: "The old Webhook URL will become invalid",
|
||||
confirmDeleteTask: "Delete this task?",
|
||||
confirmDeleteStep: "Delete this step?",
|
||||
confirmDeleteSelectedTasks: "Delete the selected {count} tasks?",
|
||||
confirmDeleteSelectedSteps: "Delete the selected {count} steps?",
|
||||
stepCopied: "Step configuration copied. You can paste it in another task editor",
|
||||
allStepsCopied: "All steps copied. You can paste them in another task editor",
|
||||
copyFirst: "Please copy first",
|
||||
pasted: "Pasted successfully",
|
||||
enterName: "Please enter a name",
|
||||
pluginTypeFirst: "Please select a type first",
|
||||
runStrategy: "Run strategy",
|
||||
runStrategyNormal: "Run normally (required for certificate tasks unless you want this task to run every time)",
|
||||
runStrategySkip: "Skip after success (choose this for other tasks)",
|
||||
runStrategyDefault: "Usually keep the default",
|
||||
runStrategyNormalHelp: "Run normally: runs every time; certificate tasks need this",
|
||||
runStrategySkipHelp: "Skip after success: skip after one successful run and run again when the certificate changes",
|
||||
triggerWebhook: "Webhook Trigger",
|
||||
triggerSchedule: "Scheduled Trigger",
|
||||
choose: "Select",
|
||||
noLogsShort: "No logs",
|
||||
statusSuccess: "success",
|
||||
statusError: "error",
|
||||
statusSkip: "skip",
|
||||
statusStart: "running",
|
||||
statusCanceled: "canceled",
|
||||
statusNone: "not run",
|
||||
statusDisabled: "disabled",
|
||||
statusNoDeployCount: "insufficient runs",
|
||||
pluginGroups: {
|
||||
all: "All",
|
||||
cert: "Certificate",
|
||||
host: "Host",
|
||||
cdn: "CDN",
|
||||
panel: "Panel",
|
||||
aliyun: "Alibaba Cloud",
|
||||
huawei: "Huawei Cloud",
|
||||
tencent: "Tencent Cloud",
|
||||
volcengine: "Volcengine",
|
||||
jdcloud: "JD Cloud",
|
||||
ucloud: "UCloud",
|
||||
baidu: "Baidu Cloud",
|
||||
qiniu: "Qiniu Cloud",
|
||||
aws: "Amazon Web Services",
|
||||
other: "Other",
|
||||
admin: "Administration",
|
||||
},
|
||||
},
|
||||
pipelineForm: {
|
||||
createTitle: "Create Certificate Pipeline",
|
||||
moreParams: "More Parameters",
|
||||
|
||||
@@ -1,4 +1,50 @@
|
||||
export default {
|
||||
title: "Suite",
|
||||
mySuite: "My Suite",
|
||||
suiteBuy: "Suite Purchase",
|
||||
myTrade: "My Orders",
|
||||
inviteCommission: "Incentive Plan",
|
||||
inviteSubtitle: "Invite friends and earn generous commissions",
|
||||
promotionAgreement: "Promotion Agreement",
|
||||
withdraw: "Withdraw",
|
||||
withdrawAvailable: "Available to withdraw {amount}",
|
||||
inviteCode: "Invitation Code",
|
||||
orderTime: "Time",
|
||||
inviteTime: "Invitation Time",
|
||||
inviteeUsername: "Invited Username",
|
||||
inviteLink: "Invitation Link",
|
||||
myLevel: "My Level",
|
||||
unset: "Not set",
|
||||
commissionRate: "Commission Rate",
|
||||
commissionAfterPayment: "Commission is calculated at this rate after a friend pays",
|
||||
proportion: "Rate",
|
||||
inviteSuccess: "Successful Invites",
|
||||
incomeRecords: "Income Records",
|
||||
enableFirst: "Please enable the incentive plan first",
|
||||
enable: "Enable Incentive Plan",
|
||||
disabled: "Incentive plan is not enabled",
|
||||
totalIncome: "Total Income",
|
||||
monthIncome: "This Month's Income",
|
||||
promotionAmount: "Total Promotion Amount",
|
||||
inviteeCount: "People Invited",
|
||||
people: " people",
|
||||
agreePromotion: "I have read and agree to the promotion agreement",
|
||||
close: "Close",
|
||||
postpone: "Later",
|
||||
agreeAndEnable: "Agree and Enable",
|
||||
agreeRequired: "Please check the agreement first",
|
||||
enabledSuccess: "Incentive plan enabled",
|
||||
purchaseSuccess: "Suite purchased successfully",
|
||||
agreementPlaceholder: "Enter the promotion agreement users must accept before enabling the incentive plan",
|
||||
activationExchange: "Redeem Activation Code",
|
||||
activationCode: "Activation Code",
|
||||
enterActivationCode: "Please enter the activation code",
|
||||
enterCdkCode: "Please enter the CDK activation code",
|
||||
activateSuccess: "Activated successfully",
|
||||
exchangeFailed: "Redemption failed",
|
||||
noSuite: "No suites available for purchase",
|
||||
suiteHelperStack: "Note: Multiple suites and addons can be purchased, and their quantities are accumulated",
|
||||
suiteHelperLatest: "Note: 1) Only the latest suite is active at a time; 2) Multiple addons can be purchased and take effect immediately; 3) Suite and addon quantities are accumulated",
|
||||
order: {
|
||||
confirmTitle: "Order Confirmation",
|
||||
package: "Package",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user