hookehuyr

feat(plan): 添加计划书列表 Mock 数据支持

- 新增 mockPlanListAPI 函数支持分页、状态筛选、关键词搜索
- 集成 Mock 数据开关,开发环境自动启用
- 支持测试分页加载、状态筛选、关键词搜索、查看功能
- 数据结构完全符合 API 文档规范
......@@ -137,10 +137,14 @@ import { ref, nextTick } from 'vue'
import Taro, { useLoad, useReachBottom } from '@tarojs/taro'
import { useFileOperation } from '@/composables/useFileOperation'
import { listAPI, viewAPI, deleteAPI } from '@/api/plan'
import { mockPlanListAPI } from '@/utils/mockData'
import NavHeader from '@/components/navigation/NavHeader.vue'
import ListItemActions from '@/components/list/ListItemActions/index.vue'
import SearchBar from '@/components/forms/SearchBar.vue'
// Mock 数据开关(开发环境使用 Mock,生产环境使用真实 API)
const USE_MOCK_DATA = process.env.NODE_ENV === 'development'
const { viewFile } = useFileOperation()
const searchValue = ref('')
......@@ -244,7 +248,7 @@ const transformApiItem = (apiItem) => {
}
/**
* 加载计划书列表(调用真实 API
* 加载计划书列表(支持 Mock 数据
* @param {number} page - 页码(从0开始,API 要求)
* @param {number} limit - 每页数量
* @param {boolean} isLoadMore - 是否为加载更多
......@@ -271,6 +275,10 @@ const transformApiItem = (apiItem) => {
* - "5" = 处理中
* - "7" = 已生成
* - "9" = 已查看
*
* 🔧 **Mock 数据说明**:
* 开发环境会使用 Mock 数据测试分页、筛选、搜索功能
* 生产环境使用真实 API
*/
const fetchPlanList = async (page = 0, limit = pageSize, isLoadMore = false) => {
try {
......@@ -297,8 +305,10 @@ const fetchPlanList = async (page = 0, limit = pageSize, isLoadMore = false) =>
params.keyword = searchValue.value
}
// 调用 API
const res = await listAPI(params)
// 🔧 根据环境选择使用 Mock 数据还是真实 API
const res = USE_MOCK_DATA
? await mockPlanListAPI(params)
: await listAPI(params)
if (res.code === 1 && res.data) {
let apiList = res.data.list || []
......
......@@ -10,6 +10,7 @@
* - myListAPI: 消息列表
* - favoriteListAPI: 收藏列表
* - feedbackListAPI: 意见反馈列表
* - planListAPI: 计划书列表(新增)
*/
// ============================================================================
......@@ -769,6 +770,150 @@ export async function mockFeedbackListAPI(params) {
}
// ============================================================================
// 8. 计划书列表 Mock (planListAPI)
// ============================================================================
const PLAN_PRODUCT_NAMES = [
'终身寿险至尊版',
'重疾险保障计划',
'百万年金保险计划',
'高端医疗险',
'养老理财保险',
'教育金保险计划',
'意外伤害保险',
'定期寿险',
'终身寿险',
'企业年金保险',
'团体意外险',
'健康保险计划'
]
const PLAN_STATUS = ['3', '5', '7', '9'] // 3=待处理, 5=处理中, 7=已生成, 9=已查看
const PLAN_CATEGORIES = [
{ id: '1', name: '人寿保险' },
{ id: '2', name: '重疾险' },
{ id: '3', name: '医疗险' },
{ id: '4', name: '年金险' },
{ id: '5', name: '意外险' }
]
const CUSTOMER_NAMES = [
'张三', '李四', '王五', '赵六', '钱七',
'孙八', '周九', '吴十', '郑十一', '陈十二',
'刘十三', '黄十四', '杨十五', '朱十六', '胡十七'
]
/**
* 生成计划书列表项
* @param {number} id - 计划书ID
* @returns {Object} 计划书对象
*/
function generatePlanItem(id) {
const productName = PLAN_PRODUCT_NAMES[Math.floor(Math.random() * PLAN_PRODUCT_NAMES.length)]
const customerName = CUSTOMER_NAMES[Math.floor(Math.random() * CUSTOMER_NAMES.length)]
const orderStatus = PLAN_STATUS[Math.floor(Math.random() * PLAN_STATUS.length)]
const category = PLAN_CATEGORIES[Math.floor(Math.random() * PLAN_CATEGORIES.length)]
// 生成创建时间(最近30天内)
const now = new Date()
const createTime = new Date(now.getTime() - Math.random() * 30 * 24 * 60 * 60 * 1000)
// 根据状态决定是否有计划书文件
const hasFiles = orderStatus === '7' || orderStatus === '9' // 已生成或已查看才有文件
const proposalFiles = []
if (hasFiles) {
// 生成1-3个计划书文件
const fileCount = Math.floor(Math.random() * 3) + 1
for (let i = 0; i < fileCount; i++) {
proposalFiles.push({
id: id * 10 + i,
file_name: `${customerName}-${productName}-计划书.pdf`,
file_url: `https://picsum.photos/seed/plan-${id}-${i}/400/300`
})
}
}
return {
id: id,
customer_name: customerName,
product_name: productName,
categories: [category],
created_time: formatDate(createTime),
order_status: orderStatus,
proposal_files: proposalFiles
}
}
/**
* Mock: planListAPI (计划书列表)
* @description 支持分页、状态筛选、关键词搜索
* @param {Object} params - 请求参数
* @param {number} params.page - 页码(从0开始)
* @param {number} params.limit - 每页数量(默认20)
* @param {string} [params.status] - 状态筛选(3=待处理, 5=处理中, 7=已生成, 9=已查看)
* @param {string} [params.keyword] - 搜索关键字
* @returns {Promise<Object>} Mock 响应
*/
export async function mockPlanListAPI(params) {
await mockDelay()
const { page = 0, limit = 20, status, keyword } = params
const totalPages = 10
// 如果超过总页数,返回空列表
if (page >= totalPages) {
console.log(`[Mock] planListAPI - 第${page}页,共0条(已到最后一页)`)
return {
code: 1,
msg: 'success',
data: {
list: [],
total: totalPages * limit
}
}
}
const list = []
const startIndex = page * limit
// 生成数据并过滤
for (let i = 0; i < limit; i++) {
const item = generatePlanItem(startIndex + i + 1)
// 状态筛选
if (status && item.order_status !== status) {
continue
}
// 关键词搜索(搜索产品名或客户名)
if (keyword) {
const searchKeyword = keyword.toLowerCase()
const productName = item.product_name.toLowerCase()
const customerName = item.customer_name.toLowerCase()
if (!productName.includes(searchKeyword) && !customerName.includes(searchKeyword)) {
continue
}
}
list.push(item)
}
console.log(`[Mock] planListAPI - 第${page}页,共${list.length}条,状态筛选:${status || '无'},关键词:"${keyword || '无'}"`)
return {
code: 1,
msg: 'success',
data: {
list,
total: totalPages * limit
}
}
}
// ============================================================================
// 导出统一 Mock API 调用器
// ============================================================================
......@@ -794,6 +939,8 @@ export async function mockAPI(apiName, params) {
return await mockFavoriteListAPI(params)
case 'feedbackListAPI':
return await mockFeedbackListAPI(params)
case 'planListAPI':
return await mockPlanListAPI(params)
default:
console.warn(`[Mock] 未知的 API: ${apiName}`)
return { code: 0, msg: 'Unknown API', data: null }
......