mirror of
https://github.com/certd/certd.git
synced 2026-05-15 04:27:31 +08:00
perf(domain): 添加域名过期时间同步进度显示功能
添加同步进度对话框,展示同步任务的实时进度和状态 更新中英文翻译文件,添加相关文案 修改AGENTS.md文档中的格式化命令说明
This commit is contained in:
@@ -20,6 +20,7 @@ export default {
|
||||
importFromProvider: "Import from Domain Provider",
|
||||
syncExpirationDate: "Sync Domain Expiration Time",
|
||||
syncTaskSubmitted: "Sync task submitted",
|
||||
syncExpirationProgress: "Sync Domain Expiration Progress",
|
||||
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",
|
||||
@@ -28,6 +29,9 @@ export default {
|
||||
progress: "Progress",
|
||||
operation: "Operation",
|
||||
total: "Total",
|
||||
current: "Current",
|
||||
running: "Running",
|
||||
done: "Done",
|
||||
skipped: "Skipped",
|
||||
failed: "Failed",
|
||||
notExecuted: "Not executed",
|
||||
|
||||
@@ -20,6 +20,7 @@ export default {
|
||||
importFromProvider: "从域名提供商导入",
|
||||
syncExpirationDate: "同步域名过期时间",
|
||||
syncTaskSubmitted: "同步任务已提交",
|
||||
syncExpirationProgress: "同步域名过期时间进度",
|
||||
expirationMonitorSetting: "域名过期监控设置",
|
||||
subdomainDnsHelper: "注意:DNS校验方式下,子域名不需要在此处维护,否则会影响证书申请(子域名托管或免费二级域名除外)",
|
||||
path: "路径",
|
||||
@@ -28,6 +29,9 @@ export default {
|
||||
progress: "进度",
|
||||
operation: "操作",
|
||||
total: "总数",
|
||||
current: "当前",
|
||||
running: "运行中",
|
||||
done: "已完成",
|
||||
skipped: "跳过",
|
||||
failed: "失败",
|
||||
notExecuted: "未执行",
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Modal, notification } from "ant-design-vue";
|
||||
import { Ref, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import * as api from "./api";
|
||||
import { useDomainImportManage } from "./use";
|
||||
import { useDomainImportManage, useSyncExpirationProcess } from "./use";
|
||||
import { Dicts } from "/@/components/plugins/lib/dicts";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { useUserStore } from "/@/store/user";
|
||||
@@ -52,6 +52,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
});
|
||||
|
||||
const openDomainImportManageDialog = useDomainImportManage();
|
||||
const openSyncExpirationProcessDialog = useSyncExpirationProcess({ crudExpose });
|
||||
|
||||
const subdomainConfirmed = ref(false);
|
||||
return {
|
||||
@@ -140,13 +141,11 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
icon: "ion:refresh-outline",
|
||||
text: t("certd.domain.syncExpirationDate"),
|
||||
click: async () => {
|
||||
await api.SyncExpirationStart();
|
||||
notification.success({
|
||||
message: t("certd.domain.syncTaskSubmitted"),
|
||||
});
|
||||
setTimeout(() => {
|
||||
crudExpose.doRefresh();
|
||||
}, 2000);
|
||||
try {
|
||||
await api.SyncExpirationStart();
|
||||
} finally {
|
||||
await openSyncExpirationProcessDialog();
|
||||
}
|
||||
},
|
||||
},
|
||||
monitorSettingSave: {
|
||||
@@ -361,7 +360,9 @@ 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"}>{t("certd.domain.path")}: {row.httpUploadRootDir}</a-tag>
|
||||
<a-tag class={"ml-5 flex items-center"}>
|
||||
{t("certd.domain.path")}: {row.httpUploadRootDir}
|
||||
</a-tag>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { message } from "ant-design-vue";
|
||||
import * as api from "./api";
|
||||
import { useFormDialog } from "/@/use/use-dialog";
|
||||
import { compute } from "@fast-crud/fast-crud";
|
||||
import { Dicts } from "/@/components/plugins/lib/dicts";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { Ref, ref } from "vue";
|
||||
import * as api from "./api";
|
||||
import DomainImportTaskStatus from "./import.vue";
|
||||
import { useI18n } from "/@/locales";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { useFormDialog } from "/@/use/use-dialog";
|
||||
export function useDomainImport() {
|
||||
const { openFormDialog } = useFormDialog();
|
||||
const { t } = useI18n();
|
||||
@@ -92,3 +91,92 @@ export function useDomainImportManage() {
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function useSyncExpirationProcess(opts: { crudExpose: any }) {
|
||||
const { openFormDialog } = useFormDialog();
|
||||
const { t } = useI18n();
|
||||
|
||||
return async function openSyncExpirationProcessDialog() {
|
||||
const taskStatus: Ref<any> = ref({});
|
||||
const errors: Ref<string[]> = ref([]);
|
||||
const timerRef: Ref<any> = ref(null);
|
||||
|
||||
function stop() {
|
||||
if (timerRef.value) {
|
||||
clearTimeout(timerRef.value);
|
||||
timerRef.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadStatus() {
|
||||
const status = await api.SyncExpirationStatus();
|
||||
taskStatus.value = status || {};
|
||||
errors.value = taskStatus.value.errors || [];
|
||||
|
||||
if (taskStatus.value.status === "running") {
|
||||
stop();
|
||||
timerRef.value = setTimeout(async () => {
|
||||
await loadStatus();
|
||||
}, 3000);
|
||||
} else {
|
||||
stop();
|
||||
await opts.crudExpose.doRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
await loadStatus();
|
||||
|
||||
await openFormDialog({
|
||||
title: t("certd.domain.syncExpirationProgress"),
|
||||
body: () => {
|
||||
const progress = Math.min(Math.round(taskStatus.value.progress || 0), 100);
|
||||
const isRunning = taskStatus.value.status === "running";
|
||||
const errorList = errors.value.map(item => {
|
||||
return <div>{item}</div>;
|
||||
});
|
||||
return (
|
||||
<div class={"w-full"}>
|
||||
<div class={"mt-4 flex flex-wrap gap-2"}>
|
||||
<a-tag color={isRunning ? "processing" : "success"}>{isRunning ? t("certd.domain.running") : t("certd.domain.done")}</a-tag>
|
||||
|
||||
<a-tag class={"m-0"} color={"blue"}>
|
||||
{t("certd.domain.total")}:{taskStatus.value.total || 0}
|
||||
</a-tag>
|
||||
<a-tag class={"m-0"} color={"green"}>
|
||||
{t("certd.success")}:{taskStatus.value.successCount || 0}
|
||||
</a-tag>
|
||||
<a-tag class={"m-0"} color={"red"}>
|
||||
{t("certd.domain.failed")}:{taskStatus.value.errorCount || 0}
|
||||
</a-tag>
|
||||
<a-tag class={"m-0"} color={"cyan"}>
|
||||
{t("certd.domain.current")}:{taskStatus.value.current || 0}
|
||||
</a-tag>
|
||||
</div>
|
||||
<div class={"mt-4 pr-4"}>
|
||||
<a-progress percent={progress} status={errors.value.length > 0 ? "exception" : isRunning ? "active" : "success"} />
|
||||
</div>
|
||||
{errors.value.length > 0 && <div class={"mt-2 break-words text-red-500 mb-4"}>{errorList}</div>}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
wrapper: {
|
||||
width: 600,
|
||||
footer: false,
|
||||
buttons: {
|
||||
cancel: {
|
||||
show: false,
|
||||
},
|
||||
reset: {
|
||||
show: false,
|
||||
},
|
||||
ok: {
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
onClosed() {
|
||||
stop();
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user