CategoryTreeView.vue 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. <script setup lang="ts">
  2. import { onMounted, ref } from 'vue'
  3. import CategoryTree from '../components/CategoryTree.vue'
  4. import { fetchCategoryTree } from '../api/category'
  5. import { fetchDemandBelongCategory } from '../api/demand'
  6. import type { CategoryNode } from '../types/category'
  7. import type { DemandsByCategory } from '../types/demand'
  8. import { groupDemandsByCategory } from '../types/demand'
  9. const nodes = ref<CategoryNode[]>([])
  10. const demandsByCategory = ref<DemandsByCategory>({})
  11. const loading = ref(true)
  12. const error = ref<string | null>(null)
  13. onMounted(async () => {
  14. try {
  15. const [tree, demands] = await Promise.all([
  16. fetchCategoryTree(),
  17. fetchDemandBelongCategory(),
  18. ])
  19. nodes.value = tree.nodes ?? []
  20. demandsByCategory.value = groupDemandsByCategory(demands.items ?? [])
  21. } catch (e) {
  22. error.value = e instanceof Error ? e.message : String(e)
  23. } finally {
  24. loading.value = false
  25. }
  26. })
  27. </script>
  28. <template>
  29. <div class="view">
  30. <div v-if="loading" class="state">正在加载分类树…</div>
  31. <div v-else-if="error" class="state error">{{ error }}</div>
  32. <CategoryTree
  33. v-else
  34. :nodes="nodes"
  35. :demands-by-category="demandsByCategory"
  36. />
  37. </div>
  38. </template>
  39. <style scoped>
  40. .view {
  41. height: 100%;
  42. min-height: 0;
  43. }
  44. .state {
  45. padding: 64px 24px;
  46. text-align: center;
  47. color: #64748b;
  48. font-size: 15px;
  49. }
  50. .state.error {
  51. color: #b91c1c;
  52. }
  53. </style>