feat: use community categories for topic navigation

This commit is contained in:
hajimi
2026-08-02 18:44:35 +08:00
parent 75b003619b
commit 3c2dddd6d1
3 changed files with 73 additions and 35 deletions
+5
View File
@@ -57,6 +57,11 @@ export function getTagLists() {
return request.get({ url: '/community/tagLists' })
}
// 社区分类列表
export function getCommunityCategoryLists() {
return request.get({ url: '/community/categoryLists' })
}
// 社区用户统计(积分、关注等)
export function getCommunityUserStats() {
return request.get({ url: '/community/userStats' })
+54 -34
View File
@@ -31,11 +31,12 @@
<view class="community-topics">
<scroll-view scroll-x class="community-topics__scroll" :show-scrollbar="false">
<view class="community-topics__list">
<view v-for="tag in displayTags" :key="tag.id" class="community-topic"
:class="{ 'community-topic--active': activeTagId === tag.id }" @tap="selectTag(tag)">
<image class="community-topic__icon-image" :src="tag.icon || DEFAULT_TOPIC_ICON" mode="aspectFill"
@error="handleTopicIconError(tag)" />
<text>{{ tag.name }}</text>
<view v-for="category in displayCategories" :key="category.id" class="community-topic"
:class="{ 'community-topic--active': activeCategoryId === category.id }"
@tap="selectCategory(category)">
<image class="community-topic__icon-image" :src="category.icon || DEFAULT_TOPIC_ICON"
mode="aspectFill" @error="handleTopicIconError(category)" />
<text>{{ category.name }}</text>
</view>
</view>
</scroll-view>
@@ -47,7 +48,7 @@
<text class="community-list__eyebrow">SPORTS COMMUNITY</text>
<text class="community-list__title">{{ feedTitle }}</text>
</view>
<text v-if="activeTagName" class="community-list__selected"># {{ activeTagName }}</text>
<text v-if="activeCategoryName" class="community-list__selected">{{ activeCategoryName }}</text>
</view>
<view v-if="loading && postList.length === 0" class="community-loading">
@@ -83,7 +84,13 @@
<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { getCommunityPosts, getCommunityUserStats, getTagLists, purchasePost, toggleLike } from '@/api/community'
import {
getCommunityCategoryLists,
getCommunityPosts,
getCommunityUserStats,
purchasePost,
toggleLike
} from '@/api/community'
import { useUserStore } from '@/stores/user'
import { getToken } from '@/utils/auth'
import AiAssistantEntry from '@/components/ai-assistant-entry/ai-assistant-entry.vue'
@@ -92,11 +99,12 @@ import PostCard from '@/packages_community/components/post-card.vue'
type FeedKey = 'recommend' | 'follow' | 'hot' | 'topic'
const userStore = useUserStore()
const COMMUNITY_ACTIVE_TAG_KEY = 'community_active_tag'
const COMMUNITY_ACTIVE_CATEGORY_KEY = 'community_active_category'
const LEGACY_COMMUNITY_ACTIVE_TAG_KEY = 'community_active_tag'
const statusBarHeight = ref(0)
const activeFeed = ref<FeedKey>('recommend')
const activeTagId = ref(0)
const tagList = ref<any[]>([])
const activeCategoryId = ref(0)
const categoryList = ref<any[]>([])
const postList = ref<any[]>([])
const userPoints = ref<number | null>(null)
const loading = ref(false)
@@ -118,22 +126,26 @@ const feedTabs: Array<{ key: FeedKey; label: string }> = [
const isLogin = computed(() => userStore.isLogin)
const userPointsText = computed(() => (isLogin.value ? String(userPoints.value ?? 0) : '登录'))
const feedTitle = computed(() => ({ recommend: '精选讨论', follow: '关注动态', hot: '热门话题', topic: '话题广场' }[activeFeed.value]))
const activeTagName = computed(() => tagList.value.find((tag) => tag.id === activeTagId.value)?.name || '')
const activeCategoryName = computed(() => categoryList.value.find(
(category) => category.id === activeCategoryId.value
)?.name || '')
const displayTags = computed(() => {
return tagList.value.map((tag) => ({
...tag,
icon: typeof tag.icon === 'string' ? tag.icon.trim() : ''
const displayCategories = computed(() => {
return categoryList.value.map((category) => ({
...category,
icon: typeof category.icon === 'string' ? category.icon.trim() : ''
}))
})
const handleTopicIconError = (tag: any) => {
tag.icon = DEFAULT_TOPIC_ICON
const handleTopicIconError = (category: any) => {
category.icon = DEFAULT_TOPIC_ICON
}
const getSavedActiveTag = () => {
const tagId = Number(uni.getStorageSync(COMMUNITY_ACTIVE_TAG_KEY))
return Number.isFinite(tagId) && tagId > 0 ? tagId : 0
const getSavedActiveCategory = () => {
const savedValue = uni.getStorageSync(COMMUNITY_ACTIVE_CATEGORY_KEY)
|| uni.getStorageSync(LEGACY_COMMUNITY_ACTIVE_TAG_KEY)
const categoryId = Number(savedValue)
return Number.isFinite(categoryId) && categoryId > 0 ? categoryId : 0
}
const goSearch = () => uni.navigateTo({ url: '/pages/search/search' })
@@ -159,14 +171,22 @@ const loadUserPoints = async () => {
}
}
const fetchTags = async () => {
const fetchCategories = async () => {
try {
tagList.value = (await getTagLists()) || []
if (activeTagId.value && !tagList.value.some((tag) => tag.id === activeTagId.value)) {
activeTagId.value = 0
categoryList.value = (await getCommunityCategoryLists()) || []
if (activeCategoryId.value && !categoryList.value.some(
(category) => category.id === activeCategoryId.value
)) {
activeCategoryId.value = 0
uni.removeStorageSync(COMMUNITY_ACTIVE_CATEGORY_KEY)
uni.removeStorageSync(LEGACY_COMMUNITY_ACTIVE_TAG_KEY)
if (activeFeed.value === 'topic') fetchPosts(true)
} else if (activeCategoryId.value) {
uni.setStorageSync(COMMUNITY_ACTIVE_CATEGORY_KEY, activeCategoryId.value)
uni.removeStorageSync(LEGACY_COMMUNITY_ACTIVE_TAG_KEY)
}
} catch (_error) {
tagList.value = []
categoryList.value = []
}
}
@@ -196,7 +216,7 @@ const fetchPosts = async (reset = false) => {
if (activeFeed.value === 'follow') params.follow = 1
if (activeFeed.value === 'hot') params.is_hot = 1
if (activeFeed.value === 'topic') params.is_topic = 1
if (activeTagId.value > 0) params.tag_id = activeTagId.value
if (activeCategoryId.value > 0) params.category_id = activeCategoryId.value
const response = await getCommunityPosts(params)
const rawList = response?.lists || []
if (requestId !== fetchRequestId.value) return
@@ -226,16 +246,16 @@ const switchFeed = (feed: FeedKey) => {
})
return
}
if (activeFeed.value === feed && (feed !== 'topic' || activeTagId.value === 0)) return
if (activeFeed.value === feed && (feed !== 'topic' || activeCategoryId.value === 0)) return
activeFeed.value = feed
if (feed !== 'topic') activeTagId.value = 0
if (feed !== 'topic') activeCategoryId.value = 0
fetchPosts(true)
}
const selectTag = (tag: any) => {
const selectCategory = (category: any) => {
activeFeed.value = 'topic'
activeTagId.value = tag.id
uni.setStorageSync(COMMUNITY_ACTIVE_TAG_KEY, tag.id)
activeCategoryId.value = category.id
uni.setStorageSync(COMMUNITY_ACTIVE_CATEGORY_KEY, category.id)
fetchPosts(true)
}
@@ -328,9 +348,9 @@ onMounted(() => {
// #ifdef APP-PLUS || MP
statusBarHeight.value = systemInfo.statusBarHeight || 44
// #endif
activeTagId.value = getSavedActiveTag()
if (activeTagId.value) activeFeed.value = 'topic'
fetchTags()
activeCategoryId.value = getSavedActiveCategory()
if (activeCategoryId.value) activeFeed.value = 'topic'
fetchCategories()
fetchPosts(true)
loadUserPoints()
})