mirror of
https://github.com/certd/certd.git
synced 2026-05-05 05:17:24 +08:00
refactor: organize certd client i18n translations
This commit is contained in:
@@ -1,17 +1,18 @@
|
||||
<template>
|
||||
<div class="flex">
|
||||
<a-input :value="valueRef" placeholder="请输入图片验证码" autocomplete="off" @update:value="onChange">
|
||||
<a-input :value="valueRef" :placeholder="t('certd.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="点击刷新">
|
||||
<div class="input-right pointer" :title="t('certd.captcha.refresh')">
|
||||
<img class="image-code" :src="imageCodeSrc" @click="resetImageCode" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: any;
|
||||
@@ -20,6 +21,7 @@ const props = defineProps<{
|
||||
defineOptions({
|
||||
name: "ImageCaptcha",
|
||||
});
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits(["update:modelValue", "change"]);
|
||||
|
||||
const valueRef = ref("");
|
||||
|
||||
@@ -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">点击进行验证</span>
|
||||
<span v-else class="status-text">验证成功</span>
|
||||
<span v-if="modelValue == null" class="status-text">{{ t("certd.captcha.clickToVerify") }}</span>
|
||||
<span v-else class="status-text">{{ t("certd.captcha.verifySuccess") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -13,8 +13,10 @@
|
||||
<script setup lang="ts">
|
||||
import { notification } from "ant-design-vue";
|
||||
import { ref, Ref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
import { loadScript } from "vue-plugin-load-script";
|
||||
const { t } = useI18n();
|
||||
const loaded = ref(false);
|
||||
async function loadCaptchaScript() {
|
||||
// 加载验证码js
|
||||
@@ -56,7 +58,7 @@ function callback(res: { ret: number; ticket: string; randstr: string; errorCode
|
||||
|
||||
if (res.errorCode && res.errorCode > 0) {
|
||||
notification.error({
|
||||
message: `验证码验证失败:${res.errorMessage || res.errorCode}`,
|
||||
message: t("certd.captcha.verifyFailed", { message: res.errorMessage || res.errorCode }),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -83,13 +85,13 @@ function loadErrorCallback(error: any) {
|
||||
// errorMessage: "jsload_error",
|
||||
// });
|
||||
notification.error({
|
||||
message: `验证码加载失败:${error?.message || error}`,
|
||||
message: t("certd.captcha.loadFailed", { message: error?.message || error }),
|
||||
});
|
||||
}
|
||||
async function triggerCaptcha() {
|
||||
if (!loaded.value) {
|
||||
notification.error({
|
||||
message: "验证码还未加载完成,请稍后再试",
|
||||
message: t("certd.captcha.notLoaded"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
+13
-11
@@ -4,7 +4,7 @@
|
||||
<!-- <td class="domain">-->
|
||||
<!-- {{ props.domain }}-->
|
||||
<!-- </td>-->
|
||||
<td class="host-record" :title="'域名:' + props.domain">
|
||||
<td class="host-record" :title="t('certd.verifyPlan.domainTitle', { domain: props.domain })">
|
||||
<fs-copyable v-model="cnameRecord.hostRecord"></fs-copyable>
|
||||
</td>
|
||||
<td style="text-align: center">CNAME</td>
|
||||
@@ -16,17 +16,17 @@
|
||||
<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="重置校验状态,重新校验">
|
||||
<a-tooltip v-if="cnameRecord.status === 'valid'" :title="t('certd.verifyPlan.resetStatusTooltip')">
|
||||
<fs-icon class="ml-2 color-yellow text-md pointer" icon="solar:undo-left-square-bold" @click="resetStatus"></fs-icon>
|
||||
</a-tooltip>
|
||||
</td>
|
||||
<td class="center">
|
||||
<template v-if="cnameRecord.status !== 'valid'">
|
||||
<a-button type="primary" size="small" :loading="loading" @click="doVerify">点击验证</a-button>
|
||||
<a-button type="primary" size="small" :loading="loading" @click="doVerify">{{ t("certd.verifyPlan.clickToValidate") }}</a-button>
|
||||
<cname-tip :record="cnameRecord"></cname-tip>
|
||||
</template>
|
||||
|
||||
<div v-else class="helper" title="后续自动申请证书需要">不要删除CNAME</div>
|
||||
<div v-else class="helper" :title="t('certd.verifyPlan.keepCnameTitle')">{{ t("certd.verifyPlan.keepCname") }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -35,18 +35,20 @@
|
||||
<script lang="ts" setup>
|
||||
import { CnameRecord, GetByDomain } from "/@/components/plugins/cert/domains-verify-plan-editor/api";
|
||||
import { ref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { dict } from "@fast-crud/fast-crud";
|
||||
import * as api from "./api.js";
|
||||
import CnameTip from "./cname-tip.vue";
|
||||
import { Modal } from "ant-design-vue";
|
||||
import { utils } from "/@/utils/index.js";
|
||||
const { t } = useI18n();
|
||||
const statusDict = dict({
|
||||
data: [
|
||||
{ label: "待设置CNAME", value: "cname", color: "warning" },
|
||||
{ label: "验证中", value: "validating", color: "blue" },
|
||||
{ label: "验证成功", value: "valid", color: "green" },
|
||||
{ label: "验证失败", value: "failed", color: "red" },
|
||||
{ label: "验证超时", value: "timeout", color: "red" },
|
||||
{ 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" },
|
||||
],
|
||||
});
|
||||
|
||||
@@ -125,8 +127,8 @@ async function doVerify() {
|
||||
|
||||
async function resetStatus() {
|
||||
Modal.confirm({
|
||||
title: "重置状态",
|
||||
content: "确定要重置校验状态吗?",
|
||||
title: t("certd.verifyPlan.resetStatus"),
|
||||
content: t("certd.verifyPlan.confirmResetStatus"),
|
||||
onOk: async () => {
|
||||
await api.ResetStatus(cnameRecord.value.id);
|
||||
await loadRecord();
|
||||
|
||||
+9
-7
@@ -2,17 +2,17 @@
|
||||
<a-tooltip :overlay-style="{ maxWidth: '400px' }">
|
||||
<template #title>
|
||||
<div>
|
||||
<div>多试几次,如果仍然无法验证通过,请按如下步骤排查问题:</div>
|
||||
<div>1. 解析记录应该添加在{{ record.domain }}域名下</div>
|
||||
<div>2. 要添加的是CNAME类型的记录,不是TXT</div>
|
||||
<div>3. 核对记录值是否是:{{ record.recordValue }}</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>
|
||||
4. 在验证中状态下,运行下面的命令,查看cname和txt解析是否正确
|
||||
{{ t("certd.verifyPlan.cnameTip.step4") }}
|
||||
<fs-copyable :style="{ color: '#52c41a' }" :model-value="nslookupCmd"></fs-copyable>
|
||||
或者
|
||||
{{ t("certd.verifyPlan.cnameTip.or") }}
|
||||
<fs-copyable :style="{ color: '#52c41a' }" :model-value="digCmd"></fs-copyable>
|
||||
</div>
|
||||
<div>5. 如果以上检查都没有问题,则可能是DNS解析生效时间比较慢,某些提供商延迟可能高达几个小时</div>
|
||||
<div>{{ t("certd.verifyPlan.cnameTip.step5") }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<fs-icon class="ml-5 pointer" icon="mingcute:question-line"></fs-icon>
|
||||
@@ -21,9 +21,11 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
const props = defineProps<{
|
||||
record: any;
|
||||
}>();
|
||||
const { t } = useI18n();
|
||||
|
||||
const nslookupCmd = computed(() => {
|
||||
return `nslookup -q=txt _acme-challenge.${props.record.domain}`;
|
||||
|
||||
+8
-5
@@ -2,11 +2,11 @@
|
||||
<table class="cname-verify-plan">
|
||||
<thead>
|
||||
<tr>
|
||||
<td style="width: 160px">主机记录</td>
|
||||
<td style="width: 100px; text-align: center">记录类型</td>
|
||||
<td style="width: 250px">请设置CNAME记录(验证成功以后不要删除)</td>
|
||||
<td style="width: 120px" class="center">状态</td>
|
||||
<td style="width: 90px" class="center">操作</td>
|
||||
<td style="width: 160px">{{ t("certd.verifyPlan.hostRecord") }}</td>
|
||||
<td style="width: 100px; text-align: center">{{ t("certd.verifyPlan.recordType") }}</td>
|
||||
<td style="width: 250px">{{ t("certd.verifyPlan.setCnameRecord") }}</td>
|
||||
<td style="width: 120px" class="center">{{ t("certd.status") }}</td>
|
||||
<td style="width: 90px" class="center">{{ t("certd.verifyPlan.operation") }}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<template v-for="key in domains" :key="key">
|
||||
@@ -19,11 +19,14 @@
|
||||
import { CnameRecord } from "/@/components/plugins/cert/domains-verify-plan-editor/api";
|
||||
import CnameRecordInfo from "/@/components/plugins/cert/domains-verify-plan-editor/cname-record-info.vue";
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
defineOptions({
|
||||
name: "CnameVerifyPlan",
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "change"]);
|
||||
|
||||
const props = defineProps<{
|
||||
|
||||
+8
-5
@@ -2,10 +2,10 @@
|
||||
<table class="http-verify-plan">
|
||||
<thead>
|
||||
<tr>
|
||||
<td style="width: 160px">网站域名</td>
|
||||
<td style="width: 100px; text-align: center">上传方式</td>
|
||||
<td style="width: 150px">上传授权</td>
|
||||
<td style="width: 200px">网站根目录路径</td>
|
||||
<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>
|
||||
</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="网站根目录,如:/www/wwwroot" @change="onRecordChange"></a-input>
|
||||
<a-input v-model:value="item.httpUploadRootDir" :placeholder="t('certd.verifyPlan.websiteRootPlaceholder')" @change="onRecordChange"></a-input>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Ref, ref, watch, nextTick } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { HttpRecord } from "/@/components/plugins/cert/domains-verify-plan-editor/type";
|
||||
import { dict } from "@fast-crud/fast-crud";
|
||||
import { Dicts } from "/@/components/plugins/lib/dicts";
|
||||
@@ -39,6 +40,8 @@ defineOptions({
|
||||
name: "HttpVerifyPlan",
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "change"]);
|
||||
|
||||
const props = defineProps<{
|
||||
|
||||
+15
-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") }}
|
||||
<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">主域名</th>
|
||||
<th>验证方式</th>
|
||||
<th>验证计划</th>
|
||||
<th style="min-width: 100px">{{ t("certd.verifyPlan.mainDomain") }}</th>
|
||||
<th>{{ t("certd.verifyPlan.challengeType") }}</th>
|
||||
<th>{{ t("certd.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">DNS类型:</span>
|
||||
<span class="label">{{ t("certd.verifyPlan.dnsType") }}:</span>
|
||||
<span class="input">
|
||||
<fs-dict-select
|
||||
v-model:value="item.dnsProviderType"
|
||||
size="small"
|
||||
:dict="dnsProviderTypeDict"
|
||||
placeholder="DNS提供商"
|
||||
:placeholder="t('certd.verifyPlan.dnsProvider')"
|
||||
@change="onPlanChanged"
|
||||
@selected-change="onDnsProviderChange(item, $event)"
|
||||
></fs-dict-select>
|
||||
@@ -44,9 +44,9 @@
|
||||
</div>
|
||||
<a-divider type="vertical" />
|
||||
<div class="form-item">
|
||||
<span class="label">DNS授权:</span>
|
||||
<span class="label">{{ t("certd.verifyPlan.dnsAccess") }}:</span>
|
||||
<span class="input">
|
||||
<access-selector v-model="item.dnsProviderAccessId" size="small" :type="item.dnsProviderAccessType || item.dnsProviderType" placeholder="请选择" @change="onPlanChanged"></access-selector>
|
||||
<access-selector v-model="item.dnsProviderAccessId" size="small" :type="item.dnsProviderAccessType || item.dnsProviderType" :placeholder="t('certd.verifyPlan.pleaseSelect')" @change="onPlanChanged"></access-selector>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -55,7 +55,7 @@
|
||||
</div>
|
||||
<div v-if="item.type === 'http'" class="plan-http">
|
||||
<http-verify-plan v-model="item.httpVerifyPlan" @change="onPlanChanged" />
|
||||
<div class="helper">证书颁发机构将请求 https://yourdomain/.well-known/acme-challenge/xxxxxx 来验证域名所有权。</div>
|
||||
<div class="helper">{{ t("certd.verifyPlan.httpHelper") }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -72,6 +72,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { dict, FsDictSelect } from "@fast-crud/fast-crud";
|
||||
import AccessSelector from "/@/views/certd/access/access-selector/index.vue";
|
||||
import CnameVerifyPlan from "./cname-verify-plan.vue";
|
||||
@@ -84,17 +85,19 @@ defineOptions({
|
||||
name: "DomainsVerifyPlanEditor",
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const challengeTypeOptions = ref<any[]>([
|
||||
{
|
||||
label: "DNS验证",
|
||||
label: t("certd.verifyPlan.dnsChallenge"),
|
||||
value: "dns",
|
||||
},
|
||||
{
|
||||
label: "CNAME验证",
|
||||
label: t("certd.verifyPlan.cnameChallenge"),
|
||||
value: "cname",
|
||||
},
|
||||
{
|
||||
label: "HTTP验证",
|
||||
label: t("certd.verifyPlan.httpChallenge"),
|
||||
value: "http",
|
||||
},
|
||||
]);
|
||||
|
||||
+7
-6
@@ -1,5 +1,6 @@
|
||||
import Validator from "async-validator";
|
||||
import { DomainsVerifyPlanInput } from "./type";
|
||||
import { $t } from "/@/locales";
|
||||
|
||||
function checkDomainVerifyPlan(rule: any, value: DomainsVerifyPlanInput) {
|
||||
if (value == null) {
|
||||
@@ -13,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(`域名${subDomain}的CNAME未验证通过,请先设置CNAME记录,点击验证按钮`);
|
||||
throw new Error($t("certd.verifyPlan.errors.cnameNotValid", { domain: subDomain }));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +23,7 @@ function checkDomainVerifyPlan(rule: any, value: DomainsVerifyPlanInput) {
|
||||
for (const item of domains) {
|
||||
//如果有通配符域名则不允许使用http校验
|
||||
if (item.startsWith("*.")) {
|
||||
throw new Error(`域名${item}为通配符域名,不支持HTTP校验`);
|
||||
throw new Error($t("certd.verifyPlan.errors.wildcardNotSupportHttp", { domain: item }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,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(`域名${subDomain}的上传方式必须填写`);
|
||||
throw new Error($t("certd.verifyPlan.errors.uploadMethodRequired", { domain: subDomain }));
|
||||
}
|
||||
if (!plan.httpUploaderAccess) {
|
||||
throw new Error(`域名${subDomain}的上传授权信息必须填写`);
|
||||
throw new Error($t("certd.verifyPlan.errors.uploadAccessRequired", { domain: subDomain }));
|
||||
}
|
||||
if (!plan.httpUploadRootDir) {
|
||||
throw new Error(`域名${subDomain}的网站根路径必须填写`);
|
||||
throw new Error($t("certd.verifyPlan.errors.websiteRootRequired", { domain: subDomain }));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (type === "dns") {
|
||||
if (!value[domain].dnsProviderType || !value[domain].dnsProviderAccessId) {
|
||||
throw new Error(`DNS模式下,域名${domain}的DNS类型和授权信息必须填写`);
|
||||
throw new Error($t("certd.verifyPlan.errors.dnsProviderRequired", { domain }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="api-test">
|
||||
<div>
|
||||
<fs-button :loading="loading" type="primary" text="测试" icon="ion:refresh-outline" @click="doTest"></fs-button>
|
||||
<fs-button :loading="loading" type="primary" :text="t('certd.pluginCommon.test')" icon="ion:refresh-outline" @click="doTest"></fs-button>
|
||||
</div>
|
||||
|
||||
<div class="helper" :class="{ error: hasError }">
|
||||
@@ -12,6 +12,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
||||
import { ref, inject } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { Form } from "ant-design-vue";
|
||||
import { getInputFromForm } from "./utils";
|
||||
|
||||
@@ -19,6 +20,8 @@ defineOptions({
|
||||
name: "ApiTest",
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const fromType: any = inject("getFromType");
|
||||
const getScope: any = inject("get:scope");
|
||||
const getPluginType: any = inject("get:plugin:type", () => {
|
||||
@@ -61,14 +64,14 @@ const doTest = async () => {
|
||||
{
|
||||
onError(err: any) {
|
||||
hasError.value = true;
|
||||
message.value = `错误:${err.message}`;
|
||||
message.value = t("certd.pluginCommon.errorWithMessage", { message: err.message });
|
||||
},
|
||||
showErrorNotify: false,
|
||||
}
|
||||
);
|
||||
message.value = "测试请求成功";
|
||||
message.value = t("certd.pluginCommon.testRequestSuccess");
|
||||
if (res) {
|
||||
message.value += `,返回:${JSON.stringify(res)}`;
|
||||
message.value += t("certd.pluginCommon.responseSuffix", { response: JSON.stringify(res) });
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { inject, ref, watch } from "vue";
|
||||
import { useI18n } from "/@/locales";
|
||||
|
||||
defineOptions({
|
||||
name: "CertDomainsGetter",
|
||||
@@ -24,6 +25,7 @@ const emit = defineEmits<{
|
||||
}>();
|
||||
|
||||
const pipeline: any = inject("pipeline");
|
||||
const { t } = useI18n();
|
||||
|
||||
function findStepFromPipeline(targetStepId: string) {
|
||||
for (const stage of pipeline.value.stages) {
|
||||
@@ -40,7 +42,7 @@ function findStepFromPipeline(targetStepId: string) {
|
||||
const errorRef = ref("");
|
||||
function getStepIdFromInputKey(inputKey: string) {
|
||||
if (!inputKey) {
|
||||
errorRef.value = "请先选择域名证书";
|
||||
errorRef.value = t("certd.pluginCommon.selectCertFirst");
|
||||
return;
|
||||
}
|
||||
return inputKey.split(".")[1];
|
||||
@@ -49,7 +51,7 @@ function getDomainFromPipeline(inputKey: string) {
|
||||
let targetStepId = getStepIdFromInputKey(inputKey);
|
||||
let certStep = findStepFromPipeline(targetStepId);
|
||||
if (!certStep) {
|
||||
errorRef.value = "找不到目标步骤,请先选择域名证书";
|
||||
errorRef.value = t("certd.pluginCommon.targetStepNotFound");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -58,7 +60,7 @@ function getDomainFromPipeline(inputKey: string) {
|
||||
targetStepId = getStepIdFromInputKey(firstLevelValue);
|
||||
certStep = findStepFromPipeline(targetStepId);
|
||||
if (!certStep) {
|
||||
errorRef.value = "找不到目标步骤,请先选择域名证书";
|
||||
errorRef.value = t("certd.pluginCommon.targetStepNotFound");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,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="这里可以搜索域名(数据来自“设置->域名管理”),您也可以直接在上面输入框输入" @keydown.enter="doSearch" />
|
||||
<fs-button type="primary" class="m-1" :loading="loading" icon="mingcute:search-2-line" @click="doSearch"> 查询 </fs-button>
|
||||
<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>
|
||||
</div>
|
||||
<div class="manager flex flex-row items-center">
|
||||
<fs-button type="primary" class="m-1" icon="mingcute:vip-1-line" @click="openDomainImportDialog">导入域名</fs-button>
|
||||
<fs-button class="m-1" type="primary" icon="carbon:gui-management" @click="openDomainManager">管理域名</fs-button>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="hasError" class="helper p-2" :class="{ error: hasError }">
|
||||
@@ -47,7 +47,7 @@
|
||||
</template>
|
||||
</a-select>
|
||||
<div class="ml-5">
|
||||
<fs-button :loading="loading" title="刷新我的域名列表" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
<fs-button :loading="loading" :title="t('certd.pluginCommon.refreshMyDomains')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="helper" :class="{ error: hasError }">
|
||||
@@ -57,6 +57,7 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, defineComponent, onMounted, ref, Ref, useAttrs } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Dicts } from "../lib/dicts";
|
||||
import { request } from "/@/api/service";
|
||||
@@ -67,6 +68,8 @@ defineOptions({
|
||||
name: "DomainSelector",
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const VNodes = defineComponent({
|
||||
props: {
|
||||
vnodes: {
|
||||
|
||||
@@ -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="刷新选项" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
<fs-button :loading="loading" :title="t('certd.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="helper" :class="{ error: hasError }">
|
||||
@@ -15,6 +15,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
||||
import { defineComponent, inject, ref, useAttrs, watch, Ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { PluginDefine } from "@certd/pipeline";
|
||||
import { getInputFromForm } from "./utils";
|
||||
|
||||
@@ -22,6 +23,8 @@ defineOptions({
|
||||
name: "RemoteAutoComplete",
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = defineProps<
|
||||
{
|
||||
watches?: string[];
|
||||
@@ -93,16 +96,16 @@ const getOptions = async () => {
|
||||
{
|
||||
onError(err: any) {
|
||||
hasError.value = true;
|
||||
message.value = `获取选项出错:${err.message}`;
|
||||
message.value = t("certd.pluginCommon.getOptionsError", { message: err.message });
|
||||
},
|
||||
showErrorNotify: false,
|
||||
}
|
||||
);
|
||||
const list = res?.list || res || [];
|
||||
if (list.length > 0) {
|
||||
message.value = "获取数据成功,请从下拉框中选择";
|
||||
message.value = t("certd.pluginCommon.getDataSuccessSelect");
|
||||
} else {
|
||||
message.value = "获取数据成功,没有数据";
|
||||
message.value = t("certd.pluginCommon.getDataSuccessEmpty");
|
||||
}
|
||||
optionsRef.value = list;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<script setup lang="ts">
|
||||
import { doRequest } from "/@/components/plugins/lib";
|
||||
import { inject, ref, useAttrs } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useFormWrapper } from "@fast-crud/fast-crud";
|
||||
import { notification } from "ant-design-vue";
|
||||
import { getInputFromForm } from "./utils";
|
||||
@@ -15,6 +16,7 @@ defineOptions({
|
||||
name: "RemoteInput",
|
||||
});
|
||||
const { openCrudFormDialog } = useFormWrapper();
|
||||
const { t } = useI18n();
|
||||
const props = defineProps<{
|
||||
modelValue: string;
|
||||
title: string;
|
||||
@@ -53,7 +55,7 @@ async function openDialog() {
|
||||
saveRemind: false,
|
||||
},
|
||||
afterSubmit() {
|
||||
notification.success({ message: "操作成功" });
|
||||
notification.success({ message: t("certd.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="查询关键字" @keydown.enter="doSearch" />
|
||||
<a-input ref="inputRef" v-model:value="searchKeyRef" class="flex-1" allow-clear :placeholder="t('certd.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") }}
|
||||
</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="刷新选项" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
<fs-button :loading="loading" :title="t('certd.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>
|
||||
@@ -38,6 +38,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
||||
import { defineComponent, inject, ref, useAttrs, watch, Ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { PluginDefine } from "@certd/pipeline";
|
||||
import { getInputFromForm } from "./utils";
|
||||
import UploadCert from "./upload-cert.vue";
|
||||
@@ -47,6 +48,8 @@ defineOptions({
|
||||
name: "RemoteSelect",
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const selectRef = ref(null);
|
||||
|
||||
const VNodes = defineComponent({
|
||||
@@ -161,7 +164,7 @@ const getOptions = async () => {
|
||||
{
|
||||
onError(err: any) {
|
||||
hasError.value = true;
|
||||
message.value = `获取选项出错:${err.message}`;
|
||||
message.value = t("certd.pluginCommon.getOptionsError", { message: err.message });
|
||||
optionsRef.value = [];
|
||||
},
|
||||
showErrorNotify: false,
|
||||
@@ -169,9 +172,9 @@ const getOptions = async () => {
|
||||
);
|
||||
let list = res?.list || res || [];
|
||||
if (list.length > 0) {
|
||||
message.value = "获取数据成功,请从下拉框中选择";
|
||||
message.value = t("certd.pluginCommon.getDataSuccessSelect");
|
||||
} else {
|
||||
message.value = "获取数据成功,没有数据";
|
||||
message.value = t("certd.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="刷新选项" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
<fs-button :loading="loading" :title="t('certd.pluginCommon.refreshOptions')" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="helper" :class="{ error: hasError }">
|
||||
@@ -14,6 +14,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
||||
import { defineComponent, inject, ref, useAttrs, watch, Ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { PluginDefine } from "@certd/pipeline";
|
||||
import { getInputFromForm } from "./utils";
|
||||
|
||||
@@ -21,6 +22,8 @@ defineOptions({
|
||||
name: "RemoteTreeSelect",
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = defineProps<
|
||||
{
|
||||
watches: string[];
|
||||
@@ -104,16 +107,16 @@ const getOptions = async () => {
|
||||
{
|
||||
onError(err: any) {
|
||||
hasError.value = true;
|
||||
message.value = `获取选项出错:${err.message}`;
|
||||
message.value = t("certd.pluginCommon.getOptionsError", { message: err.message });
|
||||
},
|
||||
showErrorNotify: false,
|
||||
}
|
||||
);
|
||||
const list = res?.list || res || [];
|
||||
if (list.length > 0) {
|
||||
message.value = "获取数据成功,请从下拉框中选择";
|
||||
message.value = t("certd.pluginCommon.getDataSuccessSelect");
|
||||
} else {
|
||||
message.value = "获取数据成功,没有数据";
|
||||
message.value = t("certd.pluginCommon.getDataSuccessEmpty");
|
||||
}
|
||||
optionsRef.value = list;
|
||||
pagerRef.value.total = list.length;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<div class="upload-cert">
|
||||
<fs-button v-model:loading="loading" type="primary" text="上传" v-bind="props.button" @click="openUploadCertDialog"></fs-button>
|
||||
<fs-button v-model:loading="loading" type="primary" :text="t('certd.pluginCommon.upload')" v-bind="props.button" @click="openUploadCertDialog"></fs-button>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { message } from "ant-design-vue";
|
||||
import { useFormDialog } from "../../../use/use-dialog";
|
||||
import { computed, inject, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { doRequest } from "../lib";
|
||||
import { getInputFromForm } from "./utils";
|
||||
import { UploadCertProps } from "./types";
|
||||
@@ -14,6 +15,7 @@ import { merge } from "lodash-es";
|
||||
|
||||
const props = defineProps<UploadCertProps>();
|
||||
const loading = ref(false);
|
||||
const { t } = useI18n();
|
||||
|
||||
const emit = defineEmits(["submit"]);
|
||||
const { openFormDialog } = useFormDialog();
|
||||
@@ -28,18 +30,18 @@ const getScope: any = inject("get:scope", () => {
|
||||
const getPluginType: any = inject("get:plugin:type", () => {
|
||||
return "plugin";
|
||||
});
|
||||
const title = computed(() => props.title || "上传证书");
|
||||
const title = computed(() => props.title || t("certd.pluginCommon.uploadCert"));
|
||||
function openUploadCertDialog() {
|
||||
const columns = merge(
|
||||
{
|
||||
certName: {
|
||||
title: "证书名称",
|
||||
title: t("certd.pluginCommon.certName"),
|
||||
form: {
|
||||
component: {
|
||||
name: "a-input",
|
||||
vModel: "value",
|
||||
},
|
||||
helper: "上传后证书显示名称",
|
||||
helper: t("certd.pluginCommon.certNameHelper"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -49,7 +51,7 @@ function openUploadCertDialog() {
|
||||
title: title.value,
|
||||
columns: {
|
||||
certName: {
|
||||
title: "证书名称",
|
||||
title: t("certd.pluginCommon.certName"),
|
||||
form: {
|
||||
component: {
|
||||
name: "a-input",
|
||||
@@ -84,7 +86,7 @@ function openUploadCertDialog() {
|
||||
showErrorNotify: true,
|
||||
}
|
||||
);
|
||||
message.success("上传成功");
|
||||
message.success(t("certd.pluginCommon.uploadSuccess"));
|
||||
emit("submit");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { dict } from "@fast-crud/fast-crud";
|
||||
import { $t } from "/@/locales";
|
||||
|
||||
export const Dicts = {
|
||||
sslProviderDict: dict({
|
||||
data: [
|
||||
{ value: "letsencrypt", label: "Let‘s Encrypt" },
|
||||
{ value: "letsencrypt", label: "Let's Encrypt" },
|
||||
{ value: "zerossl", label: "ZeroSSL" },
|
||||
],
|
||||
}),
|
||||
challengeTypeDict: dict({
|
||||
data: [
|
||||
{ value: "dns", label: "DNS校验", color: "green" },
|
||||
{ value: "cname", label: "CNAME代理校验", color: "blue" },
|
||||
{ value: "http", label: "HTTP校验", color: "yellow" },
|
||||
{ value: "dns", label: $t("certd.verifyPlan.dnsChallenge"), color: "green" },
|
||||
{ value: "cname", label: $t("certd.verifyPlan.cnameProxyChallenge"), color: "blue" },
|
||||
{ value: "http", label: $t("certd.verifyPlan.httpChallenge"), color: "yellow" },
|
||||
],
|
||||
}),
|
||||
dnsProviderTypeDict: dict({
|
||||
@@ -22,17 +23,17 @@ export const Dicts = {
|
||||
{ label: "SFTP", value: "sftp" },
|
||||
{ label: "SCP", value: "scp" },
|
||||
{ label: "FTP", value: "ftp" },
|
||||
{ label: "阿里云OSS", value: "alioss" },
|
||||
{ label: "腾讯云COS", value: "tencentcos" },
|
||||
{ label: "七牛OSS", value: "qiniuoss" },
|
||||
{ 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: "S3/Minio", value: "s3" },
|
||||
{ label: "SSH(已废弃,请选择SFTP方式)", value: "ssh", disabled: true },
|
||||
{ label: $t("certd.verifyPlan.uploader.sshDeprecated"), value: "ssh", disabled: true },
|
||||
],
|
||||
}),
|
||||
domainFromTypeDict: dict({
|
||||
data: [
|
||||
{ value: "manual", label: "手动" },
|
||||
{ value: "auto", label: "自动" },
|
||||
{ value: "manual", label: $t("certd.verifyPlan.domainFrom.manual") },
|
||||
{ value: "auto", label: $t("certd.verifyPlan.domainFrom.auto") },
|
||||
],
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -14,5 +14,93 @@ export default {
|
||||
gotoCnameTip: "Please go to CNAME Record Page",
|
||||
fromType: "From Type",
|
||||
expirationDate: "Expiration Date",
|
||||
cnameManagedInCnamePage: "For CNAME mode, please manage records on the CNAME Records page.",
|
||||
subdomainConfirmTitle: "Subdomain Confirmation",
|
||||
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",
|
||||
syncExpirationDate: "Sync Domain Expiration Time",
|
||||
syncTaskSubmitted: "Sync task submitted",
|
||||
expirationMonitorSetting: "Domain Expiration Monitor Settings",
|
||||
subdomainDnsHelper: "Note: In DNS validation mode, subdomains do not need to be maintained here, otherwise certificate application may be affected (except delegated subdomains or free second-level domains).",
|
||||
path: "Path",
|
||||
addImportTask: "Add Import Task",
|
||||
refresh: "Refresh",
|
||||
progress: "Progress",
|
||||
operation: "Operation",
|
||||
total: "Total",
|
||||
skipped: "Skipped",
|
||||
failed: "Failed",
|
||||
notExecuted: "Not executed",
|
||||
execute: "Run",
|
||||
delete: "Delete",
|
||||
confirmDelete: "Confirm deletion?",
|
||||
domainProvider: "Domain Provider",
|
||||
domainProviderAccessType: "Domain Provider Access Type",
|
||||
domainProviderAccess: "Domain Provider Access",
|
||||
},
|
||||
verifyPlan: {
|
||||
expandTip: "Click to enlarge",
|
||||
mainDomain: "Main Domain",
|
||||
challengeType: "Challenge Method",
|
||||
challengePlan: "Challenge Plan",
|
||||
dnsType: "DNS Type",
|
||||
dnsProvider: "DNS Provider",
|
||||
dnsAccess: "DNS Access",
|
||||
pleaseSelect: "Please select",
|
||||
httpHelper: "The CA will request https://yourdomain/.well-known/acme-challenge/xxxxxx to verify domain ownership.",
|
||||
dnsChallenge: "DNS Challenge",
|
||||
cnameChallenge: "CNAME Challenge",
|
||||
cnameProxyChallenge: "CNAME Proxy Challenge",
|
||||
httpChallenge: "HTTP Challenge",
|
||||
domainTitle: "Domain: {domain}",
|
||||
resetStatusTooltip: "Reset validation status and validate again",
|
||||
clickToValidate: "Validate",
|
||||
keepCnameTitle: "Required for future automatic certificate applications",
|
||||
keepCname: "Do not delete CNAME",
|
||||
resetStatus: "Reset Status",
|
||||
confirmResetStatus: "Are you sure you want to reset the validation status?",
|
||||
hostRecord: "Host Record",
|
||||
recordType: "Record Type",
|
||||
setCnameRecord: "Set the CNAME record. Do not delete it after validation succeeds.",
|
||||
operation: "Operation",
|
||||
websiteDomain: "Website Domain",
|
||||
uploadMethod: "Upload Method",
|
||||
uploadAccess: "Upload Access",
|
||||
websiteRootPath: "Website Root Path",
|
||||
websiteRootPlaceholder: "Website root path, e.g. /www/wwwroot",
|
||||
status: {
|
||||
pendingCname: "Pending CNAME Setup",
|
||||
validating: "Validating",
|
||||
valid: "Validation Successful",
|
||||
failed: "Validation Failed",
|
||||
timeout: "Validation Timed Out",
|
||||
},
|
||||
cnameTip: {
|
||||
intro: "Try a few more times. If validation still fails, troubleshoot with these steps:",
|
||||
step1: "1. The DNS record should be added under {domain}.",
|
||||
step2: "2. Add a CNAME record, not a TXT record.",
|
||||
step3: "3. Check whether the record value is: {value}",
|
||||
step4: "4. While validating, run the command below to check whether CNAME and TXT resolution are correct.",
|
||||
or: "or",
|
||||
step5: "5. If all checks pass, DNS propagation may be slow. Some providers can take several hours.",
|
||||
},
|
||||
errors: {
|
||||
cnameNotValid: "The CNAME for domain {domain} has not been validated. Set the CNAME record first, then click Validate.",
|
||||
wildcardNotSupportHttp: "Domain {domain} is a wildcard domain and does not support HTTP validation.",
|
||||
uploadMethodRequired: "The upload method for domain {domain} is required.",
|
||||
uploadAccessRequired: "The upload access for domain {domain} is required.",
|
||||
websiteRootRequired: "The website root path for domain {domain} is required.",
|
||||
dnsProviderRequired: "In DNS mode, the DNS type and access information for domain {domain} are required.",
|
||||
},
|
||||
uploader: {
|
||||
aliyunOss: "Alibaba Cloud OSS",
|
||||
tencentCos: "Tencent Cloud COS",
|
||||
qiniuOss: "Qiniu OSS",
|
||||
sshDeprecated: "SSH (deprecated, use SFTP instead)",
|
||||
},
|
||||
domainFrom: {
|
||||
manual: "Manual",
|
||||
auto: "Automatic",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -18,4 +18,24 @@ export default {
|
||||
cname_feature_guide: "CNAME feature principle and usage guide",
|
||||
mainDomain: "Main Domain",
|
||||
cnameRecord: "CNAME Record Management",
|
||||
importRecords: "Import CNAME Records",
|
||||
batchImport: "Batch Import",
|
||||
exportRecordsTip: "After exporting CNAME records, you can batch import CNAME DNS records to the domain registrar.",
|
||||
batchExport: "Batch Export",
|
||||
resetStatus: "Reset Status",
|
||||
confirmResetStatus: "Are you sure you want to reset the validation status?",
|
||||
resetStatusTooltip: "Reset validation status and validate again",
|
||||
cname: {
|
||||
importRecords: "Import CNAME Records",
|
||||
batchImport: "Batch Import",
|
||||
exportRecordsTip: "After exporting CNAME records, you can batch import CNAME DNS records to the domain registrar.",
|
||||
batchExport: "Batch Export",
|
||||
resetStatus: "Reset Status",
|
||||
confirmResetStatus: "Are you sure you want to reset the validation status?",
|
||||
resetStatusTooltip: "Reset validation status and validate again",
|
||||
domainList: "Domain List",
|
||||
domainListHelper: "One domain per line for batch import\nRemove *. from wildcard domains\nExisting records will be skipped automatically",
|
||||
cnameService: "CNAME Service",
|
||||
importTaskSubmitted: "Import task submitted",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -113,4 +113,36 @@ export default {
|
||||
helpDocLink: "Help Docs",
|
||||
suite: "Suite",
|
||||
helpDoc: "Help Document",
|
||||
pluginCommon: {
|
||||
test: "Test",
|
||||
errorWithMessage: "Error: {message}",
|
||||
testRequestSuccess: "Test request succeeded",
|
||||
responseSuffix: ", response: {response}",
|
||||
searchKeyword: "Search keyword",
|
||||
search: "Search",
|
||||
refreshOptions: "Refresh options",
|
||||
getOptionsError: "Failed to get options: {message}",
|
||||
getDataSuccessSelect: "Data loaded. Please select from the dropdown.",
|
||||
getDataSuccessEmpty: "Data loaded. No data found.",
|
||||
domainSearchPlaceholder: "Search domains here (from Settings -> Domain Management), or type directly in the input above",
|
||||
importDomain: "Import Domains",
|
||||
manageDomain: "Manage Domains",
|
||||
refreshMyDomains: "Refresh my domain list",
|
||||
upload: "Upload",
|
||||
uploadCert: "Upload Certificate",
|
||||
certName: "Certificate Name",
|
||||
certNameHelper: "Display name after upload",
|
||||
uploadSuccess: "Upload successful",
|
||||
selectCertFirst: "Please select a domain certificate first",
|
||||
targetStepNotFound: "Target step not found. Please select a domain certificate first.",
|
||||
},
|
||||
captcha: {
|
||||
inputImageCode: "Please enter the image captcha",
|
||||
refresh: "Refresh captcha",
|
||||
clickToVerify: "Click to verify",
|
||||
verifySuccess: "Verification successful",
|
||||
verifyFailed: "Verification failed. Please try again.",
|
||||
loadFailed: "Failed to load captcha",
|
||||
notLoaded: "Captcha is not loaded yet",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -97,6 +97,7 @@ export default {
|
||||
pipeline: "Pipeline",
|
||||
},
|
||||
editSchedule: "Edit Schedule",
|
||||
webhook: "Webhook",
|
||||
timerTrigger: "Timer Trigger",
|
||||
schedule: "Schedule",
|
||||
selectCron: "Please select a schedule Cron",
|
||||
|
||||
@@ -18,6 +18,7 @@ export default {
|
||||
project: {
|
||||
noProjectJoined: "You haven't joined any projects yet",
|
||||
applyToJoin: "Please apply to join a project to start using",
|
||||
projectList: "Project List",
|
||||
systemProjects: "System Project List",
|
||||
createdAt: "Created At",
|
||||
applyJoin: "Apply to Join",
|
||||
|
||||
@@ -7,8 +7,13 @@ export default {
|
||||
settingLink: "Site Monitoring Settings",
|
||||
limitInfo: "Basic edition limited to 1, professional and above unlimited, current",
|
||||
checkAll: "Check All",
|
||||
checkNow: "Check Now",
|
||||
batchDelete: "Batch Delete",
|
||||
confirmTitle: "Confirm",
|
||||
confirmContent: "Confirm to trigger check for all site certificates?",
|
||||
batchDeleteConfirm: "Are you sure you want to batch delete these {count} records?",
|
||||
deleteSuccess: "Delete successful",
|
||||
selectRecordsFirst: "Please select records first",
|
||||
checkSubmitted: "Check task submitted",
|
||||
pleaseRefresh: "Please refresh the page later to see the results",
|
||||
siteName: "Site Name",
|
||||
@@ -39,6 +44,10 @@ export default {
|
||||
ipCheckHelper: "Enable to check certificate expiration time on each IP (or source site domain) ",
|
||||
ipSyncAuto: "Enable IP Sync Auto",
|
||||
ipSyncMode: "IP Sync Mode",
|
||||
ipSyncModeHelper: "Choose whether to check only IPv4, only IPv6, or all IPs.",
|
||||
ipSyncModeAll: "Check all IPs",
|
||||
ipSyncModeIPV4Only: "Check IPv4 only",
|
||||
ipSyncModeIPV6Only: "Check IPv6 only",
|
||||
ipIgnoreCoherence: "Ignore Certificate Coherence",
|
||||
ipIgnoreCoherenceHelper: "Enable to ignore certificate coherence check, only check certificate expiration time",
|
||||
selectRequired: "Please select",
|
||||
@@ -49,6 +58,10 @@ export default {
|
||||
certInfoId: "Certificate ID",
|
||||
checkSubmittedRefresh: "Check task submitted. Please refresh later to view the result.",
|
||||
ipManagement: "IP Management",
|
||||
siteIpMonitor: "Site IP Monitor",
|
||||
ipList: "IP List",
|
||||
ipListHelper: "One IP or CNAME domain per line",
|
||||
enterImportIpOrDomain: "Please enter the IPs or domains to import",
|
||||
bulkImport: "Bulk Import",
|
||||
basicLimitError: "Basic version allows only one monitoring site. Please upgrade to the Pro version.",
|
||||
limitExceeded: "Sorry, you can only create up to {max} monitoring records. Please purchase or upgrade your plan.",
|
||||
|
||||
@@ -14,5 +14,93 @@ export default {
|
||||
gotoCnameTip: "CNAME域名配置请前往CNAME记录页面添加",
|
||||
fromType: "来源类型",
|
||||
expirationDate: "到期时间",
|
||||
cnameManagedInCnamePage: "CNAME方式请前往CNAME记录页面进行管理",
|
||||
subdomainConfirmTitle: "子域名确认",
|
||||
subdomainConfirmContent: "检测到{domain}为子域名,只有托管子域名和免费二级子域名才需要在此处维护,否则会导致申请证书失败,请确认是否继续?",
|
||||
importFromProvider: "从域名提供商导入",
|
||||
syncExpirationDate: "同步域名过期时间",
|
||||
syncTaskSubmitted: "同步任务已提交",
|
||||
expirationMonitorSetting: "域名过期监控设置",
|
||||
subdomainDnsHelper: "注意:DNS校验方式下,子域名不需要在此处维护,否则会影响证书申请(子域名托管或免费二级域名除外)",
|
||||
path: "路径",
|
||||
addImportTask: "添加导入任务",
|
||||
refresh: "刷新",
|
||||
progress: "进度",
|
||||
operation: "操作",
|
||||
total: "总数",
|
||||
skipped: "跳过",
|
||||
failed: "失败",
|
||||
notExecuted: "未执行",
|
||||
execute: "执行",
|
||||
delete: "删除",
|
||||
confirmDelete: "确认删除吗?",
|
||||
domainProvider: "域名提供商",
|
||||
domainProviderAccessType: "域名提供商访问类型",
|
||||
domainProviderAccess: "域名提供商授权",
|
||||
},
|
||||
verifyPlan: {
|
||||
expandTip: "这里可以放大",
|
||||
mainDomain: "主域名",
|
||||
challengeType: "验证方式",
|
||||
challengePlan: "验证计划",
|
||||
dnsType: "DNS类型",
|
||||
dnsProvider: "DNS提供商",
|
||||
dnsAccess: "DNS授权",
|
||||
pleaseSelect: "请选择",
|
||||
httpHelper: "证书颁发机构将请求 https://yourdomain/.well-known/acme-challenge/xxxxxx 来验证域名所有权。",
|
||||
dnsChallenge: "DNS验证",
|
||||
cnameChallenge: "CNAME验证",
|
||||
cnameProxyChallenge: "CNAME代理验证",
|
||||
httpChallenge: "HTTP验证",
|
||||
domainTitle: "域名:{domain}",
|
||||
resetStatusTooltip: "重置校验状态,重新校验",
|
||||
clickToValidate: "点击验证",
|
||||
keepCnameTitle: "后续自动申请证书需要",
|
||||
keepCname: "不要删除CNAME",
|
||||
resetStatus: "重置状态",
|
||||
confirmResetStatus: "确定要重置校验状态吗?",
|
||||
hostRecord: "主机记录",
|
||||
recordType: "记录类型",
|
||||
setCnameRecord: "请设置CNAME记录(验证成功以后不要删除)",
|
||||
operation: "操作",
|
||||
websiteDomain: "网站域名",
|
||||
uploadMethod: "上传方式",
|
||||
uploadAccess: "上传授权",
|
||||
websiteRootPath: "网站根目录路径",
|
||||
websiteRootPlaceholder: "网站根目录,如:/www/wwwroot",
|
||||
status: {
|
||||
pendingCname: "待设置CNAME",
|
||||
validating: "验证中",
|
||||
valid: "验证成功",
|
||||
failed: "验证失败",
|
||||
timeout: "验证超时",
|
||||
},
|
||||
cnameTip: {
|
||||
intro: "多试几次,如果仍然无法验证通过,请按如下步骤排查问题:",
|
||||
step1: "1. 解析记录应该添加在{domain}域名下",
|
||||
step2: "2. 要添加的是CNAME类型的记录,不是TXT",
|
||||
step3: "3. 核对记录值是否是:{value}",
|
||||
step4: "4. 在验证中状态下,运行下面的命令,查看cname和txt解析是否正确",
|
||||
or: "或者",
|
||||
step5: "5. 如果以上检查都没有问题,则可能是DNS解析生效时间比较慢,某些提供商延迟可能高达几个小时",
|
||||
},
|
||||
errors: {
|
||||
cnameNotValid: "域名{domain}的CNAME未验证通过,请先设置CNAME记录,点击验证按钮",
|
||||
wildcardNotSupportHttp: "域名{domain}为通配符域名,不支持HTTP校验",
|
||||
uploadMethodRequired: "域名{domain}的上传方式必须填写",
|
||||
uploadAccessRequired: "域名{domain}的上传授权信息必须填写",
|
||||
websiteRootRequired: "域名{domain}的网站根路径必须填写",
|
||||
dnsProviderRequired: "DNS模式下,域名{domain}的DNS类型和授权信息必须填写",
|
||||
},
|
||||
uploader: {
|
||||
aliyunOss: "阿里云OSS",
|
||||
tencentCos: "腾讯云COS",
|
||||
qiniuOss: "七牛OSS",
|
||||
sshDeprecated: "SSH(已废弃,请选择SFTP方式)",
|
||||
},
|
||||
domainFrom: {
|
||||
manual: "手动",
|
||||
auto: "自动",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -18,4 +18,24 @@ export default {
|
||||
cname_feature_guide: "CNAME功能原理及使用说明",
|
||||
mainDomain: "主域名",
|
||||
cnameRecord: "CNAME记录管理",
|
||||
importRecords: "导入CNAME记录",
|
||||
batchImport: "批量导入",
|
||||
exportRecordsTip: "导出CNAME记录之后,可用于批量导入cname解析到域名注册商",
|
||||
batchExport: "批量导出",
|
||||
resetStatus: "重置状态",
|
||||
confirmResetStatus: "确定要重置校验状态吗?",
|
||||
resetStatusTooltip: "重置校验状态,重新校验",
|
||||
cname: {
|
||||
importRecords: "导入CNAME记录",
|
||||
batchImport: "批量导入",
|
||||
exportRecordsTip: "导出CNAME记录之后,可用于批量导入cname解析到域名注册商",
|
||||
batchExport: "批量导出",
|
||||
resetStatus: "重置状态",
|
||||
confirmResetStatus: "确定要重置校验状态吗?",
|
||||
resetStatusTooltip: "重置校验状态,重新校验",
|
||||
domainList: "域名列表",
|
||||
domainListHelper: "每个域名一行,批量导入\n泛域名请去掉*.\n已经存在的会自动跳过",
|
||||
cnameService: "CNAME服务",
|
||||
importTaskSubmitted: "导入任务已提交",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -117,4 +117,36 @@ export default {
|
||||
helpDocLink: "帮助文档",
|
||||
suite: "套餐",
|
||||
helpDoc: "帮助说明",
|
||||
pluginCommon: {
|
||||
test: "测试",
|
||||
errorWithMessage: "错误:{message}",
|
||||
testRequestSuccess: "测试请求成功",
|
||||
responseSuffix: ",返回:{response}",
|
||||
searchKeyword: "查询关键字",
|
||||
search: "查询",
|
||||
refreshOptions: "刷新选项",
|
||||
getOptionsError: "获取选项出错:{message}",
|
||||
getDataSuccessSelect: "获取数据成功,请从下拉框中选择",
|
||||
getDataSuccessEmpty: "获取数据成功,没有数据",
|
||||
domainSearchPlaceholder: "这里可以搜索域名(数据来自“设置->域名管理”),您也可以直接在上面输入框输入",
|
||||
importDomain: "导入域名",
|
||||
manageDomain: "管理域名",
|
||||
refreshMyDomains: "刷新我的域名列表",
|
||||
upload: "上传",
|
||||
uploadCert: "上传证书",
|
||||
certName: "证书名称",
|
||||
certNameHelper: "上传后证书显示名称",
|
||||
uploadSuccess: "上传成功",
|
||||
selectCertFirst: "请先选择域名证书",
|
||||
targetStepNotFound: "找不到目标步骤,请先选择域名证书",
|
||||
},
|
||||
captcha: {
|
||||
inputImageCode: "请输入图形验证码",
|
||||
refresh: "刷新验证码",
|
||||
clickToVerify: "点击验证",
|
||||
verifySuccess: "验证成功",
|
||||
verifyFailed: "验证失败,请重试",
|
||||
loadFailed: "加载验证码失败",
|
||||
notLoaded: "验证码未加载完成",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -7,8 +7,13 @@ export default {
|
||||
settingLink: "站点监控设置",
|
||||
limitInfo: "基础版限制1条,专业版以上无限制,当前",
|
||||
checkAll: "检查全部",
|
||||
checkNow: "立即检查",
|
||||
batchDelete: "批量删除",
|
||||
confirmTitle: "确认",
|
||||
confirmContent: "确认触发检查全部站点证书吗?",
|
||||
batchDeleteConfirm: "确定要批量删除这{count}条记录吗",
|
||||
deleteSuccess: "删除成功",
|
||||
selectRecordsFirst: "请先勾选记录",
|
||||
checkSubmitted: "检查任务已提交",
|
||||
pleaseRefresh: "请稍后刷新页面查看结果",
|
||||
siteName: "站点名称",
|
||||
@@ -53,6 +58,10 @@ export default {
|
||||
certInfoId: "证书ID",
|
||||
checkSubmittedRefresh: "检查任务已提交,请稍后刷新查看结果",
|
||||
ipManagement: "IP管理",
|
||||
siteIpMonitor: "站点IP监控",
|
||||
ipList: "IP列表",
|
||||
ipListHelper: "IP或者CNAME域名,一行一个",
|
||||
enterImportIpOrDomain: "请输入要导入的IP或域名",
|
||||
bulkImport: "批量导入",
|
||||
basicLimitError: "基础版只能添加一个监控站点,请赞助升级专业版",
|
||||
limitExceeded: "对不起,您最多只能创建条{max}监控记录,请购买或升级套餐",
|
||||
|
||||
@@ -89,15 +89,15 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
form: {
|
||||
async beforeSubmit({ form }) {
|
||||
if (form.challengeType === "cname") {
|
||||
throw new Error("CNAME方式请前往CNAME记录页面进行管理");
|
||||
throw new Error(t("certd.domain.cnameManagedInCnamePage"));
|
||||
}
|
||||
if (form.challengeType === "dns") {
|
||||
const isSubdomain = await api.IsSubdomain({ domain: form.domain });
|
||||
if (isSubdomain && !subdomainConfirmed.value) {
|
||||
Modal.confirm({
|
||||
title: "子域名确认",
|
||||
content: `检测到${form.domain}为子域名,只有托管子域名和免费二级子域名才需要在此处维护,否则会导致申请证书失败,请确认是否继续?`,
|
||||
okText: "确认",
|
||||
title: t("certd.domain.subdomainConfirmTitle"),
|
||||
content: t("certd.domain.subdomainConfirmContent", { domain: form.domain }),
|
||||
okText: t("common.confirm"),
|
||||
okType: "danger",
|
||||
onOk: () => {
|
||||
subdomainConfirmed.value = true;
|
||||
@@ -119,9 +119,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
},
|
||||
import: {
|
||||
show: hasActionPermission("write"),
|
||||
title: "从域名提供商导入域名",
|
||||
title: t("certd.domain.importFromProvider"),
|
||||
type: "primary",
|
||||
text: "从域名提供商导入",
|
||||
text: t("certd.domain.importFromProvider"),
|
||||
needPlus: true,
|
||||
color: "gold",
|
||||
icon: "mingcute:vip-1-line",
|
||||
@@ -135,14 +135,14 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
},
|
||||
syncExpirationDate: {
|
||||
show: hasActionPermission("write"),
|
||||
title: "同步域名过期时间",
|
||||
title: t("certd.domain.syncExpirationDate"),
|
||||
type: "primary",
|
||||
icon: "ion:refresh-outline",
|
||||
text: "同步域名过期时间",
|
||||
text: t("certd.domain.syncExpirationDate"),
|
||||
click: async () => {
|
||||
await api.SyncExpirationStart();
|
||||
notification.success({
|
||||
message: "同步任务已提交",
|
||||
message: t("certd.domain.syncTaskSubmitted"),
|
||||
});
|
||||
setTimeout(() => {
|
||||
crudExpose.doRefresh();
|
||||
@@ -151,10 +151,10 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
},
|
||||
monitorSettingSave: {
|
||||
show: hasActionPermission("write"),
|
||||
title: "域名过期监控设置",
|
||||
title: t("certd.domain.expirationMonitorSetting"),
|
||||
type: "primary",
|
||||
icon: "ion:save-outline",
|
||||
text: "域名过期监控设置",
|
||||
text: t("certd.domain.expirationMonitorSetting"),
|
||||
click: async () => {
|
||||
router.push({
|
||||
path: "/certd/cert/domain/setting",
|
||||
@@ -184,7 +184,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
},
|
||||
form: {
|
||||
required: true,
|
||||
helper: "注意:DNS校验方式下,子域名不需要在此处维护,否则会影响证书申请(子域名托管或免费二级域名除外)",
|
||||
helper: t("certd.domain.subdomainDnsHelper"),
|
||||
},
|
||||
editForm: {
|
||||
component: {
|
||||
@@ -361,7 +361,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
<fs-values-format modelValue={row.challengeType} dict={Dicts.challengeTypeDict} color={"auto"}></fs-values-format>
|
||||
<fs-values-format modelValue={row.httpUploaderType} dict={httpUploaderTypeDict} color={"auto"}></fs-values-format>
|
||||
<fs-values-format class={"ml-5"} modelValue={row.httpUploaderAccess} dict={accessDict} color={"auto"}></fs-values-format>
|
||||
<a-tag class={"ml-5 flex items-center"}>路径:{row.httpUploadRootDir}</a-tag>
|
||||
<a-tag class={"ml-5 flex items-center"}>{t("certd.domain.path")}: {row.httpUploadRootDir}</a-tag>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<template>
|
||||
<div class="domain-import-task-status min-h-[300px]">
|
||||
<div class="action mb-5">
|
||||
<fs-button type="primary" icon="mingcute:vip-1-line" @click="addTask">添加导入任务</fs-button>
|
||||
<fs-button type="primary" icon="ion:refresh-outline" class="ml-2" @click="loadImportTaskStatus">刷新</fs-button>
|
||||
<fs-button type="primary" icon="mingcute:vip-1-line" @click="addTask">{{ t("certd.domain.addImportTask") }}</fs-button>
|
||||
<fs-button type="primary" icon="ion:refresh-outline" class="ml-2" @click="loadImportTaskStatus">{{ t("certd.domain.refresh") }}</fs-button>
|
||||
</div>
|
||||
<div class="table-container overflow-auto mb-10">
|
||||
<table class="cd-table border-gray-300 w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-[220px]">来源</th>
|
||||
<th class="">进度</th>
|
||||
<th class="w-[220px]">操作</th>
|
||||
<th class="w-[220px]">{{ t("certd.sourcee") }}</th>
|
||||
<th class="">{{ t("certd.domain.progress") }}</th>
|
||||
<th class="w-[220px]">{{ t("certd.domain.operation") }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -27,23 +27,23 @@
|
||||
<td>
|
||||
<div v-if="item.task">
|
||||
<div>
|
||||
<a-tag color="blue">总数:{{ item.task?.total }}</a-tag>
|
||||
<a-tag color="success" class="ml-2">成功:{{ item.task?.successCount }}</a-tag>
|
||||
<a-tag type="info" class="ml-2">跳过:{{ item.task?.skipCount }}</a-tag>
|
||||
<a-tag color="blue">{{ t("certd.domain.total") }}:{{ item.task?.total }}</a-tag>
|
||||
<a-tag color="success" class="ml-2">{{ t("certd.success") }}:{{ item.task?.successCount }}</a-tag>
|
||||
<a-tag type="info" class="ml-2">{{ t("certd.domain.skipped") }}:{{ item.task?.skipCount }}</a-tag>
|
||||
<a-tooltip v-if="item.task?.errors.length > 0">
|
||||
<template #title>
|
||||
<div v-for="error in item.task?.errors" :key="error">{{ error }}</div>
|
||||
</template>
|
||||
<a-tag color="red" class="ml-2">失败:{{ item.task?.errors.length }}</a-tag>
|
||||
<a-tag color="red" class="ml-2">{{ t("certd.domain.failed") }}:{{ item.task?.errors.length }}</a-tag>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<a-progress :percent="item.task?.progress" size="small" status="active" />
|
||||
</div>
|
||||
<div v-else>未执行</div>
|
||||
<div v-else>{{ t("certd.domain.notExecuted") }}</div>
|
||||
</td>
|
||||
<td>
|
||||
<fs-button type="primary" icon="ion:play-outline" :disabled="item.task?.status === 'running'" @click="startTask(item)">执行</fs-button>
|
||||
<fs-button type="primary" class="ml-2" danger icon="ion:trash-outline" @click="deleteTask(item)">删除</fs-button>
|
||||
<fs-button type="primary" icon="ion:play-outline" :disabled="item.task?.status === 'running'" @click="startTask(item)">{{ t("certd.domain.execute") }}</fs-button>
|
||||
<fs-button type="primary" class="ml-2" danger icon="ion:trash-outline" @click="deleteTask(item)">{{ t("certd.domain.delete") }}</fs-button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -58,11 +58,13 @@ import { onMounted, onUnmounted, ref } from "vue";
|
||||
import * as api from "./api";
|
||||
import { useDomainImport } from "./use";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { useI18n } from "/@/locales";
|
||||
defineOptions({
|
||||
name: "DomainImportTaskStatus",
|
||||
});
|
||||
|
||||
const list = ref([]);
|
||||
const { t } = useI18n();
|
||||
|
||||
async function loadImportTaskStatus() {
|
||||
const res = await api.ImportTaskStatus();
|
||||
@@ -77,8 +79,8 @@ async function startTask(item: any) {
|
||||
|
||||
async function deleteTask(item: any) {
|
||||
Modal.confirm({
|
||||
title: "确认删除吗?",
|
||||
okText: "确认",
|
||||
title: t("certd.domain.confirmDelete"),
|
||||
okText: t("common.confirm"),
|
||||
okType: "danger",
|
||||
onOk: async () => {
|
||||
await api.ImportTaskDelete(item.key);
|
||||
|
||||
@@ -5,12 +5,14 @@ import { compute } from "@fast-crud/fast-crud";
|
||||
import { Dicts } from "/@/components/plugins/lib/dicts";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import DomainImportTaskStatus from "./import.vue";
|
||||
import { useI18n } from "/@/locales";
|
||||
export function useDomainImport() {
|
||||
const { openFormDialog } = useFormDialog();
|
||||
const { t } = useI18n();
|
||||
|
||||
const columns = {
|
||||
dnsProviderType: {
|
||||
title: "域名提供商",
|
||||
title: t("certd.domain.domainProvider"),
|
||||
type: "text",
|
||||
form: {
|
||||
component: {
|
||||
@@ -29,14 +31,14 @@ export function useDomainImport() {
|
||||
},
|
||||
},
|
||||
dnsProviderAccessType: {
|
||||
title: "域名提供商访问类型",
|
||||
title: t("certd.domain.domainProviderAccessType"),
|
||||
type: "text",
|
||||
form: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
dnsProviderAccessId: {
|
||||
title: "域名提供商授权",
|
||||
title: t("certd.domain.domainProviderAccess"),
|
||||
type: "text",
|
||||
form: {
|
||||
component: {
|
||||
@@ -52,7 +54,7 @@ export function useDomainImport() {
|
||||
|
||||
return function openDomainImportDialog(req: { afterSubmit?: (res?: any) => void; form?: any }) {
|
||||
openFormDialog({
|
||||
title: "从域名提供商导入域名",
|
||||
title: t("certd.domain.importFromProvider"),
|
||||
columns: columns,
|
||||
initialForm: {
|
||||
...req.form,
|
||||
@@ -73,10 +75,11 @@ export function useDomainImport() {
|
||||
|
||||
export function useDomainImportManage() {
|
||||
const { openFormDialog } = useFormDialog();
|
||||
const { t } = useI18n();
|
||||
const settingStore = useSettingStore();
|
||||
return async function openDomainImportManageDialog(req: { afterSubmit?: (res?: any) => void; form?: any; zIndex?: number }) {
|
||||
await openFormDialog({
|
||||
title: "从域名提供商导入域名",
|
||||
title: t("certd.domain.importFromProvider"),
|
||||
body: () => {
|
||||
return <DomainImportTaskStatus />;
|
||||
},
|
||||
|
||||
@@ -79,9 +79,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
},
|
||||
import: {
|
||||
show: hasActionPermission("write"),
|
||||
title: "导入CNAME记录",
|
||||
title: t("certd.cname.importRecords"),
|
||||
type: "primary",
|
||||
text: "批量导入",
|
||||
text: t("certd.cname.batchImport"),
|
||||
icon: "mingcute:vip-1-line",
|
||||
click: () => {
|
||||
settingStore.checkPlus();
|
||||
@@ -95,9 +95,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
},
|
||||
},
|
||||
export: {
|
||||
title: "导出CNAME记录之后,可用于批量导入cname解析到域名注册商",
|
||||
title: t("certd.cname.exportRecordsTip"),
|
||||
type: "primary",
|
||||
text: "批量导出",
|
||||
text: t("certd.cname.batchExport"),
|
||||
icon: "mingcute:vip-1-line",
|
||||
click: () => {
|
||||
settingStore.checkPlus();
|
||||
@@ -235,8 +235,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
cellRender({ value, row }) {
|
||||
async function resetStatus() {
|
||||
Modal.confirm({
|
||||
title: "重置状态",
|
||||
content: "确定要重置校验状态吗?",
|
||||
title: t("certd.cname.resetStatus"),
|
||||
content: t("certd.cname.confirmResetStatus"),
|
||||
onOk: async () => {
|
||||
await api.ResetStatus(row.id);
|
||||
await crudExpose.doRefresh();
|
||||
@@ -253,7 +253,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
)}
|
||||
|
||||
{row.status === "valid" && (
|
||||
<a-tooltip title={"重置校验状态,重新校验"}>
|
||||
<a-tooltip title={t("certd.cname.resetStatusTooltip")}>
|
||||
<fs-icon class={"ml-5 pointer "} icon="solar:undo-left-square-bold" onClick={resetStatus}></fs-icon>
|
||||
</a-tooltip>
|
||||
)}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { dict } from "@fast-crud/fast-crud";
|
||||
import { message } from "ant-design-vue";
|
||||
import * as api from "./api";
|
||||
import { useFormDialog } from "/@/use/use-dialog";
|
||||
import { useI18n } from "/@/locales";
|
||||
|
||||
export const cnameProviderDict = dict({
|
||||
url: "/cname/provider/list",
|
||||
@@ -10,10 +11,11 @@ export const cnameProviderDict = dict({
|
||||
});
|
||||
export function useCnameImport() {
|
||||
const { openFormDialog } = useFormDialog();
|
||||
const { t } = useI18n();
|
||||
|
||||
const columns = {
|
||||
domainList: {
|
||||
title: "域名列表",
|
||||
title: t("certd.cname.domainList"),
|
||||
type: "text",
|
||||
form: {
|
||||
component: {
|
||||
@@ -24,11 +26,11 @@ export function useCnameImport() {
|
||||
span: 24,
|
||||
},
|
||||
required: true,
|
||||
helper: "每个域名一行,批量导入\n泛域名请去掉*.\n已经存在的会自动跳过",
|
||||
helper: t("certd.cname.domainListHelper"),
|
||||
},
|
||||
},
|
||||
cnameProviderId: {
|
||||
title: "CNAME服务",
|
||||
title: t("certd.cname.cnameService"),
|
||||
type: "dict-select",
|
||||
dict: cnameProviderDict,
|
||||
form: {
|
||||
@@ -39,14 +41,14 @@ export function useCnameImport() {
|
||||
|
||||
return function openCnameImportDialog(req: { afterSubmit?: () => void }) {
|
||||
openFormDialog({
|
||||
title: "导入CNAME记录",
|
||||
title: t("certd.cname.importRecords"),
|
||||
columns: columns,
|
||||
onSubmit: async (form: any) => {
|
||||
await api.Import({
|
||||
domainList: form.domainList,
|
||||
cnameProviderId: form.cnameProviderId,
|
||||
});
|
||||
message.success("导入任务已提交");
|
||||
message.success(t("certd.cname.importTaskSubmitted"));
|
||||
if (req.afterSubmit) {
|
||||
req.afterSubmit();
|
||||
}
|
||||
|
||||
@@ -69,17 +69,17 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
const handleBatchDelete = () => {
|
||||
if (selectedRowKeys.value?.length > 0) {
|
||||
Modal.confirm({
|
||||
title: "确认",
|
||||
content: `确定要批量删除这${selectedRowKeys.value.length}条记录吗`,
|
||||
title: t("monitor.confirmTitle"),
|
||||
content: t("monitor.batchDeleteConfirm", { count: selectedRowKeys.value.length }),
|
||||
async onOk() {
|
||||
await api.BatchDelObj(selectedRowKeys.value);
|
||||
message.info("删除成功");
|
||||
message.info(t("monitor.deleteSuccess"));
|
||||
crudExpose.doRefresh();
|
||||
selectedRowKeys.value = [];
|
||||
},
|
||||
});
|
||||
} else {
|
||||
message.error("请先勾选记录");
|
||||
message.error(t("monitor.selectRecordsFirst"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -265,7 +265,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
type: "link",
|
||||
text: null,
|
||||
tooltip: {
|
||||
title: "立即检查",
|
||||
title: t("monitor.checkNow"),
|
||||
},
|
||||
icon: "ion:play-sharp",
|
||||
click: async ({ row }) => {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||
<template #pagination-left>
|
||||
<a-tooltip title="批量删除">
|
||||
<a-tooltip :title="t('monitor.batchDelete')">
|
||||
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
|
||||
@@ -2,14 +2,16 @@ import { useFormWrapper } from "@fast-crud/fast-crud";
|
||||
|
||||
import SiteIpCertMonitor from "./index.vue";
|
||||
import { siteIpApi } from "/@/views/certd/monitor/site/ip/api";
|
||||
import { useI18n } from "/@/locales";
|
||||
|
||||
export function useSiteIpMonitor() {
|
||||
const { openDialog, openCrudFormDialog } = useFormWrapper();
|
||||
const { t } = useI18n();
|
||||
|
||||
async function openSiteIpMonitorDialog(opts: { siteId: number }) {
|
||||
await openDialog({
|
||||
wrapper: {
|
||||
title: "站点IP监控",
|
||||
title: t("monitor.siteIpMonitor"),
|
||||
width: "80%",
|
||||
is: "a-modal",
|
||||
footer: false,
|
||||
@@ -40,10 +42,10 @@ export function useSiteIpMonitor() {
|
||||
columns: {
|
||||
text: {
|
||||
type: "textarea",
|
||||
title: "IP列表",
|
||||
title: t("monitor.ipList"),
|
||||
form: {
|
||||
helper: "IP或者CNAME域名,一行一个",
|
||||
rules: [{ required: true, message: "请输入要导入的IP或域名" }],
|
||||
helper: t("monitor.ipListHelper"),
|
||||
rules: [{ required: true, message: t("monitor.enterImportIpOrDomain") }],
|
||||
component: {
|
||||
placeholder: "192.168.1.2\ncname.foo.com",
|
||||
rows: 8,
|
||||
|
||||
Reference in New Issue
Block a user