feat: 整体页面优化,删除无用svg

This commit is contained in:
Blizzard
2026-02-14 08:32:47 +08:00
parent daea00ca60
commit cbbe82ef63
59 changed files with 1265 additions and 342 deletions
+101 -13
View File
@@ -7,11 +7,20 @@ Page({
groupedTasks: [],
progress: 0,
completingTask: null,
remark: ''
remark: '',
remarkPlaceholder: '',
scrollTop: 0,
// Reward Modals
showLevelUpModal: false,
levelUpData: null,
showBadgeModal: false,
badgeData: null
},
onLoad() {
this.fetchTodayTasks();
this._popupQueue = [];
},
onShow() {
@@ -23,6 +32,42 @@ Page({
this.fetchTodayTasks();
},
// ... (fetchTodayTasks, processTaskData Omitted) ...
// Reward Queue Processing
processPopupQueue() {
if (this._popupQueue.length === 0) return;
const next = this._popupQueue[0];
if (next.type === 'level') {
this.setData({
levelUpData: next.data,
showLevelUpModal: true
});
} else if (next.type === 'badge') {
this.setData({
badgeData: next.data,
showBadgeModal: true
});
}
},
closeLevelUpModal() {
this.setData({ showLevelUpModal: false });
this._popupQueue.shift();
setTimeout(() => {
this.processPopupQueue();
}, 300);
},
closeBadgeModal() {
this.setData({ showBadgeModal: false });
this._popupQueue.shift();
setTimeout(() => {
this.processPopupQueue();
}, 300);
},
fetchTodayTasks() {
request.get('/plant/todayTask').then(res => {
// Check if res is array (list of PlantTaskVO)
@@ -45,12 +90,7 @@ Page({
// Parse Image
let imageUrl = '';
if (plant.imgList && plant.imgList.length > 0) {
let url = plant.imgList[0].url;
if (url && !url.startsWith('http') && !url.startsWith('/') && !url.startsWith('wxfile')) {
imageUrl = '/assets/' + url;
} else {
imageUrl = url;
}
imageUrl = plant.imgList[0].url || '';
}
const plantGroup = {
@@ -149,9 +189,36 @@ Page({
handleTaskClick(e) {
const task = e.currentTarget.dataset.task;
if (task.isCompleted) return;
// Compute placeholder based on task type or name
let placeholder = '添加备注 (可选)...';
// Get name from taskIcon first, then name.
// name from backend is usually the name (e.g. "浇水").
const typeRaw = (task.taskIcon ? task.taskIcon.name : task.name) || '';
const typeStr = typeRaw.toLowerCase();
if (typeStr.includes('浇水')) {
placeholder = '例如:浇了 200ml 水...';
} else if (typeStr.includes('施肥')) {
placeholder = '例如:施了通用液肥...';
} else if (typeStr.includes('修剪')) {
placeholder = '例如:修剪了枯叶和黄叶...';
} else if (typeStr.includes('换盆')) {
placeholder = '例如:更换了陶盆,加了底肥...';
} else if (typeStr.includes('换土')) {
placeholder = '例如:更换了新配方土...';
} else if (typeStr.includes('喷雾')) {
placeholder = '例如:给叶面喷了水...';
} else if (typeStr.includes('用药') || typeStr.includes('虫')) {
placeholder = '例如:喷洒了杀虫剂...';
} else if (typeStr.includes('晒太阳') || typeStr.includes('日照')) {
placeholder = '例如:晒了 2 小时太阳...';
}
this.setData({
completingTask: task,
remark: ''
remark: '',
remarkPlaceholder: placeholder
});
},
@@ -172,16 +239,29 @@ Page({
const taskId = this.data.completingTask.id;
const remark = this.data.remark || '';
// Optimistic Update immediately for better feel?
// Or wait for server? Wait is safer.
wx.showLoading({ title: '提交中...', mask: true });
request.post('/plant/completeTask', {
taskId: taskId,
remark: remark
}).then(() => {
}).then(res => {
wx.hideLoading();
// Handle Rewards
const queue = [];
// Check if res has level up or badge data
// Note: res is already data.data from request.js
if (res && res.isLevelUp && res.currentLevel) {
queue.push({ type: 'level', data: res.currentLevel });
}
// Check for Badge using IsGetBadge flag (allowing for casing variance)
if (res && (res.IsGetBadge === true || res.isGetBadge === true) && res.newBadge) {
queue.push({ type: 'badge', data: res.newBadge });
}
this._popupQueue = queue;
// Optimistic UI Update Logic
const groups = this.data.groupedTasks;
let updated = false;
@@ -208,10 +288,14 @@ Page({
showSunshine: true
});
// Hide Animation after duration
// Hide Animation after duration and Start showing modals
setTimeout(() => {
this.setData({ showSunshine: false });
}, 3000);
// Show rewards after sunshine animation
if (this._popupQueue.length > 0) {
this.processPopupQueue();
}
}, 1000); // 1.0s delay usually covers animation
// Sync with backend silently
this.fetchTodayTasks();
@@ -227,5 +311,9 @@ Page({
wx.switchTab({
url: '/pages/garden/index'
});
},
onTabItemTap() {
this.setData({ scrollTop: Math.random() * 0.01 });
}
})
+45 -3
View File
@@ -44,7 +44,7 @@
<t-button theme="primary" size="large" shape="round" bind:tap="gotoGarden" class="empty-btn">去看看花园</t-button>
</view>
<scroll-view wx:else scroll-y class="task-list" enhanced show-scrollbar="{{false}}">
<scroll-view wx:else scroll-y class="task-list" enhanced show-scrollbar="{{false}}" scroll-top="{{scrollTop}}">
<view wx:for="{{groupedTasks}}" wx:key="plantName" class="plant-task-card {{item.hasOverdue ? 'has-overdue' : ''}}">
<view class="card-header-row">
<view class="plant-info-brief">
@@ -85,7 +85,7 @@
</view>
<!-- Complete Task Popup -->
<t-popup visible="{{completingTask}}" bind:visible-change="onPopupVisibleChange" placement="center">
<t-popup visible="{{completingTask}}" bind:visible-change="onPopupVisibleChange" placement="center" close-on-overlay-click="{{false}}">
<view class="modal-card">
<view class="modal-header">
<text class="modal-title">确认完成任务</text>
@@ -110,7 +110,7 @@
<text class="remark-label">添加记录备注 (可选)</text>
<textarea
class="remark-input"
placeholder="例如:浇了500ml水..."
placeholder="{{remarkPlaceholder}}"
value="{{remark}}"
bindinput="onRemarkInput"
fixed="{{true}}"
@@ -131,6 +131,48 @@
</view>
</t-popup>
<!-- Level Up Modal -->
<t-popup visible="{{showLevelUpModal}}" bind:visible-change="closeLevelUpModal" placement="center" close-on-overlay-click="{{false}}">
<view class="reward-modal">
<view class="reward-floating-icon level-icon-bg">
<t-icon name="chart-bar" size="80rpx" color="#fff" />
</view>
<view class="reward-content">
<text class="reward-title">恭喜升级!</text>
<view class="reward-level-tag">
<text>Lv.{{levelUpData.level}} {{levelUpData.title}}</text>
</view>
<view class="reward-desc-box" wx:if="{{levelUpData.perks}}">
<text style="font-weight: bold; display: block; margin-bottom: 8rpx; color: #EF6C00;">解锁特权</text>
<text>{{levelUpData.perks}}</text>
</view>
</view>
<view class="reward-btn-container">
<t-button t-class="reward-btn btn-level" size="large" block bindtap="closeLevelUpModal">太棒了</t-button>
</view>
</view>
</t-popup>
<!-- New Badge Modal -->
<t-popup visible="{{showBadgeModal}}" bind:visible-change="closeBadgeModal" placement="center" close-on-overlay-click="{{false}}">
<view class="reward-modal">
<view class="reward-floating-icon badge-icon-bg">
<image class="reward-badge-img-large" src="{{badgeData.icon.url}}" mode="aspectFit" wx:if="{{badgeData.icon && badgeData.icon.url}}" />
<t-icon name="medal" size="80rpx" color="#fff" wx:else />
</view>
<view class="reward-content">
<text class="reward-title">解锁新徽章!</text>
<text class="reward-level-tag" style="background: #E3F2FD; color: #1565C0; border-color: #BBDEFB;">{{badgeData.name}}</text>
<view class="reward-desc-box">
<text>{{badgeData.description}}</text>
</view>
</view>
<view class="reward-btn-container">
<t-button t-class="reward-btn btn-badge" size="large" block bindtap="closeBadgeModal">收入囊中</t-button>
</view>
</view>
</t-popup>
<!-- Sunshine Animation Layer -->
<view class="sunshine-layer" wx:if="{{showSunshine}}">
<view class="sunshine-pkg">
+139
View File
@@ -864,3 +864,142 @@
0% { transform: translateY(20rpx); opacity: 0; }
100% { transform: translateY(0); opacity: 1; }
}
/* Reward Modals - Enhanced */
.reward-modal {
background: #fff;
width: 580rpx;
border-radius: 40rpx;
padding-top: 100rpx; /* Space for floating icon */
padding-bottom: 40rpx;
box-sizing: border-box;
position: relative;
overflow: visible; /* Allow floating elements */
display: flex;
flex-direction: column;
align-items: center;
box-shadow: 0 24rpx 64rpx rgba(0,0,0,0.2);
}
/* Background decorator inside modal (top curve) */
.reward-modal::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 200rpx;
background: linear-gradient(180deg, #F5F5F5 0%, #FFFFFF 100%);
border-radius: 40rpx 40rpx 0 0;
z-index: 0;
}
/* Floating Icon Wrapper */
.reward-floating-icon {
position: absolute;
top: -80rpx;
left: 50%;
transform: translateX(-50%);
width: 180rpx;
height: 180rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 16rpx 32rpx rgba(0,0,0,0.15);
z-index: 2;
background: white; /* Fallback */
}
.level-icon-bg {
background: linear-gradient(135deg, #FFB74D, #EF6C00);
border: 8rpx solid #fff;
}
.badge-icon-bg {
background: linear-gradient(135deg, #64B5F6, #1565C0);
border: 8rpx solid #fff;
}
/* Actual Image/Icon */
.reward-badge-img-large {
width: 140rpx;
height: 140rpx;
filter: drop-shadow(0 4rpx 8rpx rgba(0,0,0,0.2));
}
/* Content */
.reward-content {
position: relative;
z-index: 1;
width: 100%;
padding: 0 48rpx;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
gap: 20rpx;
}
.reward-title {
font-size: 44rpx;
font-weight: 900;
color: #263238;
margin-top: 20rpx;
}
/* Level Styles */
.reward-level-tag {
background: #FFF3E0;
color: #EF6C00;
padding: 8rpx 24rpx;
border-radius: 32rpx;
font-size: 28rpx;
font-weight: 700;
border: 2rpx solid #FFE0B2;
}
/* Description Box */
.reward-desc-box {
background: #FAFAFA;
border: 2rpx solid #F5F5F5;
border-radius: 20rpx;
padding: 24rpx;
width: 100%;
color: #546E7A;
font-size: 28rpx;
line-height: 1.6;
text-align: center;
}
/* Button */
.reward-btn-container {
width: 100%;
padding: 0 48rpx;
margin-top: 40rpx;
position: relative;
z-index: 1;
}
/* Custom Button Style override */
.reward-btn {
border-radius: 48rpx !important;
font-weight: 700 !important;
font-size: 32rpx !important;
height: 96rpx !important;
box-shadow: 0 12rpx 24rpx rgba(255, 152, 0, 0.3); /* Default orange shadow */
}
.btn-level {
background: linear-gradient(90deg, #FF9800, #F57C00) !important;
color: white !important;
box-shadow: 0 12rpx 24rpx rgba(245, 124, 0, 0.4) !important;
border: none !important;
}
.btn-badge {
background: linear-gradient(90deg, #42A5F5, #1976D2) !important;
color: white !important;
box-shadow: 0 12rpx 24rpx rgba(25, 118, 210, 0.4) !important;
border: none !important;
}