购物车逻辑完善
个人信息存储优化 团购支付
This commit is contained in:
@@ -16,8 +16,8 @@
|
||||
超级\n秒杀
|
||||
</view>
|
||||
<view class='price c-flex-column' style='flex: 1'>
|
||||
<text>{{ detailBean?.payPrice || 0 }}</text>
|
||||
<text>¥{{ detailBean?.goodsPrice || 0 }}</text>
|
||||
<text>{{ groupBuyBean?.payPrice || 0 }}</text>
|
||||
<text>¥{{ groupBuyBean?.price || 0 }}</text>
|
||||
</view>
|
||||
<view class='countdown-time c-flex-column'>
|
||||
<view class='c-flex-row'>{{ countdownTime?.days || 0 }}天
|
||||
@@ -33,12 +33,12 @@
|
||||
|
||||
<view class='goods-info-view c-flex-column'>
|
||||
<view class='c-flex-row'>
|
||||
<text class='goods-price accent-text-color'>{{ detailBean?.payPrice || 0 }}</text>
|
||||
<text>销量{{ detailBean?.totalNum || 0 }}</text>
|
||||
<text class='goods-price accent-text-color'>{{ groupBuyBean?.payPrice || 0 }}</text>
|
||||
<text>销量{{ groupBuyBean?.totalNum || 0 }}</text>
|
||||
</view>
|
||||
|
||||
<view class='c-flex-row'>
|
||||
<text style='flex: 1'>{{ detailBean?.name }}</text>
|
||||
<text style='flex: 1'>{{ groupBuyBean?.name }}</text>
|
||||
<view class='share-button c-flex-column'>
|
||||
<image :src='assetsUrl("ic_share.png")'></image>
|
||||
<button class='btn' plain open-type='share'>分享</button>
|
||||
@@ -51,7 +51,7 @@
|
||||
<text>选择</text>
|
||||
<text>规格 颜色/尺码</text>
|
||||
<image :src='assetsUrl("ic_arrow_right_gray.png")' />
|
||||
<text>共1种颜色可选</text>
|
||||
<text>共{{ getStockColorCount }}种颜色可选</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -70,27 +70,27 @@
|
||||
</view>
|
||||
|
||||
<!-- 商品详情图片 -->
|
||||
<view class='card-view image-container' v-if='detailBean?.content'>
|
||||
<view class='card-view image-container' v-if='groupBuyBean?.content'>
|
||||
<text class='card-view-title'>商品详情</text>
|
||||
<image
|
||||
v-for='(item,index) in JSON.parse(detailBean?.content).filter((a: any) => a.type === 2).map((b: any) => b.images)'
|
||||
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='c-flex-row'>
|
||||
<image :src='detailBean?.goods?.images' />
|
||||
<image :src='groupBuyBean?.goods?.images' />
|
||||
<view class='c-flex-column'>
|
||||
<text class='goods-name'>{{ detailBean?.goods?.name }}</text>
|
||||
<text class='goods-name'>{{ groupBuyBean?.goods?.name }}</text>
|
||||
<text style='color: #a6a6a6'>精选</text>
|
||||
<view class='tag-view c-flex-row'>
|
||||
<text>团长推荐</text>
|
||||
<text>今日必买</text>
|
||||
</view>
|
||||
<text style='color: #a6a6a6'>不参与会员折扣</text>
|
||||
<text style='color: #F32B2B'>¥{{ detailBean?.goods?.payPrice }}</text>
|
||||
<text class='bought_count'>已团{{ detailBean?.sendNum }}</text>
|
||||
<text style='color: #F32B2B'>¥{{ groupBuyBean?.goods?.payPrice }}</text>
|
||||
<text class='bought_count'>已团{{ groupBuyBean?.sendNum }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -99,7 +99,7 @@
|
||||
<view class='card-view coupon-container'>
|
||||
<text class='card-view-title'>赠送优惠券</text>
|
||||
<view class='c-flex-column'>
|
||||
<coupon-item v-for='(item,index) in detailBean?.couponsList' :key='index' :item='item' />
|
||||
<coupon-item v-for='(item,index) in groupBuyBean?.couponsList' :key='index' :item='item' />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -125,13 +125,13 @@
|
||||
<view class='place-order-button' @click.stop='placeOrder'>跟团购买</view>
|
||||
</view>
|
||||
</view>
|
||||
<sku-dialog ref='skuDialogRef' :bean='detailBean?.goods' @confirm='confirmGoodsSku' />
|
||||
<sku-dialog ref='skuDialogRef' :flash-price='groupBuyBean?.payPrice || 0' />
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { assetsUrl } from '@/utils/assets';
|
||||
import dayjs from 'dayjs';
|
||||
import { goPath } from '@/utils';
|
||||
import { formatTimeWithZeroPad, goPath } from '@/utils';
|
||||
import SkuDialog from '@/components/sku-dialog.vue';
|
||||
import CouponItem from './components/coupon-item.vue';
|
||||
|
||||
@@ -139,33 +139,33 @@ import { getGroupBuyDetail, getGroupBuyRecordList, preOrder } from '@/api/groupb
|
||||
import { getGoodsList } from '@/api/goods';
|
||||
import { GoodsBean } from '@/api/goods/types';
|
||||
import { useUserStore } from '@/store';
|
||||
import { GroupBuyBean, RecordBean } from '@/api/groupbuy/types';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const { userInfo } = storeToRefs(userStore);
|
||||
|
||||
const skuDialogRef = ref();
|
||||
const detailBean = ref();
|
||||
const groupBuyBean = ref<GroupBuyBean>();
|
||||
const recommendList = ref<GoodsBean[]>();
|
||||
const skuBean = ref();
|
||||
|
||||
const bannerList = ref([]);
|
||||
const swiperIndex = ref(0);
|
||||
|
||||
let interval: number;
|
||||
const countdownTime = ref<{
|
||||
days: number,
|
||||
hours: number,
|
||||
minutes: number,
|
||||
seconds: number
|
||||
days: string,
|
||||
hours: string,
|
||||
minutes: string,
|
||||
seconds: string
|
||||
}>();
|
||||
|
||||
const recordList = ref([]);
|
||||
const recordList = ref<RecordBean[]>([]);
|
||||
const currentPageNum = ref(1);
|
||||
|
||||
onLoad(async (e: any) => {
|
||||
detailBean.value = await getGroupBuyDetail(e.id);
|
||||
detailBean.value.goods.price = detailBean.value.price;
|
||||
bannerList.value = JSON.parse(detailBean.value.content).filter((item: any) => item.type === 2).map((item: any) => item.images);
|
||||
groupBuyBean.value = await getGroupBuyDetail(e.id);
|
||||
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();
|
||||
await fetchRecommendList();
|
||||
await fetchBuyRecordList();
|
||||
@@ -177,6 +177,12 @@ onUnload(() => {
|
||||
}
|
||||
});
|
||||
|
||||
const getStockColorCount = computed(() => {
|
||||
const list = Array.from(new Set(groupBuyBean.value?.goods?.stocks?.map(item => item.colorName)))
|
||||
.map(colorName => groupBuyBean.value?.goods?.stocks?.find(item => item.colorName === colorName)!);
|
||||
return list.length;
|
||||
});
|
||||
|
||||
const fetchRecommendList = async () => {
|
||||
const { rows } = await getGoodsList({
|
||||
page: {
|
||||
@@ -195,7 +201,7 @@ const fetchBuyRecordList = async (refresh: boolean = true) => {
|
||||
if(!refresh) {
|
||||
currentPageNum.value += 1;
|
||||
}
|
||||
const { list } = await getGroupBuyRecordList(detailBean.value.id, currentPageNum.value, 20);
|
||||
const { list } = await getGroupBuyRecordList(groupBuyBean?.value?.id || '', currentPageNum.value, 20);
|
||||
recordList.value = recordList.value.concat(list);
|
||||
};
|
||||
|
||||
@@ -209,16 +215,16 @@ const swiperChange = (e: any) => {
|
||||
|
||||
const countdown = () => {
|
||||
interval = setInterval(() => {
|
||||
if(detailBean.value?.endDate) {
|
||||
if(groupBuyBean.value?.endDate) {
|
||||
let now = new Date();
|
||||
let end = dayjs(detailBean.value?.endDate).toDate().getTime();
|
||||
let end = dayjs(groupBuyBean.value?.endDate).toDate().getTime();
|
||||
let remaining = Math.floor((end - now.getTime()) / 1000);
|
||||
if(remaining > 0) {
|
||||
countdownTime.value = {
|
||||
days: Math.floor(remaining / 60 / 60 / 24),
|
||||
hours: Math.floor(remaining / 60 / 60 % 24),
|
||||
minutes: Math.floor(remaining / 60 % 60),
|
||||
seconds: Math.floor(remaining % 60)
|
||||
days: formatTimeWithZeroPad(Math.floor(remaining / 60 / 60 / 24)),
|
||||
hours: formatTimeWithZeroPad(Math.floor(remaining / 60 / 60 % 24)),
|
||||
minutes: formatTimeWithZeroPad(Math.floor(remaining / 60 % 60)),
|
||||
seconds: formatTimeWithZeroPad(Math.floor(remaining % 60))
|
||||
};
|
||||
} else {
|
||||
clearInterval(interval);
|
||||
@@ -228,31 +234,27 @@ const countdown = () => {
|
||||
};
|
||||
|
||||
const showSkuDialog = (fn: Function) => {
|
||||
skuDialogRef.value.show(fn);
|
||||
};
|
||||
|
||||
const confirmGoodsSku = (e: any) => {
|
||||
skuBean.value = e;
|
||||
skuDialogRef.value.show(groupBuyBean?.value?.goods?.goodsId, fn);
|
||||
};
|
||||
|
||||
const placeOrder = async () => {
|
||||
|
||||
async function create() {
|
||||
async function create(bean: GoodsBean) {
|
||||
const params = {
|
||||
'colorId': '1725029269178814466',
|
||||
'sizeId': '0',
|
||||
'goodsId': detailBean.value.goods.goodsId,
|
||||
'groupId': detailBean.value.id,
|
||||
'colorId': bean.checkedStock.colorId,
|
||||
'sizeId': bean.checkedStock.sizeId,
|
||||
'goodsId': groupBuyBean?.value?.goods.goodsId,
|
||||
'groupId': groupBuyBean?.value?.id,
|
||||
'memberId': userInfo.value.id,
|
||||
'shareId': '123456'
|
||||
};
|
||||
|
||||
const result = await preOrder(params);
|
||||
goPath('/pages/common/groupbuy/order');
|
||||
goPath(`/pages/common/groupbuy/order?orderBean=${encodeURIComponent(JSON.stringify(result))}`);
|
||||
}
|
||||
|
||||
showSkuDialog(() => {
|
||||
create();
|
||||
showSkuDialog((e: GoodsBean) => {
|
||||
create(e);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
@@ -360,7 +362,7 @@ const placeOrder = async () => {
|
||||
margin-left: 12rpx;
|
||||
margin-right: 12rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 7rpx 7rpx 7rpx 7rpx;
|
||||
border-radius: 7rpx;
|
||||
color: #F32B2B;
|
||||
}
|
||||
|
||||
@@ -467,7 +469,7 @@ const placeOrder = async () => {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
position: absolute;
|
||||
top: 40rpx;
|
||||
top: 50rpx;
|
||||
left: 100rpx;
|
||||
}
|
||||
}
|
||||
@@ -527,7 +529,7 @@ const placeOrder = async () => {
|
||||
|
||||
.bottom-view {
|
||||
background: #FFFFFF;
|
||||
padding: 20rpx 30rpx 78rpx 33rpx;
|
||||
padding: 20rpx 30rpx 78rpx 30rpx;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
@@ -2,21 +2,27 @@
|
||||
<view class='content'>
|
||||
|
||||
<view class='card-view'>
|
||||
<image class='goods-image' :src='assetsUrl("test_bg.png")' />
|
||||
<view class='c-flex-column' style='flex: 1'>
|
||||
<text class='goods-name'>商品名称</text>
|
||||
<text class='goods-sku'>颜色、尺码</text>
|
||||
</view>
|
||||
<template v-for='(item,index) in orderBean?.orderGoods' :key='index'>
|
||||
<image class='goods-image' :src='item?.images' />
|
||||
<view class='c-flex-column' style='flex: 1'>
|
||||
<text class='goods-name'>{{ item?.goodsName }}</text>
|
||||
<text class='goods-sku'>{{ item?.stockStock?.colorName }} {{ item?.stockStock?.sizeName }}</text>
|
||||
</view>
|
||||
|
||||
<view class='c-flex-column'>
|
||||
<text class='goods-num'>x1</text>
|
||||
<text class='goods-price'>¥100</text>
|
||||
</view>
|
||||
<view class='c-flex-column'>
|
||||
<text class='goods-num'>x{{ item?.goodsNum }}</text>
|
||||
<view class='c-flex-row'>
|
||||
<text class='goods-price' style='margin-right: 10rpx;text-decoration: line-through'>¥{{ item?.originPrice }}
|
||||
</text>
|
||||
<text class='goods-price'>¥{{ item?.consumePrice }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<view class='card-view'>
|
||||
<text style='flex: 1'>实付</text>
|
||||
<text style='color: #F32B2B'>¥100</text>
|
||||
<text style='color: #F32B2B'>¥{{ orderBean?.totalPrice || 0 }}</text>
|
||||
</view>
|
||||
|
||||
<view class='bottom-view c-flex-row'>
|
||||
@@ -27,12 +33,57 @@
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { pay, progress } from '@/api/groupbuy';
|
||||
import { OrderBean } from '@/api/groupbuy/types';
|
||||
import { parseParameter, sortASCII } from '@/utils';
|
||||
import { hexMD5 } from '@/utils/common/md5';
|
||||
import { useUserStore } from '@/store';
|
||||
|
||||
import { assetsUrl } from '@/utils/assets';
|
||||
const userState = useUserStore();
|
||||
const { terminalInfo } = storeToRefs(userState);
|
||||
|
||||
const orderBean = ref<OrderBean>();
|
||||
|
||||
onLoad((e: any) => {
|
||||
orderBean.value = JSON.parse(decodeURIComponent(e?.orderBean));
|
||||
});
|
||||
|
||||
const payment = () => {
|
||||
let signParams = {
|
||||
return_url: 'return_url',
|
||||
total_amount: orderBean.value?.totalPrice,
|
||||
client_sn: orderBean.value?.id,
|
||||
terminal_sn: terminalInfo.value.terminalSn,
|
||||
subject: 'subject',
|
||||
subject_img: 'subject_img',
|
||||
merchant_name: 'merchant_name',
|
||||
notify_url: 'https://www.baidu.com'
|
||||
};
|
||||
// signParams = util.sortASCII(signParams, true);
|
||||
sortASCII(signParams, true);
|
||||
//参数拼接
|
||||
// const signStr = util.pars(signParams) + '&key=' + terminalInfo.value.terminalKey;
|
||||
const signStr = parseParameter(signParams) + '&key=' + terminalInfo.value.terminalKey;
|
||||
console.log('签名字符串', signStr);
|
||||
// const sign = utilMd5.hexMD5(signStr).toUpperCase();
|
||||
const sign = hexMD5(signStr);
|
||||
|
||||
console.log('签名结果', sign);
|
||||
|
||||
const params = {
|
||||
'id': orderBean.value?.id,
|
||||
'orderSn': signParams.client_sn,
|
||||
'terminal_key': terminalInfo.value.terminalKey,
|
||||
'terminal_sn': terminalInfo.value.terminalSn
|
||||
};
|
||||
|
||||
progress(params);
|
||||
pay({
|
||||
'orderId': orderBean.value?.id,
|
||||
'result': JSON.stringify('{payResult:xxx}')
|
||||
});
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
|
Reference in New Issue
Block a user