feat(miniprogram): Phase 5 UI/UX 优化 — 8 项改进
- 首页: 健康资讯推荐 + 空状态引导 + 快捷服务字符图标优化 - 健康 Hub: sparkline bar + 参考范围 + 打卡合并到快捷操作 - 日常监测: 3 分组折叠(晨间/晚间/其他) + 异常值高亮 + 提交前确认 - 预约: 已满时段 pointer-events:none + opacity 优化 - 咨询聊天: 消息日期分组(今天/昨天) + 图片预览 - 积分商城: 确认已有余额大字+签到+库存提示 - 医护工作台: 异常体征横幅 + 患者搜索入口 + 快捷操作扩展 - 趋势图表: 骨架屏加载状态 + ECharts 异常标记已有
This commit is contained in:
@@ -73,6 +73,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
.msg-date-divider {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 16px 0 12px;
|
||||
|
||||
&__text {
|
||||
font-size: 22px;
|
||||
color: #94A3B8;
|
||||
background: #F1F5F9;
|
||||
padding: 4px 16px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.msg-image {
|
||||
width: 320px;
|
||||
border-radius: 12px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.msg-time {
|
||||
font-size: 20px;
|
||||
color: $tx3;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { View, Text, Input, ScrollView } from '@tarojs/components';
|
||||
import { View, Text, Input, Image, ScrollView } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import {
|
||||
getSession,
|
||||
@@ -116,6 +116,24 @@ export default function ConsultationDetail() {
|
||||
return d.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
|
||||
};
|
||||
|
||||
const getDateLabel = (dateStr: string): string => {
|
||||
const d = new Date(dateStr);
|
||||
const today = new Date();
|
||||
const yesterday = new Date();
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
|
||||
const dStr = d.toDateString();
|
||||
if (dStr === today.toDateString()) return '今天';
|
||||
if (dStr === yesterday.toDateString()) return '昨天';
|
||||
return d.toLocaleDateString('zh-CN', { month: 'long', day: 'numeric' });
|
||||
};
|
||||
|
||||
const isDifferentDay = (a: string, b: string): boolean => {
|
||||
return new Date(a).toDateString() !== new Date(b).toDateString();
|
||||
};
|
||||
|
||||
const isImageUrl = (url: string) => /\.(jpg|jpeg|png|gif|webp)(\?.*)?$/i.test(url);
|
||||
|
||||
if (loading) return <Loading />;
|
||||
|
||||
const isOpen = session?.status !== 'closed';
|
||||
@@ -137,11 +155,28 @@ export default function ConsultationDetail() {
|
||||
>
|
||||
{messages.map((msg, idx) => {
|
||||
const isSelf = msg.sender_role === 'patient';
|
||||
const showDateDivider = idx === 0 || isDifferentDay(msg.created_at, messages[idx - 1].created_at);
|
||||
return (
|
||||
<View key={msg.id} id={`msg-${idx + 1}`} className={`msg-row ${isSelf ? 'msg-row--self' : ''}`}>
|
||||
<View className={`msg-bubble ${isSelf ? 'msg-bubble--self' : 'msg-bubble--other'}`}>
|
||||
<Text className='msg-text'>{msg.content}</Text>
|
||||
<Text className='msg-time'>{formatTime(msg.created_at)}</Text>
|
||||
<View key={msg.id}>
|
||||
{showDateDivider && (
|
||||
<View className='msg-date-divider'>
|
||||
<Text className='msg-date-divider__text'>{getDateLabel(msg.created_at)}</Text>
|
||||
</View>
|
||||
)}
|
||||
<View id={`msg-${idx + 1}`} className={`msg-row ${isSelf ? 'msg-row--self' : ''}`}>
|
||||
<View className={`msg-bubble ${isSelf ? 'msg-bubble--self' : 'msg-bubble--other'}`}>
|
||||
{isImageUrl(msg.content) ? (
|
||||
<Image
|
||||
className='msg-image'
|
||||
src={msg.content}
|
||||
mode='widthFix'
|
||||
onClick={() => Taro.previewImage({ urls: [msg.content], current: msg.content })}
|
||||
/>
|
||||
) : (
|
||||
<Text className='msg-text'>{msg.content}</Text>
|
||||
)}
|
||||
<Text className='msg-time'>{formatTime(msg.created_at)}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user