CLAUDE.md 28 KB

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-msg hook �用 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

🎯 核心架构模式

  1. 认证流程 - 静默认证 + 401 自动刷新
  2. 双设计宽度 - NutUI: 375px, 其他: 750px
  3. 样式策略 - TailwindCSS(80%) + Less(20%)
  4. 组件抽取 - "第 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 - 登录页

认证流程

  1. 静默认证miniProgramAuth()):

    • 调用 wx.login() 获取 code
    • 调用后端 /srv/?a=openid 接口换取 sessionid
    • 自动将 sessionid 写入 localStorage
    • 尝试调用 loginStatusAPI 获取用户信息(如已登录)
  2. 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 Hooksrc/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 注册顺序排列:

核心页面

  1. pages/index/index - 首页(产品展示、搜索、网格导航)
    • 热门产品的"产品资料"按钮跳转到 product-detail 页面,带产品 ID
    • 热门资料的"查看更多"跳转到 material-list 页面
    • 网格导航图标跳转到各个业务页面
    • 使用可复用组件(MaterialCard、ProductCard)
  2. pages/search/index - 产品和资料搜索页
    • 支持实时搜索(输入关键字自动调用 searchAPI)
    • 双Tab切换(产品、资料)
    • 支持分页加载和触底加载更多
    • 使用可复用组件(MaterialCard、ProductCard)
  3. pages/webview/index - 外部 URL 的 WebView 包装器
  4. pages/document-preview/index - 文档预览页
  5. pages/document-demo/index - 文档预览演示页
  6. pages/onboarding/index - 新用户引导

业务页面

  1. pages/family-office/index - 家族办公室服务
  2. pages/product-center/index - 产品中心页
  3. pages/category-list/index - 分类列表页
  4. pages/product-detail/index - 产品详情页
    • 通过 Taro 的 useLoad hook 接收 id 参数
    • 导航示例:go('/pages/product-detail/index', { id: 1 })
    • 参数可用于从 API 获取产品详情
  5. pages/material-list/index - 资料/文档列表页
  6. pages/week-hot-material/index - 周热门资料页
    • 使用 MaterialCard 组件展示热门资料
    • 支持分页加载和触底加载更多
  7. pages/signing/index - 签约
  8. pages/mine/index - 用户资料
  9. pages/plan/index - 业务计划管理
    • 使用 PlanSchemes 和 PlanPopup 组件
    • 支持嵌套弹窗交互(provide/inject 模式)
    • 支持滚动加载和分页
  10. pages/plan-submit-result/index - 计划提交结果页
    • 导航按钮:返回上一页(非首页)

用户相关页面

  1. pages/favorites/index - 用户收藏
  2. pages/avatar/index - 头像设置
  3. pages/message/index - 消息列表页
  4. pages/message-detail/index - 消息详情页
  5. pages/feedback-list/index - 反馈列表
  6. pages/feedback/index - 用户反馈
  7. pages/login/index - 登录页
  8. 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.jsminiProgramAuth() 函数
    • 调用 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.jssrc/api/wx/pay.js
  • 二维码src/components/qrCode.vuesrc/components/qrCodeSearch.vue
  • 海报生成器src/components/PosterBuilder/
  • 时间选择器src/components/time-picker-data/

开发工作流

添加新页面

  1. 创建页面目录

    src/pages/your-page/
    ├── index.vue
    └── index.config.js
    
  2. 配置页面index.config.js):

    export default {
     navigationBarTitleText: '您的页面标题',
     enablePullDownRefresh: true,
     backgroundColor: '#f5f5f5'
    }
    
  3. src/app.config.js 中注册路由

    pages: [
     'pages/your-page/index',
     // ...
    ]
    
  4. 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' })
  1. 添加导航(可选的 TabBar 集成):
    • 导入并使用 TabBar 组件
    • 根据路由配置激活状态

