待商榷

pull/100/head
岳琳红 2024-08-30 18:00:28 +08:00
parent 2396819644
commit a6543dc7ca
10 changed files with 1121 additions and 788 deletions

View File

@ -123,6 +123,7 @@
if (code !== 0) { if (code !== 0) {
return; return;
} }
console.log('nibuhao ')
state.pagination.list = _.concat(state.pagination.list, data.list); state.pagination.list = _.concat(state.pagination.list, data.list);
state.pagination.total = data.total; state.pagination.total = data.total;
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore'; state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';

View File

@ -8,13 +8,43 @@
<detailSkeleton v-if="state.skeletonLoading" /> <detailSkeleton v-if="state.skeletonLoading" />
<!-- 下架/售罄提醒 --> <!-- 下架/售罄提醒 -->
<s-empty v-else-if="state.goodsInfo === null" text="商品不存在或已下架" icon="/static/soldout-empty.png" showAction <s-empty v-else-if="state.goodsInfo === null" text="商品不存在或已下架" icon="/static/soldout-empty.png" showAction
actionText="再逛逛" actionUrl="/pages/goods/list" /> actionText="再逛逛" actionUrl="/pages/goods/list" />
<block v-else> <block v-else>
<view class="detail-swiper-selector"> <view class="detail-swiper-selector">
<!-- 商品轮播图 --> <!-- 商品轮播图 -->
<su-swiper class="ss-m-b-14" isPreview :list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)" <su-swiper class="ss-m-b-14" isPreview :list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)"
otStyle="tag" imageMode="widthFix" dotCur="bg-mask-40" :seizeHeight="750" /> otStyle="tag" imageMode="widthFix" dotCur="bg-mask-40" :seizeHeight="750" />
<!-- 限时折扣 -->
<view class="discount">
<image class="disImg" src="../../static/images/dis.png"></image>
<view class="discountCont">
<view class="disContT">
<view class="disContT1">
<view class="disContT1P">
0.7
</view>
<view class="disContT1End">
限时到手0.4
</view>
</view>
<view class="disContT2">
限时折扣
</view>
</view>
<view class="disContB">
<view class="disContB1">
价格1 剩余100
</view>
<view class="disContB2">
距结束仅剩
<countDown :tipText="' '" :bgColor="bgColor" :dayText="':'" :hourText="':'"
:minuteText="':'" :secondText="' '" :datatime="1725033600000 / 1000"
:isDay="false" />
</view>
</view>
</view>
</view>
<!-- 限时折扣 -->
<!-- 价格+标题 --> <!-- 价格+标题 -->
<view class="title-card detail-card ss-p-y-40 ss-p-x-20"> <view class="title-card detail-card ss-p-y-40 ss-p-x-20">
<view class="ss-flex ss-row-between ss-col-center ss-m-b-26"> <view class="ss-flex ss-row-between ss-col-center ss-m-b-26">
@ -34,15 +64,15 @@
<!-- 满减送/限时折扣活动的提示 --> <!-- 满减送/限时折扣活动的提示 -->
<div class="tag-content"> <div class="tag-content">
<view class="tag-box ss-flex"> <view class="tag-box ss-flex">
<view class="tag ss-m-r-10" v-for="promos in state.activityInfo" <view class="tag ss-m-r-10" v-for="promos in state.activityInfo" :key="promos.id"
:key="promos.id" @tap="onActivity"> @tap="onActivity">
{{ promos.name }} {{ promos.name }}
</view> </view>
</view> </view>
</div> </div>
<!-- 优惠劵 --> <!-- 优惠劵@tap="state.showModel = true" -->
<view class="get-coupon-box ss-flex ss-col-center ss-m-l-20" @tap="state.showModel = true" <view class="get-coupon-box ss-flex ss-col-center ss-m-l-20" @tap="onActivity"
v-if="state.couponInfo.length"> v-if="state.couponInfo.length">
<view class="discounts-title ss-m-r-8">领券</view> <view class="discounts-title ss-m-r-8">领券</view>
<text class="cicon-forward"></text> <text class="cicon-forward"></text>
@ -55,12 +85,12 @@
<!-- 功能卡片 --> <!-- 功能卡片 -->
<view class="detail-cell-card detail-card ss-flex-col"> <view class="detail-cell-card detail-card ss-flex-col">
<detail-cell-sku v-model="state.selectedSku.goods_sku_text" :sku="state.selectedSku" <detail-cell-sku v-model="state.selectedSku.goods_sku_text" :sku="state.selectedSku"
@tap="state.showSelectSku = true" /> @tap="state.showSelectSku = true" />
</view> </view>
<!-- 规格与数量弹框 --> <!-- 规格与数量弹框 -->
<s-select-sku :goodsInfo="state.goodsInfo" :show="state.showSelectSku" @addCart="onAddCart" <s-select-sku :goodsInfo="state.goodsInfo" :show="state.showSelectSku" @addCart="onAddCart"
@buy="onBuy" @change="onSkuChange" @close="state.showSelectSku = false" /> @buy="onBuy" @change="onSkuChange" @close="state.showSelectSku = false" />
</view> </view>
<!-- 评价 --> <!-- 评价 -->
@ -87,25 +117,36 @@
</detail-tabbar> </detail-tabbar>
<!-- 优惠劵弹窗 --> <!-- 优惠劵弹窗 -->
<s-coupon-get v-model="state.couponInfo" :show="state.showModel" @close="state.showModel = false" <!-- <s-coupon-get v-model="state.couponInfo" :show="state.showModel" @close="state.showModel = false"
@get="onGet" /> @get="onGet" /> -->
<!-- 满减送/限时折扣活动弹窗 --> <!-- 满减送/限时折扣活动弹窗 -->
<s-activity-pop v-model="state.activityInfo" :show="state.showActivityModel" <s-activity-pop v-model="state.activityInfo" :show="state.showActivityModel"
@close="state.showActivityModel = false" /> @close="state.showActivityModel = false" />
</block> </block>
</s-layout> </s-layout>
</view> </view>
</template> </template>
<script setup> <script setup>
import { reactive, computed } from 'vue'; import {
import { onLoad, onPageScroll } from '@dcloudio/uni-app'; reactive,
computed,
ref
} from 'vue';
import {
onLoad,
onPageScroll
} from '@dcloudio/uni-app';
import sheep from '@/sheep'; import sheep from '@/sheep';
import CouponApi from '@/sheep/api/promotion/coupon'; import CouponApi from '@/sheep/api/promotion/coupon';
import ActivityApi from '@/sheep/api/promotion/activity'; import ActivityApi from '@/sheep/api/promotion/activity';
import FavoriteApi from '@/sheep/api/product/favorite'; import FavoriteApi from '@/sheep/api/product/favorite';
import { formatSales, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods'; import {
formatSales,
formatGoodsSwiper,
fen2yuan
} from '@/sheep/hooks/useGoods';
import detailNavbar from './components/detail/detail-navbar.vue'; import detailNavbar from './components/detail/detail-navbar.vue';
import detailCellSku from './components/detail/detail-cell-sku.vue'; import detailCellSku from './components/detail/detail-cell-sku.vue';
import detailTabbar from './components/detail/detail-tabbar.vue'; import detailTabbar from './components/detail/detail-tabbar.vue';
@ -113,13 +154,22 @@
import detailCommentCard from './components/detail/detail-comment-card.vue'; import detailCommentCard from './components/detail/detail-comment-card.vue';
import detailContentCard from './components/detail/detail-content-card.vue'; import detailContentCard from './components/detail/detail-content-card.vue';
import detailActivityTip from './components/detail/detail-activity-tip.vue'; import detailActivityTip from './components/detail/detail-activity-tip.vue';
import { isEmpty } from 'lodash-es'; import {
import SpuApi from '@/sheep/api/product/spu'; isEmpty
} from 'lodash-es';
import SpuApi from '@/sheep/api/product/spu';
onPageScroll(() => {}); onPageScroll(() => {});
import countDown from '@/sheep/components/countDown/index.vue'
const isLogin = computed(() => sheep.$store('user').isLogin); const bgColor = {
const state = reactive({ 'bgColor': '#E93323',
'Color': '#fff',
'width': '44rpx',
'timeTxtwidth': '16rpx',
'isDay': true
}
const isLogin = computed(() => sheep.$store('user').isLogin);
const state = reactive({
goodsId: 0, goodsId: 0,
skeletonLoading: true, // SPU skeletonLoading: true, // SPU
goodsInfo: {}, // SPU goodsInfo: {}, // SPU
@ -139,28 +189,28 @@
// //
function onAddCart(e) { function onAddCart(e) {
if (!e.id) { if (!e.id) {
sheep.$helper.toast('请选择商品规格'); sheep.$helper.toast('请选择商品规格');
return; return;
} }
sheep.$store('cart').add(e); sheep.$store('cart').add(e);
} }
// //
function onBuy(e) { function onBuy(e) {
if (!state.selectedSku.id) { if (!state.selectedSku.id) {
sheep.$helper.toast('请选择商品规格'); sheep.$helper.toast('请选择商品规格');
return; return;
} }
sheep.$router.go('/pages/order/confirm', { sheep.$router.go('/pages/order/confirm', {
data: JSON.stringify({ data: JSON.stringify({
items: [{ items: [{
skuId: e.id, skuId: e.id,
count: e.goods_num, count: e.goods_num,
categoryId: state.goodsInfo.categoryId categoryId: state.goodsInfo.categoryId
}] }]
}), }),
}); });
} }
// //
@ -170,16 +220,18 @@
// //
async function onGet(id) { async function onGet(id) {
const { code } = await CouponApi.takeCoupon(id); const {
if (code !== 0) { code
return; } = await CouponApi.takeCoupon(id);
} if (code !== 0) {
uni.showToast({ return;
title: '领取成功', }
}); uni.showToast({
setTimeout(() => { title: '领取成功',
getCoupon(); });
}, 1000); setTimeout(() => {
getCoupon();
}, 1000);
} }
// TODO // TODO
@ -202,13 +254,23 @@
}); });
}); });
async function getCoupon() { async function getCoupon() {
const { code, data } = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10); const {
if (code === 0) { code,
state.couponInfo = data; data
} } = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10);
} if (code === 0) {
state.couponInfo = data;
}
}
//
const settleData = ref()
async function getSettlementByIds(ids) {
const { data } = await SpuApi.getSettlementProduct(ids);
settleData.value = data
console.log('结算信息',data)
return data;
}
onLoad((options) => { onLoad((options) => {
// //
if (!options.id) { if (!options.id) {
@ -226,36 +288,38 @@
// //
state.skeletonLoading = false; state.skeletonLoading = false;
state.goodsInfo = res.data; state.goodsInfo = res.data;
console.log('sku',res.data)
// //
if (isLogin.value) { if (isLogin.value) {
FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => { FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
if (res.code !== 0) { if (res.code !== 0) {
return; return;
} }
state.goodsInfo.favorite = res.data; state.goodsInfo.favorite = res.data;
}); });
} }
}); });
// 2. // 2.
getCoupon(); getCoupon();
// 3. // 3.
ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => { ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
if (res.code !== 0) { if (res.code !== 0) {
return; return;
} }
res.data.forEach(activity => { res.data.forEach(activity => {
if ([1, 2, 3].includes(activity.type)) { // // if ([1, 2, 3].includes(activity.type)) { // //
state.activityList.push(activity); state.activityList.push(activity);
} else if (activity.type === 5) { // } else if (activity.type === 5) { //
state.activityInfo.push(activity); state.activityInfo.push(activity);
} else { // TODO } else { // TODO
console.log('待实现!优先级不高'); console.log('待实现!优先级不高');
} }
}) })
}); });
//
getSettlementByIds(state.goodsId)
}); });
</script> </script>
@ -404,4 +468,101 @@
color: #333333; color: #333333;
} }
} }
</style>
//
.discount {
width: 750rpx;
height: 100rpx;
// background-color: red;
overflow: hidden;
position: relative;
}
.disImg {
width: 750rpx;
height: 100rpx;
position: absolute;
top: 0;
z-index: -1;
}
.discountCont {
width: 680rpx;
height: 90rpx;
margin: 10rpx auto 0 auto;
// background-color: gold;
}
.disContT {
width: 680rpx;
height: 50rpx;
display: flex;
justify-content: space-between;
}
.disContT1 {
width: 300rpx;
height: 50rpx;
// background-color: green;
display: flex;
justify-content: flex-start;
align-items: center;
}
.disContT2 {
width: 300rpx;
height: 50rpx;
line-height: 50rpx;
// background-color: green;
font-size: 30rpx;
text-align: end;
color: white;
font-weight: bolder;
font-style: oblique 20deg;
letter-spacing: .1rem;
}
.disContT1P {
color: white;
font-weight: bold;
font-size: 28rpx;
}
.disContT1End {
// width: 180rpx;
padding: 0 10rpx;
height: 30rpx;
line-height: 28rpx;
text-align: center;
font-weight: bold;
background-color: white;
color: #ff3000;
font-size: 23rpx;
border-radius: 20rpx;
margin-left: 10rpx;
}
.disContB {
width: 680rpx;
height: 40rpx;
display: flex;
justify-content: space-between;
font-size: 20rpx;
color: white;
align-items: center;
}
.disContB1 {
width: 300rpx;
height: 40rpx;
line-height: 40rpx;
}
.disContB2 {
width: 300rpx;
height: 40rpx;
line-height: 40rpx;
display: flex;
justify-content: flex-end;
}
</style>

