958 lines
21 KiB
Vue
958 lines
21 KiB
Vue
<template>
|
||
<view class="health-charts-container page-container-with-bg">
|
||
<!-- 健康状态总览卡片 -->
|
||
<view class="health-overview-card">
|
||
<view class="overview-header">
|
||
<text class="pet-name">{{ petName }}的健康档案</text>
|
||
<text class="last-update">最后更新:{{ lastUpdateTime }}</text>
|
||
</view>
|
||
|
||
<view class="health-summary">
|
||
<view class="health-score-section">
|
||
<view class="score-circle">
|
||
<view class="circle-progress" :style="{ background: `conic-gradient(${getScoreColor()} 0deg, ${getScoreColor()} ${healthScore * 3.6}deg, #E0E0E0 ${healthScore * 3.6}deg)` }">
|
||
<view class="circle-center">
|
||
<text class="score-value">{{ healthScore }}</text>
|
||
<text class="score-label">健康评分</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="score-details">
|
||
<view class="score-item">
|
||
<text class="score-name">体重状态</text>
|
||
<text class="score-points" :style="{ color: getStatusColor(weightData.status) }">{{ weightData.weightScore }}分</text>
|
||
</view>
|
||
<view class="score-item">
|
||
<text class="score-name">疫苗状态</text>
|
||
<text class="score-points" :style="{ color: getStatusColor(vaccineData.status) }">{{ vaccineData.vaccineScore }}分</text>
|
||
</view>
|
||
<view class="score-item">
|
||
<text class="score-name">医疗记录</text>
|
||
<text class="score-points" :style="{ color: getStatusColor(medicalData.status) }">{{ medicalData.medicalScore }}分</text>
|
||
</view>
|
||
<view class="score-item">
|
||
<text class="score-name">生长发育</text>
|
||
<text class="score-points" :style="{ color: getStatusColor(growthData.status) }">{{ growthData.growthScore }}分</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="health-trend">
|
||
<view class="trend-indicator" :class="healthTrend">
|
||
<text class="trend-icon">{{ getTrendIcon() }}</text>
|
||
<text class="trend-text">{{ getTrendText() }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="risk-alerts" v-if="riskFactors.length > 0">
|
||
<text class="alerts-title">⚠️ 风险提醒</text>
|
||
<view class="alert-item" v-for="risk in riskFactors" :key="risk.type" :class="risk.level">
|
||
<text class="alert-text">{{ risk.description }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 时间维度切换 -->
|
||
<view class="time-selector">
|
||
<view class="selector-header">
|
||
<text class="selector-title">📊 数据视图</text>
|
||
</view>
|
||
<view class="time-tabs">
|
||
<view
|
||
class="time-tab"
|
||
:class="{ active: activeTimeRange === range.key }"
|
||
v-for="range in timeRanges"
|
||
:key="range.key"
|
||
@click="switchTimeRange(range.key)"
|
||
>
|
||
<text class="tab-text">{{ range.label }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 多维度数据展示 -->
|
||
<view class="data-charts-section">
|
||
<!-- 体重变化趋势图表 -->
|
||
<view class="chart-card">
|
||
<view class="chart-header">
|
||
<text class="chart-title">📈 体重变化趋势</text>
|
||
<view class="chart-status" :class="weightData.status">
|
||
<text class="status-text">{{ getStatusText(weightData.status) }}</text>
|
||
</view>
|
||
</view>
|
||
<qiun-data-charts
|
||
type="line"
|
||
:opts="weightChartOpts"
|
||
:chartData="weightChartData"
|
||
:canvas2d="true"
|
||
:canvasId="'weightChart'"
|
||
:canvas-id="'weightChart'"
|
||
/>
|
||
<view class="chart-summary">
|
||
<text class="summary-text">当前体重:{{ weightData.currentWeight }}kg,较上周{{ weightData.weeklyChange.change >= 0 ? '增加' : '减少' }}{{ Math.abs(weightData.weeklyChange.change) }}kg</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 疫苗接种状态时间线 -->
|
||
<view class="chart-card">
|
||
<view class="chart-header">
|
||
<text class="chart-title">💉 疫苗接种状态</text>
|
||
<view class="chart-status" :class="vaccineData.status">
|
||
<text class="status-text">{{ getStatusText(vaccineData.status) }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="vaccine-timeline">
|
||
<view class="timeline-summary">
|
||
<view class="summary-item">
|
||
<text class="summary-label">完成度</text>
|
||
<text class="summary-value">{{ vaccineData.statusSummary.completionRate }}%</text>
|
||
</view>
|
||
<view class="summary-item">
|
||
<text class="summary-label">已完成</text>
|
||
<text class="summary-value" style="color: #4CAF50;">{{ vaccineData.statusSummary.completed }}</text>
|
||
</view>
|
||
<view class="summary-item">
|
||
<text class="summary-label">即将到期</text>
|
||
<text class="summary-value" style="color: #FF9800;">{{ vaccineData.statusSummary.expiringSoon }}</text>
|
||
</view>
|
||
<view class="summary-item">
|
||
<text class="summary-label">已过期</text>
|
||
<text class="summary-value" style="color: #F44336;">{{ vaccineData.statusSummary.expired }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 健康记录统计 -->
|
||
<view class="chart-card">
|
||
<view class="chart-header">
|
||
<text class="chart-title">🏥 健康记录统计</text>
|
||
<view class="chart-status" :class="medicalData.status">
|
||
<text class="status-text">{{ getStatusText(medicalData.status) }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="medical-stats">
|
||
<view class="stats-grid">
|
||
<view class="stat-card">
|
||
<text class="stat-number">{{ medicalData.totalRecords }}</text>
|
||
<text class="stat-label">总记录数</text>
|
||
</view>
|
||
<view class="stat-card">
|
||
<text class="stat-number">{{ medicalData.medicalVisits }}</text>
|
||
<text class="stat-label">近期就医</text>
|
||
</view>
|
||
<view class="stat-card">
|
||
<text class="stat-number">{{ medicalData.symptoms }}</text>
|
||
<text class="stat-label">异常症状</text>
|
||
</view>
|
||
<view class="stat-card">
|
||
<text class="stat-number">{{ medicalData.recentRecords }}</text>
|
||
<text class="stat-label">近期记录</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 生长发育曲线 -->
|
||
<view class="chart-card" v-if="showGrowthChart">
|
||
<view class="chart-header">
|
||
<text class="chart-title">📏 生长发育曲线</text>
|
||
<view class="chart-status" :class="growthData.status">
|
||
<text class="status-text">{{ getStatusText(growthData.status) }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="growth-info">
|
||
<view class="growth-stage">
|
||
<text class="stage-label">生长阶段:</text>
|
||
<text class="stage-value">{{ getGrowthStageText() }}</text>
|
||
</view>
|
||
<view class="growth-summary">
|
||
<text class="summary-text">{{ getGrowthSummary() }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- AI健康分析卡片 -->
|
||
<view class="ai-health-analysis">
|
||
<view class="analysis-header">
|
||
<text class="analysis-title">🤖 AI健康分析</text>
|
||
<view class="analysis-badge">
|
||
<text class="badge-text">智能分析</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="analysis-content">
|
||
<view class="analysis-section">
|
||
<text class="section-title">📊 综合评估</text>
|
||
<text class="section-content">{{ aiAnalysis.overallAssessment }}</text>
|
||
</view>
|
||
|
||
<view class="analysis-section">
|
||
<text class="section-title">📈 趋势分析</text>
|
||
<text class="section-content">{{ aiAnalysis.trendAnalysis }}</text>
|
||
</view>
|
||
|
||
<view class="analysis-section">
|
||
<text class="section-title">💡 个性化建议</text>
|
||
<text class="section-content">{{ aiAnalysis.recommendations }}</text>
|
||
</view>
|
||
|
||
<view class="analysis-section">
|
||
<text class="section-title">🛡️ 预防措施</text>
|
||
<text class="section-content">{{ aiAnalysis.preventiveMeasures }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
// 简化的健康管理器 - 从 utils/healthManager.js 和 weightManager.js 移入
|
||
const healthManager = {
|
||
getHealthScore(petId) {
|
||
// 简化的健康评分计算
|
||
return Math.floor(Math.random() * 20) + 80 // 80-100分
|
||
},
|
||
|
||
getHealthSummary(petId) {
|
||
return {
|
||
overall: '良好',
|
||
weight: '正常',
|
||
vaccine: '已完成',
|
||
lastCheckup: '2024-01-15'
|
||
}
|
||
}
|
||
}
|
||
|
||
const weightManager = {
|
||
storageKey: 'pet_weight_records',
|
||
|
||
getWeightRecords(petId) {
|
||
try {
|
||
const allRecords = uni.getStorageSync(this.storageKey) || {}
|
||
let records = allRecords[petId] || []
|
||
|
||
if (records.length === 0) {
|
||
records = this.initializeTestData(petId)
|
||
allRecords[petId] = records
|
||
uni.setStorageSync(this.storageKey, allRecords)
|
||
}
|
||
|
||
return records
|
||
} catch (error) {
|
||
console.error('获取体重记录失败:', error)
|
||
return this.initializeTestData(petId)
|
||
}
|
||
},
|
||
|
||
initializeTestData(petId) {
|
||
const now = new Date()
|
||
const testData = []
|
||
const baseWeight = 3.8
|
||
|
||
for (let i = 90; i >= 0; i -= 7) {
|
||
const date = new Date(now.getTime() - i * 24 * 60 * 60 * 1000)
|
||
const weight = baseWeight + (Math.random() - 0.5) * 0.3
|
||
|
||
testData.push({
|
||
id: Date.now() + i,
|
||
petId: petId,
|
||
weight: parseFloat(weight.toFixed(1)),
|
||
date: date.toISOString().split('T')[0],
|
||
note: i === 0 ? '最新记录' : ''
|
||
})
|
||
}
|
||
|
||
return testData.reverse()
|
||
},
|
||
|
||
addWeightRecord(petId, weight, date, note = '') {
|
||
try {
|
||
const allRecords = uni.getStorageSync(this.storageKey) || {}
|
||
if (!allRecords[petId]) {
|
||
allRecords[petId] = []
|
||
}
|
||
|
||
const newRecord = {
|
||
id: Date.now(),
|
||
petId: petId,
|
||
weight: parseFloat(weight),
|
||
date: date,
|
||
note: note
|
||
}
|
||
|
||
allRecords[petId].push(newRecord)
|
||
allRecords[petId].sort((a, b) => new Date(a.date) - new Date(b.date))
|
||
|
||
uni.setStorageSync(this.storageKey, allRecords)
|
||
return true
|
||
} catch (error) {
|
||
console.error('添加体重记录失败:', error)
|
||
return false
|
||
}
|
||
},
|
||
|
||
getWeightTrend(petId) {
|
||
const records = this.getWeightRecords(petId)
|
||
if (records.length < 2) return 'stable'
|
||
|
||
const recent = records.slice(-3)
|
||
const avg = recent.reduce((sum, r) => sum + r.weight, 0) / recent.length
|
||
const prev = records[records.length - 4]?.weight || avg
|
||
|
||
if (avg > prev + 0.2) return 'increasing'
|
||
if (avg < prev - 0.2) return 'decreasing'
|
||
return 'stable'
|
||
}
|
||
}
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
petId: '',
|
||
petName: '',
|
||
petInfo: {},
|
||
lastUpdateTime: '',
|
||
|
||
// 健康数据
|
||
healthScore: 85,
|
||
healthTrend: 'stable',
|
||
weightData: {},
|
||
vaccineData: {},
|
||
medicalData: {},
|
||
growthData: {},
|
||
riskFactors: [],
|
||
|
||
// 时间范围
|
||
activeTimeRange: 'month',
|
||
timeRanges: [
|
||
{ key: 'week', label: '近一周' },
|
||
{ key: 'month', label: '近一月' },
|
||
{ key: 'year', label: '近一年' },
|
||
{ key: 'all', label: '全部历史' }
|
||
],
|
||
|
||
// 图表配置
|
||
weightChartOpts: {
|
||
color: ["#FF8A80", "#64B5F6"],
|
||
padding: [15, 15, 0, 15],
|
||
enableScroll: false,
|
||
legend: {
|
||
show: false
|
||
},
|
||
xAxis: {
|
||
disableGrid: true,
|
||
fontSize: 10,
|
||
fontColor: "#666666"
|
||
},
|
||
yAxis: {
|
||
gridType: "dash",
|
||
dashLength: 2,
|
||
fontSize: 10,
|
||
fontColor: "#666666"
|
||
},
|
||
extra: {
|
||
line: {
|
||
type: "curve",
|
||
width: 2,
|
||
activeType: "hollow"
|
||
}
|
||
}
|
||
},
|
||
|
||
// 图表数据
|
||
weightChartData: {},
|
||
|
||
// AI分析
|
||
aiAnalysis: {
|
||
overallAssessment: '',
|
||
trendAnalysis: '',
|
||
recommendations: '',
|
||
preventiveMeasures: ''
|
||
}
|
||
}
|
||
},
|
||
|
||
computed: {
|
||
showGrowthChart() {
|
||
return this.petInfo.age < 2 // 只为幼宠显示生长曲线
|
||
}
|
||
},
|
||
|
||
onLoad(options) {
|
||
this.petId = options.petId || ''
|
||
this.petName = options.petName || '宠物'
|
||
this.loadPetInfo()
|
||
this.loadHealthData()
|
||
this.generateChartData()
|
||
},
|
||
|
||
methods: {
|
||
loadPetInfo() {
|
||
try {
|
||
const pets = uni.getStorageSync('pets') || []
|
||
this.petInfo = pets.find(pet => pet.id == this.petId) || {
|
||
id: this.petId,
|
||
name: this.petName,
|
||
breed: '橘猫',
|
||
age: 2,
|
||
gender: '公'
|
||
}
|
||
} catch (error) {
|
||
console.error('加载宠物信息失败:', error)
|
||
}
|
||
},
|
||
|
||
loadHealthData() {
|
||
// 获取综合健康数据
|
||
const healthData = healthManager.getComprehensiveHealthData(this.petId, this.petInfo)
|
||
|
||
this.healthScore = healthData.healthScore
|
||
this.healthTrend = healthData.healthTrend
|
||
this.weightData = healthData.weightData
|
||
this.vaccineData = healthData.vaccineData
|
||
this.medicalData = healthData.medicalData
|
||
this.growthData = healthData.growthData
|
||
this.riskFactors = healthData.riskFactors
|
||
|
||
// 生成AI分析
|
||
this.aiAnalysis = healthManager.generateAIHealthAnalysis(this.petId, this.petInfo)
|
||
|
||
// 更新最后更新时间
|
||
this.lastUpdateTime = new Date().toLocaleString('zh-CN', {
|
||
month: 'numeric',
|
||
day: 'numeric',
|
||
hour: '2-digit',
|
||
minute: '2-digit'
|
||
})
|
||
},
|
||
|
||
switchTimeRange(timeKey) {
|
||
this.activeTimeRange = timeKey
|
||
this.generateChartData()
|
||
},
|
||
|
||
generateChartData() {
|
||
// 生成体重图表数据
|
||
this.weightChartData = weightManager.generateChartData(this.petId, this.activeTimeRange)
|
||
},
|
||
|
||
getScoreColor() {
|
||
if (this.healthScore >= 85) return '#4CAF50'
|
||
if (this.healthScore >= 70) return '#FF9800'
|
||
return '#F44336'
|
||
},
|
||
|
||
getStatusColor(status) {
|
||
const colors = {
|
||
'good': '#4CAF50',
|
||
'warning': '#FF9800',
|
||
'poor': '#F44336'
|
||
}
|
||
return colors[status] || '#666666'
|
||
},
|
||
|
||
getStatusText(status) {
|
||
const texts = {
|
||
'good': '良好',
|
||
'warning': '注意',
|
||
'poor': '需改善'
|
||
}
|
||
return texts[status] || '未知'
|
||
},
|
||
|
||
getTrendIcon() {
|
||
const icons = {
|
||
'improving': '📈',
|
||
'stable': '➡️',
|
||
'declining': '📉'
|
||
}
|
||
return icons[this.healthTrend] || '➡️'
|
||
},
|
||
|
||
getTrendText() {
|
||
const texts = {
|
||
'improving': '改善中',
|
||
'stable': '保持稳定',
|
||
'declining': '需关注'
|
||
}
|
||
return texts[this.healthTrend] || '稳定'
|
||
},
|
||
|
||
getGrowthStageText() {
|
||
const stages = {
|
||
'kitten': '幼猫期',
|
||
'young': '青年期',
|
||
'adult': '成年期',
|
||
'senior': '老年期'
|
||
}
|
||
return stages[this.growthData.growthStage] || '成年期'
|
||
},
|
||
|
||
getGrowthSummary() {
|
||
const stage = this.growthData.growthStage
|
||
const weight = this.growthData.currentWeight
|
||
|
||
if (stage === 'kitten') {
|
||
return `幼猫期体重${weight}kg,生长发育${this.growthData.status === 'good' ? '正常' : '需关注'}`
|
||
} else if (stage === 'senior') {
|
||
return `老年期体重${weight}kg,建议定期体检关注健康状况`
|
||
} else {
|
||
return `${this.getGrowthStageText()}体重${weight}kg,整体发育状况良好`
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.health-charts-container {
|
||
padding: 20rpx;
|
||
}
|
||
|
||
/* 健康状态总览卡片 */
|
||
.health-overview-card {
|
||
background: rgba(255, 255, 255, 0.95);
|
||
backdrop-filter: blur(20rpx);
|
||
border-radius: 28rpx;
|
||
padding: 32rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.2);
|
||
border: 1rpx solid rgba(255, 255, 255, 0.3);
|
||
|
||
.overview-header {
|
||
text-align: center;
|
||
margin-bottom: 32rpx;
|
||
|
||
.pet-name {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
display: block;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.last-update {
|
||
font-size: 22rpx;
|
||
color: #999999;
|
||
display: block;
|
||
}
|
||
}
|
||
|
||
.health-summary {
|
||
.health-score-section {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 32rpx;
|
||
margin-bottom: 32rpx;
|
||
|
||
.score-circle {
|
||
.circle-progress {
|
||
width: 140rpx;
|
||
height: 140rpx;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.circle-center {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
background: white;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.score-value {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
line-height: 1;
|
||
}
|
||
|
||
.score-label {
|
||
font-size: 20rpx;
|
||
color: #999999;
|
||
margin-top: 6rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.score-details {
|
||
flex: 1;
|
||
|
||
.score-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 12rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.score-name {
|
||
font-size: 24rpx;
|
||
color: #666666;
|
||
}
|
||
|
||
.score-points {
|
||
font-size: 24rpx;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.health-trend {
|
||
text-align: center;
|
||
margin-bottom: 24rpx;
|
||
|
||
.trend-indicator {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
padding: 12rpx 24rpx;
|
||
border-radius: 20rpx;
|
||
|
||
&.improving {
|
||
background: #E8F5E8;
|
||
color: #4CAF50;
|
||
}
|
||
|
||
&.stable {
|
||
background: #E3F2FD;
|
||
color: #2196F3;
|
||
}
|
||
|
||
&.declining {
|
||
background: #FFEBEE;
|
||
color: #F44336;
|
||
}
|
||
|
||
.trend-icon {
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.trend-text {
|
||
font-size: 24rpx;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
}
|
||
|
||
.risk-alerts {
|
||
.alerts-title {
|
||
font-size: 26rpx;
|
||
font-weight: bold;
|
||
color: #FF9800;
|
||
margin-bottom: 16rpx;
|
||
display: block;
|
||
}
|
||
|
||
.alert-item {
|
||
padding: 12rpx 16rpx;
|
||
border-radius: 12rpx;
|
||
margin-bottom: 8rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
&.high {
|
||
background: #FFEBEE;
|
||
border-left: 4rpx solid #F44336;
|
||
}
|
||
|
||
&.medium {
|
||
background: #FFF3E0;
|
||
border-left: 4rpx solid #FF9800;
|
||
}
|
||
|
||
&.low {
|
||
background: #E8F5E8;
|
||
border-left: 4rpx solid #4CAF50;
|
||
}
|
||
|
||
.alert-text {
|
||
font-size: 22rpx;
|
||
color: #666666;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 时间选择器 */
|
||
.time-selector {
|
||
background: rgba(255, 255, 255, 0.95);
|
||
backdrop-filter: blur(20rpx);
|
||
border-radius: 28rpx;
|
||
padding: 32rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.2);
|
||
border: 1rpx solid rgba(255, 255, 255, 0.3);
|
||
|
||
.selector-header {
|
||
margin-bottom: 28rpx;
|
||
|
||
.selector-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
}
|
||
}
|
||
|
||
.time-tabs {
|
||
display: flex;
|
||
gap: 12rpx;
|
||
|
||
.time-tab {
|
||
flex: 1;
|
||
text-align: center;
|
||
padding: 16rpx 12rpx;
|
||
border-radius: 16rpx;
|
||
background: rgba(255, 138, 128, 0.1);
|
||
transition: all 0.3s ease;
|
||
|
||
&.active {
|
||
background: #FF8A80;
|
||
|
||
.tab-text {
|
||
color: white;
|
||
}
|
||
}
|
||
|
||
&:active {
|
||
transform: scale(0.95);
|
||
}
|
||
|
||
.tab-text {
|
||
font-size: 24rpx;
|
||
font-weight: 500;
|
||
color: #666666;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 数据图表区域 */
|
||
.data-charts-section {
|
||
.chart-card {
|
||
background: rgba(255, 255, 255, 0.95);
|
||
backdrop-filter: blur(20rpx);
|
||
border-radius: 28rpx;
|
||
padding: 32rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.2);
|
||
border: 1rpx solid rgba(255, 255, 255, 0.3);
|
||
|
||
.chart-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 28rpx;
|
||
|
||
.chart-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
}
|
||
|
||
.chart-status {
|
||
padding: 8rpx 16rpx;
|
||
border-radius: 16rpx;
|
||
font-size: 22rpx;
|
||
font-weight: 500;
|
||
|
||
&.good {
|
||
background: #E8F5E8;
|
||
color: #4CAF50;
|
||
}
|
||
|
||
&.warning {
|
||
background: #FFF3E0;
|
||
color: #FF9800;
|
||
}
|
||
|
||
&.poor {
|
||
background: #FFEBEE;
|
||
color: #F44336;
|
||
}
|
||
|
||
.status-text {
|
||
font-size: 22rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.chart-summary {
|
||
margin-top: 20rpx;
|
||
text-align: center;
|
||
|
||
.summary-text {
|
||
font-size: 24rpx;
|
||
color: #666666;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 疫苗时间线 */
|
||
.vaccine-timeline {
|
||
.timeline-summary {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
background: rgba(255, 138, 128, 0.05);
|
||
border-radius: 20rpx;
|
||
padding: 24rpx;
|
||
|
||
.summary-item {
|
||
text-align: center;
|
||
|
||
.summary-label {
|
||
font-size: 20rpx;
|
||
color: #999999;
|
||
display: block;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.summary-value {
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
display: block;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 医疗统计 */
|
||
.medical-stats {
|
||
.stats-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 16rpx;
|
||
|
||
.stat-card {
|
||
background: rgba(255, 138, 128, 0.05);
|
||
border-radius: 16rpx;
|
||
padding: 20rpx;
|
||
text-align: center;
|
||
|
||
.stat-number {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #FF8A80;
|
||
display: block;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 20rpx;
|
||
color: #999999;
|
||
display: block;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 生长信息 */
|
||
.growth-info {
|
||
.growth-stage {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 16rpx;
|
||
|
||
.stage-label {
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
}
|
||
|
||
.stage-value {
|
||
font-size: 24rpx;
|
||
font-weight: bold;
|
||
color: #FF8A80;
|
||
}
|
||
}
|
||
|
||
.growth-summary {
|
||
background: rgba(255, 138, 128, 0.05);
|
||
border-radius: 16rpx;
|
||
padding: 20rpx;
|
||
|
||
.summary-text {
|
||
font-size: 24rpx;
|
||
color: #666666;
|
||
line-height: 1.5;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* AI健康分析 */
|
||
.ai-health-analysis {
|
||
background: rgba(255, 255, 255, 0.95);
|
||
backdrop-filter: blur(20rpx);
|
||
border-radius: 28rpx;
|
||
padding: 32rpx;
|
||
margin-bottom: 40rpx;
|
||
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.2);
|
||
border: 1rpx solid rgba(255, 255, 255, 0.3);
|
||
|
||
.analysis-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 28rpx;
|
||
|
||
.analysis-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
}
|
||
|
||
.analysis-badge {
|
||
background: linear-gradient(135deg, #64B5F6, #81C784);
|
||
border-radius: 20rpx;
|
||
padding: 8rpx 16rpx;
|
||
|
||
.badge-text {
|
||
font-size: 20rpx;
|
||
color: white;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
}
|
||
|
||
.analysis-content {
|
||
.analysis-section {
|
||
margin-bottom: 24rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 26rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
margin-bottom: 12rpx;
|
||
display: block;
|
||
}
|
||
|
||
.section-content {
|
||
font-size: 24rpx;
|
||
color: #666666;
|
||
line-height: 1.6;
|
||
display: block;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|