Docker Build and Push / build-image (push) Successful in 4m8s
按 2026-10-24 评审的 5 条调整实现 (需求 T-VW-08~10 / T-PJ-11/12 / T-UI-11): 首屏 (T-VW-08/09): - /task 改为「上=最近项目条(3 个+更多入口), 下=当前项目任务管理」 - 完整项目列表迁至 /task/list, 从「更多项目」进入; /task/:pid 保留供深链 最近项目排序 (T-VW-10): - 卡片长按 300ms 拖动换位, 结果存设备端 prefs.recentOrder - 顺序 = 手动排序 > 最近访问(recentIds) > 列表序, 归档项目不展示 项目管理 (T-PJ-11/12): - 新增 ProjectManage: 成员 / 看板列 / 项目信息 三分区统一入口 - 项目信息含 改名 / 归档切换 / 删除(个人项目隐藏) / 退出(仅创建人) - 项目页头部只留「项目管理 + 新增」, 移除散置的成员/列设置按钮 底部安全距离 (T-UI-11): - 任务详情 / 人员选择 / 拷贝弹层 padding-bottom = 安全区 + 20px - 小屏下弹层 maxHeight + 内部滚动, 底部按钮完整可见 已验证: 97 文件语法 0 错误、相对导入 0 缺失
98 lines
2.9 KiB
JavaScript
98 lines
2.9 KiB
JavaScript
// 任务模块: 设备端偏好 (不落库, 不跨设备)
|
|
// 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)
|
|
}
|
|
}
|