mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-20 11:36:06 +00:00
feat(xray/dns): align DNS settings with Xray docs + UI polish
- DNS server modal: rename expectIPs -> expectedIPs (per docs); add per-server tag, clientIP, serveStale, serveExpiredTTL, timeoutMs; flip skipFallback default to false; hydration still accepts legacy expectIPs for back-compat. - DNS tab: add hosts editor (domain -> IP/array), serveStale + serveExpiredTTL controls, "Use Preset" button bringing back the legacy preset gallery (Google / Cloudflare / AdGuard + Family variants — fixed AdGuard Family IPs that were wrong in legacy), and a "Delete All" button to wipe the server list at once. - i18n: add 15 new dns.* keys across all 13 locales. - Frontend-wide formatter pass on Vue components (whitespace and attribute layout only, no behavior changes). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -66,27 +66,23 @@ function newNoiseItem() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-form
|
||||
v-if="showTcp || showUdp || showQuic"
|
||||
:colon="false"
|
||||
:label-col="{ md: { span: 8 } }"
|
||||
:wrapper-col="{ md: { span: 14 } }"
|
||||
>
|
||||
<a-form v-if="showTcp || showUdp || showQuic" :colon="false" :label-col="{ md: { span: 8 } }"
|
||||
:wrapper-col="{ md: { span: 14 } }">
|
||||
<!-- ============================== TCP MASKS ============================== -->
|
||||
<template v-if="showTcp">
|
||||
<a-form-item label="TCP Masks">
|
||||
<a-button type="primary" size="small" @click="stream.addTcpMask('fragment')">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
|
||||
<template v-for="(mask, mIdx) in (stream.finalmask.tcp || [])" :key="`tcp-${mIdx}`">
|
||||
<a-divider :style="{ margin: '0' }">
|
||||
TCP Mask {{ mIdx + 1 }}
|
||||
<DeleteOutlined
|
||||
:style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="stream.delTcpMask(mIdx)"
|
||||
/>
|
||||
<DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="stream.delTcpMask(mIdx)" />
|
||||
</a-divider>
|
||||
|
||||
<a-form-item label="Type">
|
||||
@@ -144,16 +140,16 @@ function newNoiseItem() {
|
||||
<!-- Clients -->
|
||||
<a-form-item label="Clients">
|
||||
<a-button type="primary" size="small" @click="mask.settings.clients.push([newClientServerItem()])">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
<template v-for="(group, gi) in mask.settings.clients" :key="`tcp-cg-${mIdx}-${gi}`">
|
||||
<a-divider :style="{ margin: '0' }">
|
||||
Clients Group {{ gi + 1 }}
|
||||
<DeleteOutlined
|
||||
:style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="mask.settings.clients.splice(gi, 1)"
|
||||
/>
|
||||
<DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="mask.settings.clients.splice(gi, 1)" />
|
||||
</a-divider>
|
||||
<template v-for="(item, ii) in group" :key="`tcp-ci-${mIdx}-${gi}-${ii}`">
|
||||
<a-form-item label="Type">
|
||||
@@ -177,13 +173,12 @@ function newNoiseItem() {
|
||||
</template>
|
||||
<a-form-item v-else label="Packet">
|
||||
<a-input-group v-if="item.type === 'base64'" compact>
|
||||
<a-input
|
||||
v-model:value="item.packet"
|
||||
placeholder="binary data"
|
||||
:style="{ width: 'calc(100% - 32px)' }"
|
||||
/>
|
||||
<a-input v-model:value="item.packet" placeholder="binary data"
|
||||
:style="{ width: 'calc(100% - 32px)' }" />
|
||||
<a-button @click="item.packet = RandomUtil.randomBase64()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
<template #icon>
|
||||
<ReloadOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-input-group>
|
||||
<a-input v-else v-model:value="item.packet" placeholder="binary data" />
|
||||
@@ -194,16 +189,16 @@ function newNoiseItem() {
|
||||
<!-- Servers -->
|
||||
<a-form-item label="Servers">
|
||||
<a-button type="primary" size="small" @click="mask.settings.servers.push([newClientServerItem()])">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
<template v-for="(group, gi) in mask.settings.servers" :key="`tcp-sg-${mIdx}-${gi}`">
|
||||
<a-divider :style="{ margin: '0' }">
|
||||
Servers Group {{ gi + 1 }}
|
||||
<DeleteOutlined
|
||||
:style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="mask.settings.servers.splice(gi, 1)"
|
||||
/>
|
||||
<DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="mask.settings.servers.splice(gi, 1)" />
|
||||
</a-divider>
|
||||
<template v-for="(item, ii) in group" :key="`tcp-si-${mIdx}-${gi}-${ii}`">
|
||||
<a-form-item label="Type">
|
||||
@@ -227,13 +222,12 @@ function newNoiseItem() {
|
||||
</template>
|
||||
<a-form-item v-else label="Packet">
|
||||
<a-input-group v-if="item.type === 'base64'" compact>
|
||||
<a-input
|
||||
v-model:value="item.packet"
|
||||
placeholder="binary data"
|
||||
:style="{ width: 'calc(100% - 32px)' }"
|
||||
/>
|
||||
<a-input v-model:value="item.packet" placeholder="binary data"
|
||||
:style="{ width: 'calc(100% - 32px)' }" />
|
||||
<a-button @click="item.packet = RandomUtil.randomBase64()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
<template #icon>
|
||||
<ReloadOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-input-group>
|
||||
<a-input v-else v-model:value="item.packet" placeholder="binary data" />
|
||||
@@ -248,17 +242,17 @@ function newNoiseItem() {
|
||||
<template v-if="showUdp">
|
||||
<a-form-item label="UDP Masks">
|
||||
<a-button type="primary" size="small" @click="addUdpMaskWithDefault">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
|
||||
<template v-for="(mask, mIdx) in (stream.finalmask.udp || [])" :key="`udp-${mIdx}`">
|
||||
<a-divider :style="{ margin: '0' }">
|
||||
UDP Mask {{ mIdx + 1 }}
|
||||
<DeleteOutlined
|
||||
:style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="stream.delUdpMask(mIdx)"
|
||||
/>
|
||||
<DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="stream.delUdpMask(mIdx)" />
|
||||
</a-divider>
|
||||
|
||||
<a-form-item label="Type">
|
||||
@@ -290,13 +284,8 @@ function newNoiseItem() {
|
||||
<a-input v-model:value="mask.settings.domain" placeholder="e.g., www.example.com" />
|
||||
</a-form-item>
|
||||
<a-form-item v-if="mask.type === 'xdns'" label="Domains">
|
||||
<a-select
|
||||
v-model:value="mask.settings.domains"
|
||||
mode="tags"
|
||||
:style="{ width: '100%' }"
|
||||
:token-separators="[',']"
|
||||
placeholder="e.g., www.example.com"
|
||||
/>
|
||||
<a-select v-model:value="mask.settings.domains" mode="tags" :style="{ width: '100%' }"
|
||||
:token-separators="[',']" placeholder="e.g., www.example.com" />
|
||||
</a-form-item>
|
||||
|
||||
<!-- Noise -->
|
||||
@@ -306,16 +295,16 @@ function newNoiseItem() {
|
||||
</a-form-item>
|
||||
<a-form-item label="Noise">
|
||||
<a-button type="primary" size="small" @click="mask.settings.noise.push(newNoiseItem())">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
<template v-for="(n, ni) in mask.settings.noise" :key="`udp-noise-${mIdx}-${ni}`">
|
||||
<a-divider :style="{ margin: '0' }">
|
||||
Noise {{ ni + 1 }}
|
||||
<DeleteOutlined
|
||||
:style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="mask.settings.noise.splice(ni, 1)"
|
||||
/>
|
||||
<DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="mask.settings.noise.splice(ni, 1)" />
|
||||
</a-divider>
|
||||
<a-form-item label="Type">
|
||||
<a-select :value="n.type" @change="(t) => changeItemType(n, t)">
|
||||
@@ -335,13 +324,11 @@ function newNoiseItem() {
|
||||
</template>
|
||||
<a-form-item v-else label="Packet">
|
||||
<a-input-group v-if="n.type === 'base64'" compact>
|
||||
<a-input
|
||||
v-model:value="n.packet"
|
||||
placeholder="binary data"
|
||||
:style="{ width: 'calc(100% - 32px)' }"
|
||||
/>
|
||||
<a-input v-model:value="n.packet" placeholder="binary data" :style="{ width: 'calc(100% - 32px)' }" />
|
||||
<a-button @click="n.packet = RandomUtil.randomBase64()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
<template #icon>
|
||||
<ReloadOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-input-group>
|
||||
<a-input v-else v-model:value="n.packet" placeholder="binary data" />
|
||||
@@ -356,16 +343,16 @@ function newNoiseItem() {
|
||||
<template v-if="mask.type === 'header-custom'">
|
||||
<a-form-item label="Client">
|
||||
<a-button type="primary" size="small" @click="mask.settings.client.push(newUdpClientServerItem())">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
<template v-for="(c, ci) in mask.settings.client" :key="`udp-c-${mIdx}-${ci}`">
|
||||
<a-divider :style="{ margin: '0' }">
|
||||
Client {{ ci + 1 }}
|
||||
<DeleteOutlined
|
||||
:style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="mask.settings.client.splice(ci, 1)"
|
||||
/>
|
||||
<DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="mask.settings.client.splice(ci, 1)" />
|
||||
</a-divider>
|
||||
<a-form-item label="Type">
|
||||
<a-select :value="c.type" @change="(t) => changeItemType(c, t)">
|
||||
@@ -385,13 +372,11 @@ function newNoiseItem() {
|
||||
</template>
|
||||
<a-form-item v-else label="Packet">
|
||||
<a-input-group v-if="c.type === 'base64'" compact>
|
||||
<a-input
|
||||
v-model:value="c.packet"
|
||||
placeholder="binary data"
|
||||
:style="{ width: 'calc(100% - 32px)' }"
|
||||
/>
|
||||
<a-input v-model:value="c.packet" placeholder="binary data" :style="{ width: 'calc(100% - 32px)' }" />
|
||||
<a-button @click="c.packet = RandomUtil.randomBase64()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
<template #icon>
|
||||
<ReloadOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-input-group>
|
||||
<a-input v-else v-model:value="c.packet" placeholder="binary data" />
|
||||
@@ -401,16 +386,16 @@ function newNoiseItem() {
|
||||
<a-divider :style="{ margin: '0' }" />
|
||||
<a-form-item label="Server">
|
||||
<a-button type="primary" size="small" @click="mask.settings.server.push(newUdpClientServerItem())">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
<template v-for="(s, si) in mask.settings.server" :key="`udp-s-${mIdx}-${si}`">
|
||||
<a-divider :style="{ margin: '0' }">
|
||||
Server {{ si + 1 }}
|
||||
<DeleteOutlined
|
||||
:style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="mask.settings.server.splice(si, 1)"
|
||||
/>
|
||||
<DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
|
||||
@click="mask.settings.server.splice(si, 1)" />
|
||||
</a-divider>
|
||||
<a-form-item label="Type">
|
||||
<a-select :value="s.type" @change="(t) => changeItemType(s, t)">
|
||||
@@ -430,13 +415,11 @@ function newNoiseItem() {
|
||||
</template>
|
||||
<a-form-item v-else label="Packet">
|
||||
<a-input-group v-if="s.type === 'base64'" compact>
|
||||
<a-input
|
||||
v-model:value="s.packet"
|
||||
placeholder="binary data"
|
||||
:style="{ width: 'calc(100% - 32px)' }"
|
||||
/>
|
||||
<a-input v-model:value="s.packet" placeholder="binary data" :style="{ width: 'calc(100% - 32px)' }" />
|
||||
<a-button @click="s.packet = RandomUtil.randomBase64()">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
<template #icon>
|
||||
<ReloadOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-input-group>
|
||||
<a-input v-else v-model:value="s.packet" placeholder="binary data" />
|
||||
@@ -502,39 +485,24 @@ function newNoiseItem() {
|
||||
<a-switch v-model:checked="stream.finalmask.quicParams.disablePathMTUDiscovery" />
|
||||
</a-form-item>
|
||||
<a-form-item label="Max Incoming Streams">
|
||||
<a-input-number
|
||||
v-model:value="stream.finalmask.quicParams.maxIncomingStreams"
|
||||
:min="8"
|
||||
placeholder="1024 = default"
|
||||
/>
|
||||
<a-input-number v-model:value="stream.finalmask.quicParams.maxIncomingStreams" :min="8"
|
||||
placeholder="1024 = default" />
|
||||
</a-form-item>
|
||||
<a-form-item label="Init Stream Window">
|
||||
<a-input-number
|
||||
v-model:value="stream.finalmask.quicParams.initStreamReceiveWindow"
|
||||
:min="16384"
|
||||
placeholder="8388608 = default"
|
||||
/>
|
||||
<a-input-number v-model:value="stream.finalmask.quicParams.initStreamReceiveWindow" :min="16384"
|
||||
placeholder="8388608 = default" />
|
||||
</a-form-item>
|
||||
<a-form-item label="Max Stream Window">
|
||||
<a-input-number
|
||||
v-model:value="stream.finalmask.quicParams.maxStreamReceiveWindow"
|
||||
:min="16384"
|
||||
placeholder="8388608 = default"
|
||||
/>
|
||||
<a-input-number v-model:value="stream.finalmask.quicParams.maxStreamReceiveWindow" :min="16384"
|
||||
placeholder="8388608 = default" />
|
||||
</a-form-item>
|
||||
<a-form-item label="Init Conn Window">
|
||||
<a-input-number
|
||||
v-model:value="stream.finalmask.quicParams.initConnectionReceiveWindow"
|
||||
:min="16384"
|
||||
placeholder="20971520 = default"
|
||||
/>
|
||||
<a-input-number v-model:value="stream.finalmask.quicParams.initConnectionReceiveWindow" :min="16384"
|
||||
placeholder="20971520 = default" />
|
||||
</a-form-item>
|
||||
<a-form-item label="Max Conn Window">
|
||||
<a-input-number
|
||||
v-model:value="stream.finalmask.quicParams.maxConnectionReceiveWindow"
|
||||
:min="16384"
|
||||
placeholder="20971520 = default"
|
||||
/>
|
||||
<a-input-number v-model:value="stream.finalmask.quicParams.maxConnectionReceiveWindow" :min="16384"
|
||||
placeholder="20971520 = default" />
|
||||
</a-form-item>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user