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
+16 -66
View File
@@ -220,16 +220,8 @@ const gradId = `spkGrad-${Math.random().toString(36).slice(2, 9)}`;
</script>
<template>
<svg
ref="svgRef"
width="100%"
:height="height"
:viewBox="viewBoxAttr"
preserveAspectRatio="none"
class="sparkline-svg"
@mousemove="onMouseMove"
@mouseleave="onMouseLeave"
>
<svg ref="svgRef" width="100%" :height="height" :viewBox="viewBoxAttr" preserveAspectRatio="none"
class="sparkline-svg" @mousemove="onMouseMove" @mouseleave="onMouseLeave">
<defs>
<linearGradient :id="gradId" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" :stop-color="stroke" :stop-opacity="fillOpacity" />
@@ -238,70 +230,28 @@ const gradId = `spkGrad-${Math.random().toString(36).slice(2, 9)}`;
</defs>
<g v-if="showGrid">
<line
v-for="(g, i) in gridLines"
:key="i"
:x1="g.x1" :y1="g.y1" :x2="g.x2" :y2="g.y2"
:stroke="gridColor" stroke-width="1"
class="cpu-grid-line"
/>
<line v-for="(g, i) in gridLines" :key="i" :x1="g.x1" :y1="g.y1" :x2="g.x2" :y2="g.y2" :stroke="gridColor"
stroke-width="1" class="cpu-grid-line" />
</g>
<g v-if="showAxes">
<text
v-for="(t, i) in yTicks"
:key="'y' + i"
class="cpu-grid-y-text"
:x="Math.max(0, paddingLeft - 4)"
:y="t.y + 4"
text-anchor="end"
font-size="10"
>{{ t.label }}</text>
<text
v-for="(t, i) in xTicks"
:key="'x' + i"
class="cpu-grid-x-text"
:x="t.x"
:y="paddingTop + drawHeight + 14"
text-anchor="middle"
font-size="10"
>{{ t.label }}</text>
<text v-for="(t, i) in yTicks" :key="'y' + i" class="cpu-grid-y-text" :x="Math.max(0, paddingLeft - 4)"
:y="t.y + 4" text-anchor="end" font-size="10">{{ t.label }}</text>
<text v-for="(t, i) in xTicks" :key="'x' + i" class="cpu-grid-x-text" :x="t.x" :y="paddingTop + drawHeight + 14"
text-anchor="middle" font-size="10">{{ t.label }}</text>
</g>
<path v-if="areaPath" :d="areaPath" :fill="`url(#${gradId})`" stroke="none" />
<polyline
:points="pointsStr"
fill="none"
:stroke="stroke"
:stroke-width="strokeWidth"
stroke-linecap="round"
stroke-linejoin="round"
/>
<circle
v-if="showMarker && lastPoint"
:cx="lastPoint[0]" :cy="lastPoint[1]"
:r="markerRadius"
:fill="stroke"
/>
<polyline :points="pointsStr" fill="none" :stroke="stroke" :stroke-width="strokeWidth" stroke-linecap="round"
stroke-linejoin="round" />
<circle v-if="showMarker && lastPoint" :cx="lastPoint[0]" :cy="lastPoint[1]" :r="markerRadius" :fill="stroke" />
<g v-if="showTooltip && hoverIdx >= 0 && pointsArr[hoverIdx]">
<line
class="cpu-grid-h-line"
:x1="pointsArr[hoverIdx][0]" :x2="pointsArr[hoverIdx][0]"
:y1="paddingTop" :y2="paddingTop + drawHeight"
stroke="rgba(0,0,0,0.2)" stroke-width="1"
/>
<circle
:cx="pointsArr[hoverIdx][0]" :cy="pointsArr[hoverIdx][1]"
r="3.5" :fill="stroke"
/>
<text
class="cpu-grid-text"
:x="pointsArr[hoverIdx][0]"
:y="paddingTop + 12"
text-anchor="middle"
font-size="11"
>{{ fmtHoverText() }}</text>
<line class="cpu-grid-h-line" :x1="pointsArr[hoverIdx][0]" :x2="pointsArr[hoverIdx][0]" :y1="paddingTop"
:y2="paddingTop + drawHeight" stroke="rgba(0,0,0,0.2)" stroke-width="1" />
<circle :cx="pointsArr[hoverIdx][0]" :cy="pointsArr[hoverIdx][1]" r="3.5" :fill="stroke" />
<text class="cpu-grid-text" :x="pointsArr[hoverIdx][0]" :y="paddingTop + 12" text-anchor="middle"
font-size="11">{{ fmtHoverText() }}</text>
</g>
</svg>
</template>