fix(V0.2): 任务模块 4 个 bug —— 覆盖层安全区/返回键/项目列表排序/键盘遮挡
Docker Build and Push / build-image (push) Successful in 4m17s

1. 项目管理等 cs-page 覆盖层与系统状态栏重合:
   .cs-page 补 padding-top: var(--safe-top) (复用 main.jsx 实测校准的变量)

2. 项目管理按返回键跑到上一个 Tab:
   新增 useOverlayBack —— 覆盖层打开时 pushState 哨兵, 返回键先关覆盖层
   应用于 项目管理(内层视图先回主区) 与 任务详情弹层

3. 更多项目页:
   - 头部补「+ 新建」入口
   - 项目列表支持长按拖动排序(纵向), 顺序存设备端, 与首屏最近项目共用 recentOrder
   - 顺带修复首屏 RecentProjects 拖动排序的闭包缺陷(监听器读到旧下标, 首次移动
     会 splice(-1)); 两处均改为 ref 取当前下标

4. 任务详情输入子任务被键盘遮挡:
   新增 useKeyboardInset (visualViewport 差值), 键盘弹出时抬升弹层内容并收缩
   maxHeight; 输入框聚焦后再 scrollIntoView 到可视区中部 (双保险)

已验证: 99 文件语法 0 错误、相对导入 0 缺失
This commit is contained in:
jif2.zhang
2026-10-24 21:09:19 +08:00
parent 0cdbfb434f
commit 1fd7522fa6
7 changed files with 215 additions and 20 deletions
+12 -6
View File
@@ -12,7 +12,8 @@ const MOVE_TOLERANCE = 8
export default function RecentProjects({ projects, currentId, onSelect, onMore }) {
const [ver, setVer] = useState(0) // 手动排序后强制重算
const [dragIdx, setDragIdx] = useState(-1) // 拖拽中的卡片下标
const [dragIdx, setDragIdx] = useState(-1) // 拖拽中的卡片下标 (视觉态)
const dragIdxRef = useRef(-1) // 监听器闭包读的下标 (state 在闭包里是旧值)
const barRef = useRef(null)
const timer = useRef(null)
const start = useRef(null)
@@ -51,9 +52,9 @@ export default function RecentProjects({ projects, currentId, onSelect, onMore }
}
// 按横坐标计算落点下标 (卡片宽 96 + 间距 8)
function indexAt(x) {
function indexAt(x, fallback = -1) {
const rect = barRef.current?.getBoundingClientRect()
if (!rect) return dragIdx
if (!rect) return fallback
const rel = x - rect.left + 4
return Math.max(0, Math.min(shown.length - 1, Math.floor(rel / 104)))
}
@@ -68,13 +69,16 @@ export default function RecentProjects({ projects, currentId, onSelect, onMore }
return
}
if (ev.cancelable) ev.preventDefault()
const to = indexAt(p.x)
if (to !== dragIdx && to >= 0) {
// 用 ref 取当前拖拽下标: 监听器闭包里的 state 是旧值
const from = dragIdxRef.current
const to = indexAt(p.x, from)
if (to !== from && to >= 0 && from >= 0) {
// 实时换位: 重写设备端顺序, ver 触发重算 (shown 由 memo 派生)
const ids = shown.map((p2) => p2.id)
const [moved] = ids.splice(dragIdx, 1)
const [moved] = ids.splice(from, 1)
ids.splice(to, 0, moved)
setRecentOrder(ids)
dragIdxRef.current = to
setDragIdx(to)
setVer((v) => v + 1)
}
@@ -83,6 +87,7 @@ export default function RecentProjects({ projects, currentId, onSelect, onMore }
function onEnd() {
if (active.current) setVer((v) => v + 1)
cleanup()
dragIdxRef.current = -1
setDragIdx(-1)
}
@@ -92,6 +97,7 @@ export default function RecentProjects({ projects, currentId, onSelect, onMore }
start.current = p
active.current = false
cleanup()
dragIdxRef.current = i
timer.current = setTimeout(() => {
active.current = true
setDragIdx(i)