feat(订单): 添加业务类型参数并实现认证订单支付流程
在创建订单API中添加business_type参数区分买车和认证订单 在商品详情页和认证页中分别传入对应的业务类型 完善支付组件的支付成功和失败处理逻辑
Showing
4 changed files
with
117 additions
and
42 deletions
| 1 | /* | 1 | /* |
| 2 | * @Date: 2025-07-03 17:21:45 | 2 | * @Date: 2025-07-03 17:21:45 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-07-28 11:51:11 | 4 | + * @LastEditTime: 2025-07-31 15:50:33 |
| 5 | * @FilePath: /jgdl/src/api/orders.js | 5 | * @FilePath: /jgdl/src/api/orders.js |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | */ | 7 | */ |
| ... | @@ -39,6 +39,7 @@ export const getOrderDetailAPI = (params) => fn(fetch.get(Api.GET_ORDER_DETAIL, | ... | @@ -39,6 +39,7 @@ export const getOrderDetailAPI = (params) => fn(fetch.get(Api.GET_ORDER_DETAIL, |
| 39 | * @description: 创建订单 | 39 | * @description: 创建订单 |
| 40 | * @param vehicle_id 车辆ID | 40 | * @param vehicle_id 车辆ID |
| 41 | * @param total_amount 总价 | 41 | * @param total_amount 总价 |
| 42 | + * @param business_type 业务类型(sell=买车订单, verification=认证订单) | ||
| 42 | * @returns data{ id } | 43 | * @returns data{ id } |
| 43 | */ | 44 | */ |
| 44 | export const createOrderAPI = (params) => fn(fetch.post(Api.CREATE_ORDER, params)); | 45 | export const createOrderAPI = (params) => fn(fetch.post(Api.CREATE_ORDER, params)); | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2023-12-20 14:11:11 | 2 | * @Date: 2023-12-20 14:11:11 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-07-16 18:20:38 | 4 | + * @LastEditTime: 2025-07-31 15:30:59 |
| 5 | * @FilePath: /jgdl/src/components/payCard.vue | 5 | * @FilePath: /jgdl/src/components/payCard.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -135,6 +135,20 @@ const goToPay = async () => { | ... | @@ -135,6 +135,20 @@ const goToPay = async () => { |
| 135 | url: '/pages/myOrders/index', | 135 | url: '/pages/myOrders/index', |
| 136 | }); | 136 | }); |
| 137 | } | 137 | } |
| 138 | + if (current_page === 'pages/setAuthCar/index') { // 发布认证页打开 | ||
| 139 | + // 发出支付成功事件,通知父组件更新订单状态 | ||
| 140 | + emit('paySuccess', { orderId: id.value }); | ||
| 141 | + } | ||
| 142 | + } | ||
| 143 | + }, | ||
| 144 | + fail: () => { | ||
| 145 | + let current_page = getCurrentPageUrl(); | ||
| 146 | + if (current_page === 'pages/setAuthCar/index') { // 发布认证页打开 | ||
| 147 | + Taro.showModal({ | ||
| 148 | + title: '温馨提示', | ||
| 149 | + content: '需要付费才能认证', | ||
| 150 | + showCancel: false, | ||
| 151 | + }); | ||
| 138 | } | 152 | } |
| 139 | } | 153 | } |
| 140 | }); | 154 | }); | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-09-19 14:11:06 | 2 | * @Date: 2022-09-19 14:11:06 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-07-30 14:48:32 | 4 | + * @LastEditTime: 2025-07-31 15:29:14 |
| 5 | * @FilePath: /jgdl/src/pages/productDetail/index.vue | 5 | * @FilePath: /jgdl/src/pages/productDetail/index.vue |
| 6 | * @Description: 商品详情页 | 6 | * @Description: 商品详情页 |
| 7 | --> | 7 | --> |
| ... | @@ -485,6 +485,7 @@ const handlePurchase = async () => { | ... | @@ -485,6 +485,7 @@ const handlePurchase = async () => { |
| 485 | const onPay = async ({ id, remain_time, price }) => { | 485 | const onPay = async ({ id, remain_time, price }) => { |
| 486 | try { | 486 | try { |
| 487 | const { code, data } = await createOrderAPI({ | 487 | const { code, data } = await createOrderAPI({ |
| 488 | + business_type: 'sell', | ||
| 488 | vehicle_id: id, | 489 | vehicle_id: id, |
| 489 | total_amount: price | 490 | total_amount: price |
| 490 | }) | 491 | }) | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-09-19 14:11:06 | 2 | * @Date: 2022-09-19 14:11:06 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-07-17 14:31:55 | 4 | + * @LastEditTime: 2025-08-01 14:19:54 |
| 5 | * @FilePath: /jgdl/src/pages/setAuthCar/index.vue | 5 | * @FilePath: /jgdl/src/pages/setAuthCar/index.vue |
| 6 | * @Description: 申请认证 | 6 | * @Description: 申请认证 |
| 7 | --> | 7 | --> |
| ... | @@ -90,8 +90,10 @@ | ... | @@ -90,8 +90,10 @@ |
| 90 | <nut-form-item label-position="top" label="品牌型号选择" prop="brandModel" required | 90 | <nut-form-item label-position="top" label="品牌型号选择" prop="brandModel" required |
| 91 | :rules="[{ required: true, message: '请选择品牌型号' }]"> | 91 | :rules="[{ required: true, message: '请选择品牌型号' }]"> |
| 92 | <view class="form-item-content" @click="showBrandModelPicker"> | 92 | <view class="form-item-content" @click="showBrandModelPicker"> |
| 93 | - <text class="form-value" :class="{ 'form-value-selected': formData.brand && formData.model, 'form-value-placeholder': !(formData.brand && formData.model) }"> | 93 | + <text class="form-value" |
| 94 | - {{ formData.brand && formData.model ? `${formData.brand} ${formData.model}` : '请选择品牌型号' }} | 94 | + :class="{ 'form-value-selected': formData.brand && formData.model, 'form-value-placeholder': !(formData.brand && formData.model) }"> |
| 95 | + {{ formData.brand && formData.model ? `${formData.brand} ${formData.model}` : '请选择品牌型号' | ||
| 96 | + }} | ||
| 95 | </text> | 97 | </text> |
| 96 | <Right class="arrow-icon" /> | 98 | <Right class="arrow-icon" /> |
| 97 | </view> | 99 | </view> |
| ... | @@ -99,7 +101,8 @@ | ... | @@ -99,7 +101,8 @@ |
| 99 | 101 | ||
| 100 | <!-- 续航里程 --> | 102 | <!-- 续航里程 --> |
| 101 | <nut-form-item label="续航里程" prop="range_km"> | 103 | <nut-form-item label="续航里程" prop="range_km"> |
| 102 | - <nut-input v-model="formData.range_km" placeholder="请输入" type="number" input-align="right" @input="validateRangeInput"> | 104 | + <nut-input v-model="formData.range_km" placeholder="请输入" type="number" input-align="right" |
| 105 | + @input="validateRangeInput"> | ||
| 103 | <template #right> | 106 | <template #right> |
| 104 | <text class="unit">公里</text> | 107 | <text class="unit">公里</text> |
| 105 | </template> | 108 | </template> |
| ... | @@ -108,7 +111,8 @@ | ... | @@ -108,7 +111,8 @@ |
| 108 | 111 | ||
| 109 | <!-- 最高时速 --> | 112 | <!-- 最高时速 --> |
| 110 | <nut-form-item label="最高时速" prop="max_speed_kmh"> | 113 | <nut-form-item label="最高时速" prop="max_speed_kmh"> |
| 111 | - <nut-input v-model="formData.max_speed_kmh" placeholder="请输入" type="number" input-align="right" @input="validateMaxSpeedInput"> | 114 | + <nut-input v-model="formData.max_speed_kmh" placeholder="请输入" type="number" input-align="right" |
| 115 | + @input="validateMaxSpeedInput"> | ||
| 112 | <template #right> | 116 | <template #right> |
| 113 | <text class="unit">km/h</text> | 117 | <text class="unit">km/h</text> |
| 114 | </template> | 118 | </template> |
| ... | @@ -135,6 +139,9 @@ | ... | @@ -135,6 +139,9 @@ |
| 135 | <!-- 品牌型号选择器 --> | 139 | <!-- 品牌型号选择器 --> |
| 136 | <BrandModelPicker ref="brandModelPickerRef" :brand-options="brandOptions" @confirm="onBrandModelConfirm" | 140 | <BrandModelPicker ref="brandModelPickerRef" :brand-options="brandOptions" @confirm="onBrandModelConfirm" |
| 137 | @cancel="onBrandModelCancel" /> | 141 | @cancel="onBrandModelCancel" /> |
| 142 | + | ||
| 143 | + <!-- 支付组件 --> | ||
| 144 | + <payCard :visible="show_pay" :data="payData" @close="onPayClose" @paySuccess="onPaySuccess" /> | ||
| 138 | </view> | 145 | </view> |
| 139 | </template> | 146 | </template> |
| 140 | 147 | ||
| ... | @@ -145,10 +152,12 @@ import Taro from '@tarojs/taro' | ... | @@ -145,10 +152,12 @@ import Taro from '@tarojs/taro' |
| 145 | import './index.less' | 152 | import './index.less' |
| 146 | import BASE_URL from '@/utils/config'; | 153 | import BASE_URL from '@/utils/config'; |
| 147 | import BrandModelPicker from '@/components/BrandModelPicker.vue' | 154 | import BrandModelPicker from '@/components/BrandModelPicker.vue' |
| 155 | +import payCard from '@/components/payCard.vue' | ||
| 148 | 156 | ||
| 149 | // 导入接口 | 157 | // 导入接口 |
| 150 | import { getBrandsModelsAPI } from '@/api/other'; | 158 | import { getBrandsModelsAPI } from '@/api/other'; |
| 151 | import { addVehicleAPI, editVehicleAPI, getVehicleDetailAPI } from '@/api/car'; | 159 | import { addVehicleAPI, editVehicleAPI, getVehicleDetailAPI } from '@/api/car'; |
| 160 | +import { createOrderAPI } from '@/api/orders' | ||
| 152 | 161 | ||
| 153 | // 获取页面参数 | 162 | // 获取页面参数 |
| 154 | const instance = Taro.getCurrentInstance() | 163 | const instance = Taro.getCurrentInstance() |
| ... | @@ -195,7 +204,78 @@ const brandModelPickerRef = ref(null) | ... | @@ -195,7 +204,78 @@ const brandModelPickerRef = ref(null) |
| 195 | // 品牌型号选项数据 | 204 | // 品牌型号选项数据 |
| 196 | const brandOptions = ref([]) | 205 | const brandOptions = ref([]) |
| 197 | 206 | ||
| 207 | +/** | ||
| 208 | + * 支付模块 | ||
| 209 | + */ | ||
| 210 | +const show_pay = ref(false) | ||
| 211 | +const payData = ref({ | ||
| 212 | + id: '', | ||
| 213 | + price: 0, | ||
| 214 | + remain_time: 0 | ||
| 215 | +}) | ||
| 198 | 216 | ||
| 217 | +/** | ||
| 218 | + * 发送订单支付信息到支付组件 | ||
| 219 | + * @param {Object} payInfo - 支付信息 | ||
| 220 | + * @param {string} payInfo.id - 订单ID | ||
| 221 | + * @param {number} payInfo.remain_time - 剩余时间 | ||
| 222 | + * @param {number} payInfo.price - 价格 | ||
| 223 | + */ | ||
| 224 | +const onPay = async ({ id, remain_time, price }) => { | ||
| 225 | + try { | ||
| 226 | + const { code, data } = await createOrderAPI({ | ||
| 227 | + business_type: 'verification', | ||
| 228 | + vehicle_id: id, | ||
| 229 | + total_amount: price | ||
| 230 | + }) | ||
| 231 | + if (code) { | ||
| 232 | + show_pay.value = true | ||
| 233 | + payData.value.id = data.id | ||
| 234 | + payData.value.price = price | ||
| 235 | + payData.value.remain_time = remain_time | ||
| 236 | + } | ||
| 237 | + } catch (error) { | ||
| 238 | + console.error('创建订单失败:', error) | ||
| 239 | + } | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | +/** | ||
| 243 | + * 关闭支付弹框 | ||
| 244 | + */ | ||
| 245 | +const onPayClose = () => { | ||
| 246 | + show_pay.value = false | ||
| 247 | +} | ||
| 248 | + | ||
| 249 | +/** | ||
| 250 | + * 处理支付成功事件 | ||
| 251 | + * @param {Object} data - 支付成功数据 | ||
| 252 | + * @param {string} data.orderId - 订单ID | ||
| 253 | + */ | ||
| 254 | +const onPaySuccess = ({ orderId }) => { | ||
| 255 | + if (isEditMode.value) { | ||
| 256 | + Taro.showToast({ | ||
| 257 | + title: '保存成功', | ||
| 258 | + icon: 'success', | ||
| 259 | + duration: 2000, | ||
| 260 | + complete: () => { | ||
| 261 | + // 保存成功后返回上一页 | ||
| 262 | + Taro.navigateBack() | ||
| 263 | + } | ||
| 264 | + }) | ||
| 265 | + } else { | ||
| 266 | + Taro.showModal({ | ||
| 267 | + title: '温馨提示', | ||
| 268 | + content: '认证提交成功,我们会尽快审核', | ||
| 269 | + showCancel: false, | ||
| 270 | + confirmText: '知道了', | ||
| 271 | + success: function (res) { | ||
| 272 | + if (res.confirm) { | ||
| 273 | + Taro.navigateBack() | ||
| 274 | + } | ||
| 275 | + } | ||
| 276 | + }) | ||
| 277 | + } | ||
| 278 | +} | ||
| 199 | 279 | ||
| 200 | /** | 280 | /** |
| 201 | * 触发图片上传 | 281 | * 触发图片上传 |
| ... | @@ -469,47 +549,26 @@ const onSubmit = async () => { | ... | @@ -469,47 +549,26 @@ const onSubmit = async () => { |
| 469 | if (isEditMode.value) { | 549 | if (isEditMode.value) { |
| 470 | // 编辑车辆,且认证时,op=verification,表示申请认证 | 550 | // 编辑车辆,且认证时,op=verification,表示申请认证 |
| 471 | const { code } = await editVehicleAPI({ id: carId.value, ...formData, op: 'verification' }) | 551 | const { code } = await editVehicleAPI({ id: carId.value, ...formData, op: 'verification' }) |
| 472 | - if (!code) { | 552 | + if (code) { |
| 473 | - throw new Error('更新失败') | 553 | + onPay({ |
| 554 | + id: data.id, | ||
| 555 | + remain_time: data.remain_time || 1800, // 30分钟 | ||
| 556 | + price: data.verification_price | ||
| 557 | + }) | ||
| 474 | } | 558 | } |
| 475 | } else { | 559 | } else { |
| 476 | // 新增车辆,且认证时,op=verification,表示只申请认证 | 560 | // 新增车辆,且认证时,op=verification,表示只申请认证 |
| 477 | - const { code } = await addVehicleAPI({ ...formData, op: 'verification' }) | 561 | + const { code, data } = await addVehicleAPI({ ...formData, op: 'verification' }) |
| 478 | - if (!code) { | 562 | + if (code) { |
| 479 | - throw new Error('提交失败') | 563 | + onPay({ |
| 564 | + id: data.id, | ||
| 565 | + remain_time: data.remain_time || 1800, // 30分钟 | ||
| 566 | + price: data.verification_price | ||
| 567 | + }) | ||
| 480 | } | 568 | } |
| 481 | } | 569 | } |
| 482 | 570 | ||
| 483 | Taro.hideLoading() | 571 | Taro.hideLoading() |
| 484 | - // 提交成功提示 | ||
| 485 | - if (isEditMode.value) { | ||
| 486 | - Taro.showToast({ | ||
| 487 | - title: '保存成功', | ||
| 488 | - icon: 'success', | ||
| 489 | - duration: 2000, | ||
| 490 | - complete: () => { | ||
| 491 | - // 保存成功后返回上一页 | ||
| 492 | - Taro.navigateBack() | ||
| 493 | - } | ||
| 494 | - }) | ||
| 495 | - } else { | ||
| 496 | - Taro.showModal({ | ||
| 497 | - title: '温馨提示', | ||
| 498 | - content: '认证提交成功,我们会尽快审核', | ||
| 499 | - showCancel: false, | ||
| 500 | - confirmText: '知道了', | ||
| 501 | - success: function (res) { | ||
| 502 | - if (res.confirm) { | ||
| 503 | - Taro.navigateBack() | ||
| 504 | - } | ||
| 505 | - } | ||
| 506 | - }) | ||
| 507 | - } | ||
| 508 | - | ||
| 509 | - // 返回上一页 | ||
| 510 | - // setTimeout(() => { | ||
| 511 | - // Taro.navigateBack() | ||
| 512 | - // }, 1500) | ||
| 513 | } catch (error) { | 572 | } catch (error) { |
| 514 | console.error('提交失败:', error) | 573 | console.error('提交失败:', error) |
| 515 | Taro.hideLoading() | 574 | Taro.hideLoading() | ... | ... |
-
Please register or login to post a comment