Files
sub-store/frontend/src/pages/Settings.vue
T

117 lines
4.4 KiB
Vue

<template>
<div>
<h2 class="text-xl font-bold mb-5">设置</h2>
<div v-if="loading" class="text-gray-400 text-sm">加载中...</div>
<div v-else class="space-y-4">
<!-- General settings -->
<div class="bg-white rounded-lg p-4 shadow-sm border">
<h3 class="font-semibold mb-3 text-sm">通用</h3>
<div class="space-y-3">
<div>
<label class="block text-sm mb-1">默认 User-Agent</label>
<input v-model="settings.defaultUserAgent" class="w-full px-3 py-2 border rounded-lg text-sm" />
</div>
<div>
<label class="block text-sm mb-1">默认流量查询 User-Agent</label>
<input v-model="settings.defaultFlowUserAgent" class="w-full px-3 py-2 border rounded-lg text-sm" />
</div>
<div>
<label class="block text-sm mb-1">请求超时 (ms)</label>
<input v-model="settings.defaultTimeout" class="w-full px-3 py-2 border rounded-lg text-sm" />
</div>
<div>
<label class="block text-sm mb-1">后端并发数</label>
<input v-model="settings.backendRequestConcurrency" class="w-full px-3 py-2 border rounded-lg text-sm" />
</div>
<div>
<label class="block text-sm mb-1">远程缓存 TTL (秒)</label>
<input v-model="settings.remoteCacheTtl" class="w-full px-3 py-2 border rounded-lg text-sm" />
</div>
<div class="flex items-center gap-2">
<input type="checkbox" id="cache-stale" v-model="settings.remoteCacheStaleOnError" class="rounded" />
<label for="cache-stale" class="text-sm">缓存过期时仍返回旧数据</label>
</div>
</div>
</div>
<!-- Node info API -->
<div class="bg-white rounded-lg p-4 shadow-sm border">
<h3 class="font-semibold mb-3 text-sm">节点信息 API</h3>
<input v-model="settings.nodeInfoApiUrl" placeholder="https://ipwho.is/{ip}"
class="w-full px-3 py-2 border rounded-lg text-sm font-mono" />
<p class="text-xs text-gray-400 mt-1">URL 中 {ip} 会被替换为查询的 IP</p>
</div>
<!-- Theme -->
<div class="bg-white rounded-lg p-4 shadow-sm border">
<h3 class="font-semibold mb-3 text-sm">主题</h3>
<div class="flex items-center gap-2 mb-2">
<input type="checkbox" id="theme-auto" v-model="settings.theme.auto" class="rounded" />
<label for="theme-auto" class="text-sm">自动跟随系统</label>
</div>
<div class="grid grid-cols-2 gap-2">
<div>
<label class="text-xs text-gray-500">亮色主题</label>
<input v-model="settings.theme.light" class="w-full px-3 py-2 border rounded-lg text-sm" />
</div>
<div>
<label class="text-xs text-gray-500">暗色主题</label>
<input v-model="settings.theme.dark" class="w-full px-3 py-2 border rounded-lg text-sm" />
</div>
</div>
</div>
<!-- App name -->
<div class="bg-white rounded-lg p-4 shadow-sm border">
<h3 class="font-semibold mb-3 text-sm">应用</h3>
<div>
<label class="block text-sm mb-1">应用名称</label>
<input v-model="settings.appName" class="w-full px-3 py-2 border rounded-lg text-sm" />
</div>
</div>
<button class="px-4 py-2 bg-primary-600 text-white rounded-lg text-sm hover:bg-primary-700" @click="save">保存设置</button>
</div>
<div v-if="toast" class="fixed bottom-4 right-4 px-4 py-2 rounded-lg shadow-lg text-sm z-50"
:class="toast.type === 'error' ? 'bg-red-500 text-white' : 'bg-green-500 text-white'">
{{ toast.msg }}
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { getSettings, updateSettings } from '@/api'
const settings = ref(null)
const loading = ref(true)
const toast = ref(null)
function showToast(msg, type = 'success') {
toast.value = { msg, type }
setTimeout(() => toast.value = null, 2500)
}
async function save() {
try {
await updateSettings(settings.value)
showToast('设置已保存')
} catch (e) {
showToast(e.message, 'error')
}
}
onMounted(async () => {
try {
const res = await getSettings()
settings.value = res.data
} catch (e) {
showToast(e.message, 'error')
} finally {
loading.value = false
}
})
</script>