ai-chat-ui/src/stores/settings.ts

377 lines
8.8 KiB
TypeScript

import { defineStore } from "pinia";
import { ref } from "vue";
import type { AppSettings, AIModel } from "@/types/chat";
// 分享结果类型
export interface ShareResult {
shareId: string;
shareUrl: string;
password: string;
expiresAt: number;
}
export const useSettingsStore = defineStore("settings", () => {
const MIN_SIDEBAR_WIDTH = 310;
const MAX_SIDEBAR_WIDTH = 400;
// 默认设置
const defaultSettings: AppSettings = {
// 外观设置
theme: "system",
language: "zh-CN",
fontSize: "medium",
// 对话设置
sendOnEnter: true,
showTimestamp: true,
compactMode: false,
// AI 默认设置
defaultModel: "glm-4.6v",
defaultTemperature: 0.7,
defaultMaxTokens: 4096,
defaultSystemPrompt: "你是一个有帮助的 AI 助手。",
// 功能设置
enableSound: true,
enableNotification: true,
autoSaveInterval: 30,
// 隐私设置
saveHistory: true,
shareAnalytics: false,
};
// 可用的 AI 模型
const availableModels: AIModel[] = [
{
id: "glm-4.6",
name: "智普 GLM-4.6",
description: "最强大的模型",
maxTokens: 8192,
provider: "Zhipu",
},
{
id: "glm-4.5",
name: "智普 GLM-4.5",
description: "能力均衡",
maxTokens: 8192,
provider: "Zhipu",
},
{
id: "glm-4-flash",
name: "智普 GLM-4-Flash",
description: "快速高效,适合日常对话",
maxTokens: 8192,
provider: "Zhipu",
},
{
id: "glm-4v-plus",
name: "智普 GLM-4V-Plus",
description: "强大的视觉理解模型",
maxTokens: 8192,
provider: "Zhipu",
},
{
id: "deepseek-chat",
name: "DeepSeek Chat",
description: "DeepSeek 对话模型",
maxTokens: 8192,
provider: "DeepSeek",
},
{
id: "deepseek-reasoner",
name: "DeepSeek Reasoner",
description: "DeepSeek 深度思考模型",
maxTokens: 8192,
provider: "DeepSeek",
},
];
// 状态
const settings = ref<AppSettings>({ ...defaultSettings });
const sidebarCollapsed = ref(false);
const sidebarWidth = ref(MIN_SIDEBAR_WIDTH);
const showShortcutsModal = ref(false);
const showSearchModal = ref(false);
const showSettingsModal = ref(false);
const showConversationSettingsModal = ref(false);
// 分享相关状态
const showShareModal = ref(false);
const showShareResultModal = ref(false);
const shareResult = ref<ShareResult | null>(null);
// 主题相关
function applyTheme(theme: AppSettings["theme"]) {
const root = document.documentElement;
if (theme === "system") {
const prefersDark = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
root.classList.toggle("dark", prefersDark);
} else {
root.classList.toggle("dark", theme === "dark");
}
}
function toggleTheme() {
const themes: AppSettings["theme"][] = ["light", "dark", "system"];
const currentIndex = themes.indexOf(settings.value.theme);
settings.value.theme = themes[(currentIndex + 1) % themes.length];
applyTheme(settings.value.theme);
saveToStorage();
}
function setTheme(theme: AppSettings["theme"]) {
settings.value.theme = theme;
applyTheme(theme);
saveToStorage();
}
// 字体大小
function applyFontSize(size: AppSettings["fontSize"]) {
const root = document.documentElement;
const sizeMap = {
small: "14px",
medium: "16px",
large: "18px",
};
root.style.setProperty("--base-font-size", sizeMap[size]);
}
function setFontSize(size: AppSettings["fontSize"]) {
settings.value.fontSize = size;
applyFontSize(size);
saveToStorage();
}
// 侧边栏
function toggleSidebar() {
sidebarCollapsed.value = !sidebarCollapsed.value;
saveToStorage();
}
function setSidebarWidth(width: number) {
sidebarWidth.value = Math.max(MIN_SIDEBAR_WIDTH, Math.min(MAX_SIDEBAR_WIDTH, width));
saveToStorage();
}
// 模态框
function openShortcutsModal() {
showShortcutsModal.value = true;
}
function closeShortcutsModal() {
showShortcutsModal.value = false;
}
function openSearchModal() {
showSearchModal.value = true;
}
function closeSearchModal() {
showSearchModal.value = false;
}
function openSettingsModal() {
showSettingsModal.value = true;
}
function closeSettingsModal() {
showSettingsModal.value = false;
}
function openConversationSettingsModal() {
showConversationSettingsModal.value = true;
}
function closeConversationSettingsModal() {
showConversationSettingsModal.value = false;
}
// 分享模态框
function openShareModal() {
showShareModal.value = true;
}
function closeShareModal() {
showShareModal.value = false;
}
function openShareResultModal() {
showShareResultModal.value = true;
}
function closeShareResultModal() {
showShareResultModal.value = false;
}
function setShareResult(result: ShareResult) {
shareResult.value = result;
}
function clearShareResult() {
shareResult.value = null;
}
// 更新设置
function updateSettings(updates: Partial<AppSettings>) {
Object.assign(settings.value, updates);
if (updates.theme) {
applyTheme(updates.theme);
}
if (updates.fontSize) {
applyFontSize(updates.fontSize);
}
saveToStorage();
}
// 重置设置
function resetSettings() {
settings.value = { ...defaultSettings };
applyTheme(settings.value.theme);
applyFontSize(settings.value.fontSize);
saveToStorage();
}
// 导出设置
function exportSettings(): string {
return JSON.stringify(settings.value, null, 2);
}
// 导入设置
function importSettings(json: string): boolean {
try {
const imported = JSON.parse(json);
settings.value = { ...defaultSettings, ...imported };
applyTheme(settings.value.theme);
applyFontSize(settings.value.fontSize);
saveToStorage();
return true;
} catch {
return false;
}
}
// 存储
function saveToStorage() {
try {
localStorage.setItem("chat-settings", JSON.stringify(settings.value));
localStorage.setItem(
"chat-sidebar-collapsed",
JSON.stringify(sidebarCollapsed.value),
);
localStorage.setItem(
"chat-sidebar-width",
JSON.stringify(sidebarWidth.value),
);
} catch (e) {
console.error("Failed to save settings:", e);
}
}
// 存储选中模型 ID 的 localStorage key
const MODEL_ID_KEY = "modelSelectId";
// 获取当前选择的模型 ID
function getSelectedModelId(): string {
return defaultSettings.defaultModel;
}
// 设置当前选择的模型 ID
function setSelectedModelId(modelId: string) {
localStorage.setItem(MODEL_ID_KEY, modelId);
// 同时更新 settings 中的 defaultModel
settings.value.defaultModel = modelId;
saveToStorage();
}
function loadFromStorage() {
try {
const stored = localStorage.getItem("chat-settings");
if (stored) {
settings.value = { ...defaultSettings, ...JSON.parse(stored) };
}
const collapsedStored = localStorage.getItem("chat-sidebar-collapsed");
if (collapsedStored) {
sidebarCollapsed.value = JSON.parse(collapsedStored);
}
const widthStored = localStorage.getItem("chat-sidebar-width");
if (widthStored) {
setSidebarWidth(JSON.parse(widthStored));
}
// 应用主题和字体
applyTheme(settings.value.theme);
applyFontSize(settings.value.fontSize);
} catch (e) {
console.error("Failed to load settings:", e);
}
}
// 监听系统主题变化
if (typeof window !== "undefined") {
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
mediaQuery.addEventListener("change", () => {
if (settings.value.theme === "system") {
applyTheme("system");
}
});
}
// 初始化
loadFromStorage();
return {
// 状态
settings,
sidebarCollapsed,
sidebarWidth,
showShortcutsModal,
showSearchModal,
showSettingsModal,
showConversationSettingsModal,
availableModels,
// 分享相关状态
showShareModal,
showShareResultModal,
shareResult,
// 方法
toggleTheme,
setTheme,
setFontSize,
toggleSidebar,
setSidebarWidth,
openShortcutsModal,
closeShortcutsModal,
openSearchModal,
closeSearchModal,
openSettingsModal,
closeSettingsModal,
openConversationSettingsModal,
closeConversationSettingsModal,
// 分享模态框方法
openShareModal,
closeShareModal,
openShareResultModal,
closeShareResultModal,
setShareResult,
clearShareResult,
updateSettings,
resetSettings,
exportSettings,
importSettings,
loadFromStorage,
getSelectedModelId,
setSelectedModelId,
};
});