feat(V0.2): 任务操作菜单 / 状态指示 / 移动与转子任务 / 移除扩展信息
Docker Build and Push / build-image (push) Successful in 4m13s

1. 任务 ⋯ 菜单 (列表行与看板卡片): 编辑 / 拷贝到其他项目 / 删除
   (antd-mobile ActionSheet, 带任务名标题; 拷贝抽出为 CopyTaskPopup 复用)
2. 点击任务非按钮区域 = 打开编辑页 (原本即如此, ⋯ 不再误触为编辑)
3. 修复状态选择器堆成三行: 此前 .seg 只有 .pv-head 作用域样式,
   详情弹层裸用导致纵向堆叠; 新增通用 .seg 分段样式, 当前项高亮点按即切
4. 移除任务的扩展信息 UI (T-TK-04~07 标注已取消, 决策 35):
   ExtrasCard 组件删除, DB extras 字段保留不再使用;
   项目相关长文本由项目信息块 (T-PJ-13) 承载
5. 任务移动入口: 详情页新增「看板列」ActionSheet 换列(联动裁决不变)
   与「层级」区(转为子任务=选父任务 / 转为顶层), 覆盖无法拖拽的场景
6. 列表页移除「+ 子任务」入口: 添加子任务只在详情页, 或经转子任务

已验证: 99 文件语法 0 错误、导入 0 缺失、文档 149 条/决策 35 连续
This commit is contained in:
jif2.zhang
2026-10-24 21:51:26 +08:00
parent b71ceca3f2
commit 506db0795b
10 changed files with 252 additions and 146 deletions
+53 -2
View File
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useMemo, useState } from 'react'
import { DotLoading, Toast } from 'antd-mobile'
import { ActionSheet, Dialog, DotLoading, Toast } from 'antd-mobile'
import { projectApi, taskApi } from '../../api/task.js'
import { filterVisible, msToNextBoundary } from './date.js'
import { getViewMode, setViewMode } from './prefs.js'
@@ -7,6 +7,7 @@ import ListView from './ListView.jsx'
import BoardView from './BoardView.jsx'
import TaskDetail from './TaskDetail.jsx'
import ProjectManage from './ProjectManage.jsx'
import CopyTaskPopup from '../../components/task/CopyTaskPopup.jsx'
// 项目视图容器: 列表 / 看板 切换 + 数据装载 + 乐观更新
// 嵌在任务首屏下部 (T-VW-09); 头部仅保留「项目管理」与「+ 新增」(T-PJ-11)
@@ -20,6 +21,7 @@ export default function ProjectView({ projectId, onProjectChanged, onProjectExit
const [showManage, setShowManage] = useState(false)
const [adding, setAdding] = useState(false)
const [tick, setTick] = useState(0) // 保留窗口重算触发
const [copyTask, setCopyTask] = useState(null) // ⋯菜单触发的跨项目拷贝
const load = useCallback(() => {
setErr('')
@@ -136,6 +138,44 @@ export default function ProjectView({ projectId, onProjectChanged, onProjectExit
}
}
/** 任务 ⋯ 菜单: 编辑 / 拷贝到其他项目 / 删除 */
function openTaskMenu(task) {
ActionSheet.show({
extra: (
<div className="as-extra">
<div className="as-title">{task.title}</div>
</div>
),
actions: [
{ text: '编辑', key: 'edit' },
{ text: '拷贝到其他项目', key: 'copy' },
{ text: '删除', key: 'delete', bold: true, danger: true },
],
cancelText: '取消',
onAction: async (item) => {
if (item.key === 'edit') setOpenTask(task)
else if (item.key === 'copy') setCopyTask(task)
else if (item.key === 'delete') {
const kids = task.children?.length || 0
const ok = await Dialog.confirm({
content: kids
? `删除「${task.title}」?将一并删除 ${kids} 条子任务。`
: `删除「${task.title}」?`,
confirmText: '删除',
})
if (!ok) return
try {
await taskApi.remove(task.id)
Toast.show({ content: '已删除' })
load()
} catch (e) {
Toast.show({ content: e.message })
}
}
},
})
}
if (err) {
return (
<div className="pv-embed">
@@ -196,7 +236,7 @@ export default function ProjectView({ projectId, onProjectChanged, onProjectExit
columns={columns}
onToggle={toggleDone}
onOpen={(t) => setOpenTask(t)}
onAddSub={(parent) => setOpenTask(parent)}
onMore={openTaskMenu}
/>
) : (
<BoardView
@@ -207,6 +247,7 @@ export default function ProjectView({ projectId, onProjectChanged, onProjectExit
onOpen={(t) => setOpenTask(t)}
onToggleSub={(c) => toggleDone(c)}
onToggle={(t) => toggleDone(t)}
onMore={openTaskMenu}
onQuickAdd={() => { setAdding(true) }}
/>
)}
@@ -217,12 +258,22 @@ export default function ProjectView({ projectId, onProjectChanged, onProjectExit
task={openTask}
columns={columns}
members={project.members || []}
tasks={tasks || []}
onClose={() => setOpenTask(null)}
onSaved={() => { setOpenTask(null); load() }}
onChanged={load}
/>
)}
{copyTask && (
<CopyTaskPopup
task={copyTask}
visible
onClose={() => setCopyTask(null)}
onDone={load}
/>
)}
{showManage && (
<ProjectManage
project={project}