Files
sundynix-plant-mp/pages/plant-detail/index.js
T
2026-04-28 10:36:51 +08:00

291 lines
10 KiB
JavaScript

// pages/plant-detail/index.js
import request from '../../utils/request';
import { calculateDaysSince, getPlantAgeBadge } from '../../utils/dateUtil';
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 = '未知';
const daysPlanted = calculateDaysSince(plant.plantTime);
const ageBadge = getPlantAgeBadge(daysPlanted);
if (plant.plantTime) {
adoptionDate = plant.plantTime.split('T')[0];
}
this.setData({
currentPlant: {
...plant,
location: plant.placement || '',
adoptionDate: adoptionDate,
daysPlanted: daysPlanted,
ageBadge: ageBadge,
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;
}
// Type → icon/color mapping
const typeConfig = {
growth: { icon: 'thumb-up', color: '#4CAF50', accent: '#E8F5E9' },
flower: { icon: 'heart', color: '#E91E63', accent: '#FCE4EC' },
repot: { icon: 'swap', color: '#FF9800', accent: '#FFF3E0' },
prune: { icon: 'cut', color: '#9C27B0', accent: '#F3E5F5' },
fertilize: { icon: 'edit-1', color: '#FF9800', accent: '#FFF8E1' },
soil: { icon: 'layers', color: '#795548', accent: '#EFEBE9' },
pest: { icon: 'error-circle', color: '#F44336', accent: '#FFEBEE' },
medicine: { icon: 'heart-filled', color: '#E91E63', accent: '#FCE4EC' },
move: { icon: 'map-navigation', color: '#00BCD4', accent: '#E0F7FA' },
other: { icon: 'file', color: '#2196F3', accent: '#E3F2FD' },
};
const tag = item.tag || 'other';
const cfg = typeConfig[tag] || typeConfig.other;
return {
id: item.id,
date: item.createdAtStr ? item.createdAtStr.split(' ')[0] : '',
type: tag,
title: item.name || '成长记录',
content: item.content || item.desc || '',
image: imageUrl,
iconName: cfg.icon,
iconColor: cfg.color,
accentColor: cfg.accent,
};
})
});
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' });
});
}
}
});
},
})