From 8430b9083a09f31b47a4d00656dee80fde574d0d Mon Sep 17 00:00:00 2001 From: yvan <8574526@qq.com> Date: Wed, 13 Aug 2025 17:35:29 +0800 Subject: [PATCH] 1 --- pages.json | 8 + pages/pets/health-charts.vue | 762 +--------------------------- pages/pets/pet-detail.vue | 29 +- pages/pets/pet-vaccine.vue | 928 +++++++++++++++++++++++++++++++++++ utils/vaccineManager.js | 406 +++++++++++++++ 5 files changed, 1373 insertions(+), 760 deletions(-) create mode 100644 pages/pets/pet-vaccine.vue create mode 100644 utils/vaccineManager.js diff --git a/pages.json b/pages.json index 4ddd791..fdb21f4 100644 --- a/pages.json +++ b/pages.json @@ -72,6 +72,14 @@ "navigationBarTextStyle": "white" } }, + { + "path": "pages/pets/pet-vaccine", + "style": { + "navigationBarTitleText": "疫苗管理", + "navigationBarBackgroundColor": "#FF8A80", + "navigationBarTextStyle": "white" + } + }, { "path": "pages/pets/pet-chat-simple", diff --git a/pages/pets/health-charts.vue b/pages/pets/health-charts.vue index dccbe25..a353ae5 100644 --- a/pages/pets/health-charts.vue +++ b/pages/pets/health-charts.vue @@ -1,783 +1,27 @@ diff --git a/pages/pets/pet-detail.vue b/pages/pets/pet-detail.vue index 6d672a5..4b6b666 100644 --- a/pages/pets/pet-detail.vue +++ b/pages/pets/pet-detail.vue @@ -76,12 +76,13 @@ - + 💉 疫苗状态 已完成 + 🏥 @@ -380,6 +381,12 @@ export default { }) }, + goToVaccineManagement() { + uni.navigateTo({ + url: `/pages/pets/pet-vaccine?petId=${this.petId}&petName=${this.petInfo.name}` + }) + }, + shareProfile() { uni.showToast({ title: '分享功能开发中', @@ -651,6 +658,26 @@ export default { background: rgba(255, 138, 128, 0.05); border-radius: 20rpx; padding: 20rpx; + position: relative; + + &.clickable { + cursor: pointer; + transition: all 0.3s ease; + + &:active { + transform: scale(0.98); + background: rgba(255, 138, 128, 0.1); + } + + .detail-arrow { + position: absolute; + top: 50%; + right: 16rpx; + transform: translateY(-50%); + font-size: 24rpx; + color: #CCCCCC; + } + } .detail-icon { font-size: 32rpx; diff --git a/pages/pets/pet-vaccine.vue b/pages/pets/pet-vaccine.vue new file mode 100644 index 0000000..a9e776a --- /dev/null +++ b/pages/pets/pet-vaccine.vue @@ -0,0 +1,928 @@ + + + + + diff --git a/utils/vaccineManager.js b/utils/vaccineManager.js new file mode 100644 index 0000000..af0e5f1 --- /dev/null +++ b/utils/vaccineManager.js @@ -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()