11 KiB
问题分析:service-detail.uvue 点击"提交预约"后未出现付款页面
文件:
医疗-consumer/pages/mall/consumer/home-service/service-detail.uvue关联文件:order-detail.uvue、payment.uvue、serviceOrderService.uts、homeServiceService.uts日期:2026-06-02
一、现象描述
用户在 service-detail.uvue(服务单详情/预约页)填写完地址、时间、服务对象等信息后,点击底部"提交预约"按钮:
- 页面提示"预约已提交"
- 自动跳转到
order-detail.uvue(服务单详情页) - 订单状态显示为 "待付款"
- 但用户从未进入过付款页面 (
payment.uvue) - 在
order-detail.uvue中也找不到任何"去付款"按钮
二、根因分析(代码层面)
2.1 问题点 ①:submitBooking 后直接跳 order-detail,未经过 payment
文件:service-detail.uvue 第 933~1012 行
async function submitBooking() {
// ... 表单校验 ...
const created = await createHomeServiceApplication(draft)
if (created == null) {
uni.showToast({ title: '预约提交失败,请稍后重试', icon: 'none' })
return
}
uni.showToast({ title: '预约已提交', icon: 'success' })
// ❌ 直接跳转到订单详情,没有经过付款页
uni.navigateTo({ url: '/pages/mall/consumer/home-service/order-detail?id=' + created.id })
}
预期行为:预约提交成功后,应携带订单信息跳转到 payment.uvue,让用户完成支付。
实际行为:直接 uni.navigateTo 到 order-detail.uvue,付款流程被完全跳过。
2.2 问题点 ②:order-detail.uvue 没有"去付款"按钮
文件:order-detail.uvue 第 89~96 行
<view class="action-row">
<view v-if="detail.statusText == '派单未成功'" class="secondary-btn" @click="bookAgain">再次预约</view>
<view v-else class="secondary-btn" @click="bookAgain">再次预约</view>
<view v-if="detail.status == 'pending_acceptance'" class="primary-btn" @click="goFeedback">去验收反馈</view>
<view v-else-if="consumerViewState.showRescheduleBtn" class="primary-btn" @click="bookAgain">重新选择时间</view>
<view v-else-if="detail.statusText == '派单未成功'" class="primary-btn" @click="retryDispatch">重新派单</view>
<view v-else class="primary-btn" @click="contactService">联系客服</view>
</view>
缺失:当订单状态为 "待付款"(paymentStatus == 1 && status == 'created')时,action row 没有任何"去付款"或"立即支付"的入口。
用户一旦从预约页离开,再回到订单详情,也无法完成付款。
2.3 问题点 ③:createServiceOrder 的双轨逻辑
文件:serviceOrderService.uts 第 1125~1179 行
export async function createServiceOrder(params: CreateServiceOrderParams): Promise<ServiceOrderType | null> {
// 非套餐单 → 走 ec_care_tasks 新链(前端直接 INSERT,无支付概念)
if (params.packageInfo.id == '') {
const newTask = await tryCreateCareTask(params)
if (newTask != null) {
return newTask
}
}
// 套餐单 → 走 hss_service_orders 旧链(有 payment_status 字段)
const response = await supa.from('hss_service_orders').insert({
// ... 包含 payable_amount、payment_status: 1 等字段
status: 'created',
payment_status: 1,
// ...
}).execute()
}
现状:
- 如果用户选择了套餐(
packageInfo.id != ''),订单写入hss_service_orders,payment_status = 1(未付款) - 如果用户没有选择套餐(
packageInfo.id == ''),订单写入ec_care_tasks,没有支付概念
截图中的订单有价格(¥260)且显示"待付款",说明走的是 hss_service_orders 旧链。
2.4 问题点 ④:payment.uvue 的 source 推断对 UUID 不友好(潜在风险)
文件:payment.uvue 第 1678~1683 行
if (source.value == '') {
// so- 前缀 → service,其他(包括 UUID)→ goods
source.value = orderId.value.startsWith('so-') ? 'service' : 'goods'
}
风险:如果未来 service-detail.uvue 创建的是 ec_care_tasks(UUID 格式 id),跳转到 payment.uvue 时,source 会被误判为 'goods',导致:
- 支付成功后走商品发货流程,而非服务派单流程
dispatchPaidHomecareOrder对 UUID 订单返回"同步中"提示,但 UI 可能显示商品订单的完成页
三、数据流全景图
用户填写预约信息
↓
点击【提交预约】
↓
submitBooking()
↓
createHomeServiceApplication(draft)
↓
createServiceOrder(params)
↓
┌─────────────────┬─────────────────┐
│ packageInfo.id │ packageInfo.id │
│ == '' │ != '' │
│ (非套餐) │ (套餐) │
└─────────────────┴─────────────────┘
↓ ↓
tryCreateCareTask insert hss_service_orders
(insert ec_care_tasks) payment_status = 1 (未付款)
↓ ↓
无支付概念 有支付概念
↓ ↓
但都被直接 但也被直接
跳 order-detail 跳 order-detail
↓ ↓
❌ 无付款入口 ❌ 无付款入口
四、修复方案
方案 A:提交预约后自动跳转付款页(最符合用户预期)
修改文件:service-detail.uvue submitBooking()
async function submitBooking() {
// ... 原有校验逻辑保持不变 ...
const created = await createHomeServiceApplication(draft)
if (created == null) {
uni.showToast({ title: '预约提交失败,请稍后重试', icon: 'none' })
return
}
// 判断是否需要支付(仅 hss_service_orders 旧链有支付概念)
if (shouldUseCareTaskPath(created.id)) {
// ec_care_tasks 新链:无支付,直接到详情
uni.showToast({ title: '预约已提交', icon: 'success' })
uni.navigateTo({ url: '/pages/mall/consumer/home-service/order-detail?id=' + created.id })
return
}
// hss_service_orders 旧链:需要支付,跳转到 payment.uvue
uni.showToast({ title: '预约成功,请完成支付', icon: 'success' })
uni.navigateTo({
url: '/pages/mall/consumer/payment?orderId=' + created.id
+ '&source=service'
+ '&bizType=service'
+ '&amount=' + created.amount
// + '&orderNo=' + created.caseNo // 如需
})
}
注意事项:
shouldUseCareTaskPath(id)即isUuidLike(id),用于区分 ec_care_tasks(UUID)和 hss_service_orders(so-前缀)- 如果
created对象中没有amount,需要从draft或selectedPackage中取price
方案 B:order-detail.uvue 增加"去付款"按钮(兜底补偿)
修改文件:order-detail.uvue action row
<view class="action-row">
<view v-if="detail.statusText == '派单未成功'" class="secondary-btn" @click="bookAgain">再次预约</view>
<view v-else class="secondary-btn" @click="bookAgain">再次预约</view>
<!-- ✅ 新增:待付款状态显示"去付款" -->
<view v-if="detail.statusText == '待付款'" class="primary-btn" @click="goPayment">去付款</view>
<view v-else-if="detail.status == 'pending_acceptance'" class="primary-btn" @click="goFeedback">去验收反馈</view>
<view v-else-if="consumerViewState.showRescheduleBtn" class="primary-btn" @click="bookAgain">重新选择时间</view>
<view v-else-if="detail.statusText == '派单未成功'" class="primary-btn" @click="retryDispatch">重新派单</view>
<view v-else class="primary-btn" @click="contactService">联系客服</view>
</view>
新增方法:
function goPayment() {
if (detail.value == null) {
return
}
uni.navigateTo({
url: '/pages/mall/consumer/payment?orderId=' + detail.value.id
+ '&source=service'
+ '&bizType=service'
+ '&amount=' + detail.value.amount
})
}
方案 C(推荐组合):A + B 同时实施
- A 解决主流程:用户预约后自然进入支付环节
- B 解决兜底场景:用户中途退出、支付失败、从订单列表重新进入等情况下,仍能在详情页找到付款入口
五、与刚才完善的双轨逻辑如何配合
5.1 当前已完善的逻辑
-
dispatchPaidHomecareOrder(serviceOrderService.uts):- 对 UUID 格式订单(ec_care_tasks):返回
{ success: true, code: 'SYNC_IN_PROGRESS', message: '付款成功,服务安排信息正在同步中...' } - 对
so-前缀订单(hss_service_orders):调用旧rpc_homecare_auto_dispatch
- 对 UUID 格式订单(ec_care_tasks):返回
-
payment.uvue支付成功后的派单:source == 'service'时,调用dispatchPaidHomecareOrder- 成功则跳
order-detail - 失败则显示重试弹窗
5.2 修复后配合方式
用户提交预约(选择了套餐)
↓
createServiceOrder → 写入 hss_service_orders(payment_status=1)
↓
跳转 payment.uvue(携带 orderId + source=service + amount)
↓
用户完成支付
↓
payment.uvue 调用 dispatchPaidHomecareOrder(orderId)
↓
orderId 是 so- 前缀 → 调用 rpc_homecare_auto_dispatch(旧链派单)
↓
派单成功 → 跳转 order-detail.uvue
↓
用户看到"已派单"或"服务人员已接单"
如果后端补齐了 rpc_payment_callback_activate_care_task:
- 可将
createServiceOrder改为统一创建ec_care_tasks payment.uvue支付成功后,调用新 RPC 激活 care task- 届时
service-detail.uvue的submitBooking可统一跳payment.uvue,无需区分so-/ UUID
六、需要修改的文件清单
| 文件 | 修改内容 | 优先级 |
|---|---|---|
service-detail.uvue |
submitBooking() 成功后跳 payment.uvue(旧链订单) |
P0 |
order-detail.uvue |
action row 增加"待付款" → "去付款"按钮 | P0 |
order-detail.uvue |
新增 goPayment() 方法 |
P0 |
service-detail.uvue |
确保 created 对象包含 amount / price,或从 draft 取 |
P1 |
七、验证方式
- 进入
service-detail.uvue,选择套餐,填写信息,点击"提交预约" - 预期:跳转到
payment.uvue,显示订单金额、支付方式、倒计时 - 完成支付
- 预期:自动派单,跳转到
order-detail.uvue,状态变为"已派单"或"待接单" - 测试中途退出场景:在
order-detail.uvue点击"去付款",应能重新进入payment.uvue