Browse Source

消息

master
DU 6 months ago
parent
commit
37654afe52
  1. BIN
      src/assets/big/noData.png
  2. 5
      src/pages/message/index.config.ts
  3. 191
      src/pages/message/index.scss
  4. 280
      src/pages/message/index.tsx

BIN
src/assets/big/noData.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

5
src/pages/message/index.config.ts

@ -1,4 +1,5 @@
export default { export default {
navigationStyle: 'custom', navigationBarTitleText: '消息',
usingComponents: {}, navigationBarBackgroundColor: '#FFFFFF',
navigationBarTextStyle: 'black'
} }

191
src/pages/message/index.scss

@ -1,19 +1,182 @@
.message-page { .message-page {
min-height: 100vh; width: 100%;
background-color: #121212; height: 100vh;
background: #F2F3F5;
.header {
padding: 32px; // Tabs 导航栏
background: #fff; .message-tabs {
width: 100%;
.title { height: 100%;
font-size: 36px;
font-weight: bold; // 覆盖 Taroify Tabs 样式
color: #333; :global {
.taroify-tabs__wrap {
background: #FFFFFF;
box-shadow: 0 -1px 0 0 #DDDDDD;
}
.taroify-tabs__tab {
font-size: 33px;
color: #8B8B8B;
font-weight: 400;
padding: 24px 0;
}
.taroify-tabs__tab--active {
color: #333333;
font-weight: 500;
}
.taroify-tabs__line {
background: #333333;
height: 4px;
}
.taroify-tabs__content {
background: #F2F3F5;
}
} }
} .taroify-badge--top-right{
transform:none;
background-color: #FF3B30;
}
// Tab 内容区域 - 关键 ScrollView 明确的高度
.tab-content {
width: 100%;
// 高度 = 100vh - tabbar(40Px) - Tabs标签栏(约88px) - 安全区域
height: calc(100vh - 40Px - 88px);
height: calc(100vh - 40Px - 88px - constant(safe-area-inset-bottom));
height: calc(100vh - 40Px - 88px - env(safe-area-inset-bottom));
background: #F2F3F5;
}
// 空状态
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding-top: 200px;
.empty-image {
width: 300px;
height: 300px;
margin-bottom: 40px;
}
.empty-text {
font-size: 28px;
color: #999999;
}
}
// 消息列表
.message-list {
padding: 30px 30px 0;
.message-item {
display: flex;
padding: 30px;
background: #FFFFFF;
border-radius: 16px;
margin-bottom: 30px;
// 有图片的消息
&.has-image {
.message-image {
flex-shrink: 0;
width: 208px;
height: 190px;
border-radius: 8px;
margin-right: 30px;
}
}
// 消息内容区域
.message-content {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0; // 关键 flex 子元素的文本省略生效
overflow: hidden;
// 标题行 NEW 标记
.message-title-wrapper {
display: flex;
align-items: center;
margin-bottom: 20px;
min-width: 0; // 关键让标题省略生效
.message-title {
flex: 1;
font-weight: 400;
font-size: 33px;
color: #1A1A1A;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0; // 关键确保单行省略生效
}
.content { .new-badge {
padding: 32px; flex-shrink: 0;
margin-left: 16px;
padding: 4px 12px;
background: #FF3B30;
border-radius: 4px;
font-size: 20px;
color: #FFFFFF;
font-weight: 500;
}
}
// 内容文本
.message-text {
font-size: 26px;
color: #595959;
line-height: 1.5;
margin-bottom: 20px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2; // 两行省略
line-clamp: 2; // 标准属性
-webkit-box-orient: vertical;
word-break: break-all; // 确保英文也能正常换行和省略
}
// 时间
.message-time {
display: flex;
align-items: baseline;
.time-label {
font-size: 26px;
color: #8C8C8C;
}
.time-value {
font-size: 26px;
color: #333333;
}
}
}
}
// 列表底部提示
.list-footer {
padding: 40px 0;
text-align: center;
.footer-text {
font-size: 26px;
color: #999999;
}
}
}
} }
} }

280
src/pages/message/index.tsx

