添加粉丝关注页面
This commit is contained in:
@@ -24,8 +24,8 @@ const envConfigs: Record<EnvType, EnvConfig> = {
|
|||||||
// 开发环境
|
// 开发环境
|
||||||
development: {
|
development: {
|
||||||
name: '开发环境',
|
name: '开发环境',
|
||||||
apiBaseURL: 'https://sit.light120.com',
|
// apiBaseURL: 'https://sit.light120.com',
|
||||||
// apiBaseURL: 'http://localhost:9098',
|
apiBaseURL: 'http://localhost:9098',
|
||||||
timeout: 15000,
|
timeout: 15000,
|
||||||
enableLog: true,
|
enableLog: true,
|
||||||
enableMock: true,
|
enableMock: true,
|
||||||
|
|||||||
@@ -182,29 +182,6 @@
|
|||||||
.reply-icon {
|
.reply-icon {
|
||||||
width: 12px;
|
width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
position: relative;
|
|
||||||
|
|
||||||
// 绘制回复图标(使用SVG路径)
|
|
||||||
&::before,
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
background: #333333;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
top: 1px;
|
|
||||||
left: 1px;
|
|
||||||
width: 10px;
|
|
||||||
height: 8.75px;
|
|
||||||
clip-path: polygon(0% 0%, 100% 0%, 100% 20%, 20% 20%, 20% 100%, 0% 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
width: 0;
|
|
||||||
height: 0.75px;
|
|
||||||
background: #333333;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.reply-text {
|
.reply-text {
|
||||||
@@ -225,6 +202,11 @@
|
|||||||
border-radius: 9px;
|
border-radius: 9px;
|
||||||
background: #F5F5F5;
|
background: #F5F5F5;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import { useState, useEffect } from "react";
|
|||||||
import { View, Text, ScrollView, Image } from "@tarojs/components";
|
import { View, Text, ScrollView, Image } from "@tarojs/components";
|
||||||
import { Avatar } from "@nutui/nutui-react-taro";
|
import { Avatar } from "@nutui/nutui-react-taro";
|
||||||
import { withAuth, EmptyState } from "@/components";
|
import { withAuth, EmptyState } from "@/components";
|
||||||
import noticeService from "@/services/noticeService";
|
import commentService, { CommentActivity } from "@/services/commentService";
|
||||||
import Taro from "@tarojs/taro";
|
import Taro from "@tarojs/taro";
|
||||||
import "./index.scss";
|
import "./index.scss";
|
||||||
|
|
||||||
// 评论/回复类型定义
|
// 评论/回复类型定义
|
||||||
interface CommentReplyItem {
|
interface CommentReplyItem {
|
||||||
id: string;
|
id: number;
|
||||||
user_avatar: string;
|
user_avatar: string;
|
||||||
user_nickname: string;
|
user_nickname: string;
|
||||||
action_type: "comment" | "reply"; // 评论了你的球局 / 回复了你的评论
|
action_type: "comment" | "reply"; // 评论了你的球局 / 回复了你的评论
|
||||||
@@ -16,8 +16,8 @@ interface CommentReplyItem {
|
|||||||
content: string;
|
content: string;
|
||||||
original_comment?: string; // 被回复的评论内容
|
original_comment?: string; // 被回复的评论内容
|
||||||
activity_image: string;
|
activity_image: string;
|
||||||
activity_id?: string;
|
activity_id: number;
|
||||||
is_read: number;
|
activity_title: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CommentReply = () => {
|
const CommentReply = () => {
|
||||||
@@ -34,23 +34,24 @@ const CommentReply = () => {
|
|||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const res = await noticeService.getNotificationList({
|
const res = await commentService.getMyActivities({
|
||||||
notification_type: "comment", // 筛选评论类型
|
page: 1,
|
||||||
|
pageSize: 20,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.code === 0) {
|
if (res.code === 0 && res.data) {
|
||||||
// 映射数据
|
// 映射数据
|
||||||
const mappedList = res.data.list.map((item: any) => ({
|
const mappedList = res.data.rows.map((item: CommentActivity) => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
user_avatar: item.related_user_avatar || "",
|
user_avatar: item.user?.avatar_url || "",
|
||||||
user_nickname: item.related_user_nickname || "匿名用户",
|
user_nickname: item.user?.nickname || "匿名用户",
|
||||||
action_type: (item.notification_type === "reply" ? "reply" : "comment") as "comment" | "reply",
|
action_type: item.type === "reply" ? "reply" as const : "comment" as const,
|
||||||
time: item.created_at,
|
time: item.create_time,
|
||||||
content: item.content || "",
|
content: item.content || "",
|
||||||
original_comment: item.original_content || "",
|
original_comment: item.parent_comment?.content || "",
|
||||||
activity_image: item.activity_image || "",
|
activity_image: item.game?.image_list?.[0] || "",
|
||||||
activity_id: item.related_activity_id || "",
|
activity_id: item.game_id,
|
||||||
is_read: item.is_read,
|
activity_title: item.game?.title || "",
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setCommentList(mappedList);
|
setCommentList(mappedList);
|
||||||
@@ -98,6 +99,13 @@ const CommentReply = () => {
|
|||||||
// TODO: 跳转到回复页面或弹出回复框
|
// TODO: 跳转到回复页面或弹出回复框
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 处理点击球局
|
||||||
|
const handleGameClick = (gameId: number) => {
|
||||||
|
Taro.navigateTo({
|
||||||
|
url: `/game_pages/detail/index?id=${gameId}`,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// 处理返回
|
// 处理返回
|
||||||
const handleBack = () => {
|
const handleBack = () => {
|
||||||
Taro.navigateBack();
|
Taro.navigateBack();
|
||||||
@@ -136,14 +144,22 @@ const CommentReply = () => {
|
|||||||
|
|
||||||
{/* 回复按钮 */}
|
{/* 回复按钮 */}
|
||||||
<View className="reply-button" onClick={() => handleReply(item)}>
|
<View className="reply-button" onClick={() => handleReply(item)}>
|
||||||
<View className="reply-icon"></View>
|
<Image
|
||||||
|
className="reply-icon"
|
||||||
|
src={require('@/static/message/reply-icon.svg')}
|
||||||
|
/>
|
||||||
<Text className="reply-text">回复</Text>
|
<Text className="reply-text">回复</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* 右侧球局图片 */}
|
{/* 右侧球局图片 */}
|
||||||
<Image className="activity-image" src={item.activity_image} mode="aspectFill" />
|
<Image
|
||||||
|
className="activity-image"
|
||||||
|
src={item.activity_image}
|
||||||
|
mode="aspectFill"
|
||||||
|
onClick={() => handleGameClick(item.activity_id)}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,20 +2,21 @@ import { useState, useEffect } from "react";
|
|||||||
import { View, Text, ScrollView } from "@tarojs/components";
|
import { View, Text, ScrollView } from "@tarojs/components";
|
||||||
import { Avatar } from "@nutui/nutui-react-taro";
|
import { Avatar } from "@nutui/nutui-react-taro";
|
||||||
import { withAuth, EmptyState } from "@/components";
|
import { withAuth, EmptyState } from "@/components";
|
||||||
import noticeService from "@/services/noticeService";
|
import FollowService from "@/services/followService";
|
||||||
import Taro from "@tarojs/taro";
|
import Taro from "@tarojs/taro";
|
||||||
import "./index.scss";
|
import "./index.scss";
|
||||||
|
|
||||||
// 关注项类型定义
|
// 关注项类型定义
|
||||||
interface FollowItem {
|
interface FollowItem {
|
||||||
id: string;
|
id: number;
|
||||||
user_id: string;
|
user_id: number;
|
||||||
user_avatar: string;
|
user_avatar: string;
|
||||||
user_nickname: string;
|
user_nickname: string;
|
||||||
user_signature?: string;
|
user_signature?: string;
|
||||||
|
city?: string;
|
||||||
|
ntrp_level?: string;
|
||||||
time: string;
|
time: string;
|
||||||
is_mutual: boolean; // 是否互相关注
|
is_mutual: boolean; // 是否互相关注
|
||||||
is_read: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const NewFollow = () => {
|
const NewFollow = () => {
|
||||||
@@ -32,21 +33,20 @@ const NewFollow = () => {
|
|||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const res = await noticeService.getNotificationList({
|
const res = await FollowService.get_new_fans_list(1, 20);
|
||||||
notification_type: "follow", // 筛选关注类型
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res.code === 0) {
|
if (res.list) {
|
||||||
// 映射数据
|
// 映射数据
|
||||||
const mappedList = res.data.list.map((item: any) => ({
|
const mappedList = res.list.map((item: any) => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
user_id: item.related_user_id || "",
|
user_id: item.id,
|
||||||
user_avatar: item.related_user_avatar || "",
|
user_avatar: item.avatar_url || "",
|
||||||
user_nickname: item.related_user_nickname || "匿名用户",
|
user_nickname: item.nickname || "匿名用户",
|
||||||
user_signature: item.related_user_signature || "",
|
user_signature: item.personal_profile || "",
|
||||||
time: item.created_at,
|
city: item.city || "",
|
||||||
is_mutual: item.is_mutual_follow || false,
|
ntrp_level: item.ntrp_level || "",
|
||||||
is_read: item.is_read,
|
time: item.follow_time,
|
||||||
|
is_mutual: item.is_mutual || false,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setFollowList(mappedList);
|
setFollowList(mappedList);
|
||||||
@@ -93,8 +93,7 @@ const NewFollow = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// TODO: 调用关注接口
|
await FollowService.follow_back(item.user_id);
|
||||||
// await userService.followUser({ user_id: item.user_id });
|
|
||||||
|
|
||||||
Taro.showToast({
|
Taro.showToast({
|
||||||
title: "关注成功",
|
title: "关注成功",
|
||||||
@@ -125,7 +124,7 @@ const NewFollow = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 处理点击用户
|
// 处理点击用户
|
||||||
const handleUserClick = (userId: string) => {
|
const handleUserClick = (userId: number) => {
|
||||||
Taro.navigateTo({
|
Taro.navigateTo({
|
||||||
url: `/user_pages/other/index?user_id=${userId}`,
|
url: `/user_pages/other/index?user_id=${userId}`,
|
||||||
});
|
});
|
||||||
|
|||||||
94
src/services/commentService.ts
Normal file
94
src/services/commentService.ts
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import httpService from "./httpService";
|
||||||
|
import type { ApiResponse } from "./httpService";
|
||||||
|
|
||||||
|
// 评论项接口定义
|
||||||
|
export interface CommentActivity {
|
||||||
|
id: number;
|
||||||
|
type: "comment" | "reply";
|
||||||
|
activity_type: string;
|
||||||
|
game_id: number;
|
||||||
|
parent_id: number | null;
|
||||||
|
content: string;
|
||||||
|
like_count: number;
|
||||||
|
reply_count: number;
|
||||||
|
create_time: string;
|
||||||
|
user: {
|
||||||
|
id: number;
|
||||||
|
nickname: string;
|
||||||
|
province: string;
|
||||||
|
avatar_url: string;
|
||||||
|
};
|
||||||
|
game: {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
start_time: string;
|
||||||
|
location_name: string;
|
||||||
|
image_list?: string[];
|
||||||
|
};
|
||||||
|
reply_to_user: {
|
||||||
|
id: number;
|
||||||
|
nickname: string;
|
||||||
|
avatar_url: string;
|
||||||
|
} | null;
|
||||||
|
parent_comment: {
|
||||||
|
id: number;
|
||||||
|
content: string;
|
||||||
|
user_id: number;
|
||||||
|
user_nickname: string;
|
||||||
|
} | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取评论动态请求参数
|
||||||
|
export interface GetMyActivitiesParams {
|
||||||
|
page?: number;
|
||||||
|
pageSize?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 评论动态列表响应
|
||||||
|
export interface CommentActivitiesResponse {
|
||||||
|
rows: CommentActivity[];
|
||||||
|
count: number;
|
||||||
|
page: number;
|
||||||
|
pageSize: number;
|
||||||
|
totalPages: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CommentService {
|
||||||
|
// 获取当前用户的评论和回复动态
|
||||||
|
async getMyActivities(params: GetMyActivitiesParams = {}): Promise<ApiResponse<CommentActivitiesResponse>> {
|
||||||
|
const { page = 1, pageSize = 10 } = params;
|
||||||
|
return httpService.post("/comments/my_activities", { page, pageSize }, { showLoading: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发表评论
|
||||||
|
async createComment(game_id: number, content: string): Promise<ApiResponse<any>> {
|
||||||
|
return httpService.post("/comments/create", { game_id, content });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回复评论
|
||||||
|
async replyComment(parent_id: number, reply_to_user_id: number, content: string): Promise<ApiResponse<any>> {
|
||||||
|
return httpService.post("/comments/reply", { parent_id, reply_to_user_id, content });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取评论列表
|
||||||
|
async getCommentList(game_id: number, page: number = 1, pageSize: number = 10): Promise<ApiResponse<any>> {
|
||||||
|
return httpService.post("/comments/list", { game_id, page, pageSize });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点赞/取消点赞评论
|
||||||
|
async likeComment(comment_id: number): Promise<ApiResponse<any>> {
|
||||||
|
return httpService.post("/comments/like", { comment_id });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除评论
|
||||||
|
async deleteComment(comment_id: number): Promise<ApiResponse<any>> {
|
||||||
|
return httpService.post("/comments/delete", { comment_id });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取评论的所有回复
|
||||||
|
async getCommentReplies(comment_id: number, page: number = 1, pageSize: number = 10): Promise<ApiResponse<any>> {
|
||||||
|
return httpService.post("/comments/replies", { comment_id, page, pageSize });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new CommentService();
|
||||||
@@ -84,6 +84,34 @@ export class FollowService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取新增粉丝列表(新关注的人)
|
||||||
|
static async get_new_fans_list(
|
||||||
|
page: number = 1,
|
||||||
|
page_size: number = 20
|
||||||
|
): Promise<FollowListResponse> {
|
||||||
|
try {
|
||||||
|
const response = await httpService.post<FollowListResponse>(
|
||||||
|
'/user_follow/new_fans_list',
|
||||||
|
{ page, page_size },
|
||||||
|
{ showLoading: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.code === 0) {
|
||||||
|
// 为数据添加 follow_status 标识
|
||||||
|
const list = response.data.list.map(user => ({
|
||||||
|
...user,
|
||||||
|
follow_status: user.is_mutual ? 'mutual_follow' as const : 'follower' as const
|
||||||
|
}));
|
||||||
|
return { ...response.data, list };
|
||||||
|
} else {
|
||||||
|
throw new Error(response.message || '获取新增粉丝列表失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取新增粉丝列表失败:', error);
|
||||||
|
return { list: [], total: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 获取我的关注列表
|
// 获取我的关注列表
|
||||||
static async get_following_list(
|
static async get_following_list(
|
||||||
page: number = 1,
|
page: number = 1,
|
||||||
|
|||||||
6
src/static/message/reply-icon.svg
Normal file
6
src/static/message/reply-icon.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M11 1.5H1V9H3.25V10.25L5.75 9H11V1.5Z" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M3.5 4.875V5.625" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M6 4.875V5.625" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M8.5 4.875V5.625" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 494 B |
Reference in New Issue
Block a user