feat: 微客宝H5客户端 - 基础架构+核心页面
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { homeApi } from '@/api/index'
|
||||
import { useCustomerStore } from '@/stores/customer'
|
||||
|
||||
const router = useRouter()
|
||||
const store = useCustomerStore()
|
||||
const homeData = ref(null)
|
||||
const loading = ref(true)
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const res = await homeApi.index()
|
||||
homeData.value = res.data?.data
|
||||
} catch { } finally {
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
const customer = computed(() => homeData.value?.customer || store.info)
|
||||
const todayMeals = computed(() => homeData.value?.today_meals || [])
|
||||
const latestRecords = computed(() => homeData.value?.care_records || [])
|
||||
const nannyOrder = computed(() => homeData.value?.nanny_order)
|
||||
|
||||
const mealTypeLabel = { 1: '早餐', 2: '上午茶', 3: '午餐', 4: '下午茶', 5: '晚餐', 6: '宵夜' }
|
||||
|
||||
const features = [
|
||||
{ icon: 'records', label: '护理记录', color: '#ff8fa3', path: '/care/records' },
|
||||
{ icon: 'chart-trending-o', label: '健康指标', color: '#7ec8e3', path: '/care/metrics' },
|
||||
{ icon: 'balance-list-o', label: '我的服务', color: '#a8d8a8', path: '/service/orders' },
|
||||
{ icon: 'user-o', label: '我的月嫂', color: '#c9b8f0', path: '/nanny' },
|
||||
{ icon: 'gold-coin-o', label: '我的账户', color: '#ffd580', path: '/account' },
|
||||
{ icon: 'chat-o', label: '投诉反馈', color: '#ffb085', path: '/complaints' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page">
|
||||
<!-- 顶部横幅 -->
|
||||
<div class="top-banner">
|
||||
<div class="banner-content">
|
||||
<div>
|
||||
<p class="greeting">您好,{{ customer?.name || '亲爱的客户' }} 👋</p>
|
||||
<p class="sub-text" v-if="customer?.expected_date">
|
||||
预产期:{{ customer.expected_date }}
|
||||
</p>
|
||||
<p class="sub-text" v-else-if="customer?.actual_date">
|
||||
宝宝出生:{{ customer.actual_date }}
|
||||
</p>
|
||||
</div>
|
||||
<van-icon name="home-o" size="40" color="rgba(255,255,255,0.6)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<!-- 今日用膳 -->
|
||||
<section class="card" v-if="todayMeals.length">
|
||||
<div class="card-header">
|
||||
<span class="card-title">🍱 今日用膳</span>
|
||||
<span class="more" @click="router.push('/meal')">查看全部 ›</span>
|
||||
</div>
|
||||
<div class="meal-row" v-for="m in todayMeals" :key="m.id">
|
||||
<span class="meal-type">{{ mealTypeLabel[m.meal_type] || '用餐' }}</span>
|
||||
<span class="meal-dishes" v-if="m.dishes && m.dishes.length">
|
||||
{{ m.dishes.map(d => d.name).join(' · ') }}
|
||||
</span>
|
||||
<span class="meal-dishes" v-else>待排餐</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 最新护理 -->
|
||||
<section class="card" v-if="latestRecords.length">
|
||||
<div class="card-header">
|
||||
<span class="card-title">💆 护理记录</span>
|
||||
<span class="more" @click="router.push('/care/records')">更多 ›</span>
|
||||
</div>
|
||||
<div class="record-item" v-for="r in latestRecords" :key="r.id">
|
||||
<span class="record-nurse">{{ r.nurse?.name || '护理师' }}</span>
|
||||
<span class="record-time">{{ r.recorded_at?.slice(0, 10) }}</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 月嫂信息 -->
|
||||
<section class="card" v-if="nannyOrder">
|
||||
<div class="card-header">
|
||||
<span class="card-title">👩⚕️ 我的月嫂</span>
|
||||
<span class="more" @click="router.push('/nanny')">详情 ›</span>
|
||||
</div>
|
||||
<div class="nanny-row">
|
||||
<van-icon name="user-circle-o" size="36" color="#e8718d" />
|
||||
<div class="nanny-info">
|
||||
<p class="nanny-name">{{ nannyOrder.nanny?.name }}</p>
|
||||
<p class="nanny-sub">{{ nannyOrder.nanny?.level || '专业月嫂' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 功能入口九宫格 -->
|
||||
<section class="card">
|
||||
<div class="card-title" style="margin-bottom:12px">快捷功能</div>
|
||||
<div class="features-grid">
|
||||
<div
|
||||
v-for="f in features"
|
||||
:key="f.path"
|
||||
class="feature-item"
|
||||
@click="router.push(f.path)"
|
||||
>
|
||||
<div class="feature-icon" :style="{ background: f.color + '22' }">
|
||||
<van-icon :name="f.icon" :color="f.color" size="22" />
|
||||
</div>
|
||||
<span class="feature-label">{{ f.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.page { background: #f8f0f5; min-height: 100vh; padding-bottom: 60px; }
|
||||
.top-banner {
|
||||
background: linear-gradient(135deg, #f5a0b0 0%, #e8718d 100%);
|
||||
padding: 50px 20px 30px;
|
||||
border-radius: 0 0 24px 24px;
|
||||
}
|
||||
.banner-content { display: flex; justify-content: space-between; align-items: flex-start; color: white; }
|
||||
.greeting { font-size: 20px; font-weight: 700; margin: 0 0 4px; }
|
||||
.sub-text { font-size: 13px; opacity: 0.85; margin: 0; }
|
||||
.content { padding: 16px; }
|
||||
.card { background: white; border-radius: 16px; padding: 16px; margin-bottom: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.04); }
|
||||
.card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
|
||||
.card-title { font-size: 15px; font-weight: 600; color: #1d1d1f; }
|
||||
.more { font-size: 13px; color: #e8718d; }
|
||||
.meal-row { display: flex; gap: 8px; padding: 6px 0; border-bottom: 1px solid #f5f5f5; }
|
||||
.meal-row:last-child { border: none; }
|
||||
.meal-type { font-size: 12px; color: white; background: #e8718d; padding: 2px 8px; border-radius: 10px; white-space: nowrap; }
|
||||
.meal-dishes { font-size: 13px; color: #666; }
|
||||
.record-item { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid #f5f5f5; font-size: 13px; }
|
||||
.record-item:last-child { border: none; }
|
||||
.record-nurse { color: #333; }
|
||||
.record-time { color: #999; }
|
||||
.nanny-row { display: flex; align-items: center; gap: 12px; }
|
||||
.nanny-name { font-size: 15px; font-weight: 600; margin: 0 0 2px; }
|
||||
.nanny-sub { font-size: 12px; color: #999; margin: 0; }
|
||||
.features-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
|
||||
.feature-item { display: flex; flex-direction: column; align-items: center; gap: 6px; cursor: pointer; }
|
||||
.feature-icon { width: 50px; height: 50px; border-radius: 14px; display: flex; align-items: center; justify-content: center; }
|
||||
.feature-label { font-size: 12px; color: #666; text-align: center; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user