Files
MirageServer/frontend/src/components/DNS.vue
T
Chenyang Gao f43aed2be7 增加组织magicDNS域名随机及更新机制
Signed-off-by: Chenyang Gao <gps949@outlook.com>
2023-03-25 14:37:44 +08:00

913 lines
32 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { ref, computed, nextTick, onMounted, watch, watchEffect } from "vue";
import { onBeforeRouteUpdate, useRoute, useRouter } from "vue-router";
import { useScrollOff } from "../utils.js";
import Toast from "./Toast.vue";
import AddNS from "./dns/AddNS.vue";
import EditNS from "./dns/EditNS.vue";
import UpdateTCD from "./dns/UpdateTCD.vue";
const devmode = ref("true");
const toastShow = ref(false);
const toastMsg = ref("");
watch(toastShow, () => {
if (toastShow.value) {
setTimeout(function () {
toastShow.value = false;
}, 5000);
}
});
const DisableMagicDNSShow = ref(false);
const addNSBtn = ref(null);
const AddNameserverShow = ref(false);
const addNSLeft = ref(0);
const addNSTop = ref(0);
const AddNSShow = ref(false);
function refreshPos() {
if (addNSBtn.value != null) {
addNSLeft.value = addNSBtn.value?.getBoundingClientRect().left;
if (addNSBtn.value?.getBoundingClientRect().top > window.innerHeight - 108) {
addNSTop.value = addNSBtn.value?.getBoundingClientRect().top - 58;
} else {
addNSTop.value = addNSBtn.value?.getBoundingClientRect().top + 42;
}
}
if (NSMenuBtn.value != null) {
NSMenuLeft.value = NSMenuBtn.value?.getBoundingClientRect().left - 80;
if (NSMenuBtn.value?.getBoundingClientRect().top > window.innerHeight - 112) {
NSMenuTop.value = NSMenuBtn.value?.getBoundingClientRect().top - 76;
} else {
NSMenuTop.value = NSMenuBtn.value?.getBoundingClientRect().top;
}
}
}
const NSMenuBtn = ref(null);
const NSMenuLeft = ref(0);
const NSMenuTop = ref(0);
const NSMenuShow = ref(false);
const EditNSShow = ref(false);
const UpdateTCDShow = ref(false);
const currentResolver = ref("");
const currentDomain = ref("");
const DNSCfgRemovedCurrent = computed(() => {
var tmpDNSCfg = JSON.parse(JSON.stringify(DNSCfg.value));
if (currentDomain.value == "") {
if (currentResolver.value == "") return tmpDNSCfg;
if (!tmpDNSCfg["resolvers"] || tmpDNSCfg["resolvers"].length == 0) {
var newFallbackResolvers = [];
for (var i in tmpDNSCfg["fallbackResolvers"]) {
if (tmpDNSCfg["fallbackResolvers"][i] != currentResolver.value) {
newFallbackResolvers.push(tmpDNSCfg["fallbackResolvers"][i]);
}
}
tmpDNSCfg["fallbackResolvers"] = newFallbackResolvers;
return tmpDNSCfg;
} else {
var newResolvers = [];
for (var i in tmpDNSCfg["resolvers"]) {
if (tmpDNSCfg["resolvers"][i] != currentResolver.value) {
newResolvers.push(tmpDNSCfg["resolvers"][i]);
}
}
tmpDNSCfg["resolvers"] = newResolvers;
return tmpDNSCfg;
}
} else {
if (currentResolver.value == "") return tmpDNSCfg;
var newDomain = [];
var newRoute = [];
for (var i in tmpDNSCfg["domains"]) {
if (tmpDNSCfg["domains"][i] != currentDomain.value) {
newDomain.push(tmpDNSCfg["domains"][i]);
} else {
for (var j in tmpDNSCfg["routes"][currentDomain.value]) {
if (tmpDNSCfg["routes"][currentDomain.value][j] != currentResolver.value) {
newRoute.push(tmpDNSCfg["routes"][currentDomain.value][j]);
}
}
tmpDNSCfg["routes"][currentDomain.value] = newRoute;
if (newRoute.length > 0) {
newDomain.push(currentDomain.value);
}
}
}
tmpDNSCfg["domains"] = newDomain;
if (newRoute.length == 0) {
var newRoutes = {};
for (var key in tmpDNSCfg["routes"]) {
if (key != currentDomain.value) {
newRoutes[key] = tmpDNSCfg["routes"][key];
}
}
tmpDNSCfg["routes"] = newRoutes;
}
return tmpDNSCfg;
}
});
function showNSMenu(e) {
NSMenuBtn.value = e.target;
while (NSMenuBtn.value?.tagName.toLowerCase() != "button") {
NSMenuBtn.value = NSMenuBtn.value.parentNode;
}
refreshPos();
useScrollOff(true);
currentResolver.value =
NSMenuBtn.value.parentNode.previousElementSibling.firstChild.innerText;
if (
NSMenuBtn.value.parentNode.parentNode.parentNode.previousElementSibling.firstChild
.innerText == "全球域名服务器"
) {
currentDomain.value = "";
} else {
currentDomain.value =
NSMenuBtn.value.parentNode.parentNode.parentNode.previousElementSibling.firstChild.nextElementSibling.innerText;
}
/*
console.log("currentResolver: " + currentResolver.value)
console.log("currentDomain: " + currentDomain.value)
console.log("currentCfgDomains: " + JSON.stringify(DNSCfgRemovedCurrent.value))
*/
NSMenuShow.value = true;
}
const DNSCfg = ref({});
const TCDOffers = ref([]);
const MNetName = computed(() => {
return DNSCfg.value["magicDNSDomains"][0];
});
const enOverride = computed(() => {
return DNSCfg.value["resolvers"] && DNSCfg.value["resolvers"].length > 0;
});
const enMagicDNS = computed(() => {
return DNSCfg.value["magicDNS"];
});
const resolvers = computed(() => {
if (enOverride.value) {
return DNSCfg.value["resolvers"];
}
return DNSCfg.value["fallbackResolvers"];
});
const domains = computed(() => {
return DNSCfg.value["domains"];
});
const domainResolvers = computed(() => {
return DNSCfg.value["routes"];
});
const copyBtnText = ref("复制");
function copyMNetName() {
navigator.clipboard.writeText(MNetName.value).then(function () {
copyBtnText.value = "已复制!";
setTimeout(() => {
copyBtnText.value = "复制";
}, 3000);
});
}
onMounted(() => {
refreshPos();
window.addEventListener("resize", refreshPos);
window.addEventListener("scroll", refreshPos);
axios
.get("/admin/api/dns")
.then(function (response) {
// 处理成功情况
if (response.data["status"] == "success") {
DNSCfg.value = response.data["data"];
} else {
if (response.data["status"].substring(6) == "用户信息核对失败") {
//TODO:token失效跳转
}
}
})
.catch(function (error) {
// 处理错误情况
alert(error);
});
});
function showUpdateTCD() {
UpdateTCDShow.value = true;
}
function refreshTCDOffers(newTCDOffers) {
TCDOffers.value = newTCDOffers;
}
function updateTCD(wantedTCD) {
for (var i in TCDOffers.value) {
if (TCDOffers.value[i]["tcd"] == wantedTCD) {
axios
.post("/admin/api/tcd", TCDOffers.value[i])
.then(function (response) {
if (response.data["status"] == "success") {
DNSCfg.value["magicDNSDomains"][0] = wantedTCD;
TCDOffers.value = [];
UpdateTCDShow.value = false;
toastMsg.value = "已更新蜃境网域名称";
toastShow.value = true;
} else {
toastMsg.value = response.data["status"].substring(6);
toastShow.value = true;
console.log(response.data["status"]);
}
})
.catch(function (error) {
console.log(error);
});
break;
}
}
}
function switchMagicDNS(newStatus) {
var reqData = DNSCfg.value;
switch (newStatus) {
case "on":
case "doOff":
reqData["magicDNS"] = newStatus == "on" ? true : false;
axios
.post("/admin/api/dns", reqData)
.then(function (response) {
if (response.data["status"] == "success") {
DNSCfg.value = response.data["data"];
DisableMagicDNSShow.value = false;
useScrollOff(false);
toastMsg.value = newStatus == "on" ? "已启用幻域" : "已禁用幻域";
toastShow.value = true;
} else {
console.log(response.data["status"]);
}
})
.catch(function (error) {
console.log(error);
});
break;
case "off":
useScrollOff(true);
DisableMagicDNSShow.value = true;
break;
}
}
function switchOverride(event) {
var reqData = DNSCfg.value;
if (event.target.checked) {
reqData["resolvers"] = reqData["fallbackResolvers"];
reqData["fallbackResolvers"] = [];
} else {
reqData["fallbackResolvers"] = reqData["resolvers"];
reqData["resolvers"] = [];
}
axios
.post("/admin/api/dns", reqData)
.then(function (response) {
if (response.data["status"] == "success") {
DNSCfg.value = response.data["data"];
} else {
console.log(response.data["status"]);
}
})
.catch(function (error) {
console.log(error);
});
}
function newNSAdded(newDNSCfg) {
DNSCfg.value = newDNSCfg;
AddNSShow.value = false;
}
function newNSEdited(newDNSCfg) {
DNSCfg.value = newDNSCfg;
EditNSShow.value = false;
}
function removeNS() {
axios
.post("/admin/api/dns", DNSCfgRemovedCurrent.value)
.then(function (response) {
if (response.data["status"] == "success") {
DNSCfg.value = response.data["data"];
} else {
console.log(response.data["status"]);
}
})
.catch(function (error) {
console.log(error);
})
.then(function () {
currentDomain.value = "";
currentResolver.value = "";
NSMenuShow.value = false;
useScrollOff(false);
});
}
</script>
<template>
<main class="container mx-auto pb-20 md:pb-24">
<section class="mb-24">
<header class="mb-8">
<div class="flex justify-between items-center">
<div class="flex items-center">
<h1
class="text-3xl font-semibold tracking-tight leading-tight mb-2"
tabindex="-1"
>
DNS
</h1>
</div>
</div>
</header>
<section class="mb-16 max-w-2xl">
<header class="mb-6">
<h2 class="text-xl font-semibold tracking-tight mb-1">蜃境网域</h2>
<p class="text-gray-600">
这个名称用来注册DNS条目分享设备给其他蜃境网域以及发放TLS证书
</p>
</header>
<div class="max-w-sm">
<div
class="flex border border-stone-200 hover:border-stone-400 rounded-md relative overflow-hidden min-w-0"
>
<input
onclick="this.select()"
class="outline-none py-2 px-3 w-full h-full font-mono text-sm text-ellipsis"
readonly
:value="MNetName"
/>
<button
@click="copyMNetName"
class="flex justify-center py-2 pl-3 pr-4 rounded-md bg-white focus:outline-none font-sans text-blue-500 hover:text-blue-800 font-medium text-sm whitespace-nowrap"
>
{{ copyBtnText }}
</button>
</div>
</div>
<button
@click="showUpdateTCD"
class="btn border border-stone-300 hover:border-stone-300 disabled:border-stone-300 bg-base-200 hover:bg-base-300 disabled:bg-base-200/60 text-black disabled:text-black/30 h-9 min-h-fit mt-8"
>
网域重命名
</button>
</section>
<section class="mb-16 max-w-2xl">
<header class="mb-6">
<h2 class="text-xl font-semibold tracking-tight mb-1">幻域</h2>
<p class="text-gray-600">
自动为您蜃境网域中的设备注册域名令您从而可以使用名称替代IP地址访问设备
</p>
</header>
<button
@click="switchMagicDNS('off')"
v-if="enMagicDNS"
class="btn border-0 bg-red-600 hover:bg-red-700 text-white h-9 min-h-fit"
>
停用幻域
</button>
<button
@click="switchMagicDNS('on')"
v-if="!enMagicDNS"
class="btn border-0 bg-blue-500 hover:bg-blue-900 text-white h-9 min-h-fit"
>
启用幻域
</button>
</section>
<section class="mb-16 max-w-2xl">
<header class="mb-6">
<h2 class="text-xl font-semibold tracking-tight mb-1">域名服务器</h2>
<p class="text-gray-600">设置您网络中设备可用来解析DNS的域名服务器</p>
</header>
<div class="text-gray-900">
<div v-if="enMagicDNS" class="py-3">
<header class="flex mb-1">
<h4 class="font-medium text-gray-600 mr-2 mb-1">{{ MNetName }}</h4>
<div class="space-x-2 mb-1">
<div
class="inline-flex items-center align-middle justify-center font-medium border border-gray-200 bg-gray-200 text-gray-600 rounded-sm px-1 text-xs relative -top-px"
>
<svg
width="0.9em"
height="0.9em"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="mr-1"
>
<path
d="M6.5 12.5L8.05719 15.9428L11.5 17.5L8.05719 19.0572L6.5 22.5L4.94281 19.0572L1.5 17.5L4.94281 15.9428L6.5 12.5Z"
fill="currentColor"
></path>
<path
d="M15.5 1L17.8358 6.16421L23 8.5L17.8358 10.8358L15.5 16L13.1642 10.8358L8 8.5L13.1642 6.16421L15.5 1Z"
fill="currentColor"
></path>
</svg>
<span>幻域</span>
</div>
</div>
</header>
<div
class="border border-gray-200 bg-white rounded-md divide-y overflow-hidden"
>
<div class="flex justify-between select-none">
<div class="pl-4 flex flex-1 items-start">
<div class="tabular-nums pr-2 py-2 w-full">100.100.100.100</div>
</div>
<div class="p-2 pr-4 flex items-center justify-center">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="text-gray-400"
style="transform: translateX(0.125rem) scale(0.75)"
>
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
</svg>
</div>
</div>
</div>
</div>
<div data-rbd-droppable-id="search-domains" data-rbd-droppable-context-id="0">
<div
v-for="singleDomain in domains"
class="DNSDomainGroup py-3 -mx-3 px-3 rounded-md"
data-rbd-draggable-context-id="0"
data-rbd-draggable-id="abc.com"
>
<header
class="flex items-center mb-1"
tabindex="0"
role="button"
aria-describedby="rbd-hidden-text-0-hidden-text-0"
data-rbd-drag-handle-draggable-id="abc.com"
data-rbd-drag-handle-context-id="0"
draggable="false"
>
<div class="py-1 px-2 -ml-2">
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.8"
stroke-linecap="round"
stroke-linejoin="round"
class="relative -top-px text-gray-400"
>
<circle cx="12" cy="12" r="10"></circle>
<line x1="2" y1="12" x2="22" y2="12"></line>
<path
d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"
></path>
</svg>
</div>
<h4 class="font-medium mb-1 mr-2 text-gray-600">{{ singleDomain }}</h4>
<div class="space-x-2 mb-1">
<span data-state="closed">
<div
class="inline-flex items-center align-middle justify-center font-medium border border-gray-200 bg-gray-200 text-gray-600 rounded-sm px-1 text-xs"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="0.9em"
height="0.9em"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="mr-1"
>
<polyline points="16 3 21 3 21 8"></polyline>
<line x1="4" y1="20" x2="21" y2="3"></line>
<polyline points="21 16 21 21 16 21"></polyline>
<line x1="15" y1="15" x2="21" y2="21"></line>
<line x1="4" y1="4" x2="9" y2="9"></line></svg
>分离 DNS
</div>
</span>
</div>
</header>
<div
class="border border-gray-200 bg-white rounded-md divide-y overflow-hidden"
>
<div
v-for="oneRoute in domainResolvers[singleDomain]"
class="transition-shadow -mb-px flex justify-between select-none"
>
<div class="pl-4 flex flex-1 items-start">
<div class="tabular-nums pr-2 py-2 w-full">{{ oneRoute }}</div>
</div>
<div class="pr-2 pt-1.5">
<button
@click="showNSMenu"
type="button"
id="radix-:r19:"
aria-haspopup="menu"
aria-expanded="false"
data-state="closed"
class="py-0.5 px-2 shadow-none rounded-md border border-gray-300/0 group-hover:border-gray-300/100 hover:border-gray-300/100 group-hover:bg-white hover:!bg-gray-0 group-hover:shadow-md hover:shadow-md hover:cursor-pointer active:border-gray-300/100 active:shadow focus:outline-none focus:ring transition-shadow duration-100 ease-in-out z-50"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-label="Actions"
class="text-gray-500"
>
<circle cx="12" cy="12" r="1"></circle>
<circle cx="19" cy="12" r="1"></circle>
<circle cx="5" cy="12" r="1"></circle>
</svg>
</button>
</div>
</div>
</div>
</div>
</div>
<div class="pt-3">
<header class="flex items-center mb-2">
<h4 class="font-medium text-gray-600 mr-2">全球域名服务器</h4>
<div class="flex items-center space-x-2 ml-auto">
<label
class="flex items-center cursor-pointer text-sm font-medium select-none space-x-1 text-gray-500"
for="fallback"
>
<span
class="tooltip"
data-tip="启用时连接的客户端会忽略本地DNS设置并总使用这些全球域名服务器
禁用时客户端首选本地DNS设置只在需要时使用这些全球服务器"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="relative -top-0.5 inline-block"
>
<circle cx="12" cy="12" r="10"></circle>
<line x1="12" y1="16" x2="12" y2="12"></line>
<line x1="12" y1="8" x2="12.01" y2="8"></line>
</svg>
</span>
<span>覆盖本地 DNS</span>
</label>
<input
@change="switchOverride"
:disabled="!resolvers || resolvers.length == 0"
:checked="enOverride"
id="fallback"
ref="fallback"
type="checkbox"
class="toggle toggle-xs"
/>
</div>
</header>
<div
class="border border-gray-200 bg-white rounded-md divide-y overflow-hidden"
>
<div v-if="!enOverride" class="-mb-px flex justify-between select-none">
<div class="pl-4 flex flex-1 items-start text-gray-400">
<div class="tabular-nums pr-2 py-2 w-full">本地 DNS 设置</div>
</div>
<div class="p-2 pr-4 flex items-center justify-center">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="text-gray-400"
style="transform: translateX(0.125rem) scale(0.75)"
>
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
</svg>
</div>
</div>
<div
v-for="ns in resolvers"
class="transition-shadow -mb-px flex justify-between select-none"
>
<div class="pl-4 flex flex-1 items-start">
<div class="tabular-nums pr-2 py-2 w-full">{{ ns }}</div>
</div>
<div class="pr-2 pt-1.5">
<button
@click="showNSMenu"
type="button"
id="radix-:r26:"
aria-haspopup="menu"
aria-expanded="false"
data-state="closed"
class="py-0.5 px-2 shadow-none rounded-md border border-gray-300/0 group-hover:border-gray-300/100 hover:border-gray-300/100 group-hover:bg-white hover:!bg-gray-0 group-hover:shadow-md hover:shadow-md hover:cursor-pointer active:border-gray-300/100 active:shadow focus:outline-none focus:ring transition-shadow duration-100 ease-in-out z-50"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-label="Actions"
class="text-gray-500"
>
<circle cx="12" cy="12" r="1"></circle>
<circle cx="19" cy="12" r="1"></circle>
<circle cx="5" cy="12" r="1"></circle>
</svg>
</button>
</div>
</div>
</div>
</div>
</div>
<button
ref="addNSBtn"
@click="
AddNameserverShow = true;
useScrollOff(true);
"
class="btn border border-base-300 hover:border-base-300 bg-base-200 hover:bg-base-300 text-black h-9 min-h-fit mt-8"
>
添加域名服务器
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2.2"
stroke-linecap="round"
stroke-linejoin="round"
class="ml-2"
>
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</section>
<!--以下未实现-->
<section v-if="!devmode" class="mb-16 max-w-2xl">
<header class="mb-6">
<h2 class="text-xl font-semibold tracking-tight mb-1">
HTTPS 证书
<div
class="inline-flex items-center align-middle justify-center font-medium border border-yellow-50 bg-yellow-50 text-yellow-600 rounded-full px-2 py-1 leading-none relative text-sm ml-2 -top-px"
>
Unavailable
</div>
</h2>
<p class="text-gray-600">允许用户为他们的设备生辰HTTPS证书</p>
</header>
<button
v-if="true"
class="btn border-0 bg-red-600 hover:bg-red-700 text-white h-9 min-h-fit"
>
停用HTTPS证书
</button>
<button
v-if="false"
class="btn border border-base-300 bg-base-200 hover:bg-base-300 text-black h-9 min-h-fit"
>
启用HTTPS证书
</button>
</section>
</section>
</main>
<!-- 提示框显示 -->
<Teleport to=".toast-container">
<Toast :show="toastShow" :msg="toastMsg" @close="toastShow = false"></Toast>
</Teleport>
<Teleport to="body">
<!-- 停用幻域提示框显示 -->
<template v-if="DisableMagicDNSShow">
<div
@click.self="
DisableMagicDNSShow = false;
useScrollOff(false);
"
class="fixed overflow-y-auto inset-0 py-8 z-30 bg-gray-900 bg-opacity-[0.07]"
style="pointer-events: auto"
>
<div
class="bg-white rounded-lg relative p-4 md:p-6 text-gray-700 max-w-lg min-w-[19rem] my-8 mx-auto w-[97%] shadow-2xl"
style="pointer-events: auto"
>
<header class="flex items-center justify-between space-x-4 mb-5 mr-8">
<div class="font-semibold text-lg truncate">停用幻域</div>
</header>
<form @submit.prevent="switchMagicDNS('doOff')">
<p class="text-gray-700 mb-4">
你网络中的用户将无法继续使用短名称在蜃境中访问设备
</p>
<footer class="flex mt-10 justify-end space-x-4">
<button
@click="
DisableMagicDNSShow = false;
useScrollOff(false);
"
class="btn border border-base-300 hover:border-base-300 bg-base-200 hover:bg-base-300 text-black h-9 min-h-fit"
type="button"
>
取消
</button>
<button
class="btn border-0 bg-red-600 hover:bg-red-700 text-white h-9 min-h-fit"
type="submit"
>
停用幻域
</button>
</footer>
</form>
<button
@click="
DisableMagicDNSShow = false;
useScrollOff(false);
"
class="btn btn-sm btn-ghost absolute top-5 right-5 px-2 py-2 border-0 bg-base-0 focus:bg-base-200 hover:bg-base-200"
type="button"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.25em"
height="1.25em"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
</div>
</template>
<!-- 添加域名服务器菜单显示 -->
<template v-if="AddNameserverShow">
<div
@click.self="
AddNameserverShow = false;
useScrollOff(false);
"
class="fixed overflow-y-auto inset-0 py-8 z-30 bg-opacity-0"
style="pointer-events: auto"
>
<div
class="fixed min-w-max shadow-lg border border-stone-200 rounded-md z-20"
:style="'left: ' + addNSLeft + 'px; top: ' + addNSTop + 'px;'"
>
<div class="dropdown bg-white rounded-md py-1 z-20">
<div
@click="
AddNSShow = true;
AddNameserverShow = false;
"
class="block w-40 px-4 py-2 cursor-pointer hover:bg-stone-100 focus:outline-none focus:bg-stone-100"
>
自定义
</div>
</div>
</div>
</div>
</template>
<!-- 域名服务器操作菜单显示 -->
<template v-if="NSMenuShow">
<div
@click.self="
NSMenuShow = false;
useScrollOff(false);
"
class="fixed overflow-y-auto inset-0 py-8 z-30 bg-opacity-0"
style="pointer-events: auto"
>
<div
class="fixed min-w-max shadow-lg border border-stone-200 rounded-md z-20"
:style="'left: ' + NSMenuLeft + 'px; top: ' + NSMenuTop + 'px;'"
>
<div class="dropdown bg-white rounded-md py-1 z-20">
<div
@click="
EditNSShow = true;
NSMenuShow = false;
"
class="block px-4 py-2 cursor-pointer hover:bg-stone-100 focus:outline-none focus:bg-stone-100"
>
编辑
</div>
<div class="my-1 border-b border-base-300"></div>
<div
@click="removeNS"
class="block px-4 py-2 cursor-pointer hover:bg-stone-100 focus:outline-none focus:bg-stone-100 text-red-400"
>
删除
</div>
</div>
</div>
</div>
</template>
<!-- 添加域名服务器提示框显示 -->
<AddNS
v-if="AddNSShow"
:currentDNS="DNSCfg"
@nameserver-added="newNSAdded"
@close="AddNSShow = false"
></AddNS>
<EditNS
v-if="EditNSShow"
:currentDNS="DNSCfg"
:OriDomain="currentDomain"
:OriResolver="currentResolver"
@nameserver-edited="newNSEdited"
@close="EditNSShow = false"
></EditNS>
<UpdateTCD
v-if="UpdateTCDShow"
:currenttcd="MNetName"
:tcdoffers="TCDOffers"
@refresh-offers="refreshTCDOffers"
@update-tcd="updateTCD"
@close="UpdateTCDShow = false"
></UpdateTCD>
</Teleport>
</template>
<style scoped>
.toggle {
border: 0;
--tglbg: #d6d3d1;
background-color: white;
}
.toggle:checked {
border: 0;
--tglbg: #1e40af;
background-color: white;
}
.toggle:disabled {
--togglehandleborder: 0 0 0 3px white inset,
var(--handleoffsetcalculator) 0 0 3px white inset;
}
.tooltip {
--tooltip-color: #faf9f8;
--tooltip-text-color: #3a3939;
text-align: start;
white-space: normal;
}
.tooltip:before {
max-width: 16rem;
font-size: small;
font-weight: 300;
border-radius: 0.375rem;
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
padding-left: 0.75rem;
padding-right: 0.75rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
border-width: 1px;
border-color: #e1dfde;
}
</style>