更新:课程确认订单和订单支付功能初步完成
This commit is contained in:
@@ -4,7 +4,11 @@ import type { IApiResponse } from '@/api/types'
|
|||||||
import type {
|
import type {
|
||||||
ICreateOrderParams,
|
ICreateOrderParams,
|
||||||
IGooglePayVerifyParams,
|
IGooglePayVerifyParams,
|
||||||
ICreateOrderResponse
|
ICreateOrderResponse,
|
||||||
|
IOrderGoods,
|
||||||
|
ICoupon,
|
||||||
|
ICourseOrderCreateParams,
|
||||||
|
IOrderInitData
|
||||||
} from '@/types/order'
|
} from '@/types/order'
|
||||||
import type { IUserInfo } from '@/types/user'
|
import type { IUserInfo } from '@/types/user'
|
||||||
|
|
||||||
@@ -59,5 +63,96 @@ export const orderApi = {
|
|||||||
method: 'POST'
|
method: 'POST'
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化订单准备数据
|
||||||
|
* @param params 初始化参数
|
||||||
|
*/
|
||||||
|
async initPrepareOrder(params: { uid: number; productList: Array<{ productId: number; quantity: number }> }) {
|
||||||
|
const res = await mainClient.request<IApiResponse<IOrderInitData>>({
|
||||||
|
url: 'common/buyOrder/initPrepareOrder',
|
||||||
|
method: 'POST',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据商品ID获取商品详情列表
|
||||||
|
* @param productIds 商品ID字符串(逗号分隔)
|
||||||
|
*/
|
||||||
|
async getShopProductListByIds(productIds: string) {
|
||||||
|
const res = await mainClient.request<IApiResponse<{ shopProductList: IOrderGoods[] }>>({
|
||||||
|
url: 'book/buyOrder/getShopProductListByIds',
|
||||||
|
method: 'POST',
|
||||||
|
data: { productIds }
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取VIP优惠金额
|
||||||
|
* @param productList 商品列表
|
||||||
|
*/
|
||||||
|
async getVipDiscountAmount(productList: Array<{ productId: number; quantity: number }>) {
|
||||||
|
const res = await mainClient.request<IApiResponse<{ discountAmount: number }>>({
|
||||||
|
url: 'book/buyOrder/getVipDiscountAmount',
|
||||||
|
method: 'POST',
|
||||||
|
data: { productList }
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取地区优惠金额
|
||||||
|
* @param productList 商品列表
|
||||||
|
*/
|
||||||
|
async getDistrictAmount(productList: Array<{ productId: number; quantity: number }>) {
|
||||||
|
const res = await mainClient.request<IApiResponse<{ districtAmount: number }>>({
|
||||||
|
url: 'book/buyOrder/getDistrictAmount',
|
||||||
|
method: 'POST',
|
||||||
|
data: { productList }
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取可用优惠券列表
|
||||||
|
* @param shopProductInfos 商品信息字符串(格式:productId:price:quantity,productId:price:quantity)
|
||||||
|
*/
|
||||||
|
async getCouponListPayment(shopProductInfos: string) {
|
||||||
|
const res = await mainClient.request<IApiResponse<{ couponHistoryList: ICoupon[] }>>({
|
||||||
|
url: 'common/coupon/getCouponListPayment',
|
||||||
|
method: 'POST',
|
||||||
|
data: { shopProductInfos }
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新购物车商品
|
||||||
|
* @param data 商品数据
|
||||||
|
*/
|
||||||
|
async updateCart(data: { productId: number; productAmount: number; price: number }) {
|
||||||
|
const res = await mainClient.request<IApiResponse>({
|
||||||
|
url: 'book/ordercart/update',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建课程订单
|
||||||
|
* @param data 订单数据
|
||||||
|
*/
|
||||||
|
async placeCourseOrder(data: ICourseOrderCreateParams) {
|
||||||
|
const res = await mainClient.request<IApiResponse<{ orderSn: string; money: number }>>({
|
||||||
|
url: 'book/buyOrder/placeOrder',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,11 +39,11 @@ export async function getVipInfo() {
|
|||||||
* @param current 当前页码
|
* @param current 当前页码
|
||||||
* @param limit 每页数量
|
* @param limit 每页数量
|
||||||
*/
|
*/
|
||||||
export async function getOrderList(current: number, limit: number, orderStatus: string) {
|
export async function getOrderList(page: number, limit: number, orderStatus: string) {
|
||||||
const res = await mainClient.request<IApiResponse<{ orders: IPageData<IOrder> }>>({
|
const res = await mainClient.request<IApiResponse<{ orders: IPageData<IOrder> }>>({
|
||||||
url: 'common/buyOrder/commonBuyOrderList',
|
url: 'common/buyOrder/commonBuyOrderList',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: { current, limit, orderStatus, come: '10', userId: uni.getStorageSync('userInfo').id }
|
data: { page, limit, orderStatus, come: '10', userId: uni.getStorageSync('userInfo').id }
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<!-- VIP优惠价 -->
|
<!-- VIP优惠价 -->
|
||||||
<view v-if="item.isVipPrice === 1 && item.vipPrice" class="price-info">
|
<view v-if="item.isVipPrice === 1 && item.vipPrice" class="price-info">
|
||||||
<text class="vip-price">{{ parseFloat(item.vipPrice).toFixed(2) }} 天医币</text>
|
<text class="vip-price">{{ parseFloat(item.vipPrice).toFixed(2) }} 天医币</text>
|
||||||
<text class="vip-label">VIP到手价</text>
|
<text class="vip-label">VIP优惠价</text>
|
||||||
<text class="original-price">{{ parseFloat(item.price).toFixed(2) }} 天医币</text>
|
<text class="original-price">{{ parseFloat(item.price).toFixed(2) }} 天医币</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|||||||
0
components/order/Payment.vue
Normal file
0
components/order/Payment.vue
Normal file
229
components/order/Price.vue
Normal file
229
components/order/Price.vue
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
<template>
|
||||||
|
<view class="">
|
||||||
|
<!-- 商品总价 -->
|
||||||
|
<!-- <view class="price-item">
|
||||||
|
<text class="label">{{ $t('order.totalPrice') }}</text>
|
||||||
|
<text class="value">¥{{ totalPrice.toFixed(2) }}</text>
|
||||||
|
</view> -->
|
||||||
|
|
||||||
|
<!-- 优惠券 -->
|
||||||
|
<!-- <view class="price-item" @click="showCouponPopup = true">
|
||||||
|
<view class="label-row">
|
||||||
|
<text class="label">{{ $t('order.coupon') }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="value-row">
|
||||||
|
<template v-if="!selectedCoupon">
|
||||||
|
<view v-if="availableCouponCount > 0" class="coupon-badge">
|
||||||
|
<text>{{ $t('order.couponCount', { count: availableCouponCount }) }}</text>
|
||||||
|
</view>
|
||||||
|
<text v-else-if="couponList.length === 0" class="unavailable-text">
|
||||||
|
{{ $t('order.noCoupon') }}
|
||||||
|
</text>
|
||||||
|
<text v-else class="unavailable-text">
|
||||||
|
{{ $t('order.unavailable') }}
|
||||||
|
</text>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<text class="discount-value">-¥{{ selectedCoupon.couponEntity.couponAmount }}</text>
|
||||||
|
<text class="reselect-btn">{{ $t('order.reselect') }}</text>
|
||||||
|
</template>
|
||||||
|
<image
|
||||||
|
v-if="availableCouponCount > 0 || selectedCoupon"
|
||||||
|
src="/static/icon/icon_right.png"
|
||||||
|
class="arrow-icon"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view> -->
|
||||||
|
|
||||||
|
<!-- 活动立减 -->
|
||||||
|
<view v-if="hasActivityDiscount" class="price-item">
|
||||||
|
<text class="label">{{ $t('order.activityDiscount') }}</text>
|
||||||
|
<text class="discount-value">-¥{{ activityDiscountAmount.toFixed(2) }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- VIP专享立减 -->
|
||||||
|
<view v-if="vipPrice > 0" class="price-item">
|
||||||
|
<view class="label-row">
|
||||||
|
<text class="vip-icon">VIP</text>
|
||||||
|
<text class="label">{{ $t('order.vipDiscount') }}</text>
|
||||||
|
</view>
|
||||||
|
<text class="discount-value">-¥{{ vipPrice.toFixed(2) }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 地区优惠 -->
|
||||||
|
<view v-if="districtAmount > 0" class="price-item">
|
||||||
|
<text class="label">{{ $t('order.districtDiscount') }}</text>
|
||||||
|
<text class="discount-value">-¥{{ districtAmount.toFixed(2) }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 积分 -->
|
||||||
|
<view v-if="initData && initData.user.jf > 0" class="price-item">
|
||||||
|
<view class="label-row">
|
||||||
|
<image src="/static/icon/jifen.png" class="icon-img" />
|
||||||
|
<text class="label">{{ $t('order.points') }}</text>
|
||||||
|
<text class="points-total">
|
||||||
|
({{ $t('order.allPoints') }}:{{ initData.user.jf }})
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
<text class="discount-value">-¥{{ jfNumberShow }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 积分输入 -->
|
||||||
|
<view v-if="initData && initData.user.jf > 0" class="points-input-section">
|
||||||
|
<text class="points-label">
|
||||||
|
{{ $t('order.maxPoints', { max: jfNumberMax }) }}
|
||||||
|
</text>
|
||||||
|
<view class="points-input-box">
|
||||||
|
<wd-input
|
||||||
|
v-model="jfNumber"
|
||||||
|
type="number"
|
||||||
|
:placeholder="$t('order.pointsPlaceholder')"
|
||||||
|
@input="handlePointsInput"
|
||||||
|
@clear="handlePointsClear"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<wd-cell-group border class="p-0!">
|
||||||
|
<wd-cell title="商品总价" :value="`${totalPrice.toFixed(2)}天医币`" />
|
||||||
|
<wd-cell title="优惠券" :value="`-${selectedCoupon?.couponEntity?.couponAmount || 0}天医币`" />
|
||||||
|
<wd-cell title="活动立减" :value="`-${selectedCoupon?.couponEntity?.couponAmount || 0}天医币`" />
|
||||||
|
<wd-cell :value="`-${vipPrice.toFixed(2)}天医币`">
|
||||||
|
<template #title><text class="text-[#f94f04] font-bold">VIP</text>专项立减</template>
|
||||||
|
</wd-cell>
|
||||||
|
<wd-cell title="地区优惠" :value="`-${selectedCoupon?.couponEntity?.couponAmount || 0}天医币`" />
|
||||||
|
</wd-cell-group>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
const props = defineProps({
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
totalPrice: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
vipPrice: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
:deep(.wd-cell__wrapper) {
|
||||||
|
padding: 5px 0;
|
||||||
|
|
||||||
|
.wd-cell__title {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.price-section {
|
||||||
|
.price-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 15rpx 0;
|
||||||
|
font-size: 28rpx;
|
||||||
|
|
||||||
|
.label-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vip-icon {
|
||||||
|
padding: 2rpx 8rpx;
|
||||||
|
background-color: #f94f04;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 20rpx;
|
||||||
|
border-radius: 4rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-img {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.points-total {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
|
||||||
|
.coupon-badge {
|
||||||
|
padding: 4rpx 20rpx;
|
||||||
|
background-color: #fceeeb;
|
||||||
|
color: #ec4729;
|
||||||
|
font-size: 24rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unavailable-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reselect-btn {
|
||||||
|
padding: 4rpx 12rpx;
|
||||||
|
background-color: #fe6035;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 24rpx;
|
||||||
|
border-radius: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow-icon {
|
||||||
|
width: 24rpx;
|
||||||
|
height: 24rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.discount-value {
|
||||||
|
color: #fe6035;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.points-input-section {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 15rpx 0;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
|
||||||
|
.points-label {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #7dc1f0;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.points-input-box {
|
||||||
|
width: 320rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -412,6 +412,66 @@
|
|||||||
},
|
},
|
||||||
"order": {
|
"order": {
|
||||||
"selectFuduScheme": "Select Fudu Scheme",
|
"selectFuduScheme": "Select Fudu Scheme",
|
||||||
"selectPurchaseScheme": "Select Purchase Scheme"
|
"selectPurchaseScheme": "Select Purchase Scheme",
|
||||||
|
"confirmTitle": "Confirm Order",
|
||||||
|
"goodsInfo": "Product Information",
|
||||||
|
"priceDetail": "Price Details",
|
||||||
|
"totalPrice": "Subtotal",
|
||||||
|
"coupon": "Coupon",
|
||||||
|
"points": "Points",
|
||||||
|
"vipDiscount": "VIP Exclusive Discount",
|
||||||
|
"activityDiscount": "Activity Discount",
|
||||||
|
"districtDiscount": "Regional Discount",
|
||||||
|
"actualPayment": "Total",
|
||||||
|
"paymentMethod": "Payment Method",
|
||||||
|
"virtualCoin": "Virtual Coin",
|
||||||
|
"balance": "Balance",
|
||||||
|
"recharge": "Recharge Now",
|
||||||
|
"remark": "Order Remark",
|
||||||
|
"remarkPlaceholder": "Optional: Leave a message",
|
||||||
|
"remarkTitle": "Order Remark",
|
||||||
|
"submit": "Pay Now",
|
||||||
|
"submitting": "Submitting...",
|
||||||
|
"total": "Total",
|
||||||
|
"noCoupon": "No coupons available",
|
||||||
|
"unavailable": "Unavailable",
|
||||||
|
"selectCoupon": "Please select a coupon",
|
||||||
|
"notUseCoupon": "Don't use coupon",
|
||||||
|
"reselect": "Reselect",
|
||||||
|
"selected": "Confirm",
|
||||||
|
"maxPoints": "Available Points ({max} pts)",
|
||||||
|
"pointsPlaceholder": "Enter points",
|
||||||
|
"allPoints": "Total Points",
|
||||||
|
"insufficientBalance": "Insufficient virtual coin balance",
|
||||||
|
"orderCreating": "Creating order",
|
||||||
|
"orderSuccess": "Purchase successful",
|
||||||
|
"orderFailed": "Failed, please try again",
|
||||||
|
"tooFrequent": "Too frequent, please wait",
|
||||||
|
"duplicateOrder": "You have a similar order recently. Continue?",
|
||||||
|
"duplicateConfirm": "Continue",
|
||||||
|
"duplicateCancel": "Cancel",
|
||||||
|
"customerService": "Customer Service",
|
||||||
|
"paymentTip": "1 Virtual Coin = 1 CNY",
|
||||||
|
"paymentTipTitle": "Notes",
|
||||||
|
"paymentTip1": "1. 1 Virtual Coin = 1 CNY",
|
||||||
|
"paymentTip2": "2. For questions, please call customer service",
|
||||||
|
"paymentTip3": "3. Non-mainland China users can pay by credit card. Simple and fast, recommended! Credit cards with Visa or MasterCard logos are accepted. Please send payment request to email",
|
||||||
|
"paymentTip3_1": "(click to copy) with course name, amount, registered name and phone number, or add WeChat customer service (",
|
||||||
|
"paymentTip3_2": ") (click to copy). We will send payment link within 24 hours.",
|
||||||
|
"ensureBalance": "Ensure sufficient virtual coin balance",
|
||||||
|
"vipLabel": "VIP Discount",
|
||||||
|
"activityLabel": "Activity Price",
|
||||||
|
"vipPriceLabel": "VIP Price",
|
||||||
|
"quantity": "Quantity",
|
||||||
|
"couponAmount": "¥",
|
||||||
|
"couponUseLevel": "Min. {level} CNY",
|
||||||
|
"couponExpiry": "Valid until",
|
||||||
|
"couponForever": "Permanent",
|
||||||
|
"couponReason": "Reason",
|
||||||
|
"couponUsage": "Usage",
|
||||||
|
"couponType0": "All Products",
|
||||||
|
"couponType1": "Specific Courses",
|
||||||
|
"couponType2": "Course Categories",
|
||||||
|
"couponCount": "{count} coupons"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -413,6 +413,66 @@
|
|||||||
},
|
},
|
||||||
"order": {
|
"order": {
|
||||||
"selectFuduScheme": "选择复读方案",
|
"selectFuduScheme": "选择复读方案",
|
||||||
"selectPurchaseScheme": "选择购买方案"
|
"selectPurchaseScheme": "选择购买方案",
|
||||||
|
"confirmTitle": "确认订单",
|
||||||
|
"goodsInfo": "商品信息",
|
||||||
|
"priceDetail": "价格明细",
|
||||||
|
"totalPrice": "商品总价",
|
||||||
|
"coupon": "优惠券",
|
||||||
|
"points": "积分",
|
||||||
|
"vipDiscount": "VIP专享立减",
|
||||||
|
"activityDiscount": "活动立减",
|
||||||
|
"districtDiscount": "地区优惠",
|
||||||
|
"actualPayment": "实付款",
|
||||||
|
"paymentMethod": "支付方式",
|
||||||
|
"virtualCoin": "天医币",
|
||||||
|
"balance": "余额",
|
||||||
|
"recharge": "立即充值",
|
||||||
|
"remark": "订单备注",
|
||||||
|
"remarkPlaceholder": "选填:给商家留言",
|
||||||
|
"remarkTitle": "订单备注",
|
||||||
|
"submit": "立即支付",
|
||||||
|
"submitting": "提交中...",
|
||||||
|
"total": "合计",
|
||||||
|
"noCoupon": "暂无可用优惠券",
|
||||||
|
"unavailable": "不可用",
|
||||||
|
"selectCoupon": "请选择优惠券",
|
||||||
|
"notUseCoupon": "不使用优惠券",
|
||||||
|
"reselect": "重新选择",
|
||||||
|
"selected": "选好了",
|
||||||
|
"maxPoints": "可用积分({max}分)",
|
||||||
|
"pointsPlaceholder": "请输入积分",
|
||||||
|
"allPoints": "全部积分",
|
||||||
|
"insufficientBalance": "天医币余额不足",
|
||||||
|
"orderCreating": "正在请求订单",
|
||||||
|
"orderSuccess": "购买成功",
|
||||||
|
"orderFailed": "失败,请重新下单",
|
||||||
|
"tooFrequent": "操作太频繁了,休息下吧",
|
||||||
|
"duplicateOrder": "您短时间内有一笔相同金额的订单,是否确定继续下单?",
|
||||||
|
"duplicateConfirm": "继续操作",
|
||||||
|
"duplicateCancel": "点错了",
|
||||||
|
"customerService": "客服",
|
||||||
|
"paymentTip": "1天医币 = 1元人民币",
|
||||||
|
"paymentTipTitle": "说明",
|
||||||
|
"paymentTip1": "1. 1天医币 = 1元人民币",
|
||||||
|
"paymentTip2": "2.若有疑问或意见请致电客服",
|
||||||
|
"paymentTip3": "3.非中国大陆用户可以信用卡支付。简单快捷,推荐使用!支付时使用的信用卡需要带有Visa或MasterCard的标识。请向邮箱",
|
||||||
|
"paymentTip3_1": "(点击复制)发送支付请求,内容需包含:拟购买的课程名称、支付金额、APP注册姓名及手机号码,或者加一路健康客服微信(",
|
||||||
|
"paymentTip3_2": ")(点击复制)联系我们,我们将在24小时内向您的邮箱或者微信发送支付链接,根据提示即可完成信用卡支付,无需兑换外币。",
|
||||||
|
"ensureBalance": "确保您的天医币足够支付",
|
||||||
|
"vipLabel": "VIP优惠",
|
||||||
|
"activityLabel": "活动价",
|
||||||
|
"vipPriceLabel": "VIP到手价",
|
||||||
|
"quantity": "数量",
|
||||||
|
"couponAmount": "¥",
|
||||||
|
"couponUseLevel": "满{level}元可用",
|
||||||
|
"couponExpiry": "有效期至",
|
||||||
|
"couponForever": "永久有效",
|
||||||
|
"couponReason": "不可用原因",
|
||||||
|
"couponUsage": "使用说明",
|
||||||
|
"couponType0": "全场通用",
|
||||||
|
"couponType1": "指定课程可用",
|
||||||
|
"couponType2": "指定课程品类可用",
|
||||||
|
"couponCount": "共 {count} 张"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,10 +152,10 @@
|
|||||||
"navigationBarTitleText": "%courseDetails.chapter%"
|
"navigationBarTitleText": "%courseDetails.chapter%"
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"path": "pages/course/order",
|
"path": "pages/order/confirmOrder",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationStyle": "custom",
|
"navigationStyle": "custom",
|
||||||
"navigationBarTitleText": "%courseOrder.orderTitle%"
|
"navigationBarTitleText": "%order.confirmTitle%"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -449,8 +449,6 @@ const closeGoodsSelector = () => {
|
|||||||
*/
|
*/
|
||||||
const confirmPurchase = () => {
|
const confirmPurchase = () => {
|
||||||
showProtocol.value = false
|
showProtocol.value = false
|
||||||
uni.showToast({ icon: 'none', title: '订单及支付功能开发中' })
|
|
||||||
return false
|
|
||||||
if (!selectedGoods.value) return
|
if (!selectedGoods.value) return
|
||||||
|
|
||||||
showProtocol.value = false
|
showProtocol.value = false
|
||||||
@@ -458,15 +456,16 @@ const confirmPurchase = () => {
|
|||||||
// 跳转到确认订单页
|
// 跳转到确认订单页
|
||||||
const orderData = {
|
const orderData = {
|
||||||
goods: [{ ...selectedGoods.value, productAmount: 1 }],
|
goods: [{ ...selectedGoods.value, productAmount: 1 }],
|
||||||
typeId: 0,
|
// typeId: 0,
|
||||||
navTitle: courseDetail.value?.title,
|
// navTitle: courseDetail.value?.title,
|
||||||
title: courseDetail.value?.title,
|
// title: courseDetail.value?.title,
|
||||||
isFudu: isFudu.value,
|
// isFudu: isFudu.value,
|
||||||
fuduId: isFudu.value ? fuduCatalogueId.value : undefined
|
// fuduId: isFudu.value ? fuduCatalogueId.value : undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/course/order?data=${encodeURIComponent(JSON.stringify(orderData))}`
|
// url: `/pages/order/confirmOrder?data=${encodeURIComponent(JSON.stringify(orderData))}`
|
||||||
|
url: `/pages/order/confirmOrder?goods=${selectedGoods.value.productId}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
BIN
static/icon/jifen.png
Normal file
BIN
static/icon/jifen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
BIN
static/icon/pay_3.png
Normal file
BIN
static/icon/pay_3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@@ -10,6 +10,7 @@
|
|||||||
--color-red-500: oklch(63.7% 0.237 25.331);
|
--color-red-500: oklch(63.7% 0.237 25.331);
|
||||||
--color-white: #fff;
|
--color-white: #fff;
|
||||||
--spacing: 0.25rem;
|
--spacing: 0.25rem;
|
||||||
|
--font-weight-bold: 700;
|
||||||
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
--default-transition-duration: 150ms;
|
--default-transition-duration: 150ms;
|
||||||
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
@@ -293,15 +294,40 @@
|
|||||||
.bg-red-500 {
|
.bg-red-500 {
|
||||||
background-color: var(--color-red-500);
|
background-color: var(--color-red-500);
|
||||||
}
|
}
|
||||||
|
.p-0 {
|
||||||
|
padding: calc(var(--spacing) * 0);
|
||||||
|
}
|
||||||
|
.p-0\! {
|
||||||
|
padding: calc(var(--spacing) * 0) !important;
|
||||||
|
}
|
||||||
.pt-\[40px\] {
|
.pt-\[40px\] {
|
||||||
padding-top: 40px;
|
padding-top: 40px;
|
||||||
}
|
}
|
||||||
|
.pb-0 {
|
||||||
|
padding-bottom: calc(var(--spacing) * 0);
|
||||||
|
}
|
||||||
|
.pb-0\! {
|
||||||
|
padding-bottom: calc(var(--spacing) * 0) !important;
|
||||||
|
}
|
||||||
.text-center {
|
.text-center {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
.text-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.font-bold {
|
||||||
|
--tw-font-weight: var(--font-weight-bold);
|
||||||
|
font-weight: var(--font-weight-bold);
|
||||||
|
}
|
||||||
.text-\[\#000\] {
|
.text-\[\#000\] {
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
.text-\[\#7dc1f0\] {
|
||||||
|
color: #7dc1f0;
|
||||||
|
}
|
||||||
|
.text-\[\#f94f04\] {
|
||||||
|
color: #f94f04;
|
||||||
|
}
|
||||||
.text-\[\#fff\] {
|
.text-\[\#fff\] {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
@@ -393,6 +419,10 @@
|
|||||||
inherits: false;
|
inherits: false;
|
||||||
initial-value: solid;
|
initial-value: solid;
|
||||||
}
|
}
|
||||||
|
@property --tw-font-weight {
|
||||||
|
syntax: "*";
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
@property --tw-ordinal {
|
@property --tw-ordinal {
|
||||||
syntax: "*";
|
syntax: "*";
|
||||||
inherits: false;
|
inherits: false;
|
||||||
@@ -585,6 +615,7 @@
|
|||||||
--tw-skew-x: initial;
|
--tw-skew-x: initial;
|
||||||
--tw-skew-y: initial;
|
--tw-skew-y: initial;
|
||||||
--tw-border-style: solid;
|
--tw-border-style: solid;
|
||||||
|
--tw-font-weight: initial;
|
||||||
--tw-ordinal: initial;
|
--tw-ordinal: initial;
|
||||||
--tw-slashed-zero: initial;
|
--tw-slashed-zero: initial;
|
||||||
--tw-numeric-figure: initial;
|
--tw-numeric-figure: initial;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
:root,
|
:root,
|
||||||
page {
|
page {
|
||||||
/* 文字字号 */
|
/* 文字字号 */
|
||||||
--wot-fs-title: 18px; // 标题字号/重要正文字号
|
--wot-fs-title: 36rpx; // 标题字号/重要正文字号
|
||||||
--wot-fs-content: 16px; // 普通正文
|
--wot-fs-content: 28rpx; // 普通正文
|
||||||
--wot-fs-secondary: 14px; // 次要信息,注释/补充/正文
|
--wot-fs-secondary: 24rpx; // 次要信息,注释/补充/正文
|
||||||
--wot-fs-tertiary: 12px; // 次次要信息,注释/补充/正文
|
--wot-fs-tertiary: 20rpx; // 次次要信息,注释/补充/正文
|
||||||
|
|
||||||
// 导航栏
|
// 导航栏
|
||||||
--wot-navbar-background: #fff;
|
--wot-navbar-background: #fff;
|
||||||
@@ -16,7 +16,7 @@ page {
|
|||||||
// --wot-tabbar-item-title-font-size: 16px;
|
// --wot-tabbar-item-title-font-size: 16px;
|
||||||
|
|
||||||
// cell
|
// cell
|
||||||
--wot-cell-title-fs: 16px;
|
--wot-cell-title-fs: 28rpx;
|
||||||
|
|
||||||
// dropdown
|
// dropdown
|
||||||
// --wot-drop-menu-selected-color: #5355C8;
|
// --wot-drop-menu-selected-color: #5355C8;
|
||||||
|
|||||||
148
types/order.d.ts
vendored
148
types/order.d.ts
vendored
@@ -26,61 +26,127 @@ export interface IOrder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单创建参数接口
|
* 课程订单商品信息
|
||||||
*/
|
*/
|
||||||
export interface ICreateOrderParams {
|
export interface IOrderGoods {
|
||||||
paymentMethod: '4' | '5' // 支付方式: 4-虚拟币, 5-Google Pay
|
productId: number
|
||||||
orderMoney: number | string // 订单金额
|
productName: string
|
||||||
abroadBookId: number // 图书ID
|
productImages: string
|
||||||
orderType: 'abroadBook' // 订单类型
|
price: number
|
||||||
|
vipPrice: number | null
|
||||||
|
activityPrice: number | null
|
||||||
|
isVipPrice: number // 是否有VIP优惠 0-否 1-是
|
||||||
|
productAmount: number // 购买数量
|
||||||
|
goodsType: string // 商品类型 "05" for course
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Google Pay 验证参数接口
|
* 优惠券实体信息
|
||||||
*/
|
*/
|
||||||
export interface IGooglePayVerifyParams {
|
export interface ICouponEntity {
|
||||||
purchaseToken: string // 购买凭证
|
id: number
|
||||||
orderSn: string // 订单号
|
couponName: string
|
||||||
productId: string // 产品ID
|
couponAmount: number
|
||||||
|
useLevel: number // 满多少可用
|
||||||
|
couponRange: number // 0-全场 1-指定课程 2-指定品类
|
||||||
|
remark?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单创建响应接口
|
* 优惠券信息
|
||||||
*/
|
*/
|
||||||
export interface ICreateOrderResponse {
|
export interface ICoupon {
|
||||||
code: number
|
id: number
|
||||||
orderSn: string // 订单号
|
couponId: number
|
||||||
msg?: string
|
canUse: number // 0-不可用 1-可用
|
||||||
|
canUseReason?: string
|
||||||
|
effectType: number // 0-永久有效
|
||||||
|
endTime?: string
|
||||||
|
couponEntity: ICouponEntity
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Google Pay SKU 信息接口
|
* 课程订单创建参数
|
||||||
*/
|
*/
|
||||||
export interface IGooglePaySku {
|
export interface ICourseOrderCreateParams {
|
||||||
productId: string
|
buyType: number // 0-商品页直接下单 1-购物车结算
|
||||||
type: string
|
userId: number
|
||||||
price: string
|
paymentMethod: number // 4-天医币
|
||||||
price_amount_micros: number
|
orderMoney: number // 订单金额
|
||||||
price_currency_code: string
|
realMoney: number // 实收金额
|
||||||
title: string
|
jfDeduction: number // 积分抵扣
|
||||||
description: string
|
couponId?: number // 优惠券ID
|
||||||
}
|
couponName?: string // 优惠券名称
|
||||||
|
vipDiscountAmount: number // VIP折扣金额
|
||||||
/**
|
districtMoney: number // 地区优惠金额
|
||||||
* Google Pay 支付结果接口
|
remark?: string // 备注
|
||||||
*/
|
productList: Array<{
|
||||||
export interface IGooglePayResult {
|
productId: number
|
||||||
code: number
|
quantity: number
|
||||||
data?: Array<{
|
|
||||||
original: {
|
|
||||||
purchaseToken: string
|
|
||||||
orderId: string
|
|
||||||
packageName: string
|
|
||||||
productId: string
|
|
||||||
purchaseTime: number
|
|
||||||
purchaseState: number
|
|
||||||
}
|
|
||||||
}>
|
}>
|
||||||
|
orderType: string // "order"
|
||||||
|
addressId: number // 0 for course products
|
||||||
|
appName: string // "wumen"
|
||||||
|
come: number // 2
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单初始化数据
|
||||||
|
*/
|
||||||
|
export interface IOrderInitData {
|
||||||
|
user: {
|
||||||
|
id: number
|
||||||
|
jf: number // 积分
|
||||||
|
peanutCoin: number // 天医币余额
|
||||||
|
vip?: number // VIP状态
|
||||||
|
}
|
||||||
|
is_course: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单路由参数
|
||||||
|
*/
|
||||||
|
export interface IOrderRouteParams {
|
||||||
|
goods: IOrderGoods[]
|
||||||
|
typeId: number
|
||||||
|
sourceType?: string
|
||||||
|
navTitle?: string
|
||||||
|
title?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 价格明细项
|
||||||
|
*/
|
||||||
|
export interface IPriceBreakdownItem {
|
||||||
|
type: number // 1-商品总价 2-运费 3-优惠券 4-积分 5-活动立减 6-VIP立减
|
||||||
|
text: string
|
||||||
|
imgUrl?: string
|
||||||
|
icon?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单状态
|
||||||
|
*/
|
||||||
|
export interface IOrderState {
|
||||||
|
orderData: IOrderRouteParams
|
||||||
|
goodsList: IOrderGoods[]
|
||||||
|
initData: IOrderInitData | null
|
||||||
|
totalPrice: number
|
||||||
|
vipPrice: number
|
||||||
|
districtAmount: number
|
||||||
|
actualPayment: number
|
||||||
|
jfNumber: number
|
||||||
|
jfNumberMax: number
|
||||||
|
jfNumberShow: string
|
||||||
|
couponList: ICoupon[]
|
||||||
|
selectedCoupon: ICoupon | null
|
||||||
|
showCouponPopup: boolean
|
||||||
|
remark: string
|
||||||
|
showRemarkPopup: boolean
|
||||||
|
payType: number
|
||||||
|
loading: boolean
|
||||||
|
submitting: boolean
|
||||||
|
buyingFlag: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const onPageBack = () => {
|
|||||||
/**
|
/**
|
||||||
* 拨打电话
|
* 拨打电话
|
||||||
*/
|
*/
|
||||||
export const makePhoneCall = (phoneNumber: string, title: string) => {
|
export const makePhoneCall = (phoneNumber: string, title: string = '') => {
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: title,
|
title: title,
|
||||||
content: phoneNumber,
|
content: phoneNumber,
|
||||||
|
|||||||
Reference in New Issue
Block a user