| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- <template>
- <view class="fun-task-item" :class="{ completed: task.status === 'completed', urgent: isUrgent }">
- <view class="task-icon">{{ getCategoryIcon() }}</view>
- <view class="task-content">
- <view class="task-title">{{ task.title }}</view>
- <view class="task-meta">
- <text class="points-badge">+{{ task.points }}分</text>
- <text class="deadline">{{ getTimeLeft() }}</text>
- </view>
- </view>
- <view class="task-action">
- <button v-if="task.status === 'pending'" class="complete-btn" @click="$emit('complete')">
- <text class="btn-icon">✨</text>
- <text>完成</text>
- </button>
- <view v-else class="completed-badge">
- <text class="check-icon">✅</text>
- <text>已完成</text>
- </view>
- </view>
- </view>
- </template>
- <script>
- export default {
- name: 'FunTaskItem',
- props: {
- task: { type: Object, required: true }
- },
- computed: {
- isUrgent() {
- if (this.task.status === 'completed') return false
- if (!this.task.deadline) return false
- const deadline = new Date(this.task.deadline)
- const now = new Date()
- const hoursLeft = (deadline - now) / (1000 * 60 * 60)
- return hoursLeft < 2
- }
- },
- methods: {
- getCategoryIcon() {
- const icons = {
- '学习类': '📚',
- '生活类': '🏠',
- '运动类': '⚽',
- '其他': '⭐'
- }
- return icons[this.task.category] || '📝'
- },
- getTimeLeft() {
- if (!this.task.deadline) return ''
- const deadline = new Date(this.task.deadline)
- const now = new Date()
- const diff = deadline - now
- if (diff < 0) return '已超时'
- const hours = Math.floor(diff / (1000 * 60 * 60))
- const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
- if (hours > 24) {
- const days = Math.floor(hours / 24)
- return `${days}天后`
- }
- if (hours > 0) return `${hours}小时后`
- return `${minutes}分钟后`
- }
- }
- }
- </script>
- <style scoped>
- .fun-task-item {
- display: flex;
- align-items: center;
- background: #fff;
- border-radius: 20rpx;
- padding: 24rpx;
- margin-bottom: 20rpx;
- box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05);
- transition: transform 0.2s;
- }
- .fun-task-item:active { transform: scale(0.98); }
- .fun-task-item.completed { opacity: 0.7; background: #F0FDF4; }
- .fun-task-item.urgent { border: 2rpx solid #FF6B6B; animation: pulse-urgent 1s infinite; }
- @keyframes pulse-urgent { 0%, 100% { box-shadow: 0 0 0 0 rgba(255,107,107,0.4); } 50% { box-shadow: 0 0 0 10rpx rgba(255,107,107,0); } }
- .task-icon { font-size: 48rpx; width: 80rpx; height: 80rpx; background: #F0F9FF; border-radius: 16rpx; display: flex; align-items: center; justify-content: center; margin-right: 20rpx; }
- .task-content { flex: 1; }
- .task-title { font-size: 30rpx; font-weight: 600; color: #1F2937; margin-bottom: 8rpx; }
- .task-meta { display: flex; align-items: center; gap: 16rpx; }
- .points-badge { background: linear-gradient(135deg, #FEF3C7, #FDE68A); color: #92400E; font-size: 22rpx; padding: 4rpx 12rpx; border-radius: 20rpx; font-weight: 600; }
- .deadline { font-size: 22rpx; color: #6B7280; }
- .task-action { margin-left: 20rpx; }
- .complete-btn { display: flex; align-items: center; background: linear-gradient(135deg, #0EA5E9, #06B6D4); color: #fff; border: none; border-radius: 30rpx; padding: 12rpx 24rpx; font-size: 24rpx; font-weight: 600; }
- .btn-icon { margin-right: 8rpx; }
- .completed-badge { display: flex; align-items: center; background: #ECFDF5; color: #059669; padding: 12rpx 20rpx; border-radius: 30rpx; font-size: 24rpx; }
- .check-icon { margin-right: 8rpx; }
- </style>
|