feat(任务/打卡): 已归档页面按原型重做; 打卡日历完成度改 4 档配色
Docker Build and Push / build-image (push) Successful in 1m27s
Docker Build and Push / build-image (push) Successful in 1m27s
一、已归档任务管理: 按评审通过的原型落地 (docs/V0.2/任务模块/已归档任务管理-原型.html)
- 去掉「任务类型」过滤: 类型是弱维度, 归档场景几乎不按它检索, 反而占掉一整行;
类型标签仍在行内展示。
- 关键词输入框前加常驻标签「标题」, 框内占位改为「输入关键词」。
- 归档时间新增快捷项: 全部 / 本周 / 本月 / 本季度 / 自定义;
选中后下方灰字回显实际区间 (本周=周一起算, 区间截至今天, 不跨未来);
「自定义」才展开两个日期选择器。
- 补上「筛选」按钮 (带生效条件数徽标) 与「重置」: 条件先编辑, 点按钮统一提交。
原实现改任一条件就即时重查, 连点会连发请求, 输关键词时列表会闪。
- 列表上方显示已应用条件标签 (可单独 ✕ 撤销) + 命中条数。
- 列表行重排: 标题独占一行, 元信息收成一行 (#编号 · 看板列 · 归档于日期),
「恢复 / 删除」由右侧竖排改到底部右侧横排, 降低行高。
- 空状态区分「这个项目还没有归档任务」(提示去 ⋯ 菜单归档) 与
「没有符合条件的归档任务」(建议放宽条件)。
- 修正日期边界: archivedList 的 from/to 原来直接拼 'T00:00:00Z',
本地选的日期会偏移 8 小时, 当天凌晨的归档被漏掉; 改为按本地时区换算成 UTC 瞬时。
二、打卡日历完成度配色: 由 3 档改 4 档
小半 (ratio < 0.5) -> 红 #ff3141
大半 (0.5 <= r < 1) -> 橘 #ff8f1f
完成 (r = 1) -> 蓝 #1677ff
超额 -> 绿 #00b578
注意服务端统计时把 actual 封顶在 expected (`Math.min(cnt, exp)`),
所以 ratio 永远 <= 1,**超额只能靠 status === 'over' 判断**,不能看比例;
DayRing 内新增 tierOf() 统一分级,图例同步改为四档。
验证 (真实 Windows 外壳 + CDP):
- 打卡页: 图例显示「小半/大半/完成/超额」, 计算样式分别为
rgb(255,49,65) / rgb(255,143,31) / rgb(22,119,255) / rgb(0,181,120);
当月实际渲染出 low=5 / high=1 / over=1。
- 已归档页: 筛选行标签为 标题/看板列/归档时间; 时间选项五项齐全;
按钮为 重置/筛选; 点「本周」回显 2026-10-26 ~ 2026-10-28, 点「筛选」后
徽标显示 1、条件标签可撤销、命中条数正确。
- 归档 → 已归档列表可见 → 恢复 全链路走通 (含上次修好的 TDZ 问题),
服务端确认 archived 由 t 变回 f。
- 控制台无异常。
This commit is contained in:
+94
-6
@@ -883,9 +883,11 @@ body.me-safe-top .app-safe-top { height: 0; }
|
||||
position: relative; width: 26px; height: 26px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.mv-day .day-ring-bar.partial { stroke: #ff8f1f; }
|
||||
.mv-day .day-ring-bar.full { stroke: #00b578; }
|
||||
.mv-day .day-ring-bar.over { stroke: #ff6b6b; }
|
||||
/* 环颜色 4 档: 小半(红) / 大半(橘) / 完成(蓝) / 超额(绿) */
|
||||
.mv-day .day-ring-bar.low { stroke: #ff3141; }
|
||||
.mv-day .day-ring-bar.high { stroke: #ff8f1f; }
|
||||
.mv-day .day-ring-bar.full { stroke: #1677ff; }
|
||||
.mv-day .day-ring-bar.over { stroke: #00b578; }
|
||||
/* 选中日: 蓝底之上改用白色环, 弧长仍表达完成度 */
|
||||
.mv-day.sel .day-ring-bg { stroke: rgba(255, 255, 255, .38); }
|
||||
.mv-day.sel .day-ring-bar { stroke: #fff; }
|
||||
@@ -895,9 +897,10 @@ body.me-safe-top .app-safe-top { height: 0; }
|
||||
.mv-legend { display: inline-flex; align-items: center; gap: 4px; color: #b0b6bf; }
|
||||
.mv-legend i { width: 7px; height: 7px; border-radius: 50%; display: inline-block; margin-left: 5px; }
|
||||
.mv-legend i:first-child { margin-left: 0; }
|
||||
.mv-legend i.partial { background: #ff8f1f; }
|
||||
.mv-legend i.full { background: #00b578; }
|
||||
.mv-legend i.over { background: #ff6b6b; }
|
||||
.mv-legend i.low { background: #ff3141; }
|
||||
.mv-legend i.high { background: #ff8f1f; }
|
||||
.mv-legend i.full { background: #1677ff; }
|
||||
.mv-legend i.over { background: #00b578; }
|
||||
|
||||
/* ---- 当日栏 ---- */
|
||||
.mv-daybar { display: flex; align-items: center; gap: 8px; padding: 10px 14px 2px; font-size: 13px; font-weight: 600; }
|
||||
@@ -1312,3 +1315,88 @@ textarea.inp { resize: vertical; }
|
||||
border-radius: 999px; padding: 2px 9px; flex-shrink: 0; white-space: nowrap;
|
||||
}
|
||||
.drag-pill.cur { background: #c0c7d0; }
|
||||
|
||||
/* ---- 已归档任务 (T-ARC-04/05/06) ----
|
||||
结构: 筛选卡(标题/看板列/归档时间 + 重置/筛选) -> 已应用条件 -> 列表
|
||||
交互: 条件先编辑, 点「筛选」统一提交; 生效条件可在列表上方单独撤销 */
|
||||
.arc-proj {
|
||||
margin-left: auto; font-size: 11px; color: #999; background: #f5f6f8;
|
||||
border-radius: 999px; padding: 2px 9px; max-width: 130px;
|
||||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||
}
|
||||
.arc-fcard {
|
||||
background: #fff; margin: 10px 12px 0; border-radius: 12px; padding: 4px 14px 12px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
|
||||
}
|
||||
.arc-frow { display: flex; align-items: center; gap: 10px; padding: 10px 0; border-bottom: 1px solid #f4f5f7; }
|
||||
.arc-frow:last-of-type { border-bottom: 0; }
|
||||
.arc-frow > .lbl { width: 56px; flex-shrink: 0; font-size: 12.5px; font-weight: 600; color: var(--color-text); }
|
||||
.arc-frow > .ctl { flex: 1; min-width: 0; }
|
||||
|
||||
/* 关键词输入框: 前面有常驻标签「标题」, 框内是占位提示 */
|
||||
.arc-kw {
|
||||
display: flex; align-items: center; gap: 7px;
|
||||
background: #f7f8fa; border: 1px solid #eceef1; border-radius: 8px; padding: 6px 9px;
|
||||
}
|
||||
.arc-kw:focus-within { border-color: var(--color-primary); background: #fff; }
|
||||
.arc-kw .adm-input { flex: 1; min-width: 0; border: 0; background: transparent; padding: 0; --font-size: 13px; }
|
||||
.arc-kw .adm-input-element { font-size: 13px; }
|
||||
|
||||
.arc-chips { display: flex; flex-wrap: wrap; gap: 6px; }
|
||||
.arc-chip {
|
||||
font-size: 12px; padding: 4px 10px; border-radius: 999px;
|
||||
border: 1px solid #e6e8eb; background: #fafbfc; color: var(--color-muted);
|
||||
cursor: pointer; white-space: nowrap;
|
||||
}
|
||||
.arc-chip.on { background: #eaf3ff; border-color: var(--color-primary); color: var(--color-primary); font-weight: 600; }
|
||||
|
||||
.arc-range { display: flex; align-items: center; gap: 7px; margin-top: 8px; }
|
||||
.arc-range .dp {
|
||||
font-size: 12px; padding: 4px 10px; border: 1px dashed #d9dee5; border-radius: 7px;
|
||||
color: #999; cursor: pointer; background: #fff;
|
||||
}
|
||||
.arc-range .dp.on { color: var(--color-text); border-style: solid; border-color: #d9dee5; }
|
||||
.arc-range .sep { color: #c2c6cc; font-size: 12px; }
|
||||
.arc-hint { font-size: 11px; color: #9aa4b2; margin-top: 6px; }
|
||||
|
||||
.arc-actions { display: flex; gap: 9px; padding-top: 12px; }
|
||||
.arc-btn { height: 36px; border-radius: 9px; border: 0; font-size: 13.5px; font-weight: 600; cursor: pointer; }
|
||||
.arc-btn.ghost { flex: 0 0 84px; background: #f4f5f7; color: var(--color-muted); }
|
||||
.arc-btn.primary { flex: 1; background: var(--color-primary); color: #fff; }
|
||||
.arc-btn .badge {
|
||||
display: inline-block; min-width: 16px; height: 16px; line-height: 16px; border-radius: 8px;
|
||||
background: rgba(255, 255, 255, .28); font-size: 10.5px; margin-left: 5px; padding: 0 4px;
|
||||
}
|
||||
|
||||
.arc-applied { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 11px 14px 3px; }
|
||||
.arc-applied .tag {
|
||||
font-size: 11.5px; background: #eaf3ff; color: var(--color-primary);
|
||||
border-radius: 6px; padding: 2px 7px; display: inline-flex; align-items: center; gap: 5px;
|
||||
}
|
||||
.arc-applied .tag .x { cursor: pointer; opacity: .6; }
|
||||
.arc-applied .cnt { margin-left: auto; font-size: 11.5px; color: #999; }
|
||||
|
||||
.arc-list { padding: 8px 12px 0; display: flex; flex-direction: column; gap: 8px; }
|
||||
.arc-item { background: #fff; border-radius: 10px; padding: 11px 12px; box-shadow: 0 1px 2px rgba(0, 0, 0, .04); }
|
||||
.arc-item .top { display: flex; gap: 8px; align-items: flex-start; }
|
||||
.arc-item .ttl { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 600; line-height: 1.42; word-break: break-word; }
|
||||
.arc-item .meta {
|
||||
display: flex; gap: 7px; align-items: center; flex-wrap: wrap;
|
||||
margin-top: 7px; font-size: 10.5px; color: #999;
|
||||
}
|
||||
.arc-item .meta .col { color: var(--color-muted); }
|
||||
.arc-item .meta .dot { width: 3px; height: 3px; border-radius: 50%; background: #d5d9e0; }
|
||||
.arc-item .acts {
|
||||
display: flex; gap: 7px; justify-content: flex-end;
|
||||
margin-top: 9px; padding-top: 9px; border-top: 1px dashed #f0f1f3;
|
||||
}
|
||||
.arc-item .acts .mini {
|
||||
font-size: 11.5px; padding: 3px 12px; border-radius: 999px;
|
||||
border: 1px solid var(--color-primary); color: var(--color-primary);
|
||||
background: #fff; cursor: pointer; white-space: nowrap;
|
||||
}
|
||||
.arc-item .acts .mini.danger { border-color: #ffd4d7; color: var(--color-danger); }
|
||||
|
||||
.arc-empty { text-align: center; padding: 52px 20px; color: #b8bcc4; font-size: 13px; }
|
||||
.arc-empty .ico { font-size: 34px; opacity: .35; margin-bottom: 10px; }
|
||||
.arc-empty .sub { font-size: 11.5px; color: #c2c6cc; margin-top: 6px; }
|
||||
|
||||
Reference in New Issue
Block a user