From 53cadcc35fb1467a9da96ed68c86563bc7ec1344 Mon Sep 17 00:00:00 2001 From: "lichenyang.anarkh" Date: Tue, 14 Jul 2026 15:52:01 +0800 Subject: [PATCH] fix: stabilize refreshed mini program UI --- DESIGN_SYSTEM.md | 194 ++++-- app.wxss | 541 +++++++++++++--- custom-tab-bar/index.wxml | 14 +- custom-tab-bar/index.wxss | 30 +- harness/claude-progress.md | 54 ++ harness/feature_list.json | 22 +- pages/activities/activities.wxss | 83 +-- pages/admin/admin.wxss | 236 +++---- pages/detail/detail.wxml | 11 +- pages/detail/detail.wxss | 860 ++++++++++++-------------- pages/feedback/feedback.wxml | 6 +- pages/feedback/feedback.wxss | 68 +- pages/map/map.wxml | 38 +- pages/map/map.wxss | 436 +++++-------- pages/me/me.wxml | 1 - pages/me/me.wxss | 350 ++++------- pages/my-posts/my-posts.wxss | 55 +- pages/publish/publish.wxml | 8 +- pages/publish/publish.wxss | 291 ++++----- scripts/check-devtools-readiness.mjs | 30 + scripts/check-map-list-resilience.mjs | 124 +++- 21 files changed, 1872 insertions(+), 1580 deletions(-) diff --git a/DESIGN_SYSTEM.md b/DESIGN_SYSTEM.md index f2f9dec..ba366ca 100644 --- a/DESIGN_SYSTEM.md +++ b/DESIGN_SYSTEM.md @@ -4,9 +4,18 @@ Street Tasks is a map-first WeChat mini program for short-lived neighborhood information. The UI should feel quick, local, trustworthy, and easy to scan while someone is outside or moving. -## Visual Direction +## Visual Direction — Modern Minimal -Use a warm, restrained local-life tool style. Avoid marketing-page hero layouts, glossy glass effects, heavy blue-purple gradients, oversized shadows, and decorative shapes that do not carry information. +Clean, white, generous whitespace, thin borders, almost no shadows. Color is used sparingly and meaningfully — one primary teal for actions and confirmations, orange accent for urgency. Inspired by Linear, Notion, and Apple native apps. + +**Key principles:** +- White cards on light gray background — no decorative gradients +- Thin 1rpx borders at `#E5E7EB` — shadows only for floating elements (map tools) +- One primary color (`#0F766E` teal) for interactive elements +- Accent orange (`#EA580C`) used very sparingly: discover button, resolve action +- Typography hierarchy through weight (800/600/400), not color +- Small precise radii (10/12/14rpx) — not soft pill shapes +- No decorative patterns, grids, or ornaments ## TDesign Strategy @@ -14,34 +23,122 @@ The project currently has no frontend build step and no mini program npm depende - Components should have predictable states: default, active, disabled, loading, empty, and error. - Touch targets should be at least `72rpx` high for primary actions and at least `44rpx` for small icon controls. -- Card radius should stay at or below `16rpx`. +- Card radius should stay at or below `14rpx`. - Use semantic colors instead of one-off values. - If `tdesign-miniprogram` is introduced later, map these tokens to TDesign theme variables first, then replace native controls incrementally. -## Tokens - -- Background: `#F4F1EA` -- Surface: `#FFFEFA` -- Surface muted: `#F7F3EA` -- Text strong: `#14211D` -- Text normal: `#2E423A` -- Text muted: `#697970` -- Border: `rgba(31, 63, 52, 0.12)` -- Primary: `#1F6658` -- Primary dark: `#143E37` -- Accent: `#D7673F` -- Warning: `#B9791F` -- Danger: `#A73527` -- Success surface: `#E4F0E9` -- Warning surface: `#FFF2DA` -- Danger surface: `#FFE9E2` - -## Typography - -- Page title: `40-44rpx`, `font-weight: 900`, line-height `1.12-1.18`. -- Section title: `30-32rpx`, `font-weight: 900`, line-height `1.25`. -- Body text: `28-30rpx`, line-height `1.5-1.6`. -- Meta text: `22-24rpx`, line-height `1.35-1.5`. +## Design Tokens (CSS Custom Properties) + +All tokens are defined in `app.wxss` on the `page` selector and referenced via `var(--token-name)`. Never hard-code hex or rgba values in normal page-level WXSS — use the token. Exception: `cover-view` overlays above native components such as `map` must use hard-coded values because their style support is more limited. + +### Color + +| Token | Value | Usage | +|-------|-------|-------| +| `--bg` | `#F7F8FA` | Page background | +| `--surface` | `#FFFFFF` | Card/panel surface | +| `--surface-muted` | `#F2F3F5` | Secondary surface | +| `--surface-neutral` | `#F2F3F5` | Neutral surface, disabled bg | +| `--field-bg` | `#F7F8FA` | Input field background | +| `--primary-surface` | `#F0FDFA` | Light teal tint bg | +| `--primary-deep` | `#0F766E` | Deep teal (map bg) | +| `--primary` | `#0F766E` | Brand primary | +| `--primary-dark` | `#0D655E` | Primary dark | +| `--primary-text` | `#0F766E` | Primary text variant | +| `--accent` | `#EA580C` | Accent orange (rare use) | +| `--accent-dark` | `#C2410C` | Accent dark | +| `--warning` | `#D97706` | Warning | +| `--warning-text` | `#B45309` | Warning text | +| `--warning-text-alt` | `#92400E` | Warning text alt | +| `--danger` | `#DC2626` | Danger/red | +| `--done-text` | `#047857` | Done/resolved text | +| `--success-bg` | `#ECFDF5` | Success surface | +| `--warning-bg` | `#FFFBEB` | Warning surface | +| `--danger-bg` | `#FEF2F2` | Danger surface | + +### Text Color + +| Token | Value | Usage | +|-------|-------|-------| +| `--text-strong` | `#1A1A1A` | Titles, primary content | +| `--text-normal` | `#374151` | Body text | +| `--text-muted` | `#6B7280` | Secondary, meta, helper | +| `--text-secondary` | `#4B5563` | Filter chip default | + +### Border + +| Token | Value | Usage | +|-------|-------|-------| +| `--border` | `#E5E7EB` | Default card border | +| `--border-soft` | `#E5E7EB` | Soft border | +| `--border-strong` | `#D1D5DB` | Strong border | +| `--border-focus` | `rgba(15,118,110,0.3)` | Focus/active state | +| `--divider` | `#F0F1F3` | Hairline dividers | +| `--relay-border-good` | `rgba(15,118,110,0.15)` | Relay panel good tone border | +| `--relay-border-warn` | `rgba(217,119,6,0.2)` | Relay panel warn tone border | +| `--relay-border-danger` | `rgba(220,38,38,0.18)` | Relay panel danger tone border | +| `--relay-border-done` | `rgba(4,120,87,0.15)` | Relay panel done tone border | + +### Typography Scale + +| Token | Size | Usage | +|-------|------|-------| +| `--fs-display` | `44rpx` | Large numbers, hero titles | +| `--fs-title` | `42rpx` | Page title | +| `--fs-section` | `32rpx` | Section title | +| `--fs-body` | `28rpx` | Body text | +| `--fs-label` | `24rpx` | Labels, buttons, helper | +| `--fs-meta` | `22rpx` | Smallest meta info | + +### Font Weight + +| Token | Value | Usage | +|-------|-------|-------| +| `--fw-black` | `800` | Titles only (was 900, dialed back) | +| `--fw-bold` | `600` | Section titles, labels, buttons | +| `--fw-regular` | `400` | Body text | + +### Border Radius + +| Token | Value | Usage | +|-------|-------|-------| +| `--radius-sm` | `10rpx` | Small components | +| `--radius-md` | `12rpx` | Buttons, inputs, images | +| `--radius-lg` | `14rpx` | Cards, panels, primary buttons | +| `--radius-pill` | `999rpx` | Pills, tags, chips | + +### Spacing (4rpx base) + +| Token | Value | +|-------|-------| +| `--space-1` | `4rpx` | +| `--space-2` | `8rpx` | +| `--space-3` | `12rpx` | +| `--space-4` | `16rpx` | +| `--space-5` | `20rpx` | +| `--space-6` | `24rpx` | +| `--space-7` | `28rpx` | +| `--space-8` | `32rpx` | + +### Elevation + +| Token | Value | Usage | +|-------|-------|-------| +| `--shadow-card` | `0 1rpx 3rpx rgba(0,0,0,0.04)` | Default card (barely visible) | +| `--shadow-raised` | `0 2rpx 8rpx rgba(0,0,0,0.06), 0 1rpx 2rpx rgba(0,0,0,0.04)` | Floating elements | +| `--shadow-dock` | `0 -1rpx 3rpx rgba(0,0,0,0.04)` | Bottom dock / tab bar | +| `--shadow-primary` | `0 2rpx 6rpx rgba(15,118,110,0.15)` | Primary button | +| `--shadow-accent` | `0 2rpx 6rpx rgba(234,88,12,0.15)` | Accent / share button | + +### Disabled State (unified) + +All `button[disabled]` elements use: `opacity: 1; background: var(--surface-neutral); color: var(--text-muted); box-shadow: none; border-color: transparent;` + +## Tone System + +Panels and marks use semantic tone modifiers: `.good`, `.warn`, `.danger`, `.done`, `.neutral`. In the minimal system, tones are expressed through background tint only — no gradient overlays. + +Applied to: `relay-panel`, `activity-mark`, `tag`, `trust-insight`, `trust-signal`, `signal-item`. ## Layout Rules @@ -49,20 +146,40 @@ The project currently has no frontend build step and no mini program npm depende - Lists open as bottom drawers or compact cards, not full marketing sections. - Forms use grouped fields and clear labels; helper text goes below the relevant control. - Repeated items should be compact cards with image, title, tags, and one clear next action. -- The custom tab bar should be docked to the bottom with an opaque surface. Avoid floating gaps on form or list pages because content can show through behind the navigation. +- The custom tab bar should be docked to the bottom with a near-white translucent surface. Keep it thin — one hairline border, no heavy shadow. - Keep all user-facing copy in Chinese. ## 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 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. -- `SignalPill`: small metric tile for repeated task-card signals such as confirmation count, stale count, and remaining time. -- `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. +### Global Classes (defined in app.wxss) + +- **`.panel`** — Base card: surface bg, 1rpx border, radius-lg, no shadow. +- **`.tag`** — Pill-shaped label, no border. Tone variants: `.warn`, `.danger`, `.done`, `.neutral`. +- **`.primary-button`** / **`.secondary-button`** / **`.ghost-button`** — Button hierarchy. Solid colors, no gradients. +- **`.bottom-action`** — Fixed action bar above tab bar with title + helper + primary button. +- **`.empty-panel`** — Centered empty state with `.empty-title`, `.empty-body`, `.empty-action`. +- **`.stat-panel`** — Metric grid (default 4-col). Override columns via page-level selector. Contains `.stat-item` > `.metric` + `.metric-label`. +- **`.head-mark`** — 78rpx solid near-black square with Chinese character for page headers. +- **`.form-field`** — Unified input/textarea/picker base: bg, border, radius, focus state. +- **`.filter-chip`** — Pill filter button, `.active` for selected state. +- **`.activity-mark`** — Colored label tile. Tone variants: `.done` (green), `.warn` (amber), `.danger` (red). +- **`.relay-panel`** — Share/relay prompt panel. Tone variants control border tint. Contains kicker pill, title, body, rows, actions, note. +- **`.share-button`** — Solid accent button for share actions. +- **`.page`** / **`.stack`** / **`.row`** / **`.between`** — Layout utilities. + +### Page-Specific Patterns + +- **`BottomAction`**: fixed above the custom tab bar, translucent white, with one short title, one helper line, and one primary action. Use it for page-level submit actions. +- **`FormSection`**: grouped form area with a section title and related fields. +- **`CategoryOption`**: two-column direct-choice buttons for small option sets. +- **`SignalPill`**: small metric tile for repeated task-card signals. +- **`LocationCheck`**: explicit location confirmation block in the publish form. Idle/ready/failed states expressed through border tint + bg tint. +- **`Publish readiness`** expressed through `LocationCheck` and the fixed `BottomAction`. +- **`TrustInsight`**: detail-page section before trust actions. One cautious status sentence + compact segmented metrics. +- **`RelayPanel`**: unified share/relay prompt used in 5+ contexts. Tone (`.good`/`.warn`/`.danger`/`.done`) controls border color. +- **`MapListEntry`**: compact top-right `cover-view` button — "列表 6". +- **`MapToolRow`**: location and discover controls at lower-right of map, above tab bar. +- **`CustomTabBar`**: bottom dock with a solid teal indicator above the active tab. Use normal `view`/`image` nodes because the map viewport now ends above the dock; fixed `cover-view` nodes can leave duplicate frames while content scrolls. ## QA Checklist @@ -70,3 +187,6 @@ The project currently has no frontend build step and no mini program npm depende - Check 375px-equivalent narrow screens for text overflow. - Verify buttons do not overlap safe areas or the custom tab bar. - Verify empty, loading, disabled, and active states still have visible styling. +- Verify relay panels render correctly for all 5 contexts. +- Verify tab bar indicator bar appears on the correct active tab. +- Verify no decorative gradients or grid patterns remain. diff --git a/app.wxss b/app.wxss index ed2bbb0..87fd8fe 100644 --- a/app.wxss +++ b/app.wxss @@ -1,11 +1,103 @@ +/* ============================================================ + Design Tokens — 街区任务 (Modern Minimal) + 所有颜色/尺寸/阴影统一在这里定义,组件类通过 var() 引用 + ============================================================ */ page { + /* ---- 背景与表面 ---- */ + --bg: #F7F8FA; + --surface: #FFFFFF; + --surface-muted: #F2F3F5; + --surface-neutral: #F2F3F5; + --field-bg: #F7F8FA; + --primary-surface: #F0FDFA; + + /* ---- 深绿(地图/导航/个人页) ---- */ + --primary-deep: #0F766E; + + /* ---- 文字 ---- */ + --text-strong: #1A1A1A; + --text-normal: #374151; + --text-muted: #6B7280; + --text-secondary: #4B5563; + --primary-text: #0F766E; + + /* ---- 边框 ---- */ + --border: #E5E7EB; + --border-soft: #E5E7EB; + --border-strong: #D1D5DB; + --border-focus: rgba(15, 118, 110, 0.3); + --divider: #F0F1F3; + + /* ---- Relay 面板边框色 ---- */ + --relay-border-good: rgba(15, 118, 110, 0.15); + --relay-border-warn: rgba(217, 119, 6, 0.2); + --relay-border-danger: rgba(220, 38, 38, 0.18); + --relay-border-done: rgba(4, 120, 87, 0.15); + + /* ---- 品牌色 ---- */ + --primary: #0F766E; + --primary-dark: #0D655E; + --accent: #EA580C; + --accent-dark: #C2410C; + + /* ---- 语义色 ---- */ + --warning: #D97706; + --warning-text: #B45309; + --warning-text-alt: #92400E; + --danger: #DC2626; + --success-bg: #ECFDF5; + --warning-bg: #FFFBEB; + --danger-bg: #FEF2F2; + --done-text: #047857; + + /* ---- 字号(收敛到 6 档) ---- */ + --fs-display: 44rpx; + --fs-title: 42rpx; + --fs-section: 32rpx; + --fs-body: 28rpx; + --fs-label: 24rpx; + --fs-meta: 22rpx; + + /* ---- 字重 ---- */ + --fw-black: 800; + --fw-bold: 600; + --fw-regular: 400; + + /* ---- 圆角(更小更精确) ---- */ + --radius-sm: 10rpx; + --radius-md: 12rpx; + --radius-lg: 14rpx; + --radius-pill: 999rpx; + + /* ---- 间距(4rpx 基准) ---- */ + --space-1: 4rpx; + --space-2: 8rpx; + --space-3: 12rpx; + --space-4: 16rpx; + --space-5: 20rpx; + --space-6: 24rpx; + --space-7: 28rpx; + --space-8: 32rpx; + + /* ---- Elevation(极轻) ---- */ + --shadow-card: 0 1rpx 3rpx rgba(0, 0, 0, 0.04); + --shadow-raised: 0 2rpx 8rpx rgba(0, 0, 0, 0.06), 0 1rpx 2rpx rgba(0, 0, 0, 0.04); + --shadow-dock: 0 -1rpx 3rpx rgba(0, 0, 0, 0.04); + --shadow-primary: 0 2rpx 6rpx rgba(15, 118, 110, 0.15); + --shadow-accent: 0 2rpx 6rpx rgba(234, 88, 12, 0.15); + + /* ---- 基础 ---- */ min-height: 100%; - background: #f4f1ea; - color: #14211d; + background: var(--bg); + color: var(--text-strong); font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif; - font-size: 28rpx; + font-size: var(--fs-body); + font-weight: var(--fw-regular); } +/* ============================================================ + Reset + ============================================================ */ button { display: flex; align-items: center; @@ -27,20 +119,20 @@ button::after { border: 0; } +/* ============================================================ + 布局工具类 + ============================================================ */ .page { min-height: 100vh; box-sizing: border-box; - padding: 32rpx 28rpx; - background: - linear-gradient(180deg, rgba(31, 102, 88, 0.12), rgba(244, 241, 234, 0) 300rpx), - linear-gradient(135deg, rgba(215, 103, 63, 0.08), rgba(244, 241, 234, 0) 380rpx), - #f4f1ea; + padding: var(--space-8) var(--space-7); + background: var(--bg); } .stack { display: flex; flex-direction: column; - gap: 20rpx; + gap: var(--space-5); } .row { @@ -52,85 +144,91 @@ button::after { justify-content: space-between; } +/* ============================================================ + 面板 / 卡片 + ============================================================ */ .panel { - background: #fffefa; - border: 1rpx solid rgba(31, 63, 52, 0.12); - border-radius: 16rpx; - box-shadow: 0 12rpx 32rpx rgba(23, 32, 29, 0.07); + background: var(--surface); + border: 1rpx solid var(--border); + border-radius: var(--radius-lg); } +/* ============================================================ + 文字 + ============================================================ */ .muted { - color: #697970; - font-size: 24rpx; + color: var(--text-muted); + font-size: var(--fs-label); line-height: 1.5; } .title { - color: #14211d; - font-size: 42rpx; - font-weight: 900; + color: var(--text-strong); + font-size: var(--fs-title); + font-weight: var(--fw-black); line-height: 1.15; letter-spacing: 0; } .section-title { - color: #14211d; - font-size: 32rpx; - font-weight: 900; + color: var(--text-strong); + font-size: var(--fs-section); + font-weight: var(--fw-black); line-height: 1.25; } +/* ============================================================ + 标签 / Tag + ============================================================ */ .tag { display: inline-flex; align-items: center; - min-height: 46rpx; - padding: 0 18rpx; - border: 1rpx solid rgba(31, 102, 88, 0.16); - border-radius: 999rpx; - background: #eaf4ef; - color: #1b5f52; - font-size: 22rpx; - font-weight: 800; + min-height: 40rpx; + padding: 0 16rpx; + border-radius: var(--radius-pill); + background: var(--primary-surface); + color: var(--primary-text); + font-size: var(--fs-meta); + font-weight: var(--fw-bold); } .tag.warn { - border-color: rgba(185, 121, 31, 0.2); - background: #fff2da; - color: #8a560c; + background: var(--warning-bg); + color: var(--warning-text-alt); } .tag.danger { - border-color: rgba(178, 54, 39, 0.18); - background: #ffe9e2; - color: #a73527; + background: var(--danger-bg); + color: var(--danger); } .tag.done { - border-color: rgba(31, 102, 88, 0.18); - background: #e4f0e9; - color: #28584e; + background: var(--success-bg); + color: var(--done-text); } .tag.neutral { - border-color: rgba(102, 115, 109, 0.18); - background: #f0eee7; - color: #697970; + background: var(--surface-muted); + color: var(--text-muted); } +/* ============================================================ + 按钮 + ============================================================ */ .primary-button, .secondary-button { width: 100%; - height: 92rpx; - border-radius: 16rpx; - font-weight: 900; - font-size: 30rpx; - transition: opacity 160ms ease, transform 160ms ease; + height: 88rpx; + border-radius: var(--radius-md); + font-weight: var(--fw-bold); + font-size: 28rpx; + transition: opacity 160ms ease; } .primary-button { color: #ffffff; - background: linear-gradient(135deg, #143e37, #25705f); - box-shadow: 0 18rpx 34rpx rgba(31, 102, 88, 0.24); + background: var(--primary); + box-shadow: var(--shadow-primary); } .primary-button:active, @@ -140,63 +238,366 @@ button::after { } .secondary-button { - border: 1rpx solid rgba(31, 102, 88, 0.2); - color: #1b5f52; - background: #eaf4ef; + border: 1rpx solid var(--border); + color: var(--text-strong); + background: var(--surface); } .ghost-button { height: 64rpx; - padding: 0 24rpx; - border: 1rpx solid rgba(31, 102, 88, 0.18); - border-radius: 14rpx; - background: rgba(255, 254, 250, 0.88); - color: #1b5f52; + padding: 0 var(--space-6); + border: 1rpx solid var(--border); + border-radius: var(--radius-md); + background: var(--surface); + color: var(--text-secondary); font-size: 26rpx; - font-weight: 800; + font-weight: var(--fw-bold); } +/* 统一 disabled 状态 */ button[disabled] { - opacity: 0.56; + opacity: 1; + background: var(--surface-neutral); + color: var(--text-muted); + box-shadow: none; + border-color: transparent; } +/* ============================================================ + 底部操作栏 BottomAction + 紧贴 tab bar 上方,用圆角顶部 + 向上阴影呈现"浮动面板"感, + 避免被误认为第二个 tab bar。 + ============================================================ */ .bottom-action { position: fixed; left: 0; right: 0; bottom: calc(116rpx + env(safe-area-inset-bottom)); z-index: 60; - padding: 18rpx 28rpx 20rpx; + padding: 20rpx var(--space-7) var(--space-5); box-sizing: border-box; - border-top: 1rpx solid rgba(31, 63, 52, 0.1); - background: rgba(255, 254, 250, 0.98); - box-shadow: 0 -12rpx 34rpx rgba(18, 31, 27, 0.08); + background: rgba(255, 255, 255, 0.98); + border-radius: 28rpx 28rpx 0 0; + box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.08); } .bottom-action-inner { display: grid; - grid-template-columns: minmax(0, 1fr) 220rpx; + grid-template-columns: minmax(0, 1fr) 200rpx; gap: 18rpx; align-items: center; } .bottom-action-title { - color: #14211d; + color: var(--text-strong); font-size: 26rpx; - font-weight: 900; + font-weight: var(--fw-bold); line-height: 1.25; } .bottom-action-note { - margin-top: 6rpx; - color: #697970; - font-size: 22rpx; + margin-top: var(--space-2); + color: var(--text-muted); + font-size: var(--fs-meta); line-height: 1.35; } .bottom-action .primary-button { + height: 72rpx; + border-radius: var(--radius-md); + font-size: var(--fs-body); +} + +/* ============================================================ + 空状态 EmptyPanel + ============================================================ */ +.empty-panel { + padding: 48rpx var(--space-7); + text-align: center; +} + +.empty-title { + color: var(--text-strong); + font-size: 30rpx; + font-weight: var(--fw-bold); + line-height: 1.3; +} + +.empty-body { + margin-top: var(--space-3); + color: var(--text-muted); + font-size: var(--fs-label); + line-height: 1.5; +} + +.empty-action { + margin-top: var(--space-5); + display: inline-block; +} + +/* ============================================================ + 统计面板 StatPanel + ============================================================ */ +.stat-panel { + display: grid; + grid-auto-flow: column; + grid-auto-columns: 1fr; + padding: var(--space-7) 0; +} + +.stat-item { + text-align: center; + padding: 0 var(--space-3); +} + +.stat-item + .stat-item { + border-left: 1rpx solid var(--divider); +} + +.metric { + color: var(--text-strong); + font-size: var(--fs-display); + font-weight: var(--fw-black); + line-height: 1.1; +} + +.metric-label { + margin-top: var(--space-2); + color: var(--text-muted); + font-size: var(--fs-meta); + line-height: 1.35; +} + +/* ============================================================ + 页面头标识 HeadMark + ============================================================ */ +.head-mark { + width: 78rpx; + height: 78rpx; + border-radius: var(--radius-md); + background: var(--text-strong); + color: #ffffff; + font-size: 34rpx; + font-weight: var(--fw-black); + line-height: 78rpx; + text-align: center; + flex-shrink: 0; +} + +/* ============================================================ + 表单字段 FormField + ============================================================ */ +.form-field { + width: 100%; + box-sizing: border-box; + border: 1rpx solid var(--border); + border-radius: var(--radius-md); + background: var(--field-bg); + color: var(--text-strong); + font-size: var(--fs-body); +} + +.form-field:focus, +.form-field:active { + border-color: var(--primary); + background: var(--surface); +} + +/* ============================================================ + 筛选胶囊 FilterChip + ============================================================ */ +.filter-chip { + display: inline-flex; + align-items: center; + justify-content: center; + height: 56rpx; + padding: 0 22rpx; + border: 1rpx solid var(--border); + border-radius: var(--radius-pill); + background: var(--surface); + color: var(--text-secondary); + font-size: var(--fs-label); + font-weight: var(--fw-bold); + white-space: nowrap; +} + +.filter-chip.active { + border-color: var(--primary); + background: var(--primary); + color: #ffffff; +} + +/* ============================================================ + 活动标记 ActivityMark + ============================================================ */ +.activity-mark { + display: flex; + align-items: center; + justify-content: center; + min-height: 62rpx; + padding: var(--space-3) var(--space-4); + border-radius: var(--radius-md); + background: var(--primary-surface); + color: var(--primary-text); + font-size: var(--fs-meta); + font-weight: var(--fw-bold); + line-height: 1.3; + text-align: center; +} + +.activity-mark.done { + background: var(--success-bg); + color: var(--done-text); +} + +.activity-mark.warn { + background: var(--warning-bg); + color: var(--warning-text); +} + +.activity-mark.danger { + background: var(--danger-bg); + color: var(--danger); +} + +/* ============================================================ + 分享/转发面板 RelayPanel + ============================================================ */ +.relay-panel { + position: relative; + padding: var(--space-7); + border: 1rpx solid var(--border); + border-radius: var(--radius-lg); + background: var(--surface); + overflow: hidden; +} + +/* tone 变体 — 极简风格用细边框区分 */ +.relay-panel.good { + border-color: var(--relay-border-good); +} + +.relay-panel.warn { + border-color: var(--relay-border-warn); +} + +.relay-panel.danger { + border-color: var(--relay-border-danger); +} + +.relay-panel.done { + border-color: var(--relay-border-done); +} + +/* kicker 胶囊 */ +.relay-kicker { + display: inline-flex; + align-items: center; + min-height: 38rpx; + padding: 0 14rpx; + border-radius: var(--radius-pill); + background: var(--primary-surface); + color: var(--primary-text); + font-size: var(--fs-meta); + font-weight: var(--fw-bold); + margin-bottom: var(--space-3); +} + +.relay-panel.warn .relay-kicker { + background: var(--warning-bg); + color: var(--warning-text); +} + +.relay-panel.danger .relay-kicker { + background: var(--danger-bg); + color: var(--danger); +} + +.relay-panel.done .relay-kicker { + background: var(--success-bg); + color: var(--done-text); +} + +/* 面板标题 */ +.relay-title { + color: var(--text-strong); + font-size: var(--fs-section); + font-weight: var(--fw-black); + line-height: 1.25; +} + +/* 面板正文 */ +.relay-body { + margin-top: var(--space-3); + color: var(--text-normal); + font-size: var(--fs-body); + line-height: 1.55; +} + +/* 标签-值行 */ +.relay-rows { + margin-top: var(--space-5); + display: flex; + flex-direction: column; + gap: var(--space-4); +} + +.relay-row { + display: grid; + grid-template-columns: 120rpx minmax(0, 1fr); + gap: var(--space-4); + align-items: start; +} + +.relay-row-label { + color: var(--text-muted); + font-size: var(--fs-meta); + font-weight: var(--fw-bold); + line-height: 1.4; +} + +.relay-row-value { + color: var(--text-strong); + font-size: var(--fs-body); + line-height: 1.5; +} + +/* 操作按钮区 */ +.relay-actions { + margin-top: var(--space-5); + display: flex; + gap: var(--space-4); +} + +.relay-actions .primary-button, +.relay-actions .secondary-button, +.relay-actions .share-button { + flex: 1; height: 76rpx; - border-radius: 14rpx; + font-size: var(--fs-body); +} + +/* 底部备注 */ +.relay-note { + margin-top: var(--space-4); + color: var(--text-muted); + font-size: var(--fs-meta); + line-height: 1.4; +} + +/* accent 分享按钮 */ +.share-button { + width: 100%; + height: 88rpx; + border-radius: var(--radius-md); + color: #ffffff; + background: var(--accent); font-size: 28rpx; - box-shadow: 0 12rpx 24rpx rgba(31, 102, 88, 0.2); + font-weight: var(--fw-bold); + box-shadow: var(--shadow-accent); + transition: opacity 160ms ease; +} + +.share-button:active { + opacity: 0.76; } diff --git a/custom-tab-bar/index.wxml b/custom-tab-bar/index.wxml index 613101c..45664d7 100644 --- a/custom-tab-bar/index.wxml +++ b/custom-tab-bar/index.wxml @@ -1,12 +1,14 @@ - - + - - {{item.text}} - - + + + + {{item.text}} + + diff --git a/custom-tab-bar/index.wxss b/custom-tab-bar/index.wxss index 2a3d75b..cadf216 100644 --- a/custom-tab-bar/index.wxss +++ b/custom-tab-bar/index.wxss @@ -1,3 +1,4 @@ +/* 地图在 tabBar 上方结束,这里使用普通视图以避免滚动时原生覆盖层残影。 */ .tab-shell { position: fixed; left: 0; @@ -9,13 +10,13 @@ justify-content: space-around; height: calc(116rpx + env(safe-area-inset-bottom)); padding-bottom: env(safe-area-inset-bottom); - border-top: 1rpx solid rgba(31, 63, 52, 0.1); - background: #fffefa; - box-shadow: 0 -12rpx 34rpx rgba(18, 31, 27, 0.12); + border-top: 1rpx solid #E5E7EB; + background: #FFFFFF; box-sizing: border-box; } .tab-item { + position: relative; flex: 1; display: flex; flex-direction: column; @@ -24,8 +25,16 @@ height: 116rpx; } -.tab-item.active { - background: #eef6f2; +/* 选中指示条 — 顶部 teal 色条,显示/隐藏由 WXML 的 wx:if 控制。 */ +.tab-indicator { + position: absolute; + top: 0; + left: 50%; + margin-left: -24rpx; + width: 48rpx; + height: 4rpx; + border-radius: 0 0 999rpx 999rpx; + background: #0F766E; } .tab-icon { @@ -35,18 +44,15 @@ margin: 0 auto 7rpx; } +/* 选中时图标上移;固定 margin 保持每个 tab 的布局尺寸稳定。 */ .tab-item.active .tab-icon { - transform: translateY(-2rpx); + margin-top: -4rpx; + margin-bottom: 11rpx; } .tab-text { - color: #697970; font-size: 22rpx; - font-weight: 800; + font-weight: 600; line-height: 1.1; text-align: center; } - -.tab-item.active .tab-text { - color: #1b5f52; -} diff --git a/harness/claude-progress.md b/harness/claude-progress.md index 54b60ed..49992dc 100644 --- a/harness/claude-progress.md +++ b/harness/claude-progress.md @@ -1350,3 +1350,57 @@ - 更新过的文件或工件:`.github/workflows/readiness.yml`,`.gitignore`,`package.json`,`package-lock.json`,`cloudfunctions/getMyRole/index.js`,`pages/me/me-state.js`,`pages/my-posts/my-posts.js`,`pages/activities/activities.js`,`harness/claude-progress.md`,忽略的本地 `.gstack/security-reports/2026-07-02T13-12-28Z-security.json` - 已知风险或未解决问题:没有执行真实 WeChat DevTools/真机 UI 和性能体感验收;readiness 仍报告 9420 service port blocked / connection refused。未读取全局 AI skills/hooks,因为这会超出仓库范围;也未做 CloudBase 线上数据库权限 readback - 下一步最佳动作:恢复 WeChat DevTools service port 后,做发布/地图/详情/管理/个人页真实 smoke;如果要进一步提升安全置信度,再做 CloudBase 线上集合权限 readback 和全局 agent skill/hook 扫描 + +### Session 098MainDirtyStyleFix + +- 日期:2026-07-09 +- 分支:`main` +- 工作区:`/Users/bytedance/git/x` +- 本轮目标:按用户澄清,review 并修复当前 `main` 工作区未提交样式改动引入的交互和样式回归 +- 根因:本地 dirty 样式刷新把地图原生 map 上方的 `cover-view` 浮层改成依赖 CSS 变量,而当前自定义 tabBar 注释和历史问题都表明 `cover-view` 样式支持更受限;个人页保留了空的 `profile-grid` 装饰节点,但对应绝对定位 CSS 已被删除,导致它会作为普通 grid 子项挤错头像/昵称/操作按钮;全局标题引入负字距,不适合小程序中文窄屏布局 +- 已完成:地图列表入口、定位/找一找工具、诊断面板和选中任务卡的关键 `cover-view` 样式改回硬编码值,并扩展 `scripts/check-map-list-resilience.mjs` 禁止这些原生覆盖层重新使用 `var(...)`;移除 `pages/me/me.wxml` 中残留的 `profile-grid`;把全局 `.title` 的 `letter-spacing` 改回 `0`;`scripts/check-devtools-readiness.mjs` 增加个人页残留节点和负字距回归检查;`DESIGN_SYSTEM.md` 记录普通 WXSS 用 token、原生覆盖层用硬编码值的例外 +- 运行过的验证:`bash harness/init.sh`;`node --check scripts/check-map-list-resilience.mjs`;`node --check scripts/check-devtools-readiness.mjs`;`node --no-warnings scripts/check-map-list-resilience.mjs`;`node --no-warnings scripts/check-devtools-readiness.mjs`;WeChat DevTools 本地 `wcc` 全量编译 WXML;WeChat DevTools 本地 `wcsc -lc` 全量编译 WXSS;`git diff --check`;`node scripts/check-json.mjs`;`node harness/check-harness.mjs`;最终再次 `bash harness/init.sh` +- 已记录证据:地图列表静态 guard 输出 `Map list resilience checks passed.`;readiness 输出 `DevTools readiness checks passed. Static gates passed; DevTools and real-device visual acceptance are still required.`;WCC/WCSC 均退出 0;`git diff --check` 无输出;JSON 检查输出 `Checked 11 JSON files.`;harness 输出 `Harness OK: 6 features checked.`;最终 `bash harness/init.sh` 输出 `Harness init complete.` +- 已知风险或未解决问题:当前环境没有 `npm`,所以 `npm run check` 无法直接执行;已分别执行其对应的 JSON、harness 和 readiness 子检查。DevTools service port 9420 仍为 blocked / connect_refused,因此本轮没有真实 WeChat DevTools/真机视觉和点击验收,不能写作 UI passed evidence。 +- 下一步最佳动作:在 WeChat DevTools service port 恢复后,重点手测地图页 `列表 N`、定位/找一找、marker 选中卡详情/关闭、打开抽屉,以及我的页头像/昵称/反馈或登录按钮是否仍在同一行布局内 + +### Session 099MainDirtyUiDevToolsFix + +- 日期:2026-07-10 +- 分支:`main` +- 工作区:`/Users/bytedance/git/x` +- 本轮目标:继续排查并修复当前 `main` 未提交 UI 刷新中的可复现样式和交互问题,并补真实 DevTools 页面级证据 +- 根因与修复:详情页仍保留空的 `hero-grid` 装饰节点,但本轮 dirty WXSS 已删除对应绝对定位规则;该节点因此成为 `.hero.stack` 的普通 flex 子项,额外插入 `20rpx` 间距。已删除该节点,并在 `scripts/check-devtools-readiness.mjs` 增加回归断言;保留上一轮地图 `cover-view` 硬编码、个人页 `profile-grid` 删除和标题零字距修复 +- DevTools 实测:使用 WeChat DevTools Stable `v2.01.2510290`、基础库 `3.15.2` 直接打开 `/Users/bytedance/git/x`;验证分享详情页、回首页后地图列表展开/收起、地图瓦片与选中任务卡、发布页滚动到底部、管理页异步数据加载、个人页布局;修复后重新从地图选中卡进入详情页,Hero 首屏间距恢复,未执行发布、评论、信任动作、隐藏或关闭等数据变更 +- 运行过的验证:`node --check scripts/check-devtools-readiness.mjs`;`node --no-warnings scripts/check-map-list-resilience.mjs`;`node --no-warnings scripts/check-devtools-readiness.mjs`;WeChat DevTools 本地 `wcc` 全量编译 WXML;WeChat DevTools 本地 `wcsc -lc` 全量编译 WXSS;`node scripts/check-json.mjs`;`node harness/check-harness.mjs`;`git diff --check`;`npm run check`;最终 `bash harness/init.sh` +- 已记录证据:地图 guard 输出 `Map list resilience checks passed.`;readiness 输出 `DevTools readiness checks passed. Static gates passed; DevTools and real-device visual acceptance are still required.`;WCC/WCSC 均退出 0;页面截图与 accessibility tree 均确认详情、地图、发布、管理、个人页有可见内容且主要布局不互相遮挡 +- 已知风险或未解决问题:DevTools 控制台仍显示既有 `WAServiceMainContext` `Error: timeout`,service port `9420` 仍为 disabled/connect_refused;页面可直接在 GUI 中操作,但 CLI smoke 仍 blocked。未执行真机、安全区多机型、系统分享菜单、定位授权正反分支或会改变数据的提交/处置流程,因此不标记完整 UI/功能通过 +- 下一步最佳动作:启用 DevTools Service Port 后补自动 smoke,并在真机覆盖定位授权、键盘、系统分享菜单和一条完整发布/评论/处置闭环 + +### Session 100MapViewportEdges + +- 日期:2026-07-10 +- 分支:`main` +- 工作区:`/Users/bytedance/git/x` +- 本轮目标:按用户截图修复首页顶部绿色空白和自定义 tabBar 底部边缘透出地图 +- 根因与修复:`.task-map` 原先是普通流中的 `height: 100vh`,没有显式贴住页面顶部且继续延伸到自定义 tabBar 后方;`.map-page` 同时使用绿色背景,导致原生地图合成边界出现时顶部显示绿色空区、底部设备圆角露出地图。现将 `.map-page` 固定为 `height: 100vh` 和白色兜底背景,将 `.task-map` 绝对定位到 `top: 0; left: 0`,高度改为 `calc(100vh - 116rpx - env(safe-area-inset-bottom))`,列表展开态仍保持 `38vh` +- TDD 证据:先扩展 `scripts/check-map-list-resilience.mjs` 要求固定白色地图视口和明确的地图上下边界;首次运行按预期失败,分别报告 `.map-page should provide a fixed white viewport` 与 `.task-map should start at the top and stop above the custom tabBar`;修改 WXSS 后同一检查通过 +- DevTools 实测:在 WeChat DevTools Stable `v2.01.2510290` 的 iPhone 12/13 模拟器中,修复前复现导航栏下方绿色空白;热更新后地图瓦片紧贴导航栏下沿,地图在 tabBar 顶部结束,底部圆角外只显示白色兜底;点击 `列表 6` 后抽屉正常展开,点击 `收起` 后恢复折叠态 +- 运行过的验证:`bash harness/init.sh`;`node --check scripts/check-map-list-resilience.mjs`;`node --no-warnings scripts/check-map-list-resilience.mjs`;`node --no-warnings harness/check-map-feed.mjs`;WeChat DevTools 本地 `wcc` 全量编译 WXML;WeChat DevTools 本地 `wcsc -lc` 全量编译 WXSS;`npm run check`;`node scripts/check-json.mjs`;`node harness/check-harness.mjs`;`git diff --check`;最终 `bash harness/init.sh` +- 已记录证据:地图 resilience 输出 `Map list resilience checks passed.`;map feed 输出 `Map feed checks passed.`;WCC/WCSC 退出 0;DevTools 修复后截图与 accessibility tree 均确认地图首屏、列表入口和展开抽屉有可见内容 +- 已知风险或未解决问题:DevTools 仍保留既有 `WAServiceMainContext Error: timeout`,Service Port `9420` 仍 disabled/connect_refused;本轮没有真机覆盖其他刘海/安全区尺寸,因此不标记整个地图功能 passing +- 下一步最佳动作:在至少一台真机和一台不同安全区模拟器确认地图顶部、tabBar 底部、列表抽屉和定位按钮边界一致 + +### Session 101PublishDuplicateTabBar + +- 日期:2026-07-10 +- 分支:`main` +- 工作区:`/Users/bytedance/git/x` +- 本轮目标:按用户截图修复发布页上滑后出现两套底部 tabBar +- 根因与修复:自定义 tabBar 整体使用固定 `cover-view/cover-image` 原生覆盖层;发布页滚动时该覆盖层会留下一个无文字的旧合成帧,形成上下两套图标。上一轮已经让原生地图在 tabBar 上方结束,因此 tabBar 不再需要覆盖地图;现将 `custom-tab-bar/index.wxml` 全部改为普通 `view/image`,保持原绑定、图标、文字和 active 指示条不变,并同步更新 WXSS 注释与设计系统约束 +- TDD 证据:先在 `scripts/check-devtools-readiness.mjs` 加入 tabBar 不得包含 `cover-view/cover-image`、必须保留单一普通视图 shell 的断言;首次运行按预期失败,错误为 `Custom tabBar should use normal view/image nodes; fixed cover nodes can leave duplicate native-layer frames while a page scrolls.`;结构替换后 readiness 通过 +- DevTools 实测:在 WeChat DevTools Stable `v2.01.2510290` 的 iPhone 12/13 模拟器中进入发布页,连续滚动和多次 `Page_Down` 后,active publish Webview 只包含一组 `地图/发布/管理/我的`,截图只显示一个底部 dock;切回地图页后地图瓦片和普通视图 tabBar 同时可见,没有被原生地图遮挡 +- 运行过的验证:`bash harness/init.sh`;`node --check scripts/check-devtools-readiness.mjs`;`node --no-warnings scripts/check-devtools-readiness.mjs`;WeChat DevTools 本地 `wcc` 全量编译 WXML;WeChat DevTools 本地 `wcsc -lc` 全量编译 WXSS;`npm run check`;`node scripts/check-json.mjs`;`node harness/check-harness.mjs`;`git diff --check`;最终 `bash harness/init.sh` +- 已记录证据:readiness 输出 `DevTools readiness checks passed. Static gates passed; DevTools and real-device visual acceptance are still required.`;WCC/WCSC 退出 0;发布页滚动截图和 accessibility tree 均确认单 tabBar;地图页截图确认普通 tabBar 仍可见 +- 已知风险或未解决问题:DevTools 仍有既有 `WAServiceMainContext Error: timeout`,Service Port `9420` 仍 disabled/connect_refused;未在真机做快速连续滑动和安全区复测,因此不标记发布功能整体 passing +- 下一步最佳动作:在真机连续快速上下滑发布页,并切换四个 tab,确认没有重复 dock、点击失效或安全区抖动 diff --git a/harness/feature_list.json b/harness/feature_list.json index 40072ea..d6e50be 100644 --- a/harness/feature_list.json +++ b/harness/feature_list.json @@ -1,6 +1,6 @@ { "project": "Street Tasks / 街区任务", - "last_updated": "2026-06-22", + "last_updated": "2026-07-10", "rules": { "single_active_feature": true, "passing_requires_evidence": true, @@ -171,7 +171,11 @@ "2026-06-22: Performance round 1 kept pages/map buildPosts on raw localOnly posts and built NearbyPreview from baseVisiblePosts to avoid duplicate decorateMapPost work; after a reviewer caught pre-decoration and raw selectedPost edge cases, corrected guards passed re-review.", "2026-06-22: Performance round 2 collapsed map viewport filtering, category counts, and open-post count into one posts.forEach pass; after fixing the discovery selectedPost decoration regression, reviewers Galileo, Kant, and Faraday voted PASS.", "2026-06-22: Performance round 3 added source-aware short-TTL posts caching for localOnly listPosts to avoid repeated wx storage reads while preventing local/cloud cache pollution; after multiple reviewer-caught source and cloud-mutator fixes, reviewers Hilbert, Peirce, and Godel voted PASS.", - "2026-06-22: Performance round 4 prefiltered hidden raw posts before derivePost/sort while forcing normal listPosts callers to includeHidden=false and preserving listAllPosts hidden visibility; after Banach caught includeHidden leakage, reviewers Pascal, Gibbs, and Popper voted PASS." + "2026-06-22: Performance round 4 prefiltered hidden raw posts before derivePost/sort while forcing normal listPosts callers to includeHidden=false and preserving listAllPosts hidden visibility; after Banach caught includeHidden leakage, reviewers Pascal, Gibbs, and Popper voted PASS.", + "2026-07-09: Reviewed the current local main dirty visual refresh and fixed map cover-view overlay regressions by keeping selected task card/list/tool/diagnostic cover-view styles hard-coded instead of CSS-variable based; scripts/check-map-list-resilience.mjs now guards this.", + "2026-07-10: WeChat DevTools Stable v2.01.2510290 direct UI smoke rendered map tiles, the collapsed list entry, locate/discover controls, selected-task cover-view card, expanded task drawer, and custom tabBar; the existing WAServiceMainContext timeout remained and no real-device claim was made.", + "2026-07-10: Fixed the screenshot-reported blank strip above the home map and map bleed around the tabBar bottom edge. The map viewport is now explicitly pinned to top:0 and ends above the 116rpx tabBar plus safe area, while the fixed map-page background stays white behind device corners; DevTools confirmed both collapsed and expanded list states.", + "2026-07-10: Replaced the custom tabBar cover-view/cover-image tree with normal view/image nodes after the map stopped above the dock. DevTools confirmed the map tiles and the single custom tabBar remain visible together." ], "notes": "已有实现未等于 harness passing;需要手动小程序验证证据。2026-05-18 UI 刷新采用 TDesign 式设计 token 和原生小程序控件落地,未引入 tdesign-miniprogram npm 依赖,避免在当前无小程序 npm 构建链路下增加编译风险。底部 tabBar 已由悬浮胶囊改为贴底不透明导航栏。2026-05-19 发布页和地图抽屉已落地 design-ui-designer 组件化优化。2026-05-21 白屏排查未发现 WXML/WXSS/JS 语法错误,已移除 tabBar 中新增的空 cover-view 指示条以降低渲染兼容风险;同日继续排查确认 DevTools hot reload/getAppConfig 缓存会触发 subPackages 内部错误,清编译缓存并终止重编译后地图恢复,同时加入页面诊断和云读取 fallback;随后针对 `Error: timeout` 将地图首屏改为本地优先,定位、云函数列表和地图 region 读取都不再阻塞启动;详情页已补上本地 fallback,避免本地列表任务因云端不存在而显示“任务不存在”。信息列表已改为铺满抽屉、标题后置标签、底部轻量统计。A 组地图迭代新增 NearbyPreview 首屏附近优先预览和选中态联动,并收敛长标题风险;2026-06-15 用户手测暴露普通 view/button 覆盖原生 map 不可靠,因此折叠态任务入口、定位和找一找都保持为 cover-view/cover-image;经过多轮用户截图反馈,最终布局按偏好收敛为右上角白色“列表 N”单行居中按钮、右下角定位/找一找工具行、选中任务卡上移避让工具行,打开列表时仍缩小 native map 到 38vh 让普通任务卡抽屉位于 map 下方。2026-06-14 已新增地图列表静态韧性检查并接入 readiness/preflight,且手测准备 helper 会显式运行并提示该 preflight;这只降低结构、样式和执行漏跑风险,不代表 DevTools 或真机视觉验收通过。S 组补充了地图列表真实视觉 smoke 的模板 journey 和检查清单,T 组把该 journey 变成 manual evidence 必备项,U 组提供 blocked local draft helper,V 组把 blocked draft 与 sanitized summary 生成串联,W 组为 blocked JSON/summary 状态一致性增加自动 guard,X 组进一步守住 summary 与 JSON 的 branch/commit/blocker/followUp 同源完整性,Y 组把增强 guard 接入 wrapper 默认生成链路,Z 组又把生成后手工编辑必须复跑 guard 的命令直接打印到 wrapper 成功输出,AA 组新增评审前一键 preflight 扫描 ignored local blocked summaries 并逐对复跑 guard,AB 组把该 preflight 接入 harness/init.sh 和 DevTools readiness 默认检查,AC 组把 JSON/harness/readiness 门禁暴露为 npm 级 `check` 脚本,AD 组新增最小 GitHub Actions workflow 在 push/pull_request 上运行该检查,AE 组补充 required-check runbook 和稳定 job display name 以便远端 Actions/分支保护后续验证,AF 组补充 `inspect:devtools-port` 与 `check:devtools-smoke` 手动入口,明确当前 9420 service-port blocker 可复查但不进入默认 CI/check,AG 组补充 `inspect:devtools-recovery` dry-run 入口,明确恢复动作前后的 before/actions/after/next-step 证据且不执行 quit/open 副作用,AH 组补充 ignored local recovery dry-run report 生成与 guard,降低交接草稿被改写成恢复成功或 UI passed 的风险,AI 组再补充手动 preflight 扫描所有 ignored local recovery reports 并逐份复跑 guard,降低多份本地草稿交接前漏检风险;这些仍只是在证据结构上预留、守护、演练阻塞记录并提升评审可读性。viral 侧 AD/AE/AF 又把七条旅程证据包、JSON/Markdown summary 同源和附件 manifest 同源/脱敏 guard 串起来,能让真实手测后的截图/录屏/payload/readback 附件更安全地被评审引用;但这些 guard 仍不产生真实系统分享、朋友圈、payload、CloudBase readback、窄屏或真机 passed evidence。真实 safe area、地图抽屉、原生地图层、列表滚动、带图/无图和详情点击仍需 WeChat DevTools 或真机观察。仍需在 WeChat DevTools/真机中确认 safe area、键盘、地图抽屉、定位授权分支和多分类详情链路。" }, @@ -216,7 +220,9 @@ "2026-06-23: Removed the custom expiry maximum after user feedback; the date picker no longer has an end date and publish-flow checks cover a 45-day custom expiry.", "2026-06-23: Updated publish expiry presets to 1w/1mo/long-term/custom; long-term posts carry expiryType=long_term and render as 长期有效 instead of a large day count.", "2026-06-23: Publish now defaults to the long-term expiry option while keeping the visible option order as 1周/1月/长期/自定义.", - "2026-06-23: Verification passed node --check for publish page/state, store, format helper, and posts cloud function; node --no-warnings scripts/check-publish-flow.mjs; node --no-warnings scripts/check-devtools-readiness.mjs; npm run check; bash harness/init.sh; git diff --check; and local WXML/WXSS compiler exits 0." + "2026-06-23: Verification passed node --check for publish page/state, store, format helper, and posts cloud function; node --no-warnings scripts/check-publish-flow.mjs; node --no-warnings scripts/check-devtools-readiness.mjs; npm run check; bash harness/init.sh; git diff --check; and local WXML/WXSS compiler exits 0.", + "2026-07-10: WeChat DevTools direct UI smoke scrolled the publish form through category, location, expiry, and custom-expiry controls; the fixed bottom action stayed above the custom tabBar without obscuring the final fields. No post was submitted.", + "2026-07-10: Fixed the screenshot-reported duplicate tabBar after scrolling by replacing the fixed native cover-view tab tree with normal view/image nodes. Repeated Page_Down actions left exactly one 地图/发布/管理/我的 set in the active publish Webview and one visible dock." ], "notes": "图片发布已改为云端必需;仍需部署更新后的 posts 云函数,并在 WeChat DevTools/真机中验证上传、跨用户浏览和过大图片拦截。 2026-06-12 B 组发布迭代新增发布准备度、位置确认和有效期按钮;尚未在 WeChat DevTools/真机验证定位授权、键盘遮挡、图片上传和真实发布闭环。 第二轮 B 组已收敛定位失败/重试路径和 readiness 文案;定位授权弹窗、键盘、图片上传和真实发布仍需 DevTools/真机验证。 第三轮 B 组已将发布主动作显式化为 primaryAction;仍需 DevTools/真机验证真实定位授权、键盘安全区、图片上传和跳转。 2026-06-16 发布后扩散计划只在 from=publish 详情上下文显示,普通详情页不展示;分享路径会移除 from=publish 避免接收者看到发布者专属卡。2026-06-23 有效期预设已改为 1周/1月/长期/自定义,默认选择长期;自定义时间只校验至少晚于当前 30 分钟,不限制最大日期。长期预设保存为 long_term 并显示 长期有效;功能影响是默认发布任务不会很快自动过期,因此评论/确认/列表展示会长期保持可用,关闭、过时、举报和自定义截止时间仍按原逻辑生效。仍需在 DevTools/真机中实际操作日期/时间 picker、提交本地/云端发布并检查详情页过期文案。DevTools CLI open/preview 当前被 9420 服务端口超时阻塞,需在 DevTools UI 中确认服务端口并手动重开项目。" }, @@ -346,7 +352,8 @@ "2026-06-17: scripts/check-viral-attribution.mjs is wired into scripts/check-viral-candidate.mjs and scripts/check-devtools-readiness.mjs; viral journey manual evidence now requires relay attribution params in inspectable receiver confirm/comment share payloads without claiming DevTools or real-device UI passed.", "2026-06-22: Multi-agent optimization round 2 added detail trust/resolve busy guards, button loading/disabled states, toastable error handling, and local duplicate trust-action rechecks around the async post lookup; scripts/check-detail-action-guards.mjs is wired into readiness and round 2 reviewers voted PASS.", "2026-06-22: Multi-agent optimization round 3 moved local resolve permission enforcement into utils/store.js, allowing only owner/admin resolution and ignoring stale presentation isMine fields; scripts/check-store-permission-guards.mjs covers non-owner rejection, owner success, and admin success, and round 3 received at least two PASS votes.", - "2026-06-22: Multi-agent optimization round 5 moved CloudBase listComments ordering before MAX_COMMENTS_PER_POST limit with orderBy('createdAt', 'desc'), added scripts/check-cloud-comment-order.mjs, wired it into readiness, and received PASS votes from mini program, JS, and architecture reviewers." + "2026-06-22: Multi-agent optimization round 5 moved CloudBase listComments ordering before MAX_COMMENTS_PER_POST limit with orderBy('createdAt', 'desc'), added scripts/check-cloud-comment-order.mjs, wired it into readiness, and received PASS votes from mini program, JS, and architecture reviewers.", + "2026-07-10: Removed the stale empty hero-grid child after the current dirty style refresh deleted its absolute-position CSS; this child had become a normal stack item and added an unintended 20rpx gap. DevTools then rendered the detail hero with normal top spacing, and readiness now rejects reintroducing the stale node." ], "notes": "评论与信任动作都涉及本地 storage 和 CloudBase 两条路径;当前代码实现已推进,仍需要 WeChat DevTools 手动验证后才能标记 passing。2026-05-21 详情头部已补充发布者头像/名称与右侧地址时间同排展示。当前会话转向发布图片云存储修复,避免同时存在多个 in_progress 功能。 2026-06-12 C 组详情迭代新增 TrustInsight 信任判断面板和评论头部入口;尚未在 WeChat DevTools/真机验证窄屏布局、信任动作刷新、游客登录评论引导和云端评论路径。 第二轮 C 组已收敛 TrustInsight 谨慎文案和冲突优先级自动检查;2026-06-16 组合候选同时保留发布成功扩散计划和普通详情分享提示,并新增接收侧转化提示,但仍未执行 DevTools/真机视觉、分享面板、接收路径、窄屏密度、信任动作刷新和云端评论验证。 2026-06-16 评论成功后接力提示已加入组合候选:只在评论提交成功后显示,active 低风险任务可接力转发,stale/高举报/resolved/expired/hidden 不鼓励公开扩散。传播闭环候选进一步让普通分享面板在发布成功、分享接收和评论接力状态下隐藏,降低同屏传播 CTA 竞争;确认成功后接力提示进一步覆盖 confirm 高意图时刻,且 stale/report/高风险状态不鼓励公开扩散。接收者转化迭代进一步覆盖 from=share 用户完成 confirm/comment 后的二跳接力,并用 source=receiver 让下一位接收者理解链路来源;普通详情入口、stale/report/高风险和关闭态不鼓励公开扩散。本轮接收者第一步行动入口进一步让 from=share active 且无过时/举报信号的低风险用户能直接确认或补线索,并在完成 confirm/comment 后继续优先出现 receiverConversionPrompt;普通入口、有过时/举报信号、hidden/resolved/expired 不显示鼓励性 action strip。N 组新增传播链路证据框架,把首跳 from=share、接收者行动、转化提示、二跳 source=receiver 和风险态互斥固化为自动场景模型,并提供 not_run 手测模板;这仍不代表 WeChat DevTools/真机通过。仍未执行 WeChat DevTools/真机验证五种入口视觉层级、action strip 点击、open-type share、风险态按钮、窄屏换行和真实云端评论路径。 O 组进一步把 N 组 not_run 模板升级为真实本地手测结果 gate:默认只扫描 ignored/local viral journey 结果文件,无文件时通过但明确不代表 UI passed;真实文件存在时必须匹配当前分支/commit、完整环境和唯一 required journeys,并按 passed/failed/blocked 规则校验 evidence、actual、blocker、followUp、share payload 或无法检查说明以及 overallStatus 聚合。prepare helper 只生成 ignored blocked draft 或 dry-run 输出,不声称 passed。P 组新增 no-side-effect 手测启动包,把 DevTools port/smoke blocker、evidence dry-run/check 和五条 journey 下一步收敛到单一命令;当前 9420 仍是环境 blocker,不是 UI failed 或 UI passed。Q 组新增显式 blocked evidence capture 命令,把当前 port/smoke blocker 写入 ignored local JSON 并自动跑 O checker;capture 文件仍是 blocked evidence,不是 UI passed,且默认 readiness 不执行写文件 capture。R 组把接收者完成确认/评论后的二跳提示从泛化“继续接力”升级为目标化三行信息,明确推荐转给谁、为什么可信和下一位先看什么;分类文案已对齐当前 lost_found/help_needed/street_update/check_in 枚举,风险和关闭态仍不显示鼓励性 target rows。S 组进一步在低风险二跳 path 上加入 receiverAction=confirm/comment,并让下一位接收者区分上一位刚确认或刚补线索;缺失/未知 action、非 receiver source 和风险/关闭态继续安全回退。仍未执行 WeChat DevTools/真机真实链路验证。T 组在低风险 from=share 接收者完成 confirm/comment 后新增一条可转述短理由,放在目标化三行信息与继续接力按钮之间,confirm/comment 文案不同且不新增分享 query;风险、关闭和弱 stale/report 仍不显示鼓励性理由。仍未执行 WeChat DevTools/真机真实链路验证。U 组进一步在低风险 from=share 接收者完成 confirm/comment 后增加 2-3 个“适合转给”的泛化场景建议,补足 T 组 shareReason 只解决“怎么说”的短板;它不读取联系人/微信群、不新增 targeting query,风险、关闭和弱 stale/report 仍不显示鼓励性场景建议。V 组新增微信原生分享到朋友圈渠道:只在低风险 active 详情页菜单中暴露 shareTimeline,timeline query 复用 from=share 并用 source=timeline/shareChannel=timeline 区分渠道;风险、关闭、弱 stale/report 和未知任务不开放朋友圈菜单且 payload 文案谨慎。W 组把真实朋友圈渠道纳入 manual evidence schema,新增 timeline-share-channel 与 timeline-risk-gating 两条 required journey,run package 和 blocked capture 都改为七条;这仍只是证据结构与阻塞记录能力,尚未产生真实 DevTools/真机 timeline passed evidence。X 组进一步让 source=timeline 落地页不再只是普通转发语境:低风险 active 朋友圈访客会看到“朋友圈看到”的附近任务核对说明,先看状态/评论,再确认或补线索;弱 stale/report、风险和关闭态仍优先谨慎。" }, @@ -379,7 +386,8 @@ "2026-06-15: After user-reported getMyRole failure, added formatAdminRoleError so wx-server-sdk missing dependency and undeployed cloud function failures show short actionable admin-check messages instead of raw cloud.callFunction stack traces.", "2026-06-15: Added scripts/check-admin-auth-errors.mjs and wired it into scripts/check-devtools-readiness.mjs so npm run check guards admin auth error formatting.", "2026-06-22: Multi-agent optimization round 1 hardened refreshAdminRole so missing cloud runtime, getMyRole errors, missing admins collection, malformed responses, and non-admin responses preserve guest state while clearing stale admin role; only ok === true and role === 'admin' upgrades to admin. scripts/check-admin-auth-errors.mjs now covers these cases and round 1 reviewers voted PASS.", - "2026-06-22: Performance round 5 replaced repeated admin review filter/stat full-list scans with one-pass buildAdminSummary, kept filter/stat semantics, strengthened scripts/check-admin-review.mjs after Raman caught weak guard coverage, wired the guard into readiness, and re-reviewers Aristotle, Curie, and Bohr voted PASS." + "2026-06-22: Performance round 5 replaced repeated admin review filter/stat full-list scans with one-pass buildAdminSummary, kept filter/stat semantics, strengthened scripts/check-admin-review.mjs after Raman caught weak guard coverage, wired the guard into readiness, and re-reviewers Aristotle, Curie, and Bohr voted PASS.", + "2026-07-10: WeChat DevTools direct UI smoke rendered the administrator summary, feedback section, filters, and task queue after asynchronous data load. No hide, resolve, or other destructive action was executed." ], "notes": "管理员身份依赖 getMyRole 云函数和本地 fallback。本实验分支已补充风险解释、建议动作、处置中防重复点击和确认弹窗信息;2026-06-15 已把云函数缺少 wx-server-sdk 或未部署的错误收敛为短提示和处理步骤。但真实管理员通过仍需要在 CloudBase 中重新上传部署 getMyRole 云函数并创建 admins 记录,且尚未在 WeChat DevTools 中以普通用户/管理员身份手动验证,因此不标记 passing。" }, @@ -408,7 +416,9 @@ "2026-06-13 profile iteration branch: git diff --check passed with no output.", "2026-06-13 profile iteration branch: WeChat DevTools local wcc compiled all WXML files with exit code 0.", "2026-06-13 profile iteration branch: WeChat DevTools local wcsc -lc compiled all WXSS files with exit code 0.", - "2026-06-13 profile iteration branch: bash harness/init.sh passed; npm install reported up to date, then JSON and harness checks passed." + "2026-06-13 profile iteration branch: bash harness/init.sh passed; npm install reported up to date, then JSON and harness checks passed.", + "2026-07-09: Removed the stale profile-grid decorative node from pages/me/me.wxml after the current local main dirty style refresh deleted its absolute-position CSS; scripts/check-devtools-readiness.mjs now rejects reintroducing it as a normal profile grid child.", + "2026-07-10: WeChat DevTools direct UI smoke rendered the profile header, administrator state, stats, next action, and profile links without the former profile-grid displacement. Login/profile mutation and feedback submission were not exercised." ], "notes": "这组页面是辅助面,优先级低于核心地图/发布/详情闭环。本实验分支已补充个人中心下一步建议和最近动态摘要,但尚未在 WeChat DevTools 中验证登录、补资料、跳转、长文案和窄屏表现,因此不标记 passing。" } diff --git a/pages/activities/activities.wxss b/pages/activities/activities.wxss index 7f8fa38..10afa9f 100644 --- a/pages/activities/activities.wxss +++ b/pages/activities/activities.wxss @@ -1,3 +1,6 @@ +/* ============================================================ + 参与记录 Activities Page + ============================================================ */ .list-page { padding-bottom: calc(40rpx + env(safe-area-inset-bottom)); } @@ -7,48 +10,20 @@ padding: 22rpx 0 12rpx; } -.stat-panel { +/* ---- 统计面板 — 3 列覆盖全局 ---- */ +.list-page .stat-panel { display: grid; grid-template-columns: repeat(3, 1fr); - padding: 28rpx 0; - background: #fffefa; - text-align: center; -} - -.metric { - color: #1b5f52; - font-size: 44rpx; - font-weight: 900; - line-height: 1.08; -} - -.stat-item + .stat-item { - border-left: 1rpx solid rgba(26, 46, 41, 0.1); -} - -.empty-panel { - padding: 30rpx; -} - -.empty-title { - margin-bottom: 8rpx; - color: #14211d; - font-size: 30rpx; - font-weight: 900; - line-height: 1.25; -} - -.empty-action { - margin-top: 24rpx; + padding: var(--space-7) 0; } +/* ---- 活动卡片 ---- */ .activity-card { display: grid; grid-template-columns: 144rpx 1fr; gap: 18rpx; align-items: center; - padding: 24rpx; - background: #fffefa; + padding: var(--space-6); } .activity-card:active { @@ -59,40 +34,18 @@ min-width: 0; } -.compact-title { - margin-bottom: 8rpx; - color: #14211d; - font-size: 30rpx; - font-weight: 900; - line-height: 1.28; -} - -.activity-mark { - display: flex; - align-items: center; - justify-content: center; +/* ---- 活动标记 — 覆盖全局尺寸 ---- */ +.activity-card .activity-mark { min-height: 62rpx; padding: 0 14rpx; - border-radius: 14rpx; - background: #f0eee7; - color: #697970; - font-size: 24rpx; - font-weight: 900; - text-align: center; - box-sizing: border-box; -} - -.activity-mark.done { - background: #e4f0e9; - color: #28584e; -} - -.activity-mark.warn { - background: #fff2da; - color: #915709; + font-size: var(--fs-label); + font-weight: var(--fw-bold); } -.activity-mark.danger { - background: #ffe9e2; - color: #a73527; +.compact-title { + margin-bottom: var(--space-2); + color: var(--text-strong); + font-size: 30rpx; + font-weight: var(--fw-black); + line-height: 1.28; } diff --git a/pages/admin/admin.wxss b/pages/admin/admin.wxss index d1edf08..c8907a0 100644 --- a/pages/admin/admin.wxss +++ b/pages/admin/admin.wxss @@ -1,7 +1,11 @@ +/* ============================================================ + 管理页 Admin Page (Modern Minimal) + ============================================================ */ .admin-page { padding-bottom: calc(146rpx + env(safe-area-inset-bottom)); } +/* ---- 页面头 ---- */ .admin-head { position: relative; padding: 16rpx 0 2rpx; @@ -9,48 +13,49 @@ .head-rule { width: 106rpx; - height: 8rpx; + height: 6rpx; margin-bottom: 18rpx; - border-radius: 999rpx; - background: linear-gradient(90deg, #d7673f, #1f6658); + border-radius: var(--radius-pill); + background: var(--primary); } +/* ---- 统计卡片 ---- */ .summary-grid { display: grid; grid-template-columns: repeat(4, 1fr); - gap: 14rpx; + gap: var(--space-3); } .summary-card { - padding: 24rpx 10rpx; - background: #fffefa; + padding: var(--space-6) 10rpx; + background: var(--surface); text-align: center; } .summary-card.urgent { - border-color: rgba(215, 103, 63, 0.2); - background: linear-gradient(135deg, #fff6ef, #fffefa); + background: var(--surface); } .metric { - color: #1b5f52; + color: var(--text-strong); font-size: 46rpx; - font-weight: 900; + font-weight: var(--fw-black); line-height: 1.05; } .urgent .metric { - color: #b94f34; + color: var(--accent); } +/* ---- 反馈区 ---- */ .feedback-section { display: flex; flex-direction: column; - gap: 16rpx; + gap: var(--space-4); } .section-head { - gap: 20rpx; + gap: var(--space-5); } .section-head > view { @@ -58,8 +63,8 @@ } .feedback-admin-card { - padding: 24rpx; - background: #fffefa; + padding: var(--space-6); + background: var(--surface); } .feedback-card-head { @@ -68,30 +73,31 @@ } .feedback-body { - margin-top: 16rpx; - color: #2e423a; - font-size: 28rpx; + margin-top: var(--space-4); + color: var(--text-normal); + font-size: var(--fs-body); line-height: 1.52; } .feedback-meta { - margin-top: 14rpx; - padding-top: 14rpx; - border-top: 1rpx solid rgba(26, 46, 41, 0.08); - color: #697970; - font-size: 24rpx; + margin-top: var(--space-3); + padding-top: var(--space-3); + border-top: 1rpx solid var(--divider); + color: var(--text-muted); + font-size: var(--fs-label); line-height: 1.4; } +/* ---- 搜索面板 ---- */ .search-panel { - padding: 20rpx; - background: #fffefa; + padding: var(--space-5); + background: var(--surface); } .search-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; - gap: 14rpx; + gap: var(--space-3); align-items: center; } @@ -99,10 +105,10 @@ min-width: 0; height: 74rpx; padding: 0 22rpx; - border: 1rpx solid rgba(26, 46, 41, 0.12); - border-radius: 14rpx; - background: #fbfaf4; - color: #14211d; + border: 1rpx solid var(--border); + border-radius: var(--radius-md); + background: var(--field-bg); + color: var(--text-strong); font-size: 26rpx; box-sizing: border-box; } @@ -111,53 +117,45 @@ max-width: 112rpx; height: 74rpx; padding: 0 22rpx; - border-radius: 14rpx; - background: #f0eee7; - color: #697970; - font-size: 24rpx; - font-weight: 900; + border-radius: var(--radius-md); + background: var(--surface-neutral); + color: var(--text-muted); + font-size: var(--fs-label); + font-weight: var(--fw-bold); } +/* ---- 筛选栏 — 覆盖全局 filter-chip 尺寸 ---- */ .admin-filter-bar { margin-top: 18rpx; display: flex; flex-wrap: wrap; - gap: 10rpx; + gap: var(--space-2); } -.filter-chip { - display: inline-flex; +.admin-filter-bar .filter-chip { flex: 1 1 146rpx; min-width: 0; height: 52rpx; padding: 0 10rpx; - border: 1rpx solid rgba(31, 102, 88, 0.18); - border-radius: 999rpx; - background: rgba(255, 254, 250, 0.82); - color: #3e5149; - font-size: 22rpx; - font-weight: 800; + font-size: var(--fs-meta); + font-weight: var(--fw-bold); line-height: 52rpx; } -.filter-chip.active { - border-color: rgba(31, 102, 88, 0.32); - background: #1f6658; - color: #ffffff; -} - +/* ---- 队列头 ---- */ .queue-head { - gap: 20rpx; - margin-top: 8rpx; + gap: var(--space-5); + margin-top: var(--space-2); } .queue-head > view { min-width: 0; } +/* ---- 管理卡片 ---- */ .admin-card { - padding: 20rpx; - background: #fffefa; + padding: var(--space-5); + background: var(--surface); } .card-head { @@ -167,87 +165,93 @@ .admin-tags { flex-wrap: wrap; - gap: 10rpx; + gap: var(--space-2); min-width: 0; } .post-id { flex-shrink: 0; - color: #8a9891; - font-size: 22rpx; - font-weight: 800; + color: var(--text-muted); + font-size: var(--fs-meta); + font-weight: var(--fw-bold); line-height: 44rpx; } .admin-title { - margin-top: 14rpx; - margin-bottom: 6rpx; + margin-top: var(--space-3); + margin-bottom: var(--space-1); + color: var(--text-strong); font-size: 29rpx; + font-weight: var(--fw-bold); line-height: 1.22; } .admin-body { - color: #2e423a; - font-size: 24rpx; - line-height: 1.36; - max-height: 66rpx; + color: var(--text-normal); + font-size: var(--fs-label); + line-height: 1.5; + display: -webkit-box; overflow: hidden; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; } +/* ---- 审查面板 ---- */ .review-panel { display: flex; flex-direction: column; - gap: 8rpx; - margin-top: 14rpx; - padding: 14rpx 16rpx; - border-radius: 14rpx; - background: #fbfaf4; + gap: var(--space-2); + margin-top: var(--space-3); + padding: var(--space-3) var(--space-4); + border-radius: var(--radius-md); + background: var(--field-bg); } .review-line { display: grid; grid-template-columns: 112rpx minmax(0, 1fr); - gap: 12rpx; + gap: var(--space-3); align-items: start; } .review-label { - color: #84908b; + color: var(--text-muted); font-size: 21rpx; - font-weight: 900; + font-weight: var(--fw-bold); line-height: 1.4; } .review-text { - color: #2e423a; + color: var(--text-normal); font-size: 23rpx; line-height: 1.4; } .review-text.strong { - color: #1b5f52; - font-weight: 900; + color: var(--text-strong); + font-weight: var(--fw-bold); } +/* ---- 元信息网格 ---- */ .meta-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 10rpx 14rpx; - margin-top: 16rpx; - padding: 14rpx 0; - border-top: 1rpx solid rgba(26, 46, 41, 0.08); - border-bottom: 1rpx solid rgba(26, 46, 41, 0.08); + gap: var(--space-2) var(--space-3); + margin-top: var(--space-4); + padding: var(--space-3) 0; + border-top: 1rpx solid var(--divider); + border-bottom: 1rpx solid var(--divider); } .meta-label { margin-bottom: 3rpx; - color: #84908b; + color: var(--text-muted); font-size: 20rpx; - font-weight: 900; + font-weight: var(--fw-bold); } .meta-value { - color: #2e423a; + color: var(--text-normal); font-size: 23rpx; line-height: 1.28; overflow: hidden; @@ -255,47 +259,49 @@ white-space: nowrap; } +/* ---- 信号网格 ---- */ .signal-grid { display: grid; grid-template-columns: repeat(3, 1fr); - gap: 10rpx; - margin-top: 14rpx; + gap: var(--space-2); + margin-top: var(--space-3); } .signal-item { - padding: 12rpx 8rpx; - border-radius: 14rpx; - background: #eaf4ef; + padding: var(--space-3) var(--space-2); + border-radius: var(--radius-md); + background: var(--primary-surface); text-align: center; } .signal-item.warn { - background: #fff2da; + background: var(--warning-bg); } .signal-item.danger { - background: #ffe9e2; + background: var(--danger-bg); } .signal-number { - color: #1b5f52; + color: var(--primary-text); font-size: 30rpx; - font-weight: 900; + font-weight: var(--fw-black); line-height: 1.1; } .signal-item.warn .signal-number { - color: #915709; + color: var(--warning-text); } .signal-item.danger .signal-number { - color: #a73527; + color: var(--danger); } +/* ---- 操作按钮 ---- */ .admin-actions { display: flex; - gap: 10rpx; - margin-top: 16rpx; + gap: var(--space-2); + margin-top: var(--space-4); } .admin-actions button { @@ -303,42 +309,36 @@ min-width: 0; max-width: none; height: 58rpx; - padding: 0 8rpx; - border-radius: 14rpx; - font-size: 22rpx; + padding: 0 var(--space-2); + border-radius: var(--radius-md); + font-size: var(--fs-meta); + font-weight: var(--fw-bold); line-height: 58rpx; white-space: nowrap; } .resolve-button { - border: 1rpx solid rgba(31, 102, 88, 0.18); - background: #eaf4ef; - color: #1b5f52; - font-weight: 800; + border: 1rpx solid var(--border); + background: var(--primary-surface); + color: var(--primary-text); } .hide-button { - border: 1rpx solid rgba(167, 53, 39, 0.14); - background: #ffe9e2; - color: #a73527; - font-weight: 800; + border: 1rpx solid var(--border); + background: var(--danger-bg); + color: var(--danger); } -.admin-actions button[disabled], +/* busy/disabled 覆盖 — 与全局 button[disabled] 一致 */ .admin-actions button.busy { - border-color: rgba(26, 46, 41, 0.08); - background: #f0eee7; - color: #8a9891; + border-color: transparent; } -.empty-panel { +/* ---- 空状态 ---- */ +.admin-page .empty-panel { padding: 34rpx; } -.empty-title { - margin-bottom: 10rpx; - color: #14211d; - font-size: 30rpx; - font-weight: 900; - line-height: 1.25; +.admin-page .empty-title { + margin-bottom: var(--space-2); } diff --git a/pages/detail/detail.wxml b/pages/detail/detail.wxml index 030fc92..eae28f6 100644 --- a/pages/detail/detail.wxml +++ b/pages/detail/detail.wxml @@ -6,7 +6,6 @@ - 附近任务 @@ -45,7 +44,7 @@ -