From ccdc2206386bd287de73f36ae6e9dc8ef0e58a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=88=90?= Date: Wed, 1 Oct 2025 14:01:21 +0800 Subject: [PATCH] 1 --- src/other_pages/comment_reply/index.scss | 82 +++++++++- src/other_pages/comment_reply/index.tsx | 185 +++++++++++++++++++---- src/static/message/send-icon.svg | 6 + 3 files changed, 240 insertions(+), 33 deletions(-) create mode 100644 src/static/message/send-icon.svg diff --git a/src/other_pages/comment_reply/index.scss b/src/other_pages/comment_reply/index.scss index 92755ea..e7be1bc 100644 --- a/src/other_pages/comment_reply/index.scss +++ b/src/other_pages/comment_reply/index.scss @@ -96,6 +96,11 @@ height: 48px; border-radius: 999px; flex-shrink: 0; + cursor: pointer; + + &:active { + opacity: 0.8; + } } .comment-content { @@ -111,6 +116,12 @@ font-size: 14px; line-height: 1.43; color: #000000; + cursor: pointer; + width: fit-content; + + &:active { + opacity: 0.6; + } } .action-row { @@ -225,4 +236,73 @@ color: rgba(0, 0, 0, 0.35); } } -} + + // 回复输入框 + .reply-input-container { + position: fixed; + bottom: 0; + left: 0; + right: 0; + background: #F8F8F8; + border-top: 0.5px solid rgba(0, 0, 0, 0.06); + padding: 8px 12px; + padding-bottom: calc(20px + env(safe-area-inset-bottom)); + z-index: 200; + + .reply-input-wrapper { + display: flex; + align-items: center; + gap: 0; + background: #FFFFFF; + border-radius: 20px; + + .input-row { + display: flex; + align-items: center; + gap: 8px; + width: 100%; + + height: 36px; + padding-left: 16px; + margin: 12px 0px; + + + .reply-input { + flex: 1; + border: none; + font-family: 'PingFang SC'; + font-weight: 400; + font-size: 15px; + line-height: 1.4; + color: #000000; + + &::placeholder { + color: rgba(60, 60, 67, 0.3); + font-size: 15px; + } + } + + .input-actions { + display: flex; + align-items: center; + + .send-btn { + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + flex-shrink: 0; + + .send-icon { + width: 100%; + height: 100%; + } + + } + } + } + } + } +} \ No newline at end of file diff --git a/src/other_pages/comment_reply/index.tsx b/src/other_pages/comment_reply/index.tsx index 8e94dd3..ce35fc5 100644 --- a/src/other_pages/comment_reply/index.tsx +++ b/src/other_pages/comment_reply/index.tsx @@ -1,5 +1,5 @@ import { useState, useEffect } from "react"; -import { View, Text, ScrollView, Image } from "@tarojs/components"; +import { View, Text, ScrollView, Image, Input } from "@tarojs/components"; import { Avatar } from "@nutui/nutui-react-taro"; import { withAuth, EmptyState } from "@/components"; import commentService, { CommentActivity } from "@/services/commentService"; @@ -9,6 +9,7 @@ import "./index.scss"; // 评论/回复类型定义 interface CommentReplyItem { id: number; + user_id: number; user_avatar: string; user_nickname: string; action_type: "comment" | "reply"; // 评论了你的球局 / 回复了你的评论 @@ -24,6 +25,10 @@ const CommentReply = () => { const [commentList, setCommentList] = useState([]); const [loading, setLoading] = useState(false); const [refreshing, setRefreshing] = useState(false); + const [showReplyInput, setShowReplyInput] = useState(false); + const [replyTarget, setReplyTarget] = useState(null); + const [replyContent, setReplyContent] = useState(""); + const [inputFocus, setInputFocus] = useState(false); useEffect(() => { getCommentReplyList(); @@ -32,18 +37,19 @@ const CommentReply = () => { // 获取评论和回复列表 const getCommentReplyList = async () => { if (loading) return; - + setLoading(true); try { const res = await commentService.getMyActivities({ page: 1, pageSize: 20, }); - + if (res.code === 0 && res.data) { // 映射数据 const mappedList = res.data.rows.map((item: CommentActivity) => ({ id: item.id, + user_id: item.user?.id || 0, user_avatar: item.user?.avatar_url || "", user_nickname: item.user?.nickname || "匿名用户", action_type: item.type === "reply" ? "reply" as const : "comment" as const, @@ -54,7 +60,7 @@ const CommentReply = () => { activity_id: item.game_id, activity_title: item.game?.title || "", })); - + setCommentList(mappedList); } } catch (e) { @@ -71,14 +77,14 @@ const CommentReply = () => { // 格式化时间显示 const formatTime = (timeStr: string) => { if (!timeStr) return ""; - + const date = new Date(timeStr); const now = new Date(); const diff = now.getTime() - date.getTime(); const minutes = Math.floor(diff / (1000 * 60)); const hours = Math.floor(diff / (1000 * 60 * 60)); const days = Math.floor(diff / (1000 * 60 * 60 * 24)); - + if (minutes < 60) { return `${minutes}分钟前`; } else if (hours < 24) { @@ -95,18 +101,83 @@ const CommentReply = () => { }; // 处理回复 - const handleReply = (item: CommentReplyItem) => { - console.log("回复:", item); - // TODO: 跳转到回复页面或弹出回复框 + const handleReply = (e: any, item: CommentReplyItem) => { + e.stopPropagation(); // 阻止事件冒泡 + setReplyTarget(item); + setShowReplyInput(true); + setInputFocus(true); + setReplyContent(""); }; - // 处理点击球局 - const handleGameClick = (gameId: number) => { + // 处理点击评论项(跳转到球局详情) + const handleCommentClick = (item: CommentReplyItem) => { Taro.navigateTo({ - url: `/game_pages/detail/index?id=${gameId}`, + url: `/game_pages/detail/index?id=${item.activity_id}&message_id=${item.id}`, }); }; + // 处理点击用户(跳转到个人页) + const handleUserClick = (e: any, userId: number) => { + e.stopPropagation(); // 阻止事件冒泡 + Taro.navigateTo({ + url: `/user_pages/other/index?user_id=${userId}`, + }); + }; + + // 发送回复 + const handleSendReply = async () => { + if (!replyContent.trim() || !replyTarget) { + Taro.showToast({ + title: "请输入回复内容", + icon: "none", + duration: 2000, + }); + return; + } + + try { + // TODO: 调用回复接口 + // await commentService.replyComment(replyTarget.id, replyContent); + + Taro.showToast({ + title: "回复成功", + icon: "success", + duration: 2000, + }); + + // 关闭输入框 + setShowReplyInput(false); + setReplyTarget(null); + setReplyContent(""); + setInputFocus(false); + + // 刷新列表 + getCommentReplyList(); + } catch (e) { + Taro.showToast({ + title: "回复失败", + icon: "none", + duration: 2000, + }); + } + }; + + // 取消回复 + const handleCancelReply = () => { + setShowReplyInput(false); + setReplyTarget(null); + setReplyContent(""); + setInputFocus(false); + }; + + // 输入框失去焦点 + const handleInputBlur = () => { + // 延迟执行,避免点击发送按钮时输入框先失焦导致发送失败 + // setTimeout(() => { + // handleCancelReply(); + // }, 200); + }; + // 处理返回 const handleBack = () => { Taro.navigateBack(); @@ -120,10 +191,11 @@ const CommentReply = () => { page: 1, pageSize: 20, }); - + if (res.code === 0 && res.data) { const mappedList = res.data.rows.map((item: CommentActivity) => ({ id: item.id, + user_id: item.user?.id || 0, user_avatar: item.user?.avatar_url || "", user_nickname: item.user?.nickname || "匿名用户", action_type: item.type === "reply" ? "reply" as const : "comment" as const, @@ -134,7 +206,7 @@ const CommentReply = () => { activity_id: item.game_id, activity_title: item.game?.title || "", })); - + setCommentList(mappedList); } } catch (e) { @@ -151,26 +223,36 @@ const CommentReply = () => { // 渲染评论/回复项 const renderCommentItem = (item: CommentReplyItem) => { const actionText = item.action_type === "comment" ? "评论了你的球局" : "回复了你的评论"; - + return ( - + handleCommentClick(item)} + > handleUserClick(e, item.user_id)} /> - + - {item.user_nickname} - + handleUserClick(e, item.user_id)} + > + {item.user_nickname} + + {actionText} {formatTime(item.time)} - + {item.content} - + {/* 如果是回复,显示被回复的评论 */} {item.action_type === "reply" && item.original_comment && ( @@ -178,24 +260,23 @@ const CommentReply = () => { {item.original_comment} )} - + {/* 回复按钮 */} - handleReply(item)}> - handleReply(e, item)}> + 回复 - + {/* 右侧球局图片 */} - handleGameClick(item.activity_id)} /> ); @@ -227,7 +308,7 @@ const CommentReply = () => { {commentList.length > 0 ? ( {commentList.map(renderCommentItem)} - + {/* 到底了提示 */} 到底了 @@ -237,6 +318,46 @@ const CommentReply = () => { )} + + {/* 回复输入框 */} + {showReplyInput && replyTarget && ( + <> + {/* 遮罩层 */} + + + + + + setReplyContent(e.detail.value)} + onBlur={handleInputBlur} + confirmType="send" + onConfirm={handleSendReply} + /> + + + + + + + + + + )} ); }; diff --git a/src/static/message/send-icon.svg b/src/static/message/send-icon.svg new file mode 100644 index 0000000..df171b0 --- /dev/null +++ b/src/static/message/send-icon.svg @@ -0,0 +1,6 @@ + + + + + +