确认订单页(单商品)— 前端技术方案(C 端 · shop-app)
依据: 《确认订单页(单商品)功能需求.md》v1.0、《确认订单页(单商品)技术方案.md》v1.0
关联: 《商品详情内页前端技术方案》v1.0、《我的服务前端技术方案》、《确认订单页(多商品)技术方案》v1.1(接口同源)
范围: 消费者 APP shop-app 立即购买确认页、支付结果交互;不 改后端、不 实现购物车合单页、不 实现我的订单列表。
实现状态: 页面与 API 已落地(v1.1);支付为 Mock 弹窗 + pay/cancel 接口,待联调。
1. 技术栈与约定
| 项 |
说明 |
| 框架 |
uni-app Vue 3 + uview-plus |
| 请求 |
@/utils/request;须会员 Token |
| 鉴权 |
进入页 getToken();无 Token → 引导登录 |
| 规格 v1 |
统一规格;specText 由 formatSpecDisplayText(specDisplay) 生成 |
| 数据源 |
source=BUY_NOW;preview/submit items 恒 1 行 |
| 参考 |
pages/cart/index.vue(底栏合计)、subpackage/goods/detail.vue(数量/spec) |
2. 页面与路由
| 页面 |
路径 |
入口 |
| 确认订单(单商品) |
subpackage/order/checkout |
商品详情 · 立即购买 |
| 支付结果(可选) |
subpackage/order/pay-result |
支付成功/关闭后跳转 |
Query / 入参(推荐):
| 参数 |
必填 |
说明 |
| goodsId |
✓ |
商品 ID |
| quantity |
✓ |
购买数量(详情带入,页内可改) |
| specText |
否 |
规格展示文案;缺省后端生成 |
不推荐 仅依赖 query 传价/图:确认页 以 preview 接口为准(防篡改)。
路径常量(建议新增):
// utils/pageRoute.js
export const PAGE_CHECKOUT = '/subpackage/order/checkout'
export const PAGE_PAY_RESULT = '/subpackage/order/pay-result'
3. 文件清单
| 类型 |
路径 |
说明 |
| 确认页 |
shop-app/subpackage/order/checkout.vue |
地址 + 商品 + 金额 + 备注 + 提交 + Mock 支付弹窗 |
| 支付结果 |
shop-app/subpackage/order/pay-result.vue |
成功/关闭结果页 |
| 地址条 |
shop-app/components/order/AddressBar.vue |
展示/点击切换 |
| 商品行 |
shop-app/components/order/CheckoutGoodsRow.vue |
单商品 + 规格列表 + 改量 |
| API |
shop-app/api/checkout.js |
preview / submit |
| API |
shop-app/api/order.js |
pay / cancel / detail |
| 映射 |
shop-app/utils/checkoutDisplay.js |
preview VO → 页面模型 |
| 常量 |
shop-app/constants/checkout.js |
SOURCE_BUY_NOW、PAY_TYPE=1、备注上限 |
已改上游:
| 文件 |
改动 |
subpackage/goods/detail.vue |
doBuyNow → PAGE_CHECKOUT 带 goodsId/quantity/specText |
pages.json |
分包 pkg-order |
utils/pageRoute.js |
PAGE_CHECKOUT、PAGE_PAY_RESULT |
utils/goodsDetail.js |
formatSpecDisplayText(§ 分隔规格) |
utils/cartSpec.js |
parseCartSpecText 确认页规格展示复用 |
4. 接口封装
4.1 确认页 api/checkout.js
| 方法 |
HTTP |
路径 |
说明 |
previewCheckout(data) |
POST |
/api/checkout/preview |
进入/改量/换地址 |
submitCheckout(data) |
POST |
/api/checkout/submit |
提交订单 |
preview / submit 公共 Body(BUY_NOW):
{
source: 'BUY_NOW',
addressId: 123, // preview 可选;submit 必填
items: [{
goodsId: 1,
quantity: 2,
specText: '批次:2024春季 / 包装:袋装', // 可选
buyerRemark: '' // 仅 submit
}]
}
4.2 支付 api/order.js
| 方法 |
HTTP |
路径 |
说明 |
payOrder(orderId) |
POST |
/api/order/{orderId}/pay |
v1 Mock 直接成功 |
cancelPay(orderId) |
POST |
/api/order/{orderId}/pay/cancel |
用户取消收银台 |
getOrderDetail(orderId) |
GET |
/api/order/{orderId} |
结果页 |
4.3 地址(复用)
| 方法 |
HTTP |
路径 |
getAddressList |
GET |
/api/member/address/list |
维护地址 → 跳转 我的服务 · 收货地址(已有路由)。
5. 页面结构(checkout.vue)
确认订单 checkout.vue
├── 导航栏「确认订单」
├── AddressBar(当前地址 / 切换 / 新增引导)
├── 店铺头(avatar + shopName)
├── CheckoutGoodsRow
│ ├── 主图、名称、specText、serviceDesc
│ ├── 单价、数量 stepper(1~maxStock)
│ └── 行小计
├── 金额区
│ ├── 商品总价 goodsAmountText
│ ├── 运费 freightAmountText + freightDesc
│ └── 应付 payAmountText
├── 备注 u-textarea(buyerRemark,≤200)
├── 支付方式(微信支付,固定选中)
└── 底栏:应付总额 + 「提交订单」
6. 交互流程
6.1 详情 → 确认页
detail · 立即购买
→ ensureCanPurchase(已有 purchaseAction.js)
→ uni.navigateTo({
url: `${PAGE_CHECKOUT}?goodsId=${id}&quantity=${qty}&specText=${encodeURIComponent(specText)}`
})
checkout onLoad
→ previewCheckout({ source: 'BUY_NOW', items: [{ goodsId, quantity, specText }] })
→ 渲染 address / shop / item / 金额
6.2 改数量
用户 +/- quantity
→ 本地更新 quantity(≥1,≤ maxStock)
→ debounce 300ms → previewCheckout(带 addressId)
→ 刷新 goodsAmount / freight / payAmount
6.3 切换地址
点击 AddressBar
→ 弹层列表 getAddressList()
→ 选择 addressId → previewCheckout
→ 若 freight 变化,刷新应付
无地址
→ 展示「请添加收货地址」→ 跳转我的服务新增
6.4 提交与支付(取消支付前闭环)
点击「提交订单」
→ 校验 addressId 已选
→ submitCheckout({ source, addressId, payType: 1, items: [{..., buyerRemark}] })
→ 成功得 orderId
→ 唤起支付(v1:直接调 payOrder(orderId) 模拟微信)
├── pay 成功
│ → navigateTo pay-result?status=success&orderId=
└── 用户取消 / pay 失败 / 调 cancelPay
→ Toast「订单已关闭」
→ 停留或返回详情
| 规则 |
前端 |
| COS-S5 防重复 |
submit/pay 中 loading + 按钮 disabled |
| COS11 取消关闭 |
微信 SDK 取消回调 → cancelPay |
| 库存/下架失败 |
展示后端 msg;不 生成订单 |
7. 数据映射 checkoutDisplay.js
export function mapCheckoutPreview(data) {
const item = (data.items || [])[0] || {}
return {
shop: data.shop || {},
address: data.address || null,
goods: {
goodsId: item.goodsId,
goodsName: item.goodsName,
mainPic: resolveFileUrl(item.mainPic),
specText: normalizeSpecText(item.specText),
serviceDesc: item.serviceDesc || '',
salePrice: item.salePrice,
quantity: item.quantity,
maxStock: item.maxStock,
subtotal: item.subtotal,
priceText: formatPrice(item.salePrice),
subtotalText: formatPrice(item.subtotal)
},
goodsAmount: data.goodsAmount,
freightAmount: data.freightAmount,
freightDesc: data.freightDesc || '',
payAmount: data.payAmount,
goodsAmountText: formatPrice(data.goodsAmount),
freightAmountText: formatPrice(data.freightAmount),
payAmountText: formatPrice(data.payAmount)
}
}
normalizeSpecText 可复用 cartDisplay.js 对 [object Object] 的兜底。
8. 详情页改造要点
detail.vue · doBuyNow:
async function doBuyNow() {
const ok = await ensureCanPurchase(goodsId.value, detail.value?.purchase?.reason)
if (!ok) return
const specText = formatSpecDisplayText(detail.value?.specDisplay)
const q = [
`goodsId=${goodsId.value}`,
`quantity=${quantity.value}`,
specText ? `specText=${encodeURIComponent(specText)}` : ''
].filter(Boolean).join('&')
uni.navigateTo({ url: `${PAGE_CHECKOUT}?${q}` })
}
移除占位 Toast「确认订单功能开发中」。
9. 与购物车确认页分工
| 项 |
单商品(本方案) |
多商品(购物车) |
| 路由 |
subpackage/order/checkout |
可 共用同页 或 checkout-cart |
| source |
BUY_NOW |
CART + cartItemIds |
| 进页 |
详情立即购买 |
prepare + navigate |
| pay 后 |
不 清购物车 |
删 cart 行 |
v1 建议: 单商品 独立路由;若 UI 高度一致,可后续合并为 checkout.vue + mode 参数。
10. 联调检查清单
| # |
项 |
| 1 |
未登录点立即购买 → 引导登录 |
| 2 |
preview 返回 1 行商品、默认地址 |
| 3 |
无地址时 submit 拦截并引导新增 |
| 4 |
改数量后 freight / payAmount 刷新 |
| 5 |
换地址后模版运费变化 |
| 6 |
submit 成功 → pay → 订单待发货 |
| 7 |
cancelPay 后订单已关闭,可回详情重购 |
| 8 |
下架商品 submit 失败且未生成订单 |
| 9 |
specText 不为 [object Object] |
11. 非本期
| 项 |
说明 |
| 微信 JSAPI 真实唤起 |
Mock pay 接口 |
| 我的订单列表续付 |
另册 |
| 购物车多商品确认页 |
多商品前端专册 |
| 多规格 SKU 矩阵 |
商品 SKU 落地后扩展 |
12. 修订记录
| 版本 |
说明 |
| v1.0 |
首版:BUY_NOW 确认页路由、checkout/order API、详情跳转、支付取消闭环 |
| v1.1 |
落地 checkout/pay-result 页面与组件;规格展示复用 parseCartSpecText |
文档版本:v1.1 · 工程目录 shop-app · 不修改《确认订单页(单商品)技术方案.md》(后端方案)