init: initial commit
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
// pages/tasks/index.js
|
||||
import { MOCK_TASKS_DATA } from '../../utils/mockData';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
tasks: [],
|
||||
groupedTasks: [],
|
||||
progress: 0,
|
||||
completingTask: null,
|
||||
remark: ''
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.setData({ tasks: MOCK_TASKS_DATA });
|
||||
this.processTasks();
|
||||
},
|
||||
|
||||
onShow() {
|
||||
if (typeof this.getTabBar === 'function' &&
|
||||
this.getTabBar()) {
|
||||
this.getTabBar().setData({ selected: 1 });
|
||||
}
|
||||
},
|
||||
|
||||
processTasks() {
|
||||
const { tasks } = this.data;
|
||||
|
||||
// Calculate Progress (Simulated)
|
||||
const completedCount = 3; // Mocked existing completed
|
||||
const initialTotal = MOCK_TASKS_DATA.length + completedCount;
|
||||
const currentCompleted = completedCount + (MOCK_TASKS_DATA.length - tasks.length);
|
||||
const progress = Math.min(100, Math.round((currentCompleted / initialTotal) * 100));
|
||||
|
||||
// Grouping
|
||||
const groups = {};
|
||||
tasks.forEach(task => {
|
||||
if (!groups[task.plantName]) {
|
||||
groups[task.plantName] = {
|
||||
plantName: task.plantName,
|
||||
plantImage: task.plantImage,
|
||||
tasks: [],
|
||||
hasOverdue: false
|
||||
};
|
||||
}
|
||||
groups[task.plantName].tasks.push(task);
|
||||
if (task.isOverdue) groups[task.plantName].hasOverdue = true;
|
||||
});
|
||||
|
||||
// Sorting
|
||||
const sortedGroups = Object.values(groups).sort((a, b) => {
|
||||
if (a.hasOverdue && !b.hasOverdue) return -1;
|
||||
if (!a.hasOverdue && b.hasOverdue) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
this.setData({
|
||||
groupedTasks: sortedGroups,
|
||||
progress
|
||||
});
|
||||
},
|
||||
|
||||
handleTaskClick(e) {
|
||||
// e.currentTarget.dataset.task might differ if TDesign changes event structure,
|
||||
// but 'data-task' on t-button works similarly in Miniprogram.
|
||||
const task = e.currentTarget.dataset.task;
|
||||
this.setData({
|
||||
completingTask: task,
|
||||
remark: ''
|
||||
});
|
||||
},
|
||||
|
||||
onPopupVisibleChange(e) {
|
||||
// Handle both TDesign event and manual close tap
|
||||
const visible = e.detail ? e.detail.visible : e.currentTarget.dataset.visible;
|
||||
if (!visible) {
|
||||
this.setData({ completingTask: null });
|
||||
}
|
||||
},
|
||||
|
||||
onRemarkInput(e) {
|
||||
this.setData({ remark: e.detail.value });
|
||||
},
|
||||
|
||||
handleConfirmComplete() {
|
||||
if (!this.data.completingTask) return;
|
||||
|
||||
const taskId = this.data.completingTask.id;
|
||||
// Filter out the completed task
|
||||
const newTasks = this.data.tasks.filter(t => t.id !== taskId);
|
||||
|
||||
this.setData({
|
||||
tasks: newTasks,
|
||||
completingTask: null
|
||||
}, () => {
|
||||
this.processTasks();
|
||||
wx.showToast({ title: '已完成', icon: 'success' });
|
||||
});
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"navigationBarTitleText": "我的任务",
|
||||
"usingComponents": {
|
||||
"t-fab": "tdesign-miniprogram/fab/fab",
|
||||
"t-popup": "tdesign-miniprogram/popup/popup",
|
||||
"t-progress": "tdesign-miniprogram/progress/progress",
|
||||
"t-button": "tdesign-miniprogram/button/button",
|
||||
"t-textarea": "tdesign-miniprogram/textarea/textarea",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-cell": "tdesign-miniprogram/cell/cell",
|
||||
"t-tag": "tdesign-miniprogram/tag/tag"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<!--pages/tasks/index.wxml-->
|
||||
<view class="tasks-page">
|
||||
|
||||
<!-- Progress Card -->
|
||||
<view class="progress-section">
|
||||
<view class="progress-card">
|
||||
<view class="progress-info">
|
||||
<text class="progress-card-title">今日完成进度</text>
|
||||
<text class="progress-card-desc">{{progress}}% - 继续保持!🌿</text>
|
||||
</view>
|
||||
<view class="progress-circle">
|
||||
<view class="progress-ring" style="--progress-deg: calc({{progress}} * 3.6deg);"></view>
|
||||
<text class="percentage">{{progress}}%</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Tasks Container -->
|
||||
<view class="tasks-container">
|
||||
<text class="section-title">今日待办</text>
|
||||
|
||||
<view wx:if="{{tasks.length === 0}}" class="empty-state">
|
||||
<text>太棒了!所有任务都已完成 🎉</text>
|
||||
</view>
|
||||
|
||||
<scroll-view wx:else scroll-y class="task-list" enhanced show-scrollbar="{{false}}">
|
||||
<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">
|
||||
<view class="plant-thumb-small">
|
||||
<image wx:if="{{item.plantImage}}" src="/assets/{{item.plantImage}}" mode="aspectFill"></image>
|
||||
<view wx:else class="thumb-placeholder">{{item.plantName[0]}}</view>
|
||||
</view>
|
||||
<text class="plant-name-title">{{item.plantName}}</text>
|
||||
</view>
|
||||
<text wx:if="{{item.hasOverdue}}" class="group-overdue-badge">有任务逾期</text>
|
||||
</view>
|
||||
|
||||
<view class="plant-tasks-list">
|
||||
<view wx:for="{{item.tasks}}" wx:key="id" wx:for-item="task" class="mini-task-row">
|
||||
<view class="mini-task-left">
|
||||
<!-- Task Icon with dynamic colors from backend -->
|
||||
<view class="task-type-icon-circle" style="background: {{task.taskIcon ? task.taskIcon.bgColor : '#f5f5f5'}};">
|
||||
<t-icon wx:if="{{task.taskIcon}}" name="{{task.taskIcon.icon}}" size="36rpx" color="{{task.taskIcon.color}}" />
|
||||
<t-icon wx:else name="calendar-1" size="36rpx" color="#999" />
|
||||
</view>
|
||||
<view class="mini-task-text">
|
||||
<!-- Use taskType name from taskIcon or fallback to computed name -->
|
||||
<text class="task-label">{{task.taskIcon ? task.taskIcon.name : (task.taskType === 'water'?'浇水':(task.taskType==='fertilize'?'施肥':(task.taskType==='prune'?'修剪':(task.taskType==='repot'?'换盆':'任务'))))}}</text>
|
||||
<text wx:if="{{task.isOverdue}}" class="task-overdue-text">{{task.overdueDays}}天前</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mini-check-btn {{task.isOverdue ? 'btn-urgent' : ''}}" bindtap="handleTaskClick" data-task="{{task}}">
|
||||
<t-icon name="check" size="32rpx" color="{{task.isOverdue ? '#EF5350' : '#E0E0E0'}}" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view style="height: 120rpx;"></view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- Complete Task Popup -->
|
||||
<t-popup visible="{{completingTask}}" bind:visible-change="onPopupVisibleChange" placement="center">
|
||||
<view class="modal-card">
|
||||
<view class="modal-header">
|
||||
<text class="modal-title">确认完成任务</text>
|
||||
<view class="close-btn" bindtap="onPopupVisibleChange" data-visible="{{false}}">
|
||||
<t-icon name="close" size="40rpx" color="#90A4AE" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="task-confirm-content" wx:if="{{completingTask}}">
|
||||
<view class="confirm-plant-info">
|
||||
<view class="confirm-icon" style="background: {{completingTask.taskIcon ? completingTask.taskIcon.bgColor : '#f5f5f5'}};">
|
||||
<t-icon wx:if="{{completingTask.taskIcon}}" name="{{completingTask.taskIcon.icon}}" size="48rpx" color="{{completingTask.taskIcon.color}}" />
|
||||
<t-icon wx:else name="calendar-1" size="48rpx" color="#999" />
|
||||
</view>
|
||||
<view class="confirm-text">
|
||||
<text class="cp-name">{{completingTask.plantName}}</text>
|
||||
<text class="cp-task">{{completingTask.taskIcon ? completingTask.taskIcon.name : (completingTask.taskType === 'water'?'浇水':(completingTask.taskType==='fertilize'?'施肥':(completingTask.taskType==='prune'?'修剪':(completingTask.taskType==='repot'?'换盆':'日常任务'))))}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="remark-section">
|
||||
<text class="remark-label">添加记录备注 (可选)</text>
|
||||
<textarea
|
||||
class="remark-input"
|
||||
placeholder="例如:浇了500ml水..."
|
||||
value="{{remark}}"
|
||||
bindinput="onRemarkInput"
|
||||
fixed="{{true}}"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="confirm-btn-wrap">
|
||||
<view class="confirm-complete-btn" bindtap="handleConfirmComplete">
|
||||
<t-icon name="check" size="36rpx" color="#FFF" style="margin-right: 12rpx;" />
|
||||
<text>确认完成并记录</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</t-popup>
|
||||
</view>
|
||||
@@ -0,0 +1,549 @@
|
||||
/** pages/tasks/index.wxss **/
|
||||
.tasks-page {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #F8F9FA;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Progress Section */
|
||||
.progress-section {
|
||||
padding: 0;
|
||||
margin: 40rpx 48rpx 40rpx;
|
||||
}
|
||||
|
||||
.progress-card {
|
||||
background: linear-gradient(135deg, #E8F5E9 0%, #C8E6C9 100%);
|
||||
border-radius: 40rpx;
|
||||
padding: 32rpx 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
color: #2E7D32;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.02);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-height: 170rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.progress-card::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: -50rpx;
|
||||
top: -50rpx;
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.progress-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.progress-card-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.progress-card-desc {
|
||||
font-size: 22rpx;
|
||||
opacity: 0.85;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Custom CSS Progress Ring */
|
||||
.progress-ring-container {
|
||||
width: 104rpx;
|
||||
height: 104rpx;
|
||||
position: relative;
|
||||
margin-left: 20rpx;
|
||||
z-index: 2;
|
||||
border-radius: 50%;
|
||||
background: rgba(255,255,255,0.3); /* Track color */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.progress-ring-inner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: conic-gradient(#2E7D32 var(--progress), transparent 0deg);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transform: rotate(-90deg); /* Start from top */
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Mask circle to create ring effect */
|
||||
.progress-ring-mask {
|
||||
width: 88rpx; /* 104 - (8*2) = 88 */
|
||||
height: 88rpx;
|
||||
background: #E8F5E9; /* Match card gradient start roughly or transparent? */
|
||||
/* Actually background needs to match parent. Since parent is gradient, solid color mask won't match perfectly.
|
||||
BETTER approach: Use border-radius border trick.
|
||||
*/
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
/* This method has a flaw with gradient backgrounds.
|
||||
Alternative: pure border with clip-path?
|
||||
Or simpler:
|
||||
.ring {
|
||||
width: 104rpx; height: 104rpx;
|
||||
border-radius: 50%;
|
||||
padding: 8rpx;
|
||||
background: conic-gradient(currentColor var(--val), transparent 0) content-box;
|
||||
-webkit-mask: ...
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/* Updated Approach: CSS Border Ring using masks */
|
||||
.css-progress-ring {
|
||||
width: 104rpx;
|
||||
height: 104rpx;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: conic-gradient(#FFFFFF var(--progress), rgba(255,255,255,0.3) 0deg);
|
||||
/* The ring color is White vs Track transparent/white-alpha */
|
||||
}
|
||||
|
||||
/* The inner hole */
|
||||
.css-progress-ring::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 10rpx; /* stroke width ~ 10rpx/2 ?? No. 104 wide. inset 8rpx -> 88 inner. stroke 8. */
|
||||
border-radius: 50%;
|
||||
background-color: transparent; /* We need to show the card gradient behind... difficult with this technique unless we use mask-image */
|
||||
}
|
||||
|
||||
/* Let's try standard mask composite approach or just SVG image which is easiest.
|
||||
But user wants style resolved. SVG support in WXML view is limited to background-image.
|
||||
I will use the `t-progress` but FIX the overflow by making sure container is large enough and REMOVE OVERFLOW HIDDEN from the card if necessary, OR fix the container size.
|
||||
Actually, the user said "Banner is too wide".
|
||||
I will stick to `t-progress` but I will Wrap it in a `view` that has definitive size and `overflow: visible`.
|
||||
However, user said "overflows banner".
|
||||
Let's use a SIMPLIFIED CSS Ring that doesn't rely on transparency tricks that fail on gradients:
|
||||
Use 4 borders rotated? No.
|
||||
|
||||
Let's go with the SVG Image solution in WXML. It is supported via <image> with svg data uri, or just careful CSS.
|
||||
Wait, the user's "style not resolved" likely implies `t-progress` is just broken essentially.
|
||||
I will implement a pure WXML/WXSS ring using `view` borders (two halves). This allows transparency center.
|
||||
*/
|
||||
|
||||
.ring-container {
|
||||
width: 104rpx;
|
||||
height: 104rpx;
|
||||
position: relative;
|
||||
margin-left: 20rpx;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.ring-text {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20rpx;
|
||||
font-weight: 800;
|
||||
color: #1B5E20;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* Pure CSS Progress Circle (Left/Right spin method) */
|
||||
.circle-wrap {
|
||||
width: 104rpx;
|
||||
height: 104rpx;
|
||||
background: rgba(255,255,255,0.3); /* Track */
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
overflow: hidden; /* This clips the half-circles but center is filled? No. */
|
||||
/* This method clears center by adding a smaller circle on top */
|
||||
}
|
||||
|
||||
.circle-wrap .mask,
|
||||
.circle-wrap .fill {
|
||||
width: 104rpx;
|
||||
height: 104rpx;
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.circle-wrap .mask {
|
||||
clip: rect(0px, 104rpx, 104rpx, 52rpx);
|
||||
}
|
||||
|
||||
.circle-wrap .fill {
|
||||
clip: rect(0px, 52rpx, 104rpx, 0px);
|
||||
background-color: #FFFFFF; /* Progress Color */
|
||||
}
|
||||
|
||||
.circle-wrap .mask.full,
|
||||
.circle-wrap .fill {
|
||||
animation: fill ease-in-out 3s;
|
||||
transform: rotate(126deg); /* Dynamic via style */
|
||||
}
|
||||
|
||||
/* Inner hole */
|
||||
.circle-inside {
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
border-radius: 50%;
|
||||
background: #D2E8D5; /* Approximated gradient mid-point or use transparent if specific layout allows */
|
||||
/* Since gradient is complex, solid color looks bad.
|
||||
The "Progress Circle" style issue is likely the 'cut off' or solid center blocking gradient.
|
||||
|
||||
BEST SOLUTION: Canvas 2D. But cumbersome.
|
||||
|
||||
Let's try t-progress one last time with correct constraints? No, user is annoyed.
|
||||
|
||||
Let's use a transparent PNG for the track and `conic-gradient` for the fill with a specific mix-blend-mode? No support.
|
||||
|
||||
Let's use `conic-gradient` with `mask-image`. Most modern webviews support it.
|
||||
*/
|
||||
}
|
||||
|
||||
/* Progress Circle - Matching Prototype */
|
||||
.progress-circle {
|
||||
position: relative;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 20rpx;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.progress-ring {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: conic-gradient(#2E7D32 var(--progress-deg), rgba(255, 255, 255, 0.3) 0deg);
|
||||
-webkit-mask: radial-gradient(transparent 60%, black 61%);
|
||||
mask: radial-gradient(transparent 60%, black 61%);
|
||||
}
|
||||
|
||||
.percentage {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
color: #1B5E20;
|
||||
}
|
||||
|
||||
.tasks-container {
|
||||
flex: 1;
|
||||
background: white;
|
||||
border-top-left-radius: 60rpx;
|
||||
border-top-right-radius: 60rpx;
|
||||
padding: 48rpx 40rpx 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 -8rpx 32rpx rgba(0,0,0,0.03);
|
||||
min-height: 0; /* Critical for flex scrolling */
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 800;
|
||||
color: #263238;
|
||||
margin-bottom: 32rpx;
|
||||
padding-left: 8rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.task-list {
|
||||
flex: 1;
|
||||
height: 0; /* Force flex container to define height */
|
||||
}
|
||||
|
||||
.plant-task-card {
|
||||
background: white;
|
||||
border-radius: 40rpx;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 32rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.03);
|
||||
border: 2rpx solid transparent;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.plant-task-card.has-overdue {
|
||||
border-color: rgba(239, 83, 80, 0.1);
|
||||
background: #FFF8F8;
|
||||
}
|
||||
|
||||
.card-header-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 32rpx;
|
||||
padding-bottom: 24rpx;
|
||||
border-bottom: 2rpx solid rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.plant-info-brief {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.plant-thumb-small {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 24rpx;
|
||||
overflow: hidden;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.plant-thumb-small image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.thumb-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #E8F5E9;
|
||||
color: #558B2F;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 700;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.plant-name-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 700;
|
||||
color: #263238;
|
||||
}
|
||||
|
||||
.group-overdue-badge {
|
||||
font-size: 20rpx;
|
||||
color: #EF5350;
|
||||
background: rgba(239, 83, 80, 0.1);
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.plant-tasks-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.mini-task-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mini-task-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.task-type-icon-circle {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
background: #F8F9FA;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #90A4AE;
|
||||
}
|
||||
|
||||
.task-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
|
||||
.mini-task-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4rpx;
|
||||
}
|
||||
|
||||
.task-label {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #37474F;
|
||||
}
|
||||
|
||||
.task-overdue-text {
|
||||
font-size: 22rpx;
|
||||
color: #EF5350;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.mini-check-btn {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 20rpx;
|
||||
border: 3rpx solid #E0E0E0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.mini-check-btn:active {
|
||||
background: rgba(85, 139, 47, 0.05);
|
||||
border-color: #558B2F;
|
||||
}
|
||||
|
||||
.mini-check-btn.btn-urgent {
|
||||
border-color: rgba(239, 83, 80, 0.3);
|
||||
}
|
||||
|
||||
.mini-check-btn.btn-urgent:active {
|
||||
background: rgba(239, 83, 80, 0.05);
|
||||
border-color: #EF5350;
|
||||
}
|
||||
|
||||
/* Modal Specifics */
|
||||
.modal-card {
|
||||
background: white;
|
||||
width: 640rpx;
|
||||
border-radius: 64rpx;
|
||||
padding: 48rpx;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 48rpx;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 800;
|
||||
color: #263238;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
padding: 8rpx;
|
||||
}
|
||||
|
||||
.task-confirm-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 40rpx;
|
||||
}
|
||||
|
||||
.confirm-plant-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24rpx;
|
||||
background: #F4F6F0;
|
||||
padding: 32rpx;
|
||||
border-radius: 32rpx;
|
||||
}
|
||||
|
||||
.confirm-icon {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
background: white;
|
||||
border-radius: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.icon-32 {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
|
||||
.confirm-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.cp-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
color: #263238;
|
||||
}
|
||||
|
||||
.cp-task {
|
||||
font-size: 26rpx;
|
||||
color: #90A4AE;
|
||||
}
|
||||
|
||||
.remark-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.remark-label {
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
color: #263238;
|
||||
}
|
||||
|
||||
.remark-input {
|
||||
width: 100%;
|
||||
height: 160rpx;
|
||||
background: #F8F9FA;
|
||||
border: 2rpx solid #ECEFF1;
|
||||
border-radius: 24rpx;
|
||||
padding: 24rpx;
|
||||
font-size: 28rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.confirm-btn-wrap {
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.confirm-complete-btn {
|
||||
width: 100%;
|
||||
background: #558B2F;
|
||||
color: white;
|
||||
height: 100rpx;
|
||||
border-radius: 50rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 8rpx 24rpx rgba(85, 139, 47, 0.4);
|
||||
}
|
||||
|
||||
.confirm-complete-btn:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
Reference in New Issue
Block a user