diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index f56c012e..cbe00f2c 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -1,5 +1,19 @@
diff --git a/frontend/src/api/settings.ts b/frontend/src/api/settings.ts
new file mode 100644
index 00000000..c4ee6a17
--- /dev/null
+++ b/frontend/src/api/settings.ts
@@ -0,0 +1,18 @@
+import { api } from './http'
+
+// /api/settings 是一个自由 key-value 对象(theme/language/各开关/端口/webFetchBackend/updateUrl…)。
+// GET 返裸 settings 对象;PUT 浅合并传入的 partial,返 {success, settings(合并后), webFetchSyncWarning?}。
+export type Settings = Record
+
+export const getSettings = () => api('GET', '/api/settings')
+
+export async function saveSettings(
+ partial: Settings,
+): Promise<{ settings: Settings; webFetchSyncWarning?: string }> {
+ const data = await api<{ settings?: Settings; webFetchSyncWarning?: string }>(
+ 'PUT',
+ '/api/settings',
+ partial,
+ )
+ return { settings: data.settings || {}, webFetchSyncWarning: data.webFetchSyncWarning }
+}
diff --git a/frontend/src/pages/SettingsPage.vue b/frontend/src/pages/SettingsPage.vue
index b63b4395..0e2db3e7 100644
--- a/frontend/src/pages/SettingsPage.vue
+++ b/frontend/src/pages/SettingsPage.vue
@@ -1,14 +1,65 @@
+
+
diff --git a/frontend/src/stores/settings.ts b/frontend/src/stores/settings.ts
new file mode 100644
index 00000000..4fd4d426
--- /dev/null
+++ b/frontend/src/stores/settings.ts
@@ -0,0 +1,46 @@
+import { defineStore } from 'pinia'
+import { ref } from 'vue'
+import * as settingsApi from '@/api/settings'
+import type { Settings } from '@/api/settings'
+
+export const useSettingsStore = defineStore('settings', () => {
+ const settings = ref({})
+ const loaded = ref(false)
+
+ async function load() {
+ settings.value = await settingsApi.getSettings()
+ loaded.value = true
+ return settings.value
+ }
+
+ // PUT partial(浅合并)→ 后端返合并后 settings;返回可选 webFetchSyncWarning 供 UI toast。
+ // 乐观更新(开关即时响应)+ 失败回滚(防 UI 与服务端不一致)。
+ async function save(partial: Settings): Promise {
+ const prev = { ...settings.value }
+ settings.value = { ...settings.value, ...partial }
+ try {
+ const { settings: merged, webFetchSyncWarning } = await settingsApi.saveSettings(partial)
+ settings.value = merged
+ return webFetchSyncWarning
+ } catch (e) {
+ settings.value = prev
+ throw e
+ }
+ }
+
+ // 带默认值的 typed getter(旧 app.js renderSettings 的 `!== false` / `=== true` 默认语义)
+ function bool(key: string, def: boolean): boolean {
+ const v = settings.value[key]
+ return typeof v === 'boolean' ? v : def
+ }
+ function str(key: string, def = ''): string {
+ const v = settings.value[key]
+ return typeof v === 'string' ? v : def
+ }
+ function num(key: string, def = 0): number {
+ const v = settings.value[key]
+ return typeof v === 'number' ? v : def
+ }
+
+ return { settings, loaded, load, save, bool, str, num }
+})