添加 API 调用

  1. src/api/index.js 中定义 API

    export const getProductListAPI = (params) => {
       return buildApiUrl('product_list', params)
    }
    
  2. 在页面中使用

    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 状态管理

创建 storesrc/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 意见反馈列表 意见反馈页

使用方式

  1. 在页面中导入 Mock 函数

    import { mockWeekHotAPI } from '@/utils/mockData'
    
  2. 设置 Mock 开关

    // 开发环境使用 Mock,生产环境使用真实 API
    const USE_MOCK_DATA = process.env.NODE_ENV === 'development'
    
  3. 在数据获取函数中使用

    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 为空时表示没有更多数据

关键文件总结

修改前必须理解

  1. src/utils/openid.js - 微信授权和会话管理逻辑
  2. src/utils/request.js - 带拦截器的 HTTP 客户端
  3. src/app.js - 应用启动序列和网络处理
  4. src/utils/config.js - 服务器配置(需要修改)

核心业务逻辑

  1. src/api/index.js - API 定义
  2. src/api/fn.js - 请求包装器
  3. src/stores/main.js - 主要状态管理
  4. src/stores/user.js - 用户状态管理
  5. src/stores/router.js - 路由状态管理

认证与会话

  1. src/utils/openid.js - miniProgramAuth() 静默登录
  2. src/utils/request.js - 401 拦截器和 sessionid 管理
  3. src/pages/login/index.vue - 登录页

可复用组件

  1. src/components/TabBar.vue - 底部导航栏
  2. src/components/NavHeader.vue - 自定义导航头
  3. src/components/SectionCard.vue - 分组卡片
  4. src/components/DocumentPreview/ - 文档预览
  5. src/components/MaterialCard.vue - 资料卡片(可复用)
    • 自包含业务逻辑:查看、收藏
    • 支持动态标签、文件大小格式化、学习人数显示
    • 使用页面:首页、搜索页、周热门资料页
  6. src/components/ProductCard.vue - 产品卡片(可复用)
    • 自定义样式:动态标签、封面图
    • 支持产品详情查看和计划书功能
    • 使用页面:首页、搜索页

Composables

  1. src/composables/useSectionList.js - 分组列表管理
  2. src/composables/useFileOperation.js - 文件操作
  3. src/composables/useListItemClick.js - 列表点击处理

工具函数

  1. src/utils/mockData.js - Mock 数据生成工具(开发测试用)
    • 支持多个 API 的 Mock:周热门资料、资料列表、产品列表、搜索、消息列表、收藏列表、意见反馈
    • 统一调用器:mockAPI(apiName, params)
    • 支持分页加载、模拟网络延迟、随机数据生成
  2. src/utils/documentIcons.js - 文档类型图标识别
  3. src/utils/tools.js - 通用工具函数集合
  4. src/utils/network.js - 网络状态工具
  5. src/hooks/useGo.js - 增强导航 hook

调试技巧

调试问题时:

  1. 检查环境配置

    • 验证 src/utils/config.js 中的 BASE_URL
    • 检查业务模块标识符 fclient_name
  2. 验证身份认证

    • 检查 localStorage 中的 sessionid
    • src/utils/request.js 拦截器中启用详细日志
    • 测试 401 刷新流程
  3. 网络问题

    • 使用 Taro 内置的网络状态监控
    • 检查弱网络降级场景
    • 验证离线缓存交互
  4. 样式问题

    • 确认设计宽度(375px vs 750px)
    • 检查是 NutUI 组件还是自定义组件
    • 验证 TailwindCSS 类是否已应用
  5. 导航问题

    • 检查路由是否在 src/app.config.js 中注册
    • 验证页面目录结构与路由匹配
    • 使用 useGo hook 进行一致的导航

✨ 最佳实践

组件开发

  • ✅ 使用 <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 组件在首页、搜索页、周热门资料页复用

更多最佳实践详见经验教训总结