feat: 任务和社区页面

This commit is contained in:
Blizzard
2026-02-06 17:27:35 +08:00
parent d42471e1d5
commit b800ea03b5
30 changed files with 1777 additions and 551 deletions
+76 -38
View File
@@ -1,5 +1,6 @@
// pages/garden/add/index.js
import { MOCK_PLANTS, CARE_TASK_ICONS } from '../../../utils/mockData';
import request from '../../../utils/request';
Page({
data: {
@@ -11,6 +12,8 @@ Page({
newCareTasks: [],
scrollIntoViewId: '',
uploadedImageId: '', // Store the uploaded image ID
showActionSheet: false,
actionSheetItems: [
{ label: '拍摄', value: 'camera' },
@@ -73,13 +76,43 @@ Page({
camera: 'back',
success: (res) => {
const tempFilePath = res.tempFiles[0].tempFilePath;
// 1. Show temp image immediately for UX
this.setData({
newPlantImage: tempFilePath,
isLocalImage: true
});
// Show loading
wx.showLoading({ title: 'Uploading...' });
// Call upload API
request.upload(tempFilePath).then(data => {
wx.hideLoading();
// User provided response format: { data: { file: { url: ..., id: ... } } }
// request.js unwraps 'data', so 'data' here is { file: { ... } }
const fileData = data?.file || {};
const imageUrl = fileData.url;
const imageId = fileData.id;
if (imageUrl && imageId) {
this.setData({
newPlantImage: imageUrl,
uploadedImageId: imageId,
isLocalImage: true
});
wx.showToast({ title: 'Success', icon: 'success' });
} else {
wx.showToast({ title: 'No URL returned', icon: 'none' });
}
}).catch(err => {
wx.hideLoading();
wx.showToast({ title: 'Upload Failed', icon: 'none' });
});
},
fail: (err) => {
console.log('User cancelled', err);
// User cancelled or error
}
});
},
@@ -177,52 +210,57 @@ Page({
},
handleAddPlant() {
if (!this.data.newPlantName) {
const { newPlantName, newPlantLocation, newPlantDate, uploadedImageId, newCareTasks } = this.data;
// Basic Validation
if (!newPlantName) {
wx.showToast({ title: '请输入植物名称', icon: 'none' });
return;
}
if (!uploadedImageId) {
wx.showToast({ title: '请先上传图片', icon: 'none' });
return;
}
const newId = (MOCK_PLANTS.length + 1).toString();
const adoption = new Date(this.data.newPlantDate);
const today = new Date();
const diffTime = Math.abs(today.getTime() - adoption.getTime());
const daysPlanted = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
// Prepare care schedule with icon info
const careSchedule = this.data.newCareTasks.map(task => ({
id: task.id,
taskName: task.taskName,
frequencyValue: task.frequencyValue,
frequencyUnit: task.frequencyUnit,
iconId: task.iconId,
taskIcon: task.taskIcon
// Construct Care Plans
const carePlans = newCareTasks.map(task => ({
name: task.taskName || '未命名事项',
period: task.frequencyValue || 1,
icon: JSON.stringify(task.taskIcon || {}) // Serialize icon details
}));
const newPlant = {
id: newId,
name: this.data.newPlantName,
images: [this.data.newPlantImage || 'monstera_plant_1769757312755.png'],
daysPlanted: daysPlanted,
adoptionDate: this.data.newPlantDate,
location: this.data.newPlantLocation || '未分配位置',
scientificName: 'Unknown',
family: '未知科',
genus: '未知属',
description: '新添加的植物...',
difficulty: '⭐️',
toxicity: '未知',
flowerMsg: '充满希望',
careSchedule: careSchedule
// Construct Payload
const payload = {
name: newPlantName,
plantTime: newPlantDate,
placement: newPlantLocation || '',
ossIds: [uploadedImageId],
carePlans: carePlans,
// Default fields as not in UI yet
potMaterial: '',
potSize: '',
sunlight: '',
plantingMaterial: ''
};
// In a real app we would call an API or update global store
// For this mock, we append to the imported array (memory only)
MOCK_PLANTS.push(newPlant);
// Submit
wx.showLoading({ title: 'Creating...' });
request.post('/plant/add', payload).then(res => {
wx.hideLoading();
wx.showToast({ title: '添加成功', icon: 'success' });
wx.showToast({ title: '添加成功', icon: 'success' });
// Refresh previous page (e.g. garden list) if needed
// const pages = getCurrentPages();
// const prevPage = pages[pages.length - 2];
// if (prevPage && prevPage.onRefresh) prevPage.onRefresh();
setTimeout(() => {
wx.navigateBack();
}, 1000);
setTimeout(() => {
wx.navigateBack();
}, 1000);
}).catch(err => {
wx.hideLoading();
console.error('Add plant failed', err);
// Error handling is done inside request.post, but fallback here
});
}
})
+8 -1
View File
@@ -11,7 +11,14 @@
<!-- Upload Area -->
<view class="upload-section">
<view class="image-upload-area {{newPlantImage ? 'has-image' : ''}}" bindtap="showActionSheet">
<t-image wx:if="{{newPlantImage}}" src="{{tools.resolvePath(newPlantImage)}}" mode="aspectFill" width="100%" height="100%" />
<t-image
wx:if="{{newPlantImage}}"
src="{{newPlantImage}}"
mode="aspectFill"
width="100%"
height="100%"
t-class="uploaded-img"
/>
<view wx:else class="upload-placeholder">
<t-icon name="upload" size="64rpx" color="#999" />
<text>点击上传封面图</text>
+7
View File
@@ -62,6 +62,13 @@ scroll-view ::-webkit-scrollbar {
transition: all 0.2s;
}
.uploaded-img {
width: 100%;
height: 100%;
border-radius: 32rpx; /* Matches container */
object-fit: cover;
}
.image-upload-area:active {
border-color: #558B2F; /* var(--primary) */
background: #F1F8E9;