CLAUDE.md
本文件为 Claude Code (claude.ai/code) 在处理此仓库代码时提供指导。
📚 项目文档索引
🚀 开发命令
核心命令
pnpm dev:weapp # 启动微信小程序开发服务器
pnpm dev:h5 # 启动 H5 开发服务器
pnpm build:weapp # 构建生产版本(微信小程序)
pnpm lint # 运行 ESLint
Git 工作流
从 develop 创建功能分支
# 1. 切换到 develop(确保最新)
git checkout develop
git pull
# 2. 创建功能分支
git checkout -b feature/功能名称
# 3. 开发完成后,合并回 develop
git checkout develop
git merge feature/功能名称
# 4. 删除功能分支(可选)
git branch -d feature/功能名称
分支命名规范:
-
feature/xxx- 新功能 -
fix/xxx- Bug 修复 -
refactor/xxx- 重构
版本自动更新(已实现)
规则:遵循 Semantic Versioning
-
feat- MINOR 版本更新(1.0.0 → 1.1.0) -
fix- PATCH 版本更新(1.0.0 → 1.0.1) -
perf- MINOR 版本更新 -
docs/style/refactor/test/chore- 不更新
实现方式:
- ✅
commit-msghook �用scripts/update-version.sh自动更新 - ✅ 更新后的
package.json自动加入暂存区 - ✅ 支持
feat(version):格式跳过版本更新
使用示例:
# 在当前功能分支开发
git checkout -b feature/new-page
# ... 开发代码 ...
git add .
git commit -m "feat(page): 添加新页面"
# 合并回 develop
git checkout develop
git merge feature/new-page
# 删除分支(可选)
git branch -d feature/new-page
其他平台构建
pnpm dev:alipay # 支付宝小程序开发
pnpm dev:swan # 百度小程序开发
pnpm dev:tt # 字节跳动小程序开发
📋 快速参考
🆕 最新更新(2026-02-12)
计划书功能优化:
- ✅ 添加计划书卡片状态标记("生成中"/"已完成",黄色/绿色背景)
- ✅ 修复嵌套弹窗层级冲突(使用 provide/inject 模式)
- ✅ 优化页面滚动加载并清理调试代码
- ✅ 修复搜索栏清空按钮点击无效
- ✅ 修改提交结果页按钮为"返回上一页"
- ✅ 预览成功后才调用查看接口,避免预览失败也翻状态
- ✅ 优化计划书提交跳转体验:关闭弹框时清理已选产品
- ✅ 提取计划书提交回调逻辑为 composable
认证与权限优化:
- ✅ 为所有制作计划书按钮添加登录权限检查
- ✅ 修复退出登录时红点状态未重置的问题
- ✅ 修复登录页返回按钮:清空 router store 并跳转到首页
- ✅ 修复 401 重定向死循环和返回报错问题
消息功能优化:
- ✅ 配置 TabBar 红点功能使用新的 unread_msg_count 字段
- ✅ 修复 TabBar 未读红点显示问题
- ✅ 优化消息列表卡片布局,提升信息可读性
- ✅ 增加未读消息红点提示
- ✅ 优化消息详情页布局,避免内容重复显示
- ✅ 添加消息列表 API 错误提示
样式改进:
- ✅ 增强资料卡片边框可见性(border-gray-200)
- ✅ 增大产品中心和详情页的字体与图标尺寸
- ✅ 添加全局背景色
- ✅ 增大全局字体和图标尺寸以提升可读性
- ✅ 优化首页网格导航视觉体验
- ✅ 重构"我的"页面为专业高端风格
- ✅ 优化 ProductCard 组件视觉样式
- ✅ 统一视觉柔和度和整体设计一致性
- ✅ 优化首页头图 CDN 加载
计划书字段优化:
- ✅ 优化提取金额字段并新增每年提取字段
- ✅ 隐藏产品详情页附件下载提示
- ✅ 优化输入框间距
代码质量:
- ✅ 从版本控制中移除本地配置文件 settings.local.json
- ✅ 禁用消息列表 Mock 数据,使用真实接口
- ✅ 清理调试日志
API 集成进度:
- ✅ 总接口数:29,已完成:26 (89.7%)
- ✅ 计划书模块接口联调完成(submitPlanAPI、listAPI)
新增功能:
- ✅ 消息列表和消息详情页
- ✅ 产品中心页
- ✅ 周热门资料页
- ✅ 分类列表页
- ✅ PlanFields 表单字段组件集
- ✅ useCollectOperation composable
- ✅ usePlanPermission composable
⚡ 常见问题快速解决
| 问题 | 解决方案 | 参考文档 |
|---|---|---|
| NutUI textarea 样式无法覆盖 | 使用原生 <textarea>
|
经验教训 |
| IconFont 动态切换不响应 | 添加 :key="name"
|
经验教训 |
| SVG 图标加载失败(500 错误) | 使用 import 导入 |
经验教训 |
| 代码重复 3 次 | 抽取为 Composable | 经验教训 |
| 组件对象响应式警告 | 使用 shallowRef + markRaw
|
经验教训 |
| 业务状态标记显示 | 使用条件类名 + 语义化颜色 | 经验教训 |
| 嵌套弹窗层级冲突 | 使用 provide/inject 模式 | 最近提交记录(3357bedb) |
| 401 重定向死循环 | 检查重定向拦截器逻辑 | 最近提交记录(6d2a4ec2) |
🎯 核心架构模式
- 认证流程 - 静默认证 + 401 自动刷新
- 双设计宽度 - NutUI: 375px, 其他: 750px
- 样式策略 - TailwindCSS(80%) + Less(20%)
- 组件抽取 - "第 3 次出现原则"
📦 技术栈
- 框架: Taro 4.1.9 + Vue 3.3.0 + Composition API
- UI 库: NutUI 4.3.13(京东推出的 Taro UI 库)
- 状态管理: Pinia 3.0.3 + taro-plugin-pinia
- HTTP 客户端: axios-miniprogram
- 样式: Less + TailwindCSS 3.x(双设计宽度系统)
- 构建工具: Webpack 5
📖 项目概述
Manulife WeApp(臻奇智荟圈)是一个基于 Taro 4 + Vue 3 + NutUI 构建的财富管理微信小程序。
业务模块
- 产品展示 - 热门产品展示及详情页
- 资料库 - 培训材料和文档管理
- 家办 - 家族办公室服务
- 签单 - 签约流程
- 用户中心 - 个人资料、收藏、反馈、帮助中心
🏗️ 核心架构
1. 可复用的导航组件
TabBar 组件(src/components/TabBar.vue)
- 固定底部导航栏,自动适配安全区域
- 支持图标 + 文字布局,激活状态高亮
- 使用于:首页、我的、家办、知识库、签单页面
NavHeader 组件(src/components/NavHeader.vue)
- 带返回按钮的自定义导航头
- 透明/背景变体,刘海屏设备的安全区域内边距
IconFont 组件(src/components/IconFont.vue)
- 自定义图标的图标字体包装器
- ⚠️ 动态切换时需添加
:key="name"详见经验教训
2. 身份认证流程(必需)
项目具有完善的身份认证系统,支持静默认证和会话管理。
核心文件:
-
src/utils/openid.js- 微信授权和会话管理 -
src/utils/request.js- 带 401 自动刷新拦截器的 HTTP 客户端 -
src/pages/login/index.vue- 登录页
认证流程:
-
静默认证(
miniProgramAuth()):- 调用
wx.login()获取 code - 调用后端
/srv/?a=openid接口换取 sessionid - 自动将 sessionid 写入 localStorage
- 尝试调用
loginStatusAPI获取用户信息(如已登录)
- 调用
-
401 自动刷新:
- API 返回 401 时触发
- 拦截器保存当前页面路径
- 调用
miniProgramAuth()重新获取会话 - 使用新会话重试原始请求
- 如果刷新失败,跳转到登录页
重要:
- 后端必须提供
/srv/?a=openid端点用于微信登录 - 后端必须提供
loginStatusAPI接口用于检查登录状态 - sessionid 存储在
localStorage.sessionid中 - sessionid 由请求拦截器自动注入到请求头的
cookie字段
3. API 层架构
API 定义模式(src/api/index.js):
export const yourAPI = (params) => {
return buildApiUrl('your_action', params)
}
请求包装器(src/api/fn.js):
- 所有 API 调用都应通过此包装器
- 处理常见错误场景
- 始终检查
res.code === 1判断成功
4. 增强导航系统
useGo Hook(src/hooks/useGo.js):
import { useGo } from '@/hooks/useGo'
const go = useGo()
go('/pages/detail/index') // 自动补全路径
go('/pages/product-detail/index', { id: 123 }) // 带查询参数
go.back() // 返回上一页
路由存储(src/stores/router.js):
- 维护已访问路由的栈
- 用于认证回调导航
5. 可复用 Composables
项目中的 Composables:
| Composable | 用途 | 文档 |
|---|---|---|
useSectionList |
分组列表管理 | 经验教训 |
useFileOperation |
文件下载、预览、打开 | 经验教训 |
useListItemClick |
统一的列表点击处理 | 经验教训 |
useCollectOperation |
收藏操作(新增) | 处理收藏/取消收藏逻辑 |
抽取原则:"第 3 次出现原则" - 当相同代码模式出现 3 次时,必须抽取为 Composable。
组件自包含原则(新增):
- 对于重复的UI结构,抽取为可复用组件(如 MaterialCard、ProductCard)
- 组件应该自包含业务逻辑(查看、收藏等),通过事件与父组件通信
- 避免在父组件中重复编写相同的逻辑代码
6. 样式处理策略
TailwindCSS vs Less 使用指南:
| 场景 | 使用 | 比例 |
|---|---|---|
| 布局(flex、grid、absolute) | TailwindCSS | 80% |
| 间距(padding、margin、gap) | TailwindCSS | |
| 排版(font-size、text-align) | TailwindCSS | |
| 颜色(bg-、text-、border-*) | TailwindCSS | |
| 响应式设计(sm:、md:、lg:) | TailwindCSS | |
| 组件特定样式(需要 scoped) | Less | 20% |
深度选择器(:deep()) |
Less | |
| 动画和过渡 | Less | |
伪元素(::before、::after) |
Less |
7. 响应式优化
处理组件对象响应式:
// ❌ BAD - 深度响应式导致性能问题
const menuItems = ref([
{ icon: IconFont, name: 'heart' } // Vue 会深度代理组件对象
])
// ✅ GOOD - 使用 shallowRef + markRaw
import { shallowRef, markRaw } from 'vue'
const menuItems = shallowRef([
{ icon: markRaw(IconFont), name: 'heart' } // 避免深度代理
])
页面结构
所有页面遵循以下目录结构:
src/pages/your-page/
├── index.vue # 页面组件(必须使用 <script setup>)
├── index.config.js # 页面配置(navigationBarTitleText 等)
└── assets/ # 页面特定资源(可选)
当前页面
所有页面按 src/app.config.js 注册顺序排列:
核心页面:
-
pages/index/index- 首页(产品展示、搜索、网格导航)- 热门产品的"产品资料"按钮跳转到
product-detail页面,带产品 ID - 热门资料的"查看更多"跳转到
material-list页面 - 网格导航图标跳转到各个业务页面
- 使用可复用组件(MaterialCard、ProductCard)
- 热门产品的"产品资料"按钮跳转到
-
pages/search/index- 产品和资料搜索页- 支持实时搜索(输入关键字自动调用 searchAPI)
- 双Tab切换(产品、资料)
- 支持分页加载和触底加载更多
- 使用可复用组件(MaterialCard、ProductCard)
-
pages/webview/index- 外部 URL 的 WebView 包装器 -
pages/document-preview/index- 文档预览页 -
pages/document-demo/index- 文档预览演示页 -
pages/onboarding/index- 新用户引导
业务页面:
-
pages/family-office/index- 家族办公室服务 -
pages/product-center/index- 产品中心页 -
pages/category-list/index- 分类列表页 -
pages/product-detail/index- 产品详情页- 通过 Taro 的
useLoadhook 接收id参数 - 导航示例:
go('/pages/product-detail/index', { id: 1 }) - 参数可用于从 API 获取产品详情
- 通过 Taro 的
-
pages/material-list/index- 资料/文档列表页 -
pages/week-hot-material/index- 周热门资料页- 使用 MaterialCard 组件展示热门资料
- 支持分页加载和触底加载更多
-
pages/signing/index- 签约 -
pages/mine/index- 用户资料 -
pages/plan/index- 业务计划管理- 使用 PlanSchemes 和 PlanPopup 组件
- 支持嵌套弹窗交互(provide/inject 模式)
- 支持滚动加载和分页
-
pages/plan-submit-result/index- 计划提交结果页- 导航按钮:返回上一页(非首页)
用户相关页面:
-
pages/favorites/index- 用户收藏 -
pages/avatar/index- 头像设置 -
pages/message/index- 消息列表页 -
pages/message-detail/index- 消息详情页 -
pages/feedback-list/index- 反馈列表 -
pages/feedback/index- 用户反馈 -
pages/login/index- 登录页 -
pages/help-center/index- 帮助中心和常见问题页
开发测试页面(仅开发环境):
-
pages/test-tabs/index- 标签页测试
组件库
导航与布局组件:
-
TabBar.vue- 底部导航栏 -
NavHeader.vue- 自定义导航头 -
indexNav.vue- 首页网格导航
图标与媒体组件:
-
IconFont.vue- 图标字体包装器 -
qrCode.vue- 二维码显示 -
qrCodeSearch.vue- 二维码扫描
列表与展示组件:
-
SectionCard.vue- 分组卡片组件 -
SectionItem.vue- 分组列表项组件 -
ListItemActions/- 列表项操作按钮 -
MaterialCard.vue- 资料卡片组件(可复用)- 自包含业务逻辑:查看、收藏
- 支持动态标签、文件大小格式化、学习人数显示
- 支持图片文件预览(使用 Taro.previewImage)
- 使用页面:首页、搜索页、周热门资料页
- 使用 composable:useCollectOperation、useListItemClick
-
ProductCard.vue- 产品卡片组件(可复用)- 自定义样式:动态标签、封面图
- 支持产品详情查看和计划书功能
- 使用页面:首页、搜索页、产品中心页
表单与输入组件:
-
FilterTabs.vue- 过滤标签组件 -
SearchBar.vue- 搜索栏组件
文档预览组件:
-
DocumentPreview/- 文档预览组件 -
PdfPreview.vue- PDF 预览组件 -
OfficeViewer.vue- Office 文档查看器
业务组件:
-
PlanSchemes/- 计划方案组件(SchemeA, SchemeB) -
PlanPopup/- 计划弹窗组件- 使用 provide/inject 模式实现父子弹窗通信
- 子弹窗打开时自动隐藏父级 footer
- 支持 AgePicker、DatePicker、SelectPicker 等字段组件
-
PlanFields/- 计划书表单字段组件-
AgePicker.vue- 年龄选择器 -
AmountInput.vue- 金额输入框 -
DatePicker.vue- 日期选择器 -
SelectPicker.vue- 下拉选择器 -
RadioGroup.vue- 单选按钮组
-
-
PlanTemplates/- 计划模板组件
工具组件:
-
PosterBuilder/- 海报生成器 -
time-picker-data/- 时间选择器数据
路径别名
全部配置在 config/index.js:30-38:
@/utils → src/utils
@/components → src/components
@/images → src/assets/images
@/assets → src/assets
@/composables→ src/composables
@/api → src/api
@/stores → src/stores
@/hooks → src/hooks
配置管理
环境配置(src/utils/config.js):
⚠️ 使用前必须修改:
-
BASE_URL- 设置开发/生产域名 -
REQUEST_DEFAULT_PARAMS.f- 设置业务模块标识符 -
REQUEST_DEFAULT_PARAMS.client_name- 设置应用名称
构建配置(config/index.js):
- 路径别名
- 设计宽度规则
- NutUI 自动导入
- 平台特定设置
应用配置(src/app.config.js):
- 页面路由注册
- 窗口配置
- 标签栏配置(可选)
- 分包(如需要)
🔧 重要实现细节
会话管理
-
会话 ID 存储:
localStorage.sessionid -
静默登录:
openid.js的miniProgramAuth()函数- 调用
wx.login()获取 code - 调用
/srv/?a=openid接口换取 sessionid - 自动写入 localStorage
- 调用
-
请求注入:
request.js拦截器自动读取并注入到请求头的cookie字段 - 会话清除:登出或 401 失败时清除
-
401 刷新:拦截器捕获 401 → 调用
miniProgramAuth()→ 重试原始请求
请求超时处理
- 默认超时:5 秒(
src/utils/request.js:79) - 通过
is_timeout_error()辅助函数检测超时 - 通过
is_network_error()辅助函数检测网络错误 - 两者都会触发弱网络降级流程
NutUI 自动导入
NutUI 组件通过 unplugin-vue-components 自动导入(config/index.js:91-93)。
无需手动导入 - 直接在模板中使用组件即可。
TailwindCSS 集成
- 为小程序兼容性禁用了 Preflight
- 启用了
rem2rpx转换 - 内容路径配置在
tailwind.config.js中 - 详见样式处理策略
📦 可选功能
如果不需要,可以移除以下功能:
-
微信支付:
src/utils/wechatPay.js、src/api/wx/pay.js -
二维码:
src/components/qrCode.vue、src/components/qrCodeSearch.vue -
海报生成器:
src/components/PosterBuilder/ -
时间选择器:
src/components/time-picker-data/
开发工作流
添加新页面
-
创建页面目录:
src/pages/your-page/ ├── index.vue └── index.config.js -
配置页面(
index.config.js):export default { navigationBarTitleText: '您的页面标题', enablePullDownRefresh: true, backgroundColor: '#f5f5f5' } -
在
src/app.config.js中注册路由:pages: [ 'pages/your-page/index', // ... ] -
在
index.vue中使用 composition API:<script setup> import { ref } from 'vue' import { useLoad, useShow } from '@tarojs/taro'
const pageId = ref(null)
useLoad((options) => { console.log('页面加载,参数:', options) // 接收导航参数 if (options.id) { pageId.value = options.id // 根据 ID 获取数据 } })
useShow(() => { console.log('页面显示') })
// 您的组件逻辑
**带参数导航**:
```javascript
// 从另一个页面
import { useGo } from '@/hooks/useGo'
const go = useGo()
// 带查询参数导航
go('/pages/product-detail/index', { id: 123, type: 'insurance' })
-
添加导航(可选的 TabBar 集成):
- 导入并使用
TabBar组件 - 根据路由配置激活状态
- 导入并使用
添加 API 调用
-
在
src/api/index.js中定义 API:export const getProductListAPI = (params) => { return buildApiUrl('product_list', params) } -
在页面中使用:
import { getProductListAPI } from '@/api' import { fn } from '@/api/fn'
const fetchProducts = async () => { try { const res = await fn(getProductListAPI({ page: 1 })) if (res.code === 1) { products.value = res.data } } catch (err) { console.error('获取产品失败:', err) } }
### 使用导航
**推荐**:使用 `useGo` hook 进行增强导航:
```javascript
import { useGo } from '@/hooks/useGo'
const go = useGo()
// 导航到页面
go('/pages/detail/index')
// 带参数导航(例如产品 ID)
go('/pages/product-detail/index', { id: 123 })
// 带多个参数导航
go('/pages/material-list/index', { category: 'insurance', page: 1 })
// 返回
go.back()
在目标页面接收参数:
import { useLoad } from '@tarojs/taro'
import { ref } from 'vue'
const productId = ref(null)
useLoad((options) => {
// 访问导航参数
console.log('接收到的参数:', options)
productId.value = options.id
// 根据参数获取数据
fetchProductDetail(options.id)
})
替代方案:使用 Taro 内置导航:
import Taro from '@tarojs/taro'
Taro.navigateTo({
url: '/pages/detail/index?id=123'
})
使用 Pinia 状态管理
创建 store(src/stores/yourStore.js):
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useYourStore = defineStore('yourStore', () => {
const state = ref(null)
function setState(newState) {
state.value = newState
}
return { state, setState }
})
在组件中使用:
import { useYourStore } from '@/stores/yourStore'
const store = useYourStore()
store.setState('新值')
使用 Mock 数据工具
项目提供了统一的 Mock 数据工具(src/utils/mockData.js),用于开发阶段测试分页加载等功能。
支持的 Mock API:
| API 名称 | 功能说明 | 使用页面 |
|---|---|---|
mockWeekHotAPI |
周热门资料 | 周热门资料页 |
mockFileListAPI |
资料列表 | 资料列表页 |
mockProductListAPI |
产品列表 | 产品中心页 |
mockSearchAPI |
搜索(产品+资料) | 搜索页 |
mockMessageListAPI |
消息列表 | 消息列表页 |
mockFavoriteListAPI |
收藏列表 | 收藏页 |
mockFeedbackListAPI |
意见反馈列表 | 意见反馈页 |
使用方式:
-
在页面中导入 Mock 函数:
import { mockWeekHotAPI } from '@/utils/mockData' -
设置 Mock 开关:
// 开发环境使用 Mock,生产环境使用真实 API const USE_MOCK_DATA = process.env.NODE_ENV === 'development' -
在数据获取函数中使用:
const fetchWeekHot = async (page = 0) => { loading.value = true
try { // 根据 USE_MOCK_DATA 开关决定使用 Mock 数据还是真实 API const res = USE_MOCK_DATA ? await mockWeekHotAPI({ page, limit: 20 }) : await fn(weekHotAPI({ page, limit: 20 }))
if (res.code === 1) {
weekHotList.value.push(...res.data.list)
hasMore.value = res.data.list.length >= 20
}
} catch (err) { console.error('获取周热门资料失败:', err) } finally { loading.value = false } }
**Mock 数据特性**:
- ✅ **模拟网络延迟**:100-300ms 随机延迟
- ✅ **支持分页加载**:可配置 `page` 和 `limit` 参数
- ✅ **随机数据生成**:文件大小、学习人数、收藏状态等
- ✅ **支持关键词搜索**:搜索 API 会根据关键词过滤数据
- ✅ **真实数据结构**:返回的数据结构与真实 API 一致
- ✅ **控制台日志**:每次请求都会打印 `[Mock]` 日志便于调试
**统一调用器**(可选):
也可以使用 `mockAPI()` 统一调用器:
```javascript
import { mockAPI } from '@/utils/mockData'
// 调用指定的 Mock API
const res = await mockAPI('weekHotAPI', { page: 0, limit: 20 })
注意事项:
- ⚠️ 生产环境关闭:部署时确保
USE_MOCK_DATA = false - ⚠️ 数据结构对齐:Mock 数据结构必须与真实 API 保持一致
- ⚠️ 分页逻辑:Mock API 返回的
list为空时表示没有更多数据
关键文件总结
修改前必须理解
-
src/utils/openid.js- 微信授权和会话管理逻辑 -
src/utils/request.js- 带拦截器的 HTTP 客户端 -
src/app.js- 应用启动序列和网络处理 -
src/utils/config.js- 服务器配置(需要修改)
核心业务逻辑
-
src/api/index.js- API 定义 -
src/api/fn.js- 请求包装器 -
src/stores/main.js- 主要状态管理 -
src/stores/user.js- 用户状态管理 -
src/stores/router.js- 路由状态管理
认证与会话
-
src/utils/openid.js-miniProgramAuth()静默登录 -
src/utils/request.js- 401 拦截器和 sessionid 管理 -
src/pages/login/index.vue- 登录页
可复用组件
-
src/components/TabBar.vue- 底部导航栏 -
src/components/NavHeader.vue- 自定义导航头 -
src/components/SectionCard.vue- 分组卡片 -
src/components/DocumentPreview/- 文档预览 -
src/components/MaterialCard.vue- 资料卡片(可复用)- 自包含业务逻辑:查看、收藏
- 支持动态标签、文件大小格式化、学习人数显示
- 使用页面:首页、搜索页、周热门资料页
-
src/components/ProductCard.vue- 产品卡片(可复用)- 自定义样式:动态标签、封面图
- 支持产品详情查看和计划书功能
- 使用页面:首页、搜索页
Composables
-
src/composables/useSectionList.js- 分组列表管理 -
src/composables/useFileOperation.js- 文件操作 -
src/composables/useListItemClick.js- 列表点击处理
工具函数
-
src/utils/mockData.js- Mock 数据生成工具(开发测试用)- 支持多个 API 的 Mock:周热门资料、资料列表、产品列表、搜索、消息列表、收藏列表、意见反馈
- 统一调用器:
mockAPI(apiName, params) - 支持分页加载、模拟网络延迟、随机数据生成
-
src/utils/documentIcons.js- 文档类型图标识别 -
src/utils/tools.js- 通用工具函数集合 -
src/utils/network.js- 网络状态工具 -
src/hooks/useGo.js- 增强导航 hook
调试技巧
调试问题时:
-
检查环境配置:
- 验证
src/utils/config.js中的BASE_URL - 检查业务模块标识符
f和client_name
- 验证
-
验证身份认证:
- 检查 localStorage 中的
sessionid - 在
src/utils/request.js拦截器中启用详细日志 - 测试 401 刷新流程
- 检查 localStorage 中的
-
网络问题:
- 使用 Taro 内置的网络状态监控
- 检查弱网络降级场景
- 验证离线缓存交互
-
样式问题:
- 确认设计宽度(375px vs 750px)
- 检查是 NutUI 组件还是自定义组件
- 验证 TailwindCSS 类是否已应用
-
导航问题:
- 检查路由是否在
src/app.config.js中注册 - 验证页面目录结构与路由匹配
- 使用
useGohook 进行一致的导航
- 检查路由是否在
✨ 最佳实践
组件开发
- ✅ 使用
<script setup>语法 - ✅ 使用 Composables 处理可复用逻辑
- ✅ Props 应该有类型定义
- ✅ 使用
emit进行子到父通信 - ✅ 优先使用 TailwindCSS 进行样式设计
API 集成
- ✅ 始终检查
res.code === 1判断成功 - ✅ 使用
try/catch进行错误处理 - ✅ 请求期间显示加载状态
- ✅ 优雅地处理网络错误
性能
- ✅ 使用页面懒加载(分包)
- ✅ 使用 CDN 参数优化图片
- ✅ 避免无分页的大数据集
- ✅ 在
onUnmounted中清理定时器和监听器 - ✅ 使用
shallowRef+markRaw处理组件对象
代码质量
- ✅ 遵循 Vue 3 Composition API 模式
- ✅ 使用描述性变量名
- ✅ 保持函数聚焦且简短(< 50 行)
- ✅ 所有函数必须有 JSDoc 注释 详见代码注释规范
- ✅ 提交前运行
pnpm lint
代码复用
- ✅ 遵循"第 3 次出现原则" - 代码重复 3 次时必须抽取
- ✅ 优先使用 Composables 而非 Mixins
- ✅ 组件职责单一,避免过度复杂
- ✅ 组件自包含业务逻辑 - 当UI结构重复出现时,抽取为可复用组件(如 MaterialCard、ProductCard)
- 组件内部处理业务逻辑(查看、收藏等)
- 通过事件与父组件通信
- 减少父组件的重复代码
- 示例:MaterialCard 组件在首页、搜索页、周热门资料页复用