🔥 添加自定义后缀

This commit is contained in:
7836246 2024-03-18 00:19:08 +08:00
parent 168013cb27
commit 4c6250b1f9
10 changed files with 208 additions and 10 deletions

View File

@ -1,6 +1,6 @@
<script setup lang="ts">
import {SupportedTLDs} from "~/utils/domain";
const domainStore = useDomainStore();
const SupportedTLDs = new Set(Object.keys(domainStore.SupportedTLDs));
const isOpen = ref(false)
const {t} = useI18n()
</script>

View File

@ -0,0 +1,53 @@
<template>
<div class="px-4 space-y-4">
<div class="flex gap-2 items-center">
<UInput v-model="newDomainSuffix" @input="searchSuffix" placeholder="域名后缀,如 .cn" class="flex-grow rounded shadow transition duration-200 ease-in-out" />
<UInput v-model="newWhoisServer" placeholder="Whois服务器如 whois.cnnic.net.cn" class="flex-grow border-gray-300 rounded shadow transition duration-200 ease-in-out" />
<UButton @click="addSuffix" type="button" :disabled="suffixExists" class="p-2 bg-blue-500 text-white rounded hover:bg-blue-700 shadow disabled:bg-gray-400 disabled:cursor-not-allowed transition duration-200 ease-in-out">添加</UButton>
</div>
<div class="text-sm" v-if="suffixExists">
<span class="text-red-500">后缀已存在</span>
</div>
<div class="overflow-auto h-64 mt-4 bg-gray-50 rounded shadow">
<div v-for="(server, suffix) in domainStore.SupportedTLDs" :key="suffix" class="flex items-center justify-between p-2 border-b border-gray-200 last:border-b-0">
<div>{{ suffix }}: {{ server }}</div>
<UButton @click="removeSuffix(suffix)" type="button" class="bg-red-500 hover:bg-red-700 text-white p-1 rounded shadow transition duration-200 ease-in-out">删除</UButton>
</div>
</div>
</div>
</template>
<script setup lang="ts">
const domainStore = useDomainStore();
const newDomainSuffix = ref('');
const newWhoisServer = ref('');
const suffixExists = computed(() => newDomainSuffix.value in domainStore.SupportedTLDs);
const toast = useToast()
const addSuffix = async () => {
if (newDomainSuffix.value && newWhoisServer.value && !suffixExists.value) {
await domainStore.addSuffix(newDomainSuffix.value, newWhoisServer.value);
newDomainSuffix.value = '';
newWhoisServer.value = '';
toast.add(
{ title: '添加成功' }
);
}
};
const removeSuffix = async (suffix: string) => {
await domainStore.removeSuffix(suffix);
toast.add(
{ title: '删除成功',
}
);
};
const searchSuffix = () => {
// @inputsuffixExists
};
</script>
<style scoped>
</style>

View File

