增加分销充值功能
This commit is contained in:
35
http/api/market/distributionFlow.js
Normal file
35
http/api/market/distributionFlow.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
const urlType='market'
|
||||||
|
|
||||||
|
export function distributionFlow(data) {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/distribution/distributionFlow`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function openFlow(data) {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/distribution/openFlow`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function flow(data) {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/distribution/flow`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
490
pageDistributionFlow/charge.vue
Normal file
490
pageDistributionFlow/charge.vue
Normal file
@@ -0,0 +1,490 @@
|
|||||||
|
<template>
|
||||||
|
<view class="box">
|
||||||
|
<up-navbar
|
||||||
|
title="分销"
|
||||||
|
bg-color="transparent"
|
||||||
|
:placeholder="true"
|
||||||
|
@leftClick="back"
|
||||||
|
></up-navbar>
|
||||||
|
<view class="top">
|
||||||
|
<image
|
||||||
|
src="/static/market/top-bg.png"
|
||||||
|
class="image"
|
||||||
|
mode="widthFix"
|
||||||
|
></image>
|
||||||
|
</view>
|
||||||
|
<view style="height: 38rpx"></view>
|
||||||
|
<view class="chrage-box">
|
||||||
|
<view class="u-flex u-flex-between">
|
||||||
|
<view class="u-flex">
|
||||||
|
<image
|
||||||
|
src="/static/market/gold.png"
|
||||||
|
style="width: 44rpx; height: 44rpx"
|
||||||
|
></image>
|
||||||
|
<view class="title-bg">
|
||||||
|
<image src="/static/market/title-bg.png" class="image"></image>
|
||||||
|
<view class="font-bold u-font-32 color-333 u-m-l-24">立即充值</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<text class="u-font-24 color-999"> 充值代表接受</text>
|
||||||
|
<text class="u-font-24 xieyi"> 《用户隐私协议》 </text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="list u-m-t-32 u-flex u-m-t-60"
|
||||||
|
style="align-items: flex-start"
|
||||||
|
>
|
||||||
|
<text class="font-bold u-font-32 color-333 u-text-nowrap"
|
||||||
|
>选择金额</text
|
||||||
|
>
|
||||||
|
<view class="u-m-l-60 chargeList">
|
||||||
|
<view
|
||||||
|
class="item"
|
||||||
|
v-for="(item, index) in chargeList"
|
||||||
|
:key="index"
|
||||||
|
:class="{ active: selChargeIndex == index }"
|
||||||
|
@click="changeCharge(index)"
|
||||||
|
>
|
||||||
|
<view class="price">
|
||||||
|
<text class="u-font-28">¥ </text>
|
||||||
|
<text class="font-bold" style="font-size: 48rpx">{{
|
||||||
|
item.price
|
||||||
|
}}</text>
|
||||||
|
</view>
|
||||||
|
<image
|
||||||
|
class="sel"
|
||||||
|
v-show="selChargeIndex == index"
|
||||||
|
src="/static/market/sel.png"
|
||||||
|
></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="u-flex input-box u-m-t-30">
|
||||||
|
<text class="color-333 u-font-28 font-700">其他金额</text>
|
||||||
|
<view class="u-flex-1 u-flex u-m-l-28">
|
||||||
|
<input
|
||||||
|
:min="0.01"
|
||||||
|
placeholder-class="u-font-24"
|
||||||
|
type="digit"
|
||||||
|
class="u-flex-1 u-font-28"
|
||||||
|
placeholder="请输入充值金额"
|
||||||
|
@input="inputEvent"
|
||||||
|
v-model="price"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="buy" @click="buy">立即充值</view>
|
||||||
|
|
||||||
|
<view class="u-flex u-flex-between u-m-t-60">
|
||||||
|
<view class="u-flex">
|
||||||
|
<view class="title-bg">
|
||||||
|
<image src="/static/market/title-bg.png" class="image"></image>
|
||||||
|
<view class="font-bold u-font-32 color-333 u-m-l-24">充值记录</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<text class="u-font-28 color-333">
|
||||||
|
总计:{{ state.totalRecharge || 0 }}元</text
|
||||||
|
>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="recoders-list" v-if="state.records.length">
|
||||||
|
<view class="item" v-for="(item, index) in state.records" :key="index">
|
||||||
|
<view class="u-flex u-flex-between">
|
||||||
|
<view class="u-font-28">
|
||||||
|
<view class="color-666">
|
||||||
|
<text v-if="item.type === 'self_recharge'">自助充值</text>
|
||||||
|
<text v-if="item.type === 'manual_recharge'">手动充值</text>
|
||||||
|
</view>
|
||||||
|
<view class="u-m-t-16">
|
||||||
|
<text class="color-666">时间:</text>
|
||||||
|
<text class="color-333">{{ item.createTime }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="price">
|
||||||
|
<text>{{ item.changeAmount }}</text>
|
||||||
|
<text class="yuan">元</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<up-loadmore :status="isEnd ? 'nomore' : 'loadmore'"></up-loadmore>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { mchRecharge } from "@/http/api/pay";
|
||||||
|
import * as distributionFlowApi from "@/http/api/market/distributionFlow.js";
|
||||||
|
import { onMounted, ref, reactive, watch } from "vue";
|
||||||
|
import { onLoad, onReachBottom } from "@dcloudio/uni-app";
|
||||||
|
function back() {
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
|
const options = ref({});
|
||||||
|
|
||||||
|
const price = ref("");
|
||||||
|
|
||||||
|
const chargeList = ref([
|
||||||
|
{ price: "50.00" },
|
||||||
|
{ price: "800.00" },
|
||||||
|
{ price: "1000.00" },
|
||||||
|
{ price: "2000.00" },
|
||||||
|
]);
|
||||||
|
const selChargeIndex = ref(0);
|
||||||
|
function changeCharge(index) {
|
||||||
|
selChargeIndex.value = index;
|
||||||
|
}
|
||||||
|
function parseQueryString(queryString) {
|
||||||
|
const queryParams = queryString.split("&").map((param) => param.split("="));
|
||||||
|
const params = {};
|
||||||
|
for (const [key, value] of queryParams) {
|
||||||
|
params[key] = value;
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
onLoad((opt) => {
|
||||||
|
console.log(opt);
|
||||||
|
if (opt.q) {
|
||||||
|
const q = decodeURIComponent(opt.q);
|
||||||
|
const params = parseQueryString(q.split("?")[1]);
|
||||||
|
Object.assign(options.value, params);
|
||||||
|
} else {
|
||||||
|
Object.assign(options.value, opt);
|
||||||
|
}
|
||||||
|
console.log(options.value);
|
||||||
|
if (options.value.shopId) {
|
||||||
|
price.value= options.value.amount
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
flow();
|
||||||
|
});
|
||||||
|
|
||||||
|
let timer = null;
|
||||||
|
|
||||||
|
function inputEvent(e) {
|
||||||
|
console.log(e);
|
||||||
|
clearTimeout(timer);
|
||||||
|
|
||||||
|
let value = e.detail.value;
|
||||||
|
selChargeIndex.value = -1;
|
||||||
|
// 1. 只保留数字和小数点,过滤其他所有字符
|
||||||
|
value = value.replace(/[^\d.]/g, "");
|
||||||
|
|
||||||
|
// 2. 处理多个小数点(只保留第一个)
|
||||||
|
const dotIndex = value.indexOf(".");
|
||||||
|
if (dotIndex !== -1) {
|
||||||
|
// 从第二个小数点开始,移除后续所有小数点
|
||||||
|
value =
|
||||||
|
value.slice(0, dotIndex + 1) +
|
||||||
|
value.slice(dotIndex + 1).replace(/\./g, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 限制小数位最多两位
|
||||||
|
if (dotIndex !== -1 && value.length > dotIndex + 3) {
|
||||||
|
value = value.slice(0, dotIndex + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 处理特殊情况:避免以多个0开头(如"000123" -> "0123"不合法,应改为"123")
|
||||||
|
// 但允许"0.12"这类合法格式
|
||||||
|
if (value.startsWith("0") && value.length > 1 && !value.startsWith("0.")) {
|
||||||
|
value = value.replace(/^0+/, "0"); // 多个0开头时只保留一个0
|
||||||
|
// 如果是"000"则清空(根据需求调整,也可保留为"0")
|
||||||
|
if (value === "0" && !value.includes(".")) {
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 延迟更新,避免输入闪烁
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
price.value = value;
|
||||||
|
}, 30);
|
||||||
|
}
|
||||||
|
function wxlogin() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.login({
|
||||||
|
success: (res) => {
|
||||||
|
if (res.code) {
|
||||||
|
resolve(res.code);
|
||||||
|
} else {
|
||||||
|
reject(res.errMsg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
reject(err.errMsg);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const pay = (res) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.requestPayment({
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
provider: "wxpay", //支付类型-固定值
|
||||||
|
partnerid: res.appId, // 微信支付商户号
|
||||||
|
timeStamp: res.timeStamp, // 时间戳(单位:秒)
|
||||||
|
nonceStr: res.nonceStr, // 随机字符串
|
||||||
|
package: res.package, // 固定值
|
||||||
|
signType: res.signType, //固定值
|
||||||
|
paySign: res.paySign, //签名
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-ALIPAY
|
||||||
|
provider: "alipay", //支付类型-固定值
|
||||||
|
orderInfo: res.tradeNo, // 微信支付商户号
|
||||||
|
// #endif
|
||||||
|
success: (res) => {
|
||||||
|
console.log("pay");
|
||||||
|
console.log(res);
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
uni.showToast({
|
||||||
|
title: "支付成功",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
console.log("支付成功");
|
||||||
|
resolve(true);
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-ALIPAY
|
||||||
|
if (res.resultCode == "9000") {
|
||||||
|
uni.showToast({
|
||||||
|
title: "支付成功",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
resolve(true);
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: "支付失败",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
reject(false);
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
fail: (res) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading();
|
||||||
|
}, 1000);
|
||||||
|
reject(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
async function buy() {
|
||||||
|
if (price.value <= 0) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "金额不能小于0",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const code = await wxlogin();
|
||||||
|
const shopInfo = uni.getStorageSync("shopInfo");
|
||||||
|
const res = await mchRecharge({
|
||||||
|
amount: price.value,
|
||||||
|
shopId: shopInfo.id,
|
||||||
|
code,
|
||||||
|
payType: options.value.payType || "wechatPay",
|
||||||
|
});
|
||||||
|
if (res) {
|
||||||
|
const paySuccess = await pay(res);
|
||||||
|
if (paySuccess) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "支付成功",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh() {
|
||||||
|
query.page = 1;
|
||||||
|
flow();
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = reactive({
|
||||||
|
page: 1,
|
||||||
|
size: 10,
|
||||||
|
type:'self_recharge,manual_recharge'
|
||||||
|
});
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
records: [],
|
||||||
|
totalRecharge: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const isEnd = ref(false);
|
||||||
|
async function flow() {
|
||||||
|
const res = await distributionFlowApi.flow(query);
|
||||||
|
if (query.page == 1) {
|
||||||
|
Object.assign(state, res);
|
||||||
|
} else {
|
||||||
|
state.records = state.records.concat(res.records || []);
|
||||||
|
state.totalRecharge = res.totalRecharge || 0;
|
||||||
|
}
|
||||||
|
isEnd.value = query.page >= res.totalPage * 1;
|
||||||
|
}
|
||||||
|
onReachBottom(() => {
|
||||||
|
if (isEnd.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
query.page++;
|
||||||
|
flow();
|
||||||
|
});
|
||||||
|
async function init() {
|
||||||
|
const code = await wxlogin();
|
||||||
|
const res = await mchRecharge({
|
||||||
|
...options.value,
|
||||||
|
code,
|
||||||
|
payType: options.value.payType || "wechatPay",
|
||||||
|
});
|
||||||
|
if (res) {
|
||||||
|
const paySuccess = await pay(res);
|
||||||
|
if (paySuccess) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "支付成功",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(res);
|
||||||
|
}
|
||||||
|
watch(
|
||||||
|
() => selChargeIndex.value,
|
||||||
|
(newval) => {
|
||||||
|
if (newval != -1) {
|
||||||
|
price.value = chargeList.value[newval].price;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.box {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.top {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: -1;
|
||||||
|
.image {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chrage-box {
|
||||||
|
width: 750rpx;
|
||||||
|
border-radius: 74rpx;
|
||||||
|
background: #ffffff4d;
|
||||||
|
padding: 42rpx 28rpx;
|
||||||
|
}
|
||||||
|
.title-bg {
|
||||||
|
position: relative;
|
||||||
|
.image {
|
||||||
|
position: absolute;
|
||||||
|
height: 14rpx;
|
||||||
|
width: 94rpx;
|
||||||
|
right: -10rpx;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.xieyi {
|
||||||
|
color: #ecb592;
|
||||||
|
}
|
||||||
|
.chargeList {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-left: 68rpx;
|
||||||
|
justify-content: space-between;
|
||||||
|
.item {
|
||||||
|
padding: 16rpx 36rpx;
|
||||||
|
border-radius: 22rpx;
|
||||||
|
background: linear-gradient(180deg, #f5f5f5 58.54%, #fff 104.47%);
|
||||||
|
border: 6rpx solid transparent;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
margin-right: 30rpx;
|
||||||
|
margin-bottom: 62rpx;
|
||||||
|
position: relative;
|
||||||
|
width: 220rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
&.active {
|
||||||
|
border: 6rpx solid #fe6c0e;
|
||||||
|
background: linear-gradient(180deg, #ffc29a -26.17%, #fff 64.06%);
|
||||||
|
box-shadow: 0 0 31.2rpx 2rpx #fe8b435e;
|
||||||
|
.price {
|
||||||
|
.font-bold {
|
||||||
|
color: #ff6300;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sel {
|
||||||
|
width: 42rpx;
|
||||||
|
height: 42rpx;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
bottom: -22rpx;
|
||||||
|
}
|
||||||
|
.price {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
color: #5f2e0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.item:nth-of-type(2n) {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.u-text-nowrap {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.input-box {
|
||||||
|
padding: 24rpx 16rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
background: #f6f6f6;
|
||||||
|
}
|
||||||
|
.buy {
|
||||||
|
padding: 32rpx 32rpx;
|
||||||
|
background: linear-gradient(98deg, #fe6d1100 40.64%, #ffd1b4 105.2%),
|
||||||
|
linear-gradient(259deg, #fe6d11 50.14%, #ffd1b4 114.93%);
|
||||||
|
box-shadow: 0 14rpx 30.4rpx 0 #fe8b435e;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 48rpx;
|
||||||
|
}
|
||||||
|
.recoders-list {
|
||||||
|
margin-top: 40rpx;
|
||||||
|
.item {
|
||||||
|
margin-bottom: 36rpx;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
padding: 32rpx 28rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
.price {
|
||||||
|
line-height: 44rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #fe7e00;
|
||||||
|
font-size: 48rpx;
|
||||||
|
.yuan {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
15
pages.json
15
pages.json
@@ -98,7 +98,8 @@
|
|||||||
"pageId": "PAGES_PAY",
|
"pageId": "PAGES_PAY",
|
||||||
"style" :
|
"style" :
|
||||||
{
|
{
|
||||||
"navigationBarTitleText" : "支付"
|
"navigationBarTitleText" : "分销",
|
||||||
|
"navigationStyle" : "custom"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -629,7 +630,17 @@
|
|||||||
"navigationBarTitleText": "消费返现"
|
"navigationBarTitleText": "消费返现"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"root": "pageDistributionFlow",
|
||||||
|
"pages": [{
|
||||||
|
"pageId": "PAGES_DISTRIBUTION_FLOW_CHARGE",
|
||||||
|
"path": "charge",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "分销"
|
||||||
|
}
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,6 +78,12 @@
|
|||||||
icon: '/static/indexImg/icon-order.svg',
|
icon: '/static/indexImg/icon-order.svg',
|
||||||
pageUrl: 'PAGES_MARKET_CONSUME_CASHBACK'
|
pageUrl: 'PAGES_MARKET_CONSUME_CASHBACK'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '分销',
|
||||||
|
icon: '/static/indexImg/icon-order.svg',
|
||||||
|
pageUrl: 'PAGES_PAY'
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
console.log(menusStore.adminPages);
|
console.log(menusStore.adminPages);
|
||||||
|
|||||||
389
pages/pay.vue
389
pages/pay.vue
@@ -1,13 +1,142 @@
|
|||||||
<template>
|
<template>
|
||||||
<view> </view>
|
<view class="box">
|
||||||
|
<up-navbar
|
||||||
|
title="分销"
|
||||||
|
bg-color="transparent"
|
||||||
|
:placeholder="true"
|
||||||
|
@leftClick="back"
|
||||||
|
></up-navbar>
|
||||||
|
<view class="top">
|
||||||
|
<image
|
||||||
|
src="/static/market/top-bg.png"
|
||||||
|
class="image"
|
||||||
|
mode="widthFix"
|
||||||
|
></image>
|
||||||
|
</view>
|
||||||
|
<view style="height: 38rpx"></view>
|
||||||
|
<view class="chrage-box">
|
||||||
|
<view class="u-flex u-flex-between">
|
||||||
|
<view class="u-flex">
|
||||||
|
<image
|
||||||
|
src="/static/market/gold.png"
|
||||||
|
style="width: 44rpx; height: 44rpx"
|
||||||
|
></image>
|
||||||
|
<view class="title-bg">
|
||||||
|
<image src="/static/market/title-bg.png" class="image"></image>
|
||||||
|
<view class="font-bold u-font-32 color-333 u-m-l-24">立即充值</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<text class="u-font-24 color-999"> 充值代表接受</text>
|
||||||
|
<text class="u-font-24 xieyi"> 《用户隐私协议》 </text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="list u-m-t-32 u-flex u-m-t-60"
|
||||||
|
style="align-items: flex-start"
|
||||||
|
>
|
||||||
|
<text class="font-bold u-font-32 color-333 u-text-nowrap"
|
||||||
|
>选择金额</text
|
||||||
|
>
|
||||||
|
<view class="u-m-l-60 chargeList">
|
||||||
|
<view
|
||||||
|
class="item"
|
||||||
|
v-for="(item, index) in chargeList"
|
||||||
|
:key="index"
|
||||||
|
:class="{ active: selChargeIndex == index }"
|
||||||
|
@click="changeCharge(index)"
|
||||||
|
>
|
||||||
|
<view class="price">
|
||||||
|
<text class="u-font-28">¥ </text>
|
||||||
|
<text class="font-bold" style="font-size: 48rpx">{{
|
||||||
|
item.price
|
||||||
|
}}</text>
|
||||||
|
</view>
|
||||||
|
<image
|
||||||
|
class="sel"
|
||||||
|
v-show="selChargeIndex == index"
|
||||||
|
src="/static/market/sel.png"
|
||||||
|
></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="u-flex input-box u-m-t-30">
|
||||||
|
<text class="color-333 u-font-28 font-700">其他金额</text>
|
||||||
|
<view class="u-flex-1 u-flex u-m-l-28">
|
||||||
|
<input
|
||||||
|
:min="0.01"
|
||||||
|
placeholder-class="u-font-24"
|
||||||
|
type="digit"
|
||||||
|
class="u-flex-1 u-font-28"
|
||||||
|
placeholder="请输入充值金额"
|
||||||
|
@input="inputEvent"
|
||||||
|
v-model="price"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="buy" @click="buy">立即充值</view>
|
||||||
|
|
||||||
|
<view class="u-flex u-flex-between u-m-t-60">
|
||||||
|
<view class="u-flex">
|
||||||
|
<view class="title-bg">
|
||||||
|
<image src="/static/market/title-bg.png" class="image"></image>
|
||||||
|
<view class="font-bold u-font-32 color-333 u-m-l-24">充值记录</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<text class="u-font-28 color-333">
|
||||||
|
总计:{{ state.totalRecharge || 0 }}元</text
|
||||||
|
>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="recoders-list" v-if="state.records.length">
|
||||||
|
<view class="item" v-for="(item, index) in state.records" :key="index">
|
||||||
|
<view class="u-flex u-flex-between">
|
||||||
|
<view class="u-font-28">
|
||||||
|
<view class="color-666">
|
||||||
|
<text v-if="item.type === 'self_recharge'">自助充值</text>
|
||||||
|
<text v-if="item.type === 'manual_recharge'">手动充值</text>
|
||||||
|
</view>
|
||||||
|
<view class="u-m-t-16">
|
||||||
|
<text class="color-666">时间:</text>
|
||||||
|
<text class="color-333">{{ item.createTime }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="price">
|
||||||
|
<text>{{ item.changeAmount }}</text>
|
||||||
|
<text class="yuan">元</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<up-loadmore :status="isEnd ? 'nomore' : 'loadmore'"></up-loadmore>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { mchRecharge } from "@/http/api/pay";
|
import { mchRecharge } from "@/http/api/pay";
|
||||||
import { onMounted, ref, reactive } from "vue";
|
import * as distributionFlowApi from "@/http/api/market/distributionFlow.js";
|
||||||
import { onLoad } from "@dcloudio/uni-app";
|
import { onMounted, ref, reactive, watch } from "vue";
|
||||||
|
import { onLoad, onReachBottom } from "@dcloudio/uni-app";
|
||||||
|
function back() {
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
const options = ref({});
|
const options = ref({});
|
||||||
|
|
||||||
|
const price = ref("");
|
||||||
|
|
||||||
|
const chargeList = ref([
|
||||||
|
{ price: "500.00" },
|
||||||
|
{ price: "800.00" },
|
||||||
|
{ price: "1000.00" },
|
||||||
|
{ price: "2000.00" },
|
||||||
|
]);
|
||||||
|
const selChargeIndex = ref(0);
|
||||||
|
function changeCharge(index) {
|
||||||
|
selChargeIndex.value = index;
|
||||||
|
}
|
||||||
function parseQueryString(queryString) {
|
function parseQueryString(queryString) {
|
||||||
const queryParams = queryString.split("&").map((param) => param.split("="));
|
const queryParams = queryString.split("&").map((param) => param.split("="));
|
||||||
const params = {};
|
const params = {};
|
||||||
@@ -26,9 +155,58 @@ onLoad((opt) => {
|
|||||||
Object.assign(options.value, opt);
|
Object.assign(options.value, opt);
|
||||||
}
|
}
|
||||||
console.log(options.value);
|
console.log(options.value);
|
||||||
init();
|
if (options.value.shopId) {
|
||||||
|
price.value = options.value.amount;
|
||||||
|
selChargeIndex.value = chargeList.value.findIndex(
|
||||||
|
(item) => item.price*1 === options.value.amount*1
|
||||||
|
);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
flow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let timer = null;
|
||||||
|
|
||||||
|
function inputEvent(e) {
|
||||||
|
console.log(e);
|
||||||
|
clearTimeout(timer);
|
||||||
|
|
||||||
|
let value = e.detail.value;
|
||||||
|
// 1. 只保留数字和小数点,过滤其他所有字符
|
||||||
|
value = value.replace(/[^\d.]/g, "");
|
||||||
|
|
||||||
|
// 2. 处理多个小数点(只保留第一个)
|
||||||
|
const dotIndex = value.indexOf(".");
|
||||||
|
if (dotIndex !== -1) {
|
||||||
|
// 从第二个小数点开始,移除后续所有小数点
|
||||||
|
value =
|
||||||
|
value.slice(0, dotIndex + 1) +
|
||||||
|
value.slice(dotIndex + 1).replace(/\./g, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 限制小数位最多两位
|
||||||
|
if (dotIndex !== -1 && value.length > dotIndex + 3) {
|
||||||
|
value = value.slice(0, dotIndex + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 处理特殊情况:避免以多个0开头(如"000123" -> "0123"不合法,应改为"123")
|
||||||
|
// 但允许"0.12"这类合法格式
|
||||||
|
if (value.startsWith("0") && value.length > 1 && !value.startsWith("0.")) {
|
||||||
|
value = value.replace(/^0+/, "0"); // 多个0开头时只保留一个0
|
||||||
|
// 如果是"000"则清空(根据需求调整,也可保留为"0")
|
||||||
|
if (value === "0" && !value.includes(".")) {
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 延迟更新,避免输入闪烁
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
selChargeIndex.value = chargeList.value.findIndex(
|
||||||
|
(item) => item.price*1 === value*1
|
||||||
|
);
|
||||||
|
price.value = value;
|
||||||
|
}, 30);
|
||||||
|
}
|
||||||
function wxlogin() {
|
function wxlogin() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
uni.login({
|
uni.login({
|
||||||
@@ -48,7 +226,6 @@ function wxlogin() {
|
|||||||
|
|
||||||
const pay = (res) => {
|
const pay = (res) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
uni.requestPayment({
|
uni.requestPayment({
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
provider: "wxpay", //支付类型-固定值
|
provider: "wxpay", //支付类型-固定值
|
||||||
@@ -100,6 +277,68 @@ const pay = (res) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function buy() {
|
||||||
|
if (price.value <= 0) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "金额不能小于0",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const code = await wxlogin();
|
||||||
|
const shopInfo = uni.getStorageSync("shopInfo");
|
||||||
|
const res = await mchRecharge({
|
||||||
|
amount: price.value,
|
||||||
|
shopId: shopInfo.id,
|
||||||
|
code,
|
||||||
|
payType: options.value.payType || "wechatPay",
|
||||||
|
});
|
||||||
|
if (res) {
|
||||||
|
const paySuccess = await pay(res);
|
||||||
|
if (paySuccess) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "支付成功",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh() {
|
||||||
|
query.page = 1;
|
||||||
|
flow();
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = reactive({
|
||||||
|
page: 1,
|
||||||
|
size: 10,
|
||||||
|
type: "self_recharge,manual_recharge",
|
||||||
|
});
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
records: [],
|
||||||
|
totalRecharge: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const isEnd = ref(false);
|
||||||
|
async function flow() {
|
||||||
|
const res = await distributionFlowApi.flow(query);
|
||||||
|
if (query.page == 1) {
|
||||||
|
Object.assign(state, res);
|
||||||
|
} else {
|
||||||
|
state.records = state.records.concat(res.records || []);
|
||||||
|
state.totalRecharge = res.totalRecharge || 0;
|
||||||
|
}
|
||||||
|
isEnd.value = query.page >= res.totalPage * 1;
|
||||||
|
}
|
||||||
|
onReachBottom(() => {
|
||||||
|
if (isEnd.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
query.page++;
|
||||||
|
flow();
|
||||||
|
});
|
||||||
async function init() {
|
async function init() {
|
||||||
const code = await wxlogin();
|
const code = await wxlogin();
|
||||||
const res = await mchRecharge({
|
const res = await mchRecharge({
|
||||||
@@ -107,15 +346,149 @@ async function init() {
|
|||||||
code,
|
code,
|
||||||
payType: options.value.payType || "wechatPay",
|
payType: options.value.payType || "wechatPay",
|
||||||
});
|
});
|
||||||
if(res){
|
if (res) {
|
||||||
const paySuccess= await pay(res);
|
const paySuccess = await pay(res);
|
||||||
if(paySuccess){
|
if (paySuccess) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: "支付成功",
|
title: "支付成功",
|
||||||
icon: "none",
|
icon: "none",
|
||||||
});
|
});
|
||||||
|
refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(res);
|
console.log(res);
|
||||||
}
|
}
|
||||||
|
watch(
|
||||||
|
() => selChargeIndex.value,
|
||||||
|
(newval) => {
|
||||||
|
if (newval != -1 &&price.value*1!=chargeList.value[newval].price*1) {
|
||||||
|
price.value = chargeList.value[newval].price;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.box {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.top {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: -1;
|
||||||
|
.image {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chrage-box {
|
||||||
|
width: 750rpx;
|
||||||
|
border-radius: 74rpx;
|
||||||
|
background: #ffffff4d;
|
||||||
|
padding: 42rpx 28rpx;
|
||||||
|
}
|
||||||
|
.title-bg {
|
||||||
|
position: relative;
|
||||||
|
.image {
|
||||||
|
position: absolute;
|
||||||
|
height: 14rpx;
|
||||||
|
width: 94rpx;
|
||||||
|
right: -10rpx;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.xieyi {
|
||||||
|
color: #ecb592;
|
||||||
|
}
|
||||||
|
.chargeList {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-left: 68rpx;
|
||||||
|
justify-content: space-between;
|
||||||
|
.item {
|
||||||
|
padding: 16rpx 36rpx;
|
||||||
|
border-radius: 22rpx;
|
||||||
|
background: linear-gradient(180deg, #f5f5f5 58.54%, #fff 104.47%);
|
||||||
|
border: 6rpx solid transparent;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
margin-right: 30rpx;
|
||||||
|
margin-bottom: 62rpx;
|
||||||
|
position: relative;
|
||||||
|
width: 220rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
&.active {
|
||||||
|
border: 6rpx solid #fe6c0e;
|
||||||
|
background: linear-gradient(180deg, #ffc29a -26.17%, #fff 64.06%);
|
||||||
|
box-shadow: 0 0 31.2rpx 2rpx #fe8b435e;
|
||||||
|
.price {
|
||||||
|
.font-bold {
|
||||||
|
color: #ff6300;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sel {
|
||||||
|
width: 42rpx;
|
||||||
|
height: 42rpx;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
bottom: -22rpx;
|
||||||
|
}
|
||||||
|
.price {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
color: #5f2e0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.item:nth-of-type(2n) {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.u-text-nowrap {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.input-box {
|
||||||
|
padding: 24rpx 16rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
background: #f6f6f6;
|
||||||
|
}
|
||||||
|
.buy {
|
||||||
|
padding: 32rpx 32rpx;
|
||||||
|
background: linear-gradient(98deg, #fe6d1100 40.64%, #ffd1b4 105.2%),
|
||||||
|
linear-gradient(259deg, #fe6d11 50.14%, #ffd1b4 114.93%);
|
||||||
|
box-shadow: 0 14rpx 30.4rpx 0 #fe8b435e;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 48rpx;
|
||||||
|
}
|
||||||
|
.recoders-list {
|
||||||
|
margin-top: 40rpx;
|
||||||
|
.item {
|
||||||
|
margin-bottom: 36rpx;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
padding: 32rpx 28rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
.price {
|
||||||
|
line-height: 44rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #fe7e00;
|
||||||
|
font-size: 48rpx;
|
||||||
|
.yuan {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
arr: [],
|
arr: [],
|
||||||
scrollRightTop: 0, // 右边栏目scroll-view的滚动条高度
|
scrollRightTop: 0, // 右边栏目scroll-view的滚动条高度
|
||||||
timer: null, // 定时器
|
timer: null, // 定时器
|
||||||
isTabClickOver:true
|
isTabClickOver: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
@@ -192,9 +192,9 @@
|
|||||||
let height2 = this.arr[i + 1];
|
let height2 = this.arr[i + 1];
|
||||||
// 如果不存在height2,意味着数据循环已经到了最后一个,设置左边菜单为最后一项即可
|
// 如果不存在height2,意味着数据循环已经到了最后一个,设置左边菜单为最后一项即可
|
||||||
if (!height2 || scrollHeight >= height1 && scrollHeight < height2) {
|
if (!height2 || scrollHeight >= height1 && scrollHeight < height2) {
|
||||||
if(this.isTabClickOver){
|
if (this.isTabClickOver) {
|
||||||
this.leftMenuStatus(i);
|
this.leftMenuStatus(i);
|
||||||
}else{
|
} else {
|
||||||
this.isTabClickOver = true;
|
this.isTabClickOver = true;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|||||||
BIN
static/market/gold.png
Normal file
BIN
static/market/gold.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
static/market/sel.png
Normal file
BIN
static/market/sel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 937 B |
BIN
static/market/title-bg.png
Normal file
BIN
static/market/title-bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 882 B |
BIN
static/market/top-bg.png
Normal file
BIN
static/market/top-bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
@@ -51,7 +51,9 @@ export const useMenusStore = defineStore('menus', {
|
|||||||
async getMenus() {
|
async getMenus() {
|
||||||
const data = await menusApi.getMenus()
|
const data = await menusApi.getMenus()
|
||||||
this.originMenus = data;
|
this.originMenus = data;
|
||||||
const arr = flattenNestedChildren(data).filter(v => v.miniPath)
|
const arr = flattenNestedChildren(data).filter(v =>{
|
||||||
|
return v.miniPath
|
||||||
|
})
|
||||||
this.adminPages=arr;
|
this.adminPages=arr;
|
||||||
this.menuList = this.allPages.filter(v => {
|
this.menuList = this.allPages.filter(v => {
|
||||||
const findItem = arr.find(item => item.miniPath == v.pageId || item.miniPath
|
const findItem = arr.find(item => item.miniPath == v.pageId || item.miniPath
|
||||||
|
|||||||
Reference in New Issue
Block a user