mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-07 13:44:24 +00:00
Brings Balancers to full parity with the legacy panel and adds a
DNS tab placeholder that exposes the full dns/fakedns trees as JSON
so users can edit them without falling through to Advanced.
- BalancerFormModal.vue: tag (with duplicate-tag warning across
other balancers), strategy (random/roundRobin/leastLoad/leastPing),
selector tag-mode multi-select sourced from existing outbound
tags + free-form additions, fallback. Disable-on-invalid is
driven by the duplicateTag + emptySelector computed flags.
- BalancersTab.vue: empty state with a single "Add balancer" CTA;
populated state shows the legacy 4-column table (action / tag /
strategy / selector / fallback) with per-row edit + delete in a
dropdown. On submit the wire shape preserves the
`strategy: { type }` nesting only when the strategy is non-default,
matching the legacy emit. Tag renames also chase across
routing.rules.balancerTag references so existing rules don't dangle.
- DnsTab.vue: master enable switch + raw JSON for `dns` and
`fakedns`. Legacy had a dedicated server-by-server editor + a
fakedns row editor; both are big enough to deserve their own
commits, and the JSON path supports every field today.
WARP / NordVPN provisioning modals still toast as "coming soon" —
those are third-party API integrations worth their own commits.
The xray page now has structured editors for Basics / Routing /
Outbounds / Balancers and JSON editors for DNS / Advanced — every
xray tab the legacy panel offered is functional.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
111 lines
3.1 KiB
Vue
111 lines
3.1 KiB
Vue
<script setup>
|
|
import { computed } from 'vue';
|
|
|
|
// Compact DNS editor — a master enable switch plus a JSON textarea
|
|
// for the full dns + fakedns trees. The legacy panel had a
|
|
// dedicated DNS-server modal + fakedns row editor; both are large
|
|
// enough to deserve their own commits. For now this gives users a
|
|
// working path to edit DNS settings without leaving the structured
|
|
// page.
|
|
|
|
const props = defineProps({
|
|
templateSettings: { type: Object, default: null },
|
|
});
|
|
|
|
const enableDns = computed({
|
|
get: () => !!props.templateSettings?.dns,
|
|
set: (next) => {
|
|
if (!props.templateSettings) return;
|
|
if (next) {
|
|
props.templateSettings.dns = {
|
|
servers: [],
|
|
queryStrategy: 'UseIP',
|
|
tag: 'dns_inbound',
|
|
enableParallelQuery: false,
|
|
};
|
|
props.templateSettings.fakedns = null;
|
|
} else {
|
|
delete props.templateSettings.dns;
|
|
delete props.templateSettings.fakedns;
|
|
}
|
|
},
|
|
});
|
|
|
|
const dnsJson = computed({
|
|
get: () => {
|
|
if (!props.templateSettings?.dns) return '';
|
|
try { return JSON.stringify(props.templateSettings.dns, null, 2); }
|
|
catch (_e) { return ''; }
|
|
},
|
|
set: (next) => {
|
|
if (!props.templateSettings) return;
|
|
try {
|
|
const parsed = next.trim() ? JSON.parse(next) : null;
|
|
props.templateSettings.dns = parsed;
|
|
} catch (_e) {
|
|
// wait for valid JSON — leaves the previous value untouched
|
|
}
|
|
},
|
|
});
|
|
|
|
const fakednsJson = computed({
|
|
get: () => {
|
|
if (!props.templateSettings?.fakedns) return '';
|
|
try { return JSON.stringify(props.templateSettings.fakedns, null, 2); }
|
|
catch (_e) { return ''; }
|
|
},
|
|
set: (next) => {
|
|
if (!props.templateSettings) return;
|
|
try {
|
|
const parsed = next.trim() ? JSON.parse(next) : null;
|
|
if (parsed) props.templateSettings.fakedns = parsed;
|
|
else delete props.templateSettings.fakedns;
|
|
} catch (_e) { /* wait for valid JSON */ }
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<a-space direction="vertical" size="middle" :style="{ width: '100%' }">
|
|
<a-form layout="vertical">
|
|
<a-form-item label="Enable DNS">
|
|
<a-switch v-model:checked="enableDns" />
|
|
</a-form-item>
|
|
|
|
<template v-if="enableDns">
|
|
<a-alert
|
|
type="info"
|
|
show-icon
|
|
message="The full DNS tree is editable here. A dedicated server-by-server editor is coming in a future commit."
|
|
class="mb-12"
|
|
/>
|
|
<a-form-item label="dns (JSON)">
|
|
<a-textarea
|
|
v-model:value="dnsJson"
|
|
:auto-size="{ minRows: 12, maxRows: 28 }"
|
|
spellcheck="false"
|
|
class="json-editor"
|
|
/>
|
|
</a-form-item>
|
|
|
|
<a-form-item label="fakedns (JSON, optional)">
|
|
<a-textarea
|
|
v-model:value="fakednsJson"
|
|
:auto-size="{ minRows: 6, maxRows: 18 }"
|
|
spellcheck="false"
|
|
class="json-editor"
|
|
placeholder="Leave empty to omit fakedns."
|
|
/>
|
|
</a-form-item>
|
|
</template>
|
|
</a-form>
|
|
</a-space>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.mb-12 { margin-bottom: 12px; }
|
|
.json-editor {
|
|
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
font-size: 12px;
|
|
}
|
|
</style>
|