Files
SmartElderlyCare/src/views/client/TimeBank.vue
祀梦 7077d0f9e0 feat(客户端): 添加兑换服务和任务交互功能
实现兑换服务弹窗和任务接单功能,包括:
1. 添加兑换服务弹窗及兑换逻辑
2. 实现任务列表平滑滚动和接单功能
3. 在Dashboard中添加语音通话、用药提醒和召唤机器人弹窗
4. 优化UI交互和动画效果
2026-01-12 00:54:35 +08:00

140 lines
6.9 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="space-y-6">
<!-- Balance Card -->
<div class="bg-gradient-to-r from-orange-400 to-pink-500 rounded-2xl p-6 text-white shadow-lg relative overflow-hidden">
<div class="absolute -right-6 -top-6 w-32 h-32 bg-white opacity-10 rounded-full blur-2xl"></div>
<div class="relative z-10">
<div class="text-sm opacity-90 mb-1">我的智护通证 (Token)</div>
<div class="text-4xl font-bold font-mono tracking-tight">1,250.00</div>
<div class="mt-6 flex space-x-3">
<button @click="showExchangeModal = true" class="flex-1 bg-white/20 hover:bg-white/30 backdrop-blur py-2 rounded-lg text-sm font-medium transition-colors">
兑换服务
</button>
<button @click="scrollToTasks" class="flex-1 bg-white text-orange-600 hover:bg-orange-50 py-2 rounded-lg text-sm font-medium transition-colors shadow-sm">
去赚取
</button>
</div>
</div>
</div>
<!-- Exchange Services Modal -->
<div v-if="showExchangeModal" class="fixed inset-0 bg-black/60 flex items-center justify-center z-50 p-4 backdrop-blur-sm">
<div class="bg-white rounded-3xl w-full max-w-md shadow-2xl animate-bounce-in overflow-hidden border border-gray-100 max-h-[80vh] flex flex-col">
<div class="p-6 border-b border-gray-100 flex justify-between items-center bg-gray-50/50">
<div>
<h3 class="text-xl font-black text-gray-900">兑换服务</h3>
<p class="text-xs text-gray-400 font-bold mt-1 flex items-center">
<span class="mr-1">💰</span> 当前余额: 1,250.00 Token
</p>
</div>
<button @click="showExchangeModal = false" class="text-gray-400 hover:text-gray-600 p-2"></button>
</div>
<div class="flex-1 overflow-y-auto p-4 space-y-3">
<div v-for="service in services" :key="service.id"
class="p-4 rounded-2xl border border-gray-100 hover:border-orange-200 hover:bg-orange-50/30 transition-all group flex items-center justify-between">
<div class="flex items-center space-x-4">
<div class="w-14 h-14 rounded-2xl bg-gray-50 flex items-center justify-center text-3xl shadow-inner border border-gray-100 group-hover:bg-white transition-colors">
{{ service.icon }}
</div>
<div>
<div class="font-black text-gray-900">{{ service.title }}</div>
<div class="text-[11px] text-gray-400 font-bold mt-0.5">{{ service.desc }}</div>
</div>
</div>
<div class="text-right">
<div class="text-orange-500 font-black">{{ service.price }} <span class="text-[10px]">Token</span></div>
<button @click="handleExchange(service)" class="mt-1 px-4 py-1.5 bg-gray-900 text-white text-[11px] font-bold rounded-xl hover:bg-orange-500 transition-colors">兑换</button>
</div>
</div>
</div>
<div class="p-4 bg-gray-50 border-t border-gray-100 text-center">
<p class="text-[10px] text-gray-400 font-bold mb-0">区块链通证兑换将实时记录并进行哈希上链存证</p>
</div>
</div>
</div>
<!-- Tasks List -->
<div id="tasks-section" class="scroll-mt-6">
<h3 class="text-lg font-bold text-gray-800 mb-4 px-1 flex items-center justify-between">
<span>社区互助任务</span>
<span class="text-xs font-bold text-orange-500 bg-orange-50 px-2 py-1 rounded-lg">附近 {{ tasks.length }} 个任务</span>
</h3>
<div class="space-y-3">
<div v-for="task in tasks" :key="task.id"
class="bg-white p-5 rounded-2xl shadow-sm border border-gray-100 flex justify-between items-center hover:shadow-md transition-shadow group">
<div class="flex items-center space-x-4">
<div class="w-12 h-12 rounded-2xl bg-gray-50 flex items-center justify-center text-2xl group-hover:bg-orange-50 transition-colors">
{{ task.icon }}
</div>
<div>
<div class="font-black text-gray-900">{{ task.title }}</div>
<div class="text-xs text-gray-400 font-bold mt-1 flex items-center space-x-2">
<span class="flex items-center">📍 {{ task.distance }}</span>
<span></span>
<span class="flex items-center"> {{ task.time }}</span>
</div>
</div>
</div>
<div class="flex flex-col items-end">
<div class="text-orange-500 font-black text-xl">+{{ task.reward }}</div>
<button @click="handleAcceptTask(task)" class="px-5 py-2 bg-gray-900 text-white text-xs font-bold rounded-xl mt-2 hover:bg-orange-500 shadow-sm transition-all active:scale-95">
立即接单
</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const showExchangeModal = ref(false)
const services = ref([
{ id: 1, title: '专业助浴', icon: '🛁', desc: '由专业护理员提供入户助浴服务', price: 150 },
{ id: 2, title: '全屋深度保洁', icon: '🧹', desc: '2小时专业家政深度清洁', price: 300 },
{ id: 3, title: '陪诊服务', icon: '🏥', desc: '陪同前往医院挂号、取药、就诊', price: 200 },
{ id: 4, title: '理发修甲', icon: '✂️', desc: '上门提供基础生活护理', price: 80 },
{ id: 5, title: '代办跑腿', icon: '🏃', desc: '代取快递、代办医保等事务', price: 50 },
])
const tasks = ref([
{ id: 1, title: '陪伴李奶奶聊天', icon: '👵', distance: '300m', time: '30分钟', reward: 50 },
{ id: 2, title: '协助购买日用品', icon: '🛒', distance: '500m', time: '1小时', reward: 100 },
{ id: 3, title: '教张大爷使用手机', icon: '📱', distance: '1.2km', time: '45分钟', reward: 80 },
])
const handleExchange = (service) => {
if (confirm(`确定消耗 ${service.price} Token 兑换 "${service.title}" 吗?\n兑换成功后将由平台为您指派专业服务人员。`)) {
alert(`兑换成功!\n\n区块链存证摘要已生成\nHash: 0x${Math.random().toString(16).slice(2, 10)}...${Math.random().toString(16).slice(2, 6)}\n\n工作人员将在 30 分钟内与您联系。`)
showExchangeModal.value = false
}
}
const handleAcceptTask = (task) => {
alert(`成功接单:${task.title}\n\n请准时前往任务地点。任务完成后${task.reward} Token 将自动记入您的智护通证。`)
}
const scrollToTasks = () => {
const element = document.getElementById('tasks-section')
if (element) {
element.scrollIntoView({ behavior: 'smooth' })
}
}
</script>
<style scoped>
@keyframes bounce-in {
0% { transform: scale(0.95); opacity: 0; }
70% { transform: scale(1.02); opacity: 1; }
100% { transform: scale(1); }
}
.animate-bounce-in {
animation: bounce-in 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
</style>