diff --git a/.gitea/workflows/docker-build.yml b/.gitea/workflows/docker-build.yml index 1f5d06c..818dee5 100644 --- a/.gitea/workflows/docker-build.yml +++ b/.gitea/workflows/docker-build.yml @@ -21,6 +21,11 @@ jobs: # 其他 VITE_API_BASE 值。否则 OTA 包里的前端可能连错后端, 导致 # "OTA 更新后登录失败/进不去内部"。与 android-build.yml 保持一致。 VITE_API_BASE: http://bh.vps.honor3.com:3001 + # OTA bundle 要求的最低原生二进制版本。 + # 与 package.json 的应用版本是**两个概念**: 前端 OTA 不碰原生层, + # 现有 APK 仍是 0.1.0, 所以这里固定 0.1.0 (否则旧 APK 会被判定为不兼容而收不到更新)。 + # 重打 APK 并确认原生层无破坏后, 再提升此值。 + OTA_MIN_BINARY: '0.1.0' steps: - uses: https://gitea.com/actions/checkout@v4 @@ -29,6 +34,13 @@ jobs: with: node-version: 22 + - name: Check version matches branch + # 防止 OTA 版本号与分支错位: OTA 包的 version 直接取自 package.json, + # dev-0.2 分支上必须是 0.2.x, 否则线上 OTA 会报成上一个版本的号 + env: + GITHUB_REF_NAME: ${{ github.ref_name }} + run: node scripts/ci/check-version.mjs + - name: Install deps run: npm ci --no-audit --no-fund @@ -47,7 +59,7 @@ jobs: OTA_NOTES: ${{ github.sha }} run: | set -euo pipefail - node scripts/build-ota.mjs --out ota-package --notes ${OTA_NOTES} + node scripts/build-ota.mjs --out ota-package --notes ${OTA_NOTES} --min-binary ${OTA_MIN_BINARY} echo "===== latest.json =====" cat ota-package/latest.json echo "===== bundle sha256 =====" diff --git a/.gitea/workflows/ota-build.yml b/.gitea/workflows/ota-build.yml index d293808..40538a0 100644 --- a/.gitea/workflows/ota-build.yml +++ b/.gitea/workflows/ota-build.yml @@ -21,10 +21,10 @@ on: type: string default: '' min_binary: - description: '最低 binary 版本 (留空用 src-tauri/tauri.conf.json 的 version)' + description: '最低 binary 版本 (默认 0.1.0 = 现有 APK 的原生版本, 与前端应用版本无关)' required: false type: string - default: '' + default: '0.1.0' jobs: build-ota: @@ -56,7 +56,7 @@ jobs: set -euo pipefail OUT="ota-package" ARGS="--out ${OUT}" - # inputs 留空时 → 不传 --sequence/--min-binary, 脚本默认 sequence=时间戳, min-binary=tauri.conf version + # sequence 留空 → 脚本默认用时间戳; min_binary 默认 0.1.0 (与前端版本解耦) if [ -n "${{ inputs.sequence }}" ]; then ARGS="${ARGS} --sequence ${{ inputs.sequence }}"; fi if [ -n "${OTA_NOTES}" ]; then ARGS="${ARGS} --notes ${OTA_NOTES}"; fi if [ -n "${{ inputs.min_binary }}" ]; then ARGS="${ARGS} --min-binary ${{ inputs.min_binary }}"; fi diff --git a/docs/V0.2/界面设计.html b/docs/V0.2/界面设计.html index 0ad34c2..3ca0a4e 100644 --- a/docs/V0.2/界面设计.html +++ b/docs/V0.2/界面设计.html @@ -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)}
@@ -206,8 +243,8 @@打卡 / 日历 / 清单 —— 移动端静态高保真原型(设计基线 420 × 820,适配 375~430px)
@@ -275,7 +312,6 @@环形闭合 + 对勾缩放入场(0.32s);同时 14 颗粒子沿圆周扩散(26~58px,交替主色与金色)+ 主色光环脉冲(0.7s),总时长 ≤900ms,pointer-events:none 不阻塞后续操作;并触发 18ms 轻震动。可在头部一键关闭(持久化开关),系统「减弱动效」时自动降级。
环形闭合 + 对勾缩放入场(0.32s);同时 14 颗粒子沿圆周扩散(26~58px,交替主色与金色)+ 主色光环脉冲(0.7s),总时长 ≤900ms,pointer-events:none 不阻塞后续操作;并触发 18ms 轻震动。特效恒开(V0.2 设计变更:头部不再有开关)。
三个视图均具备加载中 / 空态 / 错误(带重试)三态。空态给出明确引导按钮;头部「特效开 / 特效关」为全局动效开关,关闭后仅保留环形与对勾,不播放粒子与震动。
+三个视图均具备加载中 / 空态 / 错误(带重试)三态。空态给出明确引导按钮。V0.2 设计变更:打卡页头部不再有「特效开 / 特效关」开关,完成特效与触感反馈恒开,没有任何关闭入口。
+「首页」Tab 取消,报警与新闻成为宏观的第 5、6 个子 Tab(/macro/alerts、/macro/news),共 6 个子 Tab 可横向滚动,当前项底部有 3px 主色指示条;报警数量以红色角标挂在子 Tab 上。新闻详情改为 /macro/news/:id,底部「宏观」保持高亮。
开关默认关闭 = 按版本号判新:取服务端 latest.json 的 version(如 0.2.0-ota),与当前运行版本按数字字段逐段比较,更高才提示更新。用于生产,避免旧分支被重建(sequence 变大但版本更小)把设备拉回旧版。开关值保存在设备端 localStorage.iboard_ota_dev_mode。
开关打开 = 按 build sequence 判新:走 hotswap 插件的 checkUpdate(),只要服务端 sequence 比本地大就算新版本——每次 CI 构建 sequence 都会变(默认取时间戳),所以任何一次提交都能推到设备上,适合开发联调。切换开关会清空上一次的检查结果,避免上一种口径的结论误导。
| 项 | 约定 |
|---|---|
| 视口 | 设计稿 420×820;375~430px 内元素不换行、不裁切;底部 TabBar 5 项每项 ≥ 40px 可点宽度 |
| 视口 | 设计稿 420×820;375~430px 内元素不换行、不裁切;底部 TabBar 4 项每项 ≥ 44px 可点宽度 |
| 安全区 | TabBar 使用 antd-mobile safeArea,页面底部留出 tabbar-h + safe-bottom |
| 减弱动效 | 系统开启「减弱动效」或用户关闭特效开关 → 不播放粒子 / 光环 / 震动,只保留环形与对勾 |
| 动效 | 特效恒开(V0.2 设计变更,无开关):单次 ≤900ms、pointer-events:none,不阻塞连续打卡;不再响应 prefers-reduced-motion |
| 大字号 | 卡片采用 grid 自适应列宽,文字超长换行不截断;名称限制 20 字、检查项 40 字 |
| 深色模式 | V0.2 沿用现有浅色主题,暂不适配 |