mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-11 15:16:07 +00:00
fix(xray): align DNS outbound to spec and repair item-list rules UI
DNS outbound now mirrors xray-core's documented shape: rewriteNetwork / rewriteAddress / rewritePort / userLevel replace the legacy network / address / port keys, and unset values are dropped on the wire. Old configs are still accepted on read so saved configs migrate cleanly. While there, fix two latent bugs in repeat-item editors (DNS rules, Freedom noise, WireGuard peers): - The "+" buttons pushed plain objects into arrays of class instances, so toJson() crashed on the next read and the JSON tab silently went blank. Push proper class instances instead. - Each item heading lived outside any a-form-item, so the delete icon ignored the form's column grid and slumped left. Wrap the heading in a form-item with the standard offset wrapper-col and switch the flex to space-between so the icon sits at the right of the input column, in line with the fields below it.
This commit is contained in:
@@ -268,21 +268,23 @@ function regenerateWgKeys() {
|
||||
|
||||
<a-form-item label="Noises">
|
||||
<a-switch :checked="(outbound.settings.noises || []).length > 0"
|
||||
@change="(checked) => outbound.settings.noises = checked ? [{ type: 'rand', packet: '10-20', delay: '10-16', applyTo: 'ip' }] : []" />
|
||||
@change="(checked) => outbound.settings.noises = checked ? [new Outbound.FreedomSettings.Noise()] : []" />
|
||||
<a-button v-if="outbound.settings.noises && outbound.settings.noises.length > 0" size="small"
|
||||
type="primary" class="ml-8"
|
||||
@click="outbound.settings.noises.push({ type: 'rand', packet: '10-20', delay: '10-16', applyTo: 'ip' })">
|
||||
@click="outbound.settings.noises.push(new Outbound.FreedomSettings.Noise())">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
<template v-for="(noise, index) in outbound.settings.noises || []" :key="index">
|
||||
<div class="item-heading">
|
||||
<span>Noise {{ index + 1 }}</span>
|
||||
<DeleteOutlined v-if="outbound.settings.noises.length > 1" class="danger-icon"
|
||||
@click="outbound.settings.noises.splice(index, 1)" />
|
||||
</div>
|
||||
<a-form-item :wrapper-col="{ md: { span: 14, offset: 8 } }" :colon="false">
|
||||
<div class="item-heading">
|
||||
<span>Noise {{ index + 1 }}</span>
|
||||
<DeleteOutlined v-if="outbound.settings.noises.length > 1" class="danger-icon"
|
||||
@click="outbound.settings.noises.splice(index, 1)" />
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="Type">
|
||||
<a-select v-model:value="noise.type">
|
||||
<a-select-option v-for="x in ['rand', 'base64', 'str', 'hex']" :key="x" :value="x">{{ x
|
||||
@@ -325,24 +327,36 @@ function regenerateWgKeys() {
|
||||
|
||||
<!-- ============== DNS ============== -->
|
||||
<template v-if="isDNS">
|
||||
<a-form-item :label="t('pages.inbounds.network')">
|
||||
<a-select v-model:value="outbound.settings.network">
|
||||
<a-form-item label="Rewrite network">
|
||||
<a-select v-model:value="outbound.settings.rewriteNetwork" allow-clear placeholder="(unchanged)">
|
||||
<a-select-option v-for="x in ['udp', 'tcp']" :key="x" :value="x">{{ x }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="Rewrite address">
|
||||
<a-input v-model:value="outbound.settings.rewriteAddress" placeholder="(unchanged) e.g. 1.1.1.1" />
|
||||
</a-form-item>
|
||||
<a-form-item label="Rewrite port">
|
||||
<a-input-number v-model:value="outbound.settings.rewritePort" :min="0" :max="65535"
|
||||
:style="{ width: '100%' }" placeholder="(unchanged)" />
|
||||
</a-form-item>
|
||||
<a-form-item label="User level">
|
||||
<a-input-number v-model:value="outbound.settings.userLevel" :min="0" :style="{ width: '100%' }" />
|
||||
</a-form-item>
|
||||
<a-form-item label="Rules">
|
||||
<a-button size="small" type="primary"
|
||||
@click="outbound.settings.rules.push({ action: 'direct', qtype: '', domain: '' })">
|
||||
@click="outbound.settings.rules.push(new Outbound.DNSRule())">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
<template v-for="(rule, index) in outbound.settings.rules || []" :key="index">
|
||||
<div class="item-heading">
|
||||
<span>Rule {{ index + 1 }}</span>
|
||||
<DeleteOutlined class="danger-icon" @click="outbound.settings.rules.splice(index, 1)" />
|
||||
</div>
|
||||
<a-form-item :wrapper-col="{ md: { span: 14, offset: 8 } }" :colon="false">
|
||||
<div class="item-heading">
|
||||
<span>Rule {{ index + 1 }}</span>
|
||||
<DeleteOutlined class="danger-icon" @click="outbound.settings.rules.splice(index, 1)" />
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="Action">
|
||||
<a-select v-model:value="rule.action">
|
||||
<a-select-option v-for="a in DNSRuleActions" :key="a" :value="a">{{ a }}</a-select-option>
|
||||
@@ -393,18 +407,20 @@ function regenerateWgKeys() {
|
||||
</a-form-item>
|
||||
<a-form-item label="Peers">
|
||||
<a-button size="small" type="primary"
|
||||
@click="outbound.settings.peers.push({ endpoint: '', publicKey: '', psk: '', allowedIPs: [''], keepAlive: 0 })">
|
||||
@click="outbound.settings.peers.push(new Outbound.WireguardSettings.Peer())">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
<template v-for="(peer, index) in outbound.settings.peers || []" :key="index">
|
||||
<div class="item-heading">
|
||||
<span>Peer {{ index + 1 }}</span>
|
||||
<DeleteOutlined v-if="outbound.settings.peers.length > 1" class="danger-icon"
|
||||
@click="outbound.settings.peers.splice(index, 1)" />
|
||||
</div>
|
||||
<a-form-item :wrapper-col="{ md: { span: 14, offset: 8 } }" :colon="false">
|
||||
<div class="item-heading">
|
||||
<span>Peer {{ index + 1 }}</span>
|
||||
<DeleteOutlined v-if="outbound.settings.peers.length > 1" class="danger-icon"
|
||||
@click="outbound.settings.peers.splice(index, 1)" />
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="Endpoint">
|
||||
<a-input v-model:value="peer.endpoint" />
|
||||
</a-form-item>
|
||||
@@ -993,9 +1009,9 @@ function regenerateWgKeys() {
|
||||
.item-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
font-weight: 500;
|
||||
margin: 8px 0 4px;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
|
||||
@@ -128,8 +128,11 @@ function outboundAddresses(o) {
|
||||
case Protocols.Trojan:
|
||||
serverObj = o.settings?.servers;
|
||||
break;
|
||||
case Protocols.DNS:
|
||||
return [`${o.settings?.address || ''}:${o.settings?.port || ''}`];
|
||||
case Protocols.DNS: {
|
||||
const addr = o.settings?.rewriteAddress || o.settings?.address || '';
|
||||
const port = o.settings?.rewritePort || o.settings?.port || '';
|
||||
return addr || port ? [`${addr}:${port}`] : [];
|
||||
}
|
||||
case Protocols.Wireguard:
|
||||
return (o.settings?.peers || []).map((p) => p.endpoint);
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user