Docker Build and Push / build-image (push) Failing after 3m51s
需求 142 条 (T-*), 设计见 docs/V0.2/任务模块/ 数据层: - 新增 6 张表: Project / ProjectMember / BoardColumn / Task / TaskMember / TaskTag - 看板列是实体(可增删改排序), Task.columnId 外键 RESTRICT 防误删列丢任务 - Task.status(todo/doing/done) 与 columnId 双落库, 二者正交 领域层 server/task-domain/ (唯一口径, 前后端不重复实现): - resolveStatus: 列决定状态(只看目标列, 无拖出回退); 状态与列不匹配时按列序取第一个绑定该状态的列自动归位, 无匹配列则不移动; 子任务完全豁免 - retention: 逐列 6 档保留窗口(永不显示/当天/3天/本周/本月/永久显示), 以 doneAt 判定 - copyTask: 跨项目深拷贝, 人员按目标项目成员过滤并回报丢弃名单 接口: /api/projects, /api/columns, /api/tasks (均校验项目成员) 前端: - 底部 Tab 插入「任务」, 位于「打卡」之后; 默认首页仍为打卡 - 列表视图(子任务缩进+折叠) / 看板视图(长按拖拽换列、拖到卡片降为子任务) - 列设置(列管理+状态绑定+保留选项) / 任务详情(扩展信息卡片默认收起) / 成员管理 - 视图记忆与上次项目存设备端 已验证: 95 文件语法 0 错误、相对导入 0 缺失、领域逻辑用例全部通过
51 lines
2.6 KiB
React
51 lines
2.6 KiB
React
// 底部 TabBar 图标: 简洁线性 SVG, 仿原生 App 风格
|
|
// props: name 字符串, active 布尔
|
|
// 返回对应的 24x24 SVG 节点
|
|
const ICONS = {
|
|
// V0.2: 打卡移到最左, 原「首页」已并入宏观, home 图标不再使用
|
|
macro: (active) => (
|
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={active ? 2.2 : 1.8} strokeLinecap="round" strokeLinejoin="round">
|
|
<rect x="3" y="3" width="7" height="9" rx="1" fill={active ? 'currentColor' : 'none'} fillOpacity={active ? 0.15 : 0} />
|
|
<rect x="14" y="3" width="7" height="5" rx="1" />
|
|
<rect x="14" y="12" width="7" height="9" rx="1" fill={active ? 'currentColor' : 'none'} fillOpacity={active ? 0.15 : 0} />
|
|
<rect x="3" y="16" width="7" height="5" rx="1" />
|
|
</svg>
|
|
),
|
|
monitor: (active) => (
|
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={active ? 2.2 : 1.8} strokeLinecap="round" strokeLinejoin="round">
|
|
<path d="M3 12h4l2-5 4 10 2-5h6" fill={active ? 'currentColor' : 'none'} fillOpacity={active ? 0.12 : 0} />
|
|
</svg>
|
|
),
|
|
// 打卡: 日历 + 对勾
|
|
checkin: (active) => (
|
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={active ? 2.2 : 1.8} strokeLinecap="round" strokeLinejoin="round">
|
|
<rect x="3" y="5" width="18" height="16" rx="2" fill={active ? 'currentColor' : 'none'} fillOpacity={active ? 0.12 : 0} />
|
|
<path d="M3 10h18" />
|
|
<path d="M8 3v4M16 3v4" />
|
|
<path d="M9 15.5l2.2 2.2L15.5 13" />
|
|
</svg>
|
|
),
|
|
// 任务: 清单本 + 勾选行 (V0.2 任务模块)
|
|
task: (active) => (
|
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={active ? 2.2 : 1.8} strokeLinecap="round" strokeLinejoin="round">
|
|
<rect x="4" y="4" width="16" height="17" rx="2" fill={active ? 'currentColor' : 'none'} fillOpacity={active ? 0.12 : 0} />
|
|
<path d="M8 9.5l1.4 1.4L12 8.3" />
|
|
<path d="M14.5 9.5h3" />
|
|
<path d="M8 15.5l1.4 1.4L12 14.3" />
|
|
<path d="M14.5 15.5h3" />
|
|
</svg>
|
|
),
|
|
me: (active) => (
|
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={active ? 2.2 : 1.8} strokeLinecap="round" strokeLinejoin="round">
|
|
<circle cx="12" cy="8" r="4" fill={active ? 'currentColor' : 'none'} fillOpacity={active ? 0.15 : 0} />
|
|
<path d="M4 20c1.5-4 4.5-6 8-6s6.5 2 8 6" />
|
|
</svg>
|
|
),
|
|
}
|
|
|
|
export default function TabIcon({ name, active }) {
|
|
const render = ICONS[name]
|
|
if (!render) return null
|
|
return <span className="tab-icon">{render(!!active)}</span>
|
|
}
|