Commit be7aa12c by 李嘉林

拼团组件

parent 168e2e23
<template>
<div
class="goods-item-child"
:class="datas.componentData['borderColorShow']? 'itemBorder': ''"
:style="{
'border-radius': getBorderRadius + 'em',
'border':'1px solid'+datas.componentData['borderColor'],
'--border_color': datas.componentData['borderColor'],
'box-shadow': datas.componentData['cardShadow']
? '0px 0px 5px ' +
datas.componentData['cardShadowSize'] +
'px #ccc'
: '',
}"
>
<div
class="imgBox slidebox1"
:style="{'background-color':datas.componentData['backgroundColorShow']?datas.componentData['backgroundColor']:''}"
>
<div
class="have-group"
v-if="datas.componentData['haveGroupShow'] &&items &&items['groupBuyFlag'] =='1'"
>
{{items &&items["haveGroupNum"]? items["haveGroupNum"]: "0"}}人已团
</div>
<div
class="goodsPicture"
v-if="items != null"
:style="{ padding: datas.componentData.imgSize }"
>
<div
class="angleSign"
v-if="angleSign && angleSignImg"
:style="{
width: angleSignSize + '%',
height: angleSignSize + '%',
}"
>
<image :src="angleSignImg" mode="widthFix"></image>
</div>
<image
mode="widthFix"
:src="items['coverImage'] ==''? items['productImgUrl']: items['coverImage']"
lazy-load
></image>
<!-- items.oversoldFlag==0&&items.totalQty-0<=0 -->
<div
class="whiteBg"
v-if="items &&items.oversoldFlag ==0 &&items.totalQty - 0 <= 0"
>
<div class="cover">
<!-- <p>商品</p>
<p>售罄</p>-->
<image
mode="heightFix"
v-if="items&&items.oversoldFlag==0&&items.totalQty-0<=0"
src="http://mayi-newshop.oss-cn-shanghai.aliyuncs.com/public/png/f254fe62-6dda-46f6-a2f4-a7b2aa0474df.png"
alt
></image>
</div>
</div>
</div>
<!-- <img
v-if="items!=null"
:src="items['coverImage'] | DFSImg(400,400)"
alt
:style="{'padding':datas.componentData.imgSize}"
/>-->
</div>
<div
:style="{
'text-align': datas.componentData['initcharAlign'],
}"
class="info"
>
<div
class="info-top"
style="overflow: hidden;display: flex;justify-content: space-between;"
>
<p
class="name"
:style="{color: datas.componentData['nameColor'],fontWeight: datas.componentData['nameFontWeight'],'font-size':datas.componentData['nameFontSize'] + 'em',height: '2.8em',}"
v-if="datas.componentData['nameShow']"
>
{{items != null? items["productName"]: "名称"}}
</p>
<div
v-if="datas.componentData['followerShow']"
class="follower-wrap my-hairline--left"
:style="{
width:
datas.componentData.columnNum == 3 ? '3em' : '4em',
'padding-left':
datas.componentData.columnNum == 3 ? '0' : '0.8em',
}"
>
<div
class="follower-num"
:style="{ color: followerColor }"
>
{{items != null? items["totalCollectionCount"]? items["totalCollectionCount"]: 0: 0}}
</div>
<div class="follower-text">关注人数</div>
</div>
</div>
<!-- <p
:style="{'color':datas.componentData['describeColor'],'font-size':datas.componentData['describeFontSize']+'em'}"
v-if="datas.componentData['describeShow'] && items!=null && items.specificationsName!=''"
>{{items.specificationsName}}</p>-->
<p style="overflow: hidden; color: #999">
<span
:style="{ 'font-size': '0.7em' }"
v-if="datas.componentData['alSaleShow']"
>已售{{items != null? items["totalSalesCount"]: 0}}</span
>
<span
:style="{ 'font-size': '0.7em' }"
v-if="datas.componentData['alSaleShow'] &&datas.componentData['collectShow']"
>/</span
>
<span
:style="{ 'font-size': '0.7em' }"
v-if="datas.componentData['collectShow']"
>
剩余{{items != null &&items["qty"] !=undefined? items["qty"] > 0? items["qty"]: items.oversoldFlag == 1? "数量充足": "数量不足": ""}}
<span
v-if="items != null &&(items['qty']? items['qty'] >= 0: items['saleQty'] >= 0)"
></span
>
</span>
</p>
<template
v-if="items != null"
>
<div
class="marketing flex"
v-if="marketingTag &&marketingStyle == 0 &&items.marketingTag"
>
<div
class="item"
v-for="(item1, index1) in datas.componentData.items.marketingTag"
:key="index1"
>
{{ item1.label }}
</div>
</div>
</template>
<div class="bottom">
<template v-if="goodsType != 1">
<!-- <div v-if="vipPrice&&true" class="vipPrice1 flex">
<div class="vipIcon">VIP</div>
<div class="right"><span>8.8</span><span></span></div>
</div>-->
<div class="priceItem flex">
<p
class="price"
:style="{color: datas.componentData['priceColor'],'font-size': datas.componentData['priceFontSize'] + 'em',}"
v-if="datas.componentData['priceShow']"
>
<template
v-if="items != null &&(items['groupBuyFlag'] == '0' ||items['groupBuyFlag'] == '1')"
>
<span></span>
<span>{{items != null? items["goodsMinPrice"]: 0}}</span>
</template>
<template
v-if="items != null &&items['groupBuyFlag'] != '0' &&items['groupBuyFlag'] != '1'"
>
<span>
<span></span>
{{items != null? items["minPrice"]: 0}}
</span>
<del
style="font-size: 12px; color: #999"
v-if="items !=null &&datas.componentData['priceMarking'] &&items['minGoodsSuggestedRetailPrice'] &&items['minPrice'] -0 <items['minGoodsSuggestedRetailPrice'] -0 &&datas.componentData['columnNum'] < 3"
>
<span></span>
<span>{{items != null? items["minGoodsSuggestedRetailPrice"]: 0}}</span>
</del>
</template>
</p>
<div
v-if="vipPrice &&items != null"
class="vipPrice2 flex"
>
<p
class="left"
:style="{'font-size':datas.componentData['priceFontSize'] -0.1 +'em',}"
v-if="showVipPrice(index) == true"
>
<span></span>
<span>{{items["minPriceAfterRecommendedCardPriceTable"]}}</span>
</p>
<div
class="vipIcon line-clamp1"
v-if="showVipTag(index) == true"
>{{items["recommendedCardMinPricePriceTableName"]}}</div>
</div>
</div>
</template>
<template v-else>
<p
class="price"
:style="{color: datas.componentData['priceColor'],'font-size':datas.componentData['priceFontSize'] + 'em',}"
v-if="datas.componentData['priceShow']"
>
<template
v-if="items != null"
>
<template
v-if="items['groupBuyFlag'] == '0' ||items['groupBuyFlag'] == '1'"
>
<span></span>
<span>{{items != null? items["goodsMinPrice"]: 0}}</span>
</template>
<template v-else>
<span
v-if="items['exchangeIntegral'] &&items['exchangeIntegral'] > 0"
>{{items != null? items["exchangeIntegral"]: 0}}积分</span
>
<span
v-if="items['minPrice'] &&items['minPrice'] > 0 &&items['exchangeIntegral'] &&items['exchangeIntegral'] > 0"
>+</span
>
<template
v-if="items['minPrice'] &&items['minPrice'] > 0"
>
<span></span>
<span>{{items != null? items["minPrice"]: 0}}</span>
</template>
</template>
</template>
</p>
</template>
<template
v-if="items != null &&items['minProductGoodsCommission'] &&items['minProductGoodsCommission'] -0 >0.01">
<div
class="showCommission"
:style="{
color: commissionColor,
'border-color': commissionColor,
}"
v-if="datas.componentData.commissionStyle == 0"
>
<div
class="commission-box"
:style="{ 'background-color': commissionBgColor }"
>
<span>收益</span>
<span></span>
<span>{{items["minProductGoodsCommission"]}}</span>
</div>
</div>
</template>
<div
class="buy-now"
style="background-color: #aaa"
:style="{ 'font-size': getPayFontSize }"
v-if="items &&items.oversoldFlag ==0 &&items.totalQty - 0 <=0 &&datas.componentData['paynow']">
<span>已售罄</span>
</div>
<div
v-if="((items &&items.totalQty - 0 >0) ||(items &&items.oversoldFlag == 1)) &&datas.componentData['paynow']"
@click.stop="
onclickBuynow(items)
"
>
<i
class="buy-now-icon"
:class="'iconfont-common' + btnIcon"
:style="{ color: btnColor }"
v-if="btnType < 6"
></i>
<div
class="buy-now"
v-else
:style="{
'background-color': btnColor,
'font-size': getPayFontSize,
}"
>
<span>{{ btnTest }}</span>
</div>
</div>
</div>
<template
v-if="items != null"
>
<div
class="marketing flex"
v-if="marketingTag &&marketingStyle == 1 &&items.marketingTag"
>
<div
class="item"
v-for="(item1, index1) in datas.componentData.items.marketingTag"
:key="index1"
>
{{ item1.label }}
</div>
</div>
</template>
<template
v-if="items != null &&items['minProductGoodsCommission'] &&items['minProductGoodsCommission'] -0 >0.01"
>
<div
class="showCommissionTwo flex"
:style="{
color: commissionColor,
'border-color': commissionColor,
}"
v-if="datas.componentData.commissionStyle == 1"
>
<div
class="commission-box"
:style="{ 'background-color': commissionBgColor }"
>
<i class="iconfont-common common-iconfenxiang"></i>
<span></span>
<span></span>
<span style="font-size: 16px">{{items["minProductGoodsCommission"]}}</span>
</div>
</div>
</template>
</div>
</div>
</template>
<script type="text/ecmascript-6">
import mixin_computed from "./mixin/computed"
export default {
name: "",
props:['datas','items'],
mixins: [mixin_computed],
data() {
return {}
},
components: {},
computed: {},
created() {},
mounted() {},
methods: {}
}
</script>
<style lang="scss" scoped>
.goods-item-child {
position: relative;
overflow: hidden;
background: #ffffff;
}
.itemBorder{
border: 1px solid var(--border_color);
}
.imgBox {
position: relative;
overflow: hidden;
width: 100%;
// height: 0;
// padding-bottom: 100%;
margin: 0 auto 0.3em;
img {
display: block;
width: 100%;
// height: 100%;
// position: absolute;
// margin: auto;
// top: -9999px;
// right: -9999px;
// bottom: -9999px;
// left: -9999px;
}
.have-group {
position: absolute;
bottom: 10px;
left: 6px;
padding: 4px 8px;
background-color: rgba(0, 0, 0, 0.6);
color: white;
font-size: 12px;
border-radius: 4px;
z-index: 99;
}
.goodsPicture {
// position: absolute;
width: 100%;
height: 100%;
position: relative;
box-sizing: border-box;
.angleSign {
position: absolute;
top: 0;
left: 0;
image {
height: 100%;
// object-fit: contain;
}
}
image {
width: 100%;
}
img {
width: 100%;
}
.whiteBg {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(#fff, 0.7);
.cover {
position: absolute;
top: 20px;
left: 20px;
right: 20px;
bottom: 20px;
display: flex;
// background: rgba(#333, 0.6);
// justify-content: space-around;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 50%;
// background-image: url('../../../../../static/images/shouqing.png');
background-size: cover;
image {
width: 100%;
height: 100%;
}
p {
// font-size: 16px;
color: #fff;
font-weight: bold;
// line-height: 30px;
letter-spacing: 3px;
text-align: center;
}
}
}
}
}
.info {
padding: 5px 10px 12px;
position: relative;
background-color: white;
.name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
line-height: 1.4em;
position: relative;
}
.follower-wrap {
position: relative;
font-size: 0.8em;
// padding-left: 10px;
// border-left: 1px solid;
color: #999;
text-align: center;
height: 35px;
.follower-num {
text-align: center;
// color: #ff9933;
font-size: 1em;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.follower-text {
color: #999;
font-size: 0.7em;
text-align: center;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.vipPrice1 {
align-items: flex-end;
margin-top: 6px;
font-size: 12px;
.vipIcon {
min-width: 32px;
padding: 1px 2px;
height: 14px;
background: #333;
font-size: 10px;
line-height: 14px;
text-align: center;
color: #d7c7a1;
border-top-left-radius: 2px;
border-bottom-left-radius: 6px;
}
.right {
height: 14px;
color: #333;
font-weight: bold;
background: linear-gradient(
227deg,
rgba(212, 195, 142, 1),
rgba(252, 232, 162, 1)
);
border-radius: 0px 6px 6px 0px;
font-size: 10px;
text-align: center;
padding: 0 4px 0 2px;
}
}
.priceItem {
align-items: flex-end;
}
.vipPrice2 {
align-items: flex-end;
margin-top: 6px;
font-size: 12px;
.left {
color: #333;
font-weight: bold;
margin-left: 4px;
}
.vipIcon {
margin-left: 4px;
min-width: 32px;
padding: 1px 4px;
height: 14px;
background: #333;
font-size: 10px;
line-height: 14px;
text-align: center;
color: #d7c7a1;
border-radius: 6px;
border-top-left-radius: 2px;
}
}
.marketing {
align-items: center;
flex-wrap: wrap;
.item {
margin-top: 4px;
margin-right: 4px;
font-size: 10px;
padding: 0 6px;
border: 1px solid #ff5500;
color: #ff5500;
border-radius: 20px;
}
}
.bottom {
position: relative;
}
.price {
font-weight: 600;
margin-top: 6px;
}
.showCommission {
width: auto;
display: inline-block;
margin-top: 4px;
border: 1px solid transparent;
border-radius: 6px;
// color: #ff9933;
font-size: 10px;
// padding: 1px 6px;
overflow: hidden;
.commission-box {
padding-left: 6px;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
.buy-now {
color: #ffffff;
position: absolute;
right: 0;
bottom: 0;
border-radius: 15px;
background-color: var(--main-color);
width: 70px;
white-space: nowrap;
padding: 4px 15px;
display: flex;
justify-content: center;
align-items: center;
}
.buy-now-icon {
position: absolute;
right: 0;
bottom: 0;
font-size: 18px;
}
.showCommissionTwo {
align-items: center;
justify-content: center;
margin-top: 8px;
width: 100%;
// padding: 0 10px;
height: 26px;
font-size: 12px;
// color: #FF5500;
border: 1px solid transparent;
border-radius: 26px;
overflow: hidden;
// background: #FFEDE2;
.commission-box {
width: 100%;
height: 100%;
padding-left: 10px;
display: flex;
justify-content: center;
align-items: center;
}
i {
font-size: 14px;
margin-right: 4px;
}
}
}
</style>
<!-- 商品列表 -> 基于微商城 -->
<template>
<div
class="spell-group"
:style="{
'padding-top': getPaddingList[0]['value'] + 'px',
'padding-bottom': getPaddingList[1]['value'] + 'px',
'padding-left': getPaddingList[2]['value'] + 'px',
'padding-right': getPaddingList[3]['value'] + 'px',
}"
v-if="this.render ? targetShow : true"
>
<div
class="list-wrap heap-wrap"
:style="{'background-color': datas.componentData['heapBgColorShow']? datas.componentData['heapBgColor']: '','border-radius': datas.componentData['cardBorderRadius'] + 'em'}"
>
<div
class="tops"
:style="{'padding':datas.componentData['titleIcon'] ||(datas.componentData['moreShow'] &&datas.componentData.moreButtonSite == 'top')? '0px 0px 0px 0px': '','margin-bottom': datas.componentData['titleCardGap'] + 'px',}"
>
<div class="left flex">
<div class="img" v-if="datas.componentData['titleIcon']">
<img :src="titleIcon" alt />
</div>
<h1 class="title">{{ datas.componentData["titles"] }}</h1>
</div>
</div>
<!-- 堆叠卡片 -->
<div v-if="datas.componentData.style==='heap'">
<spell-group-heap-item
:goodsList="goodsList"
:datas="datas"
></spell-group-heap-item>
</div>
<!-- 网格模式 -->
<div class="goods" v-if="datas.componentData.style === 'list'">
<ul
:style="{'margin-left': -datas.componentData.proGap + 'px' }"
class="clearfix"
>
<li
v-for="(item, index) in getItemNum"
:key="index"
class="goods-item"
:class="datas.componentData.columnNum == 2 ? 'style2' : 'style3'"
:style="{'padding-left': datas.componentData.proGap + 'px','width': getColumnWidth,}"
@click="onclickProduct(goodsList[index])"
>
<goodsItem :datas="datas" :items="item"></goodsItem>
</li>
</ul>
</div>
<!-- 横向滑动 -->
<div
class="goods1"
:class="{ 'goods1-wibkit': render }"
v-else-if="datas.componentData.style === 'across'"
>
<div class="prev-btn">
<i
class="ant-fanhui-line"
style="font-size: 30px"
></i>
</div>
<div class="next-btn">
<i
class="ant-fanhui-line"
style="font-size: 30px"
></i>
</div>
<div
v-for="(item, index) in getItemNum"
:key="index"
:style="{ width: getColumnWidth,'margin-right': datas.componentData.proGap + 'px' }"
class="goods-item"
:class="{ lastchild: swiperNum == index + 1 }"
@click="onclickProduct(goodsList[index])"
>
<goodsItem :datas="datas" :items="item" :style="{'margin-left':datas.componentData.proGap*2+'px'}"></goodsItem>
</div>
</div>
<!-- 瀑布流 -->
<div class="waterfallFlow" v-if="datas.componentData.style === 'waterfall'">
<div class="left">
<div v-for="(item,index) in goodsList" :key="index" @click="onclickProduct(goodsList[index])" :style="{'margin-bottom':datas.componentData.proGap + 'px','margin-right':datas.componentData.proGap/2 + 'px'}">
<goodsItem
v-if="index%2==0"
:datas="datas"
:items="item"
></goodsItem>
</div>
</div>
<div class="right">
<div v-for="(item,index) in goodsList" :key="index" @click="onclickProduct(goodsList[index])" :style="{'margin-bottom':datas.componentData.proGap + 'px','margin-left':datas.componentData.proGap/2 + 'px'}">
<goodsItem
v-if="index%2==1"
:datas="datas"
:items="item"
></goodsItem>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
const app = getApp();
import goodsItem from "./goodsItem"
import mixin_computed from "./mixin/computed"
export default {
name: "spell-group",
mixins: [mixin_computed],
props: {
render: {
type: Boolean,
default: true,
},
datas: {
type: Object,
default: function () {
return {
fontSize: 16,
id: "",
pageCode: 0,
pageType: 0,
code: 0,
//判断是否运维人员
componentData: {
goodsList: [],
initProductArr: [],
titles: "这是标题",
link: "https://www.baidu.com/",
fontColor: "#000000",
goodsSource: "classify", //
style: "across", //across
imgPadding: 20,
moreShow: true,
moreButtonSite: "bottom",
rowNum: 3,
columnNum: 2,
proGap: 10,
backgroundColorShow: true,
backgroundColor: "#CCCCCC",
borderColorShow: true,
borderColor: "#999999",
get_shop_page_by_id: true,
nameFontSize: 0.8125,
imgSize: "0%",
nameColor: "#000000",
describeShow: true,
describeFontSize: 1,
priceShow: true,
priceFontSize: 0.9,
priceColor: "#000000",
angleShow: false,
colorLayoutShow: false,
colorLayoutSite: "top",
initcharAlign: "left",
followerShow: true,
// 划线价
priceMarking: true,
// 商品排序 0 默认 1销量 2新品 3价格(由低到高)
goodsSort: 0,
paddingList: [
{
name: "上",
value: 10,
},
{
name: "下",
value: 10,
},
{
name: "左",
value: 15,
},
{
name: "右",
value: 15,
},
],
},
};
},
},
},
data() {
return {
api: null,
api2: null,
targetShow: true,
loading:false,
swiperNum: 5,
toInit: true,
DFSImg: "",
sellOutShow: false,
goodsList:[],
};
},
created () {
this.DFSImg = app.DFSImg;
},
mounted() {
this.init();
},
methods: {
init() {
this.getProductList(2);
},
async getProductList(code) {
// 商品产品详情
let productIdList = [];
this.goodsList = this.datas.componentData.goodsList;
this.goodsList.forEach((element) => {
element.productImgUrl = "";
element.productName = "";
element.minPrice = "";
productIdList.push(element.productId);
});
if (productIdList.length == 0) {
this.toInit = true;
this.targetShow = false;
return;
}
let query = {
sortColumn: this.goodsSort,
sortType: this.goodsSort != 2 ? 1 : 0,
page: 1, // 当前页
rows: productIdList.length, // 一页多少条
productIdList: productIdList,
whetherShowSoldOutGoods: this.whetherShowSoldOutGoods,
whetherQueryCollectCount: true,
whetherUseVirtualSalesQty: true, //是否使用虚拟销售数量
whetherUseVirtualCollectCount: true, //是否使用虚拟收藏人数
whetherFindDistributionCommission: this
.whetherFindDistributionCommission, //是否查询商品佣金(0:不查询,1:展示,为空不查佣金)
whetherFindRecommendedCardFlag: this.vipPrice ? 1 : 0, //是否查询会员价 1是 0否
whetherShowGoodsDefaultTagFlag: this.marketingTag ? 1 : 0, //是否展示营销标签 1是 0否
};
app.goodsApi.queryProductInfo(query).then((res) => {
this.sellOutShow = true;
this.toInit = true;
// 多主题(res.data.code)和商城端(res.code)不一样
if (res.data.code == 200) {
this.datas.componentData.goodsList = res.data.data.list;
this.datas.componentData.goodsList.forEach((item) => {
item.totalCollectionCount = Number(item.totalCollectionCount) || 0;
item.qty = Number(item.qty) || 0;
item.goodsMinPrice = Number(item.goodsMinPrice).toFixed(2) || 0;
item.minPrice = Number(item.minPrice).toFixed(2) || 0;
item.minGoodsSuggestedRetailPrice =
Number(item.minGoodsSuggestedRetailPrice).toFixed(2) || 0;
item.minPriceAfterRecommendedCardPriceTable =
Number(item.minPriceAfterRecommendedCardPriceTable).toFixed(2) ||
0;
item.exchangeIntegral =
Number(item.exchangeIntegral).toFixed(2) || 0;
item.minProductGoodsCommission =
Number(item.minProductGoodsCommission).toFixed(2) || 0;
item.minGoodsSuggestedRetailPrice =
Number(item.minGoodsSuggestedRetailPrice).toFixed(2) || 0;
item.marketingTag = item.defaultTags
? this.filtermark(item.defaultTags, this.marketingTagList)
: [];
item.coverImage = this.DFSImg(item.coverImage, 700, null, 1);
item.productImgUrl = this.DFSImg(item.productImgUrl, 700, null, 1);
});
this.goodsList=this.datas.componentData.goodsList;
console.log(this.goodsList,'---------------------898')
if (this.goodsList.length <= 0) {
this.targetShow = false;
}
}
});
},
viewMore() {
if (!this.render) return;
if (this.goodsType != 1) {
if (this.datas.componentData.style == "list") {
this.$router.push({
name: "goods-commodityMenu",
query: {
categoryName: this.datas.componentData.categoryName,
categoryId: this.datas.componentData.categoryId,
},
});
} else {
this.$router.push({
name: "goods-commodityMenu",
});
}
} else {
let query = {
categoryName: this.datas.componentData.categoryName,
categoryId: this.datas.componentData.categoryId,
};
this.$router.push({
name: "pointShop-productList",
query,
});
}
},
//点击商城跳转---基于微商城
onclickProduct(item) {
let productId = item.productId;
let terminalProductId = item.terminalProductId;
let linkVal = `/goods/${productId}?terminalProductId=${terminalProductId}`;
app.$themeToLink({
type: 1,
link: linkVal
});
},
showVipPrice(index) {
// 索引 0 显示价格 1显示名称
let showFlag = false;
let vipPrice = this.goodsList[index][
"minPriceAfterRecommendedCardPriceTable"
];
if (
vipPrice &&
Number(vipPrice) <
Number(this.goodsList[index]["minPrice"])
) {
showFlag = true;
}
console.log(showFlag, "------------760");
return showFlag;
},
showVipTag(index) {
// 索引 0 显示价格 1显示名称
let showFlag = false;
let vipPrice = this.goodsList[index][
"minPriceAfterRecommendedCardPriceTable"
];
let showTag = this.goodsList[index][
"recommendedCardMinPricePriceTableName"
];
if (
vipPrice &&
showTag &&
Number(vipPrice) <=
Number(this.goodsList[index]["minPrice"])
) {
showFlag = true;
}
return showFlag;
},
filtermark(newlist, marketingTagList) {
let list = [];
if (newlist.length <= 0) return;
if (marketingTagList.length > 0) {
marketingTagList.forEach((item, index) => {
newlist.forEach((item1, index1) => {
if (item1 == item.key) {
list.push(item);
}
});
});
}
return list;
},
},
components: {
goodsItem,
},
};
</script>
<style lang="scss" scoped>
.clearfix:after {
display: block;
clear: both;
content: "";
visibility: hidden;
height: 0;
}
.clearfix {
zoom: 1;
}
.spell-group {
position: relative;
font-size: 16px;
.heap-wrap {
padding: 10px;
}
.tops {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
// padding-bottom: 0.54em;
// padding: 0px 0px 10px 5px;
.left {
align-items: center;
.img {
width: 30px;
height: 30px;
overflow: hidden;
margin-right: 10px;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
}
}
h1 {
text-align: center;
text-transform: uppercase;
// letter-spacing: 0.1em;
font-size: 18px;
color: #0a0a0a;
}
.goods {
width: 100%;
position: relative;
ul {
list-style: none;
// overflow: hidden;
li {
box-sizing: border-box;
float: left;
margin-bottom: 1em;
}
.style2:nth-child(2n + 1) {
clear: both;
}
.style3:nth-child(3n + 1) {
clear: both;
}
}
.marquee {
position: absolute;
z-index: 999;
top: 10px;
left: 20px;
}
}
.goods1 {
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
padding-bottom: 5px;
.prev-btn,
.next-btn {
width: 30px;
height: 30px;
position: absolute;
top: 50%;
z-index: 99;
opacity: 0.5;
font-size: 30px;
}
.next-btn {
right: 10px;
transform: rotateY(180deg);
}
.prev-btn {
left: 10px;
}
.goods-item {
display: inline-block;
vertical-align: top;
white-space: initial;
.items {
position: relative;
border-radius: 5px;
overflow: hidden;
// box-shadow: 1px 0px 26px 2px #f5f5f5;
background: #ffffff;
.after {
width: 100%;
height: 100%;
background-color: aliceblue;
}
}
}
.slidebox2 {
box-sizing: border-box;
-moz-box-sizing: border-box; /* Firefox */
-webkit-box-sizing: border-box; /* Safari */
}
}
.goods1-wibkit::-webkit-scrollbar {
display: none;
}
.moreBottom {
font-size: 13px;
text-align: center;
padding-top: 0.54em;
color: #6b6b6b;
.jt {
display: inline-block;
border-top: 1px solid;
border-right: 1px solid;
width: 10px;
height: 10px;
-webkit-transform: rotate(-135deg);
transform: rotate(405deg);
margin-left: 0px;
}
}
// 瀑布流
.waterfallFlow{
display: flex;
justify-content: space-between;
.left,.right{
width: 50%;
box-sizing: border-box;
}
}
}
</style>
const app = getApp();
export default {
computed: {
getBorderRadius() {
return this.datas.componentData.borderRadius == undefined
? 0.625
: this.datas.componentData.borderRadius;
},
goodsSort() {
return this.datas.componentData.goodsSort || 0;
},
// 会员价
vipPrice() {
return this.datas.componentData.vipPrice || false;
},
whetherFindDistributionCommission() {
return this.datas.componentData.whetherFindDistributionCommission ? 1 : 0;
},
categoryId() {
return this.datas.componentData.categoryId
? this.datas.componentData.categoryId
: "";
},
// 关注人数样式
followerColor() {
return this.datas.componentData.followerColor
? this.datas.componentData.followerColor
: "#ff9933";
},
// 佣金文字颜色
commissionColor() {
return this.datas.componentData.commissionColor
? this.datas.componentData.commissionColor
: "#ff9051";
},
//佣金背景颜色
commissionBgColor() {
return this.datas.componentData.commissionBgColor
? this.datas.componentData.commissionBgColor
: "";
},
// 按钮图标
btnIcon() {
return this.datas.componentData.btnIcon
? this.datas.componentData.btnIcon
: "";
},
// 按钮类型
btnType() {
return this.datas.componentData.btnType
? this.datas.componentData.btnType
: 6;
},
// 按钮颜色
btnColor() {
return this.datas.componentData.btnColor
? this.datas.componentData.btnColor
: "var(--main-color)";
},
// 按钮文案
btnTest() {
return this.datas.componentData.btnTest
? this.datas.componentData.btnTest
: "立即购买";
},
getItemNum() {
return this.datas.componentData.goodsList;
},
getPaddingList() {
return this.datas.componentData.paddingList;
},
getColumnWidth() {
if (this.datas.componentData.columnNum == 1) {
return "100%";
} else if (this.datas.componentData.columnNum == 2) {
return "50%";
} else {
return "33.3%";
}
},
getPayFontSize() {
if (this.datas.componentData.columnNum == 1) {
return "12px";
} else if (this.datas.componentData.columnNum == 2) {
return "10px";
} else {
return "8px";
}
},
getListPadding() {
if (this.datas.componentData.columnNum == 1) {
return "";
} else if (this.datas.componentData.columnNum == 2) {
return (
"0 " +
this.datas.componentData.proGap / 2 +
"px" +
" 0 " +
this.datas.componentData.proGap / 2 +
"px"
);
} else {
return "33.3%";
}
},
whetherShowSoldOutGoods() {
// 商城端接口的获取商城配置信息
// if (this.render) {
// return this.$store.state.setShopConfig.whetherShowSoldOutGoods || 1;
// } else {
// return 1;
// }
return 1;
},
goodsType() {
return this.datas.componentData.goodsType || 0;
},
// 展示标题图片
titleIcon() {
return app.DFSImg(this.datas.componentData.titleIcon, 400, 400) || "";
},
// 展示角标
angleSign() {
return this.datas.componentData.angleSign || false;
},
// 角标尺寸
angleSignSize() {
return this.datas.componentData.angleSignSize || 25;
},
// 展示角标图片
angleSignImg() {
return this.datas.componentData.angleSignImg || "";
},
// 展示营销标签
marketingTag() {
return this.datas.componentData.marketingTag || false;
},
// 展示营销标签类型
marketingStyle() {
return this.datas.componentData.marketingStyle || 0;
},
// 营销标签列表
marketingTagList() {
return this.datas.componentData.marketingTagList || [];
},
cardShadowSize() {
return this.datas.componentData.cardShadowSize
? this.datas.componentData.cardShadowSize
: 3;
}
}
};
\ No newline at end of file
......@@ -30,7 +30,7 @@
<span class="tagName">{{ item.tagName }}</span>
</div>
</div>
<image :src="info.coverUrl" mode="widthFix"></image>
<image :src="info.coverUrl" mode="widthFix" lazy-load></image>
</div>
<div class="infoText">
<p
......@@ -70,7 +70,7 @@
<span class="tagName">{{ item.tagName }}</span>
</div>
</div>
<image :src="info.coverUrl" mode="widthFix"></image>
<image :src="info.coverUrl" lazy-load mode="widthFix"></image>
</div>
</div>
</template>
......
......@@ -84,6 +84,10 @@
<div v-if="item.componentCode == 'merchants-list' && item.componentInfo.visible == 1">
<merchants-list class="goodsListItem" :datas="item"></merchants-list>
</div>
<div v-if="item.componentCode == 'spell-group' && item.componentInfo.visible == 1">
<spell-group :datas="item"></spell-group>
</div>
</div>
<bottomCont></bottomCont>
</div>
......@@ -105,6 +109,7 @@ import text from '@/components/content/text'
import imgText from '@/components/content/imgText'
import coupon from '@/components/activity/coupon'
import integralTurntable from '@/components/activity/integralTurntable'
import spellGroup from '@/components/activity/spellGroup'
import { setTabBarActive, checkTabbarPage,themeColor } from "../../utils/mayi.js";
import { throttle } from "../../utils/index.js"
const app = getApp();
......@@ -134,7 +139,8 @@ export default {
coupon,
integralTurntable,
transverseLabel,
information
information,
spellGroup
},
onShareAppMessage(res) {
let shareVal={};
......
......@@ -19,7 +19,8 @@
"photo-gallery":"/static/nativeComponents/PhotoGallery/index",
"live-broadcast":"/static/nativeComponents/LiveBroadcast/index",
"share-picture":"/static/nativeComponents/SharePicture/index",
"merchants-list":"/static/nativeComponents/MerchantsList/index"
"merchants-list":"/static/nativeComponents/MerchantsList/index",
"spell-group-heap-item":"/static/nativeComponents/spellGroup/heapItem/index"
},
"enablePullDownRefresh":true,
"backgroundColor":"#f5f5f5"
......
const app = getApp();
const { goodsApi, DFSImg, $themeToLink, $themeAddToCard } = app;
const componentOptions = {
// 组件选项
options: {
multipleSlots: true
},
behaviors: [],
properties: {
datas: {
type: Object
},
items: {
type: Object
},
indexs: {
type: Number
}
},
// 组件数据
data: {
isPageHidden: false, // 页面是否处于隐藏状态
timeData: {}
},
// 数据监听器
observers: {},
// 组件方法
methods: {
init() {},
getSaleTime(val) {
return new Date(val.replace(/-/g, "/")).getTime() - new Date().getTime();
},
showVipPrice(index) {
// 索引 0 显示价格 1显示名称
let showFlag = false;
let vipPrice = this.items["minPriceAfterRecommendedCardPriceTable"];
if (vipPrice && Number(vipPrice) < Number(this.items["minPrice"])) {
showFlag = true;
}
console.log(showFlag, "------------760");
return showFlag;
},
showVipTag(index) {
// 索引 0 显示价格 1显示名称
let showFlag = false;
let vipPrice = this.items["minPriceAfterRecommendedCardPriceTable"];
let showTag = this.items["recommendedCardMinPricePriceTableName"];
if (
vipPrice &&
showTag &&
Number(vipPrice) <= Number(this.items["minPrice"])
) {
showFlag = true;
}
return showFlag;
},
onChange(e) {
this.setData({ timeData: e.detail });
},
onclickProduct() {
let { goodsType } = this.data.datas.componentData;
let {
productId,
terminalProductId,
terminalGoodsMixId
} = this.data.items;
let linkVal = "";
if (goodsType == 0) {
linkVal = `/goods/${productId}?terminalProductId=${terminalProductId}`;
} else if (goodsType == 1) {
linkVal = `/pointShop/goodsDetail?productId${productId}&terminalProductId=${terminalProductId}&terminalGoodsMixId=${terminalGoodsMixId}`;
}
$themeToLink({
type: 1,
link: linkVal
});
},
onclickBuynow() {
let { btnType } = this.data.datas.componentData;
let {
minProductGoodsMixid,
minProductGoodsId,
minGoodsId
} = this.data.items;
let linkVal = "";
if (btnType < 6) {
// 加入购物车
console.log("加入购物车");
$themeAddToCard(this.data.items);
} else {
// 进入确认订单
linkVal = `/order/orderConfirm?productGoodsMixId=${minProductGoodsMixid}&productGoodsId=${minProductGoodsId}&goodsId=${minGoodsId}&qty=1&goodsString=null&source=3`;
}
console.log(linkVal, "-------90");
$themeToLink({ type: 1, link: linkVal });
},
toMerchants() {
let { orgId } = this.data.items;
$themeToLink({ type: 1, link: `/merchantsDetail/${orgId}` });
},
},
// 组件生命周期
lifetimes: {
created() {},
attached() {
this.init();
},
ready() {},
moved() {},
detached() {}
},
definitionFilter() {},
// 页面生命周期
pageLifetimes: {
// 页面被展示
show() {
const { isPageHidden } = this.data;
// show事件发生前,页面不是处于隐藏状态时
if (!isPageHidden) {
return;
}
// 重新执行定时器等操作
},
// 页面被隐藏
hide() {
this.setData({
isPageHidden: true
});
// 清除定时器等操作
},
// 页面尺寸变化时
resize() {}
}
};
Component(componentOptions)
{
"component": true,
"usingComponents": {
"van-count-down":"/static/vant/count-down/index"
}
}
<!-- 商品列表item -->
<view
class="goodsItem {{datas.componentData.style==='rowList'?'goodsRowList':''}} {{datas.componentData.style==='heap'?'goodsRowList goodsHeapItem':''}}"
style="--proGap2:{{datas.componentData.proGap*2}}rpx;"
bindtap="onclickProduct"
>
<view class="goods-item-child {{datas.componentData['borderColorShow']?'goods-item-child-bd':''}}" style="border-radius:{{datas.componentData.borderRadius}}em;--border_color:{{datas.componentData['borderColor']}};box-shadow:{{datas.componentData['cardShadow']?'0rpx 0rpx 10rpx '+datas.componentData['cardShadowSize']*2+'rpx #ccc':''}};">
<!-- 商品图片 -->
<view class="imgBox" style="background-color:{{datas.componentData['backgroundColorShow']?datas.componentData['backgroundColor']:''}}">
<view
class="goodsPicture"
wx:if="{{items!=null}}"
style="padding:{{datas.componentData.imgSize}}"
>
<!-- 显示拼团数 -->
<view class="have-group" wx:if="{{datas.componentData['haveGroupShow']&& (items && items['groupBuyFlag'] == '1')}}">{{items.haveGroupNum?items.haveGroupNum:0}}人已团</view>
<!-- 商品角标 -->
<view
class="angleSign"
style="width:{{datas.componentData.angleSignSize}}%;height:{{datas.componentData.angleSignSize}}%;"
wx:if="{{datas.componentData['angleSign'] && datas.componentData['angleSignImg']}}"
>
<image mode="widthFix" src="{{datas.componentData['angleSignImg']}}" />
</view>
<!-- 商品主图 -->
<image
lazy-load
mode="{{datas.componentData.style==='rowList' || datas.componentData.style==='heap'?'aspectFit':'widthFix'}}"
class="productImgUrl"
wx:if="{{datas.componentData.goodsImgType == 1}}"
src="{{items.productImgUrl}}"
/>
<image
lazy-load
mode="{{datas.componentData.style==='rowList' || datas.componentData.style==='heap'?'aspectFit':'widthFix'}}"
class="productImgUrl"
wx:else
src="{{items.coverImage}}"
/>
<!-- 售罄遮罩 -->
<view class="whiteBg" wx:if="{{items&&items.oversoldFlag==0&&items.totalQty-0<=0}}">
<view class="cover">
<image mode="aspectFit" src="http://mayi-newshop.oss-cn-shanghai.aliyuncs.com/public/png/f254fe62-6dda-46f6-a2f4-a7b2aa0474df.png" />
</view>
</view>
</view>
</view>
<!-- 商品详情 -->
<view class="info" style="text-align:{{datas.componentData['initcharAlign']}};">
<view class="info-top flex">
<view
class="name"
wx:if="{{datas.componentData['nameShow']}}"
style="color:{{datas.componentData['nameColor']}};font-weight:{{datas.componentData['nameFontWeight']}};font-size:{{datas.componentData['nameFontSize']}}em;height:2.8em;"
>
{{items!=null?items['productName']:'名称'}}
</view>
<view
class="follower-wrap"
wx:if="{{datas.componentData['followerShow']}}"
style="padding-left:{{datas.componentData.columnNum == 3 ? '0' : '20rpx'}}"
>
<view class="follower-num" style="color:{{datas.componentData['followerColor']?datas.componentData['followerColor']:'#ff9933'}};">
{{items!=null? items['totalCollectionCount']:0}}
</view>
<view class="follower-text">关注人数</view>
</view>
</view>
<!-- 已售 -->
<view class="Sold">
<text wx:if="{{datas.componentData['alSaleShow']}}">已售{{items!=null ? items['totalSalesCount'] :0}}件</text>
<text wx:if="{{datas.componentData['alSaleShow'] && datas.componentData['collectShow']}}">/</text>
<text wx:if="{{datas.componentData['collectShow']}}">剩余{{items!=null && items['qty']!=undefined ? (items['qty'] > 0 ? items['qty']: items.oversoldFlag==1?'数量充足':'数量不足') : ''}}<text wx:if="{{items!=null && (items['qty'] ? items['qty'] >= 0 : items['saleQty'] >= 0) && items.oversoldFlag!=1}}">件</text>
</text>
</view>
<!-- 标签 -->
<view class="marketing flex" wx:if="{{datas.componentData['marketingTag']&&datas.componentData['marketingStyle']==0&&items.marketingTag}}">
<view
class="item"
wx:for="{{items.marketingTag}}"
wx:key="index"
>
{{item.label}}
</view>
</view>
<!-- 底部 -->
<view class="bottom" wx:if="{{datas.componentData['goodsType'] !=1}}">
<!-- 价格 -->
<view class="priceItem flex">
<view
class="price flex"
style="color:{{datas.componentData['priceColor']}};font-size:{{datas.componentData['priceFontSize']}}em;"
wx:if="{{datas.componentData['priceShow']}}"
>
<text wx:if="{{items!=null && (items['groupBuyFlag'] == '0' ||items['groupBuyFlag'] == '1')}}">
¥{{items!=null ? items['goodsMinPrice']:0}}
</text>
<text style="font-size:24rpx;color:#999;text-decoration:line-through;" wx:if="{{items!=null&&datas.componentData['priceMarking']&&items['minGoodsSuggestedRetailPrice']&&(items['goodsMinPrice']-0<items['minGoodsSuggestedRetailPrice']-0)&&datas.componentData['columnNum']<3}}">
¥{{items['minGoodsSuggestedRetailPrice']}}
</text>
</view>
<view class="vipPrice2 flex" wx:if="{{datas.componentData.vipPrice}}">
<view class="left" wx:if="{{items.showVipPrice==true}}">
¥{{items['minPriceAfterRecommendedCardPriceTable']}}
</view>
<view class="vipIcon line-clamp1" wx:if="{{items.showVipTag==true}}">
{{items["recommendedCardMinPricePriceTableName"]}}
</view>
</view>
</view>
<!-- 收益样式一 -->
<block wx:if="{{items!=null&&items['minProductGoodsCommission']&&items['minProductGoodsCommission']-0>0.01}}">
<view
class="showCommission"
style="color:{{datas.componentData.commissionColor}};border-color:{{datas.componentData.commissionColor}};"
wx:if="{{datas.componentData.commissionStyle==0}}"
>
<view class="commission-box" style="background-color:{{datas.componentData.commissionBgColor}}">
<text>收益</text>
<text>¥{{items['minProductGoodsCommission']}}</text>
</view>
</view>
</block>
<view wx:if="{{(items&&items.totalQty-0>0||items&&items.oversoldFlag==1)&& datas.componentData['paynow']}}" catchtap="onclickBuynow">
<text wx:if="{{datas.componentData.btnType<6}}" style="color:{{datas.componentData.btnColor}}" class="buy-now-icon iconfont-common {{datas.componentData.btnIcon}}"></text>
<view
wx:else
class="buy-now"
style="background-color:{{datas.componentData.btnColor}};font-size:24rpx;"
>
{{datas.componentData.btnTest}}
</view>
</view>
</view>
<!-- 底部展示标签列表 -->
<block wx:if="{{items!=null}}">
<view class="marketing flex" wx:if="{{datas.componentData.marketingTag&&datas.componentData.marketingStyle==1&&items.marketingTag}}">
<view
class="item"
wx:for="{{items.marketingTag}}"
wx:key="index"
>
{{item.label}}
</view>
</view>
</block>
<!-- 收益样式二 -->
<block wx:if="{{items!=null&&items['minProductGoodsCommission']&&items['minProductGoodsCommission']-0>0.01}}">
<view
class="showCommissionTwo flex"
wx:if="{{datas.componentData.commissionStyle==1}}"
style="color:{{datas.componentData.commissionColor}};border-color:{{datas.componentData.commissionColor}};"
>
<view class="commission-box" style="background-color:{{datas.componentData.commissionBgColor}}">
<text class="iconfont-common common-iconfenxiang"></text>
<text style="padding:0 8rpx;">赚¥</text>
<text style="font-size:32rpx;">{{items['minProductGoodsCommission']}}</text>
</view>
</view>
</block>
</view>
</view>
</view>
@import "/static/font/common_icon.wxss";
.flex{
display: flex;
}
.goods-item-child-bd{
border: 1px solid var(--border_color);
}
image{
width: 100%;
display: block;
}
.goodsItem{
margin-bottom: var(--proGap2);
white-space: initial;
}
.goods-item-child {
position: relative;
overflow: hidden;
background: #fff;
}
.goodsRowList .goods-item-child{
display: flex;
align-items: flex-start;
}
.goodsRowList .goods-item-child .imgBox{
width: auto;
width: 180rpx;
height: 180rpx;
margin: 20rpx;
overflow: hidden;
border-radius: 12rpx;
-webkit-border-radius: 12rpx;
-moz-border-radius: 12rpx;
-ms-border-radius: 12rpx;
-o-border-radius: 12rpx;
}
.goodsRowList .goods-item-child .info{
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.goodsHeapItem{
width: 100%;
}
.merchantsEntrance{
padding: 8rpx 20rpx;
}
.merchantsEntrance .left{
align-items: center;
}
.merchantsEntrance .left .logo{
width: 52rpx;
height: 52rpx;
border-radius: 8rpx;
-webkit-border-radius: 8rpx;
-moz-border-radius: 8rpx;
-ms-border-radius: 8rpx;
-o-border-radius: 8rpx;
overflow: hidden;
background: #f5f5f5;
margin-right: 20rpx;
}
.imgBox{
position: relative;
overflow: hidden;
width: 100%;
margin: 0 auto;
}
.goodsPicture{
width: 100%;
height: 100%;
position: relative;
box-sizing: border-box;
}
.goodsPicture .have-group{
position: absolute;
bottom: 20rpx;
left: 12rpx;
padding: 8rpx 16rpx;
background-color: rgba(0,0,0,.6);
color: white;
font-size: 24rpx;
border-radius: 8rpx;
-webkit-border-radius: 8rpx;
-moz-border-radius: 8rpx;
-ms-border-radius: 8rpx;
-o-border-radius: 8rpx;
}
.goodsPicture .productImgUrl{
width: 100%;
height: 100%;
}
.goodsPicture .saleWay{
position: absolute;
bottom: 0;
left: 0;
width: 100%;
display: flex;
justify-content: center;
z-index: 2;
color: #fff;
}
.goodsPicture .saleWay .saleWayBg{
background: var(--main-color);
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: 0.5;
}
.goodsPicture .saleWay .saleTime{
position: relative;
z-index: 2;
padding: 4rpx 0;
}
.goodsPicture .saleWay .saleTime text{
color: #fff;
}
.goodsPicture .angleSign{
position: absolute;
top: 0;
left: 0;
}
.whiteBg {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(#fff, 0.7);
}
.whiteBg .cover {
position: absolute;
top: 20px;
left: 20px;
right: 20px;
bottom: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 50%;
background-size: cover;
}
.whiteBg .cover img {
width: 100%;
height: 100%;
object-fit: contain;
}
.info{
padding: 10rpx 20rpx 24rpx;
position: relative;
background-color: white;
}
.info .info-top{
overflow: hidden;
justify-content: space-between;
}
.info .name{
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
line-height: 1.4em;
position: relative;
}
.info .follower-wrap{
position: relative;
font-size: 0.8em;
color: #999;
text-align: center;
height: 70rpx;
border-left: 1px solid #999;
}
.info .follower-wrap .follower-num{
text-align: center;
font-size: 1em;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.info .follower-wrap .follower-text{
color: #999;
font-size: 0.7em;
text-align: center;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.vipPrice1{
align-items: flex-end;
margin-top: 12rpx;
font-size: 24rpx;
}
.vipPrice1 .vipIcon{
min-width: 64rpx;
padding: 2rpx 4rpx;
height: 28rpx;
background: #333;
font-size: 20rpx;
line-height: 28rpx;
text-align: center;
color: #d7c7a1;
border-top-left-radius: 4rpx;
border-bottom-left-radius: 12rpx;
}
.vipPrice1 .right{
height: 28rpx;
color: #333;
font-weight: bold;
background: linear-gradient( 227deg, rgba(212, 195, 142, 1), rgba(252, 232, 162, 1) );
border-radius: 0rpx 12rpx 12rpx 0rpx;
font-size: 20rpx;
text-align: center;
padding: 0 8rpx 0 4rpx;
-webkit-border-radius: 0rpx 12rpx 12rpx 0rpx;
-moz-border-radius: 0rpx 12rpx 12rpx 0rpx;
-ms-border-radius: 0rpx 12rpx 12rpx 0rpx;
-o-border-radius: 0rpx 12rpx 12rpx 0rpx;
}
.priceItem {
align-items: flex-end;
}
.priceItem .price{
align-items: center;
}
.vipPrice2{
align-items: flex-end;
margin-top: 12rpx;
font-size: 24rpx;
}
.vipPrice2 .left{
color: #333;
font-weight: bold;
margin-left: 8rpx;
}
.vipPrice2 .vipIcon{
margin-left: 8rpx;
min-width: 64rpx;
padding: 2rpx 8rpx;
height: 28rpx;
background: #333;
font-size: 20rpx;
line-height: 28rpx;
text-align: center;
color: #d7c7a1;
border-radius: 12rpx;
border-top-left-radius: 2rpx;
-webkit-border-radius: 12rpx;
-moz-border-radius: 12rpx;
-ms-border-radius: 12rpx;
-o-border-radius: 12rpx;
}
.Sold{
overflow: hidden;
color: #999;
}
.Sold text{
font-size: 24rpx;
}
.buy-now-icon{
color: var(--main-color);
}
.buy-now {
color: #ffffff;
position: absolute;
right: 0;
bottom: 0;
border-radius: 30rpx;
background-color: var(--main-color);
width: 140rpx;
white-space: nowrap;
padding: 8rpx 20rpx;
display: flex;
justify-content: center;
align-items: center;
-webkit-border-radius: 30rpx;
-moz-border-radius: 30rpx;
-ms-border-radius: 30rpx;
-o-border-radius: 30rpx;
}
.buy-now-icon {
position: absolute;
right: 0;
bottom: 0;
font-size: 36rpx;
}
.showCommission {
width: auto;
display: inline-block;
margin-top: 8rpx;
border: 1px solid transparent;
border-radius: 12rpx;
font-size: 10px;
overflow: hidden;
-webkit-border-radius: 12rpx;
-moz-border-radius: 12rpx;
-ms-border-radius: 12rpx;
-o-border-radius: 12rpx;
}
.showCommission .commission-box {
box-sizing: border-box;
padding: 0 10rpx;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.showCommissionTwo {
align-items: center;
justify-content: center;
margin-top: 16rpx;
width: 100%;
height: 52rpx;
font-size: 24rpx;
border: 1px solid transparent;
border-radius: 26px;
overflow: hidden;
}
.showCommissionTwo .commission-box {
width: 100%;
height: 100%;
padding-left: 20rpx;
display: flex;
justify-content: center;
align-items: center;
}
.showCommissionTwo i {
font-size: 28rpx;
margin-right: 8rpx;
}
.marketing {
align-items: center;
flex-wrap: wrap;
}
.marketing .item {
margin-top: 8rpx;
margin-right: 8rpx;
font-size: 20rpx;
padding: 0 12rpx;
border: 2rpx solid #ff5500;
color: #ff5500;
border-radius: 40rpx;
-webkit-border-radius: 40rpx;
-moz-border-radius: 40rpx;
-ms-border-radius: 40rpx;
-o-border-radius: 40rpx;
}
.bottom {
position: relative;
}
.price {
font-weight: 600;
margin-top: 12rpx;
}
\ No newline at end of file
import TouchEvent from "./utils/touchEvent";
const componentOptions = {
// 组件选项
options: {
multipleSlots: true
},
behaviors: [],
properties: {
datas: {
type:Object
},
goodsList: {
type:Array
}
},
// 组件数据
data: {
isPageHidden: false, // 页面是否处于隐藏状态
isLoading: false,
swiperCurIndex: 0,
slideClass: "",
lockSwipe: false
},
// 数据监听器
observers: {},
// 组件生命周期
lifetimes: {
created() {
new TouchEvent(this, "touchCard", {
swipe: evt => {
//在touch结束触发,evt.direction代表滑动的方向 ['Up','Right','Down','Left']
if (evt.direction === "Left") this.next(evt);
if (evt.direction === "Right") this.prev(evt);
}
});
},
attached() {}
},
// 组件方法
methods: {
next(e) {
if (this.data.lockSwipe) return;
this.data.lockSwipe = true;
if (-this.data.swiperCurIndex >= this.data.goodsList.length - 1) {
return (this.data.lockSwipe = false);
}
const index = e.currentTarget.dataset["index"];
this.setData(
{ ["goodsList[" + index + "].slideClass"]: " ani-slide-up" },
() => {
this.setData({
swiperCurIndex: --this.data.swiperCurIndex
});
}
);
setTimeout(() => {
this.data.lockSwipe = false;
this.setData({
["goodsList[" + index + "].slideClass"]: ""
});
}, 590);
},
prev(e) {
const index = e.currentTarget.dataset["index"] - 1;
if (this.data.lockSwipe || index < 0) return;
this.data.lockSwipe = true;
this.setData({
["goodsList[" + index + "].slideClass"]: " ani-slide-down",
swiperCurIndex: ++this.data.swiperCurIndex
});
setTimeout(() => {
this.data.lockSwipe = false;
this.setData({
["goodsList[" + index + "].slideClass"]: ""
});
}, 590);
}
},
definitionFilter() {},
// 页面生命周期
pageLifetimes: {
// 页面被展示
show() {
const { isPageHidden } = this.data;
// show事件发生前,页面不是处于隐藏状态时
if (!isPageHidden) {
return;
}
// 重新执行定时器等操作
},
// 页面被隐藏
hide() {
this.setData({
isPageHidden: true
});
// 清除定时器等操作
},
// 页面尺寸变化时
resize() {}
}
};
Component(componentOptions);
{
"component": true,
"usingComponents": {
"goods-item": "../GoodsItem/index"
}
}
<view class="container center">
<view class="card-swiper">
<view
wx:for="{{goodsList}}"
wx:key="index"
data-index="{{index}}"
class="{{'card-swiper-item curdistance' + (swiperCurIndex + index) + (!!item.slideClass? item.slideClass: '')}}"
bindtouchstart="touchCard.start"
bindtouchmove="touchCard.move"
bindtouchend="touchCard.end"
bindtouchcancel="touchCard.cancel"
>
<goods-item
style="width:100%"
datas="{{datas}}"
items="{{goodsList[index]}}"
indexs="{{index}}"
></goods-item>
</view>
</view>
</view>
.container{
width: 100%;
height: 200rpx;
padding: 0 0 20rpx;
}
/**index.wxss**/
.card-swiper{
position: relative;
width: 100%;
height: 100%;
color: #666;
font-size: 28rpx;
}
.card-swiper-item{
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
width: 92%;
transition: all .3s ease-out;
z-index: 0;
display: none;
overflow: hidden;
}
.card-swiper .card-swiper-item.curdistance0{
z-index: 10;
display: flex;
}
.card-swiper .card-swiper-item.curdistance1{
display: flex;
z-index: 9;
transform: scale(.95);
opacity: .7;
left: 40rpx;
}
.card-swiper .card-swiper-item.curdistance2{
display: flex;
z-index: 8;
transform: scale(.9);
opacity: .4;
left: 80rpx;
}
.ani-slide-up{
display: flex;
animation: slideUp .6s ease-out;
z-index: 11;
/* transform: rotate(25deg); */
}
.ani-slide-down{
display: flex;
animation: slideUp .6s ease-in;
animation-direction: reverse;
}
@keyframes slideUp{
0% {
}
70% {
opacity: 1;
}
100% {
transform: translateX(-1000rpx);
opacity: 0;
-webkit-transform: translateX(-1000rpx);
-moz-transform: translateX(-1000rpx);
-ms-transform: translateX(-1000rpx);
-o-transform: translateX(-1000rpx);
}
}
\ No newline at end of file
var defaultOption = {
touchStart: function () { },
touchMove: function () { },
touchEnd: function () { },
touchCancel: function () { },
multipointStart: function () { },
multipointEnd: function () { },
tap: function () { },
doubleTap: function () { },
longTap: function () { },
singleTap: function () { },
rotate: function () { },
pinch: function () { },
pressMove: function () { },
swipe: function () { }
}
export default class YrobotTouch {
constructor(pageOBJ, name, option = {}) {
this.preV = { x: null, y: null };
this.pinchStartLen = null;
this.scale = 1;
this.isDoubleTap = false;
this.delta = null;
this.last = null;
this.now = null;
this.tapTimeout = null;
this.singleTapTimeout = null;
this.longTapTimeout = null;
this.swipeTimeout = null;
this.x1 = this.x2 = this.y1 = this.y2 = null;
this.preTapPosition = { x: null, y: null };
this.lastZoom = 1;
this.tempZoom = 1;
try {
if (this._checkBeforeCreate(pageOBJ, name)) {
this._name = name
this._option = { ...defaultOption, ...option }
pageOBJ[name] = this
this._bindFunc(pageOBJ)
}
} catch (error) {
console.error(error)
}
}
_checkBeforeCreate(pageOBJ, name) {
if (!pageOBJ || !name) {
throw new Error('YrobotTouch实例化时,必须传入page对象和引用名')
return false
}
if (pageOBJ[name]) {
throw new Error('YrobotTouch实例化error: ' + name + ' 已经存在page中')
return false
}
return true
}
_bindFunc(pageOBJ) {
let funcNames = ['start', 'move', 'end', 'cancel']
for (let funcName of funcNames)
pageOBJ[this._name + '.' + funcName] = this[funcName].bind(this)
}
start(evt) {
if (!evt.touches) return;
this.now = Date.now();
this.x1 = evt.touches[0].pageX == null ? evt.touches[0].x : evt.touches[0].pageX;
this.y1 = evt.touches[0].pageY == null ? evt.touches[0].y : evt.touches[0].pageY;
this.delta = this.now - (this.last || this.now);
this._option.touchStart(evt);
if (this.preTapPosition.x !== null) {
this.isDoubleTap = (this.delta > 0 && this.delta <= 250 && Math.abs(this.preTapPosition.x - this.x1) < 30 && Math.abs(this.preTapPosition.y - this.y1) < 30);
}
this.preTapPosition.x = this.x1;
this.preTapPosition.y = this.y1;
this.last = this.now;
let preV = this.preV,
len = evt.touches.length;
if (len > 1) {
this._cancelLongTap();
this._cancelSingleTap();
let otx = evt.touches[1].pageX == null ? evt.touches[1].x : evt.touches[1].pageX;
let oty = evt.touches[1].pageY == null ? evt.touches[1].y : evt.touches[1].pageY;
let v = { x: otx - this.x1, y: oty - this.y1 };
preV.x = v.x;
preV.y = v.y;
this.pinchStartLen = getLen(preV);
this._option.multipointStart(evt);
}
this.longTapTimeout = setTimeout(function () {
evt.type = "longTap";
this._option.longTap(evt);
}.bind(this), 750);
}
move(evt) {
if (!evt.touches) return;
let preV = this.preV,
len = evt.touches.length,
currentX = evt.touches[0].pageX == null ? evt.touches[0].x : evt.touches[0].pageX,
currentY = evt.touches[0].pageY == null ? evt.touches[0].y : evt.touches[0].pageY;
this.isDoubleTap = false;
if (len > 1) {
let otx = evt.touches[1].pageX == null ? evt.touches[1].x : evt.touches[1].pageX;
let oty = evt.touches[1].pageY == null ? evt.touches[1].y : evt.touches[1].pageY;
let v = { x: otx - currentX, y: oty - currentY };
if (preV.x !== null) {
if (this.pinchStartLen > 0) {
evt.singleZoom = getLen(v) / this.pinchStartLen;
evt.zoom = evt.singleZoom * this.lastZoom;
this.tempZoom = evt.zoom;
evt.type = "pinch";
this._option.pinch(evt);
}
evt.angle = getRotateAngle(v, preV);
evt.type = "rotate";
this._option.rotate(evt);
}
preV.x = v.x;
preV.y = v.y;
} else {
if (this.x2 !== null) {
evt.deltaX = currentX - this.x2;
evt.deltaY = currentY - this.y2;
} else {
evt.deltaX = 0;
evt.deltaY = 0;
}
this._option.pressMove(evt);
}
this._option.touchMove(evt);
this._cancelLongTap();
this.x2 = currentX;
this.y2 = currentY;
if (len > 1) {
// evt.preventDefault();
}
}
end(evt) {
if (!evt.changedTouches) return;
this._cancelLongTap();
let self = this;
evt.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2); //在结束钩子都加入方向判断,但触发swipe瞬时必须位移大于30
if (evt.touches.length < 2) {
this.lastZoom = this.tempZoom;
this._option.multipointEnd(evt);
}
this._option.touchEnd(evt);
//swipe
if ((this.x2 && Math.abs(this.x1 - this.x2) > 30) ||
(this.y2 && Math.abs(this.y1 - this.y2) > 30)) {
// evt.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2);
this.swipeTimeout = setTimeout(function () {
evt.type = "swipe";
self._option.swipe(evt);
}, 0)
} else {
this.tapTimeout = setTimeout(function () {
evt.type = "tap";
self._option.tap(evt);
// trigger double tap immediately
if (self.isDoubleTap) {
evt.type = "doubleTap";
self._option.doubleTap(evt);
clearTimeout(self.singleTapTimeout);
self.isDoubleTap = false;
}
}, 0)
if (!self.isDoubleTap) {
self.singleTapTimeout = setTimeout(function () {
self._option.singleTap(evt);
}, 250);
}
}
this.preV.x = 0;
this.preV.y = 0;
this.scale = 1;
this.pinchStartLen = null;
this.x1 = this.x2 = this.y1 = this.y2 = null;
}
cancel(evt) {
clearTimeout(this.singleTapTimeout);
clearTimeout(this.tapTimeout);
clearTimeout(this.longTapTimeout);
clearTimeout(this.swipeTimeout);
this._option.touchCancel(evt);
}
_cancelLongTap() {
clearTimeout(this.longTapTimeout);
}
_cancelSingleTap() {
clearTimeout(this.singleTapTimeout);
}
_swipeDirection(x1, x2, y1, y2) {
return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
}
destroy() {
if (this.singleTapTimeout) clearTimeout(this.singleTapTimeout);
if (this.tapTimeout) clearTimeout(this.tapTimeout);
if (this.longTapTimeout) clearTimeout(this.longTapTimeout);
if (this.swipeTimeout) clearTimeout(this.swipeTimeout);
this._option.rotate = null;
this._option.touchStart = null;
this._option.multipointStart = null;
this._option.multipointEnd = null;
this._option.pinch = null;
this._option.swipe = null;
this._option.tap = null;
this._option.doubleTap = null;
this._option.longTap = null;
this._option.singleTap = null;
this._option.pressMove = null;
this._option.touchMove = null;
this._option.touchEnd = null;
this._option.touchCancel = null;
this.preV = this.pinchStartLen = this.scale = this.isDoubleTap = this.delta = this.last = this.now = this.tapTimeout = this.singleTapTimeout = this.longTapTimeout = this.swipeTimeout = this.x1 = this.x2 = this.y1 = this.y2 = this.preTapPosition = this.rotate = this.touchStart = this.multipointStart = this.multipointEnd = this.pinch = this.swipe = this.tap = this.doubleTap = this.longTap = this.singleTap = this.pressMove = this.touchMove = this.touchEnd = this.touchCancel = null;
return null;
}
}
function getLen(v) {
return Math.sqrt(v.x * v.x + v.y * v.y);
}
function dot(v1, v2) {
return v1.x * v2.x + v1.y * v2.y;
}
function getAngle(v1, v2) {
let mr = getLen(v1) * getLen(v2);
if (mr === 0) return 0;
let r = dot(v1, v2) / mr;
if (r > 1) r = 1;
return Math.acos(r);
}
function cross(v1, v2) {
return v1.x * v2.y - v2.x * v1.y;
}
function getRotateAngle(v1, v2) {
let angle = getAngle(v1, v2);
if (cross(v1, v2) > 0) {
angle *= -1;
}
return angle * 180 / Math.PI;
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment