对接接口 - 团购列表 团购核销

This commit is contained in:
赵毅 2025-08-21 18:13:52 +08:00
parent 716d94c0d8
commit 84c73e4bdf
4 changed files with 315 additions and 64 deletions

7
api/groupPurchase.js Normal file
View File

@ -0,0 +1,7 @@
export const apiArr = {
groupBuyList: "/api/v2/wechat/commodity/group-buy/list", //团购列表
groupGoodsList: "/api/v2/wechat/commodity/group-goods/list", //团购商品列表
groupBuyAddress: "/api/v2/wechat/commodity/group-buy/address", //团购自提地址
groupBuyRecord: "/api/v2/wechat/commodity/group-buy/buy-record", //团购购买记录
groupBuyWriteOff: "/api/v2/wechat/commodity/group-buy/write-off", //团购核销
};

View File

@ -3,7 +3,6 @@
max-width: 750rpx;
margin: 0 auto;
background-color: #ffffff;
min-height: 100vh;
}
/* 顶部横幅 */
@ -63,6 +62,13 @@
display: flex;
}
.goods-item2 {
border-radius: 10rpx;
padding: 15rpx;
margin-bottom: 25rpx;
display: flex;
}
.goods-image {
width: 140rpx;
height: 140rpx;
@ -101,6 +107,12 @@
margin-bottom: 10rpx;
}
.goods-price {
font-size: 28rpx;
color: #e63946;
margin-bottom: 10rpx;
}
.price-container {
display: flex;
align-items: center;
@ -112,7 +124,6 @@
font-size: 28rpx;
color: #e63946;
margin-right: 10rpx;
padding: 3rpx 8rpx;
border-radius: 4rpx;
display: flex;
}
@ -130,7 +141,6 @@
padding: 10rpx 15rpx;
background: linear-gradient(to bottom, #fef6d6, #fee8a9);
border-radius: 0 15rpx 15rpx 0;
}
.original-price {
@ -139,15 +149,15 @@
}
.countdown {
width: 250rpx;
width: auto;
font-size: 22rpx;
padding: 10rpx 15rpx;
padding: 10rpx 20rpx;
color: #ffffff;
margin-bottom: 15rpx;
border-radius: 50rpx;
background-color: #fe2f01;
position: absolute;
top: 150rpx;
top: 120rpx;
right: 0;
}
@ -207,3 +217,91 @@
right: 0;
top: -10rpx;
}
/* 规格标签样式 */
.specification-tag {
width: 130rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #feeceb;
padding: 10rpx 20rpx;
border-radius: 40rpx;
margin: 15rpx 0;
font-size: 26rpx;
color: #dd4020;
}
.specification-tag text {
margin-right: 5rpx;
}
/* 货品列表样式 */
.sku-list {
margin-top: 10rpx;
padding: 15rpx;
background-color: #f9f9f9;
border-radius: 10rpx;
}
.sku-item{
position: relative;
}
.sku-info{
display: flex;
align-items: center;
justify-content: center;
}
.sku-image{
width: 100rpx;
height: 100rpx;
border-radius: 15rpx;
overflow: hidden;
margin-right: 15rpx;
}
.sku-price {
font-size: 26rpx;
color: #e63946;
margin-right: 10rpx;
border-radius: 4rpx;
display: flex;
margin-top: 15rpx;
}
.sku-price1{
width: auto;
padding: 10rpx 15rpx;
color: #ffffff;
background-color: #fc5d15;
border-radius: 15rpx 0 0 15rpx;
}
.sku-price2{
width: auto;
padding: 10rpx 15rpx;
background: linear-gradient(to bottom, #fef6d6, #fee8a9);
border-radius: 0 15rpx 15rpx 0;
}
.sku-control {
display: flex;
align-items: center;
justify-content: flex-end;
margin-top: 15rpx;
}
.sku-countdown {
width: auto;
font-size: 22rpx;
padding: 5rpx 20rpx;
color: #ffffff;
margin-bottom: 15rpx;
border-radius: 50rpx;
background-color: #fe2f01;
position: absolute;
top: 170rpx;
right: 0;
}

View File

@ -1,4 +1,4 @@
<template>
m<template>
<view class="group-purchase-container">
<!-- 顶部横幅 -->
<view class="banner">
@ -8,26 +8,88 @@
<!-- 商品列表 -->
<view class="goods-list">
<!-- 商品项 -->
<view class="goods-item" v-for="(item, index) in goodsList" :key="index" @click="toDetail(item)">
<view v-for="(item, index) in goodsList" :key="index">
<!-- 有多个货品 -->
<view class="goods-info" v-if="item.group_buy_goods_list.length > 1">
<view class="goods-image">
<image :src="item.image" mode="aspectFill"></image>
<image :src="item.commodity_pic" mode="aspectFill"></image>
</view>
<view class="goods-info">
<view class="goods-name">{{ item.name }}</view>
<view class="goods-desc">{{ item.desc }}</view>
<view class="goods-name">{{ item.commodity_name }}</view>
<view class="goods-desc">{{ item.commodity_intro }}</view>
<view class="goods-price"> {{ getPriceRange(item.group_buy_goods_list) }} </view>
<!-- 选择规格标签 -->
<view class="specification-tag" @click.stop="toggleSkuList(index)">
<text>{{ item.showSkuList ? '收起' : '选择规格' }}</text>
<u-icon name="arrow-down" size="26rpx" color="#FF370B" v-if="!item.showSkuList"></u-icon>
<u-icon name="arrow-up" size="26rpx" color="#FF370B" v-else></u-icon>
</view>
<!-- 货品列表 -->
<view class="sku-list" v-if="item.showSkuList">
<view v-for="(sku, skuIndex) in item.group_buy_goods_list" :key="skuIndex">
<view class="sku-item" @click="toDetail(sku)">
<view class="sku-info">
<view class="sku-image">
<image :src="item.commodity_pic" mode="aspectFill"></image>
</view>
<view class="goods-info">
<view class="goods-name">{{ sku.goods_name }}</view>
<view class="goods-desc">{{ sku.goods_spec }}</view>
</view>
</view>
<view class="price-container">
<view class="sku-price">
<view class="sku-price1">团购价</view>
<view class="sku-price2">{{ sku.group_buy_price }}/{{ sku.goods_unit }}
</view>
</view>
<view class="sku-control">
<view class="decrease-btn" @tap.stop="decreaseQuantity(index, 0)">-</view>
<view class="quantity">{{ sku.quantity }}</view>
<view class="increase-btn" @tap.stop="increaseQuantity(index, 0)">+</view>
</view>
</view>
<view class="original-price">单买价 {{ sku.sales_price }}/{{ sku.goods_unit }}</view>
<view class="sku-countdown">
{{
getEndTheCountdown(sku.group_buy_activity_info.end_time)
}}
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 只有一个货品 -->
<view v-else>
<view class="goods-item2" @click="toDetail(item)">
<view class="goods-image">
<image :src="item.commodity_pic" mode="aspectFill"></image>
</view>
<view class="goods-info">
<view class="goods-name">{{ item.commodity_name }}</view>
<view class="goods-desc">{{ item.commodity_intro }}</view>
<view class="price-container">
<view class="group-price">
<view class="group-price1">团购价</view>
<view class="group-price2">{{ item.groupPrice }}</view>
<view class="group-price2">{{ item.group_buy_goods_list[0].group_buy_price }}/{{
item.group_buy_goods_list[0].goods_unit }}</view>
</view>
<view class="quantity-control">
<view class="decrease-btn" @tap.stop="decreaseQuantity(index)">-</view>
<view class="quantity">{{ item.quantity }}</view>
<view class="increase-btn" @tap.stop="increaseQuantity(index)">+</view>
<view class="decrease-btn" @tap.stop="decreaseQuantity(index, 0)">-</view>
<view class="quantity">{{ item.group_buy_goods_list[0].quantity }}</view>
<view class="increase-btn" @tap.stop="increaseQuantity(index, 0)">+</view>
</view>
</view>
<view class="original-price">单买价 {{ item.group_buy_goods_list[0].sales_price }}/{{
item.group_buy_goods_list[0].goods_unit }}</view>
<view class="countdown">
{{ getEndTheCountdown(item.group_buy_goods_list[0].group_buy_activity_info.end_time) }}
</view>
</view>
</view>
<view class="original-price">单买价 {{ item.originalPrice }}</view>
<view class="countdown">{{ item.countdown }}</view>
</view>
</view>
</view>
@ -42,55 +104,123 @@
<script>
import { picUrl, menuButtonInfo, request, NavgateTo } from "../../../utils";
import { apiArr } from '@/api/groupPurchase.js'
export default {
data() {
return {
goodsList: [
{
id: 30,
name: "泰国金枕榴莲泰国金枕榴莲",
desc: "心形榴莲 软糯香甜",
image: "/static/logo.png",
groupPrice: "¥125.9/个",
originalPrice: "¥200/个",
countdown: "19天2小时10分钟后结束",
quantity: 1
},
{
id: 30,
name: "泰国金枕榴莲泰国金枕榴莲",
desc: "心形榴莲 软糯香甜",
image: "/static/logo.png",
groupPrice: "¥125.9/个",
originalPrice: "¥200/个",
countdown: "19天2小时10分钟后结束",
quantity: 1
}
],
goodsList: [],
carNum: 5,
quantity: 0,
timer: null, // ID
endTime: '', //
updateTime: Date.now() //
};
},
methods: {
toDetail(item) {
console.log("🚀 ~ toDetail ~ toDetail:", '跳转......')
NavgateTo(`/packages/shop/groupPurchaseDetail/index?item=${JSON.stringify(item)}`)
onLoad() {
this.getGoodsList()
},
increaseQuantity(index) {
this.goodsList[index].quantity++;
this.cartCount++;
},
decreaseQuantity(index) {
if (this.goodsList[index].quantity > 1) {
this.goodsList[index].quantity--;
this.cartCount--;
onShow() {
//
if (!this.timer) {
this.timer = setInterval(() => {
//
this.updateTime = Date.now();
}, 1000);
}
},
goToCart() {
methods: {
getGoodsList() {
const params = {
user_id: uni.getStorageSync('userId')
}
request(apiArr.groupBuyList, 'POST', params).then(res => {
const list = res.group_buy_list.map(item => {
// quantity
const group_buy_goods_list = item.group_buy_goods_list.map(sku => ({
...sku,
quantity: 0
}));
return {
...item,
commodity_pic: picUrl + item.commodity_pic,
showSkuList: false,
group_buy_goods_list
}
})
this.goodsList = list
console.log("🚀 ~ getGoodsList ~ this.goodsList:", this.goodsList)
})
},
toDetail(item) {
NavgateTo(`/packages/shop/groupPurchaseDetail/index?item=${JSON.stringify(item)}`)
},
//
getPriceRange(goodsList) {
if (!goodsList || goodsList.length === 0) return '¥0';
const prices = goodsList.map(item => Number(item.sales_price));
const minPrice = Math.min(...prices);
const maxPrice = Math.max(...prices);
return minPrice === maxPrice ? `${minPrice}` : `${minPrice} ~ ¥${maxPrice}`;
},
// /
toggleSkuList(index) {
this.goodsList[index].showSkuList = !this.goodsList[index].showSkuList;
},
//
increaseQuantity(goodsIndex, skuIndex) {
this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity++;
this.carNum++;
},
//
decreaseQuantity(goodsIndex, skuIndex) {
if (this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity > 0) {
this.goodsList[goodsIndex].group_buy_goods_list[skuIndex].quantity--;
this.carNum--;
} else {
}
},
//
shopCar() {
//
uni.showToast({
title: '跳转到购物车',
icon: 'none'
});
},
//
getEndTheCountdown(endTime) {
//
const now = new Date().getTime();
const end = new Date(endTime).getTime();
//
let diff = end - now;
//
if (diff <= 0) {
return '团购已结束';
}
//
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
diff -= days * (1000 * 60 * 60 * 24);
const hours = Math.floor(diff / (1000 * 60 * 60));
diff -= hours * (1000 * 60 * 60);
const minutes = Math.floor(diff / (1000 * 60));
diff -= minutes * (1000 * 60);
//
return `${days}${hours}小时${minutes}分钟后结束`;
}
},
onHide() {
//
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
}
};

View File

@ -22,6 +22,9 @@
</template>
<script>
import { request, picUrl, NavgateTo } from '../../../utils';
import { apiArr } from '@/api/groupPurchase.js'
export default {
data() {
return {
@ -29,15 +32,28 @@ export default {
};
},
methods: {
verifyOrder() {
async verifyOrder() {
if (this.verificationCode.trim()) {
console.log("🚀 ~ verifyOrder ~ this.verificationCode:", this.verificationCode)
const params = {
verification_code: this.verificationCode,
}
try {
const res = await request(apiArr.groupBuyWriteOff, 'POST', params, { showErrorToast: false })
console.log("🚀 ~ verifyOrder ~ res:", res)
this.$refs.uToast.show({
title: '核销成功',
type: 'success',
message: "订单核销成功",
duration: 2000
})
} catch (error) {
this.$refs.uToast.show({
title: '核销失败',
type: 'error',
message: "订单核销失败",
duration: 2000
})
}
} else {
this.$u.toast('请输入核销码');
}
@ -53,7 +69,7 @@ export default {
message: "扫码成功",
duration: 2000
})
console.log('扫码结果:', res.result);
console.log('扫码成功,识别的码:', res.result);
this.verificationCode = res.result;
},
fail: (err) => {