diff --git a/frontend/src/pages/xray/DnsTab.vue b/frontend/src/pages/xray/DnsTab.vue
index 8deae677..e1be1912 100644
--- a/frontend/src/pages/xray/DnsTab.vue
+++ b/frontend/src/pages/xray/DnsTab.vue
@@ -22,6 +22,14 @@ const props = defineProps({
const STRATEGIES = ['UseSystem', 'UseIP', 'UseIPv4', 'UseIPv6'];
+const dnsFieldOmit = Object.freeze(Object.create(null));
+
+function dnsValueEmptyForOmit(v) {
+ if (v === undefined || v === null) return true;
+ if (typeof v === 'string') return v.trim() === '';
+ return false;
+}
+
const enableDNS = computed({
get: () => !!props.templateSettings?.dns,
set: (next) => {
@@ -29,7 +37,6 @@ const enableDNS = computed({
if (next) {
props.templateSettings.dns = {
tag: 'dns_inbound',
- clientIp: '',
queryStrategy: 'UseIP',
disableCache: false,
disableFallback: false,
@@ -50,16 +57,30 @@ const enableDNS = computed({
});
function dnsField(field, fallback) {
+ const omitWhenUnset = fallback === dnsFieldOmit;
return computed({
- get: () => props.templateSettings?.dns?.[field] ?? fallback,
+ get: () => {
+ const raw = props.templateSettings?.dns?.[field];
+ if (fallback === dnsFieldOmit) return raw ?? '';
+ return raw ?? fallback;
+ },
set: (v) => {
- if (props.templateSettings?.dns) props.templateSettings.dns[field] = v;
+ if (!props.templateSettings?.dns) return;
+ if (omitWhenUnset) {
+ if (dnsValueEmptyForOmit(v)) {
+ if (field in props.templateSettings.dns) delete props.templateSettings.dns[field];
+ } else {
+ props.templateSettings.dns[field] = v;
+ }
+ } else {
+ props.templateSettings.dns[field] = v;
+ }
},
});
}
const dnsTag = dnsField('tag', 'dns_inbound');
-const dnsClientIp = dnsField('clientIp', '');
+const dnsClientIp = dnsField('clientIp', dnsFieldOmit);
const dnsStrategy = dnsField('queryStrategy', 'UseIP');
const dnsDisableCache = dnsField('disableCache', false);
const dnsDisableFallback = dnsField('disableFallback', false);
diff --git a/frontend/src/pages/xray/OutboundFormModal.vue b/frontend/src/pages/xray/OutboundFormModal.vue
index 155ff86f..4310b067 100644
--- a/frontend/src/pages/xray/OutboundFormModal.vue
+++ b/frontend/src/pages/xray/OutboundFormModal.vue
@@ -34,7 +34,6 @@ const props = defineProps({
open: { type: Boolean, default: false },
outbound: { type: Object, default: null },
existingTags: { type: Array, default: () => [] },
- inboundTags: { type: Array, default: () => [] },
});
const emit = defineEmits(['update:open', 'confirm']);
@@ -318,10 +317,8 @@ function regenerateWgKeys() {
-
+
diff --git a/frontend/src/pages/xray/OutboundsTab.vue b/frontend/src/pages/xray/OutboundsTab.vue
index 11f3b898..71139a2f 100644
--- a/frontend/src/pages/xray/OutboundsTab.vue
+++ b/frontend/src/pages/xray/OutboundsTab.vue
@@ -35,15 +35,6 @@ const props = defineProps({
isMobile: { type: Boolean, default: false },
});
-const inboundTagOptions = computed(() => {
- const out = new Set();
- for (const ib of props.templateSettings?.inbounds || []) {
- if (ib.tag) out.add(ib.tag);
- }
- for (const t of props.inboundTags || []) out.add(t);
- return [...out];
-});
-
const emit = defineEmits(['reset-traffic', 'test', 'test-all', 'show-warp', 'show-nord', 'delete']);
const testMode = ref('tcp');
@@ -443,7 +434,7 @@ const rows = computed(() => {
+ @confirm="onConfirm" />
diff --git a/frontend/src/pages/xray/RoutingTab.vue b/frontend/src/pages/xray/RoutingTab.vue
index 27ae41d3..e7ce5344 100644
--- a/frontend/src/pages/xray/RoutingTab.vue
+++ b/frontend/src/pages/xray/RoutingTab.vue
@@ -65,18 +65,32 @@ const editingRule = ref(null);
const editingIndex = ref(null);
const inboundTagOptions = computed(() => {
- const out = new Set();
+ const seen = new Set();
+ const out = [];
+
+ function pushUnique(tag) {
+ if (!tag) return;
+ if (seen.has(tag)) return;
+ seen.add(tag);
+ out.push(tag);
+ }
+
for (const ib of props.templateSettings?.inbounds || []) {
- if (ib.tag) out.add(ib.tag);
+ pushUnique(ib.tag);
+ }
+ for (const t of props.inboundTags || []) {
+ pushUnique(t);
}
- for (const t of props.inboundTags || []) out.add(t);
for (const ob of props.templateSettings?.outbounds || []) {
- const rt = ob?.reverse?.tag || ob?.settings?.reverse?.tag;
- if (rt) out.add(rt);
+ const rt = ob?.reverse?.tag || ob?.settings?.reverse?.tag || ob?.settings?.inboundTag;
+ pushUnique(rt);
}
- // dnsTag if DNS is configured.
- const dt = props.templateSettings?.dns?.tag;
- if (dt) out.add(dt);
+ pushUnique(props.templateSettings?.dns?.tag);
+
+ for (const s of props.templateSettings?.dns?.servers || []) {
+ if (typeof s === 'object' && s?.tag) pushUnique(s.tag);
+ }
+
return [...out];
});