🚩 增加Dns功能 优化性能
This commit is contained in:
parent
39f1774a2b
commit
fcacfb9a04
26
components/common/DnsList.vue
Normal file
26
components/common/DnsList.vue
Normal file
@ -0,0 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
const emit = defineEmits(['action'])
|
||||
|
||||
const handleClick = () => {
|
||||
const urlParam = 'dns' // 这里是你想传递给handleAction方法的参数
|
||||
emit('action', urlParam)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div title="Change Color">
|
||||
<div
|
||||
class="cursor-pointer flex h-10 w-10 items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-700"
|
||||
@click="handleClick"
|
||||
>
|
||||
<Icon name="eos-icons:dns" class=" text-lg dark:text-white" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -9,7 +9,7 @@ const isOpen = ref(false)
|
||||
<div>
|
||||
<div title="Change Color">
|
||||
<div
|
||||
class="flex h-10 w-10 items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-700"
|
||||
class="cursor-pointer flex h-10 w-10 items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-700"
|
||||
@click="isOpen = true"
|
||||
>
|
||||
<Icon name="mdi:about-circle-outline" class=" text-lg dark:text-white" />
|
||||
|
41
components/tab/list.vue
Normal file
41
components/tab/list.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
const timeStore = useTimeStore()
|
||||
const emit = defineEmits(['action'])
|
||||
|
||||
const handleActionFromDnsList = (urlParam:string) => {
|
||||
emit('action', urlParam)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ClientOnly>
|
||||
<div class="flex justify-between w-full">
|
||||
<div>
|
||||
<!-- 左边的新元素 -->
|
||||
<UTooltip text="支持列表" :popper="{ placement: 'top' }">
|
||||
<CommonDomainList />
|
||||
</UTooltip>
|
||||
|
||||
<UTooltip text="Dns查询" :popper="{ placement: 'top' }">
|
||||
<CommonDnsList @action="handleActionFromDnsList" />
|
||||
</UTooltip>
|
||||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<!-- 右边的现有元素 -->
|
||||
<UTooltip :text="timeStore.timeZones" :popper="{ placement: 'top' }">
|
||||
<CommonTimeZonesChange />
|
||||
</UTooltip>
|
||||
<UTooltip text="主题模式" :popper="{ placement: 'top' }">
|
||||
<CommonColorChange />
|
||||
</UTooltip>
|
||||
<UTooltip text="切换语言" :popper="{ placement: 'top' }">
|
||||
<CommonLanguageChange />
|
||||
</UTooltip>
|
||||
</div>
|
||||
</div>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -2,6 +2,7 @@ export default defineI18nLocale(async locale => {
|
||||
return {
|
||||
index: {
|
||||
tips: 'The information you submit for your query will not be recorded!',
|
||||
placeholder: 'Please enter a domain name',
|
||||
},
|
||||
error:{
|
||||
formatDomain: 'Error formatting domain name',
|
||||
|
@ -2,6 +2,7 @@ export default defineI18nLocale(async locale => {
|
||||
return {
|
||||
index: {
|
||||
tips: '您提交的查詢信息不會被記錄!',
|
||||
placeholder: '請輸入域名',
|
||||
},
|
||||
error:{
|
||||
formatDomain: '域名格式錯誤',
|
||||
|
@ -2,6 +2,7 @@ export default defineI18nLocale(async locale => {
|
||||
return {
|
||||
index: {
|
||||
tips: '您提交的查询信息不会被记录!',
|
||||
placeholder: '请输入域名',
|
||||
},
|
||||
error:{
|
||||
formatDomain: '域名格式错误',
|
||||
|
@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import {SupportedTLDs} from "~/utils/domain";
|
||||
import {useStyleStore} from "~/stores/style";
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@ -9,72 +10,94 @@ const state = reactive({
|
||||
|
||||
const toast = useToast();
|
||||
const router = useRouter();
|
||||
const handleAction = async (event: any) => {
|
||||
// 先拿到并处理域名
|
||||
const domain = state.domain.trim();
|
||||
|
||||
// 分割域名为各部分
|
||||
const parts = domain.split('.');
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
|
||||
// 需要一个更严格的检查来确认域名格式是否正确
|
||||
if (parts.length < 2) {
|
||||
toast.add({
|
||||
title: '域名格式不正确',
|
||||
});
|
||||
return;
|
||||
}
|
||||
const handleAction = async (url: any) => {
|
||||
if (!state.domain) return toast.add({ title: '请输入域名' })
|
||||
let domain = trimDomain(state.domain);
|
||||
const parts = splitDomain(domain);
|
||||
|
||||
// 获取最后两个部分作为可能的顶级域名(TLD)
|
||||
const potentialTLD = parts.slice(-2).join('.');
|
||||
if (!validateDomain(parts) || !isTLDValid(parts)) return;
|
||||
|
||||
// 判断后缀是否合法
|
||||
if (!SupportedTLDs.has(parts.slice(-1)[0]) && !SupportedTLDs.has(potentialTLD)) {
|
||||
toast.add({
|
||||
title: '域名后缀不合法',
|
||||
});
|
||||
return;
|
||||
}
|
||||
domain = updateDomainForTLD(parts);
|
||||
state.domain = domain;
|
||||
|
||||
// 确定是否是二级顶级域名
|
||||
let domainToKeep = domain;
|
||||
if (SupportedTLDs.has(potentialTLD)) {
|
||||
// 如果是二级顶级域名,保留最后三个部分
|
||||
domainToKeep = parts.length > 2 ? parts.slice(-3).join('.') : domain;
|
||||
} else {
|
||||
// 否则,只保留最后两个部分
|
||||
domainToKeep = parts.slice(-2).join('.');
|
||||
}
|
||||
|
||||
// 更新state.domain为只包含顶级域名的版本
|
||||
state.domain = domainToKeep;
|
||||
|
||||
// 跳转到结果页
|
||||
await router.push('/result/' + state.domain.replace(/\./g, '_') + '.html');
|
||||
await router.push(`/${url}/${state.domain.replace(/\./g, '_')}.html`);
|
||||
}
|
||||
|
||||
const timeStore = useTimeStore()
|
||||
|
||||
const trimDomain = (domain: string): string => {
|
||||
return domain.trim();
|
||||
}
|
||||
|
||||
const splitDomain = (domain: string): string[] => {
|
||||
return domain.split('.');
|
||||
}
|
||||
|
||||
|
||||
const validateDomain = (parts: string[]): boolean => {
|
||||
if (parts.length < 2) {
|
||||
toast.add({ title: '域名格式不正确' });
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const isTLDValid = (parts: string[]): boolean => {
|
||||
const potentialTLD = parts.slice(-2).join('.');
|
||||
if (!SupportedTLDs.has(parts.slice(-1)[0]) && !SupportedTLDs.has(potentialTLD)) {
|
||||
toast.add({ title: '域名后缀不合法' });
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const updateDomainForTLD = (parts: string[]): string => {
|
||||
const potentialTLD = parts.slice(-2).join('.');
|
||||
let domainToKeep: string;
|
||||
if (SupportedTLDs.has(potentialTLD)) {
|
||||
domainToKeep = parts.length > 2 ? parts.slice(-3).join('.') : parts.join('.');
|
||||
} else {
|
||||
domainToKeep = parts.slice(-2).join('.');
|
||||
}
|
||||
return domainToKeep;
|
||||
}
|
||||
|
||||
const styleStore = useStyleStore()
|
||||
const clientMounted = ref(false);
|
||||
|
||||
onMounted(() => {
|
||||
clientMounted.value = true;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full h-[90vh] text-xs bg-[#F1F3F4] dark:bg-transparent">
|
||||
<div class=" max-w-screen-lg mx-auto pt-[25vh] px-[1em] pb-[10vh] ">
|
||||
<div
|
||||
class="w-full text-xs bg-[#F1F3F4] dark:bg-transparent"
|
||||
:class="{ 'h-[90vh]': !styleStore.isPage && clientMounted }"
|
||||
>
|
||||
<div
|
||||
class=" max-w-screen-lg mx-auto px-[1em] pb-[10vh] "
|
||||
:class="{ 'pt-[25vh]': !styleStore.isPage && clientMounted, 'pt-[5vh]': styleStore.isPage || !clientMounted }"
|
||||
>
|
||||
<nav class=" w-full text-[#464747] h-5 dark:bg-gray-700">
|
||||
<NuxtLink class="mb-3 font-bold text-2xl inline-block text-current no-underline dark:text-white"
|
||||
to="/"
|
||||
>
|
||||
<h1 class="inline-block text-current no-underline dark:text-white">Nuxt Whois</h1>
|
||||
<sup class="text-[#59a8d7] dark:text-[#ace4f8]">COM</sup>
|
||||
<h1 class="inline-block text-current no-underline dark:text-white">{{ runtimeConfig?.public?.Domain }}</h1>
|
||||
<sup class="text-[#59a8d7] dark:text-[#ace4f8]">{{ runtimeConfig?.public?.DomainSuffix }}</sup>
|
||||
</NuxtLink>
|
||||
</nav>
|
||||
<div class="mt-6">
|
||||
<UForm :state="state"
|
||||
class="flex items-center space-x-2 mb-3 dark:text-white"
|
||||
@submit="handleAction">
|
||||
@submit="handleAction('whois')">
|
||||
<!-- 容器div用于水平布局 -->
|
||||
<div class="flex-grow">
|
||||
<UInput
|
||||
v-model="state.domain"
|
||||
placeholder="输入域名"
|
||||
:placeholder="t('index.placeholder')"
|
||||
color="sky"
|
||||
size="xl"
|
||||
class="w-full " />
|
||||
@ -86,28 +109,8 @@ const timeStore = useTimeStore()
|
||||
</UForm>
|
||||
</div>
|
||||
<CommonBulletin :text="`➡️ ${t('index.tips') }`" />
|
||||
<ClientOnly>
|
||||
<div class="flex justify-between w-full">
|
||||
<div>
|
||||
<!-- 左边的新元素 -->
|
||||
<UTooltip text="支持列表" :popper="{ placement: 'top' }">
|
||||
<CommonDomainList />
|
||||
</UTooltip>
|
||||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<!-- 右边的现有元素 -->
|
||||
<UTooltip :text="timeStore.timeZones" :popper="{ placement: 'top' }">
|
||||
<CommonTimeZonesChange />
|
||||
</UTooltip>
|
||||
<UTooltip text="主题模式" :popper="{ placement: 'top' }">
|
||||
<CommonColorChange />
|
||||
</UTooltip>
|
||||
<UTooltip text="切换语言" :popper="{ placement: 'top' }">
|
||||
<CommonLanguageChange />
|
||||
</UTooltip>
|
||||
</div>
|
||||
</div>
|
||||
</ClientOnly>
|
||||
|
||||
<TabList @action="handleAction" />
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,119 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import {SupportedTLDs} from "~/utils/domain";
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const state = reactive({
|
||||
domain: '',
|
||||
})
|
||||
|
||||
const toast = useToast();
|
||||
const router = useRouter();
|
||||
const handleAction = async (event: any) => {
|
||||
// 先拿到并处理域名
|
||||
const domain = state.domain.trim();
|
||||
|
||||
// 分割域名为各部分
|
||||
const parts = domain.split('.');
|
||||
|
||||
// 需要一个更严格的检查来确认域名格式是否正确
|
||||
if (parts.length < 2) {
|
||||
toast.add({
|
||||
title: '域名格式不正确',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取最后两个部分作为可能的顶级域名(TLD)
|
||||
const potentialTLD = parts.slice(-2).join('.');
|
||||
|
||||
// 判断后缀是否合法
|
||||
if (!SupportedTLDs.has(parts.slice(-1)[0]) && !SupportedTLDs.has(potentialTLD)) {
|
||||
toast.add({
|
||||
title: '域名后缀不合法',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 确定是否是二级顶级域名
|
||||
let domainToKeep = domain;
|
||||
if (SupportedTLDs.has(potentialTLD)) {
|
||||
// 如果是二级顶级域名,保留最后三个部分
|
||||
domainToKeep = parts.length > 2 ? parts.slice(-3).join('.') : domain;
|
||||
} else {
|
||||
// 否则,只保留最后两个部分
|
||||
domainToKeep = parts.slice(-2).join('.');
|
||||
}
|
||||
|
||||
// 更新state.domain为只包含顶级域名的版本
|
||||
state.domain = domainToKeep;
|
||||
|
||||
// 跳转到结果页
|
||||
await router.push('/result/' + state.domain.replace(/\./g, '_') + '.html');
|
||||
}
|
||||
|
||||
const timeStore = useTimeStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full text-xs bg-[#F1F3F4] dark:bg-transparent">
|
||||
<div class=" max-w-screen-lg mx-auto pt-[5vh] px-[1em] pb-[10vh] ">
|
||||
<nav class=" w-full text-[#464747] h-5 dark:bg-gray-700">
|
||||
<NuxtLink class="mb-3 font-bold text-2xl inline-block text-current no-underline dark:text-white"
|
||||
to="/"
|
||||
>
|
||||
<h1 class="inline-block text-current no-underline dark:text-white">Nuxt Whois</h1>
|
||||
<sup class="text-[#59a8d7] dark:text-[#ace4f8]">COM</sup>
|
||||
</NuxtLink>
|
||||
</nav>
|
||||
<div class="mt-6">
|
||||
<UForm :state="state"
|
||||
class="flex items-center space-x-2 mb-3 dark:text-white"
|
||||
@submit="handleAction">
|
||||
<!-- 容器div用于水平布局 -->
|
||||
<div class="flex-grow">
|
||||
<UInput
|
||||
v-model="state.domain"
|
||||
placeholder="输入域名"
|
||||
color="sky"
|
||||
size="xl"
|
||||
class="w-full " />
|
||||
</div>
|
||||
<!-- 使用v-if或v-show基于state.domain的值来控制按钮的显示 -->
|
||||
<UButton type="submit" color="sky" size="xl" v-if="state.domain">
|
||||
提交
|
||||
</UButton>
|
||||
</UForm>
|
||||
</div>
|
||||
|
||||
<ClientOnly>
|
||||
<div class="flex justify-between w-full">
|
||||
<div>
|
||||
<!-- 左边的新元素 -->
|
||||
<UTooltip text="支持列表" :popper="{ placement: 'top' }">
|
||||
<CommonDomainList />
|
||||
</UTooltip>
|
||||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<!-- 右边的现有元素 -->
|
||||
<UTooltip :text="timeStore.timeZones" :popper="{ placement: 'top' }">
|
||||
<CommonTimeZonesChange />
|
||||
</UTooltip>
|
||||
<UTooltip text="主题模式" :popper="{ placement: 'top' }">
|
||||
<CommonColorChange />
|
||||
</UTooltip>
|
||||
<UTooltip text="切换语言" :popper="{ placement: 'top' }">
|
||||
<CommonLanguageChange />
|
||||
</UTooltip>
|
||||
</div>
|
||||
</div>
|
||||
</ClientOnly>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
<CommonFooter />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -2,12 +2,19 @@
|
||||
export default defineNuxtConfig({
|
||||
devtools: { enabled: true },
|
||||
modules: [
|
||||
'@nuxt/devtools',
|
||||
'@nuxt/ui',
|
||||
'@nuxtjs/i18n',
|
||||
'nuxt-headlessui',
|
||||
'@pinia/nuxt', // needed
|
||||
'@pinia-plugin-persistedstate/nuxt',
|
||||
],
|
||||
runtimeConfig: {
|
||||
public: {
|
||||
Domain: 'Nuxt Whois',
|
||||
DomainSuffix: 'Dns',
|
||||
}
|
||||
},
|
||||
app:{
|
||||
head: {
|
||||
title: 'Nuxt Whois',
|
||||
|
93
pages/dns/[domain].html.vue
Normal file
93
pages/dns/[domain].html.vue
Normal file
@ -0,0 +1,93 @@
|
||||
<script setup lang="ts">
|
||||
import {useStyleStore} from "~/stores/style";
|
||||
|
||||
const {t} = useI18n()
|
||||
|
||||
const route = useRoute();
|
||||
const {domain} = route.params;
|
||||
|
||||
const domainData = domain.replace(/_/g, '.')
|
||||
const {data, pending, error, refresh} = await useAsyncData(
|
||||
'dns',
|
||||
() => $fetch('/api/dns', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({domain: 'xukangr.com'})
|
||||
})
|
||||
)
|
||||
|
||||
const styleStore = useStyleStore()
|
||||
styleStore.setIsPage(true)
|
||||
|
||||
useHead({
|
||||
title: `${domainData} - ${t('result.title')}`,
|
||||
meta: [
|
||||
{
|
||||
hid: 'description',
|
||||
name: 'description',
|
||||
content: t('result.description', {domain: domainData})
|
||||
}
|
||||
]
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mt-5">
|
||||
<div class="bg-white shadow-lg rounded-lg overflow-hidden">
|
||||
<div class="p-6">
|
||||
<h2 class="text-2xl font-bold text-gray-800 mb-6">DNS查询结果</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<h3 class="font-semibold text-lg text-blue-600 mb-2">A记录</h3>
|
||||
<div class="border rounded-lg p-4 bg-blue-50">
|
||||
<ul class="list-none space-y-2">
|
||||
<li v-for="(record, index) in data.A" :key="'a-record-' + index" class="flex justify-between items-center">
|
||||
<span class="font-medium text-gray-700">IP:</span>
|
||||
<span class="font-normal text-gray-600">{{ record.Record }}</span>
|
||||
<span class="text-sm text-gray-500">TTL: {{ record.TTL }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-semibold text-lg text-green-600 mb-2">NS记录</h3>
|
||||
<div class="border rounded-lg p-4 bg-green-50">
|
||||
<ul class="list-none space-y-2">
|
||||
<li v-for="(record, index) in data.NS" :key="'ns-record-' + index" class="flex justify-between items-center">
|
||||
<span class="font-normal text-gray-600">{{ record.Record }}</span>
|
||||
<span class="text-sm text-gray-500">TTL: {{ record.TTL }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md:col-span-2">
|
||||
<h3 class="font-semibold text-lg text-purple-600 mb-2">SOA记录</h3>
|
||||
<div class="border rounded-lg p-4 bg-purple-50">
|
||||
<ul class="list-none space-y-2">
|
||||
<li><span class="font-medium text-gray-700">MName:</span> <span class="font-normal text-gray-600">{{ data.SOA.MName }}</span></li>
|
||||
<li><span class="font-medium text-gray-700">Email:</span> <span class="font-normal text-gray-600">{{ data.SOA.Email }}</span></li>
|
||||
<li><span class="font-medium text-gray-700">Serial:</span> <span class="font-normal text-gray-600">{{ data.SOA.Serial }}</span></li>
|
||||
<li><span class="font-medium text-gray-700">Refresh:</span> <span class="font-normal text-gray-600">{{ data.SOA.Refresh }}</span></li>
|
||||
<li><span class="font-medium text-gray-700">Retry:</span> <span class="font-normal text-gray-600">{{ data.SOA.Retry }}</span></li>
|
||||
<li><span class="font-medium text-gray-700">Expire:</span> <span class="font-normal text-gray-600">{{ data.SOA.Expire }}</span></li>
|
||||
<li><span class="font-medium text-gray-700">Minimum TTL:</span> <span class="font-normal text-gray-600">{{ data.SOA.MinimumTTL }}</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 公告部分 -->
|
||||
<CommonBulletin v-if="error" class="mt-5" >
|
||||
<template #text>
|
||||
<Icon name="bx:error" size="16px" color="red" />
|
||||
{{ t('error.notFound') }}
|
||||
</template>
|
||||
</CommonBulletin>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -1,5 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import {useStyleStore} from "~/stores/style";
|
||||
|
||||
const styleStore = useStyleStore()
|
||||
styleStore.setIsPage(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -2,10 +2,8 @@
|
||||
import {ParseWhois} from "~/utils/whoisToJson";
|
||||
import {AdjustTimeToUTCOffset} from "~/utils/utc";
|
||||
import {useTimeStore} from "~/stores/time";
|
||||
import {useStyleStore} from "~/stores/style";
|
||||
|
||||
definePageMeta({
|
||||
layout: 'result',
|
||||
})
|
||||
const route = useRoute();
|
||||
const {domain} = route.params;
|
||||
|
||||
@ -24,7 +22,8 @@ const {data, pending, error, refresh} = await useAsyncData(
|
||||
const parsedInfo = ParseWhois(data.value);
|
||||
const showRawData = ref(false);
|
||||
const timeStore = useTimeStore()
|
||||
|
||||
const styleStore = useStyleStore()
|
||||
styleStore.setIsPage(true)
|
||||
useHead({
|
||||
title: `${domainData} - ${t('result.title')}`,
|
||||
meta: [
|
||||
@ -39,7 +38,6 @@ useHead({
|
||||
|
||||
<template>
|
||||
<table
|
||||
v-if="parsedInfo.registrar"
|
||||
class="w-full bg-[#fffffe] p-4 shadow-lg rounded-lg mt-5 dark:bg-gray-800 dark:text-gray-200 text-white hover:bg-none">
|
||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<tr class="hover:bg-gray-100 text-gray-900 dark:hover:bg-gray-700 text-gray-200">
|
||||
@ -105,7 +103,7 @@ useHead({
|
||||
</table>
|
||||
|
||||
<!-- 公告部分 -->
|
||||
<CommonBulletin v-else class="mt-5" >
|
||||
<CommonBulletin v-if="error" class="mt-5" >
|
||||
<template #text>
|
||||
<Icon name="bx:error" size="16px" color="red" />
|
||||
{{ t('error.notFound') }}
|
31
server/api/dns.post.ts
Normal file
31
server/api/dns.post.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import dns from 'node:dns/promises';
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event)
|
||||
|
||||
const domain = body.domain;
|
||||
if (!domain) {
|
||||
return { error: 'Missing domain' };
|
||||
}
|
||||
try {
|
||||
const aRecords = await dns.resolve(domain, 'A');
|
||||
const nsRecords = await dns.resolve(domain, 'NS');
|
||||
const soaRecord = await dns.resolveSoa(domain);
|
||||
|
||||
return {
|
||||
A: aRecords.map(ip => ({ TTL: '600', Record: ip })), // 示例中的TTL是假设的
|
||||
NS: nsRecords.map(ns => ({ TTL: '21600', Record: ns })), // 示例中的TTL是假设的
|
||||
SOA: {
|
||||
MName: soaRecord.nsname,
|
||||
Email: soaRecord.hostmaster,
|
||||
Serial: soaRecord.serial,
|
||||
Refresh: soaRecord.refresh,
|
||||
Retry: soaRecord.retry,
|
||||
Expire: soaRecord.expire,
|
||||
MinimumTTL: soaRecord.minttl,
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`Error fetching DNS records for ${domain}:`, error);
|
||||
return { error: 'Failed to fetch DNS records' };
|
||||
}
|
||||
})
|
14
stores/style.ts
Normal file
14
stores/style.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useStyleStore = defineStore('style', {
|
||||
state: () => {
|
||||
return {
|
||||
isPage: true,
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setIsPage(isPage: boolean) {
|
||||
this.isPage = isPage
|
||||
},
|
||||
},
|
||||
})
|
@ -1,3 +1,6 @@
|
||||
// br.com,cn.com,de.com,eu.com,gb.com,gb.net,gr.com,hu.com,in.net,no.com,qc.com,ru.com,sa.com,se.com,se.net,uk.com,uk.net,us.com,uy.com,za.com,jpn.com,web.com,com,za.net,net,eu.org,za.org,org,llyw.cymru,gov.scot,gov.wales,edu,gov,int,e164.arpa,arpa,aero,asia,biz,cat,coop,info,jobs,mobi,museum,name,post,pro,tel,travel,xxx,ac,ae,af,ag,ai,am,ar,as,priv.at,at,au,aw,ax,be,bf,bg,bh,bi,bj,bm,bn,bo,br,by,bw,bz,co.ca,ca,cc,cd,ch,ci,cl,cm,edu.cn,cn,uk.co,co,cr,cx,cz,de,dk,dm,do,dz,ec,ee,eu,fi,fj,fm,fo,fr,gd,ge,gf,gg,gh,gi,gl,gp,gq,gs,gy,hk,hm,hn,hr,ht,hu,id,ie,il,im,in,io,iq,ir,is,it,je,jp,ke,kg,ki,kn,kr,kw,ky,kz,la,lb,lc,li,lk,ls,lt,lu,lv,ly,ma,md,me,mg,mk,ml,mm,mn,mq,mr,ms,mt,mu,mw,mx,my,mz,na,nc,nf,ng,nl,no,nu,nz,om,pe,pf,pk,co.pl,pl,pm,pr,ps,pt,pw,qa,re,ro,rs,ac.ru,edu.ru,com.ru,msk.ru,net.ru,nov.ru,org.ru,pp.ru,spb.ru,ru,rw,sa,sb,sc,sd,se,sg,sh,si,sk,sl,sm,sn,so,ss,st,msk.su,nov.su,spb.su,su,sx,sy,tc,td,tf,tg,th,tk,tl,tm,tn,to,tr,tv,tw,tz,biz.ua,co.ua,pp.ua,ua,ug,ac.uk,gov.uk,uk,fed.us,us,uy,uz,vc,ve,vg,vu,wf,ws,yt,ac.za,co.za,gov.za,net.za,org.za,web.za,zm,xn--2scrj9c,xn--3e0b707e,xn--3hcrj9c,xn--45br5cyl,xn--45brj9c,xn--4dbrk0ce,xn--80ao21a,xn--90a3ac,xn--90ae,xn--90ais,xn--clchc0ea0b2g2a9gcd,xn--d1alf,xn--e1a4c,xn--fiqs8s,xn--fiqz9s,xn--fpcrj9c3d,xn--fzc2c9e2c,xn--gecrj9c,xn--h2breg3eve,xn--h2brj9c8c,xn--h2brj9c,xn--j1amh,xn--j6w193g,xn--kprw13d,xn--kpry57d,xn--lgbbat1ad8j,xn--mgb9awbf,xn--mgba3a4f16a,xn--mgbaam7a8h,xn--mgbah1a3hjkrd,xn--mgbbh1a71e,xn--mgbbh1a,xn--mgberp4a5d4ar,xn--mgbgu82a,xn--mgbtx2b,xn--mgbx4cd0ab,xn--node,xn--o3cw4h,xn--ogbpf8fl,xn--p1ai,xn--pgbs0dh,xn--q7ce6a,xn--qxa6a,xn--rvc1e0am3e,xn--s9brj9c,xn--wgbh1c,xn--wgbl6a,xn--xkc2al3hye2a,xn--xkc2dl3a5ee0h,xn--y9a3aq,xn--yfro4i67o,xn--ygbi2ammx
|
||||
|
||||
export const SupportedTLDs = new Set(["br.com", "cn.com", "de.com", "eu.com", "gb.com", "gb.net", "gr.com", "hu.com", "in.net", "no.com", "qc.com", "ru.com", "sa.com", "se.com", "se.net", "uk.com", "uk.net", "us.com", "uy.com", "za.com", "jpn.com", "web.com", "com", "za.net", "net", "eu.org", "za.org", "org", "llyw.cymru", "gov.scot", "gov.wales", "edu", "gov", "int", "e164.arpa", "arpa", "aero", "asia", "biz", "cat", "coop", "info", "jobs", "mobi", "museum", "name", "post", "pro", "tel", "travel", "xxx", "ac", "ae", "af", "ag", "ai", "am", "ar", "as", "priv.at", "at", "au", "aw", "ax", "be", "bf", "bg", "bh", "bi", "bj", "bm", "bn", "bo", "br", "by", "bw", "bz", "co.ca", "ca", "cc", "cd", "ch", "ci", "cl", "cm", "edu.cn", "cn", "uk.co", "co", "cr", "cx", "cz", "de", "dk", "dm", "do", "dz", "ec", "ee", "eu", "fi", "fj", "fm", "fo", "fr", "gd", "ge", "gf", "gg", "gh", "gi", "gl", "gp", "gq", "gs", "gy", "hk", "hm", "hn", "hr", "ht", "hu", "id", "ie", "il", "im", "in", "io", "iq", "ir", "is", "it", "je", "jp", "ke", "kg", "ki", "kn", "kr", "kw", "ky", "kz", "la", "lb", "lc", "li", "lk", "ls", "lt", "lu", "lv", "ly", "ma", "md", "me", "mg", "mk", "ml", "mm", "mn", "mq", "mr", "ms", "mt", "mu", "mw", "mx", "my", "mz", "na", "nc", "nf", "ng", "nl", "no", "nu", "nz", "om", "pe", "pf", "pk", "co.pl", "pl", "pm", "pr", "ps", "pt", "pw", "qa", "re", "ro", "rs", "ac.ru", "edu.ru", "com.ru", "msk.ru", "net.ru", "nov.ru", "org.ru", "pp.ru", "spb.ru", "ru", "rw", "sa", "sb", "sc", "sd", "se", "sg", "sh", "si", "sk", "sl", "sm", "sn", "so", "ss", "st", "msk.su", "nov.su", "spb.su", "su", "sx", "sy", "tc", "td", "tf", "tg", "th", "tk", "tl", "tm", "tn", "to", "tr", "tv", "tw", "tz", "biz.ua", "co.ua", "pp.ua", "ua", "ug", "ac.uk", "gov.uk", "uk", "fed.us", "us", "uy", "uz", "vc", "ve", "vg", "vu", "wf", "ws", "yt", "ac.za", "co.za", "gov.za", "net.za", "org.za", "web.za", "zm", "xn--2scrj9c", "xn--3e0b707e", "xn--3hcrj9c", "xn--45br5cyl", "xn--45brj9c", "xn--4dbrk0ce", "xn--80ao21a", "xn--90a3ac", "xn--90ae", "xn--90ais", "xn--clchc0ea0b2g2a9gcd", "xn--d1alf", "xn--e1a4c", "xn--fiqs8s", "xn--fiqz9s", "xn--fpcrj9c3d", "xn--fzc2c9e2c", "xn--gecrj9c", "xn--h2breg3eve", "xn--h2brj9c8c", "xn--h2brj9c", "xn--j1amh", "xn--j6w193g", "xn--kprw13d", "xn--kpry57d", "xn--lgbbat1ad8j", "xn--mgb9awbf", "xn--mgba3a4f16a", "xn--mgbaam7a8h", "xn--mgbah1a3hjkrd", "xn--mgbbh1a71e", "xn--mgbbh1a", "xn--mgberp4a5d4ar", "xn--mgbgu82a", "xn--mgbtx2b", "xn--mgbx4cd0ab", "xn--node", "xn--o3cw4h", "xn--ogbpf8fl", "xn--p1ai", "xn--pgbs0dh", "xn--q7ce6a", "xn--qxa6a", "xn--rvc1e0am3e", "xn--s9brj9c", "xn--wgbh1c", "xn--wgbl6a", "xn--xkc2al3hye2a", "xn--xkc2dl3a5ee0h", "xn--y9a3aq", "xn--yfro4i67o", "xn--ygbi2ammx"]);
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user