@ -1,5 +1,4 @@
<script setup lang="ts">
import {SupportedTLDs} from "~/utils/domain";
import {useStyleStore} from "~/stores/style";
const { t } = useI18n()
@ -14,7 +13,9 @@ const router = useRouter();
const runtimeConfig = useRuntimeConfig()
const localePath = useLocalePath()
const settingsStore = useSettingsStore()
const domainStore = useDomainStore()
const SupportedTLDs = new Set(Object.keys(domainStore.SupportedTLDs));
const handleAction = async (url: any) => {
if (!state.domain) return toast.add({ title: '请输入域名' })
let domain = trimDomain(state.domain);

View File

@ -1,6 +1,7 @@
<script setup lang="ts">
import {useStyleStore} from "~/stores/style";
import {useSettingsStore} from "~/stores/settings";
import {useDomainStore} from "~/stores/domain";
const styleStore = useStyleStore()
const settingsStore = useSettingsStore()
@ -11,6 +12,7 @@ styleStore.setIsPage(true)
const {isHistory} = storeToRefs(settingsStore)
const isOpen = ref(false)
const isEditDomainOpen = ref(false)
const handleReset = async () => {
settingsStore.setHistory(true)
@ -37,11 +39,61 @@ const handleReset = async () => {
</UCard>
</div>
<div class="setting">
<div class="text-2xl font-bold mt-[30px] mb-[20px]"> 后缀设置 </div>
<u-card class="set-item">
<div class="flex justify-between items-center">
<div class="text-base"> 自定义后缀 </div>
<div class="text-sm " >
自定义编辑管理添加后缀
</div>
<div>
<u-button type="warning"
@click="isEditDomainOpen = true"
> 管理 </u-button>
</div>
</div>
<UModal
v-model="isEditDomainOpen"
>
<UCard
:ui="{
base: 'h-full flex flex-col',
rounded: '10',
divide: 'divide-y divide-gray-100 dark:divide-gray-800',
body: {
base: 'grow'
}
}"
>
<template #header>
<div class="flex items-center justify-between">
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
后缀管理
</h3>
<UButton
color="gray"
variant="ghost"
icon="i-heroicons-x-mark-20-solid"
class="-my-1"
type="button"
@click="isEditDomainOpen = false" />
</div>
</template>
<div class="mx-auto">
<DomainEditor />
</div>
</UCard>
</UModal>
</u-card>
</div>
<div class="setting">
<div class="text-2xl font-bold mt-[30px] mb-[20px]">{{ t('settings.linkOpenType') }}</div>
<UCard>
<div class="flex justify-between items-center">
<div class="text-base "> {{ t('settings.linkOpenTypeDesc') }} </div>
<div class="text-base "> {{ t('settings.linkOpenTypeDesc') }} </div>
<div>
<ClientOnly>
<CommonLinkChange />
@ -51,6 +103,7 @@ const handleReset = async () => {
</UCard>
</div>
<div class="setting">
<div class="text-2xl font-bold mt-[30px] mb-[20px]"> {{ t('settings.miscellaneous') }} </div>
<u-card class="set-item">

View File

@ -0,0 +1,24 @@
import { defineEventHandler } from 'h3';
import fs from 'fs';
import path from 'path';
interface AddSuffixBody {
suffix: string;
server: string;
}
export default defineEventHandler(async (event) => {
const body: AddSuffixBody = await readBody(event);
const filePath = path.join('server/whois/json', 'whois-servers.json');
const fileContent = fs.readFileSync(filePath, { encoding: 'utf8' });
const data: Record<string, string> = JSON.parse(fileContent);
// 添加或更新域名后缀
data[body.suffix] = body.server;
// 写入更新
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), { encoding: 'utf8' });
return { message: 'ok' };
});

View File

@ -0,0 +1,23 @@
import { defineEventHandler } from 'h3';
import fs from 'fs';
import path from 'path';
interface RemoveSuffixBody {
suffix: string;
}
export default defineEventHandler(async (event) => {
const body: RemoveSuffixBody = await readBody(event);
const filePath = path.join('server/whois/json', 'whois-servers.json');
const fileContent = fs.readFileSync(filePath, { encoding: 'utf8' });
const data: Record<string, string> = JSON.parse(fileContent);
// 删除域名后缀
delete data[body.suffix];
// 写入更新
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), { encoding: 'utf8' });
return { message: 'ok' };
});

View File

@ -1533,7 +1533,6 @@
"net.cn": "whois.cnnic.net.cn",
"org.cn": "whois.cnnic.net.cn",
"gov.cn": "whois.cnnic.net.cn",
"net.cn": "whois.cnnic.net.cn",
"ac.cn": "whois.cnnic.net.cn",
"bj.cn": "whois.cnnic.net.cn",
"sh.cn": "whois.cnnic.net.cn",
@ -1569,5 +1568,4 @@
"gz.cn": "whois.cnnic.net.cn",
"sn.cn": "whois.cnnic.net.cn",
"xj.cn": "whois.cnnic.net.cn"
}
}

View File

@ -6,7 +6,6 @@ import parametersData from '~/server/whois/json/parameters.json';
const IANA_CHK_URL = 'https://www.iana.org/whois?q=';
interface IServers {
[key: string]: string;
}

49
stores/domain.ts Normal file
View File

@ -0,0 +1,49 @@
import { defineStore } from 'pinia';
import serversData from '~/server/whois/json/whois-servers.json';
// 定义接口来描述state的结构
interface DomainState {
SupportedTLDs: Record<string, string>;
}
export const useDomainStore = defineStore('domain', {
// 使用箭头函数和类型注解定义state
state: (): DomainState => ({
SupportedTLDs: { ...serversData },
}),
actions: {
async addSuffix(suffix: string, server: string) {
const response = await $fetch('/api/addSuffix', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({suffix, server}),
});
if (response.message === 'ok') {
// 更新本地状态
await nextTick();
this.SupportedTLDs[suffix] = server;
}
},
async removeSuffix(suffix: string) {
const response = await $fetch('/api/removeSuffix', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({suffix}),
});
if (response.message === 'ok') {
await nextTick();
// 更新本地状态
delete this.SupportedTLDs[suffix];
}
}
},
persist:{
storage: persistedState.localStorage,
}
});

View File

@ -1,2 +0,0 @@
import serversData from '~/server/whois/json/whois-servers.json';
export const SupportedTLDs = new Set(Object.keys(serversData));