mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-05-13 09:36:05 +00:00
- 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>
52 lines
1.7 KiB
Vue
52 lines
1.7 KiB
Vue
<script setup>
|
|
import { ref, watch } from 'vue';
|
|
|
|
// Generic prompt modal — used by features like "import inbound" that
|
|
// need a free-form text/textarea input and a confirm callback. The
|
|
// parent owns the action; this component only surfaces the value via
|
|
// the `confirm` event when the user clicks OK.
|
|
|
|
const props = defineProps({
|
|
open: { type: Boolean, default: false },
|
|
title: { type: String, default: '' },
|
|
okText: { type: String, default: 'OK' },
|
|
// 'text' = single-line input; 'textarea' = multi-line.
|
|
type: { type: String, default: 'text', validator: (v) => ['text', 'textarea'].includes(v) },
|
|
initialValue: { type: String, default: '' },
|
|
loading: { type: Boolean, default: false },
|
|
});
|
|
|
|
const emit = defineEmits(['update:open', 'confirm']);
|
|
|
|
const value = ref('');
|
|
|
|
watch(() => props.open, (next) => {
|
|
if (next) value.value = props.initialValue;
|
|
});
|
|
|
|
function close() { emit('update:open', false); }
|
|
function ok() { emit('confirm', value.value); }
|
|
|
|
// Enter submits when single-line; ctrl+S submits in textarea mode
|
|
// (matches legacy keybindings).
|
|
function onKeydown(e) {
|
|
if (props.type !== 'textarea' && e.key === 'Enter') {
|
|
e.preventDefault();
|
|
ok();
|
|
return;
|
|
}
|
|
if (props.type === 'textarea' && e.ctrlKey && e.key.toLowerCase() === 's') {
|
|
e.preventDefault();
|
|
ok();
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<a-modal :open="open" :title="title" :ok-text="okText" cancel-text="Cancel" :mask-closable="false"
|
|
:confirm-loading="loading" @ok="ok" @cancel="close">
|
|
<a-textarea v-if="type === 'textarea'" v-model:value="value" :auto-size="{ minRows: 10, maxRows: 20 }" autofocus
|
|
@keydown="onKeydown" />
|
|
<a-input v-else v-model:value="value" autofocus @keydown="onKeydown" />
|
|
</a-modal>
|
|
</template>
|