fix(plan): 4 条阻塞 + 2 条 advisory 修复(re-review 反馈)

阻塞修复:
1. Task 7: chartData/chartOpts 加入 return,H5 模板可访问
2. Task 13: 补 onUnmounted import
3. Task 13: 删除 4 个重复的 onShow 草稿块,保留唯一规范版本
4. Task 2: 新增 USE_MOCK_API 翻 true 的步骤(api.js 默认 false)

advisory 修复:
- Task 10: margin: 24r 0 → 24rpx 0
- Task 13: 删 enablePullDownRefresh(与 scroll-view refresher 冲突)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
zheng020 2026-06-02 20:16:59 +08:00
parent 72c91c1787
commit 8f84b2ad58

View File

@ -326,7 +326,21 @@ export const dashboardApi = {
}
```
- [ ] **Step 3: 手动验证 mock 触发**
- [ ] **Step 3: 打开 `USE_MOCK_API` 开关(关键前置步骤)**
> **重要**:项目 `frontend/utils/api.js` 第 9 行 `USE_MOCK_API` 默认是 `false`,会直接请求真实后端。后端尚未实现,必须先翻成 `true` 才能用 mock 验证。
修改 `frontend/utils/api.js`
```javascript
// 第 9 行:
// 原始: const USE_MOCK_API = false
// 改为:
const USE_MOCK_API = true
```
> **切回真实接口**:后端 `/api/v1/dashboard/*` 7 个接口联调通过后,把这里改回 `false` 即可。
- [ ] **Step 4: 手动验证 mock 触发**
在 H5 dev console 跑:
```js
@ -335,11 +349,11 @@ const today = await dashboardApi.getTodayOverview(1)
console.log(today) // 预期: { crystal_balance: 2713, today_income: 213, week_rank: 12 }
```
- [ ] **Step 4: Commit**
- [ ] **Step 5: Commit**
```bash
git add frontend/utils/mock/dashboard.js frontend/utils/api.js
git commit -m "feat(dashboard): 追加 mock 数据工厂 + dashboardApi 命名空间"
git commit -m "feat(dashboard): 追加 mock 数据工厂 + dashboardApi 命名空间 + 打开 USE_MOCK_API"
```
---
@ -1164,9 +1178,7 @@ git commit -m "feat(dashboard): CrystalOverview 双卡(水晶余额+今日收
</template>
<script>
// #ifdef H5
import { ref, computed } from 'vue'
// #endif
import { computed } from 'vue'
export default {
name: 'IncomeCurve',
@ -1181,8 +1193,11 @@ export default {
// 高亮当日peak
const peak = computed(() => props.points.find((p) => p.is_peak) || null)
// 平台条件:仅 H5 编译图表所需变量
let chartData = null
let chartOpts = null
// #ifdef H5
const chartData = computed(() => {
chartData = computed(() => {
const categories = props.points.map((p) => p.date.slice(5)) // MM.DD
const barData = props.points.map((p) => p.income)
const lineData = props.points.map((p) => p.income)
@ -1195,7 +1210,7 @@ export default {
}
})
const chartOpts = {
chartOpts = {
color: ['#FFCC14', '#1BAFEE'],
padding: [16, 16, 8, 16],
dataLabel: false,
@ -1214,7 +1229,7 @@ export default {
console.log('[IncomeCurve] chart tap', e)
}
return { peak, handleChartTap }
return { peak, handleChartTap, chartData, chartOpts }
},
}
</script>
@ -2045,7 +2060,7 @@ export default {
backdrop-filter: blur(10px);
border-radius: 22rpx;
padding: 24rpx;
margin: 24r 0;
margin: 24rpx 0;
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.15);
}
@ -2631,26 +2646,16 @@ git commit -m "feat(dashboard): UpcomingUpgrades + RecentUpgrades 双列布局"
---
## Task 13: onShow 刷新 + Tab 缓存 + 下拉刷新
**Files:**
- Modify: `frontend/pages/dashboard/dashboard.vue`
- Modify: `frontend/pages.json`(启用下拉刷新)
- Modify: `frontend/pages/dashboard/dashboard.vue`(整文件重写为完整版)
- Modify: `frontend/pages.json`**不**启用 `enablePullDownRefresh`下拉刷新由 scroll-view 的 `:refresher-enabled` 接管,避免双触发冲突
- [ ] **Step 1: `uni.scss` 中追加 page-bg CSS 类**
- [ ] **Step 1: 整文件替换 `frontend/pages/dashboard/dashboard.vue`**
`uni.scss` 末尾 dashboard token 段后追加:
```scss
/* dashboard 页面背景CSS 类,组件用 class 引用,避免 inline 重复) */
.dashboard-page-bg {
background: linear-gradient(153deg, #FF9597 0%, #80DFFF 33%, #B8B8B8 74%, #D9D9D9 100%);
min-height: 100vh;
}
```
- [ ] **Step 2: 重写 `frontend/pages/dashboard/dashboard.vue`(含 onShow + scroll-view + class 引用)**
完整文件内容:
**直接用以下完整内容覆盖整个文件**(删除 Task 4 写入的占位版本、Task 6/8/9/10/12 追加挂载的中间版本):
```vue
<template>
@ -2714,7 +2719,7 @@ git commit -m "feat(dashboard): UpcomingUpgrades + RecentUpgrades 双列布局"
</template>
<script>
import { ref } from 'vue'
import { ref, onUnmounted } from 'vue'
import DashboardHeader from './components/DashboardHeader.vue'
import CrystalOverview from './components/CrystalOverview.vue'
import IncomeCurve from './components/IncomeCurve.vue'
@ -2748,83 +2753,33 @@ export default {
uni.stopPullDownRefresh()
}
// onShow用户从其他页面返回时强制刷新一次spec §4.1
onShow lifecycle hookuni-app 页面级,需在 export default 上声明setup 内通过 getCurrentInstance 获取):
```js
// 在 export default 中追加:
onShow() {
this.$options._setupRef?.refresh?.(null, true)
}
```
// 实际写法(替换上面注释块):在 setup 末尾 return 前暴露 refresh 引用
const setupRef = { refresh }
onShow lifecycle见下方 onShow 实现
},
}
</script>
```
**关于 onShow 的关键说明**uni-app 的 `onShow` 是 Options API 生命周期钩子,**必须在 `export default` 顶层声明**(不在 `setup` 内)。完整 onShow 实现:
`<script>` 块内的 `export default` 顶层(与 `components`、`setup` 同级)追加:
```javascript
export default {
components: { ... },
setup() { ... return { refresh, ... } },
onShow() {
// 页面 onShow 时强制刷新(绕 30 分钟缓存spec §4.1
this.refresh(null, true)
},
}
```
注意:`onShow` 内的 `this.refresh` 来自 `setup()``return` 暴露vue 会自动合并 setup return 到实例。
> **重要**:上面模板中 `onShow` 注释块仅作说明,**实际写入文件时按下方"onShow 完整写法"**(替换 `setup` 末段):
`setup()` 末段return 之前)追加:
```javascript
// 将 refresh 暴露给 onShow 生命周期
const _refresh = refresh
// 在 return 中暴露
return {
activeTab, loading, error, data, isReady, lastFetched,
handleTabChange, handlePullDownRefresh,
refresh: _refresh, // 给 onShow 用
}
```
> 最终 onShow 写法(重写整个 export default
```javascript
export default {
components: { DashboardHeader, CrystalOverview, IncomeCurve, ExhibitionCenter, LikeIncomeBoard, CollectionMatrix },
setup() {
const activeTab = ref('crystal')
const starId = ref(uni.getStorageSync('star_id') || null)
const { loading, error, data, refresh, isReady, lastFetched, dispose } = useDashboardData({ starId: starId.value })
function handleTabChange(tab) {
activeTab.value = tab
if (tab === 'crystal') refresh()
}
async function handlePullDownRefresh() {
await refresh(null, true)
uni.stopPullDownRefresh()
}
onUnmounted(() => dispose())
return { activeTab, loading, error, data, isReady, lastFetched, handleTabChange, handlePullDownRefresh, refresh }
return {
activeTab,
loading,
error,
data,
isReady,
lastFetched,
handleTabChange,
handlePullDownRefresh,
refresh,
}
},
// uni-app 页面级生命周期(必须在 export default 顶层,不能放 setup 内)
onShow() {
// 从其他页面返回时强制刷新spec §4.1
// 从其他页面返回时强制刷新(绕 30 分钟缓存spec §4.1
if (this.refresh) this.refresh(null, true)
},
}
```
</script>
- [ ] **Step 3: 在 `<style>` 末尾追加 scroll-view 样式**
在 dashboard.vue 的 `<style lang="scss" scoped>` 块末尾追加:
```scss
<style lang="scss" scoped>
.dashboard-page-bg {
background: linear-gradient(153deg, #FF9597 0%, #80DFFF 33%, #B8B8B8 74%, #D9D9D9 100%);
min-height: 100vh;
}
.dashboard-scroll {
height: 100vh;
}
@ -2846,27 +2801,14 @@ export default {
.placeholder-icon { font-size: 96rpx; margin-bottom: 24rpx; }
.placeholder-title { color: #ffffff; font-size: 36rpx; font-weight: 700; margin-bottom: 16rpx; }
.placeholder-sub { color: rgba(255, 255, 255, 0.7); font-size: 26rpx; }
</style>
```
> **删掉** `dashboard.vue` 现有的 `.dashboard-container`、`.dashboard-content`、`.placeholder-*`、`.season-placeholder` 旧样式(被 `<style>` 末尾的覆盖即可,但为避免重复,请删旧版块)。
- [ ] **Step 2: 确认 `pages.json` 中 dashboard 条目未启用 `enablePullDownRefresh`**
- [ ] **Step 4: 在 `pages.json` 中启用下拉刷新**
Task 1 写入的 dashboard 条目已正确(不包含 `enablePullDownRefresh`)。**不要**手动加这个字段——下拉刷新由 scroll-view 的 `:refresher-enabled="true"` 接管,两者重复会冲突。
把 dashboard 条目改为:
```json
,{
"path": "pages/dashboard/dashboard",
"style": {
"navigationStyle": "custom",
"app-plus": {
"bounce": "none"
},
"enablePullDownRefresh": true
}
}
```
- [ ] **Step 5: 手动验证**
- [ ] **Step 3: 手动验证**
刷新 H5 dev URL
- 拖动下拉 → 触发强制刷新loading.overall 短暂为 true
@ -2875,7 +2817,7 @@ export default {
- 关闭网络DevTools Network → Offline→ 各 section 显示错误态
- 恢复网络 → 点击错误卡片 → 该 section 重试成功
- [ ] **Step 6: 验证 Figma 视觉一致性**
- [ ] **Step 4: 验证 Figma 视觉一致性**
`superpowers:verification-before-completion` 流程对照 `docs/figma-analysis-data-dashboard.md` 第三节设计 token 逐项核对:
- [ ] 颜色 token 与 §3.1 一致
@ -2883,15 +2825,13 @@ export default {
- [ ] 圆角与 §3.3 一致
- [ ] 5 个等级色与 §2.7.2 一致
- [ ] **Step 7: Commit**
- [ ] **Step 5: Commit**
```bash
git add frontend/pages/dashboard/dashboard.vue frontend/uni.scss frontend/pages.json
git commit -m "feat(dashboard): onShow 强制刷新 + Tab 缓存 + 下拉刷新 + SCSS class 引用"
git add frontend/pages/dashboard/dashboard.vue
git commit -m "feat(dashboard): onShow 强制刷新 + Tab 缓存 + 下拉刷新scroll-view refresher"
```
---
## Task 14: 全链路手动验证
**Files:** 无(验证任务)