This commit is contained in:
2025-08-13 17:10:28 +08:00
parent af722a2bbc
commit 34a3f7bf1f
4 changed files with 1034 additions and 1 deletions
+336
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()