View File

@ -118,7 +118,7 @@
</template> </template>
<script setup> <script setup>
import { reactive } from 'vue'; import { reactive,ref } from 'vue';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import sheep from '@/sheep'; import sheep from '@/sheep';
import _ from 'lodash-es'; import _ from 'lodash-es';
@ -277,7 +277,16 @@
if (code !== 0) { if (code !== 0) {
return; return;
} }
state.pagination.list = _.concat(state.pagination.list, data.list); console.log('数据流',data)
// 使 map id
const ids = data.list.map(item => item.id);
// 使 join id
const idsString = ids.join(',');
//
settleData.value = await getSettlementByIds(idsString)
//
const ms = enrichDataWithSkus(data.list,settleData.value)
state.pagination.list = _.concat(state.pagination.list, ms);
state.pagination.total = data.total; state.pagination.total = data.total;
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore'; state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
mountMasonry(); mountMasonry();
@ -291,7 +300,55 @@
state.pagination.pageNo++; state.pagination.pageNo++;
getList(state.currentSort, state.currentOrder); getList(state.currentSort, state.currentOrder);
} }
//
const settleData = ref()
async function getSettlementByIds(ids) {
const { data } = await SpuApi.getSettlementProduct(ids);
// console.log('',data)
return data;
}
//
function enrichDataWithSkus(data, array) {
// id data
const dataMap = new Map(data.map(item => [item.id, { ...item }]));
// array
array.forEach(item => {
// discountPrice vipPrice null
let discountPrice = null;
let vipPrice = null;
let foundType4 = false;
let foundType6 = false;
// skus type 4 6
item.skus.forEach(sku => {
if (!foundType4 && sku.type === 4) {
discountPrice = sku.price;
foundType4 = true;
}
if (!foundType6 && sku.type === 6) {
vipPrice = sku.price;
foundType6 = true;
}
// type 4 6
if (foundType4 && foundType6) {
return;
}
});
// dataMap
if (dataMap.has(item.id)) {
dataMap.get(item.id).discountPrice = discountPrice;
dataMap.get(item.id).vipPrice = vipPrice;
dataMap.get(item.id).reward = item.reward;
}
});
//
return Array.from(dataMap.values());
}
onLoad((options) => { onLoad((options) => {
state.categoryId = options.categoryId; state.categoryId = options.categoryId;
state.keyword = options.keyword; state.keyword = options.keyword;

View File

@ -90,6 +90,7 @@
if (code !== 0) { if (code !== 0) {
return; return;
} }
console.log('nihao ')
state.categoryList = handleTree(data); state.categoryList = handleTree(data);
} }

View File

@ -13,6 +13,18 @@ const SpuApi = {
}, },
}); });
}, },
// 获得商品结算信息
getSettlementProduct: (ids) => {
return request({
url: '/trade/order/settlementProduct',
method: 'GET',
params: { ids },
custom: {
showLoading: false,
showError: false,
},
});
},
// 获得商品 SPU 分页 // 获得商品 SPU 分页
getSpuPage: (params) => { getSpuPage: (params) => {
return request({ return request({

View File

@ -2,20 +2,23 @@
<template> <template>
<su-popup :show="show" type="bottom" round="20" @close="emits('close')" showClose> <su-popup :show="show" type="bottom" round="20" @close="emits('close')" showClose>
<view class="model-box"> <view class="model-box">
<view class="title ss-m-t-16 ss-m-l-20 ss-flex">营销活动</view> <view class="title ss-m-t-16 ss-m-l-20 ss-flex">优惠</view>
<scroll-view <scroll-view
class="model-content ss-m-t-50" class="model-content ss-m-t-50"
scroll-y scroll-y
:scroll-with-animation="false" :scroll-with-animation="false"
:enable-back-to-top="true" :enable-back-to-top="true"
> >
<view v-for="item in state.activityInfo" :key="item.id"> <view class="actBox" v-for="item in state.activityInfo" :key="item.id">
<view class="ss-flex ss-col-top ss-m-b-40" @tap="onGoodsList(item)"> <view class="boxCont ss-flex ss-col-top ss-m-b-40" @tap="onGoodsList(item)">
<view class="model-content-tag ss-flex ss-row-center">满减</view> <view class="model-content-tag ss-flex ss-row-center">活动</view>
<view class="ss-m-l-20 model-content-title ss-flex-1"> <view class="ss-m-l-20 model-content-title ss-flex-1">
<view class="ss-m-b-24" v-for="rule in state.activityMap[item.id]?.rules" :key="rule"> <view class="contBu ss-m-b-24" v-for="rule in state.activityMap[item.id]?.rules" :key="rule">
{{ formatRewardActivityRule(state.activityMap[item.id], rule) }} {{ formatRewardActivityRule(state.activityMap[item.id], rule) }}
</view> </view>
<view class="contBu ss-m-b-24">
2024.08.05-2025.10.10
</view>
</view> </view>
<text class="cicon-forward" /> <text class="cicon-forward" />
</view> </view>
@ -45,7 +48,7 @@
activityInfo: computed(() => props.modelValue), activityInfo: computed(() => props.modelValue),
activityMap: {} activityMap: {}
}); });
console.log('shuju',state)
watch( watch(
() => props.show, () => props.show,
() => { () => {
@ -73,6 +76,7 @@
.model-box { .model-box {
height: 60vh; height: 60vh;
.title { .title {
justify-content: center;
font-size: 36rpx; font-size: 36rpx;
height: 80rpx; height: 80rpx;
font-weight: bold; font-weight: bold;
@ -80,26 +84,50 @@
} }
} }
.model-content { .model-content {
height: 300rpx;
padding: 0 20rpx; padding: 0 20rpx;
box-sizing: border-box; box-sizing: border-box;
background-color: red;
.model-content-tag { .model-content-tag {
background: rgba(#ff6911, 0.1); // background: rgba(#ff6911, 0.1);
font-size: 24rpx; font-size: 35rpx;
font-weight: 500; font-weight: 500;
color: #ff6911; color: #ff6911;
line-height: 42rpx; line-height: 150rpx;
width: 68rpx; width: 150rpx;
height: 32rpx; height: 150rpx;
border-radius: 5rpx; text-align: center;
// border-radius: 5rpx;
} }
.model-content-title { .model-content-title {
height: 150rpx;
font-size: 26rpx; font-size: 26rpx;
font-weight: 500; font-weight: 500;
color: #333333; color: #333333;
background-color: gold;
overflow: hidden;
} }
.cicon-forward { .cicon-forward {
font-size: 28rpx; font-size: 28rpx;
color: #999999; color: #999999;
} }
} }
//
.actBox{
width: 700rpx;
height: 150rpx;
background-color: #fff2f2;
margin: 10rpx auto;
border-radius: 10rpx;
}
.boxCont{
width: 700rpx;
height: 150rpx;
align-items: center;
}
.contBu{
height: 75rpx;
line-height: 75rpx;
}
</style> </style>

View File

@ -135,7 +135,7 @@
/** /**
* 商品卡片 * 商品卡片
*/ */
import { computed, reactive, onMounted } from 'vue'; import { computed, reactive, onMounted,ref } from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import SpuApi from '@/sheep/api/product/spu'; import SpuApi from '@/sheep/api/product/spu';
@ -202,6 +202,8 @@
*/ */
function calculateGoodsColumn(height = 0, where = 'left') { function calculateGoodsColumn(height = 0, where = 'left') {
// //
console.log('用来处理的数据',state.goodsList)
console.log(11111)
if (!state.goodsList[count]) return; if (!state.goodsList[count]) return;
// //
if (where === 'left') leftHeight += height; if (where === 'left') leftHeight += height;
@ -224,16 +226,69 @@
*/ */
async function getGoodsListByIds(ids) { async function getGoodsListByIds(ids) {
const { data } = await SpuApi.getSpuListByIds(ids); const { data } = await SpuApi.getSpuListByIds(ids);
// console.log('',data)
return data; return data;
} }
//
const settleData = ref()
async function getSettlementByIds(ids) {
const { data } = await SpuApi.getSettlementProduct(ids);
// console.log('',data)
return data;
}
//
function enrichDataWithSkus(data, array) {
// id data
const dataMap = new Map(data.map(item => [item.id, { ...item }]));
// array
array.forEach(item => {
// discountPrice vipPrice null
let discountPrice = null;
let vipPrice = null;
let foundType4 = false;
let foundType6 = false;
// skus type 4 6
item.skus.forEach(sku => {
if (!foundType4 && sku.type === 4) {
discountPrice = sku.price;
foundType4 = true;
}
if (!foundType6 && sku.type === 6) {
vipPrice = sku.price;
foundType6 = true;
}
// type 4 6
if (foundType4 && foundType6) {
return;
}
});
// dataMap
if (dataMap.has(item.id)) {
dataMap.get(item.id).discountPrice = discountPrice;
dataMap.get(item.id).vipPrice = vipPrice;
dataMap.get(item.id).reward = item.reward;
}
});
//
return Array.from(dataMap.values());
}
// //
onMounted(async () => { onMounted(async () => {
// //
state.goodsList = await getGoodsListByIds(spuIds.join(',')); const ms = await getGoodsListByIds(spuIds.join(','));
settleData.value = await getSettlementByIds(spuIds.join(','))
state.goodsList = await enrichDataWithSkus(ms,settleData.value)
// console.log('',state.goodsList)
// //
if (layoutType === LayoutTypeEnum.TWO_COL){ if (layoutType === LayoutTypeEnum.TWO_COL){
// //
console.log('用来分流的数据',state.goodsList)
calculateGoodsColumn(); calculateGoodsColumn();
} }
}); });

File diff suppressed because it is too large Load Diff

View File

@ -82,7 +82,7 @@
}); });
const propertyList = convertProductPropertyList(props.goodsInfo.skus); const propertyList = convertProductPropertyList(props.goodsInfo.skus);
console.log('传递来的sku信息',props.goodsInfo.skus)
// SKU // SKU
const skuList = computed(() => { const skuList = computed(() => {
let skuPrices = props.goodsInfo.skus; let skuPrices = props.goodsInfo.skus;

BIN
static/images/dis.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB