1
This commit is contained in:
@@ -0,0 +1,406 @@
|
||||
/**
|
||||
* 宠物疫苗管理工具类
|
||||
* 负责疫苗数据的存储、分析和AI建议生成
|
||||
*/
|
||||
|
||||
class VaccineManager {
|
||||
constructor() {
|
||||
this.storageKey = 'pet_vaccine_records'
|
||||
|
||||
// 疫苗类型定义
|
||||
this.vaccineTypes = {
|
||||
core: {
|
||||
'rabies': {
|
||||
name: '狂犬病疫苗',
|
||||
duration: 365, // 有效期天数
|
||||
interval: 365, // 接种间隔天数
|
||||
required: true,
|
||||
description: '预防狂犬病,法律要求必须接种'
|
||||
},
|
||||
'fvrcp': {
|
||||
name: '猫三联疫苗',
|
||||
duration: 365,
|
||||
interval: 365,
|
||||
required: true,
|
||||
description: '预防猫瘟热、猫杯状病毒、猫鼻气管炎'
|
||||
}
|
||||
},
|
||||
nonCore: {
|
||||
'felv': {
|
||||
name: '猫白血病疫苗',
|
||||
duration: 365,
|
||||
interval: 365,
|
||||
required: false,
|
||||
description: '预防猫白血病病毒感染'
|
||||
},
|
||||
'fip': {
|
||||
name: '猫传腹疫苗',
|
||||
duration: 365,
|
||||
interval: 365,
|
||||
required: false,
|
||||
description: '预防猫传染性腹膜炎'
|
||||
},
|
||||
'chlamydia': {
|
||||
name: '猫衣原体疫苗',
|
||||
duration: 365,
|
||||
interval: 365,
|
||||
required: false,
|
||||
description: '预防猫衣原体感染'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取宠物的疫苗记录
|
||||
* @param {string} petId 宠物ID
|
||||
* @returns {Array} 疫苗记录数组
|
||||
*/
|
||||
getVaccineRecords(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)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化测试数据
|
||||
* @param {string} petId 宠物ID
|
||||
* @returns {Array} 测试数据数组
|
||||
*/
|
||||
initializeTestData(petId) {
|
||||
const now = new Date()
|
||||
const testData = []
|
||||
|
||||
// 狂犬病疫苗记录
|
||||
testData.push({
|
||||
id: Date.now() + 1,
|
||||
petId: petId,
|
||||
vaccineType: 'rabies',
|
||||
vaccineName: '狂犬病疫苗',
|
||||
vaccineDate: new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
expiryDate: new Date(now.getTime() + 335 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
batchNumber: 'RAB2024001',
|
||||
hospital: '宠物医院',
|
||||
veterinarian: '张医生',
|
||||
note: '首次接种',
|
||||
category: 'core',
|
||||
status: 'completed'
|
||||
})
|
||||
|
||||
// 猫三联疫苗记录
|
||||
testData.push({
|
||||
id: Date.now() + 2,
|
||||
petId: petId,
|
||||
vaccineType: 'fvrcp',
|
||||
vaccineName: '猫三联疫苗',
|
||||
vaccineDate: new Date(now.getTime() - 45 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
expiryDate: new Date(now.getTime() + 320 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
batchNumber: 'FVRCP2024001',
|
||||
hospital: '宠物医院',
|
||||
veterinarian: '李医生',
|
||||
note: '年度接种',
|
||||
category: 'core',
|
||||
status: 'completed'
|
||||
})
|
||||
|
||||
// 猫白血病疫苗记录
|
||||
testData.push({
|
||||
id: Date.now() + 3,
|
||||
petId: petId,
|
||||
vaccineType: 'felv',
|
||||
vaccineName: '猫白血病疫苗',
|
||||
vaccineDate: new Date(now.getTime() - 60 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
expiryDate: new Date(now.getTime() + 305 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
batchNumber: 'FELV2024001',
|
||||
hospital: '宠物医院',
|
||||
veterinarian: '王医生',
|
||||
note: '可选接种',
|
||||
category: 'nonCore',
|
||||
status: 'completed'
|
||||
})
|
||||
|
||||
return testData
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加疫苗记录
|
||||
* @param {string} petId 宠物ID
|
||||
* @param {Object} record 疫苗记录
|
||||
*/
|
||||
addVaccineRecord(petId, record) {
|
||||
try {
|
||||
const allRecords = uni.getStorageSync(this.storageKey) || {}
|
||||
if (!allRecords[petId]) {
|
||||
allRecords[petId] = []
|
||||
}
|
||||
|
||||
const vaccineInfo = this.getVaccineInfo(record.vaccineType)
|
||||
const vaccineDate = new Date(record.vaccineDate)
|
||||
const expiryDate = new Date(vaccineDate.getTime() + vaccineInfo.duration * 24 * 60 * 60 * 1000)
|
||||
|
||||
const newRecord = {
|
||||
id: Date.now(),
|
||||
petId: petId,
|
||||
vaccineType: record.vaccineType,
|
||||
vaccineName: vaccineInfo.name,
|
||||
vaccineDate: record.vaccineDate,
|
||||
expiryDate: expiryDate.toISOString(),
|
||||
batchNumber: record.batchNumber || '',
|
||||
hospital: record.hospital || '',
|
||||
veterinarian: record.veterinarian || '',
|
||||
note: record.note || '',
|
||||
category: vaccineInfo.category,
|
||||
status: 'completed'
|
||||
}
|
||||
|
||||
allRecords[petId].push(newRecord)
|
||||
allRecords[petId].sort((a, b) => new Date(b.vaccineDate) - new Date(a.vaccineDate))
|
||||
|
||||
uni.setStorageSync(this.storageKey, allRecords)
|
||||
return newRecord
|
||||
} catch (error) {
|
||||
console.error('添加疫苗记录失败:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取疫苗信息
|
||||
* @param {string} vaccineType 疫苗类型
|
||||
* @returns {Object} 疫苗信息
|
||||
*/
|
||||
getVaccineInfo(vaccineType) {
|
||||
const coreVaccine = this.vaccineTypes.core[vaccineType]
|
||||
if (coreVaccine) {
|
||||
return { ...coreVaccine, category: 'core' }
|
||||
}
|
||||
|
||||
const nonCoreVaccine = this.vaccineTypes.nonCore[vaccineType]
|
||||
if (nonCoreVaccine) {
|
||||
return { ...nonCoreVaccine, category: 'nonCore' }
|
||||
}
|
||||
|
||||
return {
|
||||
name: '未知疫苗',
|
||||
duration: 365,
|
||||
interval: 365,
|
||||
required: false,
|
||||
category: 'unknown'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取疫苗状态统计
|
||||
* @param {string} petId 宠物ID
|
||||
* @returns {Object} 状态统计
|
||||
*/
|
||||
getVaccineStatusSummary(petId) {
|
||||
const records = this.getVaccineRecords(petId)
|
||||
const now = new Date()
|
||||
|
||||
let completed = 0
|
||||
let expiringSoon = 0 // 30天内到期
|
||||
let expired = 0
|
||||
let missing = 0
|
||||
|
||||
// 检查核心疫苗
|
||||
Object.keys(this.vaccineTypes.core).forEach(vaccineType => {
|
||||
const latestRecord = records
|
||||
.filter(r => r.vaccineType === vaccineType)
|
||||
.sort((a, b) => new Date(b.vaccineDate) - new Date(a.vaccineDate))[0]
|
||||
|
||||
if (!latestRecord) {
|
||||
missing++
|
||||
} else {
|
||||
const expiryDate = new Date(latestRecord.expiryDate)
|
||||
const daysUntilExpiry = Math.ceil((expiryDate - now) / (1000 * 60 * 60 * 24))
|
||||
|
||||
if (daysUntilExpiry < 0) {
|
||||
expired++
|
||||
} else if (daysUntilExpiry <= 30) {
|
||||
expiringSoon++
|
||||
} else {
|
||||
completed++
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const total = Object.keys(this.vaccineTypes.core).length
|
||||
const completionRate = Math.round((completed / total) * 100)
|
||||
|
||||
return {
|
||||
completed,
|
||||
expiringSoon,
|
||||
expired,
|
||||
missing,
|
||||
total,
|
||||
completionRate
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取疫苗状态
|
||||
* @param {Object} record 疫苗记录
|
||||
* @returns {string} 状态
|
||||
*/
|
||||
getVaccineStatus(record) {
|
||||
const now = new Date()
|
||||
const expiryDate = new Date(record.expiryDate)
|
||||
const daysUntilExpiry = Math.ceil((expiryDate - now) / (1000 * 60 * 60 * 24))
|
||||
|
||||
if (daysUntilExpiry < 0) {
|
||||
return 'expired'
|
||||
} else if (daysUntilExpiry <= 30) {
|
||||
return 'expiring'
|
||||
} else {
|
||||
return 'valid'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成疫苗接种计划
|
||||
* @param {string} petId 宠物ID
|
||||
* @param {Object} petInfo 宠物信息
|
||||
* @returns {Array} 接种计划
|
||||
*/
|
||||
generateVaccinePlan(petId, petInfo) {
|
||||
const records = this.getVaccineRecords(petId)
|
||||
const now = new Date()
|
||||
const plan = []
|
||||
|
||||
// 检查所有疫苗类型
|
||||
const allVaccineTypes = { ...this.vaccineTypes.core, ...this.vaccineTypes.nonCore }
|
||||
|
||||
Object.entries(allVaccineTypes).forEach(([vaccineType, vaccineInfo]) => {
|
||||
const latestRecord = records
|
||||
.filter(r => r.vaccineType === vaccineType)
|
||||
.sort((a, b) => new Date(b.vaccineDate) - new Date(a.vaccineDate))[0]
|
||||
|
||||
let nextDueDate
|
||||
let priority = 'low'
|
||||
let reason = ''
|
||||
|
||||
if (!latestRecord) {
|
||||
// 从未接种
|
||||
if (vaccineInfo.required) {
|
||||
nextDueDate = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000) // 一周后
|
||||
priority = 'high'
|
||||
reason = '必需疫苗,建议尽快接种'
|
||||
} else {
|
||||
nextDueDate = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000) // 一个月后
|
||||
priority = 'medium'
|
||||
reason = '可选疫苗,建议接种'
|
||||
}
|
||||
} else {
|
||||
// 已接种,计算下次接种时间
|
||||
const lastVaccineDate = new Date(latestRecord.vaccineDate)
|
||||
nextDueDate = new Date(lastVaccineDate.getTime() + vaccineInfo.interval * 24 * 60 * 60 * 1000)
|
||||
|
||||
const daysUntilDue = Math.ceil((nextDueDate - now) / (1000 * 60 * 60 * 24))
|
||||
|
||||
if (daysUntilDue <= 0) {
|
||||
priority = 'high'
|
||||
reason = '疫苗已过期,需要立即接种'
|
||||
} else if (daysUntilDue <= 30) {
|
||||
priority = 'medium'
|
||||
reason = '疫苗即将到期,建议提前接种'
|
||||
} else {
|
||||
priority = 'low'
|
||||
reason = '疫苗有效期内'
|
||||
}
|
||||
}
|
||||
|
||||
plan.push({
|
||||
vaccineType,
|
||||
vaccineName: vaccineInfo.name,
|
||||
category: vaccineType in this.vaccineTypes.core ? 'core' : 'nonCore',
|
||||
nextDueDate: nextDueDate.toISOString(),
|
||||
priority,
|
||||
reason,
|
||||
required: vaccineInfo.required,
|
||||
lastVaccineDate: latestRecord ? latestRecord.vaccineDate : null
|
||||
})
|
||||
})
|
||||
|
||||
// 按优先级和到期时间排序
|
||||
plan.sort((a, b) => {
|
||||
const priorityOrder = { 'high': 3, 'medium': 2, 'low': 1 }
|
||||
if (priorityOrder[a.priority] !== priorityOrder[b.priority]) {
|
||||
return priorityOrder[b.priority] - priorityOrder[a.priority]
|
||||
}
|
||||
return new Date(a.nextDueDate) - new Date(b.nextDueDate)
|
||||
})
|
||||
|
||||
return plan
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成AI分析建议
|
||||
* @param {string} petId 宠物ID
|
||||
* @param {Object} petInfo 宠物信息
|
||||
* @returns {Object} AI分析结果
|
||||
*/
|
||||
generateAIAnalysis(petId, petInfo) {
|
||||
const records = this.getVaccineRecords(petId)
|
||||
const statusSummary = this.getVaccineStatusSummary(petId)
|
||||
const vaccinePlan = this.generateVaccinePlan(petId, petInfo)
|
||||
|
||||
// 疫苗完整性分析
|
||||
let completenessAnalysis = ''
|
||||
if (statusSummary.completionRate >= 100) {
|
||||
completenessAnalysis = `${petInfo.name}的核心疫苗接种完整,免疫保护良好。`
|
||||
} else if (statusSummary.completionRate >= 50) {
|
||||
completenessAnalysis = `${petInfo.name}的疫苗接种基本完整,但还有${statusSummary.missing}种核心疫苗需要接种。`
|
||||
} else {
|
||||
completenessAnalysis = `${petInfo.name}的疫苗接种不完整,缺少${statusSummary.missing}种核心疫苗,存在健康风险。`
|
||||
}
|
||||
|
||||
// 时效性分析
|
||||
let timelinessAnalysis = ''
|
||||
if (statusSummary.expired > 0) {
|
||||
timelinessAnalysis = `有${statusSummary.expired}种疫苗已过期,免疫保护可能失效,建议立即补种。`
|
||||
} else if (statusSummary.expiringSoon > 0) {
|
||||
timelinessAnalysis = `有${statusSummary.expiringSoon}种疫苗即将到期,建议提前安排接种。`
|
||||
} else {
|
||||
timelinessAnalysis = '所有疫苗均在有效期内,免疫保护充分。'
|
||||
}
|
||||
|
||||
// 个性化建议
|
||||
const highPriorityVaccines = vaccinePlan.filter(v => v.priority === 'high')
|
||||
let recommendations = ''
|
||||
if (highPriorityVaccines.length > 0) {
|
||||
const vaccineNames = highPriorityVaccines.map(v => v.vaccineName).join('、')
|
||||
recommendations = `建议优先接种:${vaccineNames}。根据${petInfo.name}的年龄(${petInfo.age}岁)和生活环境,这些疫苗对健康保护至关重要。`
|
||||
} else {
|
||||
recommendations = `当前疫苗状态良好,建议按计划进行常规疫苗接种。定期检查疫苗有效期,确保免疫保护持续有效。`
|
||||
}
|
||||
|
||||
// 风险评估
|
||||
let riskAssessment = ''
|
||||
if (statusSummary.expired > 0 || statusSummary.missing > 0) {
|
||||
riskAssessment = '存在免疫空白期,建议避免接触其他动物,减少外出,直到完成疫苗接种。'
|
||||
}
|
||||
|
||||
return {
|
||||
completenessAnalysis,
|
||||
timelinessAnalysis,
|
||||
recommendations,
|
||||
riskAssessment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new VaccineManager()
|
||||
Reference in New Issue
Block a user