商品团购券分享处理

This commit is contained in:
2024-06-08 17:05:25 +08:00
parent 4b4ee44242
commit a620ecf624
12 changed files with 352 additions and 50 deletions

View File

@@ -51,11 +51,11 @@ export default {
else {
//生产环境
if(import.meta.env.VITE_APP_BASE_API.includes('api.lakeapp')) {
// setCompanyId('1150930317231112193');
// setRegisterStoreId('1150930317436633090');
setCompanyId('1150930317231112193');
setRegisterStoreId('1150930317436633090');
setCompanyId('1471673498334113794');
setRegisterStoreId('1471673498413805570');
// setCompanyId('1471673498334113794');
// setRegisterStoreId('1471673498413805570');
}
//测试
else {

View File

@@ -1,16 +1,14 @@
import { get, post } from '@/utils';
import { get } from '@/utils';
import { CategoryBean, GoodsBean } from '@/api/goods/types';
enum URL {
categoryList = '/ext/goods/category_list',
goodsList = '/ext/goods/query',
goodsDetail = '/ext/goods/info',
shareGoodsDetail = '/wechat/coupons/group/qrcode'
goodsDetail = '/ext/goods/info'
}
export const getCategoryList = () => get<CategoryBean[]>({ url: URL.categoryList });
export const getGoodsList = (params: any) => get<GoodsBean[]>({ url: URL.goodsList, data: params });
export const getGoodsDetail = (goodsId: string) => get<GoodsBean>({ url: URL.goodsDetail + `?goodsId=${goodsId}` });
export const getShareGoodsDetail = (shareId: string) => post<GoodsBean>({ url: URL.shareGoodsDetail + `/${shareId}` });

View File

@@ -13,11 +13,17 @@ export const getGroupBuyList = (data: {
export const getGroupBuyDetail = (
id: string) => get<GroupBuyBean>({ url: `wechat/coupons/group/get/${id}` });
export const getShareGoodsDetail = (shareId: string) => post<any>({ url: '/wechat/coupons/group/qrcode/' + `${shareId}` });
export const getShareGoodsCouponDetail = (couponId: string) => get<GroupBuyBean>({ url: 'wechat/coupons/get/' + `${couponId}` });
export const getGroupBuyRecordList = (groupId: string, pageNum: number, pageSize: number) => post<RecordBean[]>({
url: `wechat/coupons/group/order/list?groupId=${groupId}&pageNum=${pageNum}&pageSize=${pageSize}`
});
export const preOrder = (data: any) => post<GoodsBean>({ url: 'wechat/coupons/group/pre_v2', data });
export const preOrder = (data: any) => post<GoodsBean>({ url: 'wechat/coupons/pre', data });
export const preOrderV2 = (data: any) => post<GoodsBean>({ url: 'wechat/coupons/group/pre_v2', data });
export const progress = (data: any) => post<any>({ url: 'wechat/coupons/group/pay/progress', data });

View File

@@ -91,6 +91,15 @@
}
}
},
{
"path": "groupbuy/order-coupon-confirm",
"style": {
"navigationBarTitleText": "确认订单",
"usingComponents": {
"sqb-pay": "plugin://sqb-pay/sqb-pay"
}
}
},
{
"path": "webview/index",
"navigationBarTitleText": "网页"

View File

@@ -51,7 +51,7 @@
</view>
</view>
<view class='goods-sku-view c-flex-column'>
<view class='goods-sku-view c-flex-column' v-if='groupBuyBean?.goods'>
<view class='c-flex-row' @click.stop='showSkuDialog'>
<text>选择</text>
<text>规格 颜色/尺码</text>
@@ -77,13 +77,16 @@
<!-- 商品详情图片 -->
<view class='card-view image-container' v-if='groupBuyBean?.content'>
<text class='card-view-title'>商品详情</text>
<image
<text v-if='isCouponGoodsDetail' style='padding: 20rpx 35rpx;font-size: 30rpx'>
{{ groupBuyBean?.content }}
</text>
<image v-else
v-for='(item,index) in JSON.parse(groupBuyBean?.content).filter((a: any) => a.type === 2).map((b: any) => b.images)'
:src='item' mode='aspectFill' :key='index' />
</view>
<!-- 商品详情 -->
<view class='card-view goods-container'>
<view class='card-view goods-container' v-if='groupBuyBean?.goods'>
<view class='c-flex-row'>
<image :src='groupBuyBean?.goods?.images' />
<view class='c-flex-column'>
@@ -101,7 +104,7 @@
</view>
<!-- 商品详情优惠券 -->
<view class='card-view coupon-container'>
<view class='card-view coupon-container' v-if='groupBuyBean?.couponsList'>
<text class='card-view-title'>赠送优惠券</text>
<view class='c-flex-column'>
<coupon-item v-for='(item,index) in groupBuyBean?.couponsList' :key='index' :item='item' />
@@ -109,7 +112,7 @@
</view>
<!-- 商品详情跟团记录 -->
<view class='card-view record-container'>
<view class='card-view record-container' v-if='recordList&&recordList.length>0'>
<text class='card-view-title'>跟团记录</text>
<u-list :list='recordList' :border='false' @scrolltolower='loadMore'>
<u-list-item v-for='(item,index) in recordList' :key='index'>
@@ -143,8 +146,14 @@ import { formatTimeWithZeroPad, goPath, isLogin } from '@/utils';
import SkuDialog from '@/components/sku-dialog.vue';
import CouponItem from './components/coupon-item.vue';
import { getGroupBuyDetail, getGroupBuyRecordList, preOrder } from '@/api/groupbuy';
import { getGoodsList, getShareGoodsDetail } from '@/api/goods';
import {
getGroupBuyDetail,
getGroupBuyRecordList,
getShareGoodsCouponDetail,
getShareGoodsDetail,
preOrderV2
} from '@/api/groupbuy';
import { getGoodsList } from '@/api/goods';
import { GoodsBean } from '@/api/goods/types';
import { useUserStore } from '@/store';
import { GroupBuyBean, RecordBean } from '@/api/groupbuy/types';
@@ -155,6 +164,7 @@ const { userInfo } = storeToRefs(userStore);
const skuDialogRef = ref();
const groupBuyBean = ref<GroupBuyBean>();
const recommendList = ref<GoodsBean[]>();
const isCouponGoodsDetail = ref(false);
const bannerList = ref([]);
const swiperIndex = ref(0);
@@ -180,15 +190,23 @@ onLoad(async (e: any) => {
const { group, share } = await getShareGoodsDetail(e.shareId);
groupBuyBean.value = group;
}
if(e.couponId != undefined) {
isCouponGoodsDetail.value = true;
groupBuyBean.value = await getShareGoodsCouponDetail(e.couponId);
groupBuyBean.value.price = groupBuyBean.value?.offsetPrice;
bannerList.value = groupBuyBean.value?.image?.split(',');
}
// setCompanyId('1512403904150138881');
// groupBuyBean.value = await getGroupBuyDetail('1740922051118063618');
if(groupBuyBean.value) {
groupBuyBean.value.goods.price = groupBuyBean.value.price;
bannerList.value = JSON.parse(groupBuyBean.value.content).filter((item: any) => item.type === 2).map((item: any) => item.images);
countdown();
if(e.couponId === undefined) {
groupBuyBean.value.goods.price = groupBuyBean.value?.price || 0;
bannerList.value = JSON.parse(groupBuyBean.value?.content).filter((item: any) => item.type === 2).map((item: any) => item.images);
await fetchRecommendList();
await fetchBuyRecordList();
}
}
uni.hideLoading();
} else {
goPath('/pages/common/login/index');
@@ -282,7 +300,8 @@ const showSkuDialog = (fn: Function) => {
const placeOrder = async () => {
async function create(bean: GoodsBean) {
async function createGoodsOrder(bean: GoodsBean) {
await uni.showLoading();
const params = {
'colorId': bean.checkedStock.colorId,
'sizeId': bean.checkedStock.sizeId,
@@ -292,13 +311,18 @@ const placeOrder = async () => {
'shareId': '123456'
};
const result = await preOrder(params);
const result = await preOrderV2(params);
uni.hideLoading();
goPath(`/pages/common/groupbuy/order-confirm?orderBean=${encodeURIComponent(JSON.stringify(result))}`);
}
if(isCouponGoodsDetail.value) {
goPath(`/pages/common/groupbuy/order-coupon-confirm?bean=${encodeURIComponent(JSON.stringify(groupBuyBean.value))}`);
} else {
showSkuDialog((e: GoodsBean) => {
create(e);
createGoodsOrder(e);
});
}
};
</script>
@@ -679,18 +703,19 @@ const placeOrder = async () => {
margin: 0 15rpx;
text:nth-of-type(1) {
font-size: 20rpx;
font-size: 25rpx;
color: #333333;
}
text:nth-of-type(2) {
font-size: 15rpx;
font-size: 25rpx;
color: #666666;
margin-top: 10rpx;
}
}
text:nth-of-type(1) {
font-size: 30rpx;
color: #F32B2B;
}
}

View File

@@ -1,6 +1,5 @@
<template>
<view class='content'>
<view class='card-view'>
<template class='c-flex-row' v-for='item in orderBean?.orderGoods' :key='item.id'>
<image class='goods-image' :src='item?.images||defaultImage' />

View File

@@ -0,0 +1,255 @@
<template>
<view class='content'>
<view class='card-view' style='justify-content: flex-start'>
<view class='c-flex-row' style='align-items: center;flex: 1'>
<image class='goods-image' :src='imageList[0]||defaultImage' />
<view class='c-flex-column' style='margin-left: 10rpx;flex: 1'>
<text class='goods-name'>{{ groupBuyBean?.name || groupBuyBean?.title }}</text>
<text class='date'>{{ groupBuyBean?.startDate }}{{ groupBuyBean?.endDate }}</text>
</view>
<text class='goods-price'>¥{{ groupBuyBean?.payPrice }}</text>
</view>
</view>
<view class='card-view'>
<text style='flex: 1'>数量</text>
<view class='count-change-view c-flex-row'>
<view class='count-image' @click.stop='countChange(false)'>
<image :src='assetsUrl("ic_reduce.png")' />
</view>
<text>{{ goodsCount }}</text>
<view class='count-image' @click.stop='countChange(true)'>
<image :src='assetsUrl("ic_plus.png")' />
</view>
</view>
</view>
<view class='card-view'>
<text style='flex: 1'>实付</text>
<text style='color: #F32B2B'>¥{{ totalPrice || 0 }}</text>
</view>
<view class='bottom-view c-flex-row'>
<sqb-pay @navigateTo='navigateTo'
:return_url='buildSqbParams.return_url'
:total_amount='buildSqbParams.total_amount'
:terminal_sn='buildSqbParams.terminal_sn'
:client_sn='buildSqbParams.client_sn'
:subject='buildSqbParams.subject'
:subject_img='buildSqbParams.subject_img '
:merchant_name='buildSqbParams.merchant_name'
:notify_url='buildSqbParams.notify_url'
:sign='buildSqbParams.sign'>
<button class='confirm-button' @click='payment'>支付</button>
</sqb-pay>
</view>
</view>
</template>
<script lang='ts' setup>
import { preOrder } from '@/api/groupbuy';
import { OrderBean } from '@/api/order/types';
import { parseParameter, showToast, sortASCII } from '@/utils';
import { hexMD5 } from '@/utils/common/md5';
import { useUserStore } from '@/store';
import { handlePayResult } from '@/utils/order';
import { assetsUrl, defaultImage } from '@/utils/assets';
import { GroupBuyBean } from '@/api/groupbuy/types';
const userState = useUserStore();
const { userInfo, terminalInfo } = storeToRefs(userState);
const groupBuyBean = ref<GroupBuyBean>();
const imageList = ref([]);
const orderBean = ref<OrderBean>();
const goodsCount = ref(1);
onLoad((e: any) => {
groupBuyBean.value = JSON.parse(decodeURIComponent(e?.bean));
imageList.value = groupBuyBean.value?.image?.split(',');
createOrder();
});
const countChange = (isPlus: boolean) => {
if(isPlus) {
goodsCount.value += 1;
} else {
if(goodsCount.value > 1) {
goodsCount.value -= 1;
}
}
};
const totalPrice = computed(() => {
return Number(((groupBuyBean.value?.payPrice || 0) * goodsCount.value).toFixed(2));
});
const buildSqbParams = computed(() => {
const params = sortASCII({
client_sn: orderBean.value?.id || '',
return_url: '/pages/common/payresult/index',
total_amount: Number(((totalPrice.value || 0) * 100).toFixed(2)),
terminal_sn: terminalInfo.value.terminalSn,
subject: '商品团购券',
subject_img: imageList.value[0] || '',
merchant_name: terminalInfo.value.companyName,
notify_url: 'https://www.baidu.com'
}, true);
return {
...params,
sign: hexMD5(parseParameter(params) + '&key=' + terminalInfo.value.terminalKey).toUpperCase()
};
});
const navigateTo = (e: any) => {
handlePayResult(orderBean.value?.id, e, {
onSuccess: () => {
showToast('支付成功', {
icon: 'success',
complete: () => {
uni.navigateBack();
}
});
}
});
};
const createOrder = () => {
const params = {
id: groupBuyBean.value?.id,
cash: totalPrice.value,
num: goodsCount.value,
memberId: userInfo.value.id,
payBo: {
terminal_sn: terminalInfo.value.terminalSn,
terminal_key: terminalInfo.value.terminalKey,
merchant_name: userInfo.value.companyName,
total_amount: totalPrice.value,
subject: groupBuyBean.value?.name || '微信团购券',
description: groupBuyBean.value?.title || '微信团购券',
subject_img: imageList.value[0] || '',
device_id: groupBuyBean.value?.creatorId,
return_url: '/pages/payResult/index'
}
};
preOrder(params).then(res => {
orderBean.value = res as any;
});
};
const payment = () => {
};
</script>
<style lang='scss' scoped>
.content {
.card-view:nth-of-type(1) {
margin-top: 30rpx;
}
}
.card-view {
display: flex;
flex-direction: row;
margin: 10rpx 30rpx;
background: #FFFFFF;
font-size: 35rpx;
padding: 30rpx;
.goods-image {
display: flex;
width: 130rpx;
height: 130rpx;
margin-right: 15rpx;
border-radius: 8rpx;
}
.goods-name {
display: flex;
font-size: 35rpx;
font-weight: bold;
color: #333333;
margin-left: 10rpx;
}
.date {
font-size: 25rpx;
color: #999999;
margin-left: 10rpx;
margin-top: 10rpx;
}
.goods-price {
display: flex;
font-size: 30rpx;
margin-right: 10rpx;
justify-content: flex-end;
color: #333333;
}
.count-change-view {
.count-image {
display: flex;
align-items: center;
justify-content: center;
width: 54rpx;
height: 54rpx;
background: #FBFBFB;
image {
width: 15rpx;
height: 2rpx;
}
}
.count-image:nth-of-type(2) image {
width: 17rpx;
height: 17rpx;
}
text {
display: flex;
width: 54rpx;
height: 54rpx;
align-items: center;
justify-content: center;
font-weight: 400;
font-size: 30rpx;
color: #333333;
background: #F2F2F2;
}
}
}
.bottom-view {
background: #FFFFFF;
padding: 20rpx 30rpx 78rpx 33rpx;
position: fixed;
left: 0;
right: 0;
bottom: 0;
sqb-pay {
flex: 1;
.confirm-button {
display: flex;
flex: 1;
font-weight: bold;
width: 100%;
font-size: 30rpx;
height: 80rpx;
align-items: center;
justify-content: center;
background: #F32B2B;
color: #FFFFFF;
border-radius: 40rpx;
}
}
}
</style>

View File

@@ -6,7 +6,7 @@
import { getQueryParam } from '@/utils';
onLoad((options) => {
getApp().logger?.info('ticketsBuy options: ', options);
getApp().globalData?.logger?.info('ticketsBuy options: ', options);
let couponId = options?.couponsId;
if(options?.query && couponId == undefined) {
const params = decodeURIComponent(options?.query);
@@ -14,9 +14,9 @@ onLoad((options) => {
}
setTimeout(() => {
uni.reLaunch({
url: `/pages/common/groupbuy/detail?id=${couponId}`
url: `/pages/common/groupbuy/detail?couponId=${couponId}`
});
}, 300);
}, 350);
});

View File

@@ -87,7 +87,7 @@ const submenuList = [
icon: assetsUrl('ic_register_gift2.png'),
path: '/pages/common/register/reward'
// path: '/pages/common/groupbuy/detail?shareId=1797548579864748033'
// path: '/pages/coupons/ticketsBuy/ticketsBuy?couponsId=1797773484774432769'
// path: '/pages/coupons/ticketsBuy/ticketsBuy?couponsId=1799264392762138626'
},
{
title: '团购秒杀',

View File

@@ -6,15 +6,29 @@
import { getQueryParam } from '@/utils';
onLoad((options) => {
getApp().globalData?.logger?.info('app share index/index options: ', options);
let goodsShareId = '';
if(options?.scene) {
const scene = decodeURIComponent(options?.scene);
goodsShareId = scene.split('=')[1];
getApp().globalData?.logger?.info('app share index/index options: scene goodsShareId ', goodsShareId);
} else if(options?.shareId) {
goodsShareId = options?.shareId;
}
getApp().globalData?.logger?.info('app share index/index options: scene ', options);
if(options?.query) {
getApp().logger?.info('app goods share options: ', options);
const params = decodeURIComponent(options?.query);
const shareId = getQueryParam(params, 'shareId');
getApp().logger?.info('app goods share options: ', params, shareId);
if(shareId != undefined) {
goodsShareId = getQueryParam(params, 'shareId') || '';
getApp().globalData?.logger?.info('app goods share options: params ', params, goodsShareId);
}
getApp().globalData?.logger?.info('app share index/index options: query ', options);
if(goodsShareId) {
setTimeout(() => {
uni.reLaunch({
url: `/pages/common/groupbuy/detail?shareId=${shareId}`
url: `/pages/common/groupbuy/detail?shareId=${goodsShareId}`
});
}, 300);
} else {
@@ -22,11 +36,6 @@ onLoad((options) => {
url: '/pages/home/index'
});
}
} else {
uni.reLaunch({
url: '/pages/home/index'
});
}
});
</script>

View File

@@ -152,8 +152,8 @@ const useUserStore = defineStore('user', {
if(this.userInfo) {
this.userInfo.userDiscount = this.getUserDiscount;
await setCompanyId(this.userInfo.companyId);
if(getApp().globalData){
getApp().globalData.companyId = this.userInfo.companyId;
if(getApp().globalData) {
getApp().globalData!.companyId = this.userInfo.companyId;
}
} else {
await clearToken();
@@ -165,7 +165,7 @@ const useUserStore = defineStore('user', {
setCompanyInfo(partial: Partial<any>) {
this.companyInfo = partial as any;
if(getApp()?.globalData) {
getApp().globalData.companyId = this.companyInfo.id;
getApp().globalData!.companyId = this.companyInfo.id;
}
},

View File

@@ -9,6 +9,7 @@ export interface UserBean {
birthdayType: number;
card: string;
companyId: string;
companyName: string;
consumption: string;
consumptionDay: string;
couponsCount: number;