topfans/docs/superpowers/plans/2026-03-25-guide-modification.md
2026-04-07 22:28:50 +08:00

298 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 新手引导修改实现计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 修改新手引导流程:点击"去做"后直接从第一项引导开始,存储步骤进度,高亮区域支持点击触发动作
**Architecture:** 修改 GuideStartModal 的 start 事件触发逻辑,添加步骤进度存储,支持高亮区域点击事件
**Tech Stack:** Vue 3 / Vuex / uni-app
---
### Task 1: 修改 GuideStartModal 点击"去做"后直接开始引导
**Files:**
- Modify: `frontend/pages/square/square.vue:751-754`
- Modify: `frontend/components/GuideStartModal.vue:39-45`
- [ ] **Step 1: 修改 square.vue 的 handleGuideStart 方法**
```javascript
// 原本代码
const handleGuideStart = () => {
showGuideStartModal.value = false;
showGuideListModal.value = true;
};
// 修改为:直接开始第一个未完成的引导
const handleGuideStart = () => {
showGuideStartModal.value = false;
// 获取所有引导keys按顺序获取第一个未完成的
const keys = getAllGuideKeys();
const firstUndoneKey = keys.find(key => !isGuideDone(key));
if (firstUndoneKey) {
store.dispatch('guide/initGuide', firstUndoneKey);
}
};
```
需要 import
```javascript
import { getAllGuideKeys, isGuideDone } from '@/utils/guideConfig.js';
```
- [ ] **Step 2: 验证修改**
运行项目,点击"去做"按钮,验证是否直接进入第一个引导而不是显示列表弹窗。
- [ ] **Step 3: 提交**
---
### Task 2: 添加引导步骤进度存储功能
**Files:**
- Modify: `frontend/utils/guideConfig.js:252-315`
- Modify: `frontend/store/modules/guide.js:60-74`
- [ ] **Step 1: 在 guideConfig.js 添加步骤进度存储函数**
```javascript
/**
* 获取引导的当前步骤
* @param {string} key 引导key
* @returns {number} 当前步骤索引默认0
*/
export function getGuideCurrentStep(key) {
return uni.getStorageSync(`guide_step_${key}`) || 0
}
/**
* 设置引导的当前步骤
* @param {string} key 引导key
* @param {number} step 步骤索引
*/
export function setGuideCurrentStep(key, step) {
uni.setStorageSync(`guide_step_${key}`, step)
}
/**
* 获取下一个未完成的引导key
* @returns {string|null} 引导key或null
*/
export function getNextUndoneGuideKey() {
const keys = getAllGuideKeys()
return keys.find(key => !isGuideDone(key)) || null
}
```
- [ ] **Step 2: 修改 store/modules/guide.js 的 END_GUIDE mutation**
```javascript
// 在 mutations 中修改
END_GUIDE(state) {
if (state.currentGuide) {
const key = state.currentGuide.key
markGuideAsShown(key)
markGuideDone(key)
// 重置步骤进度
setGuideCurrentStep(key, 0)
}
state.currentGuide = null
state.currentStep = 0
state.isActive = false
state.isNavigating = false
},
```
- [ ] **Step 3: 修改 NEXT_STEP mutation 添加步骤存储**
```javascript
NEXT_STEP(state) {
if (state.currentGuide && state.currentStep < state.currentGuide.steps.length - 1) {
state.currentStep++
// 存储当前步骤
setGuideCurrentStep(state.currentGuide.key, state.currentStep)
}
},
```
- [ ] **Step 4: 修改 START_GUIDE mutation 恢复步骤进度**
```javascript
START_GUIDE(state, guideConfig) {
state.currentGuide = guideConfig
// 恢复之前保存的步骤进度
state.currentStep = getGuideCurrentStep(guideConfig.key) || 0
state.isActive = true
state.isNavigating = false
},
```
- [ ] **Step 5: 提交**
---
### Task 3: 高亮区域支持点击触发动作
**Files:**
- Modify: `frontend/utils/guideConfig.js:37-157` (steps 配置)
- Modify: `frontend/components/GuideOverlay.vue:245-248`
- [ ] **Step 1: 扩展 step 配置结构**
在 guideConfig.js 的 steps 配置中添加 action 字段:
```javascript
// action 支持的类型:
// 1. { type: 'navigate', url: '/pages/xxx/xxx' } - 路由跳转
// 2. { type: 'component', name: 'xxx' } - 打开组件
// 3. { type: 'function', handler: 'xxx' } - 执行函数
// 示例配置:
{
target: '.banner-carousel',
content: '这里是轮播图,点击可以查看排行榜和活动',
center: true,
buttons: ['next'],
action: {
type: 'navigate',
url: '/pages/rank/rank'
}
}
```
- [ ] **Step 2: 修改 GuideOverlay 的 handleHighlightClick 方法**
```javascript
// 点击高亮区域
function handleHighlightClick() {
const stepConfigVal = stepConfig.value
if (stepConfigVal && stepConfigVal.action) {
const { action } = stepConfigVal
if (action.type === 'navigate' && action.url) {
// 路由跳转
uni.navigateTo({
url: action.url,
fail: (err) => {
console.error('[Guide] 页面跳转失败:', err)
}
})
} else if (action.type === 'component' && action.name) {
// 打开组件(通过事件通知父组件)
store.dispatch('guide/openComponent', action.name)
} else if (action.type === 'function' && action.handler) {
// 执行函数
store.dispatch('guide/executeFunction', action.handler)
}
}
}
```
- [ ] **Step 3: 在 store 中添加处理 action 的 actions**
```javascript
// 在 store/modules/guide.js 中添加
actions: {
// ... existing actions ...
/**
* 打开组件
*/
openComponent({ commit }, componentName) {
console.log(`[Guide] 打开组件: ${componentName}`)
commit('OPEN_COMPONENT', componentName)
},
/**
* 执行函数
*/
executeFunction({ commit }, handler) {
console.log(`[Guide] 执行函数: ${handler}`)
commit('EXECUTE_FUNCTION', handler)
}
}
// 添加对应的 mutations
mutations: {
// ... existing mutations ...
OPEN_COMPONENT(state, componentName) {
state.pendingAction = { type: 'component', name: componentName }
},
EXECUTE_FUNCTION(state, handler) {
state.pendingAction = { type: 'function', handler }
}
}
// 在 state 中添加
state: {
// ... existing state ...
pendingAction: null, // 待执行的行动
}
```
- [ ] **Step 4: 提交**
---
### Task 4: 验证个人中心引导列表弹窗不受影响
**Files:**
- Review: `frontend/pages/profile/profile.vue:914-936`
- [ ] **Step 1: 检查 profile.vue 中 handleDoGuide 方法**
当前代码:
```javascript
const handleDoGuide = (key) => {
showGuideListModal.value = false;
if (isFirstEntry) {
store.dispatch("guide/initGuide", key);
} else {
store.dispatch("guide/initGuide", key);
}
};
```
验证逻辑保持不变:用户从个人中心点击进入某个引导时,触发 initGuide 动作。这与 Task 1 的修改不冲突,因为:
- square.vue 的修改只影响新用户首次点击"去做"的行为
- profile.vue 中的 GuideListModal 保持原有逻辑
- [ ] **Step 2: 测试验证**
1. 从个人中心进入引导列表
2. 点击某个引导的"去做"按钮
3. 确认引导能正常启动,且列表弹窗行为不变
- [ ] **Step 3: 提交**
---
### Task 5: 端到端测试
- [ ] **Step 1: 测试完整流程**
1. 模拟新用户登录
2. 验证 GuideStartModal 显示
3. 点击"去做"
4. 验证直接进入第一个引导而不是显示列表
5. 完成引导步骤
6. 验证步骤进度被正确存储
7. 验证高亮区域点击能触发相应动作(配置了 action 的情况下)
- [ ] **Step 2: 测试个人中心入口**
1. 进入个人中心
2. 点击引导按钮
3. 验证 GuideListModal 正常显示
4. 选择一个引导执行
5. 验证行为与之前一致
- [ ] **Step 3: 提交**