hookehuyr

feat(material-list): 添加动态分类支持

- 新增 hasCategories 状态,支持有/无分类两种模式
- 新增 fetchCategoriesFromBackend 函数,模拟后端分类数据
- 优化 initTabsData 函数,自动选中第一个分类(有分类时)
- 动态显示 Tabs(仅在有分类时显示)
- 无分类时直接显示全部资料列表

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
18 18
19 <!-- Tabs Container --> 19 <!-- Tabs Container -->
20 <view class="flex-1 min-h-0 flex flex-col"> 20 <view class="flex-1 min-h-0 flex flex-col">
21 - <nut-tabs v-model="activeTabId"> 21 + <!-- 动态显示 Tabs(仅在有分类时显示) -->
22 + <nut-tabs v-if="hasCategories" v-model="activeTabId">
22 <!-- 自定义标签栏 --> 23 <!-- 自定义标签栏 -->
23 <template #titles> 24 <template #titles>
24 <view class="filter-tabs-wrapper"> 25 <view class="filter-tabs-wrapper">
...@@ -114,6 +115,12 @@ const listVisible = ref(true) ...@@ -114,6 +115,12 @@ const listVisible = ref(true)
114 const listRenderKey = ref(0) 115 const listRenderKey = ref(0)
115 116
116 /** 117 /**
118 + * 是否有分类标签
119 + * @description 随机模拟后端返回数据,50% 概率有分类
120 + */
121 +const hasCategories = ref(false)
122 +
123 +/**
117 * 页面标题 124 * 页面标题
118 */ 125 */
119 const pageTitle = ref('资料列表') 126 const pageTitle = ref('资料列表')
...@@ -289,19 +296,45 @@ const allList = ref([ ...@@ -289,19 +296,45 @@ const allList = ref([
289 * 296 *
290 * @description 包含分类信息和对应的资料列表 297 * @description 包含分类信息和对应的资料列表
291 */ 298 */
292 -const tabsData = ref([ 299 +const tabsData = ref([])
300 +
301 +/**
302 + * 模拟后端返回的分类数据
303 + * @description 根据随机结果决定是否返回分类数据
304 + */
305 +const fetchCategoriesFromBackend = () => {
306 + // 模拟 50% 概率有分类
307 + const hasCat = Math.random() > 0.5
308 + hasCategories.value = hasCat
309 +
310 + console.log('[Material List] 模拟后端返回分类数据:', hasCat ? '有分类' : '无分类')
311 +
312 + if (hasCat) {
313 + // 有分类:返回分类列表
314 + return [
293 { id: '', name: '全部资料', list: [] }, 315 { id: '', name: '全部资料', list: [] },
294 { id: 'exam', name: '考试资料', list: [] }, 316 { id: 'exam', name: '考试资料', list: [] },
295 { id: 'product', name: '产品手册', list: [] }, 317 { id: 'product', name: '产品手册', list: [] },
296 { id: 'training', name: '培训材料', list: [] }, 318 { id: 'training', name: '培训材料', list: [] },
297 { id: 'case', name: '案例分享', list: [] }, 319 { id: 'case', name: '案例分享', list: [] },
298 -]) 320 + ]
321 + } else {
322 + // 无分类:只返回"全部资料"一个占位分类(用于数据管理)
323 + return [
324 + { id: '', name: '全部资料', list: [] }
325 + ]
326 + }
327 +}
299 328
300 /** 329 /**
301 * 初始化数据分布 330 * 初始化数据分布
302 * @description 根据分类规则将 allList 中的数据分配到各个 tab 中 331 * @description 根据分类规则将 allList 中的数据分配到各个 tab 中
303 */ 332 */
304 const initTabsData = () => { 333 const initTabsData = () => {
334 + // 1. 先获取后端返回的分类数据
335 + tabsData.value = fetchCategoriesFromBackend()
336 +
337 + // 2. 根据分类分配数据
305 tabsData.value.forEach((tab, index) => { 338 tabsData.value.forEach((tab, index) => {
306 if (tab.id === '') { 339 if (tab.id === '') {
307 tab.list = [...allList.value] 340 tab.list = [...allList.value]
...@@ -311,6 +344,16 @@ const initTabsData = () => { ...@@ -311,6 +344,16 @@ const initTabsData = () => {
311 tab.list = allList.value.filter((_, i) => (i + index) % (index + 2) === 0) 344 tab.list = allList.value.filter((_, i) => (i + index) % (index + 2) === 0)
312 } 345 }
313 }) 346 })
347 +
348 + // 3. 如果有分类,默认选中第一个 tab
349 + if (hasCategories.value && tabsData.value.length > 0) {
350 + activeTabId.value = tabsData.value[0].id
351 + console.log('[Material List] 自动选中第一个分类:', tabsData.value[0].name)
352 + } else {
353 + // 无分类时,activeTabId 设为空字符串(匹配"全部资料")
354 + activeTabId.value = ''
355 + console.log('[Material List] 无分类模式,显示全部资料')
356 + }
314 } 357 }
315 358
316 /** 359 /**
...@@ -342,16 +385,22 @@ useLoad((options) => { ...@@ -342,16 +385,22 @@ useLoad((options) => {
342 pageTitle.value = options.title 385 pageTitle.value = options.title
343 } 386 }
344 387
345 - if (options.categoryId) { 388 + // 初始化数据(会自动设置 activeTabId)
346 - activeTabId.value = options.categoryId 389 + initTabsData()
347 - console.log('[Material List] 初始分类:', activeTabId.value)
348 390
349 - // 如果有特定的加载逻辑,可以在这里调用 391 + // 如果后端有返回特定的分类 ID,可以覆盖默认选择
350 - // loadMaterialsByCategory(activeTabId.value) 392 + if (options.categoryId && hasCategories.value) {
393 + // 检查该 categoryId 是否存在于 tabsData 中
394 + const tabExists = tabsData.value.some(tab => tab.id === options.categoryId)
395 + if (tabExists) {
396 + activeTabId.value = options.categoryId
397 + console.log('[Material List] 使用页面参数的分类:', activeTabId.value)
398 + } else {
399 + console.warn('[Material List] 页面指定的分类不存在,使用默认分类')
400 + }
351 } 401 }
352 402
353 - // 初始化数据 403 + console.log('[Material List] 最终状态 - 有分类:', hasCategories.value, '当前选中:', activeTabId.value)
354 - initTabsData()
355 }) 404 })
356 405
357 /** 406 /**
......