diff --git a/.gitignore b/.gitignore index 2650016..4669fd9 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ project.private.config.json # Local agent/tooling state .agents/ .claude/ +.understand-anything/ skills-lock.json # Runtime logs diff --git a/DESIGN_SYSTEM.md b/DESIGN_SYSTEM.md index 81dd91e..f2f9dec 100644 --- a/DESIGN_SYSTEM.md +++ b/DESIGN_SYSTEM.md @@ -55,12 +55,11 @@ The project currently has no frontend build step and no mini program npm depende ## Component Patterns - `BottomAction`: fixed above the custom tab bar, opaque, with one short title, one helper line, and one primary action. Use it for page-level submit actions so primary buttons do not hide behind the tab bar. -- `FormSection`: grouped form area with a section title, helper note, and related fields. Use it instead of one long undifferentiated form card. +- `FormSection`: grouped form area with a section title and related fields. Helper notes are optional and should be omitted when field labels and placeholders already explain the task. - `CategoryOption`: two-column direct-choice buttons for small option sets such as task categories. Prefer this over a picker when the choices are few and user-facing. -- `DrawerCounter`: compact number block in bottom drawers to make counts scannable without adding another sentence. - `SignalPill`: small metric tile for repeated task-card signals such as confirmation count, stale count, and remaining time. -- `PublishReadiness`: compact checklist near the top of the publish form. It should show identity, content, category, and location completion so the fixed submit action can explain or trigger the next required step. - `LocationCheck`: explicit location confirmation block in the publish form. Use it when location is required for correctness; show idle, loading, ready, and failed states without moving the submit button, and make retry language non-technical. +- Publish readiness should be expressed through `LocationCheck` and the fixed `BottomAction`; avoid adding a separate checklist when the bottom action can name the next required step. - `TrustInsight`: detail-page section placed before trust actions. Summarize confirmations, stale reports, reports, and comment count into one cautious status sentence, then show compact segmented metrics and the next sensible action. Use it to explain the counts without implying absolute trust. - `MapListEntry`: keep the collapsed map list entry as a compact top-right `cover-view` button with the label and count on one centered text line, such as "列表 6". Do not split the label and count into separate baseline-sensitive nodes, and do not use a bottom dock for this entry. - `MapToolRow`: location and discover controls sit together at the lower-right of the map above the custom tab bar. Keep them as `cover-view` controls with solid backgrounds, and keep selected task cards above this tool row so icons remain tappable. diff --git a/harness/candidate-publish-trust-report.md b/harness/candidate-publish-trust-report.md index 031c5dc..3e02c11 100644 --- a/harness/candidate-publish-trust-report.md +++ b/harness/candidate-publish-trust-report.md @@ -2,6 +2,8 @@ 日期:2026-06-13 +说明:这是历史候选分支报告,不是当前发布页手测清单;当前 UI 已移除单独的发布准备度清单卡片,发布状态由定位块和底部主按钮承载。 + 分支:`codex/iter-candidate-publish-trust` 基础:`codex/iter-publish-flow` HEAD `2187007` diff --git a/harness/check-trust-insight.mjs b/harness/check-trust-insight.mjs index d58f1b2..dbf21aa 100644 --- a/harness/check-trust-insight.mjs +++ b/harness/check-trust-insight.mjs @@ -19,12 +19,13 @@ function insight(overrides = {}, commentCount = 0) { }, commentCount); } -function assertSignalNotesAreShort(result) { +function assertVisibleSignals(result) { + assert.equal(result.signals.length, 4); for (const signal of result.signals) { - assert( - signal.note.length <= 6, - `${signal.key} note is too long for the four-metric row: ${signal.note}` - ); + assert.ok(signal.key); + assert.ok(signal.label); + assert.equal(typeof signal.value, 'number'); + assert.ok(signal.tone); } } @@ -34,8 +35,7 @@ function assertSignalNotesAreShort(result) { assert.equal(result.title, '有确认信号'); assert.match(result.body, /4次确认信号/); assert.doesNotMatch(result.title, /有效|可信|可靠/); - assert.match(`${result.body}${result.hint}`, /现场|评论/); - assertSignalNotesAreShort(result); + assertVisibleSignals(result); } { @@ -44,7 +44,7 @@ function assertSignalNotesAreShort(result) { assert.equal(result.title, '存在多次举报'); assert.match(result.body, /2次举报/); assert.doesNotMatch(result.title, /确认/); - assertSignalNotesAreShort(result); + assertVisibleSignals(result); } { @@ -53,7 +53,7 @@ function assertSignalNotesAreShort(result) { assert.equal(result.title, '可能已经过时'); assert.match(result.body, /3次过时反馈/); assert.doesNotMatch(result.title, /确认/); - assertSignalNotesAreShort(result); + assertVisibleSignals(result); } { @@ -61,7 +61,7 @@ function assertSignalNotesAreShort(result) { assert.equal(result.tone, 'done'); assert.equal(result.title, '任务已关闭'); assert.match(result.body, /历史线索/); - assertSignalNotesAreShort(result); + assertVisibleSignals(result); } { @@ -69,7 +69,7 @@ function assertSignalNotesAreShort(result) { assert.equal(result.tone, 'neutral'); assert.equal(result.title, '任务已过期'); assert.match(result.body, /2条历史线索/); - assertSignalNotesAreShort(result); + assertVisibleSignals(result); } { @@ -77,8 +77,7 @@ function assertSignalNotesAreShort(result) { assert.equal(result.tone, 'neutral'); assert.equal(result.title, '先看评论线索'); assert.match(result.body, /5条评论/); - assert.match(result.hint, /提问|补充/); - assertSignalNotesAreShort(result); + assertVisibleSignals(result); } console.log('Trust insight checks passed.'); diff --git a/harness/claude-progress.md b/harness/claude-progress.md index 1ed4ee6..9c67102 100644 --- a/harness/claude-progress.md +++ b/harness/claude-progress.md @@ -7,8 +7,8 @@ - 标准初始化入口:`bash harness/init.sh` - 标准基础验证:`npm run check:json`,`node harness/check-harness.mjs` - 当前最高优先级未完成功能:`map-feed-001` -- 当前正在实现的用户请求:AB 组 DevTools service-port config forensics,为 9420 blocker 增加只读配置层取证,确认 Service Port UI/config 是否 disabled、端口是否匹配,以及配置结果不能替代真实 UI evidence -- 当前 blocker:AB 轮只读配置取证显示 DevTools 配置摘要中 `security.enableServicePort=false` 且 `security.port=9420`,同时端口仍无 listener、IPv4/IPv6 均 `ECONNREFUSED`;这说明下一步应由用户在 WeChat DevTools UI 中人工确认并开启 Settings -> Security Settings -> Service Port,真实朋友圈菜单、系统分享面板、payload、CloudBase attribution、窄屏和真机转化仍未产生 passed evidence +- 当前正在实现的用户请求:服务优化,在不影响功能的前提下简化所有操作和非必要展示;每次修改后 3 个子 agent 审阅,两票通过才算通过 +- 当前 blocker:静态门禁已通过;WeChat DevTools service port 9420 仍不可连接,因此真实 DevTools/真机视觉和点击验收尚未执行 ## 会话记录 @@ -1298,3 +1298,39 @@ - 更新过的文件或工件:`pages/publish/publish.js`,`scripts/check-publish-flow.mjs`,`harness/feature_list.json`,`harness/claude-progress.md` - 已知风险或未解决问题:尚未在真实 WeChat DevTools/真机中手动确认发布页初始高亮为 `长期`;DevTools service port 9420 仍阻塞,readiness 不能替代 UI passed evidence。云端路径仍需部署更新后的 `posts` 云函数 - 下一步最佳动作:在 DevTools UI 手动打开当前 worktree,确认发布页初始有效期高亮 `长期`,发布后详情页显示 `长期有效` +### Session 094UploadPackageSize + +- 日期:2026-06-25 +- 分支:`main` +- 本轮目标:修复用户反馈 WeChat DevTools 上传报错 `Error: 系统错误,错误码:80051, source size 48278KB exceed max limit 2MB` +- 根因:原始项目 checkout `/Users/bytedance/git/x` 中存在未跟踪的 `.understand-anything/` 本地分析产物目录,体积约 49MB;`project.config.json` 的 `miniprogramRoot` 为 `./` 且 `packOptions.ignore` 为空,DevTools 上传源码包时容易把该目录和其他本地工具目录一起纳入上传扫描,和报错中的 `48278KB` 高度吻合 +- 已完成:`.gitignore` 新增 `.understand-anything/`;`project.config.json` 的 `packOptions.ignore` 新增 `.git`、`.agents`、`.claude`、`.github`、`.understand-anything`、`harness`、`scripts`、`log` 目录,避免本地工具、harness、脚本和 git 元数据进入小程序上传包;未删除任何本地产物,未改动小程序运行代码 +- 运行过的验证:使用 bundled Node PATH 运行 `node scripts/check-json.mjs`、`node harness/check-harness.mjs`、`git diff --check`、按 `packOptions.ignore` 估算上传源码体积、最终 `bash harness/init.sh` +- 已记录证据:`node scripts/check-json.mjs` 输出 `Checked 11 JSON files.`;`node harness/check-harness.mjs` 输出 `Harness OK: 6 features checked.`;`git diff --check` 无输出;体积估算输出 `Approx packed source after packOptions.ignore: 579KB across 92 files`;最终 `bash harness/init.sh` 完整跑通并输出 `Harness init complete.` +- 已知风险或未解决问题:尚未由 WeChat DevTools 实际重新上传/预览验证;如果 DevTools 仍使用旧缓存,建议清理编译缓存或重新打开 `/Users/bytedance/git/x` 后再上传 +- 下一步最佳动作:在 WeChat DevTools 中重新上传或预览当前项目,确认不再出现 `source size ... exceed max limit 2MB` + +### Session 095ServiceSimplification + +- 日期:2026-07-02 +- 分支:`main` +- 本轮目标:按用户 goal 做服务优化,在不影响功能的前提下简化所有操作和非必要展示;每次修改后启动 3 个子 agent 审阅,至少 2 票 PASS 才算通过 +- 已完成:移除发布页单独准备度卡片和表单说明,保留定位块与底部主按钮状态;简化地图列表头部,移除重复分类说明和附近计数;简化详情页分享接收、发布后扩散、普通分享、TrustInsight、动作接力和评论接力中的辅助说明行;简化管理台、反馈页、我的发布、动态和个人页的重复副标题、空态提示和反馈计数;删除地图页已不展示的 `activeCategoryText`/`viewportPostCount` 状态和管理页已不展示的 `stats.feedback` +- 已完成:同步收窄发布状态和 TrustInsight 的数据/检查,移除已删除展示依赖的 `readiness.items`、`readiness.completionText`、`trustInsight.hint` 和 signal note 断言;`scripts/check-devtools-readiness.mjs` 内联 service simplification guard,覆盖活跃 readiness/smoke/runbook 文档和相关页面 JS/WXML/WXSS,防止重新引入旧准备度卡片、旧说明块、旧计数状态或未跟踪检查脚本依赖 +- 已完成:更新活跃设计/手测/readiness 文档,把当前发布验收口径统一为“发布状态、定位块、底部主按钮”;历史候选报告保留历史事实但明确标注不是当前发布页手测清单 +- 运行过的验证:`pwd`;读取 `harness/claude-progress.md`、`harness/feature_list.json`、`git log --oneline -5`;使用 bundled Node PATH 运行 `bash harness/init.sh`;`node --check pages/map/map.js`、`node --check pages/admin/admin.js`、`node --check pages/publish/publish-state.js`、`node --check scripts/check-devtools-readiness.mjs`、`node --check scripts/check-publish-flow.mjs`、`node --check scripts/check-candidate-flow.mjs`、`node --check utils/format.js`;`node --no-warnings scripts/check-devtools-readiness.mjs`;`npm run check`;`git diff --check`;旧展示/旧文档术语定向 `rg` +- 已记录证据:`npm run check` 输出 `Checked 11 JSON files.`、`Harness OK: 6 features checked.`、`Service simplification checks passed.` 和最终 `DevTools readiness checks passed. Static gates passed; DevTools and real-device visual acceptance are still required.`;`bash harness/init.sh` 输出 `Harness init complete.`;`git diff --check` 无输出;最终复审 Franklin、Ptolemy、Ramanujan 三票 PASS,无 Critical/Important findings,满足“两票通过”规则 +- 已知风险或未解决问题:没有执行真实 WeChat DevTools/真机视觉和点击验收;readiness 仍报告 9420 service port blocked / connection refused,这只能说明环境入口阻塞,不能写作 UI passed evidence。复审提出若后续继续极限清理,可再移除未渲染的 `nextAction.note` 和部分详情 helper 的旧字段,但它们不影响当前用户功能或可见展示 +- 下一步最佳动作:在 WeChat DevTools service port 恢复后,用发布、地图列表、详情信任动作/评论/分享、管理处置、反馈提交、个人页下一步做一次真实 UI smoke,并把结果记录为 passed/failed/blocked/not_covered + +### Session 096PullAndPublishPageStyle + +- 日期:2026-07-02 +- 分支:`main` +- 本轮目标:按用户要求拉取最新代码,并根据截图优化发布页样式,减少“卡片套卡片”的层级感,修正底部状态标题/禁用按钮颜色问题 +- 已完成:`git fetch origin` 后用 `git pull --ff-only --autostash origin main` 快进到 `a69d464`;保留远端默认长期/自定义有效期发布逻辑,同时解决 autostash 与本地服务简化改动在 `harness/claude-progress.md`、`pages/publish/publish-state.js`、`scripts/check-publish-flow.mjs` 的冲突 +- 已完成:发布页表单容器去掉全局 `panel` 叠层,改为单一轻量表单面板;`form-section` 改为透明分区和分隔线,去掉内层卡片边框/背景;底部 `publish-action` 状态标题颜色改为品牌深绿,禁用主按钮改成不透明浅绿底和更高对比文字 +- 运行过的验证:`node --check pages/publish/publish-state.js`;`node --check scripts/check-publish-flow.mjs`;`node --no-warnings scripts/check-publish-flow.mjs`;`npm run check`;`bash harness/init.sh`;`git diff --check`;`git diff --cached --check` +- 已记录证据:发布流专项输出 `Publish flow checks passed.`;`npm run check` 输出 `Checked 11 JSON files.`、`Harness OK: 6 features checked.`、`Service simplification checks passed.` 和最终 `DevTools readiness checks passed. Static gates passed; DevTools and real-device visual acceptance are still required.`;`bash harness/init.sh` 输出 `Harness init complete.`;两条 diff whitespace 检查均无输出 +- 已知风险或未解决问题:没有执行真实 WeChat DevTools/真机视觉验收;readiness 仍报告 9420 service port blocked / connection refused。`git pull --autostash` 因冲突保留了 `stash@{0}` 作为备份,当前改动已应用到工作区并解决冲突,未删除该备份 +- 下一步最佳动作:在 DevTools 手动打开发布页,确认截图中的表单层级已经变为单层面板、底部“还差标题/补标题”状态颜色对比正常,并实际点选 `长期/自定义` 有效期回归发布流程 diff --git a/harness/devtools-port-forensics-checklist.md b/harness/devtools-port-forensics-checklist.md index 99252d5..02e848e 100644 --- a/harness/devtools-port-forensics-checklist.md +++ b/harness/devtools-port-forensics-checklist.md @@ -190,6 +190,6 @@ O 组不执行恢复动作,只把建议交给有本机 UI 权限的执行者 - 打开微信开发者工具 UI,进入“设置 -> 安全设置”,确认“服务端口”开启;若 UI 显示关闭,手动开启后重新做只读端口检查。 - 确认当前只保留必要的 DevTools 实例;如果多个项目或多个版本同时运行,先人工识别当前项目和端口归属。 - 正常退出整个 DevTools app 后重开,不只关闭模拟器窗口;恢复前保存必要的脱敏 blocked 摘要。 -- 重新打开目标 worktree 后,先跑端口 access 检查,再做 DevTools 编译、地图首屏、发布准备度、详情信任动作和真机预览 smoke。 +- 重新打开目标 worktree 后,先跑端口 access 检查,再做 DevTools 编译、地图首屏、发布状态、详情信任动作和真机预览 smoke。 - 若 `9420` 长期 blocked,可人工切换服务端口、升级或重装 DevTools、换机器验证,或改用 UI 手测路径记录 CLI blocked。 - 恢复后仍需按真实 DevTools UI / 真机旅程记录 `passed`、`failed`、`blocked` 或 `not_covered`;端口恢复本身不能替代产品 smoke 证据。 diff --git a/harness/devtools-port-forensics-product-brief.md b/harness/devtools-port-forensics-product-brief.md index 8f2fa4a..20d133e 100644 --- a/harness/devtools-port-forensics-product-brief.md +++ b/harness/devtools-port-forensics-product-brief.md @@ -27,7 +27,7 @@ O 组不再重复恢复动作,也不继续扩大 smoke 或业务验证范围 ## 用户价值 -真实 DevTools 或真机 smoke 仍是判断地图首屏、发布准备度、定位授权、详情信任区、评论和图片链路的必要证据。O 组的价值不是让这些用户旅程通过,而是降低误判成本: +真实 DevTools 或真机 smoke 仍是判断地图首屏、发布状态、定位授权、详情信任区、评论和图片链路的必要证据。O 组的价值不是让这些用户旅程通过,而是降低误判成本: - 让后续执行者知道当前 blocker 是 DevTools 环境入口问题,不是已复现的产品缺陷。 - 把“CLI 可执行”“进程存在”“端口声明”“端口监听”拆开,避免任一单点被误写成 smoke ready。 diff --git a/harness/devtools-readiness-checklist.md b/harness/devtools-readiness-checklist.md index 34703fa..1ba0d67 100644 --- a/harness/devtools-readiness-checklist.md +++ b/harness/devtools-readiness-checklist.md @@ -1,4 +1,4 @@ -# DevTools / 真机发布准备度手测清单 +# DevTools / 真机发布流程手测清单 日期:2026-06-14 @@ -133,22 +133,22 @@ ### 4.1 游客与登录态 - [ ] 游客进入发布页。 - - 通过标准:登录提示、发布准备度和底部主按钮状态一致,不能绕过登录发布。 + - 通过标准:登录提示、位置确认状态和底部主按钮状态一致,不能绕过登录发布。 - 失败证据:首屏截图和点击主按钮后的表现。 - [ ] 已登录用户进入发布页。 - - 通过标准:登录提示消失或降级,表单可编辑,底部主按钮按准备度变化。 + - 通过标准:登录提示消失或降级,表单可编辑,底部主按钮按表单和位置状态变化。 - 失败证据:登录态截图,记录登录方式。 - [ ] 登录状态切换后返回发布页。 - 通过标准:页面状态刷新,不沿用游客禁用态或旧用户信息。 - 失败证据:切换前后录屏。 -### 4.2 必填校验与准备度状态 +### 4.2 必填校验与发布状态 - [ ] 空表单直接点击主按钮。 - 通过标准:提示第一个需要补齐的字段,不提交空任务。 - 失败证据:点击后 toast / 文案截图。 - [ ] 逐项填写标题、详情、分类、地点、有效期。 - - 通过标准:发布准备度和按钮说明同步更新,没有状态滞后。 + - 通过标准:底部按钮说明同步更新,没有状态滞后。 - 失败证据:逐项截图或录屏。 - [ ] 输入超长标题、超长正文、超长地点。 - 通过标准:计数、换行、省略和按钮区域稳定,不出现横向滚动或遮挡。 diff --git a/harness/devtools-readiness-product-brief.md b/harness/devtools-readiness-product-brief.md index d8de4e3..c3f9cd0 100644 --- a/harness/devtools-readiness-product-brief.md +++ b/harness/devtools-readiness-product-brief.md @@ -15,7 +15,7 @@ ## 2. H 组非目标 -- 不新增功能,不修改发布准备度状态机、详情 TrustInsight、评论入口、地图列表或存储逻辑。 +- 不新增功能,不修改发布状态机、详情 TrustInsight、评论入口、地图列表或存储逻辑。 - 不用自动脚本替代 WeChat DevTools 或真机手测。 - 不把 DevTools CLI、云函数、Storage 的环境问题当作产品功能已通过。 - 不提交代码,不调整其它 harness 文件。 @@ -46,9 +46,9 @@ - 详情页标题、分类、地点、距离、状态、有效期与列表展示一致。 - 隐藏或过期任务不应出现在普通地图列表中;如无法构造数据,记录为“未覆盖”。 -### 4.2 发布准备度与定位失败重试 +### 4.2 发布状态与定位失败重试 -- 首次进入发布页时观察准备度清单,字段缺失、定位等待、定位失败、位置已确认的文案和主按钮状态要一致。 +- 首次进入发布页时观察定位块和底部主按钮,字段缺失、定位等待、定位失败、位置已确认的文案和按钮状态要一致。 - 拒绝定位或模拟定位失败后,重试入口可见,点击后状态有明确变化。 - 标题、详情、分类、有效期、位置确认都完成前,主按钮不得表现为可发布。 - 提交中态不得允许重复提交。 @@ -141,7 +141,7 @@ DevTools/真机环境: 用户旅程结论: - 地图列表到详情: -- 发布准备度/定位失败重试: +- 发布状态/定位失败重试: - 发布成功后详情跳转: - 详情 TrustInsight/评论入口: - 图片/云端路径: diff --git a/harness/devtools-recovery-report-design-note.md b/harness/devtools-recovery-report-design-note.md index 53bfa0e..9849090 100644 --- a/harness/devtools-recovery-report-design-note.md +++ b/harness/devtools-recovery-report-design-note.md @@ -137,7 +137,7 @@ guard 必须拒绝这些通过或恢复声明: 它不能替代以下验证: - WeChat DevTools 中真实打开项目、编译并观察页面。 -- 地图列表、marker/detail 链路、发布准备度、详情 TrustInsight 等用户旅程 smoke。 +- 地图列表、marker/detail 链路、发布状态、详情 TrustInsight 等用户旅程 smoke。 - 真机定位授权、图片上传、safe area、键盘遮挡和云端路径验证。 最终结论应保持为:本报告可降低交接误读风险,但不能把 AH dry-run 草稿当作真实 DevTools UI smoke 通过证据。 diff --git a/harness/devtools-service-recovery-checklist.md b/harness/devtools-service-recovery-checklist.md index 7a4c65d..cb070dc 100644 --- a/harness/devtools-service-recovery-checklist.md +++ b/harness/devtools-service-recovery-checklist.md @@ -177,7 +177,7 @@ listenEvidence: 9420 无监听,nc/curl 为 connection refused recoveryAttempted: UI 正常退出未成功;CLI quit 返回 timeout;attempt-open 20s timeout actualResult: DevTools 服务端口仍不可连接,未能确认当前项目 ready rollbackOrStopPoint: 未强制杀进程,保持 blocked,等待有 UI 权限执行者处理 -manualJourneyImpact: DevTools 编译、地图首屏、发布准备度、详情信任区和真机预览均未执行 +manualJourneyImpact: DevTools 编译、地图首屏、发布状态、详情信任区和真机预览均未执行 nextAction: 人工重新开启服务端口或换机验证,再重跑 check-devtools-smoke-access evidenceLocation: 本地附件 S-recovery-01,原始日志不提交 ``` @@ -196,9 +196,9 @@ evidenceLocation: 本地附件 S-recovery-01,原始日志不提交 - 通过标准:详情页展示同一任务标题、正文、状态、发布者信息、TrustInsight、信任动作和评论入口;不出现“任务不存在”。 - 失败记录:入口方式、任务别名、post id 摘要和详情页实际状态。 -- [ ] 发布准备度和定位恢复路径。 +- [ ] 发布状态和定位恢复路径。 - 进入发布页,至少覆盖游客态或登录态一种;点击当前位置确认,覆盖允许、拒绝或失败重试中的一种真实分支。 - - 通过标准:准备度文案、底部主按钮、定位中 / 失败 / 重试状态随真实权限变化;失败不清空已填内容。 + - 通过标准:定位块文案、底部主按钮、定位中 / 失败 / 重试状态随真实权限变化;失败不清空已填内容。 - 失败记录:权限初始状态、点击步骤、toast / 文案、是否卡住 loading。 - [ ] 详情信任动作和评论入口。 diff --git a/harness/devtools-smoke-checklist.md b/harness/devtools-smoke-checklist.md index 100967c..7a16303 100644 --- a/harness/devtools-smoke-checklist.md +++ b/harness/devtools-smoke-checklist.md @@ -161,9 +161,9 @@ evidenceLocation: 本地附件 S-port-01,原始日志不提交 - 通过标准:详情页展示同一任务标题、正文、状态、发布者信息、TrustInsight、信任动作和评论入口;不出现“任务不存在”。 - 失败记录:列表任务标题、详情实际标题、post id 摘要和跳转方式。 -- [ ] 发布准备度和定位失败重试。 +- [ ] 发布状态和定位失败重试。 - 进入发布页,游客态和登录态至少覆盖一种;点击使用当前位置并覆盖允许或拒绝中的一种。 - - 通过标准:准备度文案、底部主按钮、定位中 / 失败 / 重试状态随真实权限变化;失败不清空已填内容。 + - 通过标准:定位块文案、底部主按钮、定位中 / 失败 / 重试状态随真实权限变化;失败不清空已填内容。 - 失败记录:权限初始状态、点击步骤、toast / 文案和是否卡住 loading。 - [ ] 发布成功到详情。 diff --git a/harness/devtools-smoke-product-brief.md b/harness/devtools-smoke-product-brief.md index 11847c4..4c162a1 100644 --- a/harness/devtools-smoke-product-brief.md +++ b/harness/devtools-smoke-product-brief.md @@ -21,7 +21,7 @@ ## 2. 用户/发布价值 -真实 DevTools/真机 smoke 是判断街区任务能否进入候选发布的关键门槛。发布准备度、定位授权、地图首屏、详情信任动作、评论入口、图片和云端路径,都有只能在 DevTools 或真机中观察的风险。 +真实 DevTools/真机 smoke 是判断街区任务能否进入候选发布的关键门槛。发布状态、定位授权、地图首屏、详情信任动作、评论入口、图片和云端路径,都有只能在 DevTools 或真机中观察的风险。 本轮聚焦 smoke access unblock 的价值是: @@ -88,7 +88,7 @@ - 地图首屏:打开项目、编译、进入地图页,记录控制台是否有阻断错误。 - 地图到详情:从地图 marker 或列表进入详情,确认不是空白页或任务不存在。 -- 发布准备度:打开发布页,观察定位确认、必填状态和主按钮文案。 +- 发布状态:打开发布页,观察定位确认、必填状态和主按钮文案。 - 定位分支:至少记录允许、拒绝或失败重试中的一个真实分支;未覆盖的分支必须写明。 - 详情信任入口:进入 active 详情,观察 TrustInsight、评论入口和信任动作区域是否可见。 diff --git a/harness/hardening-design-checklist.md b/harness/hardening-design-checklist.md index 27c7221..57caa47 100644 --- a/harness/hardening-design-checklist.md +++ b/harness/hardening-design-checklist.md @@ -4,17 +4,13 @@ 范围:仅覆盖 `codex/iter-candidate-hardening` 中发布页与详情页的视觉评测路径,不新增 UI,不判断代码实现优劣。 -## 1. 发布页准备度 / 定位 / 底部按钮 +## 1. 发布页定位 / 底部按钮 -### 发布准备度 +### 表单状态 -- [ ] 首屏进入发布页时,“发布准备”模块位于登录提示之后、任务内容之前,视觉层级清楚,不抢占标题区主信息。 -- [ ] 准备度计数胶囊与标题区右侧对齐自然,窄屏下不挤压“按顺序补齐”说明。 -- [ ] 准备项两列网格在默认屏宽下间距均匀,圆点、标签、状态值对齐稳定。 -- [ ] 未完成项与完成项的圆点颜色差异足够明显,但不造成强警告感。 -- [ ] 状态值过长时保持单行省略,不撑开卡片、不导致两列高度明显错位。 -- [ ] 标题、详情、分类、位置、地点、有效期逐步补齐时,准备项状态与底部按钮提示一致。 -- [ ] 游客态下登录提示、准备度模块、底部主动作之间没有互相矛盾的引导。 +- [ ] 首屏进入发布页时,登录提示之后直接进入任务内容表单,不出现额外准备度卡片。 +- [ ] 标题、详情、分类、位置、地点、有效期逐步补齐时,底部标题、说明和按钮文案能准确提示下一步。 +- [ ] 游客态下登录提示和底部主动作之间没有互相矛盾的引导。 ### 定位确认 @@ -41,9 +37,8 @@ - [ ] TrustInsight 面板位于详情 hero 与评论区之间,能被理解为读完任务后的判断辅助。 - [ ] “信任判断” eyebrow、标题、说明三层文字层级清晰,标题不应和详情页主标题竞争。 - [ ] good / warn / danger / done 等 tone 的左侧色条差异明确,但整体仍保持街区任务的克制风格。 -- [ ] 四个信号格在默认屏宽下等宽排列,数字、标签、说明垂直节奏一致。 -- [ ] 信号说明长文案单行省略,不挤压相邻信号,不破坏边框圆角。 -- [ ] hint 行与信号格之间间距合适,作为提示而不是新的主操作。 +- [ ] 四个信号格在默认屏宽下等宽排列,数字和标签垂直节奏一致。 +- [ ] 信号格不依赖二级说明文案;长数字不挤压相邻信号,不破坏边框圆角。 - [ ] resolved、expired、hidden 之外的只读态显示 summary 时,不应让用户误以为还能点击信任动作。 ### 评论入口 @@ -68,7 +63,7 @@ ### 窄屏 -- [ ] 在 320px 级别窄屏下,发布准备度两列网格不溢出;如文字变长,应优先省略状态值。 +- [ ] 在 320px 级别窄屏下,发布表单分区、位置卡片和底部操作条不溢出。 - [ ] 分类、有效期、失物方向按钮在窄屏下不出现文字截断到不可理解。 - [ ] 发布页底部操作条在窄屏下按钮仍有足够点击面积,说明文案不压住按钮。 - [ ] 详情页 hero 中标签、过期时间、标题、正文不互相遮挡。 @@ -109,7 +104,7 @@ ## 4. 不新增 UI 的硬化原则 -- [ ] 只调整现有发布准备度、定位卡片、底部按钮、TrustInsight、评论入口、信任动作的稳定性与可读性。 +- [ ] 只调整现有发布表单状态、定位卡片、底部按钮、TrustInsight、评论入口、信任动作的稳定性与可读性。 - [ ] 不新增新的浮层、提示条、卡片、入口、步骤页或解释文案来解决视觉问题。 - [ ] 优先通过间距、换行、省略、禁用态、loading 态和安全区适配完成硬化。 - [ ] 不改变现有信息架构:发布页仍是表单加底部主动作,详情页仍是 hero、信任判断、评论。 diff --git a/harness/hardening-product-brief.md b/harness/hardening-product-brief.md index a9ca72e..d619c4d 100644 --- a/harness/hardening-product-brief.md +++ b/harness/hardening-product-brief.md @@ -7,7 +7,7 @@ ## 1. F/G 候选核心产品风险排序 1. 发布闭环真实可用性风险最高:自动验证覆盖了发布页状态机、JSON、WXML/WXSS 编译,但尚未验证真机或 WeChat DevTools 中的定位授权、定位失败重试、提交中状态、发布成功后的详情跳转。 -2. 位置确认与主动作状态一致性风险次高:发布页新增准备度清单、位置确认和 `primaryAction` 状态机后,用户最容易卡住的地方是“字段已填但位置未确认/定位仍在等待/授权失败”时按钮文案与可点击状态是否一致。 +2. 位置确认与主动作状态一致性风险次高:发布页位置确认和 `primaryAction` 状态机最容易卡住的地方是“字段已填但位置未确认/定位仍在等待/授权失败”时按钮文案与可点击状态是否一致。 3. 详情信任解释的行动理解风险:TrustInsight 面板解释确认、过时、举报和评论数,但尚未验证用户在不同状态下能否正确理解“我该确认、标过时、举报还是只读”。 4. 详情页窄屏与入口竞争风险:评论区标题右侧写评论入口与原有悬浮评论按钮共存,窄屏下可能挤压 TrustInsight、信任动作或评论入口。 5. resolved/expired/hidden 等边界状态风险:报告已说明未验证 resolved/expired 只读状态,若信任动作仍显得可操作,会损害用户对任务状态的判断。 @@ -17,13 +17,13 @@ 优先验证一条从冷启动到完成发布的主路径: 1. 首次进入发布页,用户未授权定位或定位尚未完成。 -2. 填写标题、详情、分类、有效期,观察准备度清单和字数计数实时更新。 +2. 填写标题、详情、分类、有效期,观察定位块、底部主按钮和字数计数实时更新。 3. 触发定位授权、定位失败重试或手动确认当前位置,确认主按钮从补字段/确认位置/等待定位切换到可发布。 4. 点击发布,验证提交中态不会重复提交。 5. 发布成功后进入详情页,详情页展示刚发布的标题、详情、分类、地点、有效期和初始信任数据。 6. 返回地图或列表后,新任务可见且状态仍为 active。 -这条路径是硬化优先级最高的原因:它同时覆盖新增发布准备度、位置确认、状态机和发布后详情跳转,是用户产生内容的最短闭环。 +这条路径是硬化优先级最高的原因:它同时覆盖发布状态、位置确认、状态机和发布后详情跳转,是用户产生内容的最短闭环。 ## 3. 详情信任最该被验证的用户路径 diff --git a/harness/manual-preflight-alignment-checklist.md b/harness/manual-preflight-alignment-checklist.md index c3ca67c..0a6b8c5 100644 --- a/harness/manual-preflight-alignment-checklist.md +++ b/harness/manual-preflight-alignment-checklist.md @@ -75,7 +75,7 @@ ## 4. 不能替代的真实验证 - [ ] 地图列表长标题、长正文、带图/无图、底部统计、safe area、地图原生层遮挡、列表滚动和详情入口点击仍需 DevTools 或真机验证。 -- [ ] 发布准备度、定位拒绝/重试、图片上传失败回滚、发布后详情跳转、详情 TrustInsight 和评论入口仍需真实操作。 +- [ ] 发布状态、定位拒绝/重试、图片上传失败回滚、发布后详情跳转、详情 TrustInsight 和评论入口仍需真实操作。 - [ ] helper 成功只能写作 `manual run prepared` 或 `static gates passed`;不能写作 `UI passed`、`视觉已通过` 或 `真机通过`。 ## 5. 清理 diff --git a/harness/manual-runbook-checklist.md b/harness/manual-runbook-checklist.md index 27e9c92..a108e7a 100644 --- a/harness/manual-runbook-checklist.md +++ b/harness/manual-runbook-checklist.md @@ -72,7 +72,7 @@ - [ ] 按核心旅程逐项手测,并同步填写 `harness/manual-test-results.local.json`。 - `map-to-detail`:地图页渲染、marker 或列表进入正确详情、返回后仍可操作。 - - `publish-readiness-location-retry`:发布准备度、定位拒绝或失败、重试、允许后的主动作变化。 + - `publish-state-location-retry`:发布状态、定位拒绝或失败、重试、允许后的主动作变化。 - `publish-success-to-detail`:填齐表单、发布只创建一次、成功跳转新任务详情、返回地图可见。 - `detail-trust-insight-comments`:详情 TrustInsight、确认或 stale/report、重复操作限制、评论入口和重进详情。 - `image-cloud-paths`:图片上传、失败提示、保存引用形态、清缓存或跨用户可见性。 diff --git a/harness/manual-test-results.example.json b/harness/manual-test-results.example.json index 5341d4a..3dbfaad 100644 --- a/harness/manual-test-results.example.json +++ b/harness/manual-test-results.example.json @@ -91,17 +91,17 @@ "followUp": "Run this smoke journey manually after DevTools or real-device access is available; record tested device width, post ids, whether cards had images, and any screenshot or recording artifact only if it actually exists." }, { - "id": "publish-readiness-location-retry", - "title": "发布准备度与定位失败重试", + "id": "publish-state-location-retry", + "title": "发布状态与定位失败重试", "status": "blocked", "steps": [ "Open the publish tab in WeChat DevTools.", "Fill the minimum required title, body, category, and expiry fields.", - "Trigger current-location confirmation from the readiness action.", + "Trigger current-location confirmation from the location block or bottom action.", "Deny, timeout, or otherwise fail location once, then retry and allow location." ], "expected": [ - "The readiness checklist identifies location as the remaining blocker.", + "The bottom action identifies location as the remaining blocker.", "A failed location attempt shows retry-oriented copy and does not submit the post.", "After retry succeeds, the primary action changes to publish." ], diff --git a/harness/map-list-resilience-checklist.md b/harness/map-list-resilience-checklist.md index dd1e717..f264165 100644 --- a/harness/map-list-resilience-checklist.md +++ b/harness/map-list-resilience-checklist.md @@ -77,7 +77,7 @@ - 必须人工确认:左侧“确认/过时”与右侧“时间/距离”在窄屏不重叠;右侧过长时截断,左侧统计仍可读。 - [ ] 固定尺寸元素不会随内容跳动。 - - 可脚本检查:`.post-thumb` 为 `104rpx` 正方形,`.post-card .mark-button` 为 `48rpx`,`.drawer-counter` 有固定高度和最小宽度。 + - 可脚本检查:`.post-thumb` 为 `104rpx` 正方形,`.post-card .mark-button` 为 `48rpx`。 - 必须人工确认:图片加载前后、状态切换前后、筛选条数量变化时,卡片高度变化可接受且不会产生遮挡。 ## 3. 内容韧性场景 diff --git a/harness/sanitized-summary-checklist.md b/harness/sanitized-summary-checklist.md index c50839f..c89445e 100644 --- a/harness/sanitized-summary-checklist.md +++ b/harness/sanitized-summary-checklist.md @@ -61,6 +61,6 @@ - 小程序编译、首屏渲染、地图列表和详情跳转。 - 定位授权允许、拒绝、超时和重试路径。 -- 发布准备度、键盘遮挡、安全区、图片上传失败回滚和发布后详情跳转。 +- 发布表单状态、底部动作、键盘遮挡、安全区、图片上传失败回滚和发布后详情跳转。 - TrustInsight 面板、信任动作刷新、评论入口、只读状态和云端评论路径。 - CloudBase 云函数部署、存储权限、图片跨用户可见性和真实网络条件。 diff --git a/pages/activities/activities.wxml b/pages/activities/activities.wxml index b6c5ea7..375c365 100644 --- a/pages/activities/activities.wxml +++ b/pages/activities/activities.wxml @@ -1,7 +1,6 @@ 参与记录 - 你确认、标记过时或举报过的附近任务。 @@ -13,7 +12,6 @@ 还没有参与记录 - 在详情页确认有效、标记过时或举报后会出现在这里。 diff --git a/pages/admin/admin.js b/pages/admin/admin.js index cf0a19a..1ec9244 100644 --- a/pages/admin/admin.js +++ b/pages/admin/admin.js @@ -40,8 +40,7 @@ Page({ stale: 0, resolved: 0, reported: 0, - hidden: 0, - feedback: 0 + hidden: 0 } }, @@ -82,10 +81,7 @@ Page({ visiblePosts: reviewState.visiblePosts, feedbacks, feedbackError, - stats: { - ...reviewState.stats, - feedback: feedbacks.length - }, + stats: reviewState.stats, filterOptions: reviewState.filterOptions }); }, @@ -100,10 +96,7 @@ Page({ posts: reviewState.posts, visiblePosts: reviewState.visiblePosts, filterOptions: reviewState.filterOptions, - stats: { - ...reviewState.stats, - feedback: this.data.feedbacks.length - } + stats: reviewState.stats }); }, diff --git a/pages/admin/admin.wxml b/pages/admin/admin.wxml index 2aa2f5a..47ca1a1 100644 --- a/pages/admin/admin.wxml +++ b/pages/admin/admin.wxml @@ -2,7 +2,6 @@ 管理控制台 - 仅管理员可见 · {{stats.needsReview}} 条待处理 · {{stats.feedback}} 条反馈 @@ -28,14 +27,11 @@ 用户反馈 - 来自“我的”页反馈入口 - 还没有用户反馈 - 用户提交后会显示在这里。 @@ -83,14 +79,12 @@ 处置队列 - 按举报和过时风险排序 没有匹配内容 - 换个关键词,或切换到“全部”查看完整列表。 diff --git a/pages/admin/admin.wxss b/pages/admin/admin.wxss index 9a617cf..d1edf08 100644 --- a/pages/admin/admin.wxss +++ b/pages/admin/admin.wxss @@ -57,14 +57,6 @@ min-width: 0; } -.feedback-count { - flex-shrink: 0; - color: #1b5f52; - font-size: 34rpx; - font-weight: 900; - line-height: 1.2; -} - .feedback-admin-card { padding: 24rpx; background: #fffefa; diff --git a/pages/detail/detail.wxml b/pages/detail/detail.wxml index d9dabeb..030fc92 100644 --- a/pages/detail/detail.wxml +++ b/pages/detail/detail.wxml @@ -51,13 +51,6 @@ {{shareReceiverGuide.title}} - - - - @@ -186,10 +143,8 @@ {{item.value}} {{item.label}} - {{item.note}} - {{trustInsight.hint}} diff --git a/pages/map/map.wxss b/pages/map/map.wxss index b2793cb..1fdbba2 100644 --- a/pages/map/map.wxss +++ b/pages/map/map.wxss @@ -452,32 +452,6 @@ gap: 12rpx; } -.drawer-counter { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - min-width: 82rpx; - height: 64rpx; - border-radius: 14rpx; - background: #eaf4ef; -} - -.drawer-counter-value { - color: #1b5f52; - font-size: 30rpx; - font-weight: 900; - line-height: 1; -} - -.drawer-counter-label { - margin-top: 4rpx; - color: #697970; - font-size: 18rpx; - font-weight: 800; - line-height: 1; -} - .drawer-head .ghost-button { height: 64rpx; padding: 0 20rpx; diff --git a/pages/me/me.wxml b/pages/me/me.wxml index 2cb94b6..d9ed8e8 100644 --- a/pages/me/me.wxml +++ b/pages/me/me.wxml @@ -55,7 +55,6 @@ {{nextAction.title}} - {{nextAction.note}} @@ -64,7 +63,6 @@ 最近动态 - 你刚参与过的附近任务 全部 diff --git a/pages/my-posts/my-posts.wxml b/pages/my-posts/my-posts.wxml index 2cb9c8e..90cd03c 100644 --- a/pages/my-posts/my-posts.wxml +++ b/pages/my-posts/my-posts.wxml @@ -1,7 +1,6 @@ 我的发布 - 当前账号发布过的附近任务。 @@ -13,7 +12,6 @@ 还没有发布过任务 - 可以从身边的失物、路况、求助或打卡开始。 diff --git a/pages/publish/publish-state.js b/pages/publish/publish-state.js index 21b23f3..0557000 100644 --- a/pages/publish/publish-state.js +++ b/pages/publish/publish-state.js @@ -2,16 +2,6 @@ function present(value) { return Boolean(String(value || '').trim()); } -function locationValue(locationStatus, hasLocation) { - if (locationStatus === 'locating') { - return '确认中'; - } - if (locationStatus === 'failed') { - return '待重试'; - } - return hasLocation ? '已确认' : '待确认'; -} - function locationActionText(locationStatus) { if (locationStatus === 'ready') { return '重新确认'; @@ -103,39 +93,6 @@ export function buildPublishState(options = {}) { const locationDone = hasLocation && locationStatus === 'ready'; const expiryDone = hasExpiry(form); - const items = [ - { - key: 'account', - label: '身份', - value: isGuest ? '未登录' : '已登录', - done: !isGuest - }, - { - key: 'content', - label: '内容', - value: contentDone ? '已补全' : '待填写', - done: contentDone - }, - { - key: 'category', - label: '分类', - value: categoryDone ? '已选择' : '待选择', - done: categoryDone - }, - { - key: 'expiry', - label: '有效期', - value: expiryDone ? '已设置' : '待选择', - done: expiryDone - }, - { - key: 'location', - label: '位置', - value: locationValue(locationStatus, hasLocation), - done: locationDone - } - ]; - const missing = []; if (isGuest) { missing.push('登录'); @@ -156,12 +113,10 @@ export function buildPublishState(options = {}) { missing.push('当前位置'); } - const doneCount = items.filter((item) => item.done).length; const ready = missing.length === 0 && !submitting; const onlyNeedsLocation = missing.length === 1 && missing[0] === '当前位置'; const canConfirmLocation = onlyNeedsLocation && locationStatus !== 'locating'; const actionDisabled = submitting || (!isGuest && missing.length > 0 && !canConfirmLocation); - const completionText = `${doneCount}/${items.length}`; const nextLocationActionText = locationActionText(locationStatus); const primaryAction = primaryActionForState({ submitting, @@ -173,7 +128,6 @@ export function buildPublishState(options = {}) { if (submitting) { return { - items, missing, ready: false, actionDisabled: true, @@ -181,14 +135,12 @@ export function buildPublishState(options = {}) { buttonText: '发布中', title: '正在发布', note: '正在保存图片和任务信息', - completionText, locationActionText: nextLocationActionText }; } if (isGuest) { return { - items, missing, ready: false, actionDisabled: false, @@ -196,7 +148,6 @@ export function buildPublishState(options = {}) { buttonText: '去登录', title: '登录后可发布', note: '登录后会记录发布者,方便管理自己的任务', - completionText, locationActionText: nextLocationActionText }; } @@ -204,7 +155,6 @@ export function buildPublishState(options = {}) { if (!ready) { const locationCopy = onlyNeedsLocation ? missingLocationCopy(locationStatus) : null; return { - items, missing, ready: false, actionDisabled, @@ -212,13 +162,11 @@ export function buildPublishState(options = {}) { buttonText: missingActionText(missing[0], locationStatus), title: locationCopy ? locationCopy.title : `还差${missing[0]}`, note: locationCopy ? locationCopy.note : `补全${missing.join('、')}后再发布`, - completionText, locationActionText: nextLocationActionText }; } return { - items, missing, ready: true, actionDisabled: false, @@ -228,7 +176,6 @@ export function buildPublishState(options = {}) { note: imageCount > 0 ? `当前位置已确认,含${imageCount}张图片` : '当前位置已确认,可直接发布', - completionText, locationActionText: nextLocationActionText }; } diff --git a/pages/publish/publish.wxml b/pages/publish/publish.wxml index 1b7b4b1..8a4e128 100644 --- a/pages/publish/publish.wxml +++ b/pages/publish/publish.wxml @@ -5,35 +5,15 @@ 发布到{{appInfo.shortName}},自动使用你的当前位置 - + - - - - 发布准备 - 按顺序补齐,底部按钮会实时提示下一步。 - - {{readiness.completionText}} - - - - - - {{item.label}} - {{item.value}} - - - - - 任务内容 - 先说清楚附近的人需要知道什么 标题 @@ -66,7 +46,6 @@ 分类与位置 - 分类、位置和有效期决定附近的人如何看到它 类型 diff --git a/pages/publish/publish.wxss b/pages/publish/publish.wxss index 099d76b..c409557 100644 --- a/pages/publish/publish.wxss +++ b/pages/publish/publish.wxss @@ -25,27 +25,31 @@ } .form-card { - padding: 30rpx; - background: #fffefa; + padding: 30rpx 28rpx; + border: 1rpx solid rgba(31, 63, 52, 0.1); + border-radius: 18rpx; + background: rgba(255, 254, 250, 0.96); + box-shadow: 0 12rpx 30rpx rgba(23, 32, 29, 0.06); } .form-section { display: flex; flex-direction: column; - gap: 22rpx; - padding: 24rpx; - border: 1rpx solid rgba(31, 63, 52, 0.1); - border-radius: 16rpx; - background: #fffefa; + gap: 24rpx; + padding: 0; + border: 0; + background: transparent; } .form-section + .form-section { - margin-top: 4rpx; + margin-top: 10rpx; + padding-top: 28rpx; + border-top: 1rpx solid rgba(31, 63, 52, 0.1); } .form-section-head { - padding-bottom: 18rpx; - border-bottom: 1rpx solid rgba(31, 63, 52, 0.08); + padding-bottom: 0; + border-bottom: 0; } .form-section-title { @@ -55,13 +59,6 @@ line-height: 1.25; } -.form-section-note { - margin-top: 8rpx; - color: #697970; - font-size: 23rpx; - line-height: 1.4; -} - .field { min-width: 0; } @@ -88,99 +85,6 @@ font-weight: 900; } -.publish-ready { - padding: 24rpx; - border: 1rpx solid rgba(31, 102, 88, 0.14); - border-radius: 16rpx; - background: #f1f8f4; -} - -.ready-head { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 18rpx; - margin-bottom: 18rpx; -} - -.ready-title { - color: #14211d; - font-size: 30rpx; - font-weight: 900; - line-height: 1.25; -} - -.ready-note { - margin-top: 6rpx; - color: #697970; - font-size: 23rpx; - line-height: 1.4; -} - -.ready-count { - flex: 0 0 auto; - min-width: 78rpx; - height: 58rpx; - padding: 0 14rpx; - border-radius: 14rpx; - background: #1f6658; - color: #ffffff; - font-size: 26rpx; - font-weight: 900; - line-height: 58rpx; - text-align: center; -} - -.ready-grid { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 12rpx; -} - -.ready-item { - display: flex; - align-items: center; - min-width: 0; - min-height: 72rpx; - padding: 12rpx; - border-radius: 14rpx; - background: rgba(255, 254, 250, 0.82); -} - -.ready-dot { - flex: 0 0 18rpx; - width: 18rpx; - height: 18rpx; - margin-right: 12rpx; - border-radius: 999rpx; - background: #c9d0ca; -} - -.ready-item.done .ready-dot { - background: #1f6658; -} - -.ready-copy { - min-width: 0; -} - -.ready-label { - color: #2e423a; - font-size: 22rpx; - font-weight: 900; - line-height: 1.25; -} - -.ready-value { - margin-top: 4rpx; - overflow: hidden; - color: #697970; - font-size: 22rpx; - line-height: 1.25; - text-overflow: ellipsis; - white-space: nowrap; -} - .label { margin-bottom: 12rpx; color: #2e423a; @@ -503,3 +407,18 @@ .publish-action .bottom-action-inner { grid-template-columns: minmax(0, 1fr) 186rpx; } + +.publish-action .bottom-action-title { + color: #173b33; +} + +.publish-action .bottom-action-note { + color: #5f7169; +} + +.publish-action .primary-button[disabled] { + opacity: 1; + background: #dce8e2; + color: #4c665d; + box-shadow: none; +} diff --git a/project.config.json b/project.config.json index ecb9a4d..a272efa 100644 --- a/project.config.json +++ b/project.config.json @@ -31,9 +31,42 @@ }, "simulatorPluginLibVersion": {}, "packOptions": { - "ignore": [], + "ignore": [ + { + "type": "folder", + "value": ".git" + }, + { + "type": "folder", + "value": ".agents" + }, + { + "type": "folder", + "value": ".claude" + }, + { + "type": "folder", + "value": ".github" + }, + { + "type": "folder", + "value": ".understand-anything" + }, + { + "type": "folder", + "value": "harness" + }, + { + "type": "folder", + "value": "scripts" + }, + { + "type": "folder", + "value": "log" + } + ], "include": [] }, "editorSetting": {}, "cloudfunctionTemplateRoot": "cloudfunctionTemplate/" -} +} \ No newline at end of file diff --git a/scripts/check-candidate-flow.mjs b/scripts/check-candidate-flow.mjs index 5f09eac..0dc5678 100644 --- a/scripts/check-candidate-flow.mjs +++ b/scripts/check-candidate-flow.mjs @@ -67,37 +67,41 @@ function trustInsight(overrides = {}, commentCount = 0) { { const result = trustInsight({ confirmations: 5, lastConfirmedAt: Date.now() - 60 * 1000 }); assert.equal(result.title, '有确认信号'); - assert.match(result.hint, /现场|评论|判断/); + assert.match(result.body, /确认信号/); + assert.equal(result.signals.find((signal) => signal.key === 'confirm').value, 5); } { const result = trustInsight({ confirmations: 1, reportCount: 2 }); assert.equal(result.title, '存在多次举报'); - assert.match(`${result.body}${result.hint}`, /谨慎|不要直接行动|管理员/); + assert.match(result.body, /谨慎/); + assert.equal(result.signals.find((signal) => signal.key === 'report').value, 2); } { const result = trustInsight({ confirmations: 3, staleCount: 3 }); assert.equal(result.title, '可能已经过时'); - assert.match(`${result.body}${result.hint}`, /不再准确|最新情况|补充/); + assert.match(result.body, /不再准确/); + assert.equal(result.signals.find((signal) => signal.key === 'stale').value, 3); } { const result = trustInsight({}, 4); assert.equal(result.title, '先看评论线索'); - assert.match(`${result.body}${result.hint}`, /先看|提问|补充/); + assert.match(result.body, /先看/); + assert.equal(result.signals.find((signal) => signal.key === 'comment').value, 4); } { const result = trustInsight({ status: 'resolved', confirmations: 3 }, 2); assert.equal(result.title, '任务已关闭'); - assert.match(`${result.body}${result.hint}`, /历史线索|不需要继续确认/); + assert.match(result.body, /历史线索/); } { const result = trustInsight({ status: 'expired', confirmations: 3 }, 2); assert.equal(result.title, '任务已过期'); - assert.match(`${result.body}${result.hint}`, /历史线索|不再接收确认/); + assert.match(result.body, /历史线索/); } console.log('Candidate flow checks passed.'); diff --git a/scripts/check-devtools-readiness.mjs b/scripts/check-devtools-readiness.mjs index ff20958..45f41bb 100644 --- a/scripts/check-devtools-readiness.mjs +++ b/scripts/check-devtools-readiness.mjs @@ -129,6 +129,21 @@ const readinessDocs = [ 'harness/viral-manual-artifact-manifest-checklist.md' ]; +const serviceSimplificationDocs = [ + ...readinessDocs, + 'harness/devtools-smoke-product-brief.md', + 'harness/devtools-smoke-checklist.md', + 'harness/devtools-service-recovery-checklist.md', + 'harness/devtools-recovery-report-design-note.md', + 'harness/manual-runbook-checklist.md', + 'harness/manual-preflight-alignment-checklist.md', + 'harness/hardening-product-brief.md', + 'harness/hardening-design-checklist.md', + 'harness/manual-test-results.example.json', + 'harness/sanitized-summary-checklist.md', + 'DESIGN_SYSTEM.md' +]; + function readProjectFile(relativePath) { return readFileSync(join(rootDir, relativePath), 'utf8'); } @@ -199,7 +214,94 @@ function runCheck(scriptPath, label, options = {}) { ); } +function runServiceSimplificationCheck() { + const publishWxml = readProjectFile('pages/publish/publish.wxml'); + const publishWxss = readProjectFile('pages/publish/publish.wxss'); + const mapJs = readProjectFile('pages/map/map.js'); + const mapWxml = readProjectFile('pages/map/map.wxml'); + const mapWxss = readProjectFile('pages/map/map.wxss'); + const adminJs = readProjectFile('pages/admin/admin.js'); + const detailWxml = readProjectFile('pages/detail/detail.wxml'); + const detailWxss = readProjectFile('pages/detail/detail.wxss'); + const adminWxml = readProjectFile('pages/admin/admin.wxml'); + const adminWxss = readProjectFile('pages/admin/admin.wxss'); + const feedbackWxml = readProjectFile('pages/feedback/feedback.wxml'); + const meWxml = readProjectFile('pages/me/me.wxml'); + const myPostsWxml = readProjectFile('pages/my-posts/my-posts.wxml'); + const activitiesWxml = readProjectFile('pages/activities/activities.wxml'); + const serviceSimplificationDocText = serviceSimplificationDocs + .map((relativePath) => readProjectFile(relativePath)) + .join('\n'); + const combined = [ + publishWxml, + publishWxss, + mapJs, + mapWxml, + mapWxss, + adminJs, + detailWxml, + detailWxss, + adminWxml, + adminWxss, + feedbackWxml, + meWxml, + myPostsWxml, + activitiesWxml, + serviceSimplificationDocText + ].join('\n'); + + const removedDisplayPatterns = [ + ['publish readiness card', /\bpublish-ready\b|\bready-grid\b/], + ['publish section notes', /\bform-section-note\b/], + ['map drawer duplicate counter', /\bdrawer-counter\b|按发布时间排序/], + ['publish spread step list', /\bspread-steps\b|\bspread-step\b|\bspread-notes\b/], + ['ordinary share guide rows', /\bshare-guide\b|\bshare-note\b/], + ['receiver guide rows', /\bshare-receiver-rows\b|\bshare-receiver-note\b/], + ['relay prompt detail rows', /\bcomment-relay-rows\b|\bcomment-relay-row\b/], + ['trust secondary notes', /\btrust-signal-note\b|\btrust-hint\b/], + ['admin duplicate count header', /仅管理员可见|feedback-count\b|来自“我的”页反馈入口|按举报和过时风险排序/], + ['feedback/list explanatory headings', /问题、建议、想要的功能|当前账号发布过的附近任务|你确认、标记过时或举报过的附近任务/], + ['empty-state explanatory copy', /可以从身边的失物|在详情页确认有效|用户提交后会显示在这里|换个关键词/], + ['profile secondary action copy', /\{\{nextAction\.note\}\}|你刚参与过的附近任务/], + ['map removed count state', /activeCategoryText|viewportPostCount/], + ['admin removed feedback count state', /stats:\s*\{[^}]*\bfeedback\b|feedback:\s*feedbacks\.length|feedback:\s*this\.data\.feedbacks\.length/], + ['stale publish readiness docs', /PublishReadiness|发布准备度|准备度清单|准备度文案|发布准备”模块|准备度计数|准备项两列网格|publish-readiness|readiness checklist card|readiness action checklist/] + ]; + + for (const [label, pattern] of removedDisplayPatterns) { + assert.doesNotMatch(combined, pattern, `Simplified UI should not reintroduce ${label}.`); + } + + const requiredFunctionalPatterns = [ + ['publish bottom action', publishWxml, /class="bottom-action publish-action"[\s\S]*bindtap="submit"/], + ['publish location confirmation', publishWxml, /bindtap="confirmLocation"/], + ['map list filters', mapWxml, /wx:for="\{\{categoryFilters\}\}"[\s\S]*bindtap="changeCategory"/], + ['map detail entry', mapWxml, /catchtap="openDetail"/], + ['share receiver focused home CTA', detailWxml, /bindtap="goHomeWithPost"[\s\S]*回首页查这条/], + ['receiver conversion share CTA', detailWxml, /data-share-context="receiverConversion"/], + ['post-publish share CTA', detailWxml, /publishSpreadPlan\.shouldEncourageSpread[\s\S]*open-type="share"/], + ['ordinary share CTA', detailWxml, /shareMessage[\s\S]*open-type="share"/], + ['trust actions', detailWxml, /data-action="confirm"[\s\S]*data-action="stale"[\s\S]*data-action="report"/], + ['comment entry', detailWxml, /bindtap="openCommentDialog"/], + ['admin refresh', adminWxml, /bindtap="refresh"/], + ['admin search and filters', adminWxml, /bindinput="onSearchInput"[\s\S]*bindtap="changeFilter"/], + ['admin moderation actions', adminWxml, /bindtap="openDetail"[\s\S]*bindtap="resolve"[\s\S]*bindtap="hide"/], + ['feedback submit', feedbackWxml, /bindtap="submitFeedback"/], + ['profile next action', meWxml, /bindtap="handleNextAction"/], + ['profile feedback entry', meWxml, /bindtap="goFeedback"/], + ['my posts empty action and detail open', myPostsWxml, /bindtap="goPublish"[\s\S]*bindtap="openDetail"/], + ['activities empty action and detail open', activitiesWxml, /bindtap="goHome"[\s\S]*bindtap="openDetail"/] + ]; + + for (const [label, text, pattern] of requiredFunctionalPatterns) { + assert.match(text, pattern, `Simplification should keep ${label}.`); + } + + console.log('Service simplification checks passed.'); +} + runCheck('scripts/check-publish-flow.mjs', 'publish flow model check'); +runServiceSimplificationCheck(); runCheck('scripts/check-publish-spread.mjs', 'post-publish spread plan check'); runCheck('scripts/check-comment-relay.mjs', 'comment relay prompt check'); runCheck('scripts/check-action-relay.mjs', 'action relay prompt check'); diff --git a/scripts/check-publish-flow.mjs b/scripts/check-publish-flow.mjs index f0d8b48..71efa1d 100644 --- a/scripts/check-publish-flow.mjs +++ b/scripts/check-publish-flow.mjs @@ -56,14 +56,14 @@ const guestState = state({ isGuest: true }); assert.equal(guestState.buttonText, '去登录'); assert.equal(guestState.actionDisabled, false); assert.equal(guestState.primaryAction, 'login'); -assert.equal(guestState.items.find((item) => item.key === 'account').done, false); +assert.match(guestState.title, /登录/); const emptyState = state(); assert.equal(emptyState.buttonText, '补标题'); assert.equal(emptyState.actionDisabled, true); assert.equal(emptyState.primaryAction, 'fill'); assert.equal(emptyState.missing[0], '标题'); -assert.equal(emptyState.items.find((item) => item.key === 'content').done, false); +assert.match(emptyState.note, /标题|详情|当前位置/); const locatingState = state({ locationStatus: 'locating', @@ -78,7 +78,7 @@ assert.equal(locatingState.actionDisabled, true); assert.equal(locatingState.buttonText, '确认位置中'); assert.equal(locatingState.title, '正在确认位置'); assert.equal(locatingState.primaryAction, 'waitLocation'); -assert.equal(locatingState.items.find((item) => item.key === 'location').value, '确认中'); +assert.equal(locatingState.locationActionText, '确认中'); const needsLocationState = state({ form: { @@ -108,7 +108,7 @@ assert.equal(failedLocationState.buttonText, '重试定位'); assert.equal(failedLocationState.title, '位置未确认'); assert.equal(failedLocationState.primaryAction, 'confirmLocation'); assert.match(failedLocationState.note, /授权|重试/); -assert.equal(failedLocationState.items.find((item) => item.key === 'location').value, '待重试'); +assert.equal(failedLocationState.locationActionText, '重试定位'); const lostFoundState = state({ hasLocation: true, @@ -138,7 +138,7 @@ const missingExpiryState = state({ assert.equal(missingExpiryState.ready, false); assert.deepEqual(missingExpiryState.missing, ['有效期']); assert.equal(missingExpiryState.buttonText, '选有效期'); -assert.equal(missingExpiryState.items.find((item) => item.key === 'expiry').done, false); +assert.equal(missingExpiryState.primaryAction, 'fill'); const readyLostFoundState = state({ hasLocation: true, @@ -169,7 +169,6 @@ assert.equal(readyState.ready, true); assert.equal(readyState.actionDisabled, false); assert.equal(readyState.buttonText, '发布'); assert.equal(readyState.title, '可以发布到附近'); -assert.equal(readyState.completionText, '5/5'); assert.equal(readyState.primaryAction, 'publish'); assert.match(readyState.note, /2张图片/); @@ -185,7 +184,7 @@ const customExpiryState = state({ } }); assert.equal(customExpiryState.ready, true); -assert.equal(customExpiryState.items.find((item) => item.key === 'expiry').value, '已设置'); +assert.equal(customExpiryState.primaryAction, 'publish'); const longCustomExpiryState = state({ hasLocation: true, diff --git a/utils/format.js b/utils/format.js index 87a3093..0cbdcb6 100644 --- a/utils/format.js +++ b/utils/format.js @@ -61,87 +61,72 @@ export function formatTrustInsight(post = {}, commentCount = 0) { let tone = 'neutral'; let title = '还缺信任信号'; let body = '暂时没有确认、过时或举报记录,建议结合现场情况判断。'; - let hint = '你可以先用评论提问,或在现场核实后再记录判断。'; if (status === 'resolved') { tone = 'done'; title = '任务已关闭'; body = '发布者或管理员已标记处理完成,评论仅作为历史线索参考。'; - hint = '不需要继续确认,可查看评论了解处理经过。'; } else if (status === 'hidden') { tone = 'danger'; title = '内容已隐藏'; body = '这条任务因举报或管理处理被隐藏,普通列表不会继续展示。'; - hint = '如需复核,请联系管理员处理。'; } else if (status === 'expired') { tone = 'neutral'; title = '任务已过期'; body = comments > 0 ? `已超过有效期,仍可查看${comments}条历史线索。` : '已超过有效期,暂时没有历史评论可参考。'; - hint = '不再接收确认,建议返回地图查看新的附近任务。'; } else if (reportCount >= 2) { tone = 'danger'; title = '存在多次举报'; body = `已有${reportCount}次举报,发布内容需要谨慎判断。`; - hint = '不要直接行动,先看评论或等待管理员处理。'; } else if (status === 'stale' || staleCount >= 3) { tone = 'warn'; title = '可能已经过时'; body = `已有${staleCount}次过时反馈,信息可能不再准确。`; - hint = '如果你在现场看到变化,可以补充评论说明最新情况。'; } else if (reportCount > 0) { tone = 'warn'; title = '有举报提醒'; body = `已有${reportCount}次举报,建议先核对评论和现场情况。`; - hint = '如确认内容不当,可继续举报;如内容有效,可补充评论。'; } else if (staleCount > 0) { tone = 'warn'; title = '有人认为需复核'; body = `已有${staleCount}次过时反馈,信息可能发生了变化。`; - hint = '看到最新情况时,优先写评论补充现场状态。'; } else if (confirmations > 0) { tone = 'good'; title = '有确认信号'; body = `已有${confirmations}次确认信号,${lastConfirmedText}。`; - hint = '仍建议结合现场和评论判断;看到情况属实再点确认。'; } else if (comments > 0) { tone = 'neutral'; title = '先看评论线索'; body = `已有${comments}条评论,先看补充信息再决定是否行动。`; - hint = '如果评论仍不够清楚,可以继续提问或补充线索。'; } return { tone, title, body, - hint, signals: [ { key: 'confirm', label: '有效确认', value: confirmations, - note: post.lastConfirmedAt ? lastConfirmedText : '等现场确认', tone: confirmations > 0 ? 'good' : 'neutral' }, { key: 'stale', label: '过时反馈', value: staleCount, - note: staleCount >= 3 ? '已触发过时' : '3次会标记', tone: staleCount > 0 ? 'warn' : 'neutral' }, { key: 'report', label: '举报提醒', value: reportCount, - note: reportCount >= 2 ? '达到隐藏阈值' : '2次会隐藏', tone: reportCount > 0 ? 'danger' : 'neutral' }, { key: 'comment', label: '评论线索', value: comments, - note: comments > 0 ? '先看补充' : '等待补充', tone: comments > 0 ? 'comment' : 'neutral' } ]