优化: 设置域体验完善
- 校验失败红框定位字段,保存反馈改持久化成功后 - 数值越界钳制,双提示队列化不再重叠 - 搜索防抖跳分类,托盘气泡文案进多语言
This commit is contained in:
@@ -6,20 +6,21 @@
|
||||
</div>
|
||||
<div class="general-settings">
|
||||
<SettingRow ref="rowTheme" :label="$t('settings.labelTheme')" :desc="$t('settings.descTheme')">
|
||||
<select v-model="settings.theme" class="setting-select" @change="markSaved('theme')">
|
||||
<!-- 走查 P3-11:不再 @change 即显「已保存」,反馈移到 persist 完成后(防假成功) -->
|
||||
<select v-model="settings.theme" class="setting-select">
|
||||
<option value="dark">{{ $t('settings.themeDark') }}</option>
|
||||
<option value="light">{{ $t('settings.themeLight') }}</option>
|
||||
<option value="system">{{ $t('settings.themeSystem') }}</option>
|
||||
</select>
|
||||
</SettingRow>
|
||||
<SettingRow ref="rowLanguage" :label="$t('settings.labelLanguage')" :desc="$t('settings.descLanguage')">
|
||||
<select v-model="settings.language" class="setting-select" @change="markSaved('language')">
|
||||
<select v-model="settings.language" class="setting-select">
|
||||
<option value="zh-CN">{{ $t('settings.aiLanguageZh') }}</option>
|
||||
<option value="en">{{ $t('settings.aiLanguageEn') }}</option>
|
||||
</select>
|
||||
</SettingRow>
|
||||
<SettingRow ref="rowAiLanguage" :label="$t('settings.labelAiLanguage')" :desc="$t('settings.descAiLanguage')">
|
||||
<select v-model="settings.aiLanguage" class="setting-select" @change="markSaved('aiLanguage')">
|
||||
<select v-model="settings.aiLanguage" class="setting-select">
|
||||
<option value="auto">{{ $t('settings.aiLanguageAuto') }}</option>
|
||||
<option value="zh-CN">{{ $t('settings.aiLanguageZh') }}</option>
|
||||
<option value="en">{{ $t('settings.aiLanguageEn') }}</option>
|
||||
@@ -27,13 +28,13 @@
|
||||
</SettingRow>
|
||||
<SettingRow ref="rowToken" :label="$t('settings.labelShowTokenUsage')" :desc="$t('settings.descShowTokenUsage')">
|
||||
<label class="toggle">
|
||||
<input type="checkbox" v-model="settings.showTokenUsage" @change="markSaved('token')" />
|
||||
<input type="checkbox" v-model="settings.showTokenUsage" />
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</SettingRow>
|
||||
<SettingRow ref="rowStreamingMd" :label="$t('settings.labelStreamingMd')" :desc="$t('settings.descStreamingMd')">
|
||||
<label class="toggle">
|
||||
<input type="checkbox" v-model="settings.streamingMd" @change="markSaved('streamingMd')" />
|
||||
<input type="checkbox" v-model="settings.streamingMd" />
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</SettingRow>
|
||||
@@ -91,32 +92,42 @@ const rowLanguage = useTemplateRef<InstanceType<typeof SettingRow>>('rowLanguage
|
||||
const rowAiLanguage = useTemplateRef<InstanceType<typeof SettingRow>>('rowAiLanguage')
|
||||
const rowToken = useTemplateRef<InstanceType<typeof SettingRow>>('rowToken')
|
||||
const rowStreamingMd = useTemplateRef<InstanceType<typeof SettingRow>>('rowStreamingMd')
|
||||
function markSaved(key: 'theme' | 'language' | 'aiLanguage' | 'token' | 'streamingMd') {
|
||||
const map = { theme: rowTheme.value, language: rowLanguage.value, aiLanguage: rowAiLanguage.value, token: rowToken.value, streamingMd: rowStreamingMd.value }
|
||||
map[key]?.markSaved()
|
||||
|
||||
// 走查 P3-11 假成功族:原 @change 立即 markSaved,先于持久化完成,失败无人知晓。
|
||||
// 改为 set 完成后才点亮「已保存」,失败点亮行内红字。注:appSettings.set 当前对落库
|
||||
// 失败仅 console 内吞(stores/appSettings.ts 降级内存态设计),catch 实际不会触发;
|
||||
// 待 store 层把失败上抛后本处失败通道即自动生效(登记项,见批次报告)。
|
||||
async function persist(key: string, value: unknown, row: { value: { markSaved: () => void; markFailed: () => void } | null }) {
|
||||
try {
|
||||
await appSettings.set(key, value)
|
||||
row.value?.markSaved()
|
||||
} catch (e) {
|
||||
console.error(`保存设置 ${key} 失败:`, e)
|
||||
row.value?.markFailed()
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => settings.theme, (val) => {
|
||||
applyTheme(val)
|
||||
void appSettings.set('df-theme', val)
|
||||
void persist('df-theme', val, rowTheme)
|
||||
})
|
||||
|
||||
watch(() => settings.aiLanguage, (val) => {
|
||||
void appSettings.set('df-ai-language', val)
|
||||
void persist('df-ai-language', val, rowAiLanguage)
|
||||
})
|
||||
|
||||
watch(() => settings.showTokenUsage, (val) => {
|
||||
void appSettings.set('df-show-token-usage', val)
|
||||
void persist('df-show-token-usage', val, rowToken)
|
||||
})
|
||||
|
||||
watch(() => settings.streamingMd, (val) => {
|
||||
void appSettings.set('df-ai-streaming-md', val)
|
||||
void persist('df-ai-streaming-md', val, rowStreamingMd)
|
||||
})
|
||||
|
||||
watch(() => settings.language, (val) => {
|
||||
void appSettings.set('df-language', val)
|
||||
// 同步 i18n 实例,让界面立即跟随语言切换
|
||||
locale.value = val as 'zh-CN' | 'en'
|
||||
void persist('df-language', val, rowLanguage)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
Reference in New Issue
Block a user