feat(mp): 首页设备状态卡片组件 — 血压计/血糖仪快捷入口
This commit is contained in:
51
apps/miniprogram/src/components/DeviceCard/index.scss
Normal file
51
apps/miniprogram/src/components/DeviceCard/index.scss
Normal file
@@ -0,0 +1,51 @@
|
||||
@import '../../styles/variables.scss';
|
||||
|
||||
.device-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
background: $card;
|
||||
border-radius: $r;
|
||||
margin-bottom: 16rpx;
|
||||
box-shadow: $shadow-sm;
|
||||
|
||||
.device-icon {
|
||||
font-size: 48rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.device-info {
|
||||
flex: 1;
|
||||
|
||||
.device-name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: $tx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.device-status {
|
||||
font-size: 24rpx;
|
||||
margin-top: 4rpx;
|
||||
display: block;
|
||||
|
||||
&.connected { color: $pri; }
|
||||
&.idle { color: $tx3; }
|
||||
}
|
||||
|
||||
.last-sync {
|
||||
font-size: 22rpx;
|
||||
color: $tx3;
|
||||
margin-top: 4rpx;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.sync-btn {
|
||||
padding: 12rpx 28rpx;
|
||||
background: $pri;
|
||||
color: #fff;
|
||||
border-radius: $r-pill;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
39
apps/miniprogram/src/components/DeviceCard/index.tsx
Normal file
39
apps/miniprogram/src/components/DeviceCard/index.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import './index.scss';
|
||||
|
||||
interface DeviceCardProps {
|
||||
deviceName: string;
|
||||
deviceType: string;
|
||||
lastSyncAt?: string;
|
||||
status: 'connected' | 'disconnected' | 'never';
|
||||
}
|
||||
|
||||
const DEVICE_ICONS: Record<string, string> = {
|
||||
blood_pressure: '\u{1FA7A}',
|
||||
blood_glucose: '\u{1FA78}',
|
||||
heart_rate: '\u{2764}',
|
||||
blood_oxygen: '\u{1FAB1}',
|
||||
};
|
||||
|
||||
export default function DeviceCard({ deviceName, deviceType, lastSyncAt, status }: DeviceCardProps) {
|
||||
const icon = DEVICE_ICONS[deviceType] || '\u{1F4F1}';
|
||||
const statusLabel = status === 'connected' ? '已连接' : status === 'disconnected' ? '未连接' : '未配对';
|
||||
const statusClass = status === 'connected' ? 'connected' : 'idle';
|
||||
|
||||
const handleSync = () => {
|
||||
Taro.navigateTo({ url: '/pages/device-sync/index' });
|
||||
};
|
||||
|
||||
return (
|
||||
<View className='device-card' onClick={handleSync}>
|
||||
<View className='device-icon'>{icon}</View>
|
||||
<View className='device-info'>
|
||||
<Text className='device-name'>{deviceName}</Text>
|
||||
<Text className={`device-status ${statusClass}`}>{statusLabel}</Text>
|
||||
{lastSyncAt && <Text className='last-sync'>最近同步: {lastSyncAt}</Text>}
|
||||
</View>
|
||||
<View className='sync-btn'>同步</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { useState } from 'react';
|
||||
import Taro, { useDidShow } from '@tarojs/taro';
|
||||
import { useAuthStore } from '../../stores/auth';
|
||||
import { useHealthStore } from '../../stores/health';
|
||||
import EmptyState from '../../components/EmptyState';
|
||||
import DeviceCard from '../../components/DeviceCard';
|
||||
import Loading from '../../components/Loading';
|
||||
import { trackPageView } from '@/services/analytics';
|
||||
import * as appointmentApi from '@/services/appointment';
|
||||
@@ -13,8 +13,8 @@ import './index.scss';
|
||||
|
||||
const QUICK_SERVICES = [
|
||||
{ label: '预约挂号', char: '约', path: '/pages/appointment/create/index' },
|
||||
{ label: '健康录入', char: '录', path: '/pages/health/input/index' },
|
||||
{ label: '健康趋势', char: '势', path: '/pages/health/trend/index' },
|
||||
{ label: '健康录入', char: '录', path: '/pages/pkg-health/input/index' },
|
||||
{ label: '健康趋势', char: '势', path: '/pages/pkg-health/trend/index' },
|
||||
{ label: '资讯文章', char: '文', path: '/pages/article/index' },
|
||||
{ label: 'AI 报告', char: 'AI', path: '/pages/ai-report/list/index' },
|
||||
];
|
||||
@@ -123,6 +123,20 @@ export default function Index() {
|
||||
<Text className='greeting-date'>{new Date().toLocaleDateString('zh-CN', { month: 'long', day: 'numeric', weekday: 'short' })}</Text>
|
||||
</View>
|
||||
|
||||
{/* 设备快捷入口 */}
|
||||
<View className='device-section'>
|
||||
<DeviceCard
|
||||
deviceName='血压计'
|
||||
deviceType='blood_pressure'
|
||||
status='never'
|
||||
/>
|
||||
<DeviceCard
|
||||
deviceName='血糖仪'
|
||||
deviceType='blood_glucose'
|
||||
status='never'
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* 今日健康 */}
|
||||
<View className='health-section'>
|
||||
<Text className='section-title'>今日健康</Text>
|
||||
@@ -132,7 +146,7 @@ export default function Index() {
|
||||
<View className='health-empty'>
|
||||
<Text className='health-empty-text'>今天还没录入数据</Text>
|
||||
<View className='health-empty-action'>
|
||||
<View className='health-empty-btn' onClick={() => Taro.navigateTo({ url: '/pages/health/input/index' })}>
|
||||
<View className='health-empty-btn' onClick={() => Taro.navigateTo({ url: '/pages/pkg-health/input/index' })}>
|
||||
<Text className='health-empty-btn-text'>点击开始记录</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -142,7 +156,7 @@ export default function Index() {
|
||||
{healthItems.map((item) => {
|
||||
const tag = getStatusTag(item.status);
|
||||
return (
|
||||
<View className='health-cell' key={item.label} onClick={() => Taro.navigateTo({ url: `/pages/health/trend/index?indicator=${item.label === '血压' ? 'blood_pressure_systolic' : item.label === '心率' ? 'heart_rate' : item.label === '血糖' ? 'blood_sugar_fasting' : 'weight'}` })}>
|
||||
<View className='health-cell' key={item.label} onClick={() => Taro.navigateTo({ url: `/pages/pkg-health/trend/index?indicator=${item.label === '血压' ? 'blood_pressure_systolic' : item.label === '心率' ? 'heart_rate' : item.label === '血糖' ? 'blood_sugar_fasting' : 'weight'}` })}>
|
||||
<Text className='health-cell-label'>{item.label}</Text>
|
||||
<Text className='health-cell-value'>{item.value}</Text>
|
||||
<View className='health-cell-bottom'>
|
||||
|
||||
Reference in New Issue
Block a user