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:
MHSanaei
2026-05-10 17:03:11 +02:00
parent 8e7d215b4a
commit a96612f595
50 changed files with 1203 additions and 886 deletions
+7 -28
View File
@@ -111,17 +111,8 @@ async function onSave() {
</script>
<template>
<a-modal
:open="open"
:title="title"
:confirm-loading="submitting"
:ok-text="t('save')"
:cancel-text="t('cancel')"
:mask-closable="false"
width="640px"
@ok="onSave"
@cancel="close"
>
<a-modal :open="open" :title="title" :confirm-loading="submitting" :ok-text="t('save')" :cancel-text="t('cancel')"
:mask-closable="false" width="640px" @ok="onSave" @cancel="close">
<a-form layout="vertical" :model="form">
<a-row :gutter="16">
<a-col :span="12">
@@ -171,10 +162,7 @@ async function onSave() {
</a-row>
<a-form-item :label="t('pages.nodes.apiToken')" required>
<a-input-password
v-model:value="form.apiToken"
:placeholder="t('pages.nodes.apiTokenPlaceholder')"
/>
<a-input-password v-model:value="form.apiToken" :placeholder="t('pages.nodes.apiTokenPlaceholder')" />
<div class="hint">{{ t('pages.nodes.apiTokenHint') }}</div>
</a-form-item>
@@ -183,20 +171,11 @@ async function onSave() {
{{ t('pages.nodes.testConnection') }}
</a-button>
<div v-if="testResult" class="test-result">
<a-alert
v-if="testResult.status === 'online'"
type="success"
show-icon
<a-alert v-if="testResult.status === 'online'" type="success" show-icon
:message="t('pages.nodes.connectionOk', { ms: testResult.latencyMs })"
:description="testResult.xrayVersion ? `Xray ${testResult.xrayVersion}` : undefined"
/>
<a-alert
v-else
type="error"
show-icon
:message="t('pages.nodes.connectionFailed')"
:description="testResult.error"
/>
:description="testResult.xrayVersion ? `Xray ${testResult.xrayVersion}` : undefined" />
<a-alert v-else type="error" show-icon :message="t('pages.nodes.connectionFailed')"
:description="testResult.error" />
</div>
</div>
</a-form>