feat(settings): add debounce to NInputNumber in Memory/Agent/Session settings (#718)
This commit is contained in:
@@ -8,13 +8,32 @@ const settingsStore = useSettingsStore()
|
|||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
async function save(values: Record<string, any>) {
|
// 防抖保存:每个字段独立定时器,300ms 内只发最后一次 HTTP 请求
|
||||||
try {
|
const debounceTimers: Record<string, ReturnType<typeof setTimeout>> = {}
|
||||||
await settingsStore.saveSection('agent', values)
|
|
||||||
|
function save(values: Record<string, any>) {
|
||||||
|
// NSelect 等一次性操作,直接保存,不需要防抖
|
||||||
|
settingsStore.updateLocal('agent', values)
|
||||||
|
settingsStore.saveSection('agent', values).then(() => {
|
||||||
message.success(t('settings.saved'))
|
message.success(t('settings.saved'))
|
||||||
} catch (err: any) {
|
}).catch(() => {
|
||||||
message.error(t('settings.saveFailed'))
|
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>
|
</script>
|
||||||
|
|
||||||
@@ -25,7 +44,7 @@ async function save(values: Record<string, any>) {
|
|||||||
:value="settingsStore.agent.max_turns"
|
:value="settingsStore.agent.max_turns"
|
||||||
:min="1" :max="200" :step="5"
|
:min="1" :max="200" :step="5"
|
||||||
size="small" class="input-sm"
|
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>
|
||||||
<SettingRow :label="t('settings.agent.gatewayTimeout')" :hint="t('settings.agent.gatewayTimeoutHint')">
|
<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"
|
:value="settingsStore.agent.gateway_timeout"
|
||||||
:min="60" :max="7200" :step="60"
|
:min="60" :max="7200" :step="60"
|
||||||
size="small" class="input-sm"
|
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>
|
||||||
<SettingRow :label="t('settings.agent.restartDrainTimeout')" :hint="t('settings.agent.restartDrainTimeoutHint')">
|
<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"
|
:value="settingsStore.agent.restart_drain_timeout"
|
||||||
:min="10" :max="300" :step="10"
|
:min="10" :max="300" :step="10"
|
||||||
size="small" class="input-sm"
|
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>
|
||||||
<SettingRow :label="t('settings.agent.toolEnforcement')" :hint="t('settings.agent.toolEnforcementHint')">
|
<SettingRow :label="t('settings.agent.toolEnforcement')" :hint="t('settings.agent.toolEnforcementHint')">
|
||||||
|
|||||||
@@ -8,13 +8,32 @@ const settingsStore = useSettingsStore()
|
|||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
async function save(values: Record<string, any>) {
|
// 防抖保存:每个字段独立定时器,300ms 内只发最后一次 HTTP 请求
|
||||||
try {
|
const debounceTimers: Record<string, ReturnType<typeof setTimeout>> = {}
|
||||||
await settingsStore.saveSection('memory', values)
|
|
||||||
|
function save(values: Record<string, any>) {
|
||||||
|
// Switch 等一次性操作,直接保存,不需要防抖
|
||||||
|
settingsStore.updateLocal('memory', values)
|
||||||
|
settingsStore.saveSection('memory', values).then(() => {
|
||||||
message.success(t('settings.saved'))
|
message.success(t('settings.saved'))
|
||||||
} catch (err: any) {
|
}).catch(() => {
|
||||||
message.error(t('settings.saveFailed'))
|
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>
|
</script>
|
||||||
|
|
||||||
@@ -31,7 +50,7 @@ async function save(values: Record<string, any>) {
|
|||||||
:value="settingsStore.memory.memory_char_limit"
|
:value="settingsStore.memory.memory_char_limit"
|
||||||
:min="100" :max="10000" :step="100"
|
:min="100" :max="10000" :step="100"
|
||||||
size="small" class="input-sm"
|
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>
|
||||||
<SettingRow :label="t('settings.memory.userCharLimit')" :hint="t('settings.memory.userCharLimitHint')">
|
<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"
|
:value="settingsStore.memory.user_char_limit"
|
||||||
:min="100" :max="10000" :step="100"
|
:min="100" :max="10000" :step="100"
|
||||||
size="small" class="input-sm"
|
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>
|
</SettingRow>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -10,13 +10,32 @@ const sessionBrowserPrefsStore = useSessionBrowserPrefsStore();
|
|||||||
const message = useMessage();
|
const message = useMessage();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
async function save(values: Record<string, any>) {
|
// 防抖保存:每个字段独立定时器,300ms 内只发最后一次 HTTP 请求
|
||||||
try {
|
const debounceTimers: Record<string, ReturnType<typeof setTimeout>> = {};
|
||||||
await settingsStore.saveSection("session_reset", values);
|
|
||||||
|
function save(values: Record<string, any>) {
|
||||||
|
// NSelect/NSwitch 等一次性操作,直接保存,不需要防抖
|
||||||
|
settingsStore.updateLocal('session_reset', values)
|
||||||
|
settingsStore.saveSection('session_reset', values).then(() => {
|
||||||
message.success(t("settings.saved"));
|
message.success(t("settings.saved"));
|
||||||
} catch (err: any) {
|
}).catch(() => {
|
||||||
message.error(t("settings.saveFailed"));
|
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) {
|
async function toggleRequireAuth(value: boolean) {
|
||||||
@@ -64,7 +83,7 @@ async function toggleRequireAuth(value: boolean) {
|
|||||||
:step="30"
|
:step="30"
|
||||||
size="small"
|
size="small"
|
||||||
class="input-sm"
|
class="input-sm"
|
||||||
@update:value="(v) => v != null && save({ idle_minutes: v })"
|
@update:value="(v) => v != null && debouncedSave('idle_minutes', v)"
|
||||||
/>
|
/>
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
@@ -78,7 +97,7 @@ async function toggleRequireAuth(value: boolean) {
|
|||||||
:step="1"
|
:step="1"
|
||||||
size="small"
|
size="small"
|
||||||
class="input-sm"
|
class="input-sm"
|
||||||
@update:value="(v) => v != null && save({ at_hour: v })"
|
@update:value="(v) => v != null && debouncedSave('at_hour', v)"
|
||||||
/>
|
/>
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
|
|||||||
@@ -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>) {
|
async function saveSection(section: string, values: Record<string, any>) {
|
||||||
saving.value = true
|
saving.value = true
|
||||||
try {
|
try {
|
||||||
@@ -91,6 +120,6 @@ export const useSettingsStore = defineStore('settings', () => {
|
|||||||
loading, saving,
|
loading, saving,
|
||||||
display, agent, memory, sessionReset, privacy, approvals,
|
display, agent, memory, sessionReset, privacy, approvals,
|
||||||
telegram, discord, slack, whatsapp, matrix, wecom, feishu, dingtalk, weixin, platforms,
|
telegram, discord, slack, whatsapp, matrix, wecom, feishu, dingtalk, weixin, platforms,
|
||||||
fetchSettings, saveSection,
|
fetchSettings, saveSection, updateLocal,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user