添加 消息 页面更新
This commit is contained in:
@@ -1,136 +1,226 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { View, Text, ScrollView, Image } from "@tarojs/components";
|
||||
import { View, Text, Image, ScrollView } from "@tarojs/components";
|
||||
import { Avatar } from "@nutui/nutui-react-taro";
|
||||
import GuideBar from "@/components/GuideBar";
|
||||
import { withAuth } from "@/components";
|
||||
import { withAuth, EmptyState } from "@/components";
|
||||
import noticeService from "@/services/noticeService";
|
||||
import Taro, { useRouter } from "@tarojs/taro";
|
||||
import { useUserInfo } from "@/store/userStore";
|
||||
import Taro from "@tarojs/taro";
|
||||
import "./index.scss";
|
||||
|
||||
// 消息类型定义
|
||||
interface MessageItem {
|
||||
id: string;
|
||||
type: "system" | "user" | "like" | "comment" | "follow";
|
||||
notification_type: string;
|
||||
title: string;
|
||||
content: string;
|
||||
time: string;
|
||||
avatar?: string;
|
||||
isRead: boolean;
|
||||
hasAction?: boolean;
|
||||
actionText?: string;
|
||||
create_time: string;
|
||||
is_read: number;
|
||||
related_user_avatar?: string;
|
||||
related_user_nickname?: string;
|
||||
activity_image?: string;
|
||||
}
|
||||
|
||||
// 消息分类类型
|
||||
type MessageCategory = "comment" | "follow";
|
||||
|
||||
const Message = () => {
|
||||
const [activeTab] = useState<"all" | "like" | "comment" | "follow">("all");
|
||||
const userInfo = useUserInfo() as any;
|
||||
const [activeTab, setActiveTab] = useState<MessageCategory | null>(null);
|
||||
const [messageList, setMessageList] = useState<MessageItem[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [reachedBottom, setReachedBottom] = useState(false);
|
||||
|
||||
// 获取消息列表
|
||||
const getNoticeList = async () => {
|
||||
if (loading) return;
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await noticeService.getNotificationList({});
|
||||
if (res.code === 0) {
|
||||
setMessageList(res.data.list || []);
|
||||
}
|
||||
} catch (e) {
|
||||
Taro.showToast({
|
||||
title: "获取列表失败,请重试",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const getNoticeList = async () => {
|
||||
try {
|
||||
const res = await noticeService.getNotificationList({});
|
||||
if (res.code === 0) {
|
||||
setMessageList(res.data.list);
|
||||
}
|
||||
} catch (e) {
|
||||
Taro.showToast({
|
||||
title: "获取列表失败,请重试",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
} finally {
|
||||
}
|
||||
};
|
||||
getNoticeList();
|
||||
}, []);
|
||||
|
||||
// 过滤消息
|
||||
const filteredMessages = messageList.filter((message) => {
|
||||
if (activeTab === "all") return true;
|
||||
return message.type === activeTab;
|
||||
});
|
||||
// 过滤系统消息
|
||||
const filteredMessages = messageList;
|
||||
|
||||
// 渲染消息项
|
||||
const renderMessageItem = (message: MessageItem) => {
|
||||
if (message.type === "system") {
|
||||
return (
|
||||
<View className="message-item system-message" key={message.id}>
|
||||
<View className="message-header">
|
||||
<Text className="message-title">{message.title}</Text>
|
||||
<Text className="message-time">{message.time}</Text>
|
||||
</View>
|
||||
<View className="message-content">
|
||||
<Text className="message-text">{message.content}</Text>
|
||||
</View>
|
||||
{message.hasAction && (
|
||||
<View className="message-action">
|
||||
<View className="action-divider"></View>
|
||||
<View className="action-button">
|
||||
<Text className="action-text">{message.actionText}</Text>
|
||||
<Image
|
||||
className="action-arrow"
|
||||
src={require("../../static/message/icon-message-arrow.svg")}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
// 处理分类标签点击
|
||||
const handleTabClick = (tab: MessageCategory) => {
|
||||
// 点击评论标签跳转到评论和回复页面
|
||||
if (tab === "comment") {
|
||||
Taro.navigateTo({
|
||||
url: "/other_pages/comment_reply/index",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 点击关注标签跳转到新增关注页面
|
||||
if (tab === "follow") {
|
||||
Taro.navigateTo({
|
||||
url: "/other_pages/new_follow/index",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setActiveTab(activeTab === tab ? null : tab);
|
||||
};
|
||||
|
||||
return (
|
||||
<View className="message-item user-message" key={message.id}>
|
||||
<View className="message-avatar">
|
||||
<Avatar src={message.avatar} size="48px" />
|
||||
</View>
|
||||
<View className="message-info">
|
||||
<View className="message-header">
|
||||
<Text className="message-title">{message.title}</Text>
|
||||
<Text className="message-time">{message.time}</Text>
|
||||
</View>
|
||||
<View className="message-content">
|
||||
<Text className="message-text">{message.content}</Text>
|
||||
{!message.isRead && <View className="unread-indicator"></View>}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
// 处理查看详情
|
||||
const handleViewDetail = (messageId: string) => {
|
||||
console.log("查看详情:", messageId);
|
||||
// TODO: 根据消息类型跳转到对应详情页
|
||||
};
|
||||
|
||||
// 处理滚动到底部
|
||||
const handleScrollToLower = () => {
|
||||
if (!reachedBottom && filteredMessages.length > 0) {
|
||||
setReachedBottom(true);
|
||||
// 2秒后隐藏提示
|
||||
setTimeout(() => {
|
||||
setReachedBottom(false);
|
||||
}, 2000);
|
||||
}
|
||||
};
|
||||
|
||||
// 格式化时间显示
|
||||
const formatTime = (timeStr: string) => {
|
||||
if (!timeStr) return "";
|
||||
const date = new Date(timeStr);
|
||||
const now = new Date();
|
||||
const diff = now.getTime() - date.getTime();
|
||||
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (days === 0) {
|
||||
const hours = date.getHours();
|
||||
const minutes = date.getMinutes();
|
||||
return `今天 ${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
||||
} else if (days === 1) {
|
||||
const hours = date.getHours();
|
||||
const minutes = date.getMinutes();
|
||||
return `昨天 ${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
||||
} else if (days < 3) {
|
||||
return `${days}天前`;
|
||||
} else {
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth() + 1;
|
||||
const day = date.getDate();
|
||||
const hours = date.getHours();
|
||||
const minutes = date.getMinutes();
|
||||
return `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')} ${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View className="message-container">
|
||||
{/* 导航栏 */}
|
||||
{/* 顶部导航栏 */}
|
||||
<View className="navbar">
|
||||
<View className="navbar-content">
|
||||
<View className="navbar-left">
|
||||
<Avatar
|
||||
className="navbar-avatar"
|
||||
src="https://img.yzcdn.cn/vant/cat.jpeg"
|
||||
src={userInfo?.avatar_url }
|
||||
size="28px"
|
||||
/>
|
||||
<Text className="navbar-title">消息</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 消息列表 */}
|
||||
<ScrollView scrollY className="message-list" scrollWithAnimation enhanced showScrollbar={false} >
|
||||
{/* 分类标签 */}
|
||||
<View className="category-tabs">
|
||||
<View
|
||||
className={`tab-item ${activeTab === "comment" ? "active" : ""}`}
|
||||
onClick={() => handleTabClick("comment")}
|
||||
>
|
||||
<Image
|
||||
className="tab-icon"
|
||||
src={require('@/static/message/comment-icon.svg')}
|
||||
/>
|
||||
<Text className="tab-text">评论和回复</Text>
|
||||
</View>
|
||||
<View
|
||||
className={`tab-item ${activeTab === "follow" ? "active" : ""}`}
|
||||
onClick={() => handleTabClick("follow")}
|
||||
>
|
||||
<Image
|
||||
className="tab-icon"
|
||||
src={require('@/static/message/follow-icon.svg')}
|
||||
/>
|
||||
<Text className="tab-text">新增关注</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 系统消息卡片列表 */}
|
||||
<ScrollView
|
||||
scrollY
|
||||
className="message-scroll"
|
||||
scrollWithAnimation
|
||||
enhanced
|
||||
showScrollbar={false}
|
||||
lowerThreshold={50}
|
||||
onScrollToLower={handleScrollToLower}
|
||||
>
|
||||
{filteredMessages.length > 0 ? (
|
||||
<View className="message-list-content">
|
||||
{filteredMessages.map(renderMessageItem)}
|
||||
<View className="message-cards">
|
||||
{filteredMessages.map((message) => (
|
||||
<View className="message-card" key={message.id}>
|
||||
<View className="card-title-row">
|
||||
<Text className="card-title">{message.title}</Text>
|
||||
</View>
|
||||
<View className="card-time-row">
|
||||
<Text className="card-time">{formatTime(message.create_time)}</Text>
|
||||
</View>
|
||||
<View className="card-content-row">
|
||||
<Text className="card-content">{message.content}</Text>
|
||||
</View>
|
||||
<View className="card-footer">
|
||||
<View className="footer-divider"></View>
|
||||
<View className="footer-action" onClick={() => handleViewDetail(message.id)}>
|
||||
<Text className="action-text">查看详情</Text>
|
||||
<View className="action-arrow">
|
||||
|
||||
<Image className="img" src={require('@/static/message/ar-right.svg')} ></Image>
|
||||
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
))}
|
||||
{/* 到底了提示 */}
|
||||
{filteredMessages.length > 0 && (
|
||||
<View className="bottom-tip">
|
||||
<Text className="tip-text">到底了</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
) : (
|
||||
<View className="empty-state">
|
||||
<View className="empty-icon">
|
||||
<View className="empty-message-icon"></View>
|
||||
</View>
|
||||
<Text className="empty-text">暂无消息</Text>
|
||||
</View>
|
||||
<EmptyState text="暂无消息" />
|
||||
)}
|
||||
</ScrollView>
|
||||
|
||||
{/* 悬浮新建按钮 */}
|
||||
<View className="floating-button" onClick={() => console.log("新建消息")}>
|
||||
<View className="button-icon"></View>
|
||||
</View>
|
||||
|
||||
{/* 底部导航 */}
|
||||
<GuideBar currentPage="message" />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default withAuth(Message);
|
||||
export default withAuth(Message);
|
||||
Reference in New Issue
Block a user