feat(V0.2): OTA 版本与判新口径 + Tab 结构调整
1) 版本对齐分支 - package.json / tauri.conf.json / Cargo.toml / Cargo.lock: 0.1.0 -> 0.2.0, OTA 包版本变为 0.2.0-ota - 新增 scripts/ci/check-version.mjs: 分支 dev-x.y 与 package.json 版本不一致时 CI 直接失败 - docker-build.yml / ota-build.yml: min_binary_version 与前端版本解耦, 固定 0.1.0 (现有 APK 原生层仍是 0.1.0, 抬高会导致旧 APK 收不到更新) 2) 我的页 OTA「开发版本」开关 (默认关, 持久化 localStorage.iboard_ota_dev_mode) - 关: 按版本号逐字段比较 (src/utils/version.js), 服务端 version 更高才算新 - 开: 按 build sequence 判新 (hotswap checkUpdate), 每次构建都能推到设备 - Web 端: 开发口径退化为版本不同即算新; 生产口径严格比较大小 3) 打卡 Tab 移到最左并默认选中, 移除特效开关 - BottomNav: 打卡/宏观/监控/我; 删除 home 图标 - App: / 与 404 均重定向到 /checkin - RingProgress/Celebrate: 删除 effectsEnabled/setEffectsEnabled, 特效恒开 - HabitView: 去掉头部「特效开/关」按钮 4) 取消首页 Tab, 报警/新闻并入宏观 - 新增 pages/macro/AlertsView.jsx、NewsView.jsx; 删除 HomePage.jsx - MacroPage: 6 个子 Tab (油价/经济数据/策略研究/经济文章/报警/新闻), 报警角标保留 - 新闻详情 /news/:id -> /macro/news/:id (宏观 Tab 保持高亮) 5) 文档: 需求文档补 F-OT 需求点与已决策项; 设计文档新增 §10 变更记录与判新设计; 界面设计.html 11 屏 (Tab 4 项/去掉特效开关/宏观合并/我的 OTA 开关 关+开 两态)
This commit is contained in:
+241
-48
@@ -197,6 +197,43 @@
|
||||
.legend span{display:flex;align-items:center;gap:6px}
|
||||
.note{font-size:12px;color:var(--weak);margin-top:8px}
|
||||
.flow{background:#fff;border:1px solid #e6e8eb;border-radius:12px;padding:16px 18px;font-size:13px;color:#333;white-space:pre;overflow-x:auto;line-height:1.7}
|
||||
|
||||
/* ---------- 宏观子 Tab(6 项,可横向滚动) ---------- */
|
||||
.mtabs{display:flex;gap:18px;padding:10px 14px 8px;overflow-x:auto;background:#fff;border-bottom:1px solid var(--line);font-size:13px;color:var(--muted);white-space:nowrap}
|
||||
.mtabs::-webkit-scrollbar{display:none}
|
||||
.mtabs .on{color:var(--primary);font-weight:600;position:relative}
|
||||
.mtabs .on::after{content:"";position:absolute;left:50%;transform:translateX(-50%);bottom:-9px;width:22px;height:3px;border-radius:2px;background:var(--primary)}
|
||||
.mtabs .badge-dot{display:inline-block;min-width:15px;height:15px;line-height:15px;padding:0 4px;margin-left:3px;
|
||||
background:var(--danger);color:#fff;font-size:10px;border-radius:8px;text-align:center;vertical-align:1px}
|
||||
|
||||
/* ---------- 资讯卡片(报警 / 新闻) ---------- */
|
||||
.feed{padding:10px 14px 14px;display:flex;flex-direction:column;gap:8px}
|
||||
.feed-card{background:#fff;border:1px solid #eef0f2;border-radius:10px;padding:10px 12px;box-shadow:0 1px 2px rgba(0,0,0,.04)}
|
||||
.feed-title{font-size:14px;font-weight:600;line-height:1.45;color:var(--text)}
|
||||
.feed-sub{font-size:12px;color:var(--muted);margin-top:4px;line-height:1.5}
|
||||
.feed-meta{display:flex;gap:10px;font-size:11px;color:var(--weak);margin-top:6px}
|
||||
.feed-meta .rk{color:var(--primary)}
|
||||
.alert-name{color:var(--danger);font-weight:600}
|
||||
|
||||
/* ---------- 我的页 ---------- */
|
||||
.me-head{display:flex;flex-direction:column;align-items:center;gap:4px;padding:18px 0 16px;background:#fff}
|
||||
.me-avatar{width:60px;height:60px;border-radius:50%;background:#e8effd;color:var(--primary);
|
||||
display:flex;align-items:center;justify-content:center;font-size:22px;font-weight:600}
|
||||
.me-name{font-size:16px;font-weight:600}
|
||||
.me-mail{font-size:12px;color:var(--weak)}
|
||||
.me-group{margin:10px 12px 0;background:#fff;border-radius:10px;overflow:hidden;border:1px solid #eef0f2}
|
||||
.me-group .g-head{font-size:12px;color:var(--weak);padding:9px 14px 6px}
|
||||
.me-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:11px 14px;border-top:1px solid var(--line);font-size:14px}
|
||||
.me-group .g-head + .me-row{border-top:none}
|
||||
.me-row .val{font-size:12px;color:var(--weak)}
|
||||
.me-row .hint{font-size:11px;color:var(--weak);margin-top:2px;line-height:1.45}
|
||||
.sw{width:42px;height:25px;border-radius:999px;background:#e5e7eb;position:relative;flex-shrink:0;transition:background .2s}
|
||||
.sw::after{content:"";position:absolute;top:2px;left:2px;width:21px;height:21px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.2)}
|
||||
.sw.on{background:var(--success)}
|
||||
.sw.on::after{left:19px}
|
||||
.me-actions{display:flex;gap:8px;padding:12px 14px;border-top:1px solid var(--line)}
|
||||
.me-actions .mini-btn{flex:1;text-align:center;padding:7px 0;font-size:13px}
|
||||
.me-actions .mini-btn.ghost{border-color:#e5e7eb;color:var(--muted)}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -206,8 +243,8 @@
|
||||
<h1>iBoard V0.2 · 界面设计</h1>
|
||||
<p>打卡 / 日历 / 清单 —— 移动端静态高保真原型(设计基线 420 × 820,适配 375~430px)</p>
|
||||
<div class="meta">
|
||||
<span>版本 V0.2</span><span>分支 dev-0.2</span><span>antd-mobile 风格</span>
|
||||
<span>底部 5 Tab(新增「打卡」)</span><span>时区 Asia/Shanghai</span><span>文档日期 2026-10-22</span>
|
||||
<span>版本 V0.2(0.2.0)</span><span>分支 dev-0.2</span><span>antd-mobile 风格</span>
|
||||
<span>底部 4 Tab(打卡默认)</span><span>时区 Asia/Shanghai</span><span>文档日期 2026-10-22</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -275,7 +312,6 @@
|
||||
<div class="habit-summary">已完成 <strong>2</strong> / 4</div>
|
||||
</div>
|
||||
<div class="head-right">
|
||||
<div class="mini-btn">特效开</div>
|
||||
<div class="mini-btn solid">+ 新建</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -369,14 +405,12 @@
|
||||
</div>
|
||||
<div class="tabbar">
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 11l8-6 8 6v8a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1z"/></svg>首页</div>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -472,11 +506,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabbar">
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 11l8-6 8 6v8a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1z"/></svg>首页</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="caption">
|
||||
@@ -533,11 +570,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabbar">
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 11l8-6 8 6v8a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1z"/></svg>首页</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="caption">
|
||||
@@ -556,7 +596,7 @@
|
||||
<div class="habit-date">10月22日 周四</div>
|
||||
<div class="habit-summary">已完成 <strong>2</strong> / 4</div>
|
||||
</div>
|
||||
<div class="head-right"><div class="mini-btn">特效开</div><div class="mini-btn solid">+ 新建</div></div>
|
||||
<div class="head-right"><div class="mini-btn solid">+ 新建</div></div>
|
||||
</div>
|
||||
<div class="habit-list">
|
||||
<div class="habit-card">
|
||||
@@ -595,11 +635,14 @@
|
||||
<div class="btn-ghost">取消</div>
|
||||
</div>
|
||||
<div class="tabbar">
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 11l8-6 8 6v8a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1z"/></svg>首页</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="caption">
|
||||
@@ -615,7 +658,7 @@
|
||||
<div class="body">
|
||||
<div class="habit-head">
|
||||
<div><div class="habit-date">10月22日 周四</div><div class="habit-summary">已完成 <strong>3</strong> / 4</div></div>
|
||||
<div class="head-right"><div class="mini-btn">特效开</div><div class="mini-btn solid">+ 新建</div></div>
|
||||
<div class="head-right"><div class="mini-btn solid">+ 新建</div></div>
|
||||
</div>
|
||||
<div class="habit-list">
|
||||
<div class="habit-card done" style="overflow:visible">
|
||||
@@ -664,16 +707,19 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabbar">
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 11l8-6 8 6v8a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1z"/></svg>首页</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="caption">
|
||||
<b>2.5 达标瞬间 · 完成特效</b>
|
||||
<p>环形闭合 + 对勾缩放入场(0.32s);同时 14 颗粒子沿圆周扩散(26~58px,交替主色与金色)+ 主色光环脉冲(0.7s),总时长 ≤900ms,<code>pointer-events:none</code> 不阻塞后续操作;并触发 18ms 轻震动。可在头部一键关闭(持久化开关),系统「减弱动效」时自动降级。</p>
|
||||
<p>环形闭合 + 对勾缩放入场(0.32s);同时 14 颗粒子沿圆周扩散(26~58px,交替主色与金色)+ 主色光环脉冲(0.7s),总时长 ≤900ms,<code>pointer-events:none</code> 不阻塞后续操作;并触发 18ms 轻震动。<b>特效恒开</b>(V0.2 设计变更:头部不再有开关)。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -727,11 +773,14 @@
|
||||
<div class="cal-item"><i class="cdot" style="background:#a855f7"></i><span class="cname">吃药</span><span class="cmeta">每天 1 次 · 当日 0/1</span><span class="cplan">待办</span></div>
|
||||
</div>
|
||||
<div class="tabbar">
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 11l8-6 8 6v8a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1z"/></svg>首页</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="caption">
|
||||
@@ -771,11 +820,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabbar">
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 11l8-6 8 6v8a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1z"/></svg>首页</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="caption">
|
||||
@@ -791,7 +843,7 @@
|
||||
<div class="body">
|
||||
<div class="habit-head">
|
||||
<div><div class="habit-date">10月22日 周四</div><div class="habit-summary">已完成 <strong>0</strong> / 0</div></div>
|
||||
<div class="head-right"><div class="mini-btn">特效关</div><div class="mini-btn solid">+ 新建</div></div>
|
||||
<div class="head-right"><div class="mini-btn solid">+ 新建</div></div>
|
||||
</div>
|
||||
<div class="empty">
|
||||
<div class="ico">○</div>
|
||||
@@ -800,16 +852,157 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabbar">
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 11l8-6 8 6v8a1 1 0 0 1-1 1h-4v-6H9v6H5a1 1 0 0 1-1-1z"/></svg>首页</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="caption">
|
||||
<b>2.8 空态</b>
|
||||
<p>三个视图均具备加载中 / 空态 / 错误(带重试)三态。空态给出明确引导按钮;头部「特效开 / 特效关」为全局动效开关,关闭后仅保留环形与对勾,不播放粒子与震动。</p>
|
||||
<p>三个视图均具备加载中 / 空态 / 错误(带重试)三态。空态给出明确引导按钮。<b>V0.2 设计变更</b>:打卡页头部不再有「特效开 / 特效关」开关,完成特效与触感反馈<b>恒开</b>,没有任何关闭入口。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ---------- 2.9 宏观(原首页报警/新闻并入) ---------- -->
|
||||
<div class="shot">
|
||||
<div class="phone">
|
||||
<div class="navbar">宏观</div>
|
||||
<div class="body">
|
||||
<div class="mtabs">
|
||||
<div>油价</div><div>经济数据</div><div>策略研究</div><div>经济文章</div>
|
||||
<div>报警<span class="badge-dot">3</span></div><div class="on">新闻</div>
|
||||
</div>
|
||||
<div class="feed">
|
||||
<div class="feed-card">
|
||||
<div class="feed-title">央行开展 5000 亿元 MLF 操作,中标利率持平</div>
|
||||
<div class="feed-sub">本月 MLF 净投放 2000 亿元,市场流动性保持合理充裕…</div>
|
||||
<div class="feed-meta"><span>妙想财经</span><span>2026-10-22</span><span class="rk">#1</span></div>
|
||||
</div>
|
||||
<div class="feed-card">
|
||||
<div class="feed-title">9 月社零同比增长 3.2%,服务消费延续回暖</div>
|
||||
<div class="feed-sub">餐饮收入增速回升至 5.1%,可选消费分化明显…</div>
|
||||
<div class="feed-meta"><span>妙想财经</span><span>2026-10-21</span><span class="rk">#2</span></div>
|
||||
</div>
|
||||
<div class="feed-card">
|
||||
<div class="feed-title">美联储会议纪要偏鹰,美元指数小幅走强</div>
|
||||
<div class="feed-sub">点阵图显示年内或仍有一次降息空间,但分歧加大…</div>
|
||||
<div class="feed-meta"><span>妙想财经</span><span>2026-10-21</span><span class="rk">#3</span></div>
|
||||
</div>
|
||||
<div class="feed-card">
|
||||
<div class="feed-title">OPEC+ 维持减产节奏,国际油价日内涨逾 1%</div>
|
||||
<div class="feed-sub">布伦特原油重回 78 美元上方,化工链成本端承压…</div>
|
||||
<div class="feed-meta"><span>妙想财经</span><span>2026-10-20</span><span class="rk">#4</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabbar">
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab on">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="caption">
|
||||
<b>2.9 宏观 · 原「首页」报警/新闻并入<span class="tag">设计变更</span></b>
|
||||
<p>「首页」Tab 取消,报警与新闻成为宏观的第 5、6 个子 Tab(<code>/macro/alerts</code>、<code>/macro/news</code>),共 6 个子 Tab 可横向滚动,当前项底部有 3px 主色指示条;报警数量以红色角标挂在子 Tab 上。新闻详情改为 <code>/macro/news/:id</code>,底部「宏观」保持高亮。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ---------- 2.10 我的 · OTA(开发版本 关 = 默认) ---------- -->
|
||||
<div class="shot">
|
||||
<div class="phone">
|
||||
<div class="navbar">我</div>
|
||||
<div class="body">
|
||||
<div class="me-head">
|
||||
<div class="me-avatar">C</div>
|
||||
<div class="me-name">Cheney</div>
|
||||
<div class="me-mail">qian.huang@sunyard.com</div>
|
||||
</div>
|
||||
<div class="me-group">
|
||||
<div class="g-head">前端升级 (OTA)</div>
|
||||
<div class="me-row"><span>当前版本</span><span class="val">v0.2.0 · 20261022.1530</span></div>
|
||||
<div class="me-row"><span>运行资源</span><span class="val">内置</span></div>
|
||||
<div class="me-row">
|
||||
<div>
|
||||
<div>开发版本</div>
|
||||
<div class="hint">按版本号判新:仅当服务端版本号更高时才提示更新</div>
|
||||
</div>
|
||||
<div class="sw"></div>
|
||||
</div>
|
||||
<div class="me-actions">
|
||||
<div class="mini-btn solid">检查更新</div>
|
||||
<div class="mini-btn ghost">立即升级</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabbar">
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="caption">
|
||||
<b>2.10 我的 · OTA「开发版本」关闭(默认)<span class="tag">新功能</span></b>
|
||||
<p>开关默认关闭 = <b>按版本号判新</b>:取服务端 <code>latest.json</code> 的 <code>version</code>(如 <code>0.2.0-ota</code>),与当前运行版本按数字字段逐段比较,<b>更高</b>才提示更新。用于生产,避免旧分支被重建(sequence 变大但版本更小)把设备拉回旧版。开关值保存在设备端 <code>localStorage.iboard_ota_dev_mode</code>。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ---------- 2.11 我的 · OTA(开发版本 开) ---------- -->
|
||||
<div class="shot">
|
||||
<div class="phone">
|
||||
<div class="navbar">我</div>
|
||||
<div class="body">
|
||||
<div class="me-head">
|
||||
<div class="me-avatar">C</div>
|
||||
<div class="me-name">Cheney</div>
|
||||
<div class="me-mail">qian.huang@sunyard.com</div>
|
||||
</div>
|
||||
<div class="me-group">
|
||||
<div class="g-head">前端升级 (OTA)</div>
|
||||
<div class="me-row"><span>当前版本</span><span class="val">v0.2.0 · 20261022.1530</span></div>
|
||||
<div class="me-row"><span>运行资源</span><span class="val">内置</span></div>
|
||||
<div class="me-row">
|
||||
<div>
|
||||
<div>开发版本</div>
|
||||
<div class="hint">按 build sequence 判新:每次构建都算新版本,便于开发联调</div>
|
||||
</div>
|
||||
<div class="sw on"></div>
|
||||
</div>
|
||||
<div class="me-row"><span>新版本</span><span class="val">v0.2.0-ota (288 KB)</span></div>
|
||||
<div class="me-actions">
|
||||
<div class="mini-btn solid">立即升级</div>
|
||||
<div class="mini-btn ghost">回滚</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabbar">
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="8.5"/><path d="M8 12.4l2.6 2.6L16.5 9.5" stroke-linecap="round" stroke-linejoin="round"/></svg>打卡</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 19V9m5 10V5m5 14v-7m5 7V8"/></svg>宏观</div>
|
||||
<div class="tab">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><circle cx="7" cy="7.5" r="1"/><circle cx="7" cy="16.5" r="1"/></svg>监控</div>
|
||||
<div class="tab on">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="8" r="3.6"/><path d="M4.5 20c1.4-3.6 4.1-5.4 7.5-5.4S18.1 16.4 19.5 20"/></svg>我</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="caption">
|
||||
<b>2.11 我的 · OTA「开发版本」打开</b>
|
||||
<p>开关打开 = <b>按 build sequence 判新</b>:走 hotswap 插件的 <code>checkUpdate()</code>,只要服务端 <code>sequence</code> 比本地大就算新版本——每次 CI 构建 sequence 都会变(默认取时间戳),所以任何一次提交都能推到设备上,适合开发联调。切换开关会清空上一次的检查结果,避免上一种口径的结论误导。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -875,9 +1068,9 @@
|
||||
<h2>5 适配与可达性</h2>
|
||||
<table>
|
||||
<tr><th>项</th><th>约定</th></tr>
|
||||
<tr><td>视口</td><td>设计稿 420×820;375~430px 内元素不换行、不裁切;底部 TabBar 5 项每项 ≥ 40px 可点宽度</td></tr>
|
||||
<tr><td>视口</td><td>设计稿 420×820;375~430px 内元素不换行、不裁切;底部 TabBar 4 项每项 ≥ 44px 可点宽度</td></tr>
|
||||
<tr><td>安全区</td><td>TabBar 使用 antd-mobile <code>safeArea</code>,页面底部留出 <code>tabbar-h + safe-bottom</code></td></tr>
|
||||
<tr><td>减弱动效</td><td>系统开启「减弱动效」或用户关闭特效开关 → 不播放粒子 / 光环 / 震动,只保留环形与对勾</td></tr>
|
||||
<tr><td>动效</td><td><b>特效恒开</b>(V0.2 设计变更,无开关):单次 ≤900ms、<code>pointer-events:none</code>,不阻塞连续打卡;不再响应 <code>prefers-reduced-motion</code></td></tr>
|
||||
<tr><td>大字号</td><td>卡片采用 grid 自适应列宽,文字超长换行不截断;名称限制 20 字、检查项 40 字</td></tr>
|
||||
<tr><td>深色模式</td><td>V0.2 沿用现有浅色主题,暂不适配</td></tr>
|
||||
</table>
|
||||
|
||||
+108
-16
@@ -2,8 +2,8 @@
|
||||
|
||||
| 项 | 内容 |
|
||||
| --- | --- |
|
||||
| 版本 | V0.2(对应分支 `dev-0.2`) |
|
||||
| 文档状态 | 已实现(与代码一致) |
|
||||
| 版本 | V0.2(对应分支 `dev-0.2`,应用版本 `0.2.0`) |
|
||||
| 文档状态 | 已实现(与代码一致;含 2026-10-22 设计变更,见 §10) |
|
||||
| 上游文档 | `需求文档.md`(需求编号 F-CK / F-CL / F-LS / F-SY / U / D / N / E 沿用本文) |
|
||||
| 配套文档 | `数据库设计文档.md`、`界面设计.html` |
|
||||
| 技术栈 | Tauri 2 + React 18 + antd-mobile + React Router v6 + Express 4 + Prisma/MariaDB |
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
### 1.1 目标与范围
|
||||
|
||||
在既有 iBoard(首页 / 宏观 / 监控 / 我)之上新增**第 5 个底部 Tab「打卡」**,页面内以三个子视图承载三类需求:
|
||||
在既有 iBoard 之上**新增「打卡」模块并升为默认首页**(底部 Tab 由 5 个精简为 4 个:打卡 / 宏观 / 监控 / 我),页面内以三个子视图承载三类需求:
|
||||
|
||||
| 子视图 | 解决问题 | 核心隐喻 |
|
||||
| --- | --- | --- |
|
||||
@@ -23,17 +23,29 @@
|
||||
| **日历** | 回看昨天、执行今天、预知明天 | 月历网格 + 日状态点 |
|
||||
| **清单** | 出差/回老家等一次性场景的漏项检查 | 勾选清单 + 进度条 |
|
||||
|
||||
> **Tab 结构(V0.2 终态)**
|
||||
>
|
||||
> | 顺序 | Tab | 路由 | 说明 |
|
||||
> | --- | --- | --- | --- |
|
||||
> | 1 | **打卡(默认)** | `/checkin` | 根路径 `/` 重定向到此;`/checkin` 内含 打卡/日历/清单 三视图 |
|
||||
> | 2 | 宏观 | `/macro/*` | 油价 / 经济数据 / 策略研究 / 经济文章 / **报警** / **新闻**(后两者由原「首页」并入) |
|
||||
> | 3 | 监控 | `/monitor` | 服务器 + 米家环境 |
|
||||
> | 4 | 我 | `/me` | 用户信息 + 前端 OTA 升级 |
|
||||
>
|
||||
> 原「首页」Tab 已移除:其中的**报警**、**新闻** 两个模块并入宏观,作为其第 5、6 个子 Tab(`/macro/alerts`、`/macro/news`),新闻详情改为 `/macro/news/:id` 以保持宏观 Tab 高亮。
|
||||
|
||||
**不纳入 V0.2**:多用户共享清单、提醒推送、数据导出、打卡项分组、年视图热力图(见 §9 演进)。
|
||||
|
||||
### 1.2 架构总览
|
||||
|
||||
```
|
||||
┌──────────────────────── 前端 (React + antd-mobile, 打包进 Tauri / OTA) ────────────────────────┐
|
||||
│ App.jsx 路由 │
|
||||
│ App.jsx 路由 (默认 / → /checkin) │
|
||||
│ └ /checkin ──► CheckinPage ── SwipeTabs ──┬── HabitView (打卡) │
|
||||
│ ├── CalendarView (日历) │
|
||||
│ └── ListView (清单) │
|
||||
│ 组件: RingProgress(环形) / Celebrate(特效) / BottomNav / TabIcon │
|
||||
│ └ /macro/* ──► MacroPage ── 油价/经济数据/策略研究/经济文章/报警/新闻 │
|
||||
│ 组件: RingProgress(环形) / Celebrate(特效, 恒开) / BottomNav / TabIcon │
|
||||
│ 工具: src/pages/checkin/date.js (本地日期, 与后端同口径) apiClient: src/api/checkin.js │
|
||||
└──────────────────────────────────┬─────────────────────────────────────────────────────────────┘
|
||||
│ HTTPS + JWT (Authorization: Bearer)
|
||||
@@ -52,7 +64,7 @@
|
||||
| 层 | 位置 | 职责 |
|
||||
| --- | --- | --- |
|
||||
| 页面 | `src/pages/checkin/*.jsx` | 视图编排、本地状态、乐观更新与回滚 |
|
||||
| 组件 | `src/components/RingProgress.jsx` | 纯展示:SVG 环形 + 完成特效 + 特效开关 |
|
||||
| 组件 | `src/components/RingProgress.jsx` | 纯展示:SVG 环形 + 完成特效(恒开,无开关) |
|
||||
| 日期工具 | `src/pages/checkin/date.js` | 与后端同口径的本地日期运算(**改一处需同步另一处**) |
|
||||
| API 封装 | `src/api/checkin.js` | 统一走 `api()`(自带 token / 错误解析) |
|
||||
| 路由 | `server/routes/checkin.js`、`checklists.js` | 参数校验、鉴权、组装展示态 |
|
||||
@@ -72,16 +84,24 @@ server/
|
||||
index.js # 挂载两个路由
|
||||
src/
|
||||
api/checkin.js # checkinApi / checklistApi
|
||||
api/ota.js # OTA 封装 + 判新模式(version/sequence)
|
||||
utils/version.js # 版本号字段比较(纯函数, 可单测)
|
||||
utils/format.js # 日期格式化
|
||||
components/RingProgress.jsx # 环形进度 + Celebrate 特效
|
||||
components/BottomNav.jsx # 新增「打卡」Tab
|
||||
components/TabIcon.jsx # 新增 checkin 图标
|
||||
components/BottomNav.jsx # Tab: 打卡(默认)/宏观/监控/我
|
||||
components/TabIcon.jsx # 图标集(移除 home)
|
||||
pages/checkin/CheckinPage.jsx # 容器:三视图切换
|
||||
pages/checkin/HabitView.jsx # 打卡视图
|
||||
pages/checkin/CalendarView.jsx # 日历视图
|
||||
pages/checkin/ListView.jsx # 清单视图
|
||||
pages/checkin/date.js # 前端日期工具
|
||||
App.jsx # 新增 /checkin 路由
|
||||
pages/MacroPage.jsx # 宏观: 6 个子 Tab(含报警/新闻)
|
||||
pages/macro/AlertsView.jsx # 报警(原首页)
|
||||
pages/macro/NewsView.jsx # 新闻(原首页)
|
||||
pages/MePage.jsx # 我: OTA 组内「开发版本」开关
|
||||
App.jsx # / → /checkin; /macro/*; 移除 /news/:id
|
||||
styles/globals.css # 打卡相关样式段
|
||||
scripts/ci/check-version.mjs # CI: 校验分支名 ↔ package.json 版本
|
||||
docs/V0.2/ # 需求 / 设计 / 数据库设计 / 界面设计
|
||||
```
|
||||
|
||||
@@ -126,14 +146,19 @@ docs/V0.2/ # 需求 / 设计 / 数据
|
||||
### 3.1 路由与容器
|
||||
|
||||
```
|
||||
底部 Tab (BottomNav) 打卡(默认) ─ 宏观 ─ 监控 ─ 我
|
||||
/ → <Navigate to="/checkin" replace />
|
||||
/checkin → CheckinPage
|
||||
├─ NavBar「打卡」
|
||||
└─ SwipeTabs(左右滑动切换,与既有模块交互一致)
|
||||
├─ habit → HabitView (受 date 影响)
|
||||
├─ calendar → CalendarView (持有选中 date,可回写容器)
|
||||
└─ list → ListView (独立)
|
||||
/macro/* → MacroPage (油价 / 经济数据 / 策略研究 / 经济文章 / 报警 / 新闻)
|
||||
```
|
||||
|
||||
`activeKeyFromPath()` 对未匹配路径兜底返回**第一个 Tab(`/checkin`)**,与默认路由保持一致。
|
||||
|
||||
`date` 状态提升到 `CheckinPage`:日历里点某天 → 切回打卡视图时即为该日,实现「日历与打卡联动」。
|
||||
|
||||
### 3.2 组件树与关键状态
|
||||
@@ -144,8 +169,7 @@ CheckinPage
|
||||
HabitView(date)
|
||||
├── data: { today, date, items[], summary:{total,done} }
|
||||
├── bursts: { habitId: n } // 特效触发计数(+1 即播放一次)
|
||||
├── form / showForm // 新建/编辑弹窗
|
||||
└── effects: boolean // 特效开关(持久化 localStorage)
|
||||
└── form / showForm // 新建/编辑弹窗
|
||||
CalendarView(date, onDateChange)
|
||||
├── month, cal(月历), detail(当日), bursts
|
||||
└── quickValue: -1|0|1|null // 昨天/今天/明天 分段控件
|
||||
@@ -167,15 +191,15 @@ ListView()
|
||||
| 动画 | `transition: stroke-dashoffset .45s cubic-bezier(.4,0,.2,1)`(400ms 级,U-01) |
|
||||
| 中心内容 | 未达标 → `done / target` 数字;**达标 → 对勾 SVG**(`ring-check-in` 缩放入场);超额 → 右上角 `+n` 徽标 |
|
||||
| 交互 | 整个环可点 = 打卡(`clickable`),同时卡片右侧保留显式「打卡」按钮,降低发现成本 |
|
||||
| 无障碍/降级 | `disabled` 态半透明;系统「减弱动效」时特效自动关闭 |
|
||||
| 无障碍/降级 | `disabled` 态半透明;**完成特效恒开**(V0.2 设计变更:取消页面内特效开关,无任何关闭入口) |
|
||||
|
||||
**完成特效 `Celebrate`**(F-CK-07 / U-02):`fire` 计数器 +1 即触发一次 → 14 个粒子沿圆周角度扩散(`--a/--d` CSS 变量)+ 主色光环脉冲 0.7s,总时长 ≤900ms,`pointer-events:none` 不阻塞后续操作;同时 `navigator.vibrate(18)` 轻震动(U-03)。开关持久化在 `localStorage.iboard_celebrate`,`prefers-reduced-motion` 自动降级(U-07)。
|
||||
**完成特效 `Celebrate`**(F-CK-07 / U-02):`fire` 计数器 +1 即触发一次 → 14 个粒子沿圆周角度扩散(`--a/--d` CSS 变量)+ 主色光环脉冲 0.7s,总时长 ≤900ms,`pointer-events:none` 不阻塞后续操作;同时 `navigator.vibrate(18)` 轻震动(U-03)。**特效永远播放**,不再读 `localStorage.iboard_celebrate`,也不再响应 `prefers-reduced-motion` 关闭(用户明确要求「特效永远打开」)。
|
||||
|
||||
### 3.4 交互清单
|
||||
|
||||
| 视图 | 主要交互 |
|
||||
| --- | --- |
|
||||
| 打卡 | 点环/点按钮打卡(乐观更新,失败回滚 + Toast)、撤销、编辑、归档、新建弹窗(名称/周期/目标次数/颜色/备注)、特效开关 |
|
||||
| 打卡 | 点环/点按钮打卡(乐观更新,失败回滚 + Toast)、撤销、编辑、归档、新建弹窗(名称/周期/目标次数/颜色/备注) |
|
||||
| 日历 | 月份左右切换、回到今天、「昨天/今天/明天」分段切换、点日期选中、当日详情内打卡(未来日期只读显示「计划」)、本月完成率 |
|
||||
| 清单 | 进行中/已归档切换、展开/收起、逐条勾选、添加检查项、全选/全不选、复制、存为模板、归档/恢复、删除、从模板新建 |
|
||||
|
||||
@@ -298,6 +322,7 @@ ListView()
|
||||
| 层级 | 内容 | 结果 |
|
||||
| --- | --- | --- |
|
||||
| 单元 | 周期工具 23 条断言(窗口边界、周一起始、月末、闰年、日均期望、streak 跳过未结束周期) | 全通过 |
|
||||
| 单元 | 版本比较 10 条断言(`-ota` 后缀、`v` 前缀、缺位补 0、`0.10 > 0.9`、`beta.3 < beta.10`、空串) | 全通过 |
|
||||
| 接口冒烟 | 自签 JWT 端到端:每天 1 次闭合、每周 3 次 33.3%、超额 +1、撤销归零、未来日期 400、月历 31 天、模板生成 11 项、全选完成、复制重置 | 全通过,测试数据已清理 |
|
||||
| 构建 | `npm run build` | 通过 |
|
||||
| 迁移 | `prisma migrate deploy` 到目标库 | 成功 |
|
||||
@@ -323,8 +348,8 @@ ListView()
|
||||
| 周期口径前后端各实现一份 | 前端需离线即时反馈,不能等接口 | 两端算法同源同注释;口径变更必须同步 `period.js` 与 `date.js`(已写入项目记忆) |
|
||||
| 进度实时聚合而非冗余计数 | 换取一致性与配置即时生效,牺牲少量 CPU | 单用户数据量极小(月历 30 天 × 20 项),实测无感;V0.3 可加汇总表 |
|
||||
| 未来日期禁止打卡 | 防止「提前打完一周」刷进度,符合「日历看明天=计划」语义 | 明天视图只读展示「计划」,明确文案 |
|
||||
| 特效可能打扰 | 部分用户不喜动效 | 一键开关 + `prefers-reduced-motion` 自动降级 |
|
||||
| 新增第 5 个 Tab | 底部空间变拥挤 | 图标线性简洁;`TabBar` 原生 safe-area,5 项在 375px 下仍在可点区(≥44px) |
|
||||
| 特效恒开可能打扰 | 用户明确要求「特效永远打开」,不再提供开关 | 单次特效 ≤900ms 且 `pointer-events:none`,不影响连续打卡;若后续需要再评估恢复开关 |
|
||||
| Tab 调整为 4 个(打卡置左并默认) | 首页被取消,报警/新闻并入宏观后宏观有 6 个子 Tab | 子 Tab 可横向滚动;报警角标保留在子 Tab 上;底部 4 项在 375px 下热区充足(≥44px) |
|
||||
|
||||
---
|
||||
|
||||
@@ -336,3 +361,70 @@ ListView()
|
||||
4. **打卡项分组与排序拖拽**:现有 `sortOrder` 已预留,仅需交互。
|
||||
5. **清单协作/分享**:引入 `CheckListShare`。
|
||||
6. **数据导出**:清单完成后导出为图片或文本(便于发群里确认)。
|
||||
|
||||
---
|
||||
|
||||
## 10. 设计变更记录(2026-10-22)
|
||||
|
||||
### 10.1 变更清单
|
||||
|
||||
| # | 类型 | 变更 | 影响文件 |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Bug | OTA 包版本与分支不对应:`dev-0.2` 上仍是 `0.1.0` → OTA 报成 `0.1.0-ota`。统一升到 `0.2.0`,OTA 包变为 **`0.2.0-ota`**,并加 CI 强校验 | `package.json`、`src-tauri/tauri.conf.json`、`src-tauri/Cargo.toml`、`Cargo.lock`、`scripts/ci/check-version.mjs`、`docker-build.yml` |
|
||||
| 2 | 功能 | 我的页 OTA 组新增**「开发版本」Switch**(默认关),切换判新口径:开=`build sequence`,关=版本号字段比较;开关值持久化在设备端 | `src/api/ota.js`、`src/utils/version.js`、`src/pages/MePage.jsx` |
|
||||
| 3 | 设计 | 打卡 Tab 移到**最左边并默认选中**;打卡页移除**特效开关**,特效永远打开 | `BottomNav.jsx`、`App.jsx`、`TabIcon.jsx`、`HabitView.jsx`、`RingProgress.jsx`、`globals.css` |
|
||||
| 4 | 设计 | 取消「首页」Tab,其**报警 / 新闻**并入宏观,成为宏观的第 5、6 个子 Tab | `MacroPage.jsx`、新增 `macro/AlertsView.jsx`、`macro/NewsView.jsx`、删除 `HomePage.jsx` |
|
||||
|
||||
### 10.2 OTA 版本号为什么必须跟分支走
|
||||
|
||||
`scripts/build-ota.mjs` 里 `manifest.version = package.json.version + '-ota'`,也就是**版本号的唯一来源仍是 `package.json`**。
|
||||
分支按版本命名(`dev-0.2`),但版本号是手工改的,一旦忘改就会出现「分支 0.2、包版本 0.1」的错位,客户端判新逻辑全部失准。
|
||||
|
||||
| 环节 | 取值 | 现状 |
|
||||
| --- | --- | --- |
|
||||
| `package.json` `version` | `0.2.0` | 唯一手动管理点 |
|
||||
| OTA `latest.json.version` | `0.2.0-ota` | 打包脚本自动拼 `-ota` 后缀 |
|
||||
| `src/version.js` `APP_VERSION` | `0.2.0` | 前端展示与版本比较的基准 |
|
||||
| OTA `latest.json.min_binary_version` | `0.1.0` | **与前端版本解耦**:前端 bundle 要求的最低原生二进制版本。现有 APK 原生层仍是 0.1.0,跟着抬会导致旧 APK 收不到更新,CI 固定传 `--min-binary 0.1.0` |
|
||||
| CI 守卫 | `scripts/ci/check-version.mjs` | 从 `GITHUB_REF_NAME` 解析 `dev-<major>.<minor>`,要求 `version` 以该前缀开头,否则**构建直接失败**;`main`/`master` 跳过 |
|
||||
|
||||
### 10.3 判新口径:版本号 vs build sequence
|
||||
|
||||
「我的 → 前端升级 (OTA)」组内新增 `开发版本` 开关(antd-mobile `Switch`),默认**关闭**:
|
||||
|
||||
| 开关 | 判新依据 | 实现路径 | 适用场景 |
|
||||
| --- | --- | --- | --- |
|
||||
| **关(默认)** | **版本号字段大小** | `GET /api/ota/check/0` 取 `manifest.version` → `compareVersion(manifest.version, 当前运行版本) > 0` 才算新 | 生产口径。旧分支被重新构建(sequence 变大但版本更小)时不会把设备拉回旧版 |
|
||||
| **开** | **build sequence** | `tauri-plugin-hotswap` 的 `checkUpdate()`(内部拿本地 sequence 请求 `/api/ota/check/:seq`,服务端只回比它大的) | 开发联调。每次构建 sequence 都变,保证任何一次提交都能推到设备上 |
|
||||
|
||||
补充约定:
|
||||
|
||||
- **持久化**:`localStorage['iboard_ota_dev_mode'] = '1' | '0'`(默认 `'0'`)。值只存在设备端 WebView 存储里,不进数据库、不上报,换设备/清数据即回默认。
|
||||
- **当前运行版本**:已应用过 OTA 覆盖包时取覆盖包 `version`(插件 `getVersionInfo()`),否则取内置包 `APP_VERSION`;避免「内置包 0.1.0 + 覆盖包 0.2.0」时永远判定有新版本。
|
||||
- **切换开关会重置检查结果**(`otaState='idle'`、清空 `otaInfo`),避免上一种口径的结论误导用户。
|
||||
- **Web 端**:浏览器里拿不到本地 sequence。默认口径按版本号比较;开发口径退化为「服务端版本 ≠ 本地版本即算新」(近似 sequence 语义)。Web 端只提示刷新,不下载不替换,与原设计一致。
|
||||
|
||||
**版本比较算法**(`src/utils/version.js`,纯函数可单测):
|
||||
|
||||
```js
|
||||
parseVersionFields('0.2.0-ota') // → [0, 2, 0]
|
||||
compareVersion('0.2.0-ota','0.1.0') // → 1 (0.2.0 更新)
|
||||
compareVersion('0.2','0.2.0') // → 0 (缺位补 0)
|
||||
```
|
||||
|
||||
规则:按非数字字符切段 → 过滤空段 → 转数字 → 逐段比较,位数不足补 0。单测 10 条覆盖 `-ota` 后缀、`v` 前缀、多位段(`0.10 > 0.9`)、空串、`beta.3 < beta.10`,全部通过。
|
||||
|
||||
### 10.4 交互与信息架构变更
|
||||
|
||||
| 项 | 变更前 | 变更后 |
|
||||
| --- | --- | --- |
|
||||
| 底部 Tab | 首页 / 宏观 / 监控 / 打卡 / 我(5 个) | **打卡 / 宏观 / 监控 / 我(4 个)**,打卡在最左 |
|
||||
| 默认落地 | `/` → 首页(默认选中新闻) | `/` → **`/checkin`**;`RedirectIfAuthed` 与 404 兜底同样指向 `/checkin` |
|
||||
| 报警 / 新闻 | 首页内的 2 个 Tab | 宏观的第 5、6 个子 Tab(`/macro/alerts`、`/macro/news`),报警角标保留 |
|
||||
| 新闻详情 | `/news/:id`(底部无 Tab 高亮) | **`/macro/news/:id`**(宏观 Tab 保持高亮) |
|
||||
| 打卡页头部 | `[特效开/关]` + `[+ 新建]` | 只保留 `[+ 新建]`;特效恒开 |
|
||||
| 特效实现 | `effectsEnabled()` 读 `localStorage.iboard_celebrate` + `prefers-reduced-motion` 降级 | 删除开关与降级判断,`Celebrate` 只要 `fire` 变化就播放 |
|
||||
|
||||
### 10.5 界面设计同步
|
||||
|
||||
`界面设计.html` 已同步:底部 Tab 改为 4 项且「打卡」高亮在首位、打卡页去掉特效开关按钮、新增「我的 · OTA 开发版本开关」屏、宏观新增「报警 / 新闻」子 Tab 与合并后的 6 Tab 导航。
|
||||
|
||||
+22
-9
@@ -117,7 +117,7 @@
|
||||
|
||||
| 编号 | 需求描述 | 验收要点 | 优先级 |
|
||||
| --- | --- | --- | --- |
|
||||
| F-SY-01 | 底部 TabBar 新增**「打卡」页** 和 **「清单」页** | 图标风格与现有 TabIcon 一致 | P0 |
|
||||
| F-SY-01 | 底部 TabBar 新增**「打卡」页**,并作为**默认首页放在最左**;「清单」不单独占 Tab,作为打卡页内的第三个子视图 | 图标风格与现有 TabIcon 一致;启动即进入 `/checkin` | P0 |
|
||||
| F-SY-02 | 「打卡」页内集成 打卡/日历 两个功能,日历放在上半截,默认显示一行为周视图,下拉显示为月视图。 | 日历中选择时间与下部打卡任务联动 | P0 |
|
||||
| F-SY-03 | 所有接口复用现有鉴权(`authRequired`,JWT),数据按 `userId` 隔离 | 未登录跳转 `/login` | P0 |
|
||||
| F-SY-04 | 后端新增 REST 路由(建议 `/api/checkin/*`、`/api/checklist/*`),挂载到 `server/index.js` | 与现有路由风格一致 | P0 |
|
||||
@@ -132,11 +132,11 @@
|
||||
| --- | --- | --- | --- |
|
||||
| U-01 | **环形进度组件**:SVG 圆环,背景环 + 进度环,进度变化带 400ms ease-out 动画 | 组件可复用(打卡卡片、清单进度共用) | P0 |
|
||||
| U-02 | **完成特效**:达标瞬间环形闭合 + 光晕/粒子扩散,约 600ms;可重复观看不烦扰 | 不阻塞操作,动画结束自动清理 | P0 |
|
||||
| U-03 | **触感反馈**:完成打卡时轻量震动(Web Vibration API / Tauri),可在设置中关闭 | 默认开启,关闭后仅视觉反馈 | P1 |
|
||||
| U-03 | **触感反馈**:完成打卡时轻量震动(Web Vibration API / Tauri) | 固定开启,与特效一同触发 | P1 |
|
||||
| U-04 | 移动端适配:375~430px 视口,复用 `globals.css` 的 `.card` 体系,安全区与底部 TabBar 不遮挡内容 | 真机无横向滚动、无遮挡 | P0 |
|
||||
| U-05 | 空态 / 加载态 / 错误态三态齐全(首次使用引导"创建第一个打卡项") | 空态有明确 CTA | P0 |
|
||||
| U-06 | 打卡按钮足够大(点击热区 ≥ 44×44),符合移动端触控规范 | 误触率低 | P1 |
|
||||
| U-07 | 动效**性能降级**:低端设备或 `prefers-reduced-motion` 时关闭粒子特效,仅保留进度动画 | 不卡顿 | P1 |
|
||||
| U-07 | 动效**性能降级**:特效保持轻量(单次 ≤900ms、`pointer-events:none`),不给低端机造成卡顿 | 不卡顿、不阻塞操作 | P1 |
|
||||
| U-08 | 深浅色:跟随现有浅色主题,卡片/分割线风格与首页、监控页一致 | 视觉统一 | P1 |
|
||||
| U-09 | 清单勾选有明确的勾选动画(勾形描边动画) | 反馈即时 | P2 |
|
||||
|
||||
@@ -174,12 +174,23 @@
|
||||
| E-07 | 清单项全部删除后清单进度为 0/0 | 显示空清单,不显示 100% | P1 |
|
||||
| E-08 | 跨零点打卡(23:59 → 00:00) | 以**提交时刻的本地日历日**归属 | P0 |
|
||||
|
||||
### 3.9 功能需求 — 版本与升级(F-OT,2026-10-22 追加)
|
||||
|
||||
| 编号 | 需求描述 | 验收要点 | 优先级 |
|
||||
| --- | --- | --- | --- |
|
||||
| F-OT-01 | **OTA 包版本必须与分支对应**:`dev-0.2` 分支上 OTA 包版本应为 `0.2.0-ota` | `GET /api/ota/check/0` 返回 `version = 0.2.0-ota` | P0 |
|
||||
| F-OT-02 | 版本号错位在 CI 阶段就拦住:分支名 `dev-x.y` 与 `package.json` 版本主次号不一致时构建失败 | CI 输出明确报错并中断 | P0 |
|
||||
| F-OT-03 | 「我」页 OTA 组内新增**「开发版本」开关**,默认**关闭** | 关闭=按版本号比较;打开=按 build sequence 比较 | P0 |
|
||||
| F-OT-04 | 开关值**持久化在设备端**,重启 App 后保持上次选择 | 杀进程重进仍为上次状态 | P0 |
|
||||
| F-OT-05 | 版本号比较规则:按非数字字符切成数字字段,逐段比较大小(`0.2.0 > 0.1.0`,`0.10 > 0.9`) | 单测覆盖后缀/前缀/缺位/多位段 | P0 |
|
||||
| F-OT-06 | 切换开关后清空上一次的检查结果,避免误判 | 切换即回到「未检查」状态 | P1 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 优先级汇总(本期交付范围)
|
||||
|
||||
- **P0(必须)**:F-CK-01~08、F-CK-11;F-CL-01~08;F-LS-01~04;F-SY-01~05;U-01、U-02、U-04、U-05;D-01~05;N-01、N-02、N-04、N-05;E-01、E-02、E-04、E-05、E-08。
|
||||
- **P1(应该)**:F-CK-09、10、12~14;F-CL-09;F-LS-05~09;F-SY-06~08;U-03、U-06~08;D-06;N-03;E-03、E-06、E-07。
|
||||
- **P0(必须)**:F-CK-01~08、F-CK-11;F-CL-01~08;F-LS-01~04;F-SY-01~05;F-OT-01~05;U-01、U-02、U-04、U-05;D-01~05;N-01、N-02、N-04、N-05;E-01、E-02、E-04、E-05、E-08。
|
||||
- **P1(应该)**:F-CK-09、10、12~14;F-CL-09;F-LS-05~09;F-SY-06~08;F-OT-06;U-03、U-06~08;D-06;N-03;E-03、E-06、E-07。
|
||||
- **P2(可选/延后)**:F-CK-15~17;F-CL-10、11;F-LS-10、11;U-09。
|
||||
|
||||
---
|
||||
@@ -200,12 +211,12 @@
|
||||
|
||||
| # | 问题 | 建议 |
|
||||
| --- | --- | --- |
|
||||
| 1 | 是否新增第 5 个底部 Tab「打卡」,还是放在首页入口? | 建议新增 Tab,入口最清晰 |
|
||||
| 1 | 是否新增第 5 个底部 Tab「打卡」,还是放在首页入口? | ✅ **已决策(2026-10-22)**:「打卡」作为**默认首页放在最左**;原来的「首页」取消,报警/新闻并入宏观 |
|
||||
| 2 | 周起始日是周一还是周日? | 建议周一(国内习惯) |
|
||||
| 3 | 是否允许"明天提前打卡"? | 建议**不允许**(F-CK-11),保持统计口径干净 |
|
||||
| 4 | 删除打卡项时历史是否保留? | 建议默认归档保留,硬删除才清历史 |
|
||||
| 5 | 预置模板具体包含哪些项? | 评审时列出"出差/回老家"各 8~12 条初始项 |
|
||||
| 6 | 完成特效是否可全局关闭? | 建议在"我"页提供开关(默认开) |
|
||||
| 6 | 完成特效是否可全局关闭? | ✅ **已决策(2026-10-22)**:不提供关闭入口,**特效永远打开**;页面内不再有特效开关 |
|
||||
|
||||
---
|
||||
|
||||
@@ -308,8 +319,10 @@ model CheckListTemplate {
|
||||
| B-6 | **撤销语义** | 撤销删除本周期内"最近一次"打卡(按 date desc、seq desc 取第一条) |
|
||||
| B-7 | **删除打卡项** | 默认归档(`archived=true`,历史保留);`?hard=1` 才物理删除并清记录 |
|
||||
| B-8 | **接口前缀** | 打卡 `/api/checkin/*`、清单 `/api/checklists/*`,全部 `authRequired`,数据按 `userId` 隔离 |
|
||||
| B-9 | **前端入口** | 底部新增第 5 个 Tab「打卡」→ `/checkin`,页内三视图:打卡 / 日历 / 清单 |
|
||||
| B-10 | **特效开关** | 完成特效 + 触感反馈受 `localStorage iboard_celebrate` 控制(默认开),系统开启"减弱动效"时自动降级 |
|
||||
| B-9 | **前端入口** | 底部 Tab 4 个:**打卡(最左,默认选中)** / 宏观 / 监控 / 我;`/` 重定向到 `/checkin`,页内三视图:打卡 / 日历 / 清单。原「首页」取消,报警/新闻并入宏观 |
|
||||
| B-10 | **特效** | 完成特效 + 触感反馈**恒开**,页面内不提供开关(2026-10-22 变更,原 `localStorage iboard_celebrate` 机制已移除) |
|
||||
| B-11 | **OTA 版本** | OTA 包 `version = package.json.version + '-ota'`,必须与分支一致(`dev-0.2` → `0.2.0-ota`),CI 有强校验 |
|
||||
| B-12 | **OTA 判新** | 我的页「开发版本」开关(默认关,持久化 `localStorage.iboard_ota_dev_mode`):关=版本号字段比较,开=build sequence 比较 |
|
||||
|
||||
### 接口清单
|
||||
|
||||
|
||||
Reference in New Issue
Block a user