1
0
mirror of https://github.com/ZeroCatDev/Classworks.git synced 2025-07-05 02:59:23 +00:00
This commit is contained in:
SunWuyuan 2025-03-15 09:11:11 +08:00
parent 9bb3f06ba1
commit c6b6bd2ce5
No known key found for this signature in database
GPG Key ID: A6A54CF66F56BB64
8 changed files with 211 additions and 204 deletions

View File

@ -77,4 +77,4 @@ This project is built with [Vuetify](https://vuetifyjs.com/en/), a UI Library wi
[MIT](http://opensource.org/licenses/MIT) [MIT](http://opensource.org/licenses/MIT)
Copyright (c) 2016-present Vuetify, LLC Copyright (c) 2016-present Vuetify, LLC
# homeworkpage-frontend # classworks-frontend

View File

@ -1,5 +1,5 @@
{ {
"name": "HomeworkPage", "name": "ClassworkS",
"private": true, "private": true,
"type": "module", "type": "module",
"version": "0.0.0", "version": "0.0.0",

View File

@ -23,11 +23,11 @@
<a <a
class="text-decoration-none on-surface" class="text-decoration-none on-surface"
href="https://github.com/sunwuyuan/homeworkpage-frontend" href="https://github.com/sunwuyuan/classworks-frontend"
rel="noopener noreferrer" rel="noopener noreferrer"
target="_blank" target="_blank"
> >
HomeworkPage ClassworkS
</a> </a>
</div> </div>
</v-footer> </v-footer>
@ -48,7 +48,7 @@
{ {
title: 'GitHub', title: 'GitHub',
icon: 'mdi-github', icon: 'mdi-github',
href: 'https://github.com/sunwuyuan/homeworkpage-frontend', href: 'https://github.com/sunwuyuan/classworks-frontend',
} }
] ]
</script> </script>

View File

@ -17,7 +17,7 @@
/> />
</v-avatar> </v-avatar>
<h2 class="text-h5 mb-2">HomeworkPage</h2> <h2 class="text-h5 mb-2">ClassworkS</h2>
<p class="text-body-1 mb-4"> <p class="text-body-1 mb-4">
<a <a
href="https://github.com/sunwuyuan" href="https://github.com/sunwuyuan"
@ -30,7 +30,7 @@
<v-btn <v-btn
color="primary" color="primary"
variant="outlined" variant="outlined"
href="https://github.com/SunWuyuan/homeworkpage-frontend" href="https://github.com/SunWuyuan/classworks-frontend"
target="_blank" target="_blank"
prepend-icon="mdi-github" prepend-icon="mdi-github"
> >
@ -39,7 +39,7 @@
<v-btn <v-btn
color="primary" color="primary"
variant="outlined" variant="outlined"
href="https://github.com/SunWuyuan/homeworkpage-backend" href="https://github.com/SunWuyuan/classworks-backend"
target="_blank" target="_blank"
prepend-icon="mdi-github" prepend-icon="mdi-github"
> >
@ -48,7 +48,7 @@
<v-btn <v-btn
color="primary" color="primary"
variant="outlined" variant="outlined"
href="https://github.com/SunWuyuan/homeworkpage-backend/issues" href="https://github.com/SunWuyuan/classworks-backend/issues"
target="_blank" target="_blank"
prepend-icon="mdi-bug" prepend-icon="mdi-bug"
> >

View File

@ -589,7 +589,7 @@ export default {
this.provider, this.provider,
this.dataKey, this.dataKey,
this.state.boardData, this.state.boardData,
this.state.dateString this.state.dateString // dateString
); );
if (!response.success) { if (!response.success) {
@ -937,7 +937,7 @@ export default {
async saveAttendance() { async saveAttendance() {
try { try {
await this.uploadData(); await this.uploadData(); // 使
this.state.attendanceDialog = false; this.state.attendanceDialog = false;
} catch (error) { } catch (error) {
console.error("保存出勤状态失败:", error); console.error("保存出勤状态失败:", error);

View File

@ -1,17 +1,17 @@
import axios from 'axios'; import axios from "axios";
import { openDB } from 'idb'; import { openDB } from "idb";
const DB_NAME = 'HomeworkDB'; const DB_NAME = "HomeworkDB";
const DB_VERSION = 1; const DB_VERSION = 1;
const initDB = async () => { const initDB = async () => {
return openDB(DB_NAME, DB_VERSION, { return openDB(DB_NAME, DB_VERSION, {
upgrade(db) { upgrade(db) {
if (!db.objectStoreNames.contains('homework')) { if (!db.objectStoreNames.contains("homework")) {
db.createObjectStore('homework'); db.createObjectStore("homework");
} }
if (!db.objectStoreNames.contains('config')) { if (!db.objectStoreNames.contains("config")) {
db.createObjectStore('config'); db.createObjectStore("config");
} }
}, },
}); });
@ -20,12 +20,12 @@ const initDB = async () => {
const formatResponse = (data, message = null) => ({ const formatResponse = (data, message = null) => ({
success: true, success: true,
data, data,
message message,
}); });
const formatError = (message, code = 'UNKNOWN_ERROR') => ({ const formatError = (message, code = "UNKNOWN_ERROR") => ({
success: false, success: false,
error: { code, message } error: { code, message },
}); });
const providers = { const providers = {
@ -33,9 +33,9 @@ const providers = {
async loadData(key, date) { async loadData(key, date) {
try { try {
// 检查是否设置了班号 // 检查是否设置了班号
const classNumber = key.split('/').pop(); const classNumber = key.split("/").pop();
if (!classNumber) { if (!classNumber) {
return formatError('请先设置班号', 'CONFIG_ERROR'); return formatError("请先设置班号", "CONFIG_ERROR");
} }
// 使用班号作为本地存储的前缀 // 使用班号作为本地存储的前缀
@ -44,45 +44,44 @@ const providers = {
if (!rawData) { if (!rawData) {
// 如果是今天的数据且没有找到返回空结构而不是null // 如果是今天的数据且没有找到返回空结构而不是null
const today = new Date().toISOString().split('T')[0]; const today = new Date().toISOString().split("T")[0];
if (date === today) { if (date === today) {
return formatResponse({ return formatResponse({
homework: {}, homework: {},
attendance: { absent: [], late: [] } attendance: { absent: [], late: [] },
}); });
} }
return formatError('数据不存在', 'NOT_FOUND'); return formatError("数据不存在", "NOT_FOUND");
} }
return formatResponse(JSON.parse(rawData)); return formatResponse(JSON.parse(rawData));
} catch (error) { } catch (error) {
return formatError("读取本地数据失败:" + error);
return formatError('读取本地数据失败:'+error);
} }
}, },
async saveData(key, data, date) { async saveData(key, data, date) {
try { try {
// 检查是否设置了班号 // 检查是否设置了班号
const classNumber = key.split('/').pop(); const classNumber = key.split("/").pop();
if (!classNumber) { if (!classNumber) {
return formatError('请先设置班号', 'CONFIG_ERROR'); return formatError("请先设置班号", "CONFIG_ERROR");
} }
// 使用班号作为本地存储的前缀 // 使用班号作为本地存储的前缀
const storageKey = `homework_${classNumber}_${date}`; const storageKey = `homework_${classNumber}_${date}`; // 使用传入的date参数
localStorage.setItem(storageKey, JSON.stringify(data)); localStorage.setItem(storageKey, JSON.stringify(data));
return formatResponse(null, '保存成功'); return formatResponse(null, "保存成功");
} catch (error) { } catch (error) {
return formatError('保存本地数据失败:'+error); return formatError("保存本地数据失败:" + error);
} }
}, },
async loadConfig(key) { async loadConfig(key) {
try { try {
const classNumber = key.split('/').pop(); const classNumber = key.split("/").pop();
if (!classNumber) { if (!classNumber) {
return formatError('请先设置班号', 'CONFIG_ERROR'); return formatError("请先设置班号", "CONFIG_ERROR");
} }
const storageKey = `config_${classNumber}`; const storageKey = `config_${classNumber}`;
@ -91,30 +90,30 @@ const providers = {
if (!rawData) { if (!rawData) {
return formatResponse({ return formatResponse({
studentList: [], studentList: [],
displayOptions: {} displayOptions: {},
}); });
} }
return formatResponse(JSON.parse(rawData)); return formatResponse(JSON.parse(rawData));
} catch (error) { } catch (error) {
return formatError('读取本地配置失败:'+error); return formatError("读取本地配置失败:" + error);
} }
}, },
async saveConfig(key, config) { async saveConfig(key, config) {
try { try {
const classNumber = key.split('/').pop(); const classNumber = key.split("/").pop();
if (!classNumber) { if (!classNumber) {
return formatError('请先设置班号', 'CONFIG_ERROR'); return formatError("请先设置班号", "CONFIG_ERROR");
} }
const storageKey = `config_${classNumber}`; const storageKey = `config_${classNumber}`;
localStorage.setItem(storageKey, JSON.stringify(config)); localStorage.setItem(storageKey, JSON.stringify(config));
return formatResponse(null, '保存成功'); return formatResponse(null, "保存成功");
} catch (error) { } catch (error) {
return formatError('保存本地配置失败:'+error); return formatError("保存本地配置失败:" + error);
} }
} },
}, },
server: { server: {
@ -122,25 +121,27 @@ const providers = {
try { try {
const res = await axios.get(`${key}/homework?date=${date}`); const res = await axios.get(`${key}/homework?date=${date}`);
if (res.data?.status === false) { if (res.data?.status === false) {
return formatError(res.data.msg || '获取数据失败', 'SERVER_ERROR'); return formatError(res.data.msg || "获取数据失败", "SERVER_ERROR");
} }
return formatResponse(res.data); return formatResponse(res.data);
} catch (error) { } catch (error) {
return formatError( return formatError(
error.response?.data?.message || '服务器连接失败', error.response?.data?.message || "服务器连接失败",
'NETWORK_ERROR' "NETWORK_ERROR"
); );
} }
}, },
async saveData(key, data) { async saveData(key, data, date) {
try { try {
await axios.post(`${key}/homework`, data); // 添加date参数到URL
return formatResponse(null, '保存成功'); const url = date ? `${key}/homework?date=${date}` : `${key}/homework`;
await axios.post(url, data);
return formatResponse(null, "保存成功");
} catch (error) { } catch (error) {
return formatError( return formatError(
error.response?.data?.message || '保存失败', error.response?.data?.message || "保存失败",
'SAVE_ERROR' "SAVE_ERROR"
); );
} }
}, },
@ -149,13 +150,13 @@ const providers = {
try { try {
const res = await axios.get(`${key}/config`); const res = await axios.get(`${key}/config`);
if (res.data?.status === false) { if (res.data?.status === false) {
return formatError(res.data.msg || '获取配置失败', 'SERVER_ERROR'); return formatError(res.data.msg || "获取配置失败", "SERVER_ERROR");
} }
return formatResponse(res.data); return formatResponse(res.data);
} catch (error) { } catch (error) {
return formatError( return formatError(
error.response?.data?.message || '服务器连接失败', error.response?.data?.message || "服务器连接失败",
'NETWORK_ERROR' "NETWORK_ERROR"
); );
} }
}, },
@ -164,121 +165,123 @@ const providers = {
try { try {
const res = await axios.put(`${key}/config`, config); const res = await axios.put(`${key}/config`, config);
if (res.data?.status === false) { if (res.data?.status === false) {
return formatError(res.data.msg || '保存失败', 'SAVE_ERROR'); return formatError(res.data.msg || "保存失败", "SAVE_ERROR");
} }
return formatResponse(null, '保存成功'); return formatResponse(null, "保存成功");
} catch (error) { } catch (error) {
return formatError( return formatError(
error.response?.data?.message || '保存失败', error.response?.data?.message || "保存失败",
'SAVE_ERROR' "SAVE_ERROR"
); );
} }
} },
}, },
indexedDB: { indexedDB: {
async loadData(key, date) { async loadData(key, date) {
try { try {
const classNumber = key.split('/').pop(); const classNumber = key.split("/").pop();
if (!classNumber) { if (!classNumber) {
return formatError('请先设置班号', 'CONFIG_ERROR'); return formatError("请先设置班号", "CONFIG_ERROR");
} }
const db = await initDB(); const db = await initDB();
const storageKey = `homework_${classNumber}_${date}`; const storageKey = `homework_${classNumber}_${date}`;
const data = await db.get('homework', storageKey); const data = await db.get("homework", storageKey);
if (!data) { if (!data) {
const today = new Date().toISOString().split('T')[0]; const today = new Date().toISOString().split("T")[0];
if (date === today) { if (date === today) {
return formatResponse({ return formatResponse({
homework: {}, homework: {},
attendance: { absent: [], late: [] } attendance: { absent: [], late: [] },
}); });
} }
return formatError('数据不存在', 'NOT_FOUND'); return formatError("数据不存在", "NOT_FOUND");
} }
// 从字符串解析数据 // 从字符串解析数据
return formatResponse(JSON.parse(data)); return formatResponse(JSON.parse(data));
} catch (error) { } catch (error) {
return formatError('读取IndexedDB数据失败' + error); return formatError("读取IndexedDB数据失败" + error);
} }
}, },
async saveData(key, data, date) { async saveData(key, data, date) {
try { try {
const classNumber = key.split('/').pop(); const classNumber = key.split("/").pop();
if (!classNumber) { if (!classNumber) {
return formatError('请先设置班号', 'CONFIG_ERROR'); return formatError("请先设置班号", "CONFIG_ERROR");
} }
const db = await initDB(); const db = await initDB();
const storageKey = `homework_${classNumber}_${date}`; const storageKey = `homework_${classNumber}_${date}`; // 使用传入的date参数
// 将数据序列化为字符串存储 // 将数据序列化为字符串存储
await db.put('homework', JSON.stringify(data), storageKey); await db.put("homework", JSON.stringify(data), storageKey);
return formatResponse(null, '保存成功'); return formatResponse(null, "保存成功");
} catch (error) { } catch (error) {
return formatError('保存IndexedDB数据失败' + error); return formatError("保存IndexedDB数据失败" + error);
} }
}, },
async loadConfig(key) { async loadConfig(key) {
try { try {
const classNumber = key.split('/').pop(); const classNumber = key.split("/").pop();
if (!classNumber) { if (!classNumber) {
return formatError('请先设置班号', 'CONFIG_ERROR'); return formatError("请先设置班号", "CONFIG_ERROR");
} }
const db = await initDB(); const db = await initDB();
const storageKey = `config_${classNumber}`; const storageKey = `config_${classNumber}`;
const config = await db.get('config', storageKey); const config = await db.get("config", storageKey);
if (!config) { if (!config) {
return formatResponse({ return formatResponse({
studentList: [], studentList: [],
displayOptions: {} displayOptions: {},
}); });
} }
// 从字符串解析配置 // 从字符串解析配置
return formatResponse(JSON.parse(config)); return formatResponse(JSON.parse(config));
} catch (error) { } catch (error) {
return formatError('读取IndexedDB配置失败' + error); return formatError("读取IndexedDB配置失败" + error);
} }
}, },
async saveConfig(key, config) { async saveConfig(key, config) {
try { try {
const classNumber = key.split('/').pop(); const classNumber = key.split("/").pop();
if (!classNumber) { if (!classNumber) {
return formatError('请先设置班号', 'CONFIG_ERROR'); return formatError("请先设置班号", "CONFIG_ERROR");
} }
const db = await initDB(); const db = await initDB();
const storageKey = `config_${classNumber}`; const storageKey = `config_${classNumber}`;
// 将配置序列化为字符串存储 // 将配置序列化为字符串存储
await db.put('config', JSON.stringify(config), storageKey); await db.put("config", JSON.stringify(config), storageKey);
return formatResponse(null, '保存成功'); return formatResponse(null, "保存成功");
} catch (error) { } catch (error) {
return formatError('保存IndexedDB配置失败' + error); return formatError("保存IndexedDB配置失败" + error);
} }
} },
} },
}; };
export default { export default {
loadData: (provider, key, date) => providers[provider]?.loadData(key, date), loadData: (provider, key, date) => providers[provider]?.loadData(key, date),
saveData: (provider, key, data, date) => providers[provider]?.saveData(key, data, date), saveData: (provider, key, data, date) =>
providers[provider]?.saveData(key, data, date),
loadConfig: (provider, key) => providers[provider]?.loadConfig(key), loadConfig: (provider, key) => providers[provider]?.loadConfig(key),
saveConfig: (provider, key, config) => providers[provider]?.saveConfig(key, config) saveConfig: (provider, key, config) =>
providers[provider]?.saveConfig(key, config),
}; };
export const ErrorCodes = { export const ErrorCodes = {
NOT_FOUND: '数据不存在', NOT_FOUND: "数据不存在",
NETWORK_ERROR: '网络连接失败', NETWORK_ERROR: "网络连接失败",
SERVER_ERROR: '服务器错误', SERVER_ERROR: "服务器错误",
SAVE_ERROR: '保存失败', SAVE_ERROR: "保存失败",
CONFIG_ERROR: '配置错误', CONFIG_ERROR: "配置错误",
UNKNOWN_ERROR: '未知错误' UNKNOWN_ERROR: "未知错误",
}; };

View File

@ -15,7 +15,7 @@ const defaultOptions = {
addToLog: true addToLog: true
}; };
const STORAGE_KEY = 'homeworkpage_messages'; const STORAGE_KEY = 'classworks_messages';
const MAX_MESSAGES = 100; // 最大消息数量 const MAX_MESSAGES = 100; // 最大消息数量
const MAX_STORAGE_SIZE = 1024 * 1024; // 1MB 存储限制 const MAX_STORAGE_SIZE = 1024 * 1024; // 1MB 存储限制

View File

@ -10,7 +10,7 @@
*/ */
// 存储所有设置的localStorage键名 // 存储所有设置的localStorage键名
const SETTINGS_STORAGE_KEY = 'homeworkpage_settings'; const SETTINGS_STORAGE_KEY = "classworks_settings";
/** /**
* 所有配置项的定义 * 所有配置项的定义
@ -18,115 +18,116 @@ const SETTINGS_STORAGE_KEY = 'homeworkpage_settings';
*/ */
const settingsDefinitions = { const settingsDefinitions = {
// 显示设置 // 显示设置
'display.emptySubjectDisplay': { "display.emptySubjectDisplay": {
type: 'string', type: "string",
default: 'button', // 修改默认值为 'button' default: "button", // 修改默认值为 'button'
validate: value => ['card', 'button'].includes(value), validate: (value) => ["card", "button"].includes(value),
description: '空科目的显示方式:卡片或按钮' description: "空科目的显示方式:卡片或按钮",
}, },
'display.dynamicSort': { "display.dynamicSort": {
type: 'boolean', type: "boolean",
default: true, default: true,
description: '是否启用动态排序以优化显示效果' description: "是否启用动态排序以优化显示效果",
}, },
'display.showRandomButton': { "display.showRandomButton": {
type: 'boolean', type: "boolean",
default: false, default: false,
description: '是否显示随机按钮' description: "是否显示随机按钮",
}, },
// 服务器设置(合并了数据提供者设置) // 服务器设置(合并了数据提供者设置)
'server.domain': { "server.domain": {
type: 'string', type: "string",
default: '', default: "",
validate: value => !value || /^https?:\/\//.test(value), validate: (value) => !value || /^https?:\/\//.test(value),
description: '后端服务器域名' description: "后端服务器域名",
}, },
'server.classNumber': { "server.classNumber": {
type: 'string', type: "string",
default: '', default: "",
validate: value => /^[A-Za-z0-9]*$/.test(value), validate: (value) => /^[A-Za-z0-9]*$/.test(value),
description: '班级编号(无论使用哪种存储方式都需要设置)' description: "班级编号(无论使用哪种存储方式都需要设置)",
}, },
'server.provider': { "server.provider": {
type: 'string', type: "string",
default: 'indexedDB', default: "indexedDB",
validate: value => ['server', 'localStorage', 'indexedDB'].includes(value), validate: (value) =>
description: '数据提供者,用于决定数据存储方式' ["server", "localStorage", "indexedDB"].includes(value),
description: "数据提供者,用于决定数据存储方式",
}, },
// 刷新设置 // 刷新设置
'refresh.auto': { "refresh.auto": {
type: 'boolean', type: "boolean",
default: false, default: false,
description: '是否启用自动刷新' description: "是否启用自动刷新",
}, },
'refresh.interval': { "refresh.interval": {
type: 'number', type: "number",
default: 300, default: 300,
validate: value => value >= 10 && value <= 3600, validate: (value) => value >= 10 && value <= 3600,
description: '自动刷新间隔(秒)' description: "自动刷新间隔(秒)",
}, },
// 字体设置 // 字体设置
'font.size': { "font.size": {
type: 'number', type: "number",
default: 28, default: 28,
validate: value => value >= 16 && value <= 100, validate: (value) => value >= 16 && value <= 100,
description: '字体大小(像素)' description: "字体大小(像素)",
}, },
// 编辑设置 // 编辑设置
'edit.autoSave': { "edit.autoSave": {
type: 'boolean', type: "boolean",
default: true, default: true,
description: '是否启用自动保存' description: "是否启用自动保存",
}, },
'edit.refreshBeforeEdit': { "edit.refreshBeforeEdit": {
type: 'boolean', type: "boolean",
default: true, default: true,
description: '编辑前是否自动刷新' description: "编辑前是否自动刷新",
}, },
// 开发者选项 // 开发者选项
'developer.enabled': { "developer.enabled": {
type: 'boolean', type: "boolean",
default: false, default: false,
description: '是否启用开发者选项' description: "是否启用开发者选项",
}, },
'developer.showDebugConfig': { "developer.showDebugConfig": {
type: 'boolean', type: "boolean",
default: false, default: false,
description: '是否显示调试配置' description: "是否显示调试配置",
}, },
// 消息设置 // 消息设置
'message.showSidebar': { "message.showSidebar": {
type: 'boolean', type: "boolean",
default: true, default: true,
description: '是否显示消息记录侧栏', description: "是否显示消息记录侧栏",
requireDeveloper: true // 添加标记 requireDeveloper: true, // 添加标记
}, },
'message.maxActiveMessages': { "message.maxActiveMessages": {
type: 'number', type: "number",
default: 5, default: 5,
validate: value => value >= 1 && value <= 10, validate: (value) => value >= 1 && value <= 10,
description: '同时显示的最大消息数量', description: "同时显示的最大消息数量",
requireDeveloper: true requireDeveloper: true,
}, },
'message.timeout': { "message.timeout": {
type: 'number', type: "number",
default: 5000, default: 5000,
validate: value => value >= 1000 && value <= 30000, validate: (value) => value >= 1000 && value <= 30000,
description: '消息自动关闭时间(毫秒)', description: "消息自动关闭时间(毫秒)",
requireDeveloper: true requireDeveloper: true,
}, },
'message.saveHistory': { "message.saveHistory": {
type: 'boolean', type: "boolean",
default: true, default: true,
description: '是否保存消息历史记录', description: "是否保存消息历史记录",
requireDeveloper: true requireDeveloper: true,
} },
}; };
// 内存中缓存的设置值 // 内存中缓存的设置值
@ -146,7 +147,7 @@ function loadSettings() {
settingsCache = migrateFromLegacy(); settingsCache = migrateFromLegacy();
} }
} catch (error) { } catch (error) {
console.error('加载设置失败:', error); console.error("加载设置失败:", error);
settingsCache = {}; settingsCache = {};
} }
@ -164,42 +165,38 @@ function loadSettings() {
* 从旧版本的localStorage迁移数据 * 从旧版本的localStorage迁移数据
*/ */
function migrateFromLegacy() { function migrateFromLegacy() {
const settings = {}; const LEGACY_SETTINGS_KEY = "homeworkpage_settings";
const legacyKeyMap = { const LEGACY_MESSAGE_KEY = "homeworkpage_messages";
'server.domain': 'backendServerDomain',
'server.classNumber': 'classNumber',
'refresh.auto': 'autoRefresh',
'refresh.interval': 'refreshInterval',
'font.size': 'fontSize',
'edit.autoSave': 'autoSave',
'edit.refreshBeforeEdit': 'refreshBeforeEdit',
'display.emptySubjectDisplay': 'emptySubjectDisplay',
'display.dynamicSort': 'dynamicSort'
};
// 迁移旧数据 // 尝试从旧版本的设置中迁移
for (const [newKey, oldKey] of Object.entries(legacyKeyMap)) { const legacySettings = localStorage.getItem(LEGACY_SETTINGS_KEY);
const oldValue = localStorage.getItem(oldKey); if (legacySettings) {
if (oldValue !== null) { try {
const definition = settingsDefinitions[newKey]; const settings = JSON.parse(legacySettings);
switch (definition.type) { localStorage.setItem(SETTINGS_STORAGE_KEY, JSON.stringify(settings));
case 'boolean': // 可选:删除旧的设置
settings[newKey] = oldValue === 'true'; localStorage.removeItem(LEGACY_SETTINGS_KEY);
break; return settings;
case 'number': } catch (error) {
settings[newKey] = Number(oldValue); console.error("迁移旧设置失败:", error);
break; }
default: }
settings[newKey] = oldValue; // 尝试从旧版本的message中迁移
} const legacyMessages = localStorage.getItem(LEGACY_MESSAGE_KEY);
// 可选删除旧的localStorage项 if (legacyMessages) {
// localStorage.removeItem(oldKey); try {
const messages = JSON.parse(legacyMessages);
localStorage.setItem(SETTINGS_STORAGE_KEY, JSON.stringify(messages));
// 可选删除旧的message
localStorage.removeItem(LEGACY_MESSAGE_KEY);
return messages; // 返回迁移后的消息
} catch (error) {
console.error("迁移旧消息失败:", error);
} }
} }
// 保存迁移后的数据 // 如果没有旧设置或迁移失败,返回空对象
localStorage.setItem(SETTINGS_STORAGE_KEY, JSON.stringify(settings)); return {};
return settings;
} }
/** /**
@ -209,7 +206,7 @@ function saveSettings() {
try { try {
localStorage.setItem(SETTINGS_STORAGE_KEY, JSON.stringify(settingsCache)); localStorage.setItem(SETTINGS_STORAGE_KEY, JSON.stringify(settingsCache));
} catch (error) { } catch (error) {
console.error('保存设置失败:', error); console.error("保存设置失败:", error);
} }
} }
@ -230,7 +227,7 @@ function getSetting(key) {
} }
// 添加对开发者选项依赖的检查 // 添加对开发者选项依赖的检查
if (definition.requireDeveloper && !settingsCache['developer.enabled']) { if (definition.requireDeveloper && !settingsCache["developer.enabled"]) {
return definition.default; return definition.default;
} }
@ -240,11 +237,14 @@ function getSetting(key) {
// 添加设置变更日志函数 // 添加设置变更日志函数
function logSettingsChange(key, oldValue, newValue) { function logSettingsChange(key, oldValue, newValue) {
if (settingsCache['developer.enabled'] && settingsCache['developer.showDebugConfig']) { if (
settingsCache["developer.enabled"] &&
settingsCache["developer.showDebugConfig"]
) {
console.log(`[Settings] ${key}:`, { console.log(`[Settings] ${key}:`, {
old: oldValue, old: oldValue,
new: newValue, new: newValue,
time: new Date().toLocaleTimeString() time: new Date().toLocaleTimeString(),
}); });
} }
} }
@ -263,7 +263,7 @@ function setSetting(key, value) {
} }
// 添加对开发者选项依赖的检查 // 添加对开发者选项依赖的检查
if (definition.requireDeveloper && !settingsCache['developer.enabled']) { if (definition.requireDeveloper && !settingsCache["developer.enabled"]) {
console.warn(`设置项 ${key} 需要启用开发者选项`); console.warn(`设置项 ${key} 需要启用开发者选项`);
return false; return false;
} }
@ -272,8 +272,12 @@ function setSetting(key, value) {
const oldValue = settingsCache[key]; const oldValue = settingsCache[key];
// 类型转换 // 类型转换
if (typeof value !== definition.type) { if (typeof value !== definition.type) {
value = definition.type === 'boolean' ? Boolean(value) : value =
definition.type === 'number' ? Number(value) : String(value); definition.type === "boolean"
? Boolean(value)
: definition.type === "number"
? Number(value)
: String(value);
} }
// 验证 // 验证
@ -346,8 +350,8 @@ function watchSettings(callback) {
} }
}; };
window.addEventListener('storage', handler); window.addEventListener("storage", handler);
return () => window.removeEventListener('storage', handler); return () => window.removeEventListener("storage", handler);
} }
// 初始化设置 // 初始化设置
@ -359,5 +363,5 @@ export {
setSetting, setSetting,
resetSetting, resetSetting,
resetAllSettings, resetAllSettings,
watchSettings watchSettings,
}; };