mirror of
https://github.com/certd/certd.git
synced 2026-04-14 12:30:54 +08:00
perf: 输入证书域名时,支持点击导入域名
This commit is contained in:
@@ -1,24 +1,35 @@
|
||||
<template>
|
||||
<div class="domain-select">
|
||||
<div class="flex flex-row">
|
||||
<a-select class="domain-select-input" show-search :filter-option="filterOption" :options="optionsRef" :value="value" v-bind="attrs" @click="onClick" @update:value="emit('update:value', $event)">
|
||||
<a-select
|
||||
class="domain-select-input"
|
||||
:dropdown-style="dropdownStyle"
|
||||
show-search
|
||||
:filter-option="filterOption"
|
||||
:options="optionsRef"
|
||||
:value="value"
|
||||
v-bind="attrs"
|
||||
@click="onClick"
|
||||
@update:value="emit('update:value', $event)"
|
||||
>
|
||||
<template #dropdownRender="{ menuNode }">
|
||||
<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-button class="ml-2" :loading="loading" type="text" @click="doSearch">
|
||||
<template #icon>
|
||||
<search-outlined />
|
||||
</template>
|
||||
查询
|
||||
</a-button>
|
||||
<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>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="hasError" class="helper p-2" :class="{ error: hasError }">
|
||||
{{ message }}
|
||||
@@ -31,6 +42,15 @@
|
||||
<a-pagination v-model:current="pagerRef.pageNo" simple :total="pagerRef.total" :page-size="pagerRef.pageSize" @change="onPageChange" />
|
||||
</div>
|
||||
</template>
|
||||
<template #option="scope">
|
||||
<div class="flex flex-row items-center">
|
||||
<span class="min-w-60">{{ scope.label }}</span>
|
||||
<div>
|
||||
<fs-values-format :model-value="scope.challengeType" :dict="challengeTypeDict"></fs-values-format>
|
||||
<fs-values-format :model-value="scope.dnsProviderType" :dict="dnsProviderTypeDict"></fs-values-format>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-select>
|
||||
<div class="ml-5">
|
||||
<fs-button :loading="loading" title="刷新我的域名列表" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||
@@ -44,6 +64,9 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, defineComponent, ref, Ref, useAttrs } from "vue";
|
||||
import { request } from "/@/api/service";
|
||||
import { Dicts } from "../lib/dicts";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useDomainImport, useDomainImportManage } from "/@/views/certd/cert/domain/use";
|
||||
|
||||
defineOptions({
|
||||
name: "DomainSelector",
|
||||
@@ -114,10 +137,14 @@ const getOptions = async () => {
|
||||
options.push({
|
||||
value: item.domain,
|
||||
label: item.domain,
|
||||
dnsProviderType: item.dnsProviderType,
|
||||
challengeType: item.challengeType,
|
||||
});
|
||||
options.push({
|
||||
value: `*.${item.domain}`,
|
||||
label: `*.${item.domain}`,
|
||||
dnsProviderType: item.dnsProviderType,
|
||||
challengeType: item.challengeType,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -162,6 +189,29 @@ async function paginationClick(e: any) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
const dnsProviderTypeDict = Dicts.dnsProviderTypeDict;
|
||||
const challengeTypeDict = Dicts.challengeTypeDict;
|
||||
|
||||
const router = useRouter();
|
||||
function openDomainManager(e: any) {
|
||||
e.preventDefault();
|
||||
// router.push("/certd/cert/domain");
|
||||
window.open(`${window.location.origin}/#/certd/cert/domain`);
|
||||
}
|
||||
|
||||
const openDomainImportManageDialog = useDomainImportManage();
|
||||
function openDomainImportDialog() {
|
||||
openDomainImportManageDialog({
|
||||
zIndex: 2060,
|
||||
afterSubmit: res => {
|
||||
refreshOptions();
|
||||
},
|
||||
});
|
||||
}
|
||||
const dropdownStyle = ref({
|
||||
zIndex: 2000,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less"></style>
|
||||
|
||||
@@ -6,6 +6,7 @@ export type FormOptionReq = {
|
||||
onSubmit?: any;
|
||||
body?: any;
|
||||
initialForm?: any;
|
||||
zIndex?: number;
|
||||
};
|
||||
|
||||
export function useFormDialog() {
|
||||
@@ -19,6 +20,7 @@ export function useFormDialog() {
|
||||
form: {
|
||||
initialForm: req.initialForm,
|
||||
wrapper: {
|
||||
zIndex: req.zIndex,
|
||||
title: req.title,
|
||||
saveRemind: false,
|
||||
slots: {
|
||||
|
||||
@@ -3,11 +3,10 @@ import { Modal, notification } from "ant-design-vue";
|
||||
import { Ref, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import * as api from "./api";
|
||||
import DomainImportTaskStatus from "./import.vue";
|
||||
import { useDomainImportManage } from "./use";
|
||||
import { Dicts } from "/@/components/plugins/lib/dicts";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import { useUserStore } from "/@/store/user";
|
||||
import { useFormDialog } from "/@/use/use-dialog";
|
||||
import { createAccessApi } from "/@/views/certd/access/api";
|
||||
import { useI18n } from "/src/locales";
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
@@ -51,7 +50,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
url: "pi/dnsProvider/dnsProviderTypeDict",
|
||||
});
|
||||
|
||||
const { openFormDialog } = useFormDialog();
|
||||
const openDomainImportManageDialog = useDomainImportManage();
|
||||
return {
|
||||
crudOptions: {
|
||||
settings: {
|
||||
@@ -104,13 +103,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
color: "gold",
|
||||
icon: "mingcute:vip-1-line",
|
||||
click: async () => {
|
||||
settingStore.checkPlus();
|
||||
await openFormDialog({
|
||||
title: "从域名提供商导入域名",
|
||||
body: () => {
|
||||
return <DomainImportTaskStatus />;
|
||||
},
|
||||
onSubmit: async (form: any) => {
|
||||
await openDomainImportManageDialog({
|
||||
afterSubmit: res => {
|
||||
crudExpose.doRefresh();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<div v-else>未执行</div>
|
||||
</td>
|
||||
<td>
|
||||
<fs-button type="primary" icon="ion:play-outline" @click="startTask(item)">执行</fs-button>
|
||||
<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>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -53,7 +53,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from "vue";
|
||||
import { onMounted, onUnmounted, ref } from "vue";
|
||||
import * as api from "./api";
|
||||
import { Modal } from "ant-design-vue";
|
||||
import { useDomainImport } from "./use";
|
||||
@@ -90,7 +90,10 @@ const openDomainImportDialog = useDomainImport();
|
||||
|
||||
async function addTask() {
|
||||
await openDomainImportDialog({
|
||||
afterSubmit: async () => {
|
||||
afterSubmit: async (res?: any) => {
|
||||
if (res) {
|
||||
await api.ImportTaskStart(res.key);
|
||||
}
|
||||
await loadImportTaskStatus();
|
||||
},
|
||||
});
|
||||
@@ -105,8 +108,16 @@ async function editTask(item: any) {
|
||||
});
|
||||
}
|
||||
|
||||
const checkIntervalRef = ref();
|
||||
onMounted(async () => {
|
||||
await loadImportTaskStatus();
|
||||
checkIntervalRef.value = setInterval(async () => {
|
||||
await loadImportTaskStatus();
|
||||
}, 3000);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(checkIntervalRef.value);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ 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 DomainImportTaskStatus from "./import.vue";
|
||||
export function useDomainImport() {
|
||||
const { openFormDialog } = useFormDialog();
|
||||
|
||||
@@ -49,7 +50,7 @@ export function useDomainImport() {
|
||||
},
|
||||
};
|
||||
|
||||
return function openDomainImportDialog(req: { afterSubmit?: () => void; form?: any }) {
|
||||
return function openDomainImportDialog(req: { afterSubmit?: (res?: any) => void; form?: any }) {
|
||||
openFormDialog({
|
||||
title: "从域名提供商导入域名",
|
||||
columns: columns,
|
||||
@@ -57,13 +58,33 @@ export function useDomainImport() {
|
||||
...req.form,
|
||||
},
|
||||
onSubmit: async (form: any) => {
|
||||
await api.ImportTaskSave({
|
||||
const res = await api.ImportTaskSave({
|
||||
key: form.key,
|
||||
dnsProviderType: form.dnsProviderType,
|
||||
dnsProviderAccessId: form.dnsProviderAccessId,
|
||||
});
|
||||
if (req.afterSubmit) {
|
||||
req.afterSubmit();
|
||||
req.afterSubmit(res);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function useDomainImportManage() {
|
||||
const { openFormDialog } = useFormDialog();
|
||||
const settingStore = useSettingStore();
|
||||
return async function openDomainImportManageDialog(req: { afterSubmit?: (res?: any) => void; form?: any; zIndex?: number }) {
|
||||
settingStore.checkPlus();
|
||||
await openFormDialog({
|
||||
title: "从域名提供商导入域名",
|
||||
body: () => {
|
||||
return <DomainImportTaskStatus />;
|
||||
},
|
||||
zIndex: req.zIndex,
|
||||
onSubmit: async (form: any) => {
|
||||
if (req.afterSubmit) {
|
||||
req.afterSubmit(form);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -261,7 +261,10 @@ export class DomainService extends BaseService<DomainEntity> {
|
||||
|
||||
const itemHandle = async (domainRecord: any) => {
|
||||
task.incrementCurrent()
|
||||
const domain = domainRecord.domain
|
||||
let domain = domainRecord.domain
|
||||
if (domain.endsWith(".")) {
|
||||
domain = domain.slice(0, -1)
|
||||
}
|
||||
|
||||
const old = await this.findOne({
|
||||
where: {
|
||||
@@ -410,7 +413,7 @@ export class DomainService extends BaseService<DomainEntity> {
|
||||
await this.deleteDomainImportTask({userId,key})
|
||||
}
|
||||
|
||||
await this.addDomainImportTask({userId,dnsProviderType,dnsProviderAccessId,index})
|
||||
return await this.addDomainImportTask({userId,dnsProviderType,dnsProviderAccessId,index})
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin {
|
||||
vModel: "value",
|
||||
mode: "tags",
|
||||
// open: false,
|
||||
placeholder: "foo.com / *.foo.com / *.sub.foo.com / *.bar.com",
|
||||
placeholder: "请输入证书域名,比如:foo.com / *.foo.com / *.sub.foo.com / *.bar.com",
|
||||
tokenSeparators: [",", " ", ",", "、", "|"],
|
||||
search: true,
|
||||
pager:true,
|
||||
|
||||
@@ -192,7 +192,7 @@ export class HuaweiDnsProvider extends AbstractDnsProvider {
|
||||
let list = ret.zones || []
|
||||
list = list.map((item: any) => ({
|
||||
id: item.id,
|
||||
domain: item.name,
|
||||
domain: item.name.endsWith(".") ? item.name.slice(0, -1) : item.name,
|
||||
}));
|
||||
return {
|
||||
total:ret.metadata.total_count || list.length,
|
||||
|
||||
Reference in New Issue
Block a user