feat(h5): 首页默认展示全部大类的材料种类,未选中时分组列出

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
caoqianming 2026-04-27 09:22:54 +08:00
parent a084f5c7e0
commit 1a0af18457
1 changed files with 38 additions and 19 deletions

View File

@ -1,5 +1,5 @@
<script setup>
import { ref, onMounted, watch } from 'vue'
import { ref, onMounted, computed, watch } from 'vue'
import { useRouter } from 'vue-router'
import MajorCategoryCard from '@/components/MajorCategoryCard.vue'
import CategoryCard from '@/components/CategoryCard.vue'
@ -21,14 +21,17 @@ const majors = [
]
const selected = ref(ui.selectedMajor)
const categories = ref([])
const categoriesByMajor = ref({})
const loading = ref(false)
const loadCategories = async (major) => {
if (!major) { categories.value = []; return }
const loadAll = async () => {
loading.value = true
try { categories.value = await fetchCategoriesByMajor(major) }
finally { loading.value = false }
try {
const results = await Promise.all(majors.map((m) => fetchCategoriesByMajor(m.value)))
const map = {}
majors.forEach((m, i) => { map[m.value] = results[i] })
categoriesByMajor.value = map
} finally { loading.value = false }
}
const onSelect = (v) => {
@ -36,13 +39,25 @@ const onSelect = (v) => {
ui.setMajor(selected.value)
}
watch(selected, loadCategories, { immediate: true })
const visibleGroups = computed(() => {
if (selected.value) {
return [{ major: majors.find((m) => m.value === selected.value), categories: categoriesByMajor.value[selected.value] || [] }]
}
return majors.map((m) => ({ major: m, categories: categoriesByMajor.value[m.value] || [] }))
})
watch(selected, (v) => {
if (v && !categoriesByMajor.value[v]) {
fetchCategoriesByMajor(v).then((r) => { categoriesByMajor.value = { ...categoriesByMajor.value, [v]: r } })
}
})
onMounted(async () => {
if (!auth.user) { try { await auth.loadUser() } catch {} }
await loadAll()
})
const goCategory = (c) => router.push({ name: 'CategoryDetail', params: { major: selected.value, category: c.value } })
const goCategory = (major, c) => router.push({ name: 'CategoryDetail', params: { major, category: c.value } })
const onLogout = () => { auth.logout(); router.replace('/login') }
</script>
@ -59,20 +74,24 @@ const onLogout = () => { auth.logout(); router.replace('/login') }
@click="onSelect(m.value)" />
</section>
<section class="px-4 pb-6">
<transition name="fade">
<div v-if="selected">
<div class="text-xs text-muted mb-2">细分种类</div>
<div v-if="loading" class="grid grid-cols-2 gap-3">
<Skeleton v-for="n in 4" :key="n" class="h-14" />
<section class="px-4 pb-6 space-y-5">
<div v-if="loading && !Object.keys(categoriesByMajor).length" class="grid grid-cols-2 gap-3">
<Skeleton v-for="n in 6" :key="n" class="h-14" />
</div>
<template v-else>
<div v-for="g in visibleGroups" :key="g.major.value">
<div class="flex items-center justify-between mb-2">
<div class="text-xs text-muted">{{ g.major.label }} · 材料种类</div>
<span class="text-[11px] text-muted tnum">{{ g.categories.length }} </span>
</div>
<div v-else-if="categories.length" class="grid grid-cols-2 gap-3">
<CategoryCard v-for="c in categories" :key="c.value" :value="c.value" :count="c.count" @click="goCategory(c)" />
<div v-if="g.categories.length" class="grid grid-cols-2 gap-3">
<CategoryCard v-for="c in g.categories" :key="c.value" :value="c.value" :count="c.count"
@click="goCategory(g.major.value, c)" />
</div>
<div v-else class="py-10 text-center text-sm text-muted">该大类暂无已审核材料</div>
<div v-else class="py-6 text-center text-xs text-muted bg-white rounded-card">暂无已审核材料</div>
</div>
<div v-else class="py-10 text-center text-sm text-muted">点击上方分类查看细分种类</div>
</transition>
</template>
</section>
</div>
</template>