index.vue
5.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
<template>
<div class="min-h-screen bg-[#f9fafb] pb-[calc(160rpx+env(safe-area-inset-bottom))]">
<!-- Navigation Header -->
<NavHeader :title="pageTitle" />
<!-- Loading State -->
<div v-if="loading" class="px-[40rpx] mt-[80rpx] flex items-center justify-center">
<text class="text-[#9CA3AF] text-[28rpx]">加载中...</text>
</div>
<!-- Content List -->
<div v-else-if="sections.length > 0" class="px-[40rpx] mt-[40rpx] relative z-10">
<SectionCard
v-for="(section, index) in sections"
:key="index"
:title="section.title"
:items="section.items"
@item-click="handleItemClick"
/>
</div>
<!-- Empty State -->
<div v-else class="px-[40rpx] mt-[80rpx] flex items-center justify-center">
<!-- <text class="text-[#9CA3AF] text-[28rpx]">暂无分类</text> -->
<nut-empty description="暂无分类" image="empty" />
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
import { useLoad } from '@tarojs/taro'
import NavHeader from '@/components/NavHeader.vue'
import SectionCard from '@/components/SectionCard.vue'
import { fileListAPI } from '@/api/file'
import { useGo } from '@/hooks/useGo'
import Taro from '@tarojs/taro'
const go = useGo()
/**
* 页面状态
*/
const loading = ref(false)
const data = ref({})
/**
* 页面标题
*/
const pageTitle = ref('分类列表')
/**
* 最大层级
*/
const maxLevel = computed(() => data.value?.max_level || 0)
/**
* 将 API 返回的 children 数据转换为 SectionCard 需要的格式
* @description 将嵌套的 children 数组转换为 sections 格式
*
* 数据结构:
* - 第一层(大标题):level=1,如"入职前"、"入职中"、"入职后"
* - 第二层(小标题):level=2,如"考试报名"、"资格考试报名入口"
*
* @returns {Array<{title: string, items: Array}>}
*/
const sections = computed(() => {
const children = data.value?.children || []
if (children.length === 0) {
return []
}
// 为每个第一层分类创建一个 section
return children.map(level1Category => ({
title: level1Category.category_name, // 大标题:"入职前"
items: (level1Category.children || []).map(level2Category => ({
id: level2Category.id,
title: level2Category.category_name, // 小标题:"考试报名"
subtitle: level2Category.list?.length ? `${level2Category.list.length} 个文件` : '',
icon: level2Category.icon || '',
level: level2Category.level,
maxDepth: level2Category.max_depth,
// 保留原始数据供点击事件使用
_raw: level2Category
}))
}))
})
/**
* 获取文档分类列表
* @param {Object} options - 页面参数
* @param {string} options.cid - 分类ID(首次进入)
* @param {string} options.id - 子分类ID(后续层级)
* @param {string} options.title - 页面标题
*/
const fetchCategoryList = async (options) => {
try {
loading.value = true
// 构建请求参数
const params = {}
if (options.cid) {
params.cid = options.cid // 首次进入使用 cid
} else if (options.id) {
params.cid = options.id // 后续层级使用 id
}
console.log('[Category List] 请求参数:', params)
// 调用接口(直接调用,不使用 fn() 包装)
const res = await fileListAPI(params)
if (res.code === 1 && res.data) {
data.value = res.data
// console.log('[Category List] 分类数据:', res.data)
// console.log('[Category List] 最大层级:', maxLevel.value)
// console.log('[Category List] 转换后的 sections:', JSON.stringify(sections.value, null, 2))
} else {
Taro.showToast({
title: res.msg || '获取分类列表失败',
icon: 'none',
duration: 2000
})
}
} catch (error) {
console.error('[Category List] 获取分类列表失败:', error)
throw error
} finally {
loading.value = false
}
}
/**
* 处理分类点击事件
* @description 根据该分类的层级和是否有子分类决定跳转
*
* 数据结构说明:
* - level=1: 第一层(大标题),如"入职前"、"入职中"、"入职后"
* - level=2: 第二层(小标题),如"考试报名"、"资格考试报名入口"
* - max_level: 总的最大层级数
* - max_depth: 当前分支的最大深度
*
* 跳转规则:
* - 如果当前是第二层(level=2),直接跳转到 material-list(最终层)
* - category-list 只显示两层结构
*
* @param {Object} item - 被点击的项目数据(第二层分类)
*/
const handleItemClickWithNav = (item, go) => {
console.log('[Category List] 点击分类:', item)
console.log('[Category List] 分类层级:', item.level)
console.log('[Category List] 最大深度:', item.maxDepth)
// 当前点击的是第二层(level=2),直接跳转到文档列表
console.log('[Category List] 跳转到文档列表')
go('/pages/material-list/index', {
id: item.id,
title: item.title
})
}
// 导出 handleItemClick 供 SectionCard 使用
const handleItemClick = (item) => handleItemClickWithNav(item, go)
/**
* 页面加载时接收参数并初始化
*/
useLoad((options) => {
console.log('[Category List] 页面参数:', options)
// 设置页面标题
if (options.title) {
pageTitle.value = options.title
}
// 获取分类列表
fetchCategoryList(options)
})
</script>
<script>
export default {
name: 'CategoryListIndex'
}
</script>