// 任务模块: 设备端偏好 (不落库, 不跨设备) // lastProjectId 上次访问的项目 (T-VW-07) // viewMode 按项目记忆的视图 list | board (T-VW-03/06) // recentIds 自动按最近访问排序的项目 id (最前 = 最近), 上限 10 (T-VW-08) // recentOrder 首屏最近项目卡片的手动排序结果, 优先于 recentIds (T-VW-10) const KEY = 'iboard_task_prefs' function blank() { return { lastProjectId: null, viewMode: {}, recentIds: [], recentOrder: [] } } function read() { try { const raw = localStorage.getItem(KEY) if (!raw) return blank() const obj = JSON.parse(raw) return { lastProjectId: obj.lastProjectId ?? null, viewMode: obj.viewMode && typeof obj.viewMode === 'object' ? obj.viewMode : {}, recentIds: Array.isArray(obj.recentIds) ? obj.recentIds : [], recentOrder: Array.isArray(obj.recentOrder) ? obj.recentOrder : [], } } catch { return blank() } } function write(obj) { try { localStorage.setItem(KEY, JSON.stringify(obj)) } catch { /* 忽略配额错误 */ } } export function getLastProjectId() { return read().lastProjectId } export function setLastProjectId(id) { const cur = read() cur.lastProjectId = id ?? null write(cur) } /** 视图记忆: 无记录返回 null, 由调用方决定默认值 */ export function getViewMode(projectId) { if (!projectId) return null return read().viewMode[String(projectId)] || null } export function setViewMode(projectId, mode) { if (!projectId) return const cur = read() cur.viewMode[String(projectId)] = mode write(cur) } /** 最近访问记录: 把 id 提到队首, 上限 10 (T-VW-08) */ export function getRecentIds() { return read().recentIds } export function setRecentIds(id) { if (!id) return const cur = read() cur.recentIds = [id, ...cur.recentIds.filter((x) => x !== id)].slice(0, 10) write(cur) } /** 首屏卡片手动排序 (T-VW-10): 完整顺序, 排在前面的项目优先展示 */ export function getRecentOrder() { return read().recentOrder } export function setRecentOrder(ids) { const cur = read() cur.recentOrder = (Array.isArray(ids) ? ids : []).map(Number).filter(Boolean) write(cur) } /** 清理已不可见的项目记录 */ export function prunePrefs(visibleIds) { const set = new Set((visibleIds || []).map(Number)) const cur = read() let dirty = false if (cur.lastProjectId && !set.has(cur.lastProjectId)) { cur.lastProjectId = null; dirty = true } for (const k of Object.keys(cur.viewMode)) { if (!set.has(Number(k))) { delete cur.viewMode[k]; dirty = true } } const ri = cur.recentIds.filter((id) => set.has(id)) const ro = cur.recentOrder.filter((id) => set.has(id)) if (ri.length !== cur.recentIds.length || ro.length !== cur.recentOrder.length) dirty = true if (dirty) { cur.recentIds = ri cur.recentOrder = ro write(cur) } }