This commit is contained in:
@@ -50,9 +50,11 @@ export const wechatLogin = (code: string) => request({ url: '/wechat/login/', me
|
||||
// Forum / Community
|
||||
export const getTopics = (params: any) => request({ url: '/community/topics/', data: params })
|
||||
export const getTopicDetail = (id: number) => request({ url: `/community/topics/${id}/` })
|
||||
export const likeTopic = (id: number) => request({ url: `/community/topics/${id}/like/`, method: 'POST' })
|
||||
export const createTopic = (data: any) => request({ url: '/community/topics/', method: 'POST', data })
|
||||
export const updateTopic = (id: number, data: any) => request({ url: `/community/topics/${id}/`, method: 'PATCH', data })
|
||||
export const getReplies = (params: any) => request({ url: '/community/replies/', data: params })
|
||||
export const likeReply = (id: number) => request({ url: `/community/replies/${id}/like/`, method: 'POST' })
|
||||
export const createReply = (data: any) => request({ url: '/community/replies/', method: 'POST', data })
|
||||
export const updateReply = (id: number, data: any) => request({ url: `/community/replies/${id}/`, method: 'PATCH', data })
|
||||
export const deleteReply = (id: number) => request({ url: `/community/replies/${id}/`, method: 'DELETE' })
|
||||
|
||||
@@ -310,6 +310,10 @@ const ForumList = () => {
|
||||
<AtIcon value='eye' size='14' color='#777' />
|
||||
<Text>{item.view_count || 0}</Text>
|
||||
</View>
|
||||
<View className='stat-item'>
|
||||
<AtIcon value='heart' size='14' color='#777' />
|
||||
<Text>{item.like_count || 0}</Text>
|
||||
</View>
|
||||
<View className='stat-item'>
|
||||
<AtIcon value='message' size='14' color='#777' />
|
||||
<Text>{item.replies?.length || 0}</Text>
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'
|
||||
import Taro, { useRouter, useShareAppMessage, useShareTimeline, useDidShow } from '@tarojs/taro'
|
||||
import { View, Text, Image, Video, Input, ScrollView } from '@tarojs/components'
|
||||
import { AtActivityIndicator, AtIcon, AtActionSheet, AtActionSheetItem, AtFloatLayout } from 'taro-ui'
|
||||
import { getTopicDetail, createReply, uploadMedia, getStarUsers } from '../../../api'
|
||||
import { getTopicDetail, createReply, uploadMedia, getStarUsers, likeTopic, likeReply } from '../../../api'
|
||||
import MarkdownReader from '../../../components/MarkdownReader'
|
||||
import './detail.scss'
|
||||
|
||||
@@ -70,6 +70,48 @@ const ForumDetail = () => {
|
||||
setShowStarUsers(false)
|
||||
}
|
||||
|
||||
const handleLikeTopic = async () => {
|
||||
const token = Taro.getStorageSync('token')
|
||||
if (!token) {
|
||||
Taro.showToast({ title: '请先登录', icon: 'none' })
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await likeTopic(topic.id)
|
||||
const data = res.data || res
|
||||
setTopic(prev => ({
|
||||
...prev,
|
||||
is_liked: data.liked,
|
||||
like_count: data.count
|
||||
}))
|
||||
} catch (error) {
|
||||
Taro.showToast({ title: '操作失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
const handleLikeReply = async (replyId) => {
|
||||
const token = Taro.getStorageSync('token')
|
||||
if (!token) {
|
||||
Taro.showToast({ title: '请先登录', icon: 'none' })
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await likeReply(replyId)
|
||||
const data = res.data || res
|
||||
setTopic(prev => ({
|
||||
...prev,
|
||||
replies: prev.replies.map(r => {
|
||||
if (r.id === replyId) {
|
||||
return { ...r, is_liked: data.liked, like_count: data.count }
|
||||
}
|
||||
return r
|
||||
})
|
||||
}))
|
||||
} catch (error) {
|
||||
Taro.showToast({ title: '操作失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
// 分享给好友
|
||||
useShareAppMessage(() => {
|
||||
return {
|
||||
@@ -197,6 +239,10 @@ const ForumDetail = () => {
|
||||
<AtIcon value='eye' size='14' color='#666' style={{marginRight: 4}} />
|
||||
<Text>{topic.view_count}</Text>
|
||||
</View>
|
||||
<View style={{display: 'flex', alignItems: 'center', marginLeft: 10}} onClick={handleLikeTopic}>
|
||||
<AtIcon value={topic.is_liked ? 'heart-2' : 'heart'} size='14' color={topic.is_liked ? '#ff4d4f' : '#666'} style={{marginRight: 4}} />
|
||||
<Text style={{color: topic.is_liked ? '#ff4d4f' : '#666'}}>{topic.like_count || 0}</Text>
|
||||
</View>
|
||||
|
||||
{userInfo && topic.author === userInfo.id && (
|
||||
<View onClick={handleEdit} style={{display: 'flex', alignItems: 'center', marginLeft: 'auto', padding: '6px 12px', background: 'rgba(0, 185, 107, 0.15)', borderRadius: 20}}>
|
||||
@@ -238,6 +284,10 @@ const ForumDetail = () => {
|
||||
<Text style={{fontSize: 10, color: '#666', marginTop: 2}}>#{idx + 1} • {new Date(reply.created_at).toLocaleDateString()}</Text>
|
||||
</View>
|
||||
<View style={{display: 'flex', alignItems: 'center'}}>
|
||||
<View onClick={() => handleLikeReply(reply.id)} style={{marginRight: 10, display: 'flex', alignItems: 'center'}}>
|
||||
<AtIcon value={reply.is_liked ? 'heart-2' : 'heart'} size='14' color={reply.is_liked ? '#ff4d4f' : '#ccc'} />
|
||||
<Text style={{fontSize: 10, color: reply.is_liked ? '#ff4d4f' : '#999', marginLeft: 2}}>{reply.like_count || 0}</Text>
|
||||
</View>
|
||||
<View onClick={() => handleReplyToUser(reply.author_info?.nickname)} style={{marginRight: 10, padding: '2px 6px', background: '#f0f0f0', borderRadius: 4}}>
|
||||
<Text style={{fontSize: 10, color: '#666'}}>回复</Text>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user