完善服务模块缺少付款页的bug

This commit is contained in:
2026-06-02 11:35:31 +08:00
parent c3324d459a
commit 881262940c
35 changed files with 29069 additions and 557 deletions

View File

@@ -0,0 +1,289 @@
# 问题分析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 行
```uts
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 行
```uts
<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 行
```uts
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 行
```uts
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()`
```uts
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_tasksUUID和 hss_service_orders`so-` 前缀)
- 如果 `created` 对象中没有 `amount`,需要从 `draft``selectedPackage` 中取 `price`
---
### 方案 Border-detail.uvue 增加"去付款"按钮(兜底补偿)
**修改文件**`order-detail.uvue` action row
```uts
<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>
```
**新增方法**
```uts
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 当前已完善的逻辑
1. **`dispatchPaidHomecareOrder`**`serviceOrderService.uts`
- 对 UUID 格式订单ec_care_tasks返回 `{ success: true, code: 'SYNC_IN_PROGRESS', message: '付款成功,服务安排信息正在同步中...' }`
-`so-` 前缀订单hss_service_orders调用旧 `rpc_homecare_auto_dispatch`
2. **`payment.uvue` 支付成功后的派单**
- `source == 'service'` 时,调用 `dispatchPaidHomecareOrder`
- 成功则跳 `order-detail`
- 失败则显示重试弹窗
### 5.2 修复后配合方式
```
用户提交预约(选择了套餐)
createServiceOrder → 写入 hss_service_orderspayment_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 |
---
## 七、验证方式
1. 进入 `service-detail.uvue`,选择套餐,填写信息,点击"提交预约"
2. **预期**:跳转到 `payment.uvue`,显示订单金额、支付方式、倒计时
3. 完成支付
4. **预期**:自动派单,跳转到 `order-detail.uvue`,状态变为"已派单"或"待接单"
5. 测试中途退出场景:在 `order-detail.uvue` 点击"去付款",应能重新进入 `payment.uvue`