更新 2026-04-18 21:54
This commit is contained in:
parent
a6bd72f0d4
commit
b486dd313a
@ -8,24 +8,20 @@
|
|||||||
|
|
||||||
<view class="c-hero">
|
<view class="c-hero">
|
||||||
<text class="c-hero-title">服务预约</text>
|
<text class="c-hero-title">服务预约</text>
|
||||||
<text class="c-hero-sub">一键预约洗美,到店与进度随时可查</text>
|
<text class="c-hero-sub">在线选时段,到店更省心</text>
|
||||||
<button class="app-btn-main app-btn-primary c-hero-cta" hover-class="c-hero-cta--hover" @click="openCustCreateAppt">
|
<button class="app-btn-main app-btn-primary c-hero-cta" hover-class="c-hero-cta--hover" @click="openCustCreateAppt">
|
||||||
预约服务
|
预约服务
|
||||||
</button>
|
</button>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="home-dash">
|
<view class="c-cust-section">
|
||||||
<view
|
<text class="c-cust-section-title">我的预约</text>
|
||||||
v-for="card in dashCards"
|
<text v-if="listMode === 'tab'" class="c-cust-section-hint">以下可查看已提交的预约,按状态筛选</text>
|
||||||
:key="card.key"
|
</view>
|
||||||
class="dash-card"
|
|
||||||
:class="{ 'dash-card--active': activeDashKey === card.key }"
|
<!-- 宠主:不做门店 KPI 看板;仅在有「与我相关」的进行态时给一行轻量提示(§2) -->
|
||||||
@click="onDashCardClick(card.key)"
|
<view v-if="petOwnerMeSummaryLine && listMode === 'tab'" class="c-cust-me-line">
|
||||||
>
|
<text class="c-cust-me-line-text">{{ petOwnerMeSummaryLine }}</text>
|
||||||
<text class="dash-card-value">{{ card.value }}</text>
|
|
||||||
<text class="dash-card-label">{{ card.label }}</text>
|
|
||||||
<text class="dash-card-hint">{{ card.hint }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="listMode === 'today'" class="list-mode-bar">
|
<view v-if="listMode === 'today'" class="list-mode-bar">
|
||||||
@ -67,13 +63,12 @@
|
|||||||
:empty-hint="listEmptyHint"
|
:empty-hint="listEmptyHint"
|
||||||
@retry="fetchAppointments"
|
@retry="fetchAppointments"
|
||||||
>
|
>
|
||||||
<template v-if="custEmptyProminent" #empty>
|
<template v-if="custEmptyGuidance" #empty>
|
||||||
<text class="c-empty-emoji">📅</text>
|
<text class="c-empty-emoji">📋</text>
|
||||||
<text class="c-empty-title">还没有预约</text>
|
<text class="c-empty-title">当前没有可展示的预约</text>
|
||||||
<text class="c-empty-hint">创建预约后,待开始与进行中的单会出现在下方列表</text>
|
<text class="c-empty-hint">请使用上方「预约服务」创建;提交后会在本列表显示进度</text>
|
||||||
<button class="app-btn-main app-btn-primary c-empty-cta" @click="openCustCreateAppt">立即预约</button>
|
|
||||||
</template>
|
</template>
|
||||||
<view class="order-list">
|
<view class="order-list order-list--cust">
|
||||||
<view
|
<view
|
||||||
v-for="item in ordersForList"
|
v-for="item in ordersForList"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@ -94,10 +89,6 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</AppPageState>
|
</AppPageState>
|
||||||
|
|
||||||
<view class="fab-appt fab-appt--cust-secondary" @click="openCustCreateAppt" hover-class="fab-appt--hover">
|
|
||||||
<text class="fab-appt-icon">+</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- B端:看板(新建预约改为右下角悬浮按钮,避免与小程序胶囊重叠) -->
|
<!-- B端:看板(新建预约改为右下角悬浮按钮,避免与小程序胶囊重叠) -->
|
||||||
@ -355,6 +346,17 @@ const dashCards = computed(() => {
|
|||||||
|
|
||||||
const newApptCount = computed(() => orders.value.filter(o => o.status === 'new').length)
|
const newApptCount = computed(() => orders.value.filter(o => o.status === 'new').length)
|
||||||
const doingApptCount = computed(() => orders.value.filter(o => o.status === 'doing').length)
|
const doingApptCount = computed(() => orders.value.filter(o => o.status === 'doing').length)
|
||||||
|
|
||||||
|
/** 宠主:与我相关的轻量一句(非门店经营看板,见产品说明 §2) */
|
||||||
|
const petOwnerMeSummaryLine = computed(() => {
|
||||||
|
if (userInfo.role !== 'customer') return ''
|
||||||
|
const n = newApptCount.value
|
||||||
|
const d = doingApptCount.value
|
||||||
|
if (!n && !d) return ''
|
||||||
|
if (n && d) return `你有 ${n} 个待开始、${d} 个进行中的预约`
|
||||||
|
if (n) return `你有 ${n} 个待开始的预约`
|
||||||
|
return `你有 ${d} 个进行中的预约`
|
||||||
|
})
|
||||||
const serviceTypes = ref([])
|
const serviceTypes = ref([])
|
||||||
const showNewAppt = ref(false)
|
const showNewAppt = ref(false)
|
||||||
const creatingAppt = ref(false)
|
const creatingAppt = ref(false)
|
||||||
@ -446,8 +448,8 @@ const showListPlaceholder = computed(
|
|||||||
() => !appointmentsLoading.value && !appointmentsError.value && ordersForList.value.length === 0
|
() => !appointmentsLoading.value && !appointmentsError.value && ordersForList.value.length === 0
|
||||||
)
|
)
|
||||||
|
|
||||||
/** 宠主 Tab 列表为空:用自定义空态突出主按钮(与首屏 CTA 一致) */
|
/** 宠主 Tab 列表为空:仅文案引导,避免与首屏「立即预约」重复入口 */
|
||||||
const custEmptyProminent = computed(
|
const custEmptyGuidance = computed(
|
||||||
() => userInfo.role === 'customer' && listMode.value === 'tab' && showListPlaceholder.value
|
() => userInfo.role === 'customer' && listMode.value === 'tab' && showListPlaceholder.value
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -462,7 +464,7 @@ const listEmptyHint = computed(() => {
|
|||||||
return '可返回列表切换日期或 Tab'
|
return '可返回列表切换日期或 Tab'
|
||||||
}
|
}
|
||||||
if (userInfo.role === 'customer') {
|
if (userInfo.role === 'customer') {
|
||||||
return '切换上方 Tab 查看不同状态,或新建预约'
|
return '切换上方状态查看不同进度'
|
||||||
}
|
}
|
||||||
return '切换上方状态或新建预约'
|
return '切换上方状态或新建预约'
|
||||||
})
|
})
|
||||||
@ -736,24 +738,29 @@ onShow(() => {
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
.c-hero {
|
.c-hero {
|
||||||
padding: 24px 20px 32px;
|
margin: 8px 16px 0;
|
||||||
|
padding: 22px 20px 20px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow: 0 1px 8px rgba(15, 23, 42, 0.06);
|
||||||
}
|
}
|
||||||
.c-hero-title {
|
.c-hero-title {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 26px;
|
font-size: 22px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
color: #1a1a1a;
|
color: #1a1a1a;
|
||||||
letter-spacing: -0.5px;
|
letter-spacing: -0.3px;
|
||||||
}
|
}
|
||||||
.c-hero-sub {
|
.c-hero-sub {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #999993;
|
color: #6b6b65;
|
||||||
margin-top: 4px;
|
margin-top: 8px;
|
||||||
|
line-height: 1.45;
|
||||||
}
|
}
|
||||||
.c-hero-cta {
|
.c-hero-cta {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 20px;
|
margin-top: 18px;
|
||||||
border-radius: 14px !important;
|
border-radius: 14px !important;
|
||||||
font-size: 16px !important;
|
font-size: 16px !important;
|
||||||
font-weight: 700 !important;
|
font-weight: 700 !important;
|
||||||
@ -761,40 +768,56 @@ onShow(() => {
|
|||||||
.c-hero-cta--hover {
|
.c-hero-cta--hover {
|
||||||
opacity: 0.94;
|
opacity: 0.94;
|
||||||
}
|
}
|
||||||
|
.c-cust-section {
|
||||||
|
margin: 18px 16px 8px;
|
||||||
|
}
|
||||||
|
.c-cust-section-title {
|
||||||
|
display: block;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1a1a1a;
|
||||||
|
}
|
||||||
|
.c-cust-section-hint {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #a8a89f;
|
||||||
|
margin-top: 4px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
.c-cust-me-line {
|
||||||
|
margin: 0 16px 10px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
background: #f7faf8;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid #e8f5ee;
|
||||||
|
}
|
||||||
|
.c-cust-me-line-text {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #3d5a4a;
|
||||||
|
line-height: 1.45;
|
||||||
|
}
|
||||||
.c-empty-emoji {
|
.c-empty-emoji {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 40px;
|
font-size: 36px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 10px;
|
||||||
|
opacity: 0.9;
|
||||||
}
|
}
|
||||||
.c-empty-title {
|
.c-empty-title {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 17px;
|
font-size: 16px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #1a1a1a;
|
color: #3f3f3a;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.c-empty-hint {
|
.c-empty-hint {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #999993;
|
color: #a8a89f;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
line-height: 1.5;
|
line-height: 1.55;
|
||||||
padding: 0 8px;
|
padding: 0 12px;
|
||||||
}
|
|
||||||
.c-empty-cta {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 280px;
|
|
||||||
margin: 24px auto 0;
|
|
||||||
border-radius: 14px !important;
|
|
||||||
}
|
|
||||||
.fab-appt--cust-secondary {
|
|
||||||
background: #e8f8ef;
|
|
||||||
box-shadow: 0 4px 14px rgba(45, 185, 109, 0.22);
|
|
||||||
}
|
|
||||||
.fab-appt--cust-secondary .fab-appt-icon {
|
|
||||||
color: #2db96d;
|
|
||||||
}
|
}
|
||||||
.c-form-card {
|
.c-form-card {
|
||||||
margin: 0 16px;
|
margin: 0 16px;
|
||||||
@ -944,6 +967,9 @@ onShow(() => {
|
|||||||
|
|
||||||
/* B端列表(底部留白,避免最后一条被悬浮钮挡住) */
|
/* B端列表(底部留白,避免最后一条被悬浮钮挡住) */
|
||||||
.order-list { padding: 12px 16px 88px; }
|
.order-list { padding: 12px 16px 88px; }
|
||||||
|
.order-list--cust {
|
||||||
|
padding: 12px 16px 28px;
|
||||||
|
}
|
||||||
.order-card {
|
.order-card {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user