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>
Showing
1 changed file
with
59 additions
and
10 deletions
| ... | @@ -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 | /** | ... | ... |
-
Please register or login to post a comment