🎨 增加 Go 后端

This commit is contained in:
江西小徐
2024-04-07 11:08:05 +08:00
parent 04c82ab25d
commit 61275be2bf
165 changed files with 7043 additions and 3599 deletions
+112
View File
@@ -0,0 +1,112 @@
<script setup lang="ts">
import {type MenuOption, NIcon} from "naive-ui";
import type {Component} from "vue";
import {Settings, Wrench, Pentagon, MessageCircleMore} from 'lucide-vue-next';
function renderIcon(icon: Component) {
return () => h(NIcon, null, {default: () => h(icon)})
}
const route = useRoute()
const router = useRouter()
const menusOptions: MenuOption[] = [
{
label: '控制台',
key: '/admin/dashboard',
icon: renderIcon(Pentagon)
},
{
label: 'Whois管理',
key: 'whois',
icon: renderIcon(Settings),
children: [
{
label: '后缀管理',
key: '/admin/whois/website',
icon: renderIcon(Wrench),
}
]
},
{
label: 'Dns管理',
key: 'dns',
icon: renderIcon(Settings),
children: [
{
label: '后缀管理',
key: '/admin/whois/website',
icon: renderIcon(Wrench),
}
]
},
{
label: 'Domain管理',
key: 'domain',
icon: renderIcon(Settings),
children: [
{
label: '后缀管理',
key: '/admin/whois/website',
icon: renderIcon(Wrench),
}
]
},
{
label: '系统管理',
key: 'settings',
icon: renderIcon(Settings),
children: [
{
label: '网站设置',
key: '/admin/settings/website',
icon: renderIcon(Wrench),
},
{
label: '公告管理',
key: '/admin/settings/bulletin',
icon: renderIcon(MessageCircleMore),
}
]
}
]
const activeKey = computed(() => route.path)
console.log(route.path)
function handleMenuSelect(key: any, item: any) {
if (isExternal(item.key)) {
router.push(item.key)
} else {
router.push(item.key)
}
}
</script>
<template>
<div class="flex h-screen bg-gray-100">
<!-- Left Sidebar -->
<div class="w-64 text-black">
<n-menu
ref="menu"
class="side-menu"
accordion
:indent="18"
:collapsed-icon-size="22"
:collapsed-width="64"
:options="menusOptions"
:value="activeKey"
@update:value="handleMenuSelect"
/>
</div>
<!-- Right Content -->
<div class="flex-1 p-10">
<slot/>
</div>
</div>
</template>
<style scoped>
</style>
+132
View File
@@ -0,0 +1,132 @@
<script setup lang="ts">
const route = useRoute()
const router = useRouter();
const {t} = useI18n()
const localePath = useLocalePath()
const message = useMessage()
const settingsStore = useSettingsStore()
const {isObj, domainSearch, selectedOption, webSiteConfig} = storeToRefs(settingsStore)
//设置不同页面的样式
const stylePage = computed(() => {
return route.meta?.stylePage
})
// 提取主域名的函数,直接返回提取结果,不尝试猜测二级顶级域名
const handleAction = async (url) => {
const etDomainSearch = ExtractDomain(domainSearch.value);
switch (url) {
case 'whois':
// 使用正则表达式校验提取的主域名
if (DomainRegex.test(etDomainSearch)) {
// 将正确数据进行记录
domainSearch.value = etDomainSearch;
// 参数校验成功,进行跳转
const urlType = etDomainSearch.replace(/\./g, '_');
await router.push(localePath(`/whois/${urlType}.html`));
} else if (Ipv4Regex.test(domainSearch.value)) {
// 处理用户操作的异步函数
const urlType = domainSearch.value.replace(/\./g, '_');
await router.push(localePath(`/whois/${urlType}.html`));
} else {
message.error('请输入有效的域名或IP地址')
return;
}
break;
case 'dns':
// 使用正则表达式校验提取的主域名
if (DomainRegex.test(etDomainSearch)) {
// 将正确数据进行记录
domainSearch.value = etDomainSearch;
// 参数校验成功,进行跳转
const urlType = etDomainSearch.replace(/\./g, '_');
await router.push(localePath(`/dns/${urlType}.html`));
} else if (Ipv4Regex.test(domainSearch.value)) {
// 处理用户操作的异步函数
const urlType = domainSearch.value.replace(/\./g, '_');
await router.push(localePath(`/dns/${urlType}.html`));
} else {
message.error('请输入有效的域名或IP地址')
return;
}
return
}
}
const handleSelectOptions = (value: any) => {
settingsStore.setSelectedOption(value);
}
</script>
<template>
<div
class="w-full text-xs bg-[#F1F3F4] dark:bg-transparent"
:class="{ 'h-[90vh]': !stylePage }"
>
<div
class=" max-w-screen-lg mx-auto px-[1em] pb-[10vh] "
:class="{ 'pt-[25vh]': !stylePage, 'pt-[5vh]': stylePage }"
>
<nav
v-if="isObj.isLogo"
class=" w-full text-[#464747] h-5 ">
<NuxtLink class="mb-3 font-bold text-2xl inline-block text-current no-underline dark:text-white"
:to="localePath('/')"
>
<h1 class="inline-block text-current no-underline dark:text-white">{{ webSiteConfig.logoLeftText }}</h1>
<sup class="text-[#59a8d7] dark:text-[#ace4f8]">{{ webSiteConfig.logoRightText }}</sup>
</NuxtLink>
</nav>
<div class="mt-6">
<ClientOnly>
<div class="flex items-center space-x-2 mb-3 dark:text-white"
>
<!-- 容器div用于水平布局 -->
<div class="flex-grow">
<NInputGroup>
<n-select
class="w-1/4"
size="large"
v-model:value="selectedOption"
:options="webSiteConfig.defaultSelectOptions"
@update:value="handleSelectOptions"
/>
<NAutoComplete
v-model:value="domainSearch"
@keyup.enter="handleAction(settingsStore.selectedOption)"
:input-props="{ autocomplete: 'off' }"
type="text"
:placeholder="t('index.placeholder')"
size="large"
clearable
autofocus
class="w-full ">
</NAutoComplete>
</NInputGroup>
</div>
<!-- 使用v-if基于state.domain的值来控制按钮的显示 -->
<NButton type="primary"
size="large"
@click="handleAction(settingsStore.selectedOption)"
v-if="settingsStore.domainSearch">
{{ t('index.onSubmit') }}
</NButton>
</div>
</ClientOnly>
</div>
<CommonBulletin
v-if="!stylePage && isObj.isBulletin"
:text="`➡️ ${t('index.tips') }`"
/>
<TabList @action="handleAction"/>
<slot/>
</div>
</div>
<CommonFooter/>
</template>
<style scoped>
</style>
+14
View File
@@ -0,0 +1,14 @@
<script setup lang="ts">
</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] ">
<slot />
</div>
</div>
</template>
<style scoped>
</style>