@ -1,26 +1,288 @@
/** /**
* *
*/ */
import { View, Text } from '@tarojs/components' import { View, Text, Image, ScrollView } from '@tarojs/components'
import { useLoad } from '@tarojs/taro' import { useLoad } from '@tarojs/taro'
import { observer } from 'mobx-react' import { observer } from 'mobx-react'
import { useState } from 'react'
import { Tabs, Badge } from '@taroify/core'
import noDataImg from '../../assets/big/noData.png'
import './index.scss' import './index.scss'
// 消息数据接口
interface Message {
id: string
title: string
content: string
time: string
createTime: number // 时间戳
image?: string // 可选图片
}
const MessageIndex = observer(() => { const MessageIndex = observer(() => {
const [activeTab, setActiveTab] = useState(0)
// 模拟消息数据
const currentTime = Date.now()
const fiveMinutesAgo = currentTime - 5 * 60 * 1000
const [invitationMessages, setInvitationMessages] = useState<Message[]>([
{
id: '1',
title: '[中式台球]来力.山岩-A03号球桌邀球',
content: '[中式台球]来力.山岩-A03/03号球桌邀球',
time: '2025-01-10 00:00:00',
createTime: currentTime - 2 * 60 * 1000, // 2分钟前(NEW)
},
{
id: '2',
title: '[斯诺克]星辉台球-B05号球桌邀球',
content: '[斯诺克]星辉台球-B05/05号球桌邀球',
time: '2025-01-09 23:55:00',
createTime: currentTime - 3 * 60 * 1000, // 3分钟前(NEW)
},
{
id: '3',
title: '[中式台球]黑八大师-C02号球桌邀球',
content: '[中式台球]黑八大师-C02/02号球桌邀球',
time: '2025-01-09 20:30:00',
createTime: currentTime - 4 * 60 * 60 * 1000, // 4小时前
},
{
id: '7',
title: '[九球]晶彩桌球世界-D06号球桌邀球',
content: '[九球]晶彩桌球世界-D06/06号球桌邀球,欢迎高手来战!',
time: '2025-01-09 19:15:00',
createTime: currentTime - 5 * 60 * 60 * 1000,
},
{
id: '8',
title: '[中式台球]飓风台球-E08号球桌邀球',
content: '[中式台球]飓风台球-E08/08号球桌邀球,新手友好,一起练习',
time: '2025-01-09 18:00:00',
createTime: currentTime - 6 * 60 * 60 * 1000,
},
{
id: '9',
title: '[斯诺克]星耀俱乐部-F01号球桌邀球',
content: '[斯诺克]星耀俱乐部-F01/01号球桌邀球,求高手指点',
time: '2025-01-09 16:30:00',
createTime: currentTime - 8 * 60 * 60 * 1000,
},
{
id: '10',
title: '[中式台球]来力台球厅-G03号球桌邀球',
content: '[中式台球]来力台球厅-G03/03号球桌邀球,一起切磋球技',
time: '2025-01-09 15:00:00',
createTime: currentTime - 9 * 60 * 60 * 1000,
},
])
const [storeMessages, setStoreMessages] = useState<Message[]>([
{
id: '4',
title: '公告:缴费时间三等奖发缴费时间...',
content: '金风科技上课福建省咖啡机看得见风可视对讲开发机十大费晶...',
time: '2025-01-10',
createTime: currentTime - 1 * 60 * 60 * 1000,
image: require('../../assets/big/fjmd.png'),
},
{
id: '5',
title: '公告:缴费时间三等奖发缴费时间...',
content: '金风科技上课福建省咖啡机看得见风可视对讲开发机十大费晶...',
time: '2025-01-10',
createTime: currentTime - 2 * 60 * 60 * 1000,
},
{
id: '11',
title: '活动通知:新店开业优惠活动',
content: '来力台球厅新店盛大开业,前100名顾客可享受5折优惠,还有精美礼品相送!',
time: '2025-01-09 20:00:00',
createTime: currentTime - 4 * 60 * 60 * 1000,
image: require('../../assets/big/smkt.png'),
},
{
id: '12',
title: '店铺公告:营业时间调整通知',
content: '尊敬的顾客,本店营业时间将调整为每天09:00-24:00,感谢您的支持!',
time: '2025-01-09 14:30:00',
createTime: currentTime - 10 * 60 * 60 * 1000,
},
{
id: '13',
title: '特惠活动:周末会员日专享优惠',
content: '本周末会员专享8折优惠,非会员可享受9折优惠,欢迎预约!',
time: '2025-01-09 10:00:00',
createTime: currentTime - 14 * 60 * 60 * 1000,
image: require('../../assets/big/tghx.png'),
},
])
const [systemMessages, setSystemMessages] = useState<Message[]>([
{
id: '6',
title: '系统维护通知',
content: '系统将于今晚22:00-23:00进行维护升级,期间部分功能可能无法使用...',
time: '2025-01-09 18:00:00',
createTime: currentTime - 6 * 60 * 60 * 1000,
},
{
id: '14',
title: '版本更新公告',
content: 'APP已更新至v2.0版本,新增多项功能优化,提升用户体验,建议您及时更新',
time: '2025-01-09 12:00:00',
createTime: currentTime - 12 * 60 * 60 * 1000,
},
{
id: '15',
title: '安全提醒',
content: '请注意保护您的账号安全,不要向他人透露密码和验证码信息,谨防诈骗',
time: '2025-01-08 20:00:00',
createTime: currentTime - 28 * 60 * 60 * 1000,
},
{
id: '16',
title: '用户协议更新通知',
content: '用户服务协议和隐私政策已更新,请您及时查阅了解最新内容',
time: '2025-01-08 10:00:00',
createTime: currentTime - 38 * 60 * 60 * 1000,
},
])
useLoad(() => { useLoad(() => {
console.log('消息页面加载') console.log('消息页面加载')
// TODO: 调用接口获取消息数据
}) })
return ( // 获取当前 tab 的消息列表
<View className="message-page"> const getCurrentMessages = () => {
<View className="header"> switch (activeTab) {
<Text className="title"></Text> case 0:
</View> return invitationMessages
<View className="content"> case 1:
<View className="placeholder"> return storeMessages
<Text>...</Text> case 2:
return systemMessages
default:
return []
}
}
// 判断消息是否为新消息(5分钟内)
const isNewMessage = (createTime: number) => {
const fiveMinutesAgo = Date.now() - 5 * 60 * 1000
return createTime > fiveMinutesAgo
}
// 计算未读消息数(5分钟内的)
const getUnreadCount = (messages: Message[]) => {
return messages.filter(msg => isNewMessage(msg.createTime)).length
}
// 渲染空状态
const renderEmptyState = () => (
<View className="empty-state">
<Image className="empty-image" src={noDataImg} mode="aspectFit" />
<Text className="empty-text">~</Text>
</View>
)
// 渲染消息列表
const renderMessages = () => {
const messages = getCurrentMessages()
if (messages.length === 0) {
return renderEmptyState()
}
return (
<View className="message-list">
{messages.map((message: Message) => (
<View
key={message.id}
className={`message-item ${message.image ? 'has-image' : ''}`}
>
{message.image && (
<Image
className="message-image"
src={message.image}
mode="aspectFill"
/>
)}
<View className="message-content">
<View className="message-title-wrapper">
<Text className="message-title">{message.title}</Text>
{isNewMessage(message.createTime) && (
<View className="new-badge">NEW</View>
)}
</View>
<Text className="message-text">{message.content}</Text>
<View className="message-time">
<Text className="time-label"></Text>
<Text className="time-value">{message.time}</Text>
</View>
</View>
</View>
))}
{/* 到底了提示 */}
<View className="list-footer">
<Text className="footer-text">~</Text>
</View> </View>
</View> </View>
)
}
return (
<View className="message-page">
{/* Tabs 导航栏 */}
<Tabs className="message-tabs" value={activeTab} onChange={setActiveTab}>
<Tabs.TabPane
title={
getUnreadCount(invitationMessages) > 0 ? (
<Badge dot position="top-right"></Badge>
) : (
'邀球消息'
)
}
>
<ScrollView scrollY className="tab-content">
{renderMessages()}
</ScrollView>
</Tabs.TabPane>
<Tabs.TabPane
title={
getUnreadCount(storeMessages) > 0 ? (
<Badge dot position="top-right"></Badge>
) : (
'门店消息'
)
}
>
<ScrollView scrollY className="tab-content">
{renderMessages()}
</ScrollView>
</Tabs.TabPane>
<Tabs.TabPane
title={
getUnreadCount(systemMessages) > 0 ? (
<Badge dot position="top-right"></Badge>
) : (
'系统消息'
)
}
>
<ScrollView scrollY className="tab-content">
{renderMessages()}
</ScrollView>
</Tabs.TabPane>
</Tabs>
</View> </View>
) )
}) })

Loading…
Cancel
Save