hookehuyr

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

- 新增 mockPlanListAPI 函数支持分页、状态筛选、关键词搜索
- 集成 Mock 数据开关,开发环境自动启用
- 支持测试分页加载、状态筛选、关键词搜索、查看功能
- 数据结构完全符合 API 文档规范
...@@ -137,10 +137,14 @@ import { ref, nextTick } from 'vue' ...@@ -137,10 +137,14 @@ import { ref, nextTick } from 'vue'
137 import Taro, { useLoad, useReachBottom } from '@tarojs/taro' 137 import Taro, { useLoad, useReachBottom } from '@tarojs/taro'
138 import { useFileOperation } from '@/composables/useFileOperation' 138 import { useFileOperation } from '@/composables/useFileOperation'
139 import { listAPI, viewAPI, deleteAPI } from '@/api/plan' 139 import { listAPI, viewAPI, deleteAPI } from '@/api/plan'
140 +import { mockPlanListAPI } from '@/utils/mockData'
140 import NavHeader from '@/components/navigation/NavHeader.vue' 141 import NavHeader from '@/components/navigation/NavHeader.vue'
141 import ListItemActions from '@/components/list/ListItemActions/index.vue' 142 import ListItemActions from '@/components/list/ListItemActions/index.vue'
142 import SearchBar from '@/components/forms/SearchBar.vue' 143 import SearchBar from '@/components/forms/SearchBar.vue'
143 144
145 +// Mock 数据开关(开发环境使用 Mock,生产环境使用真实 API)
146 +const USE_MOCK_DATA = process.env.NODE_ENV === 'development'
147 +
144 const { viewFile } = useFileOperation() 148 const { viewFile } = useFileOperation()
145 149
146 const searchValue = ref('') 150 const searchValue = ref('')
...@@ -244,7 +248,7 @@ const transformApiItem = (apiItem) => { ...@@ -244,7 +248,7 @@ const transformApiItem = (apiItem) => {
244 } 248 }
245 249
246 /** 250 /**
247 - * 加载计划书列表(调用真实 API 251 + * 加载计划书列表(支持 Mock 数据
248 * @param {number} page - 页码(从0开始,API 要求) 252 * @param {number} page - 页码(从0开始,API 要求)
249 * @param {number} limit - 每页数量 253 * @param {number} limit - 每页数量
250 * @param {boolean} isLoadMore - 是否为加载更多 254 * @param {boolean} isLoadMore - 是否为加载更多
...@@ -271,6 +275,10 @@ const transformApiItem = (apiItem) => { ...@@ -271,6 +275,10 @@ const transformApiItem = (apiItem) => {
271 * - "5" = 处理中 275 * - "5" = 处理中
272 * - "7" = 已生成 276 * - "7" = 已生成
273 * - "9" = 已查看 277 * - "9" = 已查看
278 + *
279 + * 🔧 **Mock 数据说明**:
280 + * 开发环境会使用 Mock 数据测试分页、筛选、搜索功能
281 + * 生产环境使用真实 API
274 */ 282 */
275 const fetchPlanList = async (page = 0, limit = pageSize, isLoadMore = false) => { 283 const fetchPlanList = async (page = 0, limit = pageSize, isLoadMore = false) => {
276 try { 284 try {
...@@ -297,8 +305,10 @@ const fetchPlanList = async (page = 0, limit = pageSize, isLoadMore = false) => ...@@ -297,8 +305,10 @@ const fetchPlanList = async (page = 0, limit = pageSize, isLoadMore = false) =>
297 params.keyword = searchValue.value 305 params.keyword = searchValue.value
298 } 306 }
299 307
300 - // 调用 API 308 + // 🔧 根据环境选择使用 Mock 数据还是真实 API
301 - const res = await listAPI(params) 309 + const res = USE_MOCK_DATA
310 + ? await mockPlanListAPI(params)
311 + : await listAPI(params)
302 312
303 if (res.code === 1 && res.data) { 313 if (res.code === 1 && res.data) {
304 let apiList = res.data.list || [] 314 let apiList = res.data.list || []
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
10 * - myListAPI: 消息列表 10 * - myListAPI: 消息列表
11 * - favoriteListAPI: 收藏列表 11 * - favoriteListAPI: 收藏列表
12 * - feedbackListAPI: 意见反馈列表 12 * - feedbackListAPI: 意见反馈列表
13 + * - planListAPI: 计划书列表(新增)
13 */ 14 */
14 15
15 // ============================================================================ 16 // ============================================================================
...@@ -769,6 +770,150 @@ export async function mockFeedbackListAPI(params) { ...@@ -769,6 +770,150 @@ export async function mockFeedbackListAPI(params) {
769 } 770 }
770 771
771 // ============================================================================ 772 // ============================================================================
773 +// 8. 计划书列表 Mock (planListAPI)
774 +// ============================================================================
775 +
776 +const PLAN_PRODUCT_NAMES = [
777 + '终身寿险至尊版',
778 + '重疾险保障计划',
779 + '百万年金保险计划',
780 + '高端医疗险',
781 + '养老理财保险',
782 + '教育金保险计划',
783 + '意外伤害保险',
784 + '定期寿险',
785 + '终身寿险',
786 + '企业年金保险',
787 + '团体意外险',
788 + '健康保险计划'
789 +]
790 +
791 +const PLAN_STATUS = ['3', '5', '7', '9'] // 3=待处理, 5=处理中, 7=已生成, 9=已查看
792 +
793 +const PLAN_CATEGORIES = [
794 + { id: '1', name: '人寿保险' },
795 + { id: '2', name: '重疾险' },
796 + { id: '3', name: '医疗险' },
797 + { id: '4', name: '年金险' },
798 + { id: '5', name: '意外险' }
799 +]
800 +
801 +const CUSTOMER_NAMES = [
802 + '张三', '李四', '王五', '赵六', '钱七',
803 + '孙八', '周九', '吴十', '郑十一', '陈十二',
804 + '刘十三', '黄十四', '杨十五', '朱十六', '胡十七'
805 +]
806 +
807 +/**
808 + * 生成计划书列表项
809 + * @param {number} id - 计划书ID
810 + * @returns {Object} 计划书对象
811 + */
812 +function generatePlanItem(id) {
813 + const productName = PLAN_PRODUCT_NAMES[Math.floor(Math.random() * PLAN_PRODUCT_NAMES.length)]
814 + const customerName = CUSTOMER_NAMES[Math.floor(Math.random() * CUSTOMER_NAMES.length)]
815 + const orderStatus = PLAN_STATUS[Math.floor(Math.random() * PLAN_STATUS.length)]
816 + const category = PLAN_CATEGORIES[Math.floor(Math.random() * PLAN_CATEGORIES.length)]
817 +
818 + // 生成创建时间(最近30天内)
819 + const now = new Date()
820 + const createTime = new Date(now.getTime() - Math.random() * 30 * 24 * 60 * 60 * 1000)
821 +
822 + // 根据状态决定是否有计划书文件
823 + const hasFiles = orderStatus === '7' || orderStatus === '9' // 已生成或已查看才有文件
824 + const proposalFiles = []
825 +
826 + if (hasFiles) {
827 + // 生成1-3个计划书文件
828 + const fileCount = Math.floor(Math.random() * 3) + 1
829 + for (let i = 0; i < fileCount; i++) {
830 + proposalFiles.push({
831 + id: id * 10 + i,
832 + file_name: `${customerName}-${productName}-计划书.pdf`,
833 + file_url: `https://picsum.photos/seed/plan-${id}-${i}/400/300`
834 + })
835 + }
836 + }
837 +
838 + return {
839 + id: id,
840 + customer_name: customerName,
841 + product_name: productName,
842 + categories: [category],
843 + created_time: formatDate(createTime),
844 + order_status: orderStatus,
845 + proposal_files: proposalFiles
846 + }
847 +}
848 +
849 +/**
850 + * Mock: planListAPI (计划书列表)
851 + * @description 支持分页、状态筛选、关键词搜索
852 + * @param {Object} params - 请求参数
853 + * @param {number} params.page - 页码(从0开始)
854 + * @param {number} params.limit - 每页数量(默认20)
855 + * @param {string} [params.status] - 状态筛选(3=待处理, 5=处理中, 7=已生成, 9=已查看)
856 + * @param {string} [params.keyword] - 搜索关键字
857 + * @returns {Promise<Object>} Mock 响应
858 + */
859 +export async function mockPlanListAPI(params) {
860 + await mockDelay()
861 +
862 + const { page = 0, limit = 20, status, keyword } = params
863 + const totalPages = 10
864 +
865 + // 如果超过总页数,返回空列表
866 + if (page >= totalPages) {
867 + console.log(`[Mock] planListAPI - 第${page}页,共0条(已到最后一页)`)
868 + return {
869 + code: 1,
870 + msg: 'success',
871 + data: {
872 + list: [],
873 + total: totalPages * limit
874 + }
875 + }
876 + }
877 +
878 + const list = []
879 + const startIndex = page * limit
880 +
881 + // 生成数据并过滤
882 + for (let i = 0; i < limit; i++) {
883 + const item = generatePlanItem(startIndex + i + 1)
884 +
885 + // 状态筛选
886 + if (status && item.order_status !== status) {
887 + continue
888 + }
889 +
890 + // 关键词搜索(搜索产品名或客户名)
891 + if (keyword) {
892 + const searchKeyword = keyword.toLowerCase()
893 + const productName = item.product_name.toLowerCase()
894 + const customerName = item.customer_name.toLowerCase()
895 +
896 + if (!productName.includes(searchKeyword) && !customerName.includes(searchKeyword)) {
897 + continue
898 + }
899 + }
900 +
901 + list.push(item)
902 + }
903 +
904 + console.log(`[Mock] planListAPI - 第${page}页,共${list.length}条,状态筛选:${status || '无'},关键词:"${keyword || '无'}"`)
905 +
906 + return {
907 + code: 1,
908 + msg: 'success',
909 + data: {
910 + list,
911 + total: totalPages * limit
912 + }
913 + }
914 +}
915 +
916 +// ============================================================================
772 // 导出统一 Mock API 调用器 917 // 导出统一 Mock API 调用器
773 // ============================================================================ 918 // ============================================================================
774 919
...@@ -794,6 +939,8 @@ export async function mockAPI(apiName, params) { ...@@ -794,6 +939,8 @@ export async function mockAPI(apiName, params) {
794 return await mockFavoriteListAPI(params) 939 return await mockFavoriteListAPI(params)
795 case 'feedbackListAPI': 940 case 'feedbackListAPI':
796 return await mockFeedbackListAPI(params) 941 return await mockFeedbackListAPI(params)
942 + case 'planListAPI':
943 + return await mockPlanListAPI(params)
797 default: 944 default:
798 console.warn(`[Mock] 未知的 API: ${apiName}`) 945 console.warn(`[Mock] 未知的 API: ${apiName}`)
799 return { code: 0, msg: 'Unknown API', data: null } 946 return { code: 0, msg: 'Unknown API', data: null }
......