mirror of
https://github.com/certd/certd.git
synced 2026-04-28 07:57:25 +08:00
perf: 证书流水线创建域名输入框支持获取域名数据进行选择
This commit is contained in:
+1
@@ -39,6 +39,7 @@ import { dict } from "@fast-crud/fast-crud";
|
|||||||
import * as api from "./api.js";
|
import * as api from "./api.js";
|
||||||
import CnameTip from "./cname-tip.vue";
|
import CnameTip from "./cname-tip.vue";
|
||||||
import { Modal } from "ant-design-vue";
|
import { Modal } from "ant-design-vue";
|
||||||
|
import { utils } from "/@/utils/index.js";
|
||||||
const statusDict = dict({
|
const statusDict = dict({
|
||||||
data: [
|
data: [
|
||||||
{ label: "待设置CNAME", value: "cname", color: "warning" },
|
{ label: "待设置CNAME", value: "cname", color: "warning" },
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
<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)">
|
||||||
|
<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>
|
||||||
|
<div v-if="hasError" class="helper p-2" :class="{ error: hasError }">
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
<a-divider style="margin: 4px 0" />
|
||||||
|
</template>
|
||||||
|
<v-nodes :vnodes="menuNode" />
|
||||||
|
|
||||||
|
<div v-if="pager === true" class="pager text-center p-5" @click="paginationClick">
|
||||||
|
<a-pagination v-model:current="pagerRef.pageNo" simple :total="pagerRef.total" :page-size="pagerRef.pageSize" @change="onPageChange" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-select>
|
||||||
|
<div class="ml-5">
|
||||||
|
<fs-button :loading="loading" title="刷新我的域名列表" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="helper" :class="{ error: hasError }">
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, defineComponent, ref, Ref, useAttrs } from "vue";
|
||||||
|
import { request } from "/@/api/service";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "DomainSelector",
|
||||||
|
});
|
||||||
|
|
||||||
|
const VNodes = defineComponent({
|
||||||
|
props: {
|
||||||
|
vnodes: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return this.vnodes;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
search?: boolean;
|
||||||
|
pager?: boolean;
|
||||||
|
value?: any[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
"update:value": any;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const attrs = useAttrs();
|
||||||
|
|
||||||
|
const searchKeyRef = ref("");
|
||||||
|
const optionsRef = ref([]);
|
||||||
|
const message = ref("");
|
||||||
|
const hasError = ref(false);
|
||||||
|
const loading = ref(false);
|
||||||
|
const pagerRef: Ref = ref({
|
||||||
|
pageNo: 1,
|
||||||
|
total: 0,
|
||||||
|
pageSize: 20,
|
||||||
|
});
|
||||||
|
const getOptions = async () => {
|
||||||
|
if (loading.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.value = "";
|
||||||
|
hasError.value = false;
|
||||||
|
loading.value = true;
|
||||||
|
const pageNo = pagerRef.value.pageNo;
|
||||||
|
const pageSize = pagerRef.value.pageSize;
|
||||||
|
try {
|
||||||
|
const res = await request({
|
||||||
|
url: "/cert/domain/page",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
query: {
|
||||||
|
domain: props.search ? searchKeyRef.value : undefined,
|
||||||
|
},
|
||||||
|
page: {
|
||||||
|
offset: (pageNo - 1) * pageSize,
|
||||||
|
limit: pageSize,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const list = res?.records || res || [];
|
||||||
|
|
||||||
|
const options = [];
|
||||||
|
for (let item of list) {
|
||||||
|
options.push({
|
||||||
|
value: item.domain,
|
||||||
|
label: item.domain,
|
||||||
|
});
|
||||||
|
options.push({
|
||||||
|
value: `*.${item.domain}`,
|
||||||
|
label: `*.${item.domain}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
optionsRef.value = options;
|
||||||
|
pagerRef.value.total = list.length;
|
||||||
|
if (props.pager) {
|
||||||
|
if (res.total != null) {
|
||||||
|
pagerRef.value.total = res.total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const filterOption = (input: string, option: any) => {
|
||||||
|
return option.label.toLowerCase().includes(input.toLowerCase()) || String(option.value).toLowerCase().includes(input.toLowerCase());
|
||||||
|
};
|
||||||
|
|
||||||
|
async function onClick() {
|
||||||
|
if (optionsRef.value?.length === 0) {
|
||||||
|
await refreshOptions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshOptions() {
|
||||||
|
await getOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doSearch() {
|
||||||
|
pagerRef.value.pageNo = 1;
|
||||||
|
await refreshOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onPageChange(current: any) {
|
||||||
|
await refreshOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function paginationClick(e: any) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less"></style>
|
||||||
@@ -85,7 +85,9 @@ const message = ref("");
|
|||||||
const hasError = ref(false);
|
const hasError = ref(false);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const pagerRef: Ref = ref({
|
const pagerRef: Ref = ref({
|
||||||
current: 1,
|
pageNo: 1,
|
||||||
|
total: 0,
|
||||||
|
pageSize: 100,
|
||||||
});
|
});
|
||||||
const getOptions = async () => {
|
const getOptions = async () => {
|
||||||
if (loading.value) {
|
if (loading.value) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import RemoteSelect from "./common/remote-select.vue";
|
|||||||
import RemoteInput from "./common/remote-input.vue";
|
import RemoteInput from "./common/remote-input.vue";
|
||||||
import RemoteTreeSelect from "./common/remote-tree-select.vue";
|
import RemoteTreeSelect from "./common/remote-tree-select.vue";
|
||||||
import CertDomainsGetter from "./common/cert-domains-getter.vue";
|
import CertDomainsGetter from "./common/cert-domains-getter.vue";
|
||||||
|
import DomainSelector from "./common/domain-selector.vue";
|
||||||
import OutputSelector from "/@/components/plugins/common/output-selector/index.vue";
|
import OutputSelector from "/@/components/plugins/common/output-selector/index.vue";
|
||||||
import DnsProviderSelector from "/@/components/plugins/cert/dns-provider-selector/index.vue";
|
import DnsProviderSelector from "/@/components/plugins/cert/dns-provider-selector/index.vue";
|
||||||
import DomainsVerifyPlanEditor from "/@/components/plugins/cert/domains-verify-plan-editor/index.vue";
|
import DomainsVerifyPlanEditor from "/@/components/plugins/cert/domains-verify-plan-editor/index.vue";
|
||||||
@@ -29,6 +30,7 @@ export default {
|
|||||||
app.component("RemoteTreeSelect", RemoteTreeSelect);
|
app.component("RemoteTreeSelect", RemoteTreeSelect);
|
||||||
app.component("RemoteInput", RemoteInput);
|
app.component("RemoteInput", RemoteInput);
|
||||||
app.component("CertDomainsGetter", CertDomainsGetter);
|
app.component("CertDomainsGetter", CertDomainsGetter);
|
||||||
|
app.component("DomainSelector", DomainSelector);
|
||||||
app.component("InputPassword", InputPassword);
|
app.component("InputPassword", InputPassword);
|
||||||
app.component("ParamsShow", ParamsShow);
|
app.component("ParamsShow", ParamsShow);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="tsx" setup>
|
<script lang="tsx" setup>
|
||||||
import { defineProps, inject, ref, useAttrs } from "vue";
|
import { inject, ref, useAttrs } from "vue";
|
||||||
import { Modal } from "ant-design-vue";
|
import { Modal } from "ant-design-vue";
|
||||||
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
|
||||||
|
|
||||||
|
|||||||
@@ -12,16 +12,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="tsx" setup>
|
<script lang="tsx" setup>
|
||||||
import { computed, onMounted, reactive, ref } from "vue";
|
|
||||||
import dayjs from "dayjs";
|
|
||||||
import { message, Modal } from "ant-design-vue";
|
import { message, Modal } from "ant-design-vue";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { computed, onMounted, reactive, ref } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
import * as api from "./api";
|
import * as api from "./api";
|
||||||
import { useSettingStore } from "/@/store/settings";
|
import { useSettingStore } from "/@/store/settings";
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import { useUserStore } from "/@/store/user";
|
import { useUserStore } from "/@/store/user";
|
||||||
import { mitter } from "/@/utils/util.mitt";
|
|
||||||
import { useI18n } from "vue-i18n";
|
|
||||||
import { env } from "/@/utils/util.env";
|
import { env } from "/@/utils/util.env";
|
||||||
|
import { mitter } from "/@/utils/util.mitt";
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const settingStore = useSettingStore();
|
const settingStore = useSettingStore();
|
||||||
|
|||||||
@@ -9,12 +9,14 @@ export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin {
|
|||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: "证书域名",
|
title: "证书域名",
|
||||||
component: {
|
component: {
|
||||||
name: "a-select",
|
name: "domain-selector",
|
||||||
vModel: "value",
|
vModel: "value",
|
||||||
mode: "tags",
|
mode: "tags",
|
||||||
open: false,
|
// open: false,
|
||||||
placeholder: "foo.com / *.foo.com / *.bar.com",
|
placeholder: "foo.com / *.foo.com / *.sub.foo.com / *.bar.com",
|
||||||
tokenSeparators: [",", " ", ",", "、", "|"],
|
tokenSeparators: [",", " ", ",", "、", "|"],
|
||||||
|
search: true,
|
||||||
|
pager:true,
|
||||||
},
|
},
|
||||||
rules: [{ type: "domains" }],
|
rules: [{ type: "domains" }],
|
||||||
required: true,
|
required: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user