Files
sundynix-plant-mp/pages/plant-detail/index.js
T
2026-02-14 08:32:47 +08:00

275 lines
8.8 KiB
JavaScript

// pages/plant-detail/index.js
import request from '../../utils/request';
Page({
data: {
currentPlant: null,
activeImageIndex: 0,
activeTab: 'info',
careLogs: [],
displayCareLogs: [],
displayCareLimit: 5,
records: [],
displayRecords: [],
displayRecordLimit: 5,
swiperImages: [],
// Growth Modal
showGrowthModal: false,
newRecordType: 'growth',
newRecordContent: '',
newRecordImage: ''
},
onLoad(options) {
if (options.id) {
this.initData(options.id);
}
},
onShow() {
if (this.data.currentPlant && this.data.currentPlant.id) {
this.initData(this.data.currentPlant.id);
}
},
initData(id) {
request.get('/plant/detail', { id }).then(plant => {
const swiperImages = plant.imgList.map(img => {
return img.url;
});
// Parse carePlans icon if it's a string
const carePlans = (plant.carePlans || []).map(cp => {
let iconObj = {};
if (typeof cp.icon === 'string' && cp.icon.startsWith('{')) {
try {
iconObj = JSON.parse(cp.icon);
} catch (e) {
console.error('Parse icon error', e);
}
}
return { ...cp, taskIcon: iconObj };
});
// Calculate days planted and format date
let adoptionDate = '未知';
let daysPlanted = 0;
if (plant.plantTime) {
const start = new Date(plant.plantTime);
const now = new Date();
const diffTime = now - start;
if (diffTime > 0) {
daysPlanted = Math.floor(diffTime / (1000 * 60 * 60 * 24));
}
adoptionDate = plant.plantTime.split('T')[0];
}
this.setData({
currentPlant: {
...plant,
location: plant.placement || '',
adoptionDate: adoptionDate,
daysPlanted: daysPlanted,
careSchedule: carePlans
},
swiperImages: swiperImages,
// Map logs and records directly from plant detail response
careLogs: this.processLogs(plant.careRecords || []),
records: (plant.growthRecords || plant.recordList || []).map(item => {
// Extract image URL safely
let imageUrl = '';
if (item.imgList && item.imgList.length > 0) {
imageUrl = item.imgList[0].url;
}
return {
id: item.id,
date: item.createdAtStr ? item.createdAtStr.split(' ')[0] : '',
type: item.tag || 'growth',
title: item.name || '成长记录',
content: item.content || item.desc || '',
image: imageUrl
};
})
});
this.updateDisplayLogs();
this.updateDisplayRecords();
}).catch(err => {
console.error('Fetch detail failed', err);
});
},
processLogs(logs) {
return logs.map(log => {
// Handle time format (e.g., 2025-02-02 10:00:00)
const timeStr = log.createdAtStr || log.opTime || log.createTime || '';
let dateStr = timeStr;
let timeOnly = '';
if (timeStr.includes(' ')) {
const parts = timeStr.split(' ');
dateStr = parts[0];
timeOnly = parts[1].substring(0, 5); // HH:mm
}
const dateParts = dateStr.split('-');
const month = dateParts.length > 1 ? dateParts[1] : '';
const day = dateParts.length > 2 ? dateParts[2] : '';
// Map icon properties from icon JSON
let type = 'other';
let taskIcon = 'assignment'; // Default TDesign icon
let iconColor = '#8D6E63';
let iconBgColor = '#EFEBE9';
if (log.icon && typeof log.icon === 'string' && log.icon.startsWith('{')) {
try {
const iconObj = JSON.parse(log.icon);
if (iconObj.id) type = iconObj.id;
if (iconObj.icon) taskIcon = iconObj.icon;
if (iconObj.color) iconColor = iconObj.color;
if (iconObj.bgColor) iconBgColor = iconObj.bgColor;
} catch (e) { }
} else if (log.opType) {
type = log.opType;
}
// Use name directly if available
const typeLabel = log.name || this.getCareTypeLabel(type);
return {
...log,
day: day,
month: month,
time: timeOnly,
type: type,
typeLabel: typeLabel,
remark: log.remark || log.content || '',
taskIcon: taskIcon,
iconColor: iconColor,
iconBgColor: iconBgColor
};
});
},
getCareTypeLabel(type) {
const map = {
water: '浇水',
fertilize: '施肥',
prune: '修剪',
repot: '换盆',
pesticide: '除虫',
sun: '晒太阳',
other: '养护'
};
return map[type] || '日常养护';
},
updateDisplayLogs() {
this.setData({
displayCareLogs: this.data.careLogs.slice(0, this.data.displayCareLimit)
});
},
onSwiperChange(e) {
this.setData({ activeImageIndex: e.detail.current });
},
switchTab(e) {
const tab = e.currentTarget.dataset.tab;
if (tab) {
this.setData({ activeTab: tab });
}
},
// Prevent background scroll when modal is open
preventTouchMove() {
return false;
},
toggleCareLimit() {
const newLimit = this.data.displayCareLimit + 5;
this.setData({ displayCareLimit: newLimit });
this.updateDisplayLogs();
},
updateDisplayRecords() {
this.setData({
displayRecords: this.data.records.slice(0, this.data.displayRecordLimit)
});
},
toggleRecordLimit() {
const newLimit = this.data.displayRecordLimit + 5;
this.setData({ displayRecordLimit: newLimit });
this.updateDisplayRecords();
},
// Navigate to Edit Page with EventChannel
handleOpenEditModal() {
if (this.data.currentPlant && this.data.currentPlant.id) {
wx.navigateTo({
url: `/pages/plant-detail/edit/index?id=${this.data.currentPlant.id}&source=detail`,
success: (res) => {
// Send current data to the opened page
res.eventChannel.emit('acceptDataFromOpenerPage', {
plant: this.data.currentPlant
});
}
});
}
},
// Growth Record Logic
handlePreviewRecordImage(e) {
const src = e.currentTarget.dataset.src;
if (!src) return;
wx.previewImage({
current: src,
urls: [src]
});
},
openGrowthModal() {
if (this.data.currentPlant && this.data.currentPlant.id) {
wx.navigateTo({
url: `/pages/plant-detail/growth-record/index?plantId=${this.data.currentPlant.id}`
});
}
},
handleDeletePlant() {
if (!this.data.currentPlant || !this.data.currentPlant.id) return;
wx.showModal({
title: '确认删除',
content: '确定要删除这个植物吗?删除后无法恢复。',
confirmColor: '#EF5350',
success: (res) => {
if (res.confirm) {
wx.showLoading({ title: '删除中...' });
// Attempting to use consistent API pattern: POST /plant/deletePlant with ids array
request.post('/plant/deletePlant', { ids: [this.data.currentPlant.id] }).then(() => {
wx.hideLoading();
wx.showToast({ title: '已删除', icon: 'success' });
setTimeout(() => {
wx.switchTab({ url: '/pages/garden/index' });
}, 1000);
}).catch(err => {
wx.hideLoading();
console.error('Delete plant failed', err);
wx.showToast({ title: '删除失败', icon: 'none' });
});
}
}
});
},
})