待商榷

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) {
return;
}
console.log('nibuhao ')
state.pagination.list = _.concat(state.pagination.list, data.list);
state.pagination.total = data.total;
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';

View File

@ -8,13 +8,43 @@
<detailSkeleton v-if="state.skeletonLoading" />
<!-- 下架/售罄提醒 -->
<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>
<view class="detail-swiper-selector">
<!-- 商品轮播图 -->
<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="ss-flex ss-row-between ss-col-center ss-m-b-26">
@ -34,15 +64,15 @@
<!-- 满减送/限时折扣活动的提示 -->
<div class="tag-content">
<view class="tag-box ss-flex">
<view class="tag ss-m-r-10" v-for="promos in state.activityInfo"
:key="promos.id" @tap="onActivity">
<view class="tag ss-m-r-10" v-for="promos in state.activityInfo" :key="promos.id"
@tap="onActivity">
{{ promos.name }}
</view>
</view>
</div>
<!-- 优惠劵 -->
<view class="get-coupon-box ss-flex ss-col-center ss-m-l-20" @tap="state.showModel = true"
<!-- 优惠劵@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">
<view class="discounts-title ss-m-r-8">领券</view>
<text class="cicon-forward"></text>
@ -55,12 +85,12 @@
<!-- 功能卡片 -->
<view class="detail-cell-card detail-card ss-flex-col">
<detail-cell-sku v-model="state.selectedSku.goods_sku_text" :sku="state.selectedSku"
@tap="state.showSelectSku = true" />
@tap="state.showSelectSku = true" />
</view>
<!-- 规格与数量弹框 -->
<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>
<!-- 评价 -->
@ -87,25 +117,36 @@
</detail-tabbar>
<!-- 优惠劵弹窗 -->
<s-coupon-get v-model="state.couponInfo" :show="state.showModel" @close="state.showModel = false"
@get="onGet" />
<!-- <s-coupon-get v-model="state.couponInfo" :show="state.showModel" @close="state.showModel = false"
@get="onGet" /> -->
<!-- 满减送/限时折扣活动弹窗 -->
<s-activity-pop v-model="state.activityInfo" :show="state.showActivityModel"
@close="state.showActivityModel = false" />
@close="state.showActivityModel = false" />
</block>
</s-layout>
</view>
</template>
<script setup>
import { reactive, computed } from 'vue';
import { onLoad, onPageScroll } from '@dcloudio/uni-app';
import {
reactive,
computed,
ref
} from 'vue';
import {
onLoad,
onPageScroll
} from '@dcloudio/uni-app';
import sheep from '@/sheep';
import CouponApi from '@/sheep/api/promotion/coupon';
import ActivityApi from '@/sheep/api/promotion/activity';
import FavoriteApi from '@/sheep/api/product/favorite';
import { formatSales, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods';
import FavoriteApi from '@/sheep/api/product/favorite';
import {
formatSales,
formatGoodsSwiper,
fen2yuan
} from '@/sheep/hooks/useGoods';
import detailNavbar from './components/detail/detail-navbar.vue';
import detailCellSku from './components/detail/detail-cell-sku.vue';
import detailTabbar from './components/detail/detail-tabbar.vue';
@ -113,13 +154,22 @@
import detailCommentCard from './components/detail/detail-comment-card.vue';
import detailContentCard from './components/detail/detail-content-card.vue';
import detailActivityTip from './components/detail/detail-activity-tip.vue';
import { isEmpty } from 'lodash-es';
import SpuApi from '@/sheep/api/product/spu';
import {
isEmpty
} from 'lodash-es';
import SpuApi from '@/sheep/api/product/spu';
onPageScroll(() => {});
const isLogin = computed(() => sheep.$store('user').isLogin);
const state = reactive({
import countDown from '@/sheep/components/countDown/index.vue'
const bgColor = {
'bgColor': '#E93323',
'Color': '#fff',
'width': '44rpx',
'timeTxtwidth': '16rpx',
'isDay': true
}
const isLogin = computed(() => sheep.$store('user').isLogin);
const state = reactive({
goodsId: 0,
skeletonLoading: true, // SPU
goodsInfo: {}, // SPU
@ -139,28 +189,28 @@
//
function onAddCart(e) {
if (!e.id) {
sheep.$helper.toast('请选择商品规格');
return;
}
if (!e.id) {
sheep.$helper.toast('请选择商品规格');
return;
}
sheep.$store('cart').add(e);
}
//
function onBuy(e) {
if (!state.selectedSku.id) {
sheep.$helper.toast('请选择商品规格');
return;
}
sheep.$router.go('/pages/order/confirm', {
data: JSON.stringify({
items: [{
skuId: e.id,
count: e.goods_num,
categoryId: state.goodsInfo.categoryId
}]
}),
});
if (!state.selectedSku.id) {
sheep.$helper.toast('请选择商品规格');
return;
}
sheep.$router.go('/pages/order/confirm', {
data: JSON.stringify({
items: [{
skuId: e.id,
count: e.goods_num,
categoryId: state.goodsInfo.categoryId
}]
}),
});
}
//
@ -170,16 +220,18 @@
//
async function onGet(id) {
const { code } = await CouponApi.takeCoupon(id);
if (code !== 0) {
return;
}
uni.showToast({
title: '领取成功',
});
setTimeout(() => {
getCoupon();
}, 1000);
const {
code
} = await CouponApi.takeCoupon(id);
if (code !== 0) {
return;
}
uni.showToast({
title: '领取成功',
});
setTimeout(() => {
getCoupon();
}, 1000);
}
// TODO
@ -202,13 +254,23 @@
});
});
async function getCoupon() {
const { code, data } = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10);
if (code === 0) {
state.couponInfo = data;
}
}
async function getCoupon() {
const {
code,
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) => {
//
if (!options.id) {
@ -226,36 +288,38 @@
//
state.skeletonLoading = false;
state.goodsInfo = res.data;
//
if (isLogin.value) {
FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
if (res.code !== 0) {
return;
}
state.goodsInfo.favorite = res.data;
});
}
console.log('sku',res.data)
//
if (isLogin.value) {
FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
if (res.code !== 0) {
return;
}
state.goodsInfo.favorite = res.data;
});
}
});
// 2.
getCoupon();
getCoupon();
// 3.
ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
if (res.code !== 0) {
return;
}
res.data.forEach(activity => {
if ([1, 2, 3].includes(activity.type)) { // //
state.activityList.push(activity);
} else if (activity.type === 5) { //
state.activityInfo.push(activity);
} else { // TODO
console.log('待实现!优先级不高');
}
})
res.data.forEach(activity => {
if ([1, 2, 3].includes(activity.type)) { // //
state.activityList.push(activity);
} else if (activity.type === 5) { //
state.activityInfo.push(activity);
} else { // TODO
console.log('待实现!优先级不高');
}
})
});
//
getSettlementByIds(state.goodsId)
});
</script>
@ -404,4 +468,101 @@
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>
<script setup>
import { reactive } from 'vue';
import { reactive,ref } from 'vue';
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import sheep from '@/sheep';
import _ from 'lodash-es';
@ -277,7 +277,16 @@
if (code !== 0) {
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.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
mountMasonry();
@ -291,7 +300,55 @@
state.pagination.pageNo++;
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) => {
state.categoryId = options.categoryId;
state.keyword = options.keyword;

View File

@ -90,6 +90,7 @@
if (code !== 0) {
return;
}
console.log('nihao ')
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 分页
getSpuPage: (params) => {
return request({

View File

@ -2,20 +2,23 @@
<template>
<su-popup :show="show" type="bottom" round="20" @close="emits('close')" showClose>
<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
class="model-content ss-m-t-50"
scroll-y
:scroll-with-animation="false"
:enable-back-to-top="true"
>
<view 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="model-content-tag ss-flex ss-row-center">满减</view>
<view class="actBox" v-for="item in state.activityInfo" :key="item.id">
<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="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) }}
</view>
<view class="contBu ss-m-b-24">
2024.08.05-2025.10.10
</view>
</view>
<text class="cicon-forward" />
</view>
@ -45,7 +48,7 @@
activityInfo: computed(() => props.modelValue),
activityMap: {}
});
console.log('shuju',state)
watch(
() => props.show,
() => {
@ -73,6 +76,7 @@
.model-box {
height: 60vh;
.title {
justify-content: center;
font-size: 36rpx;
height: 80rpx;
font-weight: bold;
@ -80,26 +84,50 @@
}
}
.model-content {
height: 300rpx;
padding: 0 20rpx;
box-sizing: border-box;
background-color: red;
.model-content-tag {
background: rgba(#ff6911, 0.1);
font-size: 24rpx;
// background: rgba(#ff6911, 0.1);
font-size: 35rpx;
font-weight: 500;
color: #ff6911;
line-height: 42rpx;
width: 68rpx;
height: 32rpx;
border-radius: 5rpx;
line-height: 150rpx;
width: 150rpx;
height: 150rpx;
text-align: center;
// border-radius: 5rpx;
}
.model-content-title {
height: 150rpx;
font-size: 26rpx;
font-weight: 500;
color: #333333;
background-color: gold;
overflow: hidden;
}
.cicon-forward {
font-size: 28rpx;
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>

View File

@ -135,7 +135,7 @@
/**
* 商品卡片
*/
import { computed, reactive, onMounted } from 'vue';
import { computed, reactive, onMounted,ref } from 'vue';
import sheep from '@/sheep';
import SpuApi from '@/sheep/api/product/spu';
@ -202,6 +202,8 @@
*/
function calculateGoodsColumn(height = 0, where = 'left') {
//
console.log('用来处理的数据',state.goodsList)
console.log(11111)
if (!state.goodsList[count]) return;
//
if (where === 'left') leftHeight += height;
@ -224,16 +226,69 @@
*/
async function getGoodsListByIds(ids) {
const { data } = await SpuApi.getSpuListByIds(ids);
// console.log('',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 () => {
//
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){
//
console.log('用来分流的数据',state.goodsList)
calculateGoodsColumn();
}
});

File diff suppressed because it is too large Load Diff

View File

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

BIN
static/images/dis.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB