欢迎来到本期的博客!不好意思搁置太久了剩下的文章我的订单页面,是在想不到好看的页面了自己的奇思妙想哈哈哈虽然一点丑但是功能齐全!!! 如果有小伙伴有优化UI的思路可进行在仓库当中提PR
谢谢大家!
本篇将学习我的订单页面的搭建和订单页面的接口搭建比如购买课程页面下单了但是没有进行支付那么可以在我的订单页面进行再次支付
、也可进行取消订单
、退款订单
、订单超时系统主动取消订单
等知识点.快来学习吧~
💗 本次为前端知识点如果不懂前端可以去仓库直接copy出来使用,如果有什么问题可以在评论区留言,我会第一时间回复大家的.关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ 💗
作者: 杨不易呀 在此之前我已经更新了 13 章微信支付实战教程同学们感兴趣可前往我的腾讯云主页查看学习!
本次项目使用技术栈
后端: SpringBoot3.1.x、Mysql8.0、MybatisPlus
前端: Vue3、Vite、ElementPlus
小程序: Uniapp、UviewPlus、Vue3
桌面应用: Electron以慢著称,为什么桌面QQ却选择它做架构升级?跟着大厂玩(electron-egg)
可以看到我们的页面分为上下两块区域,上面区域我们已经在之前的文章当中完美实现直接拿来复用就完事了,下部分为一行 tabBar 作用为展示不同的状态订单.(还是使用 uview 的组件库即可实现 so easy to happy 切菜一样~)
可以看到我们有标志性的功能 订单倒计时 有标题、支付人、支付金额、下单时间、和下单的时候如果没有支付则在我的订单页面可以再次发起支付请求、还有用户取消订单业务.
好了我们已经分析的差不多了是不是很简单哈哈哈来我们直接开造!!!
在此之前请先把该启动启动好
在 yby6-uniApp-wechatPay-blog/pages
目录下创建 order 文件夹在创建 order.vue 页面
为了大家的方便我直接贴不重要的初始化页面代码,这些你们都看的懂咱们之前已经写过啦~
复制下面的代码到 order.vue 页面当中
<!-- yangbuyi Copyright (c) https://yby6.com 2023. -->
<script setup>
import { onLoad, onReady } from '@dcloudio/uni-app'
import { getCurrentInstance, ref } from "vue";
import Tabbar from "../tabbar/tabbar.vue";
// 获取当前实例
const { proxy } = getCurrentInstance()
// 加载层
const loading = ref(false)
// ==========================生命周期==========================
onLoad(() => {
console.log('onLoad');
});
onReady(() => {
console.log('onReady');
});
</script>
<template>
<view class="app-container">
<view class="container">
<!-- 上部分 -->
<view>
<u-notice-bar color="red" text="注意:小程序可查看有限只渲染近50条支付信息,完整请前往PC端!!!"></u-notice-bar>
<view class="PaymentChannel_title">
<u-tooltip text="PC端微信支付系统: https://lzys522.cn/wx" copyText="https://lzys522.cn/wx"
overlay></u-tooltip>
</view>
<view class="PaymentChannel_title">
<u-tooltip text="注意:0.4以上,支付成功后可在订单列表进行退款."
copyText="注意:0.4以上,支付成功后可在订单列表进行退款."
overlay></u-tooltip>
</view>
<view class="PaymentChannel_title"
style="color: red; margin-bottom: 10px;font-size: 14px;height: auto !important;">
<u-tooltip text="开源仓库: https://gitee.com/yangbuyi/wxDemo" copyText="https://gitee.com/yangbuyi/wxDemo"
overlay></u-tooltip>
</view>
</view>
<!-- 下部分 -->
<view>
</view>
<!-- 加载层 -->
<u-loading-page :loading="loading"/>
<!-- 菜单 -->
<tabbar selected="1"></tabbar>
</view>
</view>
</template>
<style lang="scss" scoped>
::v-deep .u-cell__body__content {
width: 70%;
}
.btn {
margin-left: 6px;
display: inline-block;
}
.payView {
/*float:right*/
display: inline-block;
text-align: right;
vertical-align: baseline;
float: right;
}
.time {
@include flex;
align-items: center;
&__custom {
margin-top: 4px;
width: 22px;
height: 22px;
background-color: $u-primary;
border-radius: 4px;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
&__item {
color: #fff;
font-size: 12px;
text-align: center;
}
}
&__doc {
color: $u-primary;
padding: 0px 4px;
}
&__item {
color: #606266;
font-size: 15px;
margin-right: 4px;
}
}
</style>
修改 📎pages.json
在 pages
数组当中新增
{
"path": "pages/order/order",
"style": {
"navigationBarTitleText": ""
}
},
在 list
数组当中新增
{
"pagePath": "pages/order/order"
},
完美、接下来我们进行编写 tabars 状态滑块按钮
打开组件库 UviewPlus 注意我们是 vue3 所以是 3.x 版本
地址: https://uiadmin.net/uview-plus/components/tabs.html
随便选择你自己喜欢的直接复制对应代码即可~
// ==========================数据==========================
const tabList = ref([
{ name: "全部" },
{ name: "未支付" },
{ name: "退款中" },
{ name: "已退款" },
{ name: "支付成功" },
{ name: "超时关闭" },
{ name: "用户取消" }
]);
<u-tabs
:list="tabList"
lineWidth="30"
lineColor="#ffb9b9"
:activeStyle="{
color: '#FF8B8B',
fontWeight: 'bold',
transform: 'scale(1.06)',
}"
:inactiveStyle="{
color: '#303133',
transform: 'scale(1)'
}"
itemStyle="padding-left: 15px; padding-right: 15px; height: 34px;margin-bottom: 2px;"
>
</u-tabs>
我感觉还不错 hahah ~
同学们自己手动敲一遍吧冲冲
逻辑: 当我们切换状态的时候要去后端请求不同状态的数据并且渲染到小程序当中
地址: https://uiadmin.net/uview-plus/components/list.html
是不是感觉到了和我们页面的不一样,因为我自定义的呀,要不然为什么这么丑~
方法代码
// 底部触发
const scrolltolower = (data) => {
console.log(data);
};
// 模拟数据
const loadmore = () => {
for (let i = 0; i < 10; i++) {
indexList.value.push({
url: urls[2],
});
}
};
生命周期加载模拟数据
onLoad(() => {
loadmore();
console.log('onLoad');
});
页面代码
<u-list
@scrolltolower="scrolltolower"
>
<u-list-item
v-for="(item, index) in indexList"
:key="index"
>
<u-cell>
<template #title>
<view>
我是标题
</view>
<template #label>
<view>
我是子标题
</view>
</template>
</template>
</u-cell>
</u-list-item>
</u-list>
好的目前我们就已经搭建好了一个雏形,我们继续完善给他把标题、支付人、下单时间等进行编写,搞定后我们将要去编写后端代码接口请求列表数据.
需要的接口为我的订单列表分页接口,还记得我上次编写前端 PC 我的订单的时候写了一个么,我们还需要编写一个小程序端的因为我这里就只是允许展示前五十条信息~ 其余的可以通过查询条件来查哦~
打开后端代码修改 OrderInfoController.java 页面
同学们手动写一下把,新增 orderUniAppPage 接口
👌可以正常调用成功
在 api
目录下创建 orderInfo.js 文件
// yangbuyi Copyright (c) https://yby6.com 2023.
import request from '@/utils/request'
export default {
// 查询订单列表
orderUniAppPage(data) {
return request({
url: '/api/orderInfo/orderUniAppPage',
method: 'get',
params: data
})
}
}
这部分很简单我就直接把代码贴上来啦(简单且麻烦)
<u-list-item
v-for="(item, index) in orderList" :key="index">
<u-cell>
<template #title>
<view>
<view>
<view style="display: inline-block">
<u-tag :text="item.title"></u-tag>
</view>
<view class="payView">
<view>
<u-tag :text="item.orderStatus" v-if="item.orderStatus === '未支付'"></u-tag>
<u-tag :text="item.orderStatus" v-if="item.orderStatus === '支付成功'" type="success"></u-tag>
<u-tag :text="item.orderStatus" v-if="item.orderStatus === '超时已关闭'" type="warning"></u-tag>
<u-tag :text="item.orderStatus" v-if="item.orderStatus === '用户已取消'" type="info"></u-tag>
<u-tag :text="item.orderStatus" v-if="item.orderStatus === '退款中'" type="danger"></u-tag>
<u-tag :text="item.orderStatus" v-if="item.orderStatus === '已退款'" type="info"></u-tag>
</view>
</view>
<view style="margin-top: 5px;">
订单支付人: {{ item.title.split('-')[1] ? item.title.split('-')[1] : 'PC用户' }}
</view>
</view>
</view>
<template #label>
<view style="float:left;">
<view style="text-align: left;">
订单金额:{{ item.totalFee / 100 }} 元
</view>
<view style="text-align: left;">
<view style="display: inline-block;">
下单时间: {{ item.createTime }}
</view>
</view>
</view>
<view style="float:right;margin-top: 5px;">
<view class="btn" v-if="item.orderStatus === '支付成功'">
<u-button size="small" type="primary"
text="退款"></u-button>
</view>
<view class="btn" v-if="item.orderStatus === '未支付'">
<u-button size="small" type="primary" :disabled="payBtnDisabled"
text="支付"></u-button>
</view>
<view class="btn" v-if="item.orderStatus === '未支付'">
<u-button size="small" type="error"
text="取消"></u-button>
</view>
</view>
</template>
</template>
</u-cell>
</u-list-item>
接下来就是对订单的操作了,待完成的有 支付按钮、取消按钮、退款按钮、倒计时超时取消订单 写了我三个小时如果有帮助到您麻烦点个赞~谢谢💗
用于在 '购买课程页面'进行了下单但是未支付的情况,这时候千万查看我的订单那么应该可以继续支付订单,降低了后端的成本和订单下单量重复的问题.
用于在用户还未支付,用户不想要了那么会主观的主动的进行去取消订单,不想买了.
顾名思义用于用户在支付订单后(还未发货等一些情况)可进行申请退款操作
这个的话就是我们系统完全需要的功能,如果用户在某个时间下单,下单完毕后我们不可能一直存在这个订单我们需要有个时间效益来进行限制这个订单的过期,那么一般电商的时间都是设置了 15 分钟倒计时系统主动发起超时订单取消接口.
以上 支付接口、取消订单接口、退款接口 我们已经在往期从零玩转完毕! 有同学如果需要的可前往查看.
还记得我们上面写了三个按钮方法吗
它对应三个功能: 支付、取消、退款 接下来我们进行完善它!!!!
我们进行编写三个函数方法来进行点击看看效果
// 用户主动取消订单
const cancelOrder = (obj) => {
console.log(obj);
}
// 用户断点支付
const toPay = (obj) => {
console.log(obj);
}
// 用户主动退款
const refund = (obj) => {
console.log(obj);
}
点击任意按钮会输出当前点击的对象(也就是后台的一条记录)信息
创建一条未支付订单
前往我的订单点击未支付状态查询
修改 weChatPay.js
新增取消订单接口 注意自己的后端接口是否是这个哦~
// 取消订单
export function cancel(orderNo) {
return request({
url: '/api/wx-pay/native/cancel/' + orderNo,
method: 'post'
})
}
toast("订单取消成功"); 是我们上次封装的提示框
建议同学们自己手动敲一遍~
// 用户主动取消订单
const cancelOrder = (obj) => {
console.log(obj);
loading.value = true;
cancel(obj.orderNo).then((res) => {
toast("订单取消成功");
// 刷新列表
loadmore();
});
}
可以看到我们发起取消订单接口成功并且提示了我们还刷新了列表
用于在 '购买课程页面'进行了下单但是未支付的情况,这时候千万查看我的订单那么应该可以继续支付订单,降低了后端的成本和订单下单量重复的问题.
下单接口在前面我们已经编写过前后端都写过所以现在接入很简单
修改 weCharPay.js
新增下单接口(如果已经存在则无视)
// 统一JSAPI下单
export function JSAPI(productId, openId) {
return request({
'url': `/api/wx-pay/js-api/${ productId }`,
'method': 'post',
'params': {
"openId": openId
}
})
}
创建一条未支付订单
修改 toPay
函数 直接将购买界面的支付代码 copy 过来即可哈哈哈
逻辑: 为了安全怕绕过登录直接进行支付,那么这里进行判断一下是否登录
建议同学们手动敲打一下
// 用户断点支付
const toPay = (obj) => {
console.log(obj);
const storageSync = uni.getStorageSync('token');
const nickName = uni.getStorageSync('nickName');
payBtnDisabled.value = true;
if (!storageSync || !nickName) {
payBtnDisabled.value = false;
toast("还未登录欸!");
return;
}
JSAPI(obj.productId, storageSync + "|" + nickName)
.then((res) => {
const wx = res.data;
toast("创建订单成功正在拉起支付请稍等....");
uni.requestPayment({
provide: 'wxpay',
timeStamp: wx.timeStamp,
nonceStr: wx.nonceStr,
package: wx.package,
signType: wx.signType,
paySign: wx.paySign,
success: (res) => {
console.log(res);
payBtnDisabled.value = false;
},
fail: (res) => {
console.log(res);
toast("取消支付可继续点击支付重新发起");
payBtnDisabled.value = false;
},
});
})
.catch((err) => {
console.log(err);
payBtnDisabled.value = false;
});
}
查看后端检查看看是否重新创建了订单 显然没有重新创建我们是进行判断了的
查看效果
前往 uviewplus 组件库找到我们的 modal 弹出层
地址: https://uiadmin.net/uview-plus/components/modal.html
新增变量
// 退款弹出
const refundDialogVisible = ref(false);
// 退款表单
const refundForm = ref({
orderNo: '',
refundNo: '',
reason: '',
});
// 退款表单验证规则
const rules = ref({
'refundNo': {
type: 'number',
required: true,
max: 4,
message: '请填写后四位交易订单号(数字)',
trigger: [ 'blur', 'change' ]
},
'reason': {
type: 'string',
required: true,
message: '请填写退款原因',
trigger: [ 'blur', 'change' ]
},
})
思路在弹出层当中嵌入 form 表单
<!-- 弹出层退款 -->
<u-modal
:loading="loading"
title="申请退款"
:show="refundDialogVisible"
showCancelButton
@confirm="refundOrder"
@cancel="closeDialog "
>
<view>
<!-- 注意,如果需要兼容微信小程序,最好通过setRules方法设置rules规则 -->
<u-form
labelPosition="left"
:model="refundForm"
:rules="rules"
ref="uForm"
>
<u-form-item
labelWidth="100px"
label="交易订单号"
prop="refundNo"
borderBottom
ref="item1"
>
<u-input
v-model="refundForm.refundNo"
border="none"
></u-input>
</u-form-item>
<u-form-item
labelWidth="100px"
label="退款原因"
prop="reason"
borderBottom
ref="item2"
>
<u-input
v-model="refundForm.reason"
border="none"
></u-input>
</u-form-item>
</u-form>
</view>
</u-modal>
//关闭退款对话框
const closeDialog = () => {
console.log('close.................');
refundDialogVisible.value = false;
refundForm.value = {
orderNo: '',
refundNo: '',
reason: '',
};
refundSubmitBtnDisabled.value = false;
};
用于用户不行进行退款了的情况
后端接口我们在之前的 PC 系列 文章已经编写和讲解过我们看看需要传递什么
修改 weChatPay.js
新增退款接口
// 申请退款
export function refunds(orderNo, reason, refundNo) {
return request({
url: '/api/wx-pay/native/refunds/' + orderNo + '/' + refundNo + "/" + reason,
method: 'post'
})
}
编写发起退款请求函数
先进行看看退款请求按钮是否是禁用状态 禁用则不允许提交请求
开启我们的组件库表单的非空校验并且限制最大输入的订单号为 4 位因为后端我们进行了单独的处理
创建一个订单进行支付成功
记住我们这次的交易订单号后四位 我这里是 3070
直接找到我们刚刚支付的订单
本章节文章相当于已经完结 《从零玩转系列之微信支付》在我准备开启这篇教程我当时是感受支付的乐趣并且感觉官方文档有些麻烦自此萌生出写一篇从零玩转的微信支付可能会有同学觉得简单,调用API嘛但是努力写文章可以帮助到需要的人那么这件事情就不简单啦~ 完结 🎆
本期结束咱们下次再见👋~
🌊 关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ 💗
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。