Files
2026-04-28 10:36:51 +08:00

1013 lines
20 KiB
Plaintext

/** pages/tasks/index.wxss **/
.tasks-page {
height: 100vh;
display: flex;
flex-direction: column;
background-color: #F4F6F0;
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;
/* Removed background: white to avoid "too white" look */
padding: 24rpx 32rpx 0;
display: flex;
flex-direction: column;
overflow: hidden;
min-height: 0;
}
.section-title {
font-size: 36rpx;
font-weight: 800;
color: #263238;
margin-bottom: 24rpx;
padding-left: 12rpx;
flex-shrink: 0;
}
.task-list {
flex: 1;
height: 0;
}
.plant-task-card {
background: #FFFFFF;
border-radius: 32rpx;
padding: 32rpx;
margin-bottom: 32rpx;
/* Enhanced shadow for depth */
box-shadow: 0 12rpx 32rpx rgba(100, 110, 100, 0.08);
border: none;
transition: all 0.2s;
position: relative;
overflow: hidden;
}
/* Decorator for card - subtle green accent */
.plant-task-card::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 8rpx;
height: 100%;
background: #66BB6A;
opacity: 0.8;
}
.plant-task-card::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 160rpx;
height: 160rpx;
background: radial-gradient(circle at top right, #E8F5E9 0%, transparent 70%);
opacity: 0.8;
}
.plant-task-card.has-overdue {
border: 2rpx solid rgba(239, 83, 80, 0.2);
background: #FFF;
}
.plant-task-card.has-overdue::after {
background: #EF5350;
}
.card-header-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 28rpx;
padding-bottom: 0;
border-bottom: none;
}
.plant-info-brief {
display: flex;
align-items: center;
gap: 20rpx;
}
.plant-thumb-small {
width: 88rpx;
height: 88rpx;
border-radius: 20rpx;
overflow: hidden;
background: #f0f0f0;
box-shadow: 0 4rpx 10rpx rgba(0,0,0,0.05);
}
.plant-thumb-small image {
width: 100%;
height: 100%;
}
.thumb-placeholder {
width: 100%;
height: 100%;
background: #C8E6C9;
color: #2E7D32;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
font-size: 36rpx;
}
.plant-name-title {
font-size: 32rpx;
font-weight: 800;
color: #1B5E20;
letter-spacing: 1rpx;
}
.group-overdue-badge {
font-size: 20rpx;
color: #C62828;
background: #FFCDD2;
padding: 6rpx 18rpx;
border-radius: 20rpx;
font-weight: 700;
}
.plant-tasks-list {
display: flex;
flex-direction: column;
gap: 24rpx;
}
.mini-task-row {
display: flex;
justify-content: space-between;
align-items: center;
/* Distinct background for task row */
background: #F8F9FA;
padding: 20rpx;
border-radius: 24rpx;
width: 100%;
box-sizing: border-box;
border: 1rpx solid #F1F3F4;
}
.mini-task-left {
display: flex;
align-items: center;
gap: 24rpx;
}
.task-type-icon-circle {
width: 72rpx;
height: 72rpx;
background: #FFF;
border-radius: 24rpx; /* Softer square */
display: flex;
align-items: center;
justify-content: center;
color: #90A4AE;
box-shadow: 0 4rpx 8rpx rgba(0,0,0,0.03);
}
.task-icon {
width: 32rpx;
height: 32rpx;
}
.mini-task-text {
display: flex;
flex-direction: column;
gap: 6rpx;
}
.task-label {
font-size: 30rpx;
font-weight: 600;
color: #37474F;
}
.task-overdue-text {
font-size: 22rpx;
color: #D32F2F;
font-weight: 700;
}
/* Checkbox Styling - Square */
.mini-check-btn {
width: 56rpx;
height: 56rpx;
border-radius: 12rpx; /* Square with slight radius */
border: 4rpx solid #CFD8DC; /* Thick border */
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
box-sizing: border-box;
background: #FFF;
}
.mini-check-btn:active {
background: #F5F5F5;
border-color: #90A4AE;
}
/* Checked State */
.mini-check-btn.btn-checked {
background: #4CAF50 !important;
border-color: #4CAF50 !important;
animation: checkPop 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
@keyframes checkPop {
0% { transform: scale(0.6); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
/* Urgent/Overdue State */
.mini-check-btn.btn-urgent {
border-color: #EF5350;
background: #FFEBEE;
}
.mini-check-btn.btn-urgent.btn-checked {
background: #EF5350; /* If overdue but checked (rare case?) */
}
.mini-check-btn.btn-urgent:active {
background: #FFCDD2;
}
/* 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);
}
/* Empty State Custom */
.empty-state-custom {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60rpx 0;
gap: 40rpx;
position: relative;
overflow: hidden;
}
.empty-scene {
position: relative;
width: 100%;
height: 320rpx;
display: flex;
justify-content: center;
align-items: center;
}
/* Sun Animation */
.sun-box {
position: absolute;
top: 10rpx;
right: 120rpx;
width: 120rpx;
height: 120rpx;
animation: sunSpin 20s linear infinite;
z-index: 1;
}
.sun-core {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 60rpx;
height: 60rpx;
background: radial-gradient(circle, #FFEB3B 0%, #FBC02D 100%);
border-radius: 50%;
box-shadow: 0 0 20rpx rgba(253, 216, 53, 0.6);
}
.sun-rays {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
border: 4rpx dashed #FDD835;
opacity: 0.6;
}
@keyframes sunSpin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* Clouds */
.cloud {
position: absolute;
background: #E1F5FE;
border-radius: 20rpx;
opacity: 0.8;
z-index: 1;
}
.cloud-1 {
width: 100rpx;
height: 36rpx;
top: 40rpx;
left: 10%;
animation: cloudFloat 15s linear infinite alternate;
}
.cloud-2 {
width: 80rpx;
height: 28rpx;
top: 80rpx;
right: 15%;
animation: cloudFloat 12s linear infinite alternate-reverse;
}
@keyframes cloudFloat {
from { transform: translateX(-20rpx); }
to { transform: translateX(20rpx); }
}
/* Replaced Empty Img with Icon Group */
.empty-icon-group {
position: relative;
width: 200rpx;
height: 200rpx;
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
}
.icon-bg-circle {
position: absolute;
width: 160rpx;
height: 160rpx;
background: white;
border-radius: 50%;
box-shadow: 0 8rpx 32rpx rgba(76, 175, 80, 0.15);
z-index: 1;
}
.emoji-icon {
font-size: 100rpx;
line-height: 1;
position: relative;
z-index: 2;
/* Slight shadow for depth */
text-shadow: 0 4rpx 8rpx rgba(0,0,0,0.1);
display: flex;
align-items: center;
justify-content: center;
}
.sparkle {
position: absolute;
background: #FFD54F;
clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
z-index: 3;
animation: sparkleTwinkle 2s ease-in-out infinite;
}
.s1 {
width: 24rpx;
height: 24rpx;
top: 10rpx;
right: 20rpx;
animation-delay: 0.2s;
}
.s2 {
width: 16rpx;
height: 16rpx;
bottom: 30rpx;
left: 20rpx;
animation-delay: 1.2s;
}
@keyframes sparkleTwinkle {
0%, 100% { transform: scale(0.8) rotate(0deg); opacity: 0.6; }
50% { transform: scale(1.2) rotate(180deg); opacity: 1; }
}
.plant-breathing {
animation: plantBreathe 4s ease-in-out infinite;
}
@keyframes plantBreathe {
0% { transform: scale(1) translateY(0); }
50% { transform: scale(1.05) translateY(-6rpx); }
100% { transform: scale(1) translateY(0); }
}
.empty-text {
display: flex;
flex-direction: column;
align-items: center;
gap: 12rpx;
font-size: 34rpx;
font-weight: 700;
color: #2E7D32;
z-index: 2;
}
.empty-sub {
font-size: 26rpx;
color: #7CB342;
font-weight: 500;
}
.empty-btn {
margin-top: 20rpx;
box-shadow: 0 8rpx 16rpx rgba(85, 139, 47, 0.2);
}
/* Sunshine Animation Layer */
.sunshine-layer {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
}
.sunshine-pkg {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
animation: flyAndCollect 3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
.sun-halo {
position: absolute;
width: 300rpx;
height: 300rpx;
background: radial-gradient(circle, rgba(255, 235, 59, 0.6) 0%, rgba(255, 193, 7, 0) 70%);
border-radius: 50%;
z-index: 0;
animation: sunPulse 1s ease-in-out infinite alternate;
}
.sun-core-emoji {
font-size: 140rpx;
line-height: 1;
position: relative;
z-index: 2;
text-shadow: 0 0 40rpx rgba(255, 160, 0, 0.5);
}
.sun-add-text {
position: absolute;
top: 140rpx;
font-size: 40rpx;
font-weight: 900;
color: #FF6F00;
white-space: nowrap;
text-shadow: 0 2rpx 4rpx rgba(255, 255, 255, 0.8), 0 0 10rpx rgba(255, 160, 0, 0.3);
z-index: 3;
animation: textFadeIn 0.5s ease-out forwards;
}
@keyframes flyAndCollect {
0% {
transform: scale(0.2);
opacity: 0;
}
15% {
transform: scale(1.1);
opacity: 1;
}
30% {
transform: scale(1);
opacity: 1;
}
100% {
/* Fly to top left (approximate progress bar location) */
transform: translate(-35vw, -45vh) scale(0.2);
opacity: 0;
}
}
@keyframes sunPulse {
from { transform: scale(0.9); opacity: 0.5; }
to { transform: scale(1.1); opacity: 0.8; }
}
@keyframes textFadeIn {
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;
}