hookehuyr

docs: 整理文档结构并使用中文命名

**主要变更**:
- 将组件相关文档移动到 guides/components/
  - LoadMoreList 迁移指南.md
  - LoadMoreList 完整使用指南.md
- 将 API/Mock 相关文档移动到 api-specs/数据文档/
  - Mock 数据完整总结.md
  - Mock 数据设置指南.md
  - API 集成日志.md
- 将测试相关文档移动到相应目录
  - 滚动加载测试指南.md → guides/testing/
  - 计划测试实施报告.md → reports/测试报告/
- 更新所有文档中的相对路径引用
- 添加文档命名使用中文规则到全局规则

**详细信息**:
- **影响文件**: docs/ 目录下所有文档
- **技术栈**: 文档组织
- **测试状态**: N/A
- **备注**: 提升文档可维护性和查找效率

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
......@@ -302,7 +302,7 @@ console.log(product.form_sn) // 应该有值,如 "life-insurance-wiop3e"
- [完整架构文档](./plan-entry-architecture.md)
- [经验教训总结](../lessons-learned/plan-entry-module-summary.md)
- [API 联调日志](../api-integration-log.md)
- [API 联调日志](../api-specs/API 集成日志.md)
---
......
......@@ -9,7 +9,6 @@ docs/
├── CHANGELOG.md # 项目变更日志(核心文档)
├── README.md # 本文件(文档导航索引)
├── lessons-learned.md # 经验教训总结(核心文档)
├── api-integration-log.md # API 联调日志
├── guides/ # 📘 使用指南和教程
│ ├── START_HERE.md # 新人入门指南
......@@ -77,7 +76,7 @@ docs/
### 核心文档
- 📖 [项目变更日志](CHANGELOG.md) - 所有功能、修复和优化的记录
- 📖 [经验教训总结](lessons-learned.md) - 开发中的最佳实践和常见陷阱
- 📖 [API 联调日志](api-integration-log.md) - 接口联调状态记录
- 📖 [API 联调日志](api-specs/API 集成日志.md) - 接口联调状态记录
### 新手入门
👉 **[guides/START_HERE.md](guides/START_HERE.md)** - 快速了解项目功能
......@@ -163,7 +162,7 @@ UI/UX 设计稿和生成的代码:
### 更新日志
- 项目级别的更新:修改 `CHANGELOG.md`
- API 联调记录:修改 `api-integration-log.md`
- API 联调记录:修改 `api-specs/API 集成日志.md`
---
......
# 原始页面备份
> **备份时间**: 2026-02-08
> **备份原因**: LoadMoreList 组件迁移前的代码备份
> **迁移提交**: ce4b99b refactor: 迁移所有剩余页面到 LoadMoreList 组件
---
## 📁 备份文件列表
| 文件 | 大小 | 说明 |
|------|------|------|
| `message-index.vue.bak` | 3.7 KB | 消息列表页(迁移前) |
| `product-center-index.vue.bak` | 13.9 KB | 产品中心页(迁移前) |
| `material-list-index.vue.bak` | 24.6 KB | 资料列表页(迁移前) |
| `search-index.vue.bak` | 17 KB | 搜索页(迁移前) |
---
## 🔄 如何恢复原始代码
### 方法 1: 手动恢复(推荐)
如果新组件有问题,可以手动恢复:
```bash
# 1. 删除当前文件
rm src/pages/message/index.vue
# 2. 从备份恢复
cp docs/backups/original-pages/message-index.vue.bak src/pages/message/index.vue
# 3. 重复其他文件...
```
### 方法 2: 使用 Git 恢复
使用 Git 命令恢复到迁移前的版本:
```bash
# 恢复单个文件
git checkout ce4b99b^ -- src/pages/message/index.vue
# 恢复所有文件
git checkout ce4b99b^ -- src/pages/message/index.vue \
src/pages/product-center/index.vue \
src/pages/material-list/index.vue \
src/pages/search/index.vue
```
---
## 📋 迁移前后对比
### message 页面
| 指标 | 迁移前 | 迁移后 |
|------|--------|--------|
| 代码行数 | 149 行 | 229 行 |
| 分页逻辑 | 手动实现 | LoadMoreList 组件 |
| 下拉刷新 | ❌ 无 | ✅ 有 |
### product-center 页面
| 指标 | 迁移前 | 迁移后 |
|------|--------|--------|
| 代码行数 | 510 行 | 592 行 |
| 分页逻辑 | 手动实现 | LoadMoreList 组件 |
| 搜索功能 | ✅ 有 | ✅ 保留 |
| Tabs | ✅ 有 | ✅ 保留 |
### material-list 页面
| 指标 | 迁移前 | 迁移后 |
|------|--------|--------|
| 代码行数 | 888 行 | 828 行 |
| 分页逻辑 | 手动实现 | LoadMoreList 组件 |
| 分类缓存 | ✅ 有 | ✅ 保留 |
| 搜索防抖 | ✅ 有 | ✅ 保留 |
### search 页面
| 指标 | 迁移前 | 迁移后 |
|------|--------|--------|
| 代码行数 | 603 行 | 549 行 |
| 分页逻辑 | 手动实现 | LoadMoreList 组件 |
| 双列表系统 | ✅ 有 | ✅ 保留 |
| 自动 tab 选择 | ✅ 有 | ✅ 保留 |
---
## ⚠️ 注意事项
1. **备份文件只读**: 这些是 `.bak` 文件,只用于参考,不应直接修改
2. **使用 Git 版本控制**: 建议使用 Git 命令恢复,而不是手动复制
3. **测试新组件**: 如果新组件有问题,先检查是否可以通过修改解决
4. **保留备份**: 建议保留这些备份文件,直到确认新组件完全稳定
---
## 🔍 迁移问题排查
如果新组件有问题,按以下步骤排查:
### 1. 检查 Props 是否正确
```vue
<!-- ❌ 错误:缺少必需 props -->
<LoadMoreList :list="products" @load-more="handleLoadMore">
<!-- ✅ 正确:包含所有必需 props -->
<LoadMoreList
:list="products"
:page="page"
:has-more="hasMore"
:loading="loading"
:loading-more="loadingMore"
@load-more="handleLoadMore"
>
```
### 2. 检查数据加载逻辑
```javascript
// ❌ 错误:未正确处理追加数据
const handleLoadMore = async (page) => {
const newData = await fetchData({ page })
currentList.value = newData // 错误:会覆盖之前的数据
}
// ✅ 正确:追加数据
const handleLoadMore = async (page) => {
const newData = await fetchData({ page })
currentList.value = [...currentList.value, ...newData]
}
```
### 3. 检查 hasMore 判断逻辑
```javascript
// ❌ 错误:使用总数量判断
hasMore.value = currentList.value.length < total
// ✅ 正确:使用返回数据量判断
hasMore.value = newData.length >= pageSize
```
### 4. 检查 page 初始值
```javascript
// 如果 API 页码从 1 开始
const page = ref(1)
// 如果 API 页码从 0 开始
const page = ref(0)
// 组件会自动 +1,所以不需要手动 +1
```
---
## 📖 相关文档
- [LoadMoreList 完整指南](../guides/components/LoadMoreList 完整使用指南.md)
- [LoadMoreList 迁移指南](../guides/components/LoadMoreList 迁移指南.md)
- [项目 CLAUDE.md](../../CLAUDE.md)
---
**创建时间**: 2026-02-08
**维护者**: Claude Code
This diff is collapsed. Click to expand it.
<template>
<view class="min-h-screen bg-[#F9FAFB] pb-safe">
<NavHeader title="我的消息" />
<!-- 列表区域 -->
<view class="p-4">
<template v-if="messageList.length > 0">
<view
v-for="item in messageList"
:key="item.id"
class="bg-white rounded-xl p-4 mb-3 shadow-sm active:opacity-70 transition-opacity"
@tap="handleItemClick(item)"
>
<view class="flex justify-between items-start mb-2">
<view class="flex-1 mr-2">
<view class="text-base font-bold text-gray-900 line-clamp-1">
{{ item.title }}
</view>
</view>
<text class="text-xs text-gray-400 shrink-0 mt-1">
{{ item.create_time }}
</text>
</view>
<view class="text-sm text-gray-600 line-clamp-2 leading-relaxed">
{{ item.intro || item.content || '暂无简介' }}
</view>
</view>
<!-- 加载更多/没有更多 -->
<view class="py-4 text-center text-[24rpx] text-gray-400">
<text v-if="loading">加载中...</text>
<text v-else-if="!hasMore">没有更多了</text>
<text v-else>上拉加载更多</text>
</view>
</template>
<!-- 空状态 -->
<nut-empty
v-else-if="!loading && messageList.length === 0"
description="暂无消息"
image="empty"
/>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { useLoad, usePullDownRefresh, useReachBottom, stopPullDownRefresh } from '@tarojs/taro'
import { useGo } from '@/hooks/useGo'
import NavHeader from '@/components/NavHeader.vue'
import { myListAPI } from '@/api/news'
import { mockMessageListAPI } from '@/utils/mockData'
// ⚠️ MOCK 数据开关 - 开发环境使用 mock 数据,生产环境使用真实 API
const USE_MOCK_DATA = process.env.NODE_ENV === 'development'
const go = useGo()
const messageList = ref([])
const page = ref(1)
const limit = ref(10)
const hasMore = ref(true)
const loading = ref(false)
/**
* @description 加载消息列表
* @param {boolean} refresh 是否刷新
*/
const fetchMessageList = async (refresh = false) => {
if (loading.value) return
if (refresh) {
page.value = 1
hasMore.value = true
} else if (!hasMore.value) {
return
}
loading.value = true
try {
console.log('[Message] 使用 Mock 数据:', USE_MOCK_DATA)
// 根据开关选择使用真实 API 或 Mock 数据
const res = USE_MOCK_DATA
? await mockMessageListAPI({
page: page.value,
limit: limit.value
})
: await myListAPI({
page: page.value,
limit: limit.value
})
if (res.code === 1) {
const list = res.data?.list || []
if (refresh) {
messageList.value = list
} else {
messageList.value = [...messageList.value, ...list]
}
if (list.length < limit.value) {
hasMore.value = false
} else {
page.value++
}
}
} catch (err) {
console.error('获取消息列表失败:', err)
} finally {
loading.value = false
if (refresh) {
stopPullDownRefresh()
}
}
}
/**
* @description 跳转到详情页
* @param {Object} item 消息对象
*/
const handleItemClick = (item) => {
go('/pages/message-detail/index', { id: item.id })
}
// 页面加载
useLoad(() => {
fetchMessageList(true)
})
// 下拉刷新
usePullDownRefresh(() => {
fetchMessageList(true)
})
// 上拉加载更多
useReachBottom(() => {
fetchMessageList()
})
</script>
<style lang="less">
/* Scoped styles if needed */
</style>
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
......@@ -670,7 +670,7 @@ if (!Number.isNaN(birthDate.getTime())) {
### 项目文档
- [计划书架构设计](../plan/plan-entry-architecture.md)
- [API 联调日志](../api-integration-log.md)
- [API 联调日志](../api-specs/API 集成日志.md)
- [变更日志](../CHANGELOG.md)
### 技术文档
......