完善服务模块缺少付款页的bug
This commit is contained in:
289
docs/home-service/FIX_service_detail_no_payment_page.md
Normal file
289
docs/home-service/FIX_service_detail_no_payment_page.md
Normal 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_tasks(UUID)和 hss_service_orders(`so-` 前缀)
|
||||
- 如果 `created` 对象中没有 `amount`,需要从 `draft` 或 `selectedPackage` 中取 `price`
|
||||
|
||||
---
|
||||
|
||||
### 方案 B:order-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_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 |
|
||||
|
||||
---
|
||||
|
||||
## 七、验证方式
|
||||
|
||||
1. 进入 `service-detail.uvue`,选择套餐,填写信息,点击"提交预约"
|
||||
2. **预期**:跳转到 `payment.uvue`,显示订单金额、支付方式、倒计时
|
||||
3. 完成支付
|
||||
4. **预期**:自动派单,跳转到 `order-detail.uvue`,状态变为"已派单"或"待接单"
|
||||
5. 测试中途退出场景:在 `order-detail.uvue` 点击"去付款",应能重新进入 `payment.uvue`
|
||||
Reference in New Issue
Block a user