feat: use community categories for topic navigation
This commit is contained in:
@@ -7,6 +7,7 @@ use app\common\model\community\CommunityPost;
|
|||||||
use app\common\model\community\CommunityComment;
|
use app\common\model\community\CommunityComment;
|
||||||
use app\common\model\community\CommunityLike;
|
use app\common\model\community\CommunityLike;
|
||||||
use app\common\model\community\CommunityFollow;
|
use app\common\model\community\CommunityFollow;
|
||||||
|
use app\common\model\community\CommunityCategory;
|
||||||
use app\common\model\community\CommunityTag;
|
use app\common\model\community\CommunityTag;
|
||||||
use app\common\model\user\User;
|
use app\common\model\user\User;
|
||||||
use app\common\model\ai\AiAnalysis;
|
use app\common\model\ai\AiAnalysis;
|
||||||
@@ -24,7 +25,7 @@ class CommunityController extends BaseApiController
|
|||||||
{
|
{
|
||||||
private const LIUHE_TAGS = ['旧澳六合', '新澳六合'];
|
private const LIUHE_TAGS = ['旧澳六合', '新澳六合'];
|
||||||
|
|
||||||
public array $notNeedLogin = ['postLists', 'postDetail', 'commentLists', 'tagLists', 'userProfile', 'followList', 'fansList'];
|
public array $notNeedLogin = ['postLists', 'postDetail', 'commentLists', 'tagLists', 'categoryLists', 'userProfile', 'followList', 'fansList'];
|
||||||
|
|
||||||
// 帖子列表
|
// 帖子列表
|
||||||
public function postLists()
|
public function postLists()
|
||||||
@@ -423,6 +424,18 @@ class CommunityController extends BaseApiController
|
|||||||
return $this->data($list);
|
return $this->data($list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 分类列表
|
||||||
|
public function categoryLists()
|
||||||
|
{
|
||||||
|
$list = CommunityCategory::where('status', 1)
|
||||||
|
->order('sort desc')
|
||||||
|
->order('id desc')
|
||||||
|
->field('id,name,icon,post_count')
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
return $this->data($list);
|
||||||
|
}
|
||||||
|
|
||||||
// 购买帖子
|
// 购买帖子
|
||||||
// confirm=0 探测是否已购买;confirm=1 确认扣分购买
|
// confirm=0 探测是否已购买;confirm=1 确认扣分购买
|
||||||
public function purchasePost()
|
public function purchasePost()
|
||||||
|
|||||||
@@ -57,6 +57,11 @@ export function getTagLists() {
|
|||||||
return request.get({ url: '/community/tagLists' })
|
return request.get({ url: '/community/tagLists' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 社区分类列表
|
||||||
|
export function getCommunityCategoryLists() {
|
||||||
|
return request.get({ url: '/community/categoryLists' })
|
||||||
|
}
|
||||||
|
|
||||||
// 社区用户统计(积分、关注等)
|
// 社区用户统计(积分、关注等)
|
||||||
export function getCommunityUserStats() {
|
export function getCommunityUserStats() {
|
||||||
return request.get({ url: '/community/userStats' })
|
return request.get({ url: '/community/userStats' })
|
||||||
|
|||||||
@@ -31,11 +31,12 @@
|
|||||||
<view class="community-topics">
|
<view class="community-topics">
|
||||||
<scroll-view scroll-x class="community-topics__scroll" :show-scrollbar="false">
|
<scroll-view scroll-x class="community-topics__scroll" :show-scrollbar="false">
|
||||||
<view class="community-topics__list">
|
<view class="community-topics__list">
|
||||||
<view v-for="tag in displayTags" :key="tag.id" class="community-topic"
|
<view v-for="category in displayCategories" :key="category.id" class="community-topic"
|
||||||
:class="{ 'community-topic--active': activeTagId === tag.id }" @tap="selectTag(tag)">
|
:class="{ 'community-topic--active': activeCategoryId === category.id }"
|
||||||
<image class="community-topic__icon-image" :src="tag.icon || DEFAULT_TOPIC_ICON" mode="aspectFill"
|
@tap="selectCategory(category)">
|
||||||
@error="handleTopicIconError(tag)" />
|
<image class="community-topic__icon-image" :src="category.icon || DEFAULT_TOPIC_ICON"
|
||||||
<text>{{ tag.name }}</text>
|
mode="aspectFill" @error="handleTopicIconError(category)" />
|
||||||
|
<text>{{ category.name }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
@@ -47,7 +48,7 @@
|
|||||||
<text class="community-list__eyebrow">SPORTS COMMUNITY</text>
|
<text class="community-list__eyebrow">SPORTS COMMUNITY</text>
|
||||||
<text class="community-list__title">{{ feedTitle }}</text>
|
<text class="community-list__title">{{ feedTitle }}</text>
|
||||||
</view>
|
</view>
|
||||||
<text v-if="activeTagName" class="community-list__selected"># {{ activeTagName }}</text>
|
<text v-if="activeCategoryName" class="community-list__selected">{{ activeCategoryName }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="loading && postList.length === 0" class="community-loading">
|
<view v-if="loading && postList.length === 0" class="community-loading">
|
||||||
@@ -83,7 +84,13 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { onShow } from '@dcloudio/uni-app'
|
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 { useUserStore } from '@/stores/user'
|
||||||
import { getToken } from '@/utils/auth'
|
import { getToken } from '@/utils/auth'
|
||||||
import AiAssistantEntry from '@/components/ai-assistant-entry/ai-assistant-entry.vue'
|
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'
|
type FeedKey = 'recommend' | 'follow' | 'hot' | 'topic'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
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 statusBarHeight = ref(0)
|
||||||
const activeFeed = ref<FeedKey>('recommend')
|
const activeFeed = ref<FeedKey>('recommend')
|
||||||
const activeTagId = ref(0)
|
const activeCategoryId = ref(0)
|
||||||
const tagList = ref<any[]>([])
|
const categoryList = ref<any[]>([])
|
||||||
const postList = ref<any[]>([])
|
const postList = ref<any[]>([])
|
||||||
const userPoints = ref<number | null>(null)
|
const userPoints = ref<number | null>(null)
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
@@ -118,22 +126,26 @@ const feedTabs: Array<{ key: FeedKey; label: string }> = [
|
|||||||
const isLogin = computed(() => userStore.isLogin)
|
const isLogin = computed(() => userStore.isLogin)
|
||||||
const userPointsText = computed(() => (isLogin.value ? String(userPoints.value ?? 0) : '登录'))
|
const userPointsText = computed(() => (isLogin.value ? String(userPoints.value ?? 0) : '登录'))
|
||||||
const feedTitle = computed(() => ({ recommend: '精选讨论', follow: '关注动态', hot: '热门话题', topic: '话题广场' }[activeFeed.value]))
|
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(() => {
|
const displayCategories = computed(() => {
|
||||||
return tagList.value.map((tag) => ({
|
return categoryList.value.map((category) => ({
|
||||||
...tag,
|
...category,
|
||||||
icon: typeof tag.icon === 'string' ? tag.icon.trim() : ''
|
icon: typeof category.icon === 'string' ? category.icon.trim() : ''
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleTopicIconError = (tag: any) => {
|
const handleTopicIconError = (category: any) => {
|
||||||
tag.icon = DEFAULT_TOPIC_ICON
|
category.icon = DEFAULT_TOPIC_ICON
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSavedActiveTag = () => {
|
const getSavedActiveCategory = () => {
|
||||||
const tagId = Number(uni.getStorageSync(COMMUNITY_ACTIVE_TAG_KEY))
|
const savedValue = uni.getStorageSync(COMMUNITY_ACTIVE_CATEGORY_KEY)
|
||||||
return Number.isFinite(tagId) && tagId > 0 ? tagId : 0
|
|| 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' })
|
const goSearch = () => uni.navigateTo({ url: '/pages/search/search' })
|
||||||
@@ -159,14 +171,22 @@ const loadUserPoints = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchTags = async () => {
|
const fetchCategories = async () => {
|
||||||
try {
|
try {
|
||||||
tagList.value = (await getTagLists()) || []
|
categoryList.value = (await getCommunityCategoryLists()) || []
|
||||||
if (activeTagId.value && !tagList.value.some((tag) => tag.id === activeTagId.value)) {
|
if (activeCategoryId.value && !categoryList.value.some(
|
||||||
activeTagId.value = 0
|
(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) {
|
} 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 === 'follow') params.follow = 1
|
||||||
if (activeFeed.value === 'hot') params.is_hot = 1
|
if (activeFeed.value === 'hot') params.is_hot = 1
|
||||||
if (activeFeed.value === 'topic') params.is_topic = 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 response = await getCommunityPosts(params)
|
||||||
const rawList = response?.lists || []
|
const rawList = response?.lists || []
|
||||||
if (requestId !== fetchRequestId.value) return
|
if (requestId !== fetchRequestId.value) return
|
||||||
@@ -226,16 +246,16 @@ const switchFeed = (feed: FeedKey) => {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (activeFeed.value === feed && (feed !== 'topic' || activeTagId.value === 0)) return
|
if (activeFeed.value === feed && (feed !== 'topic' || activeCategoryId.value === 0)) return
|
||||||
activeFeed.value = feed
|
activeFeed.value = feed
|
||||||
if (feed !== 'topic') activeTagId.value = 0
|
if (feed !== 'topic') activeCategoryId.value = 0
|
||||||
fetchPosts(true)
|
fetchPosts(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectTag = (tag: any) => {
|
const selectCategory = (category: any) => {
|
||||||
activeFeed.value = 'topic'
|
activeFeed.value = 'topic'
|
||||||
activeTagId.value = tag.id
|
activeCategoryId.value = category.id
|
||||||
uni.setStorageSync(COMMUNITY_ACTIVE_TAG_KEY, tag.id)
|
uni.setStorageSync(COMMUNITY_ACTIVE_CATEGORY_KEY, category.id)
|
||||||
fetchPosts(true)
|
fetchPosts(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,9 +348,9 @@ onMounted(() => {
|
|||||||
// #ifdef APP-PLUS || MP
|
// #ifdef APP-PLUS || MP
|
||||||
statusBarHeight.value = systemInfo.statusBarHeight || 44
|
statusBarHeight.value = systemInfo.statusBarHeight || 44
|
||||||
// #endif
|
// #endif
|
||||||
activeTagId.value = getSavedActiveTag()
|
activeCategoryId.value = getSavedActiveCategory()
|
||||||
if (activeTagId.value) activeFeed.value = 'topic'
|
if (activeCategoryId.value) activeFeed.value = 'topic'
|
||||||
fetchTags()
|
fetchCategories()
|
||||||
fetchPosts(true)
|
fetchPosts(true)
|
||||||
loadUserPoints()
|
loadUserPoints()
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user