积分商城修改

This commit is contained in:
2025-12-11 11:34:06 +08:00
parent 87f2ee8c3d
commit bb2830730d
6 changed files with 372 additions and 170 deletions

View File

@@ -46,14 +46,17 @@
<view class="title">商品详情</view>
</view>
<view class="u-m-t-32">
<image class="w-full" v-for="(item,index) in item.goodsDescription" :key="index" mode="widthFix" :src="item">
<image class="w-full" v-for="(item,index) in item.goodsDescription" :key="index" mode="widthFix"
:src="item">
</image>
</view>
</view>
<view style="height: 100px"></view>
<view class="fixed-bottom u-flex u-row-center">
<view class="btn" @click="exchangeClick" :class="isCanExchange">立即兑换</view>
<view class="btn" @click="exchangeClick" :class="[isCanExchange?'':'gray']">
{{returnBtmText}}
</view>
</view>
<!-- 兑换确认弹窗start -->
@@ -76,27 +79,27 @@
</view>
<view class="goods-info">
<view class="u-flex">
<image class="cover"></image>
<image class="cover" :src="item.goodsImageUrl"></image>
<view class="u-flex u-flex-1 u-row-between u-p-l-16 u-col-center">
<view>
<view class="u-font-32 font-bold">这里是商品名称</view>
<view class="u-m-t-54 color-666">8000积分+9.99</view>
<view class="u-font-32 font-bold">{{item.goodsName}}</view>
<view class="u-m-t-54 color-666">{{item.requiredPoints}}积分+{{item.extraPrice}}</view>
</view>
<text class="color-666">X1</text>
</view>
</view>
<view class="u-m-t-20 waring u-flex u-col-center">
<view class="u-m-t-20 waring u-flex u-col-center" v-if="item.goodsCategory=='优惠券'">
<up-icon name="info-circle" size="16" color="#FF9900"></up-icon>
<view class="u-m-l-16">优惠券为虚拟发放一旦兑换不支持退款请悉知</view>
</view>
</view>
<view class="bottom font-bold text-right">
<text>合计 8000积分 + ¥9.99</text>
<text>合计 {{item.requiredPoints}}积分 + ¥{{item.extraPrice}}</text>
</view>
<view class="u-m-t-42 u-flex u-row-center">
<view class="btn">确认兑换</view>
<view class="btn" @click="payExchange">确认兑换</view>
</view>
</view>
</up-popup>
@@ -113,6 +116,9 @@
} from '@/utils/uniapp.js'
import modal from "@/scoreShop/components/modal.vue";
import * as pointGoodsApi from "@/common/api/order/pointGoods.js";
import {
pay
} from '@/utils/pay.js'
const imgs = {
bg: "https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/2/9fd6a3ad2b384f6cb4e88ed6b77bd334.png",
};
@@ -125,6 +131,10 @@
});
function exchangeClick() {
if (item.extraPrice > 0) {
popupData.show = true
return
}
modalData.show = true;
}
@@ -132,7 +142,45 @@
// modalData.show = false;
exchange()
}
async function payExchange() {
uni.showLoading({
title: '兑换中……'
})
const openId = await getOpenId()
uni.hideLoading()
if (openId) {
pointGoodsApi.exchange({
pointsGoodsId: item.id,
shopId: item.shopId,
number: 1,
price: item.extraPrice,
openId
}).then(orderRes => {
popupData.show = false;
pay(orderRes.payInfo).then(res => {
console.log(res)
if (res) {
uni.setStorageSync('exchange_goods_success', orderRes.goodsRecord)
uni.redirectTo({
url: '/scoreShop/success/index'
})
} else {
uni.showToast({
title: '兑换失败',
icon: 'none'
})
}
})
})
} else {
uni.showToast({
title: '鉴权失败,兑换失败',
icon: 'none'
})
}
}
async function exchange() {
uni.showLoading({
title: '兑换中……'
@@ -148,12 +196,12 @@
openId
}).then(res => {
modalData.show = false;
if(res){
uni.setStorageSync('exchange_goods_success',res)
if (res) {
uni.setStorageSync('exchange_goods_success', res)
uni.redirectTo({
url:'/scoreShop/success/index'
url: '/scoreShop/success/index'
})
}else{
} else {
uni.showToast({
title: '兑换失败',
icon: 'none'
@@ -219,11 +267,27 @@
if (item.quantity <= 0) {
return false
}
if(item.limitQuota&&item.boughtCount>=item.limitQuota){
if (item.limitQuota && item.boughtCount >= item.limitQuota) {
return false
}
return true
})
const returnBtmText = computed(() => {
if (isCanExchange.value) {
return '立即兑换'
}
if (pointsUser.pointBalance < item.requiredPoints) {
const num = item.requiredPoints - pointsUser.pointBalance
return `积分不足,还差${num}积分`
}
if (item.quantity <= 0) {
return `库存不足`
}
if (item.limitQuota && item.boughtCount >= item.limitQuota) {
return `单人兑换已达上限`
}
})
onLoad((opt) => {
const exchange_goods = uni.getStorageSync('exchange_goods')
if (exchange_goods.goodsDescription) {
@@ -342,7 +406,7 @@
background-color: #fff;
bottom: 0;
z-index: 10;
.btn {
padding: 16rpx 62rpx;

View File

@@ -25,7 +25,7 @@
</template>
<template v-if="layout === 'block'">
<view class="item">
<view class="img coupon" v-if="item.goodsCategory=='优惠'&&item.couponInfo">
<view class="img coupon" v-if="item.goodsCategory=='优惠'&&item.couponInfo">
<couponIcon :item="item.couponInfo" typeKey="couponType" />
</view>
<image class="img" v-else lazy-load :src="item.goodsImageUrl"></image>
@@ -37,7 +37,7 @@
</view>
<view class="u-flex u-col-center u-m-t-16 u-row-between">
<view class="limit" v-if="item.limitQuota">限购{{item.limitQuota}}</view>
<view class="btn" v-if="canExchange(item)">兑换</view>
<view class="btn" v-if="item.quantity>0">兑换</view>
<view class="btn end" v-else>已兑完</view>
</view>
</view>
@@ -65,7 +65,7 @@
});
function toDetail(item) {
if (!canExchange(item)) {
if (item.quantity<=0) {
return
}
uni.setStorageSync('exchange_goods', item)

View File

@@ -1,6 +1,6 @@
<template>
<view class="list">
<view v-for="(item, index) in list" :key="index" class="item">
<view v-for="(item, index) in list" :key="index" class="item" @click="toDetail(item)">
<view class="u-flex u-row-between">
<text class="color-999">{{item.createTime}}</text>
<text class="status " :class="[returnStatusClass(item)]">{{item.status}}</text>
@@ -16,9 +16,9 @@
</view>
</view>
<view class="u-m-t-28 u-flex u-row-right btns">
<view class="btn look" @click="lookCode(item)" v-if="item.goodsCategory!='优惠券'">查看券码</view>
<view class="btn black" @click="tuikuan(item)" v-if="canRefund(item)">申请退款</view>
<view class="btn black" @click="cancelRefund(item)" v-if="item.status=='退款中'" >取消退款</view>
<view class="btn look" @click.stop="lookCode(item)" v-if="item.goodsCategory!='优惠券'">查看券码</view>
<view class="btn black" @click.stop="refund(item)" v-if="canRefund(item)">申请退款</view>
<view class="btn black" @click.stop="cancelRefund(item)" v-if="item.status=='退款中'" >取消退款</view>
</view>
</view>
</view>
@@ -39,12 +39,19 @@
emits("lookCode", item);
};
function tuikuan(item) {
function refund(item) {
emits("refund", item);
}
function cancelRefund(item) {
emits("cancelRefund", item);
}
function toDetail(item){
uni.setStorageSync('points_order_detail',item)
uni.navigateTo({
url:'/scoreShop/order/detail'
})
}
function returnStatusClass(item) {
if (item.status == '已完成' || item.status == '已退款') {

View File

@@ -1,156 +1,279 @@
<template>
<view class="min-page bg-f7 color-333 u-font-28">
<view class="top">
<view class="u-flex u-col-center">
<up-image width="208rpx" height="208rpx"></up-image>
<view class="u-p-l-28 u-flex-1">
<view class="font-bold">这里是商品名称</view>
<view class="u-flex u-row-between u-m-t-8">
<text class="color1 font-bold">8000积分</text>
<text class="status success">已完成</text>
</view>
<view class="u-m-t-8 font-bold color1"> X1 </view>
</view>
</view>
<template v-if="true">
<view class="u-m-t-16">
<view class="u-flex u-row-center">
<up-qrcode cid="ex1" :size="104" :val="qrcode"></up-qrcode>
</view>
<view class="u-m-t-22 u-flex u-row-center">
<text>{{ qrcode }}</text>
<view @click="copyCode">
<image
src="/scoreShop/static/image/copy.png"
class="u-m-l-24 copy"
></image>
</view>
</view>
</view>
</template>
<view class="min-page bg-f7 color-333 u-font-28">
<view class="top">
<view class="u-flex u-col-center">
<up-image width="208rpx" height="208rpx" :src="item.goodsImageUrl" v-if="item.goodsCategory!='优惠券'"></up-image>
<view class="" style="width: 208rpx;height: 208rpx;">
<couponIcon :item="item.couponInfo" typeKey="couponType" />
</view>
<view class="u-p-l-28 u-flex-1">
<view class="font-bold">{{item.pointsGoodsName}}</view>
<view class="u-flex u-row-between u-m-t-8">
<text class="color1 font-bold">{{item.spendPoints}}积分</text>
<text class="status " :class="[returnStatusClass(item)]">{{item.status}}</text>
</view>
<view class="u-m-t-8 font-bold color1"> X{{item.number}} </view>
</view>
</view>
<template v-if="item.goodsCategory=='其它商品'">
<view class="u-m-t-16">
<view class="u-flex u-row-center">
<up-qrcode cid="ex1" :size="104" :val="qrcode"></up-qrcode>
</view>
<view class="u-m-t-22 u-flex u-row-center">
<text>{{ qrcode }}</text>
<view @click="copyCode">
<image src="/scoreShop/static/image/copy.png" class="u-m-l-24 copy"></image>
</view>
</view>
</view>
</template>
<view class="u-m-t-16">
<text class="color-666">领取方式</text>
<text class="u-m-l-20">需前往店铺自行兑换领取</text>
</view>
</view>
<view class="u-m-t-16">
<text class="color-666">领取方式</text>
<text class="u-m-l-20" v-if="item.goodsCategory=='其它商品'">需前往店铺自行兑换领取</text>
<text class="u-m-l-20" v-else>系统发放</text>
</view>
</view>
<view class="bottom">
<view class="u-flex u-row-between item">
<text>兑换商品</text>
<text class="color-666">这里是商品名称</text>
</view>
<view class="u-flex u-row-between item">
<text>兑换数量</text>
<text class="color-666">1</text>
</view>
<view class="u-flex u-row-between item">
<text>消耗积分</text>
<text class="color-666">800</text>
</view>
<view class="u-flex u-row-between item">
<text>支付金额</text>
<text class="color-666">9.99</text>
</view>
<view class="u-flex u-row-between item">
<text>下单时间</text>
<text class="color-666">2025-12-3 17:1932</text>
</view>
<view class="u-flex u-row-between item">
<text>核销时间</text>
<text class="color-666">2025-12-04 01:13:14</text>
</view>
<view class="u-flex u-row-between item">
<text>订单号</text>
<text class="color-666">DH202511300001</text>
</view>
</view>
<view class="bottom">
<view class="u-flex u-row-between item">
<text>兑换商品</text>
<text class="color-666">{{item.pointsGoodsName}}</text>
</view>
<view class="u-flex u-row-between item">
<text>兑换数量</text>
<text class="color-666">{{item.number}}</text>
</view>
<view class="u-flex u-row-between item">
<text>消耗积分</text>
<text class="color-666">{{item.spendPoints}}</text>
</view>
<view class="u-flex u-row-between item">
<text>支付金额</text>
<text class="color-666">{{item.extraPaymentAmount}}</text>
</view>
<view class="u-flex u-row-between item">
<text>下单时间</text>
<text class="color-666">{{item.createTime}}</text>
</view>
<view class="u-flex u-row-between item">
<text>核销时间</text>
<text class="color-666">{{item.checkoutTime||''}}</text>
</view>
<view class="u-flex u-row-between item">
<text>订单号</text>
<text class="color-666">{{item.orderNo}}</text>
</view>
</view>
<view class="btns">
<view class="btn cancel">申请退款</view>
<view class="btn success ">取消退款</view>
</view>
</view>
<view class="btns">
<view class="btn cancel" @click="refund(item)" v-if="canRefund(item)">申请退款</view>
<view class="btn success " @click="cancelRefund(item)" v-if="item.status=='退款中'">取消退款</view>
</view>
</view>
</template>
<script setup>
const qrcode = ref("251202150055");
function copyCode() {
uni.setClipboardData({
data: qrcode.value,
success: function () {
uni.showToast({
title: "复制成功",
icon: "none",
});
},
});
}
import couponIcon from "@/components/coupon-icon/index";
import * as pointGoodsApi from "@/common/api/order/pointGoods.js";
const qrcode = ref();
function copyCode() {
uni.setClipboardData({
data: qrcode.value,
success: function() {
uni.showToast({
title: "复制成功",
icon: "none",
});
},
});
}
const item = reactive({
})
function returnStatusClass(item) {
if (item.status == '已完成' || item.status == '已退款') {
return 'gray'
}
if (item.status == '待核销') {
return 'success'
}
if (item.status == '退款中') {
return 'error'
}
}
function canRefund(item) {
if(item.status=='已退款'|| item.status=='退款中'||item.goodsCategory!='其它商品' ){
return false
}
return true
}
function init() {
const data = uni.getStorageSync('points_order_detail')
qrcode.value=data.couponCode
Object.assign(item, data)
}
onLoad(init)
function refund(item) {
uni.showModal({
title: '提示',
content: '是否申请退款',
showCancel: true,
success(res) {
if (res.confirm) {
pointGoodsApi.applyRefund({
orderNo: item.orderNo,
recordId: item.id
}).then(res => {
if (res) {
uni.showToast({
title: '申请退款成功',
icon: 'none'
})
} else {
uni.showToast({
title: '申请退款失败',
icon: 'none'
})
}
setTimeout(() => {
refresh()
}, 1000)
})
}
}
})
}
function refresh(){
pointGoodsApi.recordOne({
id:item.id
}).then(res=>{
Object.assign(item,res)
})
}
function cancelRefund(item) {
uni.showModal({
title: '提示',
content: '是否取消退款',
showCancel: true,
success(res) {
if (res.confirm) {
pointGoodsApi.cancelRefund({
orderNo: item.orderNo,
recordId: item.id
}).then(res => {
if (res) {
uni.showToast({
title: '取消退款成功',
icon: 'none'
})
} else {
uni.showToast({
title: '取消退款失败',
icon: 'none'
})
}
setTimeout(() => {
refresh()
}, 1000)
})
}
}
})
}
</script>
<style lang="scss" scoped>
.min-page {
padding: 28rpx;
}
.top {
padding: 32rpx 24rpx;
background: #fff;
.color1 {
color: #9c571f;
}
.status {
padding: 8rpx 18rpx;
border-radius: 8rpx;
border: 2rpx solid transparent;
&.success {
background: rgba(123, 209, 54, 0.12);
border-color: #7bd136;
color: #7bd136;
}
&.gray {
background: #9999991f;
border-color: #999;
color: #999;
}
&.error {
background: #ff1c1c2e;
border-color: #ff1c1c;
color: #ff1c1c;
}
}
}
.copy {
width: 28rpx;
height: 28rpx;
}
.bottom {
background: #fff;
border-radius: 32rpx;
padding: 16rpx 28rpx;
margin-top: 48rpx;
.item {
padding: 16rpx 0;
}
}
.btns {
margin-top: 66rpx;
display: flex;
justify-content: center;
gap: 48rpx;
.btn {
border: 2rpx solid transparent;
border-radius: 100rpx;
background: #fff;
padding: 14rpx 76rpx;
font-size: 32rpx;
&.success {
background-color: #e8ad7b;
border-color: #e8ad7b;
color: #fff;
}
&.cancel {
border-color: #e8ad7b;
color: #e8ad7b;
}
}
}
</style>
.min-page {
padding: 28rpx;
}
.top {
padding: 32rpx 24rpx;
background: #fff;
.color1 {
color: #9c571f;
}
.status {
padding: 8rpx 18rpx;
border-radius: 8rpx;
border: 2rpx solid transparent;
&.success {
background: rgba(123, 209, 54, 0.12);
border-color: #7bd136;
color: #7bd136;
}
&.gray {
background: #9999991f;
border-color: #999;
color: #999;
}
&.error {
background: #ff1c1c2e;
border-color: #ff1c1c;
color: #ff1c1c;
}
}
}
.copy {
width: 28rpx;
height: 28rpx;
}
.bottom {
background: #fff;
border-radius: 32rpx;
padding: 16rpx 28rpx;
margin-top: 48rpx;
.item {
padding: 16rpx 0;
}
}
.btns {
margin-top: 66rpx;
display: flex;
justify-content: center;
gap: 48rpx;
.btn {
border: 2rpx solid transparent;
border-radius: 100rpx;
background: #fff;
padding: 14rpx 76rpx;
font-size: 32rpx;
&.success {
background-color: #e8ad7b;
border-color: #e8ad7b;
color: #fff;
}
&.cancel {
border-color: #e8ad7b;
color: #e8ad7b;
}
}
}
</style>

View File

@@ -171,7 +171,7 @@
function getList() {
const status = tabs.list.find(v => v.value == tabs.sel)
pointGoodsApi.recordPage({
...query,
...query,status:tabs.sel?status.name:''
}).then(res => {
const newList = res.records
if (query.page == 1) {