377 lines
8.8 KiB
TypeScript
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,
|
|
};
|
|
});
|