feat(settings): add debounce to NInputNumber in Memory/Agent/Session settings (#718)

This commit is contained in:
memeflyfly
2026-05-14 15:47:17 +08:00
committed by GitHub
parent e6f403b787
commit bb83ac7d9e
4 changed files with 109 additions and 23 deletions
@@ -8,13 +8,32 @@ const settingsStore = useSettingsStore()
const message = useMessage()
const { t } = useI18n()
async function save(values: Record<string, any>) {
try {
await settingsStore.saveSection('agent', values)
// 防抖保存:每个字段独立定时器,300ms 内只发最后一次 HTTP 请求
const debounceTimers: Record<string, ReturnType<typeof setTimeout>> = {}
function save(values: Record<string, any>) {
// NSelect 等一次性操作,直接保存,不需要防抖
settingsStore.updateLocal('agent', values)
settingsStore.saveSection('agent', values).then(() => {
message.success(t('settings.saved'))
} catch (err: any) {
}).catch(() => {
message.error(t('settings.saveFailed'))
}
})
}
function debouncedSave(key: string, value: any) {
// 先立即更新本地 store(UI 即时响应)
settingsStore.updateLocal('agent', { [key]: value })
// 再防抖发 HTTP 保存
if (debounceTimers[key]) clearTimeout(debounceTimers[key])
debounceTimers[key] = setTimeout(async () => {
try {
await settingsStore.saveSection('agent', { [key]: value })
message.success(t('settings.saved'))
} catch (err: any) {
message.error(t('settings.saveFailed'))
}
}, 300)
}
</script>
@@ -25,7 +44,7 @@ async function save(values: Record<string, any>) {
:value="settingsStore.agent.max_turns"
:min="1" :max="200" :step="5"
size="small" class="input-sm"
@update:value="v => v != null && save({ max_turns: v })"
@update:value="v => v != null && debouncedSave('max_turns', v)"
/>
</SettingRow>
<SettingRow :label="t('settings.agent.gatewayTimeout')" :hint="t('settings.agent.gatewayTimeoutHint')">
@@ -33,7 +52,7 @@ async function save(values: Record<string, any>) {
:value="settingsStore.agent.gateway_timeout"
:min="60" :max="7200" :step="60"
size="small" class="input-sm"
@update:value="v => v != null && save({ gateway_timeout: v })"
@update:value="v => v != null && debouncedSave('gateway_timeout', v)"
/>
</SettingRow>
<SettingRow :label="t('settings.agent.restartDrainTimeout')" :hint="t('settings.agent.restartDrainTimeoutHint')">
@@ -41,7 +60,7 @@ async function save(values: Record<string, any>) {
:value="settingsStore.agent.restart_drain_timeout"
:min="10" :max="300" :step="10"
size="small" class="input-sm"
@update:value="v => v != null && save({ restart_drain_timeout: v })"
@update:value="v => v != null && debouncedSave('restart_drain_timeout', v)"
/>
</SettingRow>
<SettingRow :label="t('settings.agent.toolEnforcement')" :hint="t('settings.agent.toolEnforcementHint')">
@@ -8,13 +8,32 @@ const settingsStore = useSettingsStore()
const message = useMessage()
const { t } = useI18n()
async function save(values: Record<string, any>) {
try {
await settingsStore.saveSection('memory', values)
// 防抖保存:每个字段独立定时器,300ms 内只发最后一次 HTTP 请求
const debounceTimers: Record<string, ReturnType<typeof setTimeout>> = {}
function save(values: Record<string, any>) {
// Switch 等一次性操作,直接保存,不需要防抖
settingsStore.updateLocal('memory', values)
settingsStore.saveSection('memory', values).then(() => {
message.success(t('settings.saved'))
} catch (err: any) {
}).catch(() => {
message.error(t('settings.saveFailed'))
}
})
}
function debouncedSave(key: string, value: any) {
// 先立即更新本地 store(UI 即时响应)
settingsStore.updateLocal('memory', { [key]: value })
// 再防抖发 HTTP 保存
if (debounceTimers[key]) clearTimeout(debounceTimers[key])
debounceTimers[key] = setTimeout(async () => {
try {
await settingsStore.saveSection('memory', { [key]: value })
message.success(t('settings.saved'))
} catch (err: any) {
message.error(t('settings.saveFailed'))
}
}, 300)
}
</script>
@@ -31,7 +50,7 @@ async function save(values: Record<string, any>) {
:value="settingsStore.memory.memory_char_limit"
:min="100" :max="10000" :step="100"
size="small" class="input-sm"
@update:value="v => v != null && save({ memory_char_limit: v })"
@update:value="v => v != null && debouncedSave('memory_char_limit', v)"
/>
</SettingRow>
<SettingRow :label="t('settings.memory.userCharLimit')" :hint="t('settings.memory.userCharLimitHint')">
@@ -39,7 +58,7 @@ async function save(values: Record<string, any>) {
:value="settingsStore.memory.user_char_limit"
:min="100" :max="10000" :step="100"
size="small" class="input-sm"
@update:value="v => v != null && save({ user_char_limit: v })"
@update:value="v => v != null && debouncedSave('user_char_limit', v)"
/>
</SettingRow>
</section>
@@ -10,13 +10,32 @@ const sessionBrowserPrefsStore = useSessionBrowserPrefsStore();
const message = useMessage();
const { t } = useI18n();
async function save(values: Record<string, any>) {
try {
await settingsStore.saveSection("session_reset", values);
// 防抖保存:每个字段独立定时器,300ms 内只发最后一次 HTTP 请求
const debounceTimers: Record<string, ReturnType<typeof setTimeout>> = {};
function save(values: Record<string, any>) {
// NSelect/NSwitch 等一次性操作,直接保存,不需要防抖
settingsStore.updateLocal('session_reset', values)
settingsStore.saveSection('session_reset', values).then(() => {
message.success(t("settings.saved"));
} catch (err: any) {
}).catch(() => {
message.error(t("settings.saveFailed"));
}
});
}
function debouncedSave(key: string, value: any) {
// 先立即更新本地 store(UI 即时响应)
settingsStore.updateLocal('session_reset', { [key]: value });
// 再防抖发 HTTP 保存
if (debounceTimers[key]) clearTimeout(debounceTimers[key])
debounceTimers[key] = setTimeout(async () => {
try {
await settingsStore.saveSection('session_reset', { [key]: value });
message.success(t("settings.saved"));
} catch (err: any) {
message.error(t("settings.saveFailed"));
}
}, 300);
}
async function toggleRequireAuth(value: boolean) {
@@ -64,7 +83,7 @@ async function toggleRequireAuth(value: boolean) {
:step="30"
size="small"
class="input-sm"
@update:value="(v) => v != null && save({ idle_minutes: v })"
@update:value="(v) => v != null && debouncedSave('idle_minutes', v)"
/>
</SettingRow>
<SettingRow
@@ -78,7 +97,7 @@ async function toggleRequireAuth(value: boolean) {
:step="1"
size="small"
class="input-sm"
@update:value="(v) => v != null && save({ at_hour: v })"
@update:value="(v) => v != null && debouncedSave('at_hour', v)"
/>
</SettingRow>
<SettingRow
+30 -1
View File
@@ -51,6 +51,35 @@ export const useSettingsStore = defineStore('settings', () => {
}
}
function updateLocal(section: string, values: Record<string, any>) {
switch (section) {
case 'display': display.value = { ...display.value, ...values }; break
case 'agent': agent.value = { ...agent.value, ...values }; break
case 'memory': memory.value = { ...memory.value, ...values }; break
case 'session_reset': sessionReset.value = { ...sessionReset.value, ...values }; break
case 'privacy': privacy.value = { ...privacy.value, ...values }; break
case 'approvals': approvals.value = { ...approvals.value, ...values }; break
case 'telegram': telegram.value = { ...telegram.value, ...values }; break
case 'discord': discord.value = { ...discord.value, ...values }; break
case 'slack': slack.value = { ...slack.value, ...values }; break
case 'whatsapp': whatsapp.value = { ...whatsapp.value, ...values }; break
case 'matrix': matrix.value = { ...matrix.value, ...values }; break
case 'wecom': wecom.value = { ...wecom.value, ...values }; break
case 'feishu': feishu.value = { ...feishu.value, ...values }; break
case 'dingtalk': dingtalk.value = { ...dingtalk.value, ...values }; break
case 'weixin': weixin.value = { ...weixin.value, ...values }; break
case 'platforms': {
for (const [key, val] of Object.entries(values)) {
platforms.value = {
...platforms.value,
[key]: { ...(platforms.value[key] || {}), ...(val as Record<string, any>) },
}
}
break
}
}
}
async function saveSection(section: string, values: Record<string, any>) {
saving.value = true
try {
@@ -91,6 +120,6 @@ export const useSettingsStore = defineStore('settings', () => {
loading, saving,
display, agent, memory, sessionReset, privacy, approvals,
telegram, discord, slack, whatsapp, matrix, wecom, feishu, dingtalk, weixin, platforms,
fetchSettings, saveSection,
fetchSettings, saveSection, updateLocal,
}
})