This commit is contained in:
yvan 2025-08-13 17:10:28 +08:00
parent af722a2bbc
commit 34a3f7bf1f
4 changed files with 1034 additions and 1 deletions

View File

@ -64,6 +64,14 @@
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/pets/pet-weight",
"style": {
"navigationBarTitleText": "体重管理",
"navigationBarBackgroundColor": "#FF8A80",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/pets/pet-chat-simple",

View File

@ -40,9 +40,10 @@
<text class="stat-number">{{ petInfo.companionDays || 0 }}</text>
<text class="stat-label">陪伴天数</text>
</view>
<view class="stat-item">
<view class="stat-item clickable" @click="goToWeightManagement">
<text class="stat-number">{{ petInfo.weight || '4.2kg' }}</text>
<text class="stat-label">当前体重</text>
<text class="stat-arrow"></text>
</view>
<view class="stat-item">
<text class="stat-number">85</text>
@ -359,6 +360,12 @@ export default {
this.viewRecords()
},
goToWeightManagement() {
uni.navigateTo({
url: `/pages/pets/pet-weight?petId=${this.petId}&petName=${this.petInfo.name}`
})
},
shareProfile() {
uni.showToast({
title: '分享功能开发中',
@ -555,6 +562,24 @@ export default {
.stat-item {
text-align: center;
position: relative;
&.clickable {
cursor: pointer;
transition: all 0.3s ease;
&:active {
transform: scale(0.95);
}
.stat-arrow {
position: absolute;
top: 8rpx;
right: 8rpx;
font-size: 20rpx;
color: #CCCCCC;
}
}
.stat-number {
font-size: 32rpx;

664
pages/pets/pet-weight.vue Normal file
View File

@ -0,0 +1,664 @@
<template>
<view class="weight-container">
<!-- 当前体重状态卡片 -->
<view class="current-weight-card">
<view class="weight-header">
<text class="pet-name">{{ petName }}的体重管理</text>
<text class="last-update">最后更新{{ lastUpdateTime }}</text>
</view>
<view class="weight-display">
<view class="current-weight">
<text class="weight-value">{{ currentWeight }}</text>
<text class="weight-unit">kg</text>
</view>
<view class="weight-status" :class="weightStatusClass">
<text class="status-text">{{ weightStatusText }}</text>
</view>
</view>
</view>
<!-- 体重对比仪表盘 -->
<view class="comparison-dashboard">
<view class="dashboard-header">
<text class="dashboard-title">📊 体重变化对比</text>
</view>
<view class="comparison-grid">
<view class="comparison-item">
<view class="comparison-icon">📈</view>
<view class="comparison-content">
<text class="comparison-label">较上周</text>
<text class="comparison-value" :class="weeklyChangeClass">
{{ weeklyChange }}
</text>
<text class="comparison-percent" :class="weeklyChangeClass">
{{ weeklyPercent }}
</text>
</view>
</view>
<view class="comparison-item">
<view class="comparison-icon">📊</view>
<view class="comparison-content">
<text class="comparison-label">较上月</text>
<text class="comparison-value" :class="monthlyChangeClass">
{{ monthlyChange }}
</text>
<text class="comparison-percent" :class="monthlyChangeClass">
{{ monthlyPercent }}
</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: activeTab === tab.key }"
v-for="tab in timeTabs"
:key="tab.key"
@click="switchTimeRange(tab.key)"
>
<text class="tab-text">{{ tab.label }}</text>
</view>
</view>
</view>
<!-- 体重变化图表 -->
<view class="chart-container">
<view class="chart-header">
<text class="chart-title">📈 {{ currentTimeRange }}体重趋势</text>
</view>
<qiun-data-charts
type="line"
:opts="chartOpts"
:chartData="chartData"
:canvas2d="true"
:canvasId="'weightChart'"
:canvas-id="'weightChart'"
/>
</view>
<!-- AI分析卡片 -->
<view class="ai-analysis-card">
<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">{{ healthAssessment }}</text>
</view>
<view class="analysis-section">
<text class="section-title">📈 趋势分析</text>
<text class="section-content">{{ trendAnalysis }}</text>
</view>
<view class="analysis-section">
<text class="section-title">💡 建议</text>
<text class="section-content">{{ recommendations }}</text>
</view>
<view class="analysis-section" v-if="medicalAdvice">
<text class="section-title"> 医疗建议</text>
<text class="section-content warning">{{ medicalAdvice }}</text>
</view>
</view>
</view>
<!-- 添加体重记录按钮 -->
<view class="add-weight-btn" @click="addWeightRecord">
<text class="add-btn-text">+ 添加体重记录</text>
</view>
</view>
</template>
<script>
import weightManager from '@/utils/weightManager.js'
export default {
data() {
return {
petId: '',
petName: '',
petInfo: {},
currentWeight: '4.2',
lastUpdateTime: '2024-01-20 14:30',
weightStatusText: '健康范围',
weightStatusClass: 'healthy',
//
weeklyChange: '+0.1kg',
weeklyPercent: '+2.4%',
weeklyChangeClass: 'increase',
monthlyChange: '+0.3kg',
monthlyPercent: '+7.1%',
monthlyChangeClass: 'increase',
//
activeTab: 'week',
timeTabs: [
{ key: 'week', label: '近一周' },
{ key: 'month', label: '近一月' },
{ key: 'year', label: '近一年' },
{ key: 'all', label: '全部历史' }
],
currentTimeRange: '近一周',
//
chartOpts: {
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"
}
}
},
//
chartData: {},
// AI
healthAssessment: '根据小橘的品种橘猫、年龄2岁和性别当前体重4.2kg处于健康范围内。成年橘猫的理想体重通常在3.5-5.5kg之间。',
trendAnalysis: '近期体重呈稳定上升趋势,增长速度适中。这种增长模式符合健康成长规律,无需过度担心。',
recommendations: '建议保持当前的饮食习惯每日定时定量喂食。增加适量运动如逗猫棒游戏15-20分钟。定期监测体重变化。',
medicalAdvice: ''
}
},
onLoad(options) {
this.petId = options.petId || ''
this.petName = options.petName || '宠物'
this.loadPetInfo()
this.loadWeightData()
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)
}
},
loadWeightData() {
//
this.currentWeight = weightManager.getCurrentWeight(this.petId) || 4.2
//
const weeklyChange = weightManager.calculateWeightChange(this.petId, 7)
const monthlyChange = weightManager.calculateWeightChange(this.petId, 30)
//
this.weeklyChange = weeklyChange.change >= 0 ? `+${weeklyChange.change}kg` : `${weeklyChange.change}kg`
this.weeklyPercent = weeklyChange.percent >= 0 ? `+${weeklyChange.percent}%` : `${weeklyChange.percent}%`
this.weeklyChangeClass = weeklyChange.trend
//
this.monthlyChange = monthlyChange.change >= 0 ? `+${monthlyChange.change}kg` : `${monthlyChange.change}kg`
this.monthlyPercent = monthlyChange.percent >= 0 ? `+${monthlyChange.percent}%` : `${monthlyChange.percent}%`
this.monthlyChangeClass = monthlyChange.trend
//
const healthRange = weightManager.getHealthyWeightRange(this.petInfo)
if (this.currentWeight >= healthRange.min && this.currentWeight <= healthRange.max) {
this.weightStatusText = '健康范围'
this.weightStatusClass = 'healthy'
} else if (this.currentWeight < healthRange.min) {
this.weightStatusText = '偏轻'
this.weightStatusClass = 'warning'
} else {
this.weightStatusText = '偏重'
this.weightStatusClass = 'warning'
}
// AI
const aiAnalysis = weightManager.generateAIAnalysis(this.petId, this.petInfo)
this.healthAssessment = aiAnalysis.healthAssessment
this.trendAnalysis = aiAnalysis.trendAnalysis
this.recommendations = aiAnalysis.recommendations
this.medicalAdvice = aiAnalysis.medicalAdvice
//
const records = weightManager.getWeightRecords(this.petId)
if (records.length > 0) {
const lastRecord = records[records.length - 1]
const lastDate = new Date(lastRecord.date)
this.lastUpdateTime = `${lastDate.getMonth() + 1}-${lastDate.getDate()} ${lastDate.getHours()}:${lastDate.getMinutes().toString().padStart(2, '0')}`
}
},
switchTimeRange(timeKey) {
this.activeTab = timeKey
const timeMap = {
'week': '近一周',
'month': '近一月',
'year': '近一年',
'all': '全部历史'
}
this.currentTimeRange = timeMap[timeKey]
this.generateChartData()
},
generateChartData() {
// 使 weightManager
this.chartData = weightManager.generateChartData(this.petId, this.activeTab)
},
addWeightRecord() {
uni.showModal({
title: '添加体重记录',
editable: true,
placeholderText: '请输入体重(kg)',
success: (res) => {
if (res.confirm && res.content) {
const weight = parseFloat(res.content)
if (weight && weight > 0 && weight < 20) {
const record = weightManager.addWeightRecord(this.petId, {
weight: weight,
date: new Date().toISOString(),
note: '手动添加'
})
if (record) {
uni.showToast({
title: '添加成功',
icon: 'success'
})
//
this.loadWeightData()
this.generateChartData()
} else {
uni.showToast({
title: '添加失败',
icon: 'error'
})
}
} else {
uni.showToast({
title: '请输入有效的体重值',
icon: 'error'
})
}
}
}
})
}
}
}
</script>
<style lang="scss" scoped>
.weight-container {
background: linear-gradient(135deg, #FF8A80 0%, #FFB6C1 25%, #FECFEF 50%, #F8BBD9 100%);
min-height: 100vh;
padding: 20rpx;
}
/* 当前体重状态卡片 */
.current-weight-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);
.weight-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;
}
}
.weight-display {
text-align: center;
.current-weight {
margin-bottom: 20rpx;
.weight-value {
font-size: 72rpx;
font-weight: bold;
color: #FF8A80;
}
.weight-unit {
font-size: 32rpx;
color: #666666;
margin-left: 8rpx;
}
}
.weight-status {
padding: 12rpx 24rpx;
border-radius: 20rpx;
display: inline-block;
&.healthy {
background: #E8F5E8;
color: #4CAF50;
}
&.warning {
background: #FFF3E0;
color: #FF9800;
}
&.danger {
background: #FFEBEE;
color: #F44336;
}
.status-text {
font-size: 24rpx;
font-weight: 500;
}
}
}
}
/* 体重对比仪表盘 */
.comparison-dashboard {
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);
.dashboard-header {
margin-bottom: 28rpx;
.dashboard-title {
font-size: 32rpx;
font-weight: bold;
color: #333333;
}
}
.comparison-grid {
display: flex;
gap: 20rpx;
.comparison-item {
flex: 1;
background: rgba(255, 138, 128, 0.05);
border-radius: 20rpx;
padding: 24rpx;
display: flex;
align-items: center;
gap: 16rpx;
.comparison-icon {
font-size: 32rpx;
width: 48rpx;
text-align: center;
}
.comparison-content {
flex: 1;
.comparison-label {
font-size: 22rpx;
color: #999999;
display: block;
margin-bottom: 8rpx;
}
.comparison-value {
font-size: 28rpx;
font-weight: bold;
display: block;
margin-bottom: 4rpx;
&.increase {
color: #FF8A80;
}
&.decrease {
color: #4CAF50;
}
&.stable {
color: #666666;
}
}
.comparison-percent {
font-size: 20rpx;
display: block;
&.increase {
color: #FF8A80;
}
&.decrease {
color: #4CAF50;
}
&.stable {
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;
}
}
}
}
/* 图表容器 */
.chart-container {
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 {
margin-bottom: 28rpx;
.chart-title {
font-size: 32rpx;
font-weight: bold;
color: #333333;
}
}
}
/* AI分析卡片 */
.ai-analysis-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);
.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;
&.warning {
color: #FF9800;
background: #FFF3E0;
padding: 16rpx;
border-radius: 12rpx;
}
}
}
}
}
/* 添加体重记录按钮 */
.add-weight-btn {
background: linear-gradient(135deg, #FF8A80, #FFB6C1);
border-radius: 28rpx;
padding: 24rpx;
text-align: center;
margin-bottom: 40rpx;
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.3);
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
}
.add-btn-text {
font-size: 32rpx;
font-weight: bold;
color: white;
}
}
</style>

336
utils/weightManager.js Normal file
View File

@ -0,0 +1,336 @@
/**
* 宠物体重管理工具类
* 负责体重数据的存储分析和AI建议生成
*/
class WeightManager {
constructor() {
this.storageKey = 'pet_weight_records'
}
/**
* 获取宠物的体重记录
* @param {string} petId 宠物ID
* @returns {Array} 体重记录数组
*/
getWeightRecords(petId) {
try {
const allRecords = uni.getStorageSync(this.storageKey) || {}
return allRecords[petId] || []
} catch (error) {
console.error('获取体重记录失败:', error)
return []
}
}
/**
* 添加体重记录
* @param {string} petId 宠物ID
* @param {Object} record 体重记录
*/
addWeightRecord(petId, record) {
try {
const allRecords = uni.getStorageSync(this.storageKey) || {}
if (!allRecords[petId]) {
allRecords[petId] = []
}
const newRecord = {
id: Date.now(),
weight: record.weight,
date: record.date || new Date().toISOString(),
note: record.note || '',
timestamp: Date.now()
}
allRecords[petId].push(newRecord)
allRecords[petId].sort((a, b) => new Date(a.date) - new Date(b.date))
uni.setStorageSync(this.storageKey, allRecords)
return newRecord
} catch (error) {
console.error('添加体重记录失败:', error)
return null
}
}
/**
* 获取当前体重
* @param {string} petId 宠物ID
* @returns {number} 当前体重
*/
getCurrentWeight(petId) {
const records = this.getWeightRecords(petId)
if (records.length === 0) return 0
return records[records.length - 1].weight
}
/**
* 计算体重变化
* @param {string} petId 宠物ID
* @param {number} days 对比天数
* @returns {Object} 变化数据
*/
calculateWeightChange(petId, days) {
const records = this.getWeightRecords(petId)
if (records.length < 2) {
return {
change: 0,
percent: 0,
trend: 'stable'
}
}
const now = new Date()
const compareDate = new Date(now.getTime() - days * 24 * 60 * 60 * 1000)
const currentWeight = this.getCurrentWeight(petId)
const compareRecord = records.find(record =>
new Date(record.date) >= compareDate
) || records[0]
const change = currentWeight - compareRecord.weight
const percent = compareRecord.weight > 0 ? (change / compareRecord.weight) * 100 : 0
let trend = 'stable'
if (Math.abs(percent) > 1) {
trend = change > 0 ? 'increase' : 'decrease'
}
return {
change: Number(change.toFixed(1)),
percent: Number(percent.toFixed(1)),
trend: trend,
previousWeight: compareRecord.weight
}
}
/**
* 生成图表数据
* @param {string} petId 宠物ID
* @param {string} timeRange 时间范围
* @returns {Object} 图表数据
*/
generateChartData(petId, timeRange) {
const records = this.getWeightRecords(petId)
if (records.length === 0) {
return {
categories: [],
series: [{ name: "体重", data: [] }]
}
}
let filteredRecords = []
const now = new Date()
switch (timeRange) {
case 'week':
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
filteredRecords = records.filter(record => new Date(record.date) >= weekAgo)
break
case 'month':
const monthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000)
filteredRecords = records.filter(record => new Date(record.date) >= monthAgo)
break
case 'year':
const yearAgo = new Date(now.getTime() - 365 * 24 * 60 * 60 * 1000)
filteredRecords = records.filter(record => new Date(record.date) >= yearAgo)
break
default:
filteredRecords = records
}
// 如果数据点太少,补充一些模拟数据
if (filteredRecords.length === 0) {
filteredRecords = this.generateMockData(timeRange)
}
const categories = filteredRecords.map(record => {
const date = new Date(record.date)
if (timeRange === 'year' || timeRange === 'all') {
return `${date.getMonth() + 1}`
} else {
return `${date.getMonth() + 1}/${date.getDate()}`
}
})
const data = filteredRecords.map(record => record.weight)
return {
categories: categories,
series: [{ name: "体重", data: data }]
}
}
/**
* 生成模拟数据用于演示
* @param {string} timeRange 时间范围
* @returns {Array} 模拟数据
*/
generateMockData(timeRange) {
const now = new Date()
const mockData = []
switch (timeRange) {
case 'week':
for (let i = 6; i >= 0; i--) {
const date = new Date(now.getTime() - i * 24 * 60 * 60 * 1000)
mockData.push({
weight: 4.0 + Math.random() * 0.4,
date: date.toISOString()
})
}
break
case 'month':
for (let i = 4; i >= 0; i--) {
const date = new Date(now.getTime() - i * 7 * 24 * 60 * 60 * 1000)
mockData.push({
weight: 3.9 + i * 0.075,
date: date.toISOString()
})
}
break
case 'year':
for (let i = 5; i >= 0; i--) {
const date = new Date(now.getTime() - i * 60 * 24 * 60 * 60 * 1000)
mockData.push({
weight: 3.2 + (5 - i) * 0.2,
date: date.toISOString()
})
}
break
default:
for (let i = 6; i >= 0; i--) {
const date = new Date(now.getTime() - i * 90 * 24 * 60 * 60 * 1000)
mockData.push({
weight: 1.2 + (6 - i) * 0.5,
date: date.toISOString()
})
}
}
return mockData
}
/**
* 生成AI健康分析
* @param {string} petId 宠物ID
* @param {Object} petInfo 宠物信息
* @returns {Object} AI分析结果
*/
generateAIAnalysis(petId, petInfo) {
const currentWeight = this.getCurrentWeight(petId)
const weeklyChange = this.calculateWeightChange(petId, 7)
const monthlyChange = this.calculateWeightChange(petId, 30)
// 根据品种、年龄、性别判断健康范围
const healthRange = this.getHealthyWeightRange(petInfo)
const isHealthy = currentWeight >= healthRange.min && currentWeight <= healthRange.max
// 健康评估
let healthAssessment = ''
if (isHealthy) {
healthAssessment = `根据${petInfo.name}的品种(${petInfo.breed})、年龄(${petInfo.age}岁)和性别(${petInfo.gender}),当前体重${currentWeight}kg处于健康范围内${healthRange.min}-${healthRange.max}kg`
} else if (currentWeight < healthRange.min) {
healthAssessment = `当前体重${currentWeight}kg低于健康范围${healthRange.min}-${healthRange.max}kg建议增加营养摄入。`
} else {
healthAssessment = `当前体重${currentWeight}kg超出健康范围${healthRange.min}-${healthRange.max}kg建议控制饮食并增加运动。`
}
// 趋势分析
let trendAnalysis = ''
if (weeklyChange.trend === 'stable') {
trendAnalysis = '近期体重保持稳定,这是一个良好的状态。'
} else if (weeklyChange.trend === 'increase') {
if (weeklyChange.percent > 5) {
trendAnalysis = `近期体重上升较快(${weeklyChange.percent}%),需要关注饮食控制。`
} else {
trendAnalysis = `近期体重呈适度上升趋势(${weeklyChange.percent}%),增长速度适中。`
}
} else {
if (weeklyChange.percent < -5) {
trendAnalysis = `近期体重下降较快(${weeklyChange.percent}%),建议检查健康状况。`
} else {
trendAnalysis = `近期体重呈下降趋势(${weeklyChange.percent}%),请注意营养补充。`
}
}
// 建议
let recommendations = this.generateRecommendations(currentWeight, healthRange, weeklyChange)
// 医疗建议
let medicalAdvice = ''
if (Math.abs(weeklyChange.percent) > 10 || !isHealthy) {
medicalAdvice = '建议咨询兽医,进行专业的健康检查和营养指导。'
}
return {
healthAssessment,
trendAnalysis,
recommendations,
medicalAdvice
}
}
/**
* 获取健康体重范围
* @param {Object} petInfo 宠物信息
* @returns {Object} 健康体重范围
*/
getHealthyWeightRange(petInfo) {
// 简化的品种体重范围映射
const breedRanges = {
'橘猫': { min: 3.5, max: 5.5 },
'英短': { min: 3.0, max: 5.0 },
'美短': { min: 3.5, max: 5.5 },
'布偶': { min: 4.0, max: 7.0 },
'波斯': { min: 3.0, max: 5.5 },
'暹罗': { min: 2.5, max: 4.5 }
}
const baseRange = breedRanges[petInfo.breed] || { min: 3.0, max: 6.0 }
// 根据性别调整(公猫通常比母猫重一些)
if (petInfo.gender === '公') {
baseRange.min += 0.5
baseRange.max += 0.5
}
return baseRange
}
/**
* 生成个性化建议
* @param {number} currentWeight 当前体重
* @param {Object} healthRange 健康范围
* @param {Object} weeklyChange 周变化
* @returns {string} 建议内容
*/
generateRecommendations(currentWeight, healthRange, weeklyChange) {
let recommendations = []
if (currentWeight < healthRange.min) {
recommendations.push('增加高质量蛋白质摄入,如优质猫粮、煮熟的鸡胸肉')
recommendations.push('少量多餐每日3-4次定时喂食')
recommendations.push('确保充足的饮水')
} else if (currentWeight > healthRange.max) {
recommendations.push('控制食物分量,减少高热量零食')
recommendations.push('增加运动量每日逗猫棒游戏20-30分钟')
recommendations.push('选择低脂肪、高纤维的减肥猫粮')
} else {
recommendations.push('保持当前的饮食习惯,每日定时定量喂食')
recommendations.push('适量运动如逗猫棒游戏15-20分钟')
recommendations.push('定期监测体重变化')
}
if (weeklyChange.trend === 'increase' && weeklyChange.percent > 3) {
recommendations.push('近期体重增长较快,建议减少零食摄入')
} else if (weeklyChange.trend === 'decrease' && weeklyChange.percent < -3) {
recommendations.push('近期体重下降,注意观察食欲和精神状态')
}
return recommendations.join('') + '。'
}
}
export default new WeightManager()