Files
medical-mall/pages/mall/consumer/messages.uvue

1331 lines
29 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="messages-page">
<!-- 智能顶部导航栏 - 与主页保持一致 -->
<view class="smart-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="nav-container">
<text class="nav-title">消息中心</text>
<view class="nav-actions">
<view class="action-btn" @click="clearAllUnread">
<text class="action-icon">🧹</text>
<text class="action-text">一键已读</text>
</view>
</view>
</view>
</view>
<!-- 导航栏占位符 -->
<view class="navbar-placeholder" :style="{ height: (statusBarHeight + 10) + 'px' }"></view>
<!-- 消息分类标签 - 固定在顶部,方便随时切换 -->
<view class="tabs-container">
<view class="message-tabs">
<view
v-for="tab in messageTabs"
:key="tab.id"
:class="['tab-item', { active: activeTab === tab.id }]"
@click="switchTab(tab.id)"
>
<text class="tab-name">{{ tab.name }}</text>
<text v-if="tab.unread > 0" class="tab-badge">{{ tab.unread > 99 ? '99+' : tab.unread }}</text>
</view>
</view>
</view>
<!-- 消息列表内容区 -->
<scroll-view
scroll-y
class="messages-content"
refresher-enabled
:refresher-triggered="refreshing"
@refresherrefresh="onRefresh"
:scroll-top="scrollTop"
>
<!-- 客服消息 -->
<view v-if="activeTab === 'service'" class="message-section">
<!-- 在线客服卡片 -->
<view class="customer-service-info">
<view class="service-header">
<text class="service-title">康乐医药在线客服</text>
<text class="service-status online">在线</text>
</view>
<text class="service-desc">专业医药顾问在线解答,服务时间 9:00-22:00</text>
<view class="service-categories">
<view class="category-item" @click="startQuickService('用药咨询')">
<text class="category-icon">💊</text>
<text class="category-name">用药咨询</text>
</view>
<view class="category-item" @click="startQuickService('处方咨询')">
<text class="category-icon">📋</text>
<text class="category-name">处方咨询</text>
</view>
<view class="category-item" @click="startQuickService('副作用咨询')">
<text class="category-icon">⚠️</text>
<text class="category-name">副作用咨询</text>
</view>
<view class="category-item" @click="startQuickService('药品配送')">
<text class="category-icon">🚚</text>
<text class="category-name">药品配送</text>
</view>
</view>
</view>
<!-- 客服消息列表 -->
<view
v-for="message in serviceMessages"
:key="message.id"
:class="['message-item', { unread: !message.read, active: message.active }]"
@click="startChatWithService(message)"
>
<view class="message-icon-wrapper">
<image
v-if="message.avatar"
class="message-avatar"
:src="message.avatar"
mode="aspectFill"
/>
<view v-else class="message-icon-default" :style="{ backgroundColor: message.color }">
<text>{{ message.icon }}</text>
</view>
<view v-if="message.online" class="online-dot"></view>
</view>
<view class="message-content">
<view class="message-header">
<view class="message-title-wrapper">
<text class="message-title">{{ message.title }}</text>
<text v-if="message.role" class="message-role">{{ message.role }}</text>
</view>
<view class="message-header-right">
<text class="message-time">{{ message.time }}</text>
<text v-if="message.unreadCount > 0" class="message-unread-count">{{ message.unreadCount }}</text>
</view>
</view>
<view class="message-preview-wrapper">
<text class="message-preview">{{ message.content }}</text>
<text v-if="message.lastMessage" class="last-message">{{ message.lastMessage }}</text>
</view>
<view v-if="message.tags" class="message-tags">
<text v-for="tag in message.tags" :key="tag" class="message-tag">{{ tag }}</text>
</view>
</view>
</view>
<!-- 客服系统提示 -->
<view class="service-tips">
<text class="tip-icon">💡</text>
<text class="tip-text">温馨提示:请勿相信任何要求转账、付款的信息,谨防诈骗</text>
</view>
</view>
<!-- 系统通知 -->
<view v-if="activeTab === 'system'" class="message-section">
<view
v-for="message in systemMessages"
:key="message.id"
:class="['message-item', { unread: !message.read }]"
@click="viewSystemMessage(message)"
>
<view class="message-icon-wrapper">
<text class="message-icon">📢</text>
</view>
<view class="message-content">
<view class="message-header">
<text class="message-title">{{ message.title }}</text>
<text class="message-time">{{ message.time }}</text>
</view>
<text class="message-preview">{{ message.content }}</text>
<view v-if="message.important" class="important-tag">重要</view>
</view>
</view>
</view>
<!-- 订单消息 -->
<view v-if="activeTab === 'order'" class="message-section">
<view
v-for="message in orderMessages"
:key="message.id"
:class="['message-item', { unread: !message.read }]"
@click="viewOrderMessage(message)"
>
<view class="message-icon-wrapper">
<text class="message-icon">📦</text>
</view>
<view class="message-content">
<view class="message-header">
<text class="message-title">{{ message.title }}</text>
<text class="message-time">{{ message.time }}</text>
</view>
<text class="message-preview">{{ message.content }}</text>
<text class="order-info" v-if="message.order_no">订单号: {{ message.order_no }}</text>
<view v-if="message.status" class="order-status" :class="message.status">
{{ message.statusText }}
</view>
</view>
</view>
</view>
<!-- 优惠活动 -->
<view v-if="activeTab === 'promo'" class="message-section">
<view
v-for="message in promoMessages"
:key="message.id"
:class="['message-item', { unread: !message.read }]"
@click="viewPromoMessage(message)"
>
<view class="message-icon-wrapper">
<text class="message-icon">🎁</text>
</view>
<view class="message-content">
<view class="message-header">
<text class="message-title">{{ message.title }}</text>
<text class="message-time">{{ message.time }}</text>
</view>
<text class="message-preview">{{ message.content }}</text>
<view v-if="message.coupon" class="coupon-info" @click.stop="claimCoupon(message)">
<text class="coupon-text">{{ message.coupon }}优惠券</text>
<text class="coupon-expiry">有效期至 {{ message.expiry }}</text>
<text class="coupon-action">{{ message.claimed ? '已领取' : '点击领取' }}</text>
</view>
</view>
</view>
</view>
<!-- 空状态 -->
<view v-if="!loading && currentMessages.length === 0 && activeTab !== 'service'" class="empty-messages">
<text class="empty-icon">💬</text>
<text class="empty-title">暂无消息</text>
<text class="empty-desc">暂时没有新消息</text>
</view>
<!-- 底部安全区域 -->
<view class="safe-area"></view>
</scroll-view>
<!-- 底部固定按钮 -->
<view class="floating-action">
<button class="action-button" @click="startNewChat">
<text class="button-icon">✏️</text>
<text class="button-text">新建聊天</text>
</button>
</view>
</view>
</template>
<script setup lang="uts">
import { ref, reactive, computed, onMounted } from 'vue'
// 响应式数据
const activeTab = ref<string>('service')
const refreshing = ref<boolean>(false)
const loading = ref<boolean>(false)
const unreadCount = ref<number>(12)
const statusBarHeight = ref(0)
const scrollTop = ref(0)
// 初始化页面布局数据
const initPage = () => {
const systemInfo = uni.getSystemInfoSync()
statusBarHeight.value = systemInfo.statusBarHeight || 0
// 计算滚动区域高度:屏幕高度 - 状态栏 - 导航栏(44) - 标签栏(42)
const windowHeight = systemInfo.windowHeight
scrollHeight.value = windowHeight - statusBarHeight.value - 44 - 42
}
// 消息分类标签
const messageTabs = reactive([
{ id: 'service', name: '客服消息', unread: 5 },
{ id: 'system', name: '系统通知', unread: 3 },
{ id: 'order', name: '订单消息', unread: 2 },
{ id: 'promo', name: '优惠活动', unread: 2 }
])
// Mock 客服消息数据
const serviceMessages = reactive([
{
id: 'service001',
title: '康乐医药在线客服',
role: '官方客服',
content: '您好,我是康乐医药在线客服,有什么可以帮助您的吗?',
lastMessage: '请问有什么药品需要咨询?',
time: '刚刚',
read: false,
type: 'service',
avatar: 'https://picsum.photos/50/50?random=service1',
online: true,
unreadCount: 3,
tags: ['在线', '专业药师'],
icon: '👨‍⚕️',
color: '#4CAF50'
},
{
id: 'service002',
title: '处方药咨询',
role: '药师',
content: '关于您的处方药咨询,我们已经收到,请提供处方照片。',
lastMessage: '已收到您的处方,正在审核中...',
time: '10:30',
read: true,
type: 'service',
avatar: 'https://picsum.photos/50/50?random=service2',
online: true,
unreadCount: 0,
tags: ['处方药', '审核'],
icon: '💊',
color: '#2196F3'
},
{
id: 'service003',
title: '药品配送服务',
role: '配送客服',
content: '您的订单预计今天下午送达,请保持电话畅通。',
lastMessage: '配送员正在路上预计30分钟内送达',
time: '09:45',
read: false,
type: 'service',
avatar: 'https://picsum.photos/50/50?random=service3',
online: true,
unreadCount: 1,
tags: ['配送中', '今日达'],
icon: '🚚',
color: '#FF9800'
},
{
id: 'service004',
title: '用药指导',
role: '临床药师',
content: '关于您咨询的药品服用方法,建议饭后半小时服用。',
lastMessage: '记得按时服药,如有不适及时联系',
time: '昨天',
read: true,
type: 'service',
avatar: 'https://picsum.photos/50/50?random=service4',
online: false,
unreadCount: 0,
tags: ['用药指导', '专业'],
icon: '📋',
color: '#9C27B0'
},
{
id: 'service005',
title: '售后服务中心',
role: '售后专员',
content: '您申请的药品退换货已受理,我们会尽快处理。',
lastMessage: '退款将在3-5个工作日内退回原账户',
time: '前天',
read: false,
type: 'service',
avatar: 'https://picsum.photos/50/50?random=service5',
online: true,
unreadCount: 2,
tags: ['售后', '退换货'],
icon: '🔄',
color: '#F44336'
}
])
// Mock 系统通知数据
const systemMessages = reactive([
{
id: 'sys001',
title: '系统维护通知',
content: '平台将于今晚23:00-01:00进行系统维护届时部分功能可能无法使用。',
time: '2023-11-23 15:30',
read: false,
type: 'system',
important: true
},
{
id: 'sys002',
title: '隐私政策更新',
content: '我们已更新隐私政策,请查阅相关条款。',
time: '2023-11-22 10:15',
read: true,
type: 'system',
important: false
},
{
id: 'sys003',
title: '账户安全提醒',
content: '检测到您的账户在异地登录,如果不是您本人操作,请及时修改密码。',
time: '2023-11-21 18:45',
read: false,
type: 'system',
important: true
}
])
// Mock 订单消息数据
const orderMessages = reactive([
{
id: 'order001',
title: '订单发货通知',
content: '您的订单202311230001已发货点击查看物流信息。',
time: '2023-11-23 14:20',
read: false,
type: 'order',
order_no: '202311230001',
status: 'shipping',
statusText: '配送中'
},
{
id: 'order002',
title: '订单支付成功',
content: '您的订单202311220001支付成功商家正在备货中。',
time: '2023-11-22 09:30',
read: false,
type: 'order',
order_no: '202311220001',
status: 'processing',
statusText: '处理中'
},
{
id: 'order003',
title: '订单确认收货',
content: '您的订单202311210001已完成期待您的评价。',
time: '2023-11-21 16:15',
read: true,
type: 'order',
order_no: '202311210001',
status: 'completed',
statusText: '已完成'
}
])
// Mock 优惠活动数据
const promoMessages = reactive([
{
id: 'promo001',
title: '新人专享券',
content: '您有一张新人专享优惠券已到账有效期3天。',
time: '2023-11-23 08:00',
read: false,
type: 'promo',
coupon: '50元',
expiry: '2023-11-26',
claimed: false
},
{
id: 'promo002',
title: '双11大促',
content: '双11狂欢购物节全场满300减50。',
time: '2023-11-22 12:30',
read: true,
type: 'promo',
coupon: '满300减50',
expiry: '2023-11-30',
claimed: false
}
])
// 计算当前显示的消息
const currentMessages = computed(() => {
switch (activeTab.value) {
case 'system': return systemMessages
case 'order': return orderMessages
case 'service': return serviceMessages
case 'promo': return promoMessages
default: return []
}
})
// 生命周期
onMounted(() => {
initPage()
loadMessages()
})
// 加载消息
const loadMessages = () => {
loading.value = true
setTimeout(() => {
// 模拟加载消息数据
updateUnreadCount()
loading.value = false
}, 800)
}
// 更新未读数量
const updateUnreadCount = () => {
let totalUnread = 0
const serviceUnread = serviceMessages.filter(msg => !msg.read).length
messageTabs[0].unread = serviceUnread
totalUnread += serviceUnread
const systemUnread = systemMessages.filter(msg => !msg.read).length
messageTabs[1].unread = systemUnread
totalUnread += systemUnread
const orderUnread = orderMessages.filter(msg => !msg.read).length
messageTabs[2].unread = orderUnread
totalUnread += orderUnread
const promoUnread = promoMessages.filter(msg => !msg.read).length
messageTabs[3].unread = promoUnread
totalUnread += promoUnread
unreadCount.value = totalUnread
}
// 切换标签
const switchTab = (tabId: string) => {
activeTab.value = tabId
// 切换标签时回到顶部,使用微小变化触发滚动更新
scrollTop.value = scrollTop.value === 0 ? 0.01 : 0
}
// 开始与客服聊天
const startChatWithService = (message: any) => {
message.read = true
message.unreadCount = 0
updateUnreadCount()
uni.navigateTo({
url: `/pages/mall/consumer/chat?id=${message.id}&name=${encodeURIComponent(message.title)}&role=${encodeURIComponent(message.role)}`
})
}
// 快速开始服务
const startQuickService = (category: string) => {
uni.navigateTo({
url: `/pages/mall/consumer/chat?category=${encodeURIComponent(category)}`
})
}
// 新建聊天
const startNewChat = () => {
uni.showActionSheet({
itemList: ['用药咨询', '处方咨询', '副作用咨询', '药品配送', '其他问题'],
success: (res) => {
const categories = ['用药咨询', '处方咨询', '副作用咨询', '药品配送', '其他问题']
const category = categories[res.tapIndex]
startQuickService(category)
}
})
}
// 查看系统消息
const viewSystemMessage = (message: any) => {
message.read = true
updateUnreadCount()
uni.navigateTo({
url: `/pages/mall/consumer/message-detail?id=${message.id}&type=system`
})
}
// 查看订单消息
const viewOrderMessage = (message: any) => {
message.read = true
updateUnreadCount()
uni.navigateTo({
url: `/pages/mall/consumer/order-detail?id=${message.order_no}`
})
}
// 查看优惠活动
const viewPromoMessage = (message: any) => {
message.read = true
updateUnreadCount()
uni.navigateTo({
url: `/pages/mall/consumer/coupons`
})
}
// 领取优惠券
const claimCoupon = (message: any) => {
if (message.claimed) {
uni.showToast({
title: '您已领取该优惠券',
icon: 'none'
})
return
}
message.claimed = true
// 保存领取状态到本地存储,供个人页读取
const claimedCouponsCount = uni.getStorageSync('claimedCoupons') || 0
uni.setStorageSync('claimedCoupons', (claimedCouponsCount as number) + 1)
// 保存详细的优惠券信息到 myCoupons 列表
const myCoupons = uni.getStorageSync('myCoupons')
let couponsList: any[] = []
if (myCoupons) {
try {
couponsList = JSON.parse(myCoupons as string) as any[]
} catch (e) {
console.error('Failed to parse myCoupons', e)
}
}
couponsList.push({
title: message.title,
amount: message.coupon,
expiry: message.expiry,
id: message.id
})
uni.setStorageSync('myCoupons', JSON.stringify(couponsList))
uni.showToast({
title: '领取成功',
icon: 'success'
})
}
// 清除所有未读
const clearAllUnread = () => {
uni.showModal({
title: '确认操作',
content: '确定要标记所有消息为已读吗?',
success: (res) => {
if (res.confirm) {
serviceMessages.forEach(msg => {
msg.read = true
msg.unreadCount = 0
})
systemMessages.forEach(msg => msg.read = true)
orderMessages.forEach(msg => msg.read = true)
promoMessages.forEach(msg => msg.read = true)
messageTabs.forEach(tab => tab.unread = 0)
unreadCount.value = 0
uni.showToast({
title: '已标记所有消息为已读',
icon: 'success'
})
}
}
})
}
// 下拉刷新
const onRefresh = () => {
refreshing.value = true
setTimeout(() => {
loadMessages()
refreshing.value = false
uni.showToast({
title: '刷新成功',
icon: 'success'
})
}, 1000)
}
</script>
<style>
/* 页面结构优化 - 避免双滚动条 */
.messages-page {
width: 100%;
height: 100vh;
background-color: #f8fafc;
display: flex;
flex-direction: column;
overflow: hidden; /* 关键防止body滚动 */
}
/* 智能导航栏 */
.smart-navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
background: linear-gradient(135deg, #4CAF50 0%, #2E7D32 100%);
z-index: 1000;
box-shadow: 0 2px 12px rgba(76, 175, 80, 0.15);
/* height: 50px; 移除固定高度,由内容决定 */
display: flex;
flex-direction: row; /* 显式设置行方向 */
align-items: center;
justify-content: center;
flex-shrink: 0; /* 防止被压缩 */
}
.nav-container {
padding: 0 16px;
display: flex;
flex-direction: row; /* 关键修复UVUE默认是column必须显式设置为row才能横向排列 */
align-items: center;
justify-content: space-between;
width: 100%;
max-width: 1400px;
margin: 0 auto;
height: 44px; /* 调整为标准高度 44px */
}
.nav-title {
font-size: 18px;
font-weight: bold;
color: white;
flex: 1; /* 自适应宽度 */
}
.nav-actions {
display: flex;
flex-direction: row; /* 显式设置行方向 */
align-items: center;
}
.action-btn {
display: flex;
flex-direction: row; /* 显式设置行方向 */
align-items: center;
background: rgba(255, 255, 255, 0.2);
padding: 4px 12px;
border-radius: 20px;
cursor: pointer;
transition: all 0.2s ease;
}
.action-btn:hover {
background: rgba(255, 255, 255, 0.3);
}
.action-icon {
font-size: 14px;
margin-right: 4px;
}
.action-text {
font-size: 12px;
color: white;
font-weight: 500;
}
/* 导航栏占位符 */
.navbar-placeholder {
width: 100%;
flex-shrink: 0;
}
/* 消息分类标签容器 */
.tabs-container {
background: white;
padding: 0 10px;
border-bottom: 1px solid #e0e0e0;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
z-index: 900;
height: 42px; /* 减小高度,更紧凑 */
flex-shrink: 0;
}
.message-tabs {
display: flex;
flex-direction: row; /* 横向排列 */
height: 100%;
/* overflow-x: auto; 移除自动滚动,改为自适应宽度 */
max-width: 1400px;
margin: 0 auto;
gap: 4px; /* 减小间距 */
justify-content: space-between; /* 均匀分布 */
}
.message-tabs::-webkit-scrollbar {
display: none;
}
.tab-item {
padding: 0 4px;
display: flex; /* 改为 flex 布局 */
flex-direction: row; /* 关键:横向排列 文字和数字 */
align-items: center; /* 垂直居中 */
justify-content: center;
position: relative;
height: 100%;
border-bottom: 3px solid transparent;
transition: all 0.3s ease;
white-space: nowrap; /* 防止换行 */
flex: 1; /* 关键:均分宽度,消除滚动条 */
min-width: 0; /* 允许压缩 */
}
.tab-item.active {
color: #4CAF50;
border-bottom-color: #4CAF50;
font-weight: bold;
}
.tab-name {
font-size: 14px; /* 微调字体大小适配小屏 */
overflow: hidden;
text-overflow: ellipsis;
}
/* 徽标样式优化 - 放在文字右边 */
.tab-badge {
background-color: #FF5722;
color: white;
font-size: 10px;
padding: 1px 5px;
border-radius: 10px;
min-width: 16px;
text-align: center;
font-weight: bold;
margin-left: 4px; /* 距离文字的间距 */
display: flex;
align-items: center;
justify-content: center;
height: 16px;
}
/* 消息内容区 */
.messages-content {
flex: 1; /* 关键:自适应剩余高度 */
height: 0; /* 关键强制flex item计算高度 */
width: 100%;
max-width: 1400px;
margin: 0 auto;
padding-bottom: 20px;
}
/* 客服信息区域 */
.customer-service-info {
background: white;
border-radius: 12px;
padding: 20px;
margin: 15px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.service-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.service-title {
font-size: 18px;
font-weight: bold;
color: #333;
}
.service-status {
font-size: 12px;
padding: 4px 10px;
border-radius: 12px;
font-weight: 500;
}
.service-status.online {
background: #E8F5E9;
color: #4CAF50;
}
.service-desc {
font-size: 14px;
color: #666;
line-height: 1.5;
margin-bottom: 20px;
}
.service-categories {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
.category-item {
background: #f8f9fa;
border-radius: 10px;
padding: 15px;
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
transition: all 0.3s ease;
}
.category-item:hover {
background: #e8f5e9;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(76, 175, 80, 0.2);
}
.category-icon {
font-size: 24px;
margin-bottom: 8px;
}
.category-name {
font-size: 13px;
color: #333;
font-weight: 500;
}
/* 消息项 */
.message-section {
padding: 10px;
}
.message-item {
background-color: white;
border-radius: 12px;
padding: 15px;
margin-bottom: 10px;
display: flex;
align-items: flex-start;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
cursor: pointer;
}
.message-item:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
}
.message-item.unread {
background-color: #f0f9f0;
border-left: 3px solid #4CAF50;
}
.message-item.active {
border: 1px solid #4CAF50;
}
.message-icon-wrapper {
width: 50px;
height: 50px;
border-radius: 25px;
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
margin-right: 15px;
flex-shrink: 0;
position: relative;
}
.message-icon-default {
width: 100%;
height: 100%;
border-radius: 25px;
display: flex;
align-items: center;
justify-content: center;
}
.message-icon-default text {
font-size: 24px;
color: white;
}
.message-avatar {
width: 100%;
height: 100%;
border-radius: 25px;
}
.online-dot {
position: absolute;
bottom: 2px;
right: 2px;
width: 12px;
height: 12px;
background-color: #4CAF50;
border-radius: 6px;
border: 2px solid white;
}
.message-content {
flex: 1;
min-width: 0;
}
.message-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 8px;
}
.message-title-wrapper {
flex: 1;
min-width: 0;
margin-right: 10px;
}
.message-title {
font-size: 16px;
color: #333;
font-weight: bold;
display: block;
margin-bottom: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.message-role {
font-size: 12px;
color: #4CAF50;
background: #E8F5E9;
padding: 2px 8px;
border-radius: 10px;
display: inline-block;
}
.message-header-right {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 4px;
}
.message-time {
font-size: 12px;
color: #999;
white-space: nowrap;
}
.message-unread-count {
font-size: 11px;
color: white;
background: #FF5722;
padding: 2px 6px;
border-radius: 10px;
min-width: 18px;
text-align: center;
font-weight: bold;
}
.message-preview-wrapper {
margin-bottom: 8px;
}
.message-preview {
font-size: 14px;
color: #666;
line-height: 1.4;
margin-bottom: 4px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.last-message {
font-size: 13px;
color: #999;
display: block;
}
.message-tags {
display: flex;
gap: 6px;
flex-wrap: wrap;
}
.message-tag {
font-size: 11px;
color: #666;
background: #f0f0f0;
padding: 3px 8px;
border-radius: 10px;
}
.order-info {
font-size: 12px;
color: #4CAF50;
background-color: #E8F5E9;
padding: 4px 10px;
border-radius: 4px;
display: inline-block;
margin-top: 8px;
}
.order-status {
display: inline-block;
font-size: 12px;
padding: 4px 10px;
border-radius: 12px;
margin-top: 8px;
margin-left: 8px;
}
.order-status.shipping {
background: #E3F2FD;
color: #2196F3;
}
.order-status.processing {
background: #FFF3E0;
color: #FF9800;
}
.order-status.completed {
background: #E8F5E9;
color: #4CAF50;
}
.important-tag {
display: inline-block;
background-color: #FF5722;
color: white;
font-size: 11px;
padding: 3px 8px;
border-radius: 10px;
margin-top: 8px;
}
.coupon-info {
background: linear-gradient(135deg, #FF9800, #FF5722);
border-radius: 8px;
padding: 10px;
margin-top: 8px;
color: white;
}
.coupon-text {
font-size: 14px;
font-weight: bold;
display: block;
margin-bottom: 4px;
}
.coupon-expiry {
font-size: 12px;
opacity: 0.9;
}
.coupon-action {
font-size: 12px;
color: #fff;
background-color: rgba(255, 255, 255, 0.2);
padding: 2px 8px;
border-radius: 10px;
margin-top: 4px;
align-self: flex-start;
}
/* 客服系统提示 */
.service-tips {
background: #FFF3E0;
border-radius: 10px;
padding: 15px;
margin: 15px;
display: flex;
align-items: flex-start;
gap: 10px;
}
.tip-icon {
font-size: 18px;
color: #FF9800;
flex-shrink: 0;
margin-top: 2px;
}
.tip-text {
font-size: 13px;
color: #666;
line-height: 1.5;
}
/* 空状态 */
.empty-messages {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 80px 20px;
text-align: center;
}
.empty-icon {
font-size: 80px;
color: #ddd;
margin-bottom: 20px;
}
.empty-title {
font-size: 18px;
color: #666;
margin-bottom: 10px;
}
.empty-desc {
font-size: 14px;
color: #999;
}
/* 底部浮动按钮 */
.floating-action {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 100;
}
.action-button {
background: linear-gradient(135deg, #4CAF50, #2E7D32);
color: white;
border: none;
border-radius: 25px;
padding: 12px 20px;
display: flex;
align-items: center;
box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3);
font-weight: 500;
}
.button-icon {
font-size: 18px;
margin-right: 8px;
}
.button-text {
font-size: 14px;
font-weight: bold;
}
.safe-area {
height: 80px;
}
/* 响应式适配 */
@media screen and (max-width: 320px) {
.tab-name {
font-size: 13px;
}
.service-categories {
grid-template-columns: 1fr;
}
}
@media screen and (min-width: 415px) {
.message-item {
padding: 20px;
}
.message-icon-wrapper {
width: 60px;
height: 60px;
border-radius: 30px;
}
.message-icon-default text {
font-size: 28px;
}
.customer-service-info {
padding: 25px;
}
.service-categories {
grid-template-columns: repeat(4, 1fr);
}
/* 平板和桌面端优化标签栏显示 */
.message-tabs {
justify-content: flex-start; /* 左对齐 */
}
.tab-item {
padding: 0 24px; /* 增加点击区域 */
}
}
/* 平板设备 */
@media screen and (min-width: 768px) {
.smart-navbar {
padding: 0 30px;
}
.tabs-container {
padding: 0 30px;
}
.message-section {
padding: 20px 30px;
}
.customer-service-info {
margin: 20px 30px;
}
.service-tips {
margin: 20px 30px;
}
}
/* 暗黑模式适配 */
@media (prefers-color-scheme: dark) {
.messages-page {
background-color: #121212;
}
.smart-navbar {
background: linear-gradient(135deg, #2E7D32 0%, #1B5E20 100%);
}
.tabs-container {
background-color: #1e1e1e;
border-bottom-color: #333;
}
.tab-item.active {
color: #4CAF50;
}
.customer-service-info,
.message-item,
.service-tips {
background-color: #1e1e1e;
}
.message-item.unread {
background-color: #2d2d2d;
}
.category-item {
background: #2d2d2d;
}
.category-name {
color: #fff;
}
.service-title,
.message-title {
color: #fff;
}
.service-desc,
.message-preview,
.last-message,
.tip-text {
color: #aaa;
}
.message-icon-wrapper {
background-color: #2d2d2d;
}
.order-info {
background-color: #1b5e20;
color: #a5d6a7;
}
.coupon-info {
background: linear-gradient(135deg, #ff8f00, #ef6c00);
}
.message-tag {
background: #333;
color: #ccc;
}
.action-btn {
background: rgba(255, 255, 255, 0.1);
}
.action-btn:hover {
background: rgba(255, 255, 255, 0.2);
}
}
</style>