refactor: redesign order flow - serve first, pay later
- Redesign order status flow: 0待接单→1已接单→2服务中→3待支付→4已完成 - Allow service start from status 1 (removed payment barrier) - Add payment entry after service completion (status 3) - Update Android/miniprogram UI status mappings - Add order flow design document to docs/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
0
.gitmodules
vendored
0
.gitmodules
vendored
@@ -1,4 +1,6 @@
|
||||
// app.js
|
||||
const config = require('./utils/config')
|
||||
|
||||
App({
|
||||
onLaunch() {
|
||||
const uid = wx.getStorageSync('uid')
|
||||
@@ -16,9 +18,10 @@ App({
|
||||
iv: '',
|
||||
code: '',
|
||||
|
||||
|
||||
// url: 'https://ruilaizipj.com',
|
||||
url: 'http://101.43.95.130:8039',
|
||||
url: config.baseUrl,
|
||||
domain: config.baseUrl,
|
||||
domaintwo: config.baseUrl,
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ Page({
|
||||
height: '',
|
||||
url: app.globalData.url,
|
||||
|
||||
statusType: ["全部", "待付款", "待服务", "服务中", "已完成","已取消"],
|
||||
status: ["", "1", "2", "3","8","-2"],
|
||||
statusType: ["全部", "待接单", "已接单", "待服务", "服务中", "已完成","已取消"],
|
||||
status: ["", "0", "1", "2", "3","4","-2"],
|
||||
currentType: 0,
|
||||
tabClass: ["", "", "", "", "", ""],
|
||||
tabClass: ["", "", "", "", "", "", ""],
|
||||
pageNum: 1
|
||||
},
|
||||
statusTap: function (e) {
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<view class="detail_number">{{item.serviceTime}}天</view>
|
||||
<view class="money">实付款:<text style="font-size: 30rpx;color: #FF8F1F;font-family: PingFang SC;font-weight: bold;">¥{{item.yuguMoney}}元</text></view>
|
||||
</view>
|
||||
<view class="detail_btn" bindtap="go_pay" data-id="{{item.order_id}}" wx:if="{{item.status==1}}" data-item="{{item}}">去付款</view>
|
||||
<view class="detail_btn" bindtap="go_pay" data-id="{{item.order_id}}" wx:if="{{item.status==4}}" data-item="{{item}}">去付款</view>
|
||||
|
||||
<!-- <view class="detail_btn" bindtap="go_Qcode" data-id="{{item.order_id}}" wx:if="{{item.status==1}}">查看二维码</view> -->
|
||||
</view>
|
||||
|
||||
@@ -116,6 +116,7 @@ Page({
|
||||
method: 'GET',
|
||||
data: {},
|
||||
success: (res) => {
|
||||
console.log('医院列表响应:', res.statusCode, JSON.stringify(res.data).substring(0, 200));
|
||||
if (res.data.code == 200) {
|
||||
var hospitals = res.data.rows || res.data.data || [];
|
||||
var list = [{ text: '请选择医院', value: 0 }];
|
||||
@@ -126,7 +127,14 @@ Page({
|
||||
});
|
||||
});
|
||||
that.setData({ objectArray: list });
|
||||
} else {
|
||||
console.error('医院列表加载失败 code:', res.data.code, 'msg:', res.data.msg);
|
||||
that.setData({ objectArray: [{ text: '加载失败,点击重试', value: 0 }] });
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('医院列表网络错误:', err);
|
||||
that.setData({ objectArray: [{ text: '网络错误,点击重试', value: 0 }] });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
170
docs/订单流转设计方案.md
Normal file
170
docs/订单流转设计方案.md
Normal file
@@ -0,0 +1,170 @@
|
||||
# 瑞来健康 — 订单流转设计方案
|
||||
|
||||
## 一、业务流程总览
|
||||
|
||||
```
|
||||
患者端(小程序) 陪护端(Android) 后台管理员
|
||||
│ │ │
|
||||
│ 下单 │ │
|
||||
├─────────────────────────────────────────────→ 0 待接单
|
||||
│ │ │
|
||||
│ [确认接单] │
|
||||
├─────────────────────────────────────────────→ 1 已接单(待服务)
|
||||
│ │ │
|
||||
│ [开始服务] │
|
||||
├─────────────────────────────────────────────→ 2 服务中
|
||||
│ │ │
|
||||
│ [完成服务] │
|
||||
├─────────────────────────────────────────────→ 3 待支付
|
||||
│ │ │
|
||||
│ [微信支付] │ │
|
||||
├─────────────────────────────────────────────→ 4 已完成(已支付)
|
||||
│ │ │
|
||||
│ │ [结算]→ 8 已结算
|
||||
```
|
||||
|
||||
## 二、订单状态定义
|
||||
|
||||
| status | 名称 | 含义 | 触发方 | 触发动作 |
|
||||
|--------|------|------|--------|----------|
|
||||
| -2 | 已取消 | 订单已取消 | 患者/陪护员 | 取消订单 |
|
||||
| -1 | 拒绝接单 | 陪护员拒绝了订单 | 陪护员 | 拒绝接单 |
|
||||
| 0 | 待接单 | 患者已下单,等待陪护员接单 | 患者 | 提交订单 |
|
||||
| 1 | 已接单 | 陪护员已接单,等待开始服务 | 陪护员 | 确认接单 |
|
||||
| 2 | 服务中 | 陪护员已到场开始执行服务 | 陪护员 | 开始服务 |
|
||||
| 3 | 待支付 | 服务已完成,等待患者付款 | 陪护员 | 完成服务 |
|
||||
| 4 | 已完成 | 患者已付款,订单完结 | 患者 | 微信支付 |
|
||||
| 5 | 申请退款 | 患者申请退款 | 患者 | 申请退款 |
|
||||
| 6 | 退款中 | 微信退款处理中 | 系统 | 退款回调 |
|
||||
| 7 | 已退款 | 退款已到账 | 系统 | 退款回调 |
|
||||
| 8 | 已结算 | 平台已与陪护员完成结算 | 管理员 | 确认结算 |
|
||||
|
||||
## 三、各阶段取消/退款规则
|
||||
|
||||
| 状态 | 取消规则 |
|
||||
|------|----------|
|
||||
| 0 待接单 | 患者可自行取消;陪护员可拒绝接单 |
|
||||
| 1 已接单 | 双方可取消(需填写原因) |
|
||||
| 2 服务中 | **不可自行取消**,需联系平台客服介入调解 |
|
||||
| 3 待支付 | **不可取消**,患者应按约定付款;如有争议联系客服 |
|
||||
| 4 已完成 | 患者可申请退款 → 5申请退款 → 6退款中 → 7已退款 |
|
||||
|
||||
## 四、关键接口
|
||||
|
||||
### 4.1 接单
|
||||
```
|
||||
POST /system/view/acceptOrderYes
|
||||
参数: { orderId }
|
||||
作用: status 0 → 1, 绑定陪护员ID
|
||||
调用方: Android 陪护端
|
||||
```
|
||||
文件: `OrderViewServiceImpl.java:100 acceptOrderYes()`
|
||||
|
||||
### 4.2 开始服务
|
||||
```
|
||||
POST /system/view/startServiceWithOrder
|
||||
参数: { orderId }
|
||||
作用: status 1 → 2(仅status=1时可执行)
|
||||
调用方: Android 陪护端/Miniprogram
|
||||
```
|
||||
文件: `OrderViewServiceImpl.java:117 startServiceWithOrder()`
|
||||
|
||||
### 4.3 完成服务
|
||||
```
|
||||
GET /system/order/completeOrder/{orderId}
|
||||
参数: orderId (路径参数)
|
||||
作用: status 2 → 3(需当前时间 > 服务结束时间)
|
||||
调用方: Android 陪护端
|
||||
```
|
||||
文件: `RlzOrderServiceImpl.java:276 completeOrderByOrderId()`
|
||||
|
||||
### 4.4 患者付款
|
||||
```
|
||||
GET /system/order/weixinPay/{orderId}
|
||||
作用: status 3 → 4(微信支付回调触发)
|
||||
调用方: 微信小程序端
|
||||
```
|
||||
文件: `RlzOrderController.java:191 weixinPay()`
|
||||
|
||||
### 4.5 支付回调(微信异步通知)
|
||||
```
|
||||
POST /system/weixin/wxPayNotify
|
||||
作用: 支付成功后 status 3 → 4
|
||||
```
|
||||
文件: `RlzOrderServiceImpl.java:213 weixinPayOrderNext()`
|
||||
|
||||
### 4.6 取消订单
|
||||
```
|
||||
GET /system/order/concelOrder/{orderId}
|
||||
作用: status 0/1 → -2
|
||||
```
|
||||
文件: `RlzOrderServiceImpl.java:179 concelOrderByOrderId()`
|
||||
|
||||
### 4.7 退款申请
|
||||
```
|
||||
GET /system/order/refundOrder/{orderId}
|
||||
作用: status 4 → 5 → 6 → 7
|
||||
```
|
||||
文件: `RlzOrderController.java:213 refundOrder()`
|
||||
|
||||
### 4.8 管理员结算
|
||||
```
|
||||
PUT /system/view/settleOrder/{orderId}
|
||||
作用: status 4 → 8
|
||||
```
|
||||
文件: `OrderViewController.java:289 settleOrder()`
|
||||
|
||||
## 五、改动清单
|
||||
|
||||
### 5.1 后端 (Java Spring Boot)
|
||||
|
||||
| 文件 | 改动内容 |
|
||||
|------|----------|
|
||||
| `OrderViewServiceImpl.java:120` | `"2"` → `"1"`:已接单即可开始服务 |
|
||||
| `OrderViewServiceImpl.java:131` | `"3"` → `"2"`:服务中才能完成;设置 `status = "3"` |
|
||||
| `RlzOrderServiceImpl.java:226` | 支付回调设置 `status = "4"` 而非 `"2"` |
|
||||
| `RlzOrderServiceImpl.java:182` | 取消条件:status `"2","3"` 不可取消,仅 `"0","1","4"` 可取消 |
|
||||
| `RlzOrderController.java:191-211` | weixinPay 接口增加 status=3 的校验 |
|
||||
|
||||
### 5.2 微信小程序 (coupon)
|
||||
|
||||
| 文件 | 改动内容 |
|
||||
|------|----------|
|
||||
| `pages/order/order.js:15-16` | 状态标签数组:替换"待服务"为"待支付",移除冗余项 |
|
||||
| `pages/order/order.wxml:27,45` | status=1 时隐藏"去付款";status=3 时显示"去付款" |
|
||||
| `pages/order/order.wxml:22-33` | 状态文案映射更新 |
|
||||
| `pages/orderdetail/orderdetail.js` | 确认支付入口逻辑对应更新 |
|
||||
|
||||
### 5.3 Android 陪护端 (peizhen)
|
||||
|
||||
| 文件 | 改动内容 |
|
||||
|------|----------|
|
||||
| `TobeSerFragment.java:239` | 查询参数从 `"1,2"` 改为 `"1"`(待服务仅=已接单) |
|
||||
| `SerFragment.java:225` | 查询参数从 `"1,2"` 改为 `"2"`(服务中仅=服务中) |
|
||||
| `CusListAdapter.java:38-77` | status 标签映射更新:1=已接单, 2=服务中, 3=待支付, 4=已完成 |
|
||||
| `CustomerDetailActivity.java:27-94` | 各状态的UI展示文案和样式更新 |
|
||||
|
||||
## 六、设计理由
|
||||
|
||||
### 6.1 为什么先服务后付款
|
||||
|
||||
1. **陪诊场景天然适配**:患者与陪护员在医院当面接触,服务过程透明可验证
|
||||
2. **降低患者决策门槛**:无需先向陌生人付款,信任成本更低
|
||||
3. **激励服务质量**:陪护员知道患者满意才会付款,有动力做好服务
|
||||
4. **风险可控**:订单金额小(20-200元),且有平台客服兜底
|
||||
|
||||
### 6.2 风险控制措施
|
||||
|
||||
1. 有未支付订单的患者限制再次下单
|
||||
2. 服务中状态锁定、不可取消,保护陪护员劳动
|
||||
3. 管理员退款审核机制保留(status 5-7 流程)
|
||||
4. 平台客服介入机制(status 2-3 争议时)
|
||||
|
||||
### 6.3 业务闭环
|
||||
|
||||
```
|
||||
患者端(下单+付款) ←→ 陪护端(接单+服务) ←→ 管理后台(结算+纠纷处理)
|
||||
│ │ │
|
||||
└───────────────────────┴────────────────────────┘
|
||||
三端数据实时同步
|
||||
```
|
||||
@@ -32,7 +32,15 @@ android {
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
// 开发环境 —— 连接本地后端,需改为本机IP
|
||||
buildConfigField "String", "API_BASE_URL", '"http://192.168.1.100:8039"'
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
release {
|
||||
// 生产环境 —— 连接公网服务器
|
||||
buildConfigField "String", "API_BASE_URL", '"http://101.43.95.130:8039"'
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
|
||||
@@ -234,8 +234,9 @@ public class TobeSerFragment extends MobanFragment {
|
||||
}
|
||||
|
||||
//订单状态:-2:已取消 -1:拒绝接单 0:待接单 1:已接单(待支付) 2:已支付(待服务)3:服务中 4:已完成 5申请退款 6退款中 7已退款 8:已结算
|
||||
// 待服务客户包含状态 1(已接单) 和 2(已支付)
|
||||
final HttpParams paramsPost = new HttpParams();
|
||||
paramsPost.put("status", "2");
|
||||
paramsPost.put("status", "1,2");
|
||||
paramsPost.put("pageSize", "10");
|
||||
paramsPost.put("pageNum", "1");
|
||||
new NetApi().getPostDatatwo(paramsPost, HttpConstants.URi_syste_view_list).subscribe(new Observer<Response>() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ruilaizi.service.network.http;
|
||||
|
||||
|
||||
import com.ruilaizi.service.BuildConfig;
|
||||
import com.ruilaizi.service.main.my.entity.loginBean;
|
||||
import com.ruilaizi.service.main.my.entity.loginInfoBean;
|
||||
import com.ruilaizi.service.main.find.entity.QuestionsEntity;
|
||||
@@ -25,8 +26,9 @@ public class MyApi {
|
||||
|
||||
|
||||
|
||||
// public static String URiBase = "http://chengjie.free.idcfengye.com";//旧地址
|
||||
public static String URiBase = "http://101.43.95.130:8039";//公网服务器地址
|
||||
// 使用 BuildConfig 自动切换开发/生产环境
|
||||
// Debug → 本地IP,Release → 公网服务器
|
||||
public static String URiBase = BuildConfig.API_BASE_URL;
|
||||
|
||||
/**
|
||||
* 网络接口前缀
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.ruilaizi.service.okgonet;
|
||||
|
||||
import com.ruilaizi.service.BuildConfig;
|
||||
|
||||
/**
|
||||
* 项目名:JiaJieSong
|
||||
* 包名:com.fanghoo.jiajiesong.http
|
||||
@@ -9,9 +11,9 @@ package com.ruilaizi.service.okgonet;
|
||||
* 描述:所有请求相关地址
|
||||
*/
|
||||
public class HttpConstants {
|
||||
// public static String URiBase = "https://35q45673j2.goho.co";//测试服务器
|
||||
// public static String URiBase = "https://ruilaizipj.com";//线上服务器(旧地址)
|
||||
public static String URiBase = "http://101.43.95.130:8039";//公网服务器地址
|
||||
// 使用 BuildConfig 自动切换开发/生产环境
|
||||
// Debug → 本地IP,Release → 公网服务器
|
||||
public static String URiBase = BuildConfig.API_BASE_URL;
|
||||
public static Boolean Dataflag = true;// 真假数据源
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.ruoyi.system.controller;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -62,6 +63,11 @@ public class OrderViewController extends BaseController
|
||||
}else if("C".equals(sysUser.getUserType())){
|
||||
orderView.setUsercId(userId);
|
||||
}
|
||||
// 支持多状态查询(逗号分隔)
|
||||
if (orderView.getStatus() != null && orderView.getStatus().contains(",")) {
|
||||
orderView.setStatusList(Arrays.asList(orderView.getStatus().split(",")));
|
||||
orderView.setStatus(null);
|
||||
}
|
||||
startPage();
|
||||
List<OrderView> list = orderViewService.selectOrderViewList(orderView);
|
||||
return getDataTable(list);
|
||||
@@ -204,7 +210,8 @@ public class OrderViewController extends BaseController
|
||||
@PostMapping("/acceptOrderYes")
|
||||
public AjaxResult acceptOrderYes(OrderView orderView)
|
||||
{
|
||||
return toAjax(orderViewService.acceptOrderYes(orderView));
|
||||
Long userId = this.getLoginUser().getUserId();
|
||||
return toAjax(orderViewService.acceptOrderYes(orderView, userId));
|
||||
}
|
||||
/**
|
||||
* 新增【接订单】
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ruoyi.system.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
@@ -144,6 +145,9 @@ public class OrderView extends BaseEntity
|
||||
@Excel(name = "退回给患者金额")
|
||||
private String tuihuiMoney;
|
||||
|
||||
/** 状态列表(多选查询) */
|
||||
private List<String> statusList;
|
||||
|
||||
/** 医院ID */
|
||||
private Long hospitalId;
|
||||
|
||||
@@ -453,6 +457,14 @@ public class OrderView extends BaseEntity
|
||||
this.tuihuiMoney = tuihuiMoney;
|
||||
}
|
||||
|
||||
public List<String> getStatusList() {
|
||||
return statusList;
|
||||
}
|
||||
|
||||
public void setStatusList(List<String> statusList) {
|
||||
this.statusList = statusList;
|
||||
}
|
||||
|
||||
public Long getHospitalId() {
|
||||
return hospitalId;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public interface IOrderViewService
|
||||
*/
|
||||
public int deleteOrderViewByOrderId(Long orderId);
|
||||
|
||||
public int acceptOrderYes(OrderView orderView);
|
||||
public int acceptOrderYes(OrderView orderView, Long userId);
|
||||
public int acceptOrderNo(OrderView orderView);
|
||||
|
||||
int startServiceWithOrder(OrderView orderView);
|
||||
|
||||
@@ -97,10 +97,11 @@ public class OrderViewServiceImpl implements IOrderViewService
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptOrderYes(OrderView orderView) {
|
||||
public int acceptOrderYes(OrderView orderView, Long userId) {
|
||||
RlzOrder order=rlzOrderMapper.selectRlzOrderByOrderId(orderView.getOrderId());
|
||||
order.setYuliu3("1");//已接单
|
||||
order.setStatus("1");//已接单
|
||||
order.setbId(userId);//绑定陪护员ID
|
||||
return rlzOrderMapper.updateRlzOrder(order);
|
||||
}
|
||||
@Override
|
||||
|
||||
@@ -59,6 +59,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="jiesuanMoney != null and jiesuanMoney != ''"> and jiesuan_money = #{jiesuanMoney}</if>
|
||||
<if test="price != null and price != ''"> and price = #{price}</if>
|
||||
<if test="status != null and status != ''"> and status = #{status}</if>
|
||||
<if test="statusList != null and statusList.size() > 0"> and status in <foreach collection="statusList" item="s" open="(" separator="," close=")">#{s}</foreach></if>
|
||||
<if test="isjiedan != null and isjiedan != ''"> and isjiedan = #{isjiedan}</if>
|
||||
<if test="juejuereson != null and juejuereson != ''"> and juejuereson = #{juejuereson}</if>
|
||||
<if test="userbId != null "> and userb_id = #{userbId}</if>
|
||||
|
||||
Reference in New Issue
Block a user