first commit
This commit is contained in:
74
src/components/Loading/bone.vue
Normal file
74
src/components/Loading/bone.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<div class="my-bone">
|
||||
<div class="top">
|
||||
|
||||
</div>
|
||||
<div class="list">
|
||||
<div class="list-item" v-for="item in arr" :key="item">
|
||||
<div class="left"></div>
|
||||
<div class="right">
|
||||
<div class="right_div"></div>
|
||||
<div class="right_div"></div>
|
||||
<div class="right_div"></div>
|
||||
<div class="right_div"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
arr: [1,2,3,4,5,6,7,8,9,10]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.my-bone {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 9999;
|
||||
background: white;
|
||||
padding: 20rpx;
|
||||
overflow: hidden;
|
||||
.top {
|
||||
height: 260rpx;
|
||||
background: #eee;
|
||||
}
|
||||
.list {
|
||||
margin-top: 40rpx;
|
||||
.list-item {
|
||||
margin-top: 40rpx;
|
||||
display: flex;
|
||||
height: 260rpx;
|
||||
}
|
||||
.left {
|
||||
flex: none;
|
||||
width: 200rpx;
|
||||
margin-right: 20rpx;
|
||||
background: #eee;
|
||||
}
|
||||
.right {
|
||||
flex: auto;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: space-between;
|
||||
.right_div{
|
||||
height: 40rpx;
|
||||
background: #eee;
|
||||
}
|
||||
// div {
|
||||
// height: 40rpx;
|
||||
// background: #eee;
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
77
src/components/Loading/loading.scss
Normal file
77
src/components/Loading/loading.scss
Normal file
File diff suppressed because one or more lines are too long
48
src/components/Loading/loading.vue
Normal file
48
src/components/Loading/loading.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="zy-loading" v-if="loadingShow" @touchmove.stop.prevent="moveHandle" :animation="animationData">
|
||||
<div class="zy-loading-mask"></div>
|
||||
<div class="zy-loading-border"></div>
|
||||
<div class="zy-loading-img"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ZYLoading',
|
||||
data () {
|
||||
return {
|
||||
animationData: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
loadingShow() {
|
||||
// console.log('this.$store',this.$store.getters.loading)
|
||||
return this.$store.getters.loading
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
show () {
|
||||
const animation = uni.createAnimation({
|
||||
duration: 500,
|
||||
timingFunction: 'ease-in-out'
|
||||
})
|
||||
animation.opacity(0).step()
|
||||
this.animationData = animation.export()
|
||||
setTimeout(() => {
|
||||
animation.opacity(1).step()
|
||||
this.animationData = animation.export()
|
||||
}, 50)
|
||||
},
|
||||
moveHandle () {}
|
||||
},
|
||||
watch: {
|
||||
loadingShow (to) {
|
||||
// if (to) this.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use './loading';
|
||||
</style>
|
||||
113
src/components/Modal/modal.scss
Normal file
113
src/components/Modal/modal.scss
Normal file
@@ -0,0 +1,113 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.y-modal {
|
||||
position: fixed;
|
||||
z-index: 900;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(black, .6);
|
||||
animation: bounceInUp .8s ease-in-out;
|
||||
|
||||
.y-modal-wrapper {
|
||||
@extend %flex-center;
|
||||
height: 80vh;
|
||||
}
|
||||
}
|
||||
|
||||
.y-promopt {
|
||||
@extend %bgwhite;
|
||||
width: 600rpx;
|
||||
padding: 40rpx;
|
||||
border-radius: 10rpx;
|
||||
box-shadow: 0 2rpx 4rpx rgba(black, .3);
|
||||
border: 1rpx solid #4EB331;
|
||||
@extend %ft30;
|
||||
color: #333;
|
||||
box-sizing: border-box;
|
||||
// .title {
|
||||
// }
|
||||
.textarea {
|
||||
border: 1rpx solid #DCDFE6;
|
||||
@extend %pd20;
|
||||
@extend %ft30;
|
||||
height: 150rpx;
|
||||
border-radius: 10rpx;
|
||||
margin: 40rpx 0 80rpx;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.btn-group {
|
||||
@extend %flex-between;
|
||||
}
|
||||
.btn-cancel, .btn-confirm {
|
||||
@extend %btn-base;
|
||||
}
|
||||
.btn-cancel {
|
||||
margin-right: 20rpx;
|
||||
background: #F56C6C;
|
||||
}
|
||||
}
|
||||
|
||||
.y-confirm-check {
|
||||
@extend %ft32;
|
||||
@extend %bgwhite;
|
||||
border-radius: 6rpx;
|
||||
width: 600rpx;
|
||||
.title {
|
||||
@extend %ft36;
|
||||
padding: 32rpx 0 20rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.icon-text {
|
||||
color: #909399;
|
||||
@extend %flex-center;
|
||||
// line-height: 0;
|
||||
margin-top: 20rpx;
|
||||
.ipt{
|
||||
margin-bottom: 5rpx;
|
||||
border: 1rpx solid #cdcdcd;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
}
|
||||
.icon-check {
|
||||
@extend %bg-no-repeat-center;
|
||||
background-size: 60%;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
border: 1rpx solid #DCDFE6;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.checked {
|
||||
@extend %icon-checked-main;
|
||||
border-color: #4EB331;
|
||||
}
|
||||
.body {
|
||||
padding-bottom: 48rpx;
|
||||
}
|
||||
.text {
|
||||
@extend %ft30;
|
||||
color: #909399;
|
||||
text-align: center;
|
||||
}
|
||||
.btn-group {
|
||||
box-sizing: border-box;
|
||||
border-top: 1rpx solid #eee;
|
||||
@extend %flex-left;
|
||||
}
|
||||
.btn-cancel, .btn-confirm {
|
||||
flex: 1;
|
||||
@extend %ft36;
|
||||
height: 100rpx;
|
||||
@extend %flex-center;
|
||||
}
|
||||
.btn-cancel {
|
||||
color: #909399;
|
||||
border-right: 1rpx solid #eee;
|
||||
}
|
||||
.btn-confirm {
|
||||
color: #4EB331;
|
||||
}
|
||||
}
|
||||
18
src/components/Modal/modal.vue
Normal file
18
src/components/Modal/modal.vue
Normal file
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<div class="y-modal" @click.stop @touchmove.stop.prevent>
|
||||
<!-- <div class="h5-placeholder"></div> -->
|
||||
<div class="y-modal-wrapper">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use "./modal.scss";
|
||||
</style>
|
||||
53
src/components/Modal/promopt.vue
Normal file
53
src/components/Modal/promopt.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<Modal>
|
||||
<div class="y-promopt">
|
||||
<!-- <div class="title">{{title}}:</div> -->
|
||||
<textarea v-model.trim="text" class="textarea" :placeholder="title" auto-focus></textarea>
|
||||
<div class="btn-group">
|
||||
<div @click="cancel" class="btn-cancel">取消</div>
|
||||
<div @click="confirm" class="btn-confirm">确定</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from './modal'
|
||||
export default {
|
||||
components: {
|
||||
Modal
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'textarea'
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
text: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
cancel () {
|
||||
this.$emit('close')
|
||||
},
|
||||
confirm () {
|
||||
if (!this.text) {
|
||||
this.$toast(this.title)
|
||||
return false
|
||||
}
|
||||
this.$emit('confirm', this.text)
|
||||
this.$emit('close')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use "./modal.scss";
|
||||
</style>
|
||||
17
src/components/badge/badge.scss
Normal file
17
src/components/badge/badge.scss
Normal file
@@ -0,0 +1,17 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.y-badge {
|
||||
position: relative;
|
||||
.y-badge-dot {
|
||||
position: absolute;
|
||||
border-radius: 30rpx;
|
||||
background-color: #F56C6C;
|
||||
right: 5rpx;
|
||||
top: 5rpx;
|
||||
font-size: 20rpx;
|
||||
color: white;
|
||||
padding: 6rpx;
|
||||
min-width: 26rpx;
|
||||
@extend %flex-center;
|
||||
}
|
||||
}
|
||||
21
src/components/badge/badge.vue
Normal file
21
src/components/badge/badge.vue
Normal file
@@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<div class="y-badge">
|
||||
<div class="y-badge-dot" v-if="count>0">{{count}}</div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
count: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use './badge.scss';
|
||||
</style>
|
||||
91
src/components/car-group/car-group.scss
Normal file
91
src/components/car-group/car-group.scss
Normal file
@@ -0,0 +1,91 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.car-group {
|
||||
overflow-y: auto;
|
||||
margin: 20rpx auto;
|
||||
background: #eee;
|
||||
// width: 750rpx;
|
||||
// box-sizing: border-box;
|
||||
@extend %pdlr;
|
||||
.car-item{
|
||||
background:#fff;
|
||||
padding:0 20rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
.store-info {
|
||||
@extend %flex-between;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
height: 100rpx;
|
||||
border-bottom: 1rpx solid #E4E7ED;
|
||||
// padding-left: 100rpx;
|
||||
// border: 1rpx solid greenyellow;
|
||||
background-color: #fff;
|
||||
}
|
||||
.circle{
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 20rpx;
|
||||
background-color:#eee;
|
||||
}
|
||||
// .waybillSLG{
|
||||
// border: 1rpx solid red;
|
||||
// width: 150rpx;
|
||||
// padding: 10rpx;
|
||||
// white-space: nowrap;
|
||||
// color: #4EB331;
|
||||
// }
|
||||
.icon-right-aw {
|
||||
flex: none;
|
||||
@extend %icon-aw-right-slim;
|
||||
width: 30rpx;
|
||||
background-position: right center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 30rpx;
|
||||
}
|
||||
.store-name {
|
||||
flex: 1;
|
||||
@extend %oneline;
|
||||
}
|
||||
.store-mobile {
|
||||
flex: none;
|
||||
}
|
||||
.skuName-item{
|
||||
display:flex;
|
||||
// width: 90vw;
|
||||
// border:1rpx solid red;
|
||||
}
|
||||
.skuName-cell {
|
||||
@extend %flex-left;
|
||||
// border-bottom: 1rpx solid #E4E7ED;
|
||||
|
||||
border: 1rpx solid #e2dfdf;
|
||||
margin-bottom: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
background-color: #fff;
|
||||
padding: 10rpx;
|
||||
// display: flex;
|
||||
// width: 100vw;
|
||||
}
|
||||
.delButton{
|
||||
// height: 240rpx;
|
||||
line-height: 140rpx;
|
||||
background: #ff0000;
|
||||
// border: 1rpx solid green;
|
||||
color: #fff;
|
||||
margin-top: 10rpx;
|
||||
margin-left:30rpx;
|
||||
font-size: 30rpx;
|
||||
// width: 100rpx;
|
||||
padding:10rpx 20rpx;
|
||||
}
|
||||
.flex-auto {
|
||||
@extend %flex-auto;
|
||||
}
|
||||
// .skuName-item:last-child{
|
||||
// // margin-bottom: 194rpx;
|
||||
// }
|
||||
}
|
||||
241
src/components/car-group/car-group.vue
Normal file
241
src/components/car-group/car-group.vue
Normal file
@@ -0,0 +1,241 @@
|
||||
<template>
|
||||
<div class="car-group">
|
||||
<div class="car-item">
|
||||
<div class="store-info">
|
||||
<div style="display:flex">
|
||||
<div class="circle"></div>
|
||||
<!-- isMaterial -->
|
||||
<div class="store-name" v-if="isMaterial">物料店</div>
|
||||
<!-- v-if="storeID!=='666666' && storeMap" -->
|
||||
<div class="store-name" v-else >{{storeMap[storeID].name}}</div>
|
||||
<!-- <div class="store-name" v-else="storeID!=='666666'">物料店</div> -->
|
||||
</div>
|
||||
<!-- <div class="waybillSLG">
|
||||
<span >购满¥{{ waybillSLG.satisfy }}减¥{{waybillSLG.reduce}}运费</span>
|
||||
</div>
|
||||
<div style="display:flex">
|
||||
<div>去凑单</div>
|
||||
<div class="icon-right-aw"></div>
|
||||
</div> -->
|
||||
<!-- <div class="store-mobile" @click="call(storeMap[storeID].mobile)">{{storeMap[storeID].mobile}}</div> -->
|
||||
</div>
|
||||
<!-- style="border:1rpx solid red;" -->
|
||||
<div
|
||||
v-for="(skuName, index) in skuNamesNew"
|
||||
:key="index"
|
||||
class="skuName-item"
|
||||
:style="{'transform': 'translateX(' + skuName.offset + 'px)'}"
|
||||
@touchmove="touchmove_cart"
|
||||
@touchstart="touchstart_cart($event,index)"
|
||||
@touchend="touchend_cart"
|
||||
>
|
||||
<div class="skuName-cell">
|
||||
<check-item
|
||||
v-if="!isMaterial"
|
||||
@on-click="checkSkuName(skuName, index)"
|
||||
:checked="skuName.checked"
|
||||
></check-item>
|
||||
<good-cell
|
||||
:titleWidth="isMaterial?'482rpx':'412rpx'"
|
||||
ref="goodCell"
|
||||
class="flex-auto"
|
||||
:index="index"
|
||||
:skuName="skuName"
|
||||
:noBorder="true"
|
||||
:waitShow="false"
|
||||
type="cart"
|
||||
@handleSkuNamePlus="handleSkuNamePlus"
|
||||
@handleSkuNameMinus="handleSkuNameMinus($event, skuName)"
|
||||
@handleSkuNameChange="handleSkuNameChange"
|
||||
></good-cell>
|
||||
</div>
|
||||
<div class="delButton" @click.stop="del(index)" :style="delBtnHenght">删除</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GoodCell from "@/components/goodCmp/good-cell/good-cell.vue";
|
||||
import CheckItem from "@/components/checkItem/check-item.vue";
|
||||
import { errToast, modal } from "@/utils/uniapi.js";
|
||||
import { mapGetters } from "vuex";
|
||||
// import { msgData } from "@/config";
|
||||
export default {
|
||||
components: {
|
||||
GoodCell,
|
||||
CheckItem,
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
shopCar: true,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
storeID: {
|
||||
type: String,
|
||||
},
|
||||
skuNames: {
|
||||
type: Array,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
checked: true,
|
||||
currentIndex: -1,
|
||||
skuNamesNew: [],
|
||||
moveX: 0,
|
||||
offsetDistance: 50,
|
||||
delBtnHenght:'height: 260rpx;' // 140rpx
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// console.log('打印手机系统信息', this.iosOrAndroid, '宽度', this.iosOrAndroid.screenWidth)
|
||||
if (this.iosOrAndroid && this.iosOrAndroid.screenWidth) {
|
||||
this.offsetDistance = (this.iosOrAndroid.screenWidth * 50) / 375
|
||||
// console.log('查看偏移的宽度',this.offsetDistance)
|
||||
}
|
||||
// 750 260*2
|
||||
// 1080 x
|
||||
// x = (this.iosOrAndroid.screenHeight *260*2 )/ (750 * 2)
|
||||
},
|
||||
watch: {
|
||||
skuNames: {
|
||||
handler(val) {
|
||||
this.skuNamesNew = []
|
||||
val.forEach((item,index) => {
|
||||
// #ifdef MP-WEIXIN
|
||||
if (item.checked === false && item.storeID === 666666 ) {
|
||||
this.checkSkuName(item,index)
|
||||
}
|
||||
// #endif
|
||||
this.skuNamesNew.push({
|
||||
...item,
|
||||
offset:0
|
||||
})
|
||||
});
|
||||
},
|
||||
immediate: true,
|
||||
deep:true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
storeMap:"indexPage/storeMap",
|
||||
isMaterial: "indexPage/isMaterial",
|
||||
iosOrAndroid: "iosOrAndroid"
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
// 删除商品
|
||||
async del(index) {
|
||||
this.handleSkuNameChange({index,count:0})
|
||||
},
|
||||
touchstart_cart(e, index) {
|
||||
// console.log('打印移动开始时的信息',e)
|
||||
if (this.currentIndex !== -1 && this.currentIndex !== index) {
|
||||
if (this.skuNamesNew[this.currentIndex]) {
|
||||
this.skuNamesNew[this.currentIndex].offset = 0
|
||||
}
|
||||
}
|
||||
this.moveX = e.changedTouches[0].pageX
|
||||
// this.skuNamesNew[index].offset = -50
|
||||
this.currentIndex = index
|
||||
},
|
||||
touchmove_cart(e) {
|
||||
let distance = 0
|
||||
|
||||
// 向右滑动
|
||||
if (e.changedTouches[0].pageX - this.moveX >= 0) {
|
||||
distance = 0
|
||||
// if (e.changedTouches[0].pageX - this.moveX >= 50) {
|
||||
// distance = 50
|
||||
// } else {
|
||||
// distance = e.changedTouches[0].pageX - this.moveX
|
||||
// }
|
||||
}
|
||||
|
||||
// 向左滑动
|
||||
if (e.changedTouches[0].pageX - this.moveX < 0) {
|
||||
if (Math.abs(e.changedTouches[0].pageX - this.moveX) >= this.offsetDistance) {
|
||||
// distance = -50
|
||||
distance = - this.offsetDistance
|
||||
} else {
|
||||
distance = 0 - Math.abs(e.changedTouches[0].pageX - this.moveX)
|
||||
}
|
||||
}
|
||||
|
||||
// 偏移
|
||||
this.skuNamesNew[this.currentIndex].offset = distance
|
||||
},
|
||||
// 手指松开后
|
||||
touchend_cart(e) {
|
||||
let distance = e.changedTouches[0].pageX - this.moveX
|
||||
if (distance >0) {
|
||||
// this.skuNamesNew[this.currentIndex].offset = distance >= 50?50: 0
|
||||
this.skuNamesNew[this.currentIndex].offset = 0
|
||||
}
|
||||
if(distance<0) {
|
||||
this.skuNamesNew[this.currentIndex].offset = Math.abs(distance) >= this.offsetDistance?0-this.offsetDistance: 0
|
||||
}
|
||||
},
|
||||
// 商品 +
|
||||
handleSkuNamePlus(index) {
|
||||
this.$emit("handleSkuNamePlus", {
|
||||
index,
|
||||
key: this.storeID,
|
||||
});
|
||||
},
|
||||
// 商品 -
|
||||
handleSkuNameMinus(index, skuName, count = 2) {
|
||||
// console.log('商品减少--------')
|
||||
this.$emit("handleSkuNameMinus", {
|
||||
index,
|
||||
key: this.storeID,
|
||||
countNew:count
|
||||
});
|
||||
},
|
||||
handleSkuNameChange({ index, count }) {
|
||||
this.$emit("handleSkuNameChange", {
|
||||
index,
|
||||
count,
|
||||
key: this.storeID,
|
||||
});
|
||||
},
|
||||
// check商品
|
||||
async checkSkuName(skuName, index) {
|
||||
try {
|
||||
|
||||
// 修改store里面
|
||||
await this.$store.dispatch("cartPage/checkSkuName", {
|
||||
skuName,
|
||||
checkStatus: !skuName.checked,
|
||||
});
|
||||
// 通知父级修改
|
||||
this.$emit("handleSkuNameCheck", {
|
||||
index,
|
||||
key: this.storeID,
|
||||
checkStatus: !skuName.checked,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
errToast(e);
|
||||
}
|
||||
},
|
||||
// 打电话
|
||||
async call(phoneNumber) {
|
||||
if (phoneNumber) {
|
||||
let confirm = await modal("拨打电话", "是否拨打门店电话");
|
||||
if (confirm) uni.makePhoneCall({ phoneNumber });
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use "./car-group.scss";
|
||||
</style>
|
||||
24
src/components/checkItem/check-item.scss
Normal file
24
src/components/checkItem/check-item.scss
Normal file
@@ -0,0 +1,24 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.y-check-box {
|
||||
flex: none;
|
||||
@extend %flex-left;
|
||||
.check-cirle {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
border: 1rpx solid #DCDFE6;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
.checked {
|
||||
@extend %icon-checked;
|
||||
background-color: #4EB331;
|
||||
@extend %bg-no-repeat-center;
|
||||
background-size: 52%;
|
||||
}
|
||||
.y-checkbox-text {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
53
src/components/checkItem/check-item.vue
Normal file
53
src/components/checkItem/check-item.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<div class="y-check-box" @click="handleClick">
|
||||
<div
|
||||
:class="{
|
||||
'check-cirle': true,
|
||||
'checked': checked
|
||||
}"
|
||||
:style="{
|
||||
width: width + 'rpx',
|
||||
height: height + 'rpx'
|
||||
}"
|
||||
>
|
||||
</div>
|
||||
<div class="y-checkbox-text" :style="{'font-size': fontSize + 'rpx'}" v-if="text">{{text}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'checkItem',
|
||||
props: {
|
||||
checked: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
default: 50
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 50
|
||||
},
|
||||
fontSize: {
|
||||
type: Number,
|
||||
default: 32
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick () {
|
||||
this.$emit('on-click')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use './check-item.scss'
|
||||
</style>
|
||||
31
src/components/commonCmp/img-lazy/img-lazy.scss
Normal file
31
src/components/commonCmp/img-lazy/img-lazy.scss
Normal file
@@ -0,0 +1,31 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.img-lazy-load {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.img-thumb, .img-origin {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
filter: blur(1vw);
|
||||
object-fit: fill;
|
||||
}
|
||||
.img-origin {
|
||||
animation: fadeIn .2s;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
filter: blur(1vw);
|
||||
// transform: scale(1.05);
|
||||
}
|
||||
to {
|
||||
filter: blur(0);
|
||||
// transform: scale(1);
|
||||
}
|
||||
}
|
||||
52
src/components/commonCmp/img-lazy/img-lazy.vue
Normal file
52
src/components/commonCmp/img-lazy/img-lazy.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div class="img-lazy-load">
|
||||
<!-- | img150type2 -->
|
||||
<image class="img-thumb" :mode="mode" :src="src" @load="imgOnload" @error="errorImg"></image>
|
||||
<image v-if="originSrc" class="img-origin" :mode="mode" :src="url"></image>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'aspectFill'
|
||||
},
|
||||
src: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
clip: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
originSrc: '',
|
||||
url:''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
errorImg(e) {
|
||||
console.log('图片加载错误',e)
|
||||
},
|
||||
// 图片加载完成
|
||||
imgOnload () {
|
||||
this.url = this.src.includes('https') ? this.src : this.src.replace('http','https')
|
||||
uni.getImageInfo({
|
||||
// src: this.src.replace('http://', 'https://') + `?` + this.clip,
|
||||
src: this.url,
|
||||
success: ({path}) => {
|
||||
// console.log('path',path)
|
||||
this.originSrc = path
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use './img-lazy.scss';
|
||||
</style>
|
||||
29
src/components/commonCmp/list-none.scss
Normal file
29
src/components/commonCmp/list-none.scss
Normal file
@@ -0,0 +1,29 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.cmp-list-none {
|
||||
@extend %flex-center;
|
||||
flex-flow: column;
|
||||
.list-none-img {
|
||||
width: 300rpx;
|
||||
height: 300rpx;
|
||||
@extend %bg-no-repeat-center;
|
||||
@extend %bg-size-100;
|
||||
}
|
||||
.img-noGoods {
|
||||
@extend %img-noGoods;
|
||||
}
|
||||
.img-noOrders {
|
||||
@extend %img-noOrders;
|
||||
}
|
||||
.img-noShopCar {
|
||||
@extend %img-noShopCar;
|
||||
}
|
||||
.img-noPosition {
|
||||
@extend %icon-no-position;
|
||||
}
|
||||
.list-none-msg {
|
||||
font-size: 32rpx;
|
||||
color: #909399;
|
||||
padding-top: 30rpx;
|
||||
}
|
||||
}
|
||||
32
src/components/commonCmp/list-none.vue
Normal file
32
src/components/commonCmp/list-none.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div class="cmp-list-none">
|
||||
<div :class="{
|
||||
'list-none-img': true,
|
||||
'img-noGoods': img === 'img-noGoods',
|
||||
'img-noShopCar': img === 'img-noShopCar',
|
||||
'img-noOrders': img === 'img-noOrders',
|
||||
'img-noPosition': img === 'img-noPosition'
|
||||
}"></div>
|
||||
<div class="list-none-msg">{{msg}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
img: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'img-noGoods'
|
||||
},
|
||||
msg: {
|
||||
type: String,
|
||||
default: '没有查询到东西'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use './list-none.scss';
|
||||
</style>
|
||||
53
src/components/commonCmp/search-input/search-input.scss
Normal file
53
src/components/commonCmp/search-input/search-input.scss
Normal file
@@ -0,0 +1,53 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.cmp-search-input {
|
||||
@extend %flex-center;
|
||||
.input-wrapper {
|
||||
// position: relative;
|
||||
flex: 1;
|
||||
background-color: #efefef;
|
||||
// padding: 10rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50rpx;
|
||||
@extend %flex-center;
|
||||
height: 60rpx;
|
||||
}
|
||||
.input {
|
||||
flex: auto;
|
||||
color: #333;
|
||||
width: 100%;
|
||||
font-size: 30rpx;
|
||||
padding: 10rpx;
|
||||
}
|
||||
.input-placeholder {
|
||||
color: #666;
|
||||
}
|
||||
.icon-search, .icon-delete {
|
||||
flex: none;
|
||||
// position: absolute;
|
||||
top: 50%;
|
||||
// transform: translateY(-50%);
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
@extend %bg-no-repeat-center;
|
||||
background-size: 30rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
.icon-search {
|
||||
left: 10rpx;
|
||||
@extend %icon-search;
|
||||
}
|
||||
.icon-delete {
|
||||
right: 10rpx;
|
||||
@extend %icon-delete;
|
||||
}
|
||||
.btn-search {
|
||||
font-size: 30rpx;
|
||||
margin-left:20rpx;
|
||||
color: #fff;
|
||||
border-radius: 70rpx;
|
||||
padding: 10rpx 20rpx;
|
||||
background-color: rgb(129, 190, 78);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
67
src/components/commonCmp/search-input/search-input.vue
Normal file
67
src/components/commonCmp/search-input/search-input.vue
Normal file
@@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<div class="cmp-search-input">
|
||||
<div class="input-wrapper">
|
||||
<div class="icon-search"></div>
|
||||
<input
|
||||
v-model.trim="text"
|
||||
class="input"
|
||||
type="text"
|
||||
:placeholder="placeholder"
|
||||
placeholder-class="input-placeholder"
|
||||
confirm-type="search"
|
||||
@input="handleInput"
|
||||
@confirm="handleConfirm"
|
||||
:focus="focus"
|
||||
>
|
||||
<div v-if="text" class="icon-delete" @click="handleDelete"></div>
|
||||
</div>
|
||||
<div v-if="searchBtnShow" class="btn-search" @click="handleConfirm">搜索</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {debounce} from '@/utils'
|
||||
export default {
|
||||
props: {
|
||||
searchBtnShow: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请输入商品名称'
|
||||
},
|
||||
focus: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
text: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleInput: debounce(function (e) {
|
||||
// console.log(e.detail.value)
|
||||
let value = e.detail.value
|
||||
// console.log(value)
|
||||
this.$emit('on-change', value)
|
||||
}, 500),
|
||||
handleConfirm (e) {
|
||||
// console.log(e.detail.value)
|
||||
let value = e.detail.value || this.text
|
||||
// console.log(value)
|
||||
this.$emit('on-change', value)
|
||||
},
|
||||
handleDelete () {
|
||||
this.text = ''
|
||||
this.$emit('on-change', '')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use './search-input.scss';
|
||||
</style>
|
||||
38
src/components/goodCmp/Search/search-btn.vue
Normal file
38
src/components/goodCmp/Search/search-btn.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="zy-search-btn" :class="{'showBtn':isShowBtn===true}" @click="handleClick" :style="{background: background, color: color}">
|
||||
<div class="zy-search-btn" >
|
||||
<div class="icon"></div>
|
||||
<div class="placeholder" >{{name}}</div>
|
||||
</div>
|
||||
<div v-if="isShowBtn" class="searchBtn" >搜索</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ZySearchBtn',
|
||||
props: {
|
||||
name: {
|
||||
default: '请输入商品名称'
|
||||
},
|
||||
background: {
|
||||
default: '#f5f5f5'
|
||||
},
|
||||
color: {
|
||||
default: '#cccccc'
|
||||
},
|
||||
isShowBtn: {
|
||||
default:false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick () {
|
||||
this.$emit('click')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use "./search.scss";
|
||||
</style>
|
||||
31
src/components/goodCmp/Search/search.scss
Normal file
31
src/components/goodCmp/Search/search.scss
Normal file
@@ -0,0 +1,31 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.zy-search-btn {
|
||||
height: 70rpx;
|
||||
@extend %flex-center;
|
||||
font-size: 30rpx;
|
||||
border-radius: 70rpx;
|
||||
.icon {
|
||||
// 放大镜
|
||||
// @include svg_icon(search, a8a8a8);
|
||||
@extend %icon-search;
|
||||
@extend %bg-no-repeat-center;
|
||||
@extend %bg-size-100;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin-right: 10rpx;
|
||||
margin-left:10rpx;
|
||||
}
|
||||
}
|
||||
.showBtn{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.searchBtn{
|
||||
// 搜索按钮
|
||||
padding:10rpx 20rpx;
|
||||
border-radius: 25rpx;
|
||||
margin-right: 10rpx;
|
||||
background: rgb(129, 190, 78);
|
||||
color:#fff;
|
||||
}
|
||||
120
src/components/goodCmp/good-cell-index/good-cell-big.scss
Normal file
120
src/components/goodCmp/good-cell-index/good-cell-big.scss
Normal file
@@ -0,0 +1,120 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.good-cell-big {
|
||||
@extend %pd20;
|
||||
@extend %bgwhite;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 0 4rpx rgba(#DCDFE6, 1);
|
||||
border-radius: 10rpx;
|
||||
.good-img {
|
||||
width: 300rpx;
|
||||
height: 300rpx;
|
||||
.good-img-size{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.good-name {
|
||||
font-size: 28rpx;
|
||||
margin-top: 20rpx;
|
||||
color: #333;
|
||||
height: 4em;
|
||||
overflow: hidden;
|
||||
text-align: justify;
|
||||
line-height: 1.2;
|
||||
|
||||
}
|
||||
.good-price {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.btn-wait{
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
}
|
||||
.btn-self{
|
||||
color: #fff;
|
||||
background-color: rgba(78, 179, 49, 0.6);
|
||||
}
|
||||
.countTime-wrap{
|
||||
height: 17rpx;
|
||||
width: 100%;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.countTime{
|
||||
color: #E6A23C;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.stock-and-waitPirce{
|
||||
display: flex;
|
||||
}
|
||||
.price {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
.unit{
|
||||
font-size:28rpx;
|
||||
color:#fe6263;
|
||||
}
|
||||
}
|
||||
.ori-price {
|
||||
font-size: 20rpx;
|
||||
color: #b2b2b2;
|
||||
margin-left: 10rpx;
|
||||
text-decoration: line-through;
|
||||
&:before {
|
||||
content: "¥";
|
||||
}
|
||||
}
|
||||
.act-type-wrapper {
|
||||
height: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.act-type {
|
||||
@extend %act-type-text;
|
||||
}
|
||||
.check-detail{
|
||||
font-size:28rpx;
|
||||
color:rgba(78, 179, 49, 0.6);
|
||||
}
|
||||
.handle-shopcar {
|
||||
margin-top: 20rpx;
|
||||
height: 50rpx;
|
||||
}
|
||||
.add-cart{
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
font-size:30rpx;
|
||||
background:#81be4e;
|
||||
color:#fff;
|
||||
text-align:center;
|
||||
border-radius:20rpx;
|
||||
margin-top:10rpx;
|
||||
}
|
||||
}
|
||||
// #ifdef MP-KUAISHOU
|
||||
.viewDetail{
|
||||
// border:1px solid red;
|
||||
text-align: center;
|
||||
background: rgba(78, 179, 49, 0.8);
|
||||
border-radius: 20rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
color:#fff;
|
||||
}
|
||||
// #endif
|
||||
|
||||
|
||||
// .good-cell-big{
|
||||
// box-sizing: border-box;
|
||||
// box-shadow: 0 0 4rpx rgba(#DCDFE6, 1);
|
||||
// border-radius: 10rpx;
|
||||
// .good-img {
|
||||
// width: 300rpx;
|
||||
// height: 300rpx;
|
||||
// img {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
221
src/components/goodCmp/good-cell-index/good-cell-big.vue
Normal file
221
src/components/goodCmp/good-cell-index/good-cell-big.vue
Normal file
@@ -0,0 +1,221 @@
|
||||
<template>
|
||||
<div class="good-cell-big" ref="" @click="toGoodDetail" >
|
||||
<div class="good-img" v-if="skuName.img">
|
||||
<img class="good-img-size" :src="skuName.img" alt="加载中..." />
|
||||
</div>
|
||||
<div class="good-name" v-if="skuName.name">{{skuName.name}}</div>
|
||||
<div class="countTime-wrap">
|
||||
<div class="countTime" v-if="skuName.actType===5 && skuName.actPrice!==0 && skuName.trendType !==0 && timeTen">{{skuName.trendType===2 ? '降价' :'升价'}}还剩 {{msg}}</div>
|
||||
</div>
|
||||
<div class="priceStyle" v-if="skuName.unit">
|
||||
<span>每</span>
|
||||
<!-- <span v-if="isB2B">斤</span> -->
|
||||
<span v-if="!isB2B || isMaterial">{{skuName.unit}}</span>
|
||||
<span v-else>斤</span>
|
||||
<span>约为</span>
|
||||
<!-- <span class="priceColor" v-if="isMaterial || isB2B">{{$filters.toFixed2(price*100)}}</span> -->
|
||||
<span class="priceColor" v-if="isMaterial">{{$filters.toFixed2(skuName.curPrice)}}</span>
|
||||
<span class="priceColor" v-else-if="isB2B">{{$filters.toFixed2(skuName.price*100)}}</span>
|
||||
<span class="priceColor" v-else>{{$filters.toFixed2(skuName.curPrice)}}</span>
|
||||
<span>元(以实际价格为准)</span>
|
||||
</div>
|
||||
<div class="good-price" v-if="newPrice">
|
||||
<div class="price">
|
||||
<div class="good-price" >
|
||||
<span>¥</span>
|
||||
<span class="good-price-font" >{{newPrice }}</span>
|
||||
</div>
|
||||
<span class="unit" v-if="isMaterial || isB2B">/{{skuName.unit}}</span>
|
||||
<!-- <span class="unit" v-if="isB2B">/{{skuName.unit}}</span> -->
|
||||
<span class="unit" v-else>/斤</span>
|
||||
<div class="ori-price" v-if="skuName.oriPrice && !isMaterial" >{{$filters.toFixed2(skuName.oriPrice)}}</div>
|
||||
</div>
|
||||
<div class="act-type-wrapper">
|
||||
<div class="act-type" v-if="skuName.actType">{{actTypeArr[skuName.actType]}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="add-cart" @click.stop="addCart" v-if="skuName.count===0 && isShowShop">加入购物车</div>
|
||||
<template v-if="skuName.count!==0 && isShowShop">
|
||||
<div class="handle-shopcar" @click.stop="clickStop" v-if="skuName.id !== 6031118">
|
||||
<plus-minus :skuName="skuName" :count="skuName.count" type="input" @clickPlus="handlePlus" @clickMinus="handleMinus" @countChange="countChange"></plus-minus>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from "vuex";
|
||||
import { toast, modal, errToast,jumpPage } from "@/utils/uniapi.js";
|
||||
import PlusMinus from "@/components/goodCmp/plus-minus/plus-minus";
|
||||
import { msgData, actTypeArr } from "@/config";
|
||||
// import orderPage from '@/apis/orderPage'
|
||||
// import { handleCreatePay } from '@/utils/uniapi.js'
|
||||
export default {
|
||||
components: {
|
||||
PlusMinus
|
||||
},
|
||||
props: {
|
||||
skuName: Object,
|
||||
index: {
|
||||
type: Number,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
actTypeArr,
|
||||
fromTime: null,
|
||||
toTime: null,
|
||||
modalShow: false,
|
||||
msg: "",
|
||||
num: null,
|
||||
// price: null,
|
||||
price: 0,
|
||||
checked: false,
|
||||
preCreateData: {},
|
||||
highPrice: null,
|
||||
lowPrice: null
|
||||
// imgUrl:'https://image.jxc4.com/image/8a98a93946f9f70dd84960c06725f4fb.jpg'
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
storeID:"indexPage/storeID",
|
||||
defaultAddress: "addressVue/defaultAddress",
|
||||
isB2B:'indexPage/isB2B',
|
||||
isLogin: "login/isLogin",
|
||||
isShowShop: "isShowShop",
|
||||
isMaterial: "indexPage/isMaterial",
|
||||
materialInfo:"indexPage/materialInfo"
|
||||
}),
|
||||
newPrice(){
|
||||
let priceStr = ''
|
||||
// let curPrice = this.isB2B ? this.skuName.curPrice : this.price * 100
|
||||
let curPrice = this.isMaterial ? this.skuName.curPrice : this.isB2B ? this.skuName.curPrice : this.price * 100
|
||||
// let curPrice = this.isB2B ? this.skuName.curPrice : this.price
|
||||
// console.log(this.isB2B,'打印当前的价格',curPrice,'skuName',this.skuName.curPrice,'this.price',this.price)
|
||||
if (curPrice !== 0) {
|
||||
priceStr = ((curPrice/100).toFixed(2)).split('.')[0] + '.' + ((curPrice/100).toFixed(2)).split('.')[1]
|
||||
}
|
||||
return priceStr
|
||||
}
|
||||
},
|
||||
created() {
|
||||
let weight = this.skuName.weight ? this.skuName.weight : 1
|
||||
this.price = ((this.skuName.curPrice / 100) / weight) * 500;
|
||||
// if (this.skuName.id === 6041958 ) {
|
||||
// console.log(this.skuName.curPrice / 100,'this.price',this.price,'weight')
|
||||
// }
|
||||
|
||||
},
|
||||
methods: {
|
||||
// // 设置图片信息
|
||||
// setImgInfo() { // val
|
||||
// this.imgUrl = this.skuName.img
|
||||
// },
|
||||
// 加入购物车
|
||||
addCart(){
|
||||
// console.log('添加购物车')
|
||||
if(!this.isLogin){
|
||||
toast('请登录')
|
||||
jumpPage('switchTab','/pages/mine/index',800)
|
||||
return
|
||||
}
|
||||
this.handlePlus()
|
||||
},
|
||||
// 阻止点击事传播
|
||||
clickStop(){
|
||||
// console.log('阻止点击事件传播')
|
||||
},
|
||||
//守家
|
||||
waitPriceDown(x) {
|
||||
this.modalShow = true;
|
||||
console.log(x);
|
||||
},
|
||||
close() {
|
||||
this.modalShow = false;
|
||||
},
|
||||
async handlePlus() {
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// if (this.isMaterial && this.skuName.id === 6039382 && this.materialInfo && this.materialInfo.fromStoreInfo && this.materialInfo.fromStoreInfo.packageSwitch === 1) {
|
||||
// toast('禁止购买物料袋,请联系运营')
|
||||
// return
|
||||
// }
|
||||
// #endif
|
||||
|
||||
this.$emit("handleSkuNamePlus", this.index);
|
||||
},
|
||||
async handleMinus() {
|
||||
if (this.skuName.count === 1) {
|
||||
let confirm = await modal("温馨提示", msgData.delGoods);
|
||||
if (!confirm) return
|
||||
}
|
||||
this.$emit("handleSkuNameMinus", this.index);
|
||||
},
|
||||
async countChange(count) {
|
||||
try {
|
||||
// await this.changeCar({
|
||||
// skuName: this.skuName,
|
||||
// count,
|
||||
// });
|
||||
this.$emit("handleSkuNameChange", {
|
||||
index: this.index,
|
||||
count,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
errToast(e);
|
||||
}
|
||||
},
|
||||
// 跳转到商品详情页
|
||||
toGoodDetail() {
|
||||
if (this.shopCar) return false;
|
||||
jumpPage('navigateTo',`/pagesGoods/good-detail/index?skuID=${this.skuName.id}&storeID=${this.skuName.storeID}`)
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use "./good-cell-big.scss";
|
||||
.red {
|
||||
flex: 1;
|
||||
color: #fe6263;
|
||||
margin: 10rpx 0;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.gray {
|
||||
flex: 1;
|
||||
color: #999;
|
||||
margin: 10rpx 0;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.priceStyle{
|
||||
color: rgb(149, 209,131);
|
||||
font-size: 25rpx;
|
||||
margin-bottom:10rpx;
|
||||
}
|
||||
.priceColor{
|
||||
color:#fe6263;
|
||||
}
|
||||
|
||||
|
||||
.good-price {
|
||||
font-size: 32rpx;
|
||||
color: #fe6263;
|
||||
font-weight: 500;
|
||||
// &:before {
|
||||
// content: "¥";
|
||||
// font-size: 28rpx;
|
||||
// }
|
||||
|
||||
&-font{
|
||||
font-size: 38rpx;
|
||||
&:after{
|
||||
// content: ".";
|
||||
font-size: 28rpx;
|
||||
padding:0 5rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
129
src/components/goodCmp/good-cell/good-cell.scss
Normal file
129
src/components/goodCmp/good-cell/good-cell.scss
Normal file
@@ -0,0 +1,129 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.good-cell {
|
||||
// @extend %pd20;
|
||||
padding: 30rpx 0;
|
||||
display: flex;
|
||||
// border-bottom: 1rpx solid #F2F6FC;
|
||||
border-bottom: 1rpx solid #dadada;
|
||||
.good-img {
|
||||
flex: none;
|
||||
width: 150rpx;
|
||||
height: 150rpx;
|
||||
.good-img-size{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
// img {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// }
|
||||
}
|
||||
.good-info {
|
||||
flex: auto;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
.lookDetail{
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
font-size:30rpx;
|
||||
background:#81be4e;
|
||||
color:#fff;
|
||||
text-align:center;
|
||||
border-radius:20rpx;
|
||||
margin-top:10rpx;
|
||||
}
|
||||
.good-name {
|
||||
font-size: 30rpx;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
min-height: 80rpx;
|
||||
line-height: 1.1;
|
||||
}
|
||||
.btn-wait{
|
||||
flex: 1;
|
||||
}
|
||||
.btn-self{
|
||||
color: #fff;
|
||||
background-color: rgba(78, 179, 49, 0.6);
|
||||
}
|
||||
.countTime-wrap{
|
||||
height: 17px;
|
||||
width: 100%;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
.countTime{
|
||||
color: #E6A23C;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.stock-and-waitPirce{
|
||||
display: flex;
|
||||
}
|
||||
.act-type-wrapper {
|
||||
height: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.act-type {
|
||||
@extend %act-type-text;
|
||||
}
|
||||
.good-price {
|
||||
@extend %flex-between;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.price {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
.cur-price {
|
||||
font-size: 32rpx;
|
||||
color: #fe6263;
|
||||
font-weight: 700;;
|
||||
&:before {
|
||||
content: "¥";
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
.ori-price {
|
||||
font-size: 20rpx;
|
||||
color: #b2b2b2;
|
||||
margin-left: 10rpx;
|
||||
text-decoration: line-through;
|
||||
&:before {
|
||||
content: "¥";
|
||||
}
|
||||
}
|
||||
.handle-shopcar {
|
||||
flex: none;
|
||||
// background: red;
|
||||
margin-left: auto;
|
||||
height: 60rpx;
|
||||
@extend %flex-center;
|
||||
}
|
||||
.cart-act-count {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: flex-end;
|
||||
line-height: 1;
|
||||
.act-count-show {
|
||||
width: 220rpx;
|
||||
@extend %flex-between;
|
||||
}
|
||||
}
|
||||
.add-cart{
|
||||
width: 200rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
font-size:30rpx;
|
||||
background:#81be4e;
|
||||
color:#fff;
|
||||
text-align:center;
|
||||
border-radius:20rpx;
|
||||
// border:1rpx solid red;
|
||||
}
|
||||
}
|
||||
|
||||
.no-border{
|
||||
border-bottom: 1rpx solid #fff !important;
|
||||
}
|
||||
212
src/components/goodCmp/good-cell/good-cell.vue
Normal file
212
src/components/goodCmp/good-cell/good-cell.vue
Normal file
@@ -0,0 +1,212 @@
|
||||
<template>
|
||||
<div @click="toGoodDetail" :class="{
|
||||
'good-cell': true,
|
||||
'no-border': noBorder
|
||||
}">
|
||||
<div class="good-img" v-if="skuName && skuName.img">
|
||||
<img :src="$filters.urlToHttps(skuName.img)" alt="加载中..." class="good-img-size"/>
|
||||
</div>
|
||||
<div class="good-info">
|
||||
<!-- style="width: 412rpx;" 193px-->
|
||||
<!-- width:fit-content -->
|
||||
<div class="good-name" :style="{'width':titleWidth}">{{skuName.name}}</div>
|
||||
|
||||
<div class="countTime-wrap" v-if="skuName.actType===5 &&skuName.actPrice!==0 &&skuName.trendType !==0 && timeTen && waitShow">
|
||||
<div class="countTime" >{{skuName.trendType===2 ? '降价' :'升价'}}还剩 {{msg}}</div>
|
||||
</div>
|
||||
<div class="act-type-wrapper">
|
||||
<div class="act-type" v-if="skuName.actType">{{actTypeArr[skuName.actType]}}</div>
|
||||
</div>
|
||||
<!-- v-if="isShowShop" -->
|
||||
<div class="good-price">
|
||||
<div class="price">
|
||||
<good-price :price="skuName.curPrice"></good-price>
|
||||
<div class="ori-price" v-if="skuName && skuName.oriPrice && !isMaterial">{{$filters.toFixed2(skuName.oriPrice)}}</div>
|
||||
</div>
|
||||
|
||||
<div class="add-cart" @click.stop="addCart" v-if="skuName.count===0 && isShowShop">加入购物车</div>
|
||||
<!-- #ifdef MP-TOUTIAO || APP-PLUS -->
|
||||
<!-- @click.stop="addCart" v-if="skuName.count===0" -->
|
||||
<div class="add-cart" v-if="!isShowShop">查看详情</div>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- v-if="skuName.count!==0 && isShowShop" -->
|
||||
<template v-if="skuName.count!==0 && isShowShop">
|
||||
<div class="handle-shopcar" @click.stop="clickStop" v-if="skuName.id !== 6031118" >
|
||||
<plus-minus type="input" :skuName="skuName" :count="skuName.count" @clickPlus="handlePlus" @clickMinus="handleMinus" @countChange="countChange"></plus-minus>
|
||||
</div>
|
||||
</template>
|
||||
<!-- <div v-if="!isShowShop" class="lookDetail" style="border:1rpx solid red">查看详情</div> -->
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 购物车活动商品普通商品分层 -->
|
||||
<div class="cart-act-count" v-if="type === 'cart' && skuName.actType && skuName.count > 1">
|
||||
<div class="act-count-show">
|
||||
<span>{{$filters.toFixed2(skuName.curPrice)}}</span>
|
||||
<span>x1</span>
|
||||
</div>
|
||||
<div class="act-count-show">
|
||||
<span>{{$filters.toFixed2(skuName.oriPrice)}}</span>
|
||||
<span>x{{skuName.count - 1}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from "vuex";
|
||||
import { toast, modal, errToast,jumpPage } from "@/utils/uniapi.js";
|
||||
import PlusMinus from "@/components/goodCmp/plus-minus/plus-minus";
|
||||
import { actTypeArr } from "@/config";
|
||||
|
||||
import GoodPrice from '@/components/goodCmp/good-price/good-price'
|
||||
import orderPage from '@/apis/orderPage'
|
||||
import { handleCreatePay } from '@/utils/uniapi.js'
|
||||
export default {
|
||||
name: "goodCell",
|
||||
inject: {
|
||||
shopCar: {
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
PlusMinus,
|
||||
GoodPrice
|
||||
},
|
||||
props: {
|
||||
skuName: {
|
||||
type: Object,
|
||||
// default() {
|
||||
// return {};
|
||||
// },
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
},
|
||||
noBorder: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
waitShow: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
titleWidth: {
|
||||
type: String,
|
||||
default:'390rpx'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
countTime: "countTime",
|
||||
storeID:"indexPage/storeID",
|
||||
defaultAddress: "addressVue/defaultAddress",
|
||||
isLogin:"login/isLogin",
|
||||
isShowShop: "isShowShop",
|
||||
isMaterial: "indexPage/isMaterial"
|
||||
}),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
actTypeArr,
|
||||
msg: "",
|
||||
modalShow: false,
|
||||
fromTime: null,
|
||||
toTime: null,
|
||||
num: null,
|
||||
price: null,
|
||||
beforeCreateData: {},
|
||||
timer: null,
|
||||
highPrice: null,
|
||||
lowPrice: null,
|
||||
timeTen: true,
|
||||
imgUrl:'https://image.jxc4.com/image/8a98a93946f9f70dd84960c06725f4fb.jpg'
|
||||
};
|
||||
},
|
||||
beforeDestroy() {
|
||||
clearInterval(this.timer);
|
||||
},
|
||||
methods: {
|
||||
// 加入购物车
|
||||
addCart() {
|
||||
if (!this.isLogin) {
|
||||
errToast('请登录')
|
||||
jumpPage('switchTab', '/pages/mine/index', 800)
|
||||
return
|
||||
}
|
||||
this.handlePlus()
|
||||
},
|
||||
clickStop(){
|
||||
// console.log('阻止点击事件传递')
|
||||
},
|
||||
waitPriceDown(x) {
|
||||
this.modalShow = true;
|
||||
console.log(x);
|
||||
},
|
||||
|
||||
close() {
|
||||
this.modalShow = false;
|
||||
},
|
||||
//倒计时
|
||||
countDown(time1) {
|
||||
if (this.toTime > new Date()) {
|
||||
let res = ((new Date(time1) - new Date()) / (1000 * 60)) % 10;
|
||||
let minutes = Math.floor(res);
|
||||
let seconds = Math.floor((res * 60) % 60);
|
||||
//console.log(seconds.toString().length);
|
||||
if (seconds.toString().length < 2) {
|
||||
seconds = "0" + seconds;
|
||||
}
|
||||
this.msg = "0" + minutes + "分 : " + seconds + "秒";
|
||||
}
|
||||
},
|
||||
//销量
|
||||
stock() {
|
||||
let num = this.skuName.stock;
|
||||
if (num >= 1000) {
|
||||
return "库存:1000+";
|
||||
} else if (num < 1000 && num > 0) {
|
||||
return "库存:" + num;
|
||||
} else if (num === 0) {
|
||||
return "卖完了";
|
||||
}
|
||||
},
|
||||
async handlePlus() {
|
||||
this.$emit("handleSkuNamePlus", this.index)
|
||||
},
|
||||
async handleMinus() {
|
||||
this.$emit("handleSkuNameMinus", this.index)
|
||||
},
|
||||
async countChange(count) {
|
||||
this.$emit("handleSkuNameChange", {
|
||||
index: this.index,
|
||||
count,
|
||||
});
|
||||
},
|
||||
// 跳转到商品详情页
|
||||
toGoodDetail() {
|
||||
jumpPage('navigateTo',`/pagesGoods/good-detail/index?skuID=${this.skuName.id}&storeID=${this.skuName.storeID}`)
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use "./good-cell.scss";
|
||||
.red {
|
||||
flex: 1;
|
||||
color: #fe6263;
|
||||
margin: 10rpx 0;
|
||||
}
|
||||
.gray {
|
||||
flex: 1;
|
||||
color: #999;
|
||||
margin: 10rpx 0;
|
||||
}
|
||||
</style>
|
||||
20
src/components/goodCmp/good-price/good-price.scss
Normal file
20
src/components/goodCmp/good-price/good-price.scss
Normal file
@@ -0,0 +1,20 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.good-price {
|
||||
font-size: 32rpx;
|
||||
color: #fe6263;
|
||||
font-weight: 500;
|
||||
// &:before {
|
||||
// content: "¥";
|
||||
// font-size: 28rpx;
|
||||
// }
|
||||
|
||||
&-font{
|
||||
font-size: 38rpx;
|
||||
&:after{
|
||||
// content: ".";
|
||||
font-size: 28rpx;
|
||||
padding:0 5rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/components/goodCmp/good-price/good-price.vue
Normal file
31
src/components/goodCmp/good-price/good-price.vue
Normal file
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="good-price">
|
||||
<span>¥</span>
|
||||
<span class="good-price-font" >{{newPrice }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
// props: {
|
||||
// price:{
|
||||
// type:Number,
|
||||
// default:0
|
||||
// }
|
||||
// },
|
||||
props:['price'],
|
||||
computed: {
|
||||
newPrice(){
|
||||
let str = ''
|
||||
if(this.price!==0){
|
||||
str = ((this.price/100).toFixed(2)).split('.')[0] + '.' + ((this.price/100).toFixed(2)).split('.')[1]
|
||||
}
|
||||
return str
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use './good-price.scss';
|
||||
</style>
|
||||
33
src/components/goodCmp/leftCats/left-cats.scss
Normal file
33
src/components/goodCmp/leftCats/left-cats.scss
Normal file
@@ -0,0 +1,33 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.left-cats {
|
||||
// height: calc(100vh - 90rpx);
|
||||
/* #ifndef H5 */
|
||||
height: calc(100vh - 90rpx);
|
||||
/* #endif */
|
||||
/* #ifdef H5 */
|
||||
height: calc(100vh - 270rpx);
|
||||
/* #endif */
|
||||
.cats-item {
|
||||
height: 110rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
@extend %flex-center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cat-name {
|
||||
border-left: 6rpx solid transparent;
|
||||
flex: 1;
|
||||
height: 60rpx;
|
||||
@extend %flex-center;
|
||||
}
|
||||
|
||||
.active {
|
||||
background: white;
|
||||
color: #4EB331;
|
||||
.cat-name {
|
||||
border-left-color: #4EB331;
|
||||
}
|
||||
}
|
||||
}
|
||||
52
src/components/goodCmp/leftCats/left-cats.vue
Normal file
52
src/components/goodCmp/leftCats/left-cats.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
|
||||
<scroll-view class="left-cats" scroll-y :scroll-into-view="intoID" scroll-with-animation>
|
||||
<div
|
||||
:class="{
|
||||
'cats-item': true,
|
||||
active: cat.id === current
|
||||
}"
|
||||
v-for="(cat, index) in catL1"
|
||||
:key="cat.id"
|
||||
:id="'l' + cat.id"
|
||||
@click="handleClick(cat.id, index)"
|
||||
>
|
||||
<text class="cat-name">{{cat.name}}</text>
|
||||
</div>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'LeftCats',
|
||||
props: {
|
||||
catL1: {
|
||||
default: []
|
||||
},
|
||||
current: {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
intoID: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick (id, index) {
|
||||
this.$emit('catChange', {
|
||||
id,
|
||||
index
|
||||
})
|
||||
// this.intoID = 'l' + id
|
||||
},
|
||||
scrollInToID (id) {
|
||||
this.intoID = 'l' + id
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use './left-cats.scss';
|
||||
</style>
|
||||
70
src/components/goodCmp/plus-minus/plus-minus.scss
Normal file
70
src/components/goodCmp/plus-minus/plus-minus.scss
Normal file
@@ -0,0 +1,70 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.cmp-minus-plus, .cmp-minus-plus2 {
|
||||
@extend %flex-center;
|
||||
.minus-plus-wrapper {
|
||||
@extend %flex-center;
|
||||
}
|
||||
.btn-minus, .btn-plus {
|
||||
flex: none;
|
||||
@extend %bg-no-repeat-center;
|
||||
@extend %bgwhite;
|
||||
background-size: 24rpx;
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 50%;
|
||||
border: 1rpx solid #DCDFE6;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: 0;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
.btn-minus {
|
||||
@extend %icon-minus;
|
||||
}
|
||||
.btn-plus {
|
||||
@extend %icon-plus;
|
||||
}
|
||||
.count {
|
||||
flex: none;
|
||||
color: #333;
|
||||
font-size: 34rpx;
|
||||
width: 70rpx;
|
||||
text-align: center;
|
||||
margin: 0 10rpx;
|
||||
color: #606266;
|
||||
}
|
||||
.input-count {
|
||||
// background :red;
|
||||
color: #606266;
|
||||
font-size: 34rpx;
|
||||
}
|
||||
// .type-shopCar {
|
||||
// background: #DCDFE6;
|
||||
// border-radius: 10rpx;
|
||||
// margin: 0 10rpx;
|
||||
// }
|
||||
.cannot-buy {
|
||||
color: #909399;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.cmp-minus-plus2 {
|
||||
.disabled {
|
||||
opacity: .2;
|
||||
}
|
||||
}
|
||||
|
||||
.add-cart{
|
||||
// padding:0 20rpx;
|
||||
// width: calc(100%-125px);
|
||||
width: 100vw;
|
||||
height: 64rpx;
|
||||
line-height: 64rpx;
|
||||
font-size:30rpx;
|
||||
background:#81be4e;
|
||||
color:#fff;
|
||||
text-align:center;
|
||||
border-radius:20rpx;
|
||||
}
|
||||
85
src/components/goodCmp/plus-minus/plus-minus.vue
Normal file
85
src/components/goodCmp/plus-minus/plus-minus.vue
Normal file
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div class="cmp-minus-plus">
|
||||
<div class="add-cart" v-if="!count" @click.stop="handlePlus">加入购物车</div>
|
||||
<div class="minus-plus-wrapper" v-else>
|
||||
<div class="btn-minus" @click.stop="handleMinus"></div>
|
||||
<div :class="{count: true, 'type-shopCar': typeShopCar}">
|
||||
<span v-if="type !== 'input'">{{count}}</span>
|
||||
<input v-if="type === 'input'" type="number" class="input-count" @blur="countChange" v-model.number="inputCount">
|
||||
</div>
|
||||
<div class="btn-plus" @click.stop="handlePlus"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { errToast,jumpPage } from '@/utils/uniapi.js'
|
||||
import { msgData } from '@/config.js'
|
||||
import {debounce} from '@/utils'
|
||||
export default {
|
||||
inject: {
|
||||
shopCar: {
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
props:['count','type','skuName'],
|
||||
data() {
|
||||
return {
|
||||
typeShopCar: false,
|
||||
inputCount: this.count
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
isLogin: 'login/isLogin',
|
||||
storeMap: "indexPage/storeMap",
|
||||
storeID: "indexPage/storeID",
|
||||
isMaterial: "indexPage/isMaterial",
|
||||
})
|
||||
},
|
||||
mounted() {
|
||||
this.typeShopCar = this.shopCar
|
||||
this.inputCount = this.count
|
||||
},
|
||||
watch: {
|
||||
count(count) {
|
||||
this.inputCount = +count
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// minus
|
||||
handleMinus:debounce(function() {
|
||||
if (!this.isMaterial && this.storeMap[this.storeID[0]].status !== 1) return errToast(msgData.storeIsClose) // 判断当前门店是否营业
|
||||
this.$emit('clickMinus')
|
||||
},1000),
|
||||
// plus
|
||||
handlePlus:debounce(function() {
|
||||
if (!this.isMaterial && this.storeMap[this.storeID[0]].status !== 1) return errToast(msgData.storeIsClose) // 判断当前门店是否营业
|
||||
|
||||
// 判断用的登录状态
|
||||
if (!this.isLogin) {
|
||||
errToast('请登录')
|
||||
jumpPage('switchTab', '/pages/mine/index', 800)
|
||||
return
|
||||
}
|
||||
|
||||
this.$emit('clickPlus')
|
||||
},1000),
|
||||
// count改变
|
||||
countChange:debounce(function(e) {
|
||||
if(+e.target.value > this.skuName.stock) {
|
||||
this.inputCount = this.skuName.count
|
||||
return errToast('暂时没有那么多商品喔~')
|
||||
}
|
||||
const count = +e.target.value
|
||||
if (!count) this.inputCount = 0
|
||||
if (count !== this.count) this.$emit('countChange', count ? count : 0)
|
||||
},1000)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use "./plus-minus.scss";
|
||||
</style>
|
||||
59
src/components/goodCmp/topCats/top-cats.scss
Normal file
59
src/components/goodCmp/topCats/top-cats.scss
Normal file
@@ -0,0 +1,59 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
// 顶部二级菜单
|
||||
.top-cats {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
// 遮罩
|
||||
&:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
background: linear-gradient(to left, white, rgba(white, 0));
|
||||
right: 15%;
|
||||
width: 80rpx;
|
||||
height: 100%;
|
||||
}
|
||||
.scroll-x {
|
||||
// white-space: nowrap;
|
||||
width: 85%;
|
||||
// background: red;
|
||||
|
||||
.scroll-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.scroll-item {
|
||||
// display: inline-block;
|
||||
flex: none;
|
||||
font-size: 28rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
.scroll-item-placeholder {
|
||||
flex: none;
|
||||
width: 80rpx;
|
||||
height: 50rpx;
|
||||
}
|
||||
.cat-active {
|
||||
color: #4EB331;
|
||||
border: 1rpx solid #4EB331;
|
||||
padding: 4rpx 10rpx;
|
||||
background: rgb(234, 240, 227);
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
}
|
||||
.btn-up-down {
|
||||
width: 15%;
|
||||
height: 79rpx;
|
||||
// @include svg_icon(arraw-up, 9a9a9a);
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAANRJREFUWEft1MENwjAMBVB7AlZhhLJJOcRnRuGcHOgmdARWYQKjSI0UFUKSn0Mvzr35L1+1mQ4+fHA+GcAasAasgaEGvPdzXGQisqALDQZs4Y8t+IoiIEAKV9V3BDDziYggRDcgD2fmKQJUdUURXYB9uIi8IsB7f0YRzYBSePr5UEQToBY+gqgCWsNRxF9AbziCKALQ8F7ET8BoeA/iCxBCmFT1GZdMnPM0auiqzaeDmS/OuTW/q9TAnYiW0fC8CSKaReS2f0h1CtCXt35nAGvAGrAGPjJjsyGUY8cAAAAAAElFTkSuQmCC");
|
||||
background-size: 20rpx;
|
||||
@extend %bg-no-repeat-center;
|
||||
transform: rotateX(180deg);
|
||||
transition: all .5s;
|
||||
}
|
||||
.arrow-active {
|
||||
transform: rotateX(0);
|
||||
}
|
||||
}
|
||||
77
src/components/goodCmp/topCats/top-cats.vue
Normal file
77
src/components/goodCmp/topCats/top-cats.vue
Normal file
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<div class="top-cats">
|
||||
<scroll-view class="scroll-x" :scroll-left="scrollLeft" scroll-x="true" :scroll-into-view="intoID" @scroll="scroll">
|
||||
<div class="scroll-area">
|
||||
<div
|
||||
:class="{
|
||||
'scroll-item': true,
|
||||
'cat-active': current === cat.id
|
||||
}"
|
||||
v-for="(cat, index) in cats"
|
||||
:key="cat.id"
|
||||
:id="'c' + cat.id"
|
||||
@click="clickCat(cat.id, index)"
|
||||
>
|
||||
{{cat.name}}
|
||||
</div>
|
||||
<div class="scroll-item-placeholder"></div>
|
||||
</div>
|
||||
</scroll-view>
|
||||
<div :class="{'btn-up-down': true, 'arrow-active': up}" @click="clickArrow"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {debounce} from '@/utils'
|
||||
export default {
|
||||
name: 'TopCats',
|
||||
props: ['cats', 'current', 'wallShow', 'up'],
|
||||
data () {
|
||||
return {
|
||||
intoID: 'c0',
|
||||
scrollLeft: 0,
|
||||
oldScroll: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 点击箭头
|
||||
clickArrow () {
|
||||
this.$emit('toggleCat2')
|
||||
},
|
||||
// 点击分类
|
||||
clickCat (id, index) {
|
||||
this.$emit('cat2Change', {
|
||||
id,
|
||||
index
|
||||
})
|
||||
},
|
||||
scrollInToIndex (index) {
|
||||
this.intoID = 'c' + this.cats[index - 1 >= 0 ? index - 1 : 0].id
|
||||
},
|
||||
// 设置位置
|
||||
// setScroll (id) {
|
||||
// let index = this.cats.findIndex(item => item.id === id)
|
||||
// this.intoID = 'c' + this.cats[index - 1 >= 0 ? index - 1 : 0].id
|
||||
// },
|
||||
// 滚动防抖
|
||||
scroll: debounce(function (e) {
|
||||
this.oldScroll = e.detail.scrollLeft
|
||||
}, 50)
|
||||
},
|
||||
watch: {
|
||||
cats (to, from) {
|
||||
if (from[1] && to[1] && to[1].id !== from[1].id) {
|
||||
// 回到原点
|
||||
this.scrollLeft = this.oldScroll
|
||||
this.$nextTick(() => {
|
||||
this.scrollLeft = 0
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use "./top-cats.scss";
|
||||
</style>
|
||||
23
src/components/goodCmp/topCatsWall/top-cats-wall.scss
Normal file
23
src/components/goodCmp/topCatsWall/top-cats-wall.scss
Normal file
@@ -0,0 +1,23 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.top-cats-wall {
|
||||
background: white;
|
||||
font-size: 28rpx;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
padding: 20rpx 0 40rpx;
|
||||
.wall-item {
|
||||
width: 30%;
|
||||
// margin-left: (10% / 5);
|
||||
margin-top: 4%;
|
||||
box-sizing: border-box;
|
||||
border: 2rpx solid #ddd;
|
||||
height: 50rpx;
|
||||
@extend %flex-center;
|
||||
border-radius: 30rpx;
|
||||
}
|
||||
.active {
|
||||
border-color: #4EB331;
|
||||
background: rgba(#4EB331, .2);
|
||||
}
|
||||
}
|
||||
35
src/components/goodCmp/topCatsWall/top-cats-wall.vue
Normal file
35
src/components/goodCmp/topCatsWall/top-cats-wall.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div class="top-cats-wall">
|
||||
<div
|
||||
:class="{
|
||||
'wall-item': true,
|
||||
'active': current === cat.id
|
||||
}"
|
||||
v-for="(cat, index) in cats"
|
||||
:key="cat.id"
|
||||
@click="handleClick(cat.id, index)"
|
||||
>
|
||||
{{cat.name}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'TopCatsWall',
|
||||
props: ['cats', 'current'],
|
||||
methods: {
|
||||
// 点击分类
|
||||
handleClick (id, index) {
|
||||
this.$emit('clickCat2', {
|
||||
id,
|
||||
index
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use './top-cats-wall.scss';
|
||||
</style>
|
||||
65
src/components/jxEmpty/index.vue
Normal file
65
src/components/jxEmpty/index.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<view class="empty-root">
|
||||
<image
|
||||
class="img"
|
||||
:src="src"
|
||||
mode="scaleToFill"
|
||||
/>
|
||||
<text class="text">{{ title }}</text>
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props:{
|
||||
icon: {
|
||||
type:String,
|
||||
default:'kongzhuangtai',
|
||||
},
|
||||
size:{
|
||||
type:Number,
|
||||
default:150
|
||||
},
|
||||
title:{
|
||||
type:String,
|
||||
// default:'暂无数据'
|
||||
default:'暂无门店列表'
|
||||
},
|
||||
color:{
|
||||
type:String,
|
||||
default:'#7fc86c'
|
||||
},
|
||||
src:{
|
||||
type:String,
|
||||
default:'https://image.jxc4.com/image/d0adecd3671e8a1c2294783b22a46426.png'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.empty-root {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 999999;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
.img {
|
||||
width: 400rpx;
|
||||
height: 400rpx;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: v-bind(color);
|
||||
text-decoration: none;
|
||||
margin-top: -70rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
32
src/components/layout/left-right-cell.scss
Normal file
32
src/components/layout/left-right-cell.scss
Normal file
@@ -0,0 +1,32 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.left-right-cell {
|
||||
// width: 100vw;
|
||||
@extend %flex-between;
|
||||
@extend %pdlr;
|
||||
min-height: 100rpx;
|
||||
box-sizing: border-box;
|
||||
font-size: 32rpx;
|
||||
@extend %bgwhite;
|
||||
.left, .right {
|
||||
color: #333;
|
||||
}
|
||||
.left {
|
||||
flex: none;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
.right {
|
||||
@extend %flex-right;
|
||||
flex: auto;
|
||||
@extend %oneline;
|
||||
.icon-right-aw {
|
||||
flex: none;
|
||||
@extend %icon-aw-right-slim;
|
||||
width: 50rpx;
|
||||
height: 30rpx;
|
||||
background-position: right center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/components/layout/left-right-cell.vue
Normal file
26
src/components/layout/left-right-cell.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<view class="left-right-cell">
|
||||
<view class="left">
|
||||
<slot name="left"></slot>
|
||||
</view>
|
||||
<view class="right">
|
||||
<slot name="right"></slot>
|
||||
<view v-if="!noClick" class="icon-right-aw"></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
noClick: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use './left-right-cell.scss';
|
||||
</style>
|
||||
23
src/components/material-info/index.vue
Normal file
23
src/components/material-info/index.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div class="material-info">
|
||||
<div>单量: {{preSaleCount}},已选袋子件数/数量: {{totalBag.unitCount}}件/{{totalBag.totalCount}}个</div>
|
||||
<div :class="{danger: bagOverload !== '未超出购买限制'}">{{bagOverload}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters} from 'vuex'
|
||||
export default {
|
||||
computed: {
|
||||
...mapGetters({
|
||||
preSaleCount: 'indexPage/preSaleCount',
|
||||
totalBag: 'indexPage/totalBag',
|
||||
bagOverload: 'indexPage/bagOverload',
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use "./material-info.scss"
|
||||
</style>
|
||||
11
src/components/material-info/material-info.scss
Normal file
11
src/components/material-info/material-info.scss
Normal file
@@ -0,0 +1,11 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.material-info {
|
||||
font-size: 30rpx;
|
||||
color: #606266;
|
||||
text-align: center;
|
||||
.danger {
|
||||
color: #F56C6C;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
188
src/components/nearlyStoreCom/index.scss
Normal file
188
src/components/nearlyStoreCom/index.scss
Normal file
@@ -0,0 +1,188 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
|
||||
.nearlyStores{
|
||||
margin-top:20rpx;
|
||||
background:#fff;
|
||||
border-radius:10rpx;
|
||||
padding:10rpx;
|
||||
|
||||
// border: 1rpx solid red;
|
||||
box-shadow: 0rpx 2rpx 10rpx rgb(207, 207, 207);
|
||||
}
|
||||
|
||||
.storeInfo{
|
||||
display:flex;
|
||||
font-size:30rpx;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.storeImg{
|
||||
width:120rpx;
|
||||
height:120rpx;
|
||||
}
|
||||
|
||||
.storeStatus{
|
||||
position:absolute;
|
||||
// top:80rpx;
|
||||
bottom: 0;
|
||||
left:0;
|
||||
width:120rpx;
|
||||
text-align:center;
|
||||
background:rgba(0,0,0,0.5);
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
.storeRight{
|
||||
margin-left:20rpx;
|
||||
}
|
||||
|
||||
.storeName{
|
||||
display:flex;
|
||||
font-weight:bold;
|
||||
margin-bottom:4rpx;
|
||||
}
|
||||
|
||||
.storeTime,.storeTime1,.storeTime2{
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.storeTime2{
|
||||
margin-left:20rpx;
|
||||
}
|
||||
|
||||
.storeRate{
|
||||
display:flex !important;
|
||||
font-size: 24rpx;
|
||||
margin-top:6rpx
|
||||
}
|
||||
|
||||
.fullReduce{
|
||||
display:flex;
|
||||
margin-bottom:20rpx;
|
||||
justify-content:space-between;
|
||||
font-size: 24rpx;
|
||||
width:566rpx;
|
||||
margin-top:6rpx;
|
||||
|
||||
&Fee{
|
||||
border:1rpx solid #f16a6a;
|
||||
text-align:center;
|
||||
border-radius:10rpx;
|
||||
padding:6rpx;
|
||||
// background: #fff;
|
||||
color: #f16a6a;
|
||||
}
|
||||
}
|
||||
|
||||
.storeGood{
|
||||
// border: 1rpx solid red;
|
||||
display:flex;
|
||||
// margin-left:142rpx;
|
||||
margin-left:20rpx;
|
||||
overflow:hidden;
|
||||
overflow-x:auto;
|
||||
width:98%;
|
||||
white-space:nowrap;
|
||||
|
||||
&Item:not(:last-child){
|
||||
margin-right:20rpx;
|
||||
// width: 100%;
|
||||
}
|
||||
|
||||
// .storeGood:not(:last-child){
|
||||
// // margin-left: 0;
|
||||
// border: 1rpx solid red;
|
||||
// }
|
||||
|
||||
&Img{
|
||||
width:146rpx;
|
||||
height:146rpx;
|
||||
}
|
||||
|
||||
&Name{
|
||||
width:120rpx;
|
||||
white-space:nowrap;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
font-size:24rpx;
|
||||
}
|
||||
|
||||
&Price{
|
||||
color:#ff0000;
|
||||
font-size:24rpx;
|
||||
}
|
||||
|
||||
&Price::before{
|
||||
content: '¥';
|
||||
font-size:20rpx;
|
||||
}
|
||||
|
||||
&More{
|
||||
// border: 1rpx solid green;
|
||||
// position: relative;
|
||||
// right: 0;
|
||||
position:sticky;
|
||||
right:0;
|
||||
writing-mode:vertical-lr;
|
||||
text-align:center;
|
||||
background:rgba(132, 132, 132, 0.5);
|
||||
color:#fff;
|
||||
padding:0 12rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.top-title_near ,.top-title{
|
||||
background: #fff;
|
||||
padding: 20rpx 0;
|
||||
border-radius: 10rpx;
|
||||
line-height: 1;
|
||||
box-shadow: 5rpx 5rpx 4rpx rgba(194, 193, 192, 0.2);
|
||||
}
|
||||
.top-title{
|
||||
@extend %flex-left;
|
||||
}
|
||||
|
||||
.top-title_near{
|
||||
display: flex;
|
||||
justify-content: space-between !important;
|
||||
}
|
||||
|
||||
.icon-border {
|
||||
width: 6rpx;
|
||||
background-color: #4EB331;
|
||||
height: 30rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.title {
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
.ranking_left,.ranking_right{
|
||||
display:flex;
|
||||
border:0
|
||||
}
|
||||
|
||||
.operationRaking,.optimalScore,.nearlyDistance{
|
||||
padding:4px 10px;
|
||||
font-size:28rpx;
|
||||
}
|
||||
|
||||
.active_status{
|
||||
border-bottom:2rpx solid #4EB331;
|
||||
color:#4EB331;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.top-goods-list {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
.goods-item {
|
||||
margin-top: 20rpx;
|
||||
width: 345rpx;
|
||||
flex: none ;
|
||||
}
|
||||
}
|
||||
198
src/components/nearlyStoreCom/index.vue
Normal file
198
src/components/nearlyStoreCom/index.vue
Normal file
@@ -0,0 +1,198 @@
|
||||
<template>
|
||||
<div class="top-title_near">
|
||||
|
||||
<div class="ranking_left">
|
||||
<slot>
|
||||
<div class="icon-border"></div>
|
||||
<div class="title">附近商家</div>
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<div class="ranking_right">
|
||||
<div class="operationRaking" :class="activeID === 1 ?'active_status' :''" @click="optionSort(1)">综合排序</div>
|
||||
<div class="optimalScore" :class="activeID === 2 ?'active_status' :''" @click="optionSort(2)">评分最优</div>
|
||||
<div class="nearlyDistance" :class="activeID === 3 ?'active_status' :''" @click="optionSort(3)">距离最近</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div v-show="nearStatus === 'noMore'">
|
||||
<div
|
||||
class="nearlyStores"
|
||||
v-for="(item, index) in nearlyStores"
|
||||
:key="index"
|
||||
@click="clickMore(item)"
|
||||
>
|
||||
<!-- 商家信息 -->
|
||||
<div class="storeInfo">
|
||||
<div style="display: flex;align-items: center;">
|
||||
<image :src="item.storeInfo.brandLogo" class="storeImg" alt="加载中1111111" />
|
||||
</div>
|
||||
<div v-if="item.storeInfo.status===-1" class="storeStatus">休息中</div>
|
||||
<div class="storeRight">
|
||||
<div class="storeName" style="display: flex;">
|
||||
<div>{{item.storeInfo.storeName }}</div>
|
||||
<div v-if="item.storeInfo.brandName">--</div>
|
||||
<div>{{ item.storeInfo.brandName }}</div>
|
||||
</div>
|
||||
<!-- 营业时间 -->
|
||||
<div style="text-align: left;display: flex;">
|
||||
<div class="storeTime">营业时间:</div>
|
||||
<div class="storeTime1" v-if="item.storeInfo.openTime1 && item.storeInfo.closeTime1">{{$filters.processingHours(item.storeInfo.openTime1)}}-{{$filters.processingHours(item.storeInfo.closeTime1)}}</div>
|
||||
<div class="storeTime2" v-if="item.storeInfo.openTime2 && item.storeInfo.closeTime2">{{$filters.processingHours(item.storeInfo.openTime2)}}-{{$filters.processingHours(item.storeInfo.closeTime2)}}</div>
|
||||
</div>
|
||||
<!-- 评分 -->
|
||||
<div class="storeRate">
|
||||
<div>门店评分:</div>
|
||||
<div v-if="item.storeInfo && item.storeInfo.storeWeeklyScore">
|
||||
<uni-rate :size="20" allow-half :value="(item.storeInfo.storeWeeklyScore *5) /100" />
|
||||
</div>
|
||||
<div v-else>暂无评分</div>
|
||||
</div>
|
||||
<!-- 满减 -->
|
||||
<div class="fullReduce">
|
||||
<div v-if="item.StoreDeductionInfo[0].deliveryFeeDeductionFee && item.StoreDeductionInfo[0].deliveryFeeDeductionSill" class="fullReduceFee">
|
||||
满{{item.StoreDeductionInfo[0].deliveryFeeDeductionSill/100}}减{{item.StoreDeductionInfo[0].deliveryFeeDeductionFee/100}}
|
||||
</div>
|
||||
<!-- 距离 -->
|
||||
<div v-if="String(item.storeInfo.distance).length<=3">距您{{item.storeInfo.distance}}m</div>
|
||||
<div v-else>距您{{(item.storeInfo.distance/1000).toFixed(2)}}km</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 商品 -->
|
||||
<div class="storeGood" v-if="item.StoreSkuInfo!==null && !isSearch" @click.stop="clickStop">
|
||||
<div v-for="(ite,i) in item.StoreSkuInfo" :key="i" class="storeGoodItem" @click="toDetail(ite)">
|
||||
<image :src="$filters.urlToHttps(ite.img)" class="storeGoodImg" alt="" />
|
||||
<div class="storeGoodName" >{{ite.skuName}}</div>
|
||||
<div class="storeGoodPrice" >{{(ite.price/100).toFixed(2)}}元/{{ite.unit}}</div>
|
||||
</div>
|
||||
<div class="storeGoodMore" @click="clickMore(item)">查看更多</div>
|
||||
</div>
|
||||
<!-- 搜索商品 -->
|
||||
<div class="storeGood" v-if="isSearch" @click.stop="clickStop">
|
||||
<div v-for="(ite,i) in item.searchSku" :key="i" class="storeGoodItem" @click="toDetail(ite)">
|
||||
<image :src="$filters.urlToHttps(ite.img)" class="storeGoodImg" alt="" />
|
||||
<div class="storeGoodName" >{{ite.skuName}}</div>
|
||||
<!-- <div class="storeGoodPrice" >{{(ite.price/100).toFixed(2)}}元/{{ite.unit}}</div> -->
|
||||
<div class="storeGoodPrice" >{{(ite.curPrice/100).toFixed(2)}}元/{{ite.unit}}</div>
|
||||
</div>
|
||||
<div class="storeGoodMore" @click="clickMore(item)">查看更多</div>
|
||||
</div>
|
||||
<!-- <div class="enterStore" v-else >
|
||||
<div style="padding:20rpx;background:rgba(78, 179, 49, 0.9);color:#fff;border-radius: 10rpx;border:1rpx solid red;"> </div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<div style="background:#fff;margin-top:20rpx" v-if="!isSearch">
|
||||
<uni-load-more :status="nearStatus" ></uni-load-more>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import apiStore from '@/apis/apiStore';
|
||||
import { mapGetters, mapActions } from "vuex";
|
||||
import {debounce} from '@/utils'
|
||||
import {store} from "@/store";
|
||||
import { jumpPage } from "@/utils/uniapi.js";
|
||||
export default {
|
||||
props:{
|
||||
storeList:{
|
||||
type:Array,
|
||||
default:() => []
|
||||
},
|
||||
isSearch:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
// nearlyStores:[],
|
||||
nearStatus:'loading',
|
||||
originalNearlyStores:[],
|
||||
activeID: 1,
|
||||
}
|
||||
},
|
||||
// watch:{
|
||||
// storeList:{
|
||||
// handleError(val){
|
||||
// console.log('打印val的值',val)
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
computed:{
|
||||
...mapGetters({
|
||||
myLocation:"indexPage/myLocation",
|
||||
reLocation: "indexPage/reLocation",
|
||||
storeID: "indexPage/storeID",
|
||||
isLogin: "login/isLogin",
|
||||
}),
|
||||
nearlyStores(){
|
||||
if(this.storeList && this.storeList.length>0) {
|
||||
this.nearStatus = 'loading'
|
||||
this.originalNearlyStores = [...this.storeList] // 原始数据
|
||||
this.activeID = this.activeID !==1 ? this.activeID : 1 // 获取推荐商家时,为综合排序
|
||||
this.nearStatus = 'noMore'
|
||||
}
|
||||
return this.storeList
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
// 查看更多
|
||||
async clickMore(item) {
|
||||
if(item.dnsType) store.commit('indexPage/changeDNS',item.dnsType) // 更换域名
|
||||
else store.commit('indexPage/changeDNS','wxC4') // 更换域名
|
||||
// console.log('item.storeInfo.storeIDn,,,99999999',item.storeInfo.storeID)
|
||||
store.commit("indexPage/changeStoreID", [+item.storeInfo.storeID])
|
||||
// if(this.isLogin ) await store.dispatch('cartPage/getCarList', store.getters['indexPage/storeID'])
|
||||
if(this.isLogin ) {
|
||||
await store.dispatch('cartPage/getCarList', this.storeID) // 获取购物车列表
|
||||
await store.dispatch('addressVue/getList') // 加载地址列表
|
||||
}
|
||||
if(!(this.storeMap && this.storeMap[this.storeID[0]])) await store.dispatch('indexPage/getStoreInfo', { storeID: this.storeID[0] }) // 获取当前门店的信息
|
||||
jumpPage('navigateTo','/pagesGoods/good/index')
|
||||
},
|
||||
// 跳转到详情页
|
||||
toDetail(ite) {
|
||||
// if(ite.storeID !== this.storeID[0])
|
||||
store.commit("indexPage/changeStoreID", [+ite.storeID])
|
||||
jumpPage('navigateTo', `/pagesGoods/good-detail/index?skuID=${ite.skuID}&storeID=${ite.storeID}`)
|
||||
},
|
||||
clickStop(){
|
||||
// console.log('阻止默认事件')
|
||||
},
|
||||
optionSort: debounce(function (e) {
|
||||
this.activeID = e
|
||||
this.nearStatus = 'loading'
|
||||
switch (e) {
|
||||
case 1:
|
||||
this.nearlyStores = [...this.originalNearlyStores]
|
||||
break
|
||||
case 2:
|
||||
this.nearlyStores.sort(this.ArraySort('storeWeeklyScore','L2S'))
|
||||
break
|
||||
case 3:
|
||||
this.nearlyStores.sort(this.ArraySort('distance', 'S2L'))
|
||||
break
|
||||
}
|
||||
this.nearStatus = 'noMore'
|
||||
},500),
|
||||
// 数组排序 type L2S 大 ——> 小 S2L 小 ——> 大
|
||||
ArraySort(property,type){
|
||||
return function (a,b){
|
||||
let value1=a.storeInfo[property]
|
||||
let value2 = b.storeInfo[property]
|
||||
return type === 'L2S'? value2 - value1 : value1 - value2
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use './index.scss';
|
||||
</style>
|
||||
59
src/components/shopCarIcon/index.scss
Normal file
59
src/components/shopCarIcon/index.scss
Normal file
@@ -0,0 +1,59 @@
|
||||
@use '@/assets/bundle.scss';
|
||||
.btn-toShopCar-new {
|
||||
// position: fixed;
|
||||
// left: 40rpx;
|
||||
// bottom: 100rpx;
|
||||
background-color: rgba(black, .6);
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
z-index: 10;
|
||||
@extend %flex-center;
|
||||
}
|
||||
.icon-shopcar {
|
||||
@extend %icon-shopcar-white;
|
||||
@extend %bg-no-repeat-center;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
background-size: 50rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.fixed-box {
|
||||
pointer-events: none; // 这里是重点,盒子可穿透操作
|
||||
width: 100vw;
|
||||
height: 90vh;
|
||||
position: fixed;
|
||||
top: 100rpx;
|
||||
left: 0;
|
||||
z-index: 100000;
|
||||
}
|
||||
.fixed-button {
|
||||
opacity: 1;
|
||||
// background: #ccc;
|
||||
border-radius: 100%;
|
||||
pointer-events: auto;
|
||||
// width: max-content;
|
||||
// height: auto;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
overflow: hidden;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
left: 20rpx;
|
||||
top: 85vh;
|
||||
.imger{
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
overflow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* 适配iphonex 有底部横条的 */
|
||||
@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
|
||||
.fixed-box {
|
||||
bottom: constant(safe-area-inset-bottom);
|
||||
bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
}
|
||||
39
src/components/shopCarIcon/index.vue
Normal file
39
src/components/shopCarIcon/index.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<movable-area class="fixed-box">
|
||||
<movable-view @click="switchToShopCar" class="fixed-button" direction="all" :inertia="true">
|
||||
<div class="btn-toShopCar-new" >
|
||||
<badge :count="shopCount">
|
||||
<div class="icon-shopcar"></div>
|
||||
</badge>
|
||||
</div>
|
||||
</movable-view>
|
||||
</movable-area>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters, mapActions} from 'vuex'
|
||||
import { jumpPage,errToast } from "@/utils/uniapi.js";
|
||||
export default {
|
||||
computed: {
|
||||
...mapGetters({
|
||||
shopCount: 'cartPage/carCount',
|
||||
isLogin: "login/isLogin",
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
switchToShopCar() {
|
||||
// #ifndef MP-TOUTIAO || APP-PLUS
|
||||
jumpPage('switchTab','/pages/cart/index')
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-TOUTIAO || APP-PLUS
|
||||
jumpPage('navigateTo','/pages/cart/index')
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use "./index.scss";
|
||||
</style>
|
||||
121
src/components/waterfall/index.scss
Normal file
121
src/components/waterfall/index.scss
Normal file
@@ -0,0 +1,121 @@
|
||||
@use "@/assets/bundle.scss";
|
||||
|
||||
.waterfalls-flow {
|
||||
overflow: hidden;
|
||||
padding: 10rpx;
|
||||
/* #ifdef MP-ALIPAY */
|
||||
background-color: #f4f4f4;
|
||||
/* #endif */
|
||||
&-column {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
.column-value {
|
||||
width: 100%;
|
||||
font-size: 0;
|
||||
overflow: hidden;
|
||||
transition: opacity .4s;
|
||||
opacity: 0;
|
||||
border:1rpx solid #e6e1e1;
|
||||
// box-shadow: 1rpx 1rpx 1rpx 1rpx #8c8c8c;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
&-show {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.inner {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
|
||||
&-hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&-error {
|
||||
background: #f2f2f2 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAiAQMAAAAatXkPAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAAIZJREFUCNdlzjEKwkAUBNAfEGyCuYBkLyLuxRYW2SKlV1JSeA2tUiZg4YrLjv9PGsHqNTPMSAQuyAJgRDHSyvBPwtZoSJXakeJI9iuRLGDygdl6V0yKDtyMAeMPZySj8yfD+UapvRPj2JOwkyAooSV5IwdDjPdCPspe8LyTl9IKJvDETKKRv6vnlUasgg0fAAAAAElFTkSuQmCC) no-repeat center center;
|
||||
}
|
||||
}
|
||||
|
||||
.good-name {
|
||||
font-size: 28rpx;
|
||||
margin-top: 20rpx;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
text-align: justify;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.good-price {
|
||||
// border:1rpx solid red;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin:10rpx 0;
|
||||
font-weight: 500;
|
||||
color: #fe6263;
|
||||
}
|
||||
|
||||
.price {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
||||
.price-text{
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.price-text::before{
|
||||
content: "¥";
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.unit{
|
||||
font-size:28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.ori-price {
|
||||
font-size: 20rpx;
|
||||
color: #b2b2b2;
|
||||
margin-left: 10rpx;
|
||||
text-decoration: line-through;
|
||||
&:before {
|
||||
content: "¥";
|
||||
}
|
||||
}
|
||||
|
||||
.act-type-wrapper {
|
||||
height: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.act-type {
|
||||
@extend %act-type-text;
|
||||
}
|
||||
|
||||
.countTime-wrap{
|
||||
height: 17rpx;
|
||||
width: 100%;
|
||||
margin-bottom: 5rpx;
|
||||
}
|
||||
|
||||
.countTime{
|
||||
color: #E6A23C;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.priceStyle{
|
||||
color: rgb(149, 209,131);
|
||||
font-size: 25rpx;
|
||||
margin-bottom:10rpx;
|
||||
}
|
||||
|
||||
.priceColor{
|
||||
color:#fe6263;
|
||||
}
|
||||
}
|
||||
404
src/components/waterfall/index.vue
Normal file
404
src/components/waterfall/index.vue
Normal file
@@ -0,0 +1,404 @@
|
||||
<template>
|
||||
<view class="waterfalls-flow">
|
||||
<view v-for="(item, index) in data.column" :key="index" class="waterfalls-flow-column"
|
||||
:id="`waterfalls_flow_column_${index + 1}`" :msg="msg" :style="{ 'width': w, 'margin-left': index == 0 ? 0 : m }">
|
||||
<view :class="['column-value', { 'column-value-show': item2.o }]" v-for="(item2, index2) in columnValue(index)"
|
||||
:key="index2" :style="[s1]" @click.stop="wapperClick(item2)">
|
||||
<image
|
||||
:class="['img', { 'img-hide': item2[hideImageKey] == true || item2[hideImageKey] == 1 }, { 'img-error': !item2[data.imageKey] }]"
|
||||
:src="item2[data.imageKey]" mode="widthFix" @load="imgLoad(item2, index + 1)"
|
||||
@error="imgError(item2, index + 1)" @click.stop="imageClick(item2)">
|
||||
</image>
|
||||
<view class="inner">
|
||||
<view>
|
||||
<view class="good-name">{{ item2.name }}</view>
|
||||
<view class="countTime-wrap">
|
||||
<view class="countTime"
|
||||
v-if="item2.actType === 5 && item2.actPrice !== 0 && item2.trendType !== 0 && timeTen">
|
||||
{{ item2.trendType === 2 ? '降价' : '升价' }}还剩 {{ skunameMsg }}</view>
|
||||
</view>
|
||||
|
||||
<view class="priceStyle" v-if="item2.unit">
|
||||
<text>每</text>
|
||||
<text v-if="isB2B && storeID[0] !== 666666">斤</text>
|
||||
<span v-else>{{ item2.unit }}</span>
|
||||
<text>约为</text>
|
||||
<span class="priceColor" >{{ $filters.toFixed2(item2.curPrice) }}</span>
|
||||
<text>元(以实际价格为准)</text>
|
||||
</view>
|
||||
<view class="good-price">
|
||||
<view class="price">
|
||||
<view class="price-text">
|
||||
<span class="good-price-font" v-if="isB2B || storeID[0] === 666666">{{((item2.curPrice/100).toFixed(2)).split('.')[0] + '.' + ((item2.curPrice/100).toFixed(2)).split('.')[1] }}</span>
|
||||
<span class="good-price-font" v-else-if="item2.weight">{{(((((item2.curPrice/100)/item2.weight)*500)/100).toFixed(2)).split('.')[0] + '.' + (((((item2.curPrice/100)/item2.weight)*500)/100).toFixed(2)).split('.')[1] }}</span>
|
||||
<span class="good-price-font" v-else>{{(((((item2.curPrice/100))*500)/100).toFixed(2)).split('.')[0] + '.' + (((((item2.curPrice/100))*500)/100).toFixed(2)).split('.')[1] }}</span>
|
||||
</view>
|
||||
<span class="unit" v-if="storeID[0] === 666666 || isB2B">/{{item2.unit}}</span>
|
||||
<text class="unit" v-else>/斤</text>
|
||||
<view class="ori-price" v-if="item2.oriPrice && !isMaterial" >{{$filters.toFixed2(item2.oriPrice)}}</view>
|
||||
</view>
|
||||
|
||||
<view class="act-type-wrapper">
|
||||
<view class="act-type" v-if="item2.actType">{{actTypeArr[item2.actType]}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="isShowShop">
|
||||
<PlusMinus :type="'input'" :skuName="item2" :count="item2.count" @clickPlus="skuNamePlusRecommend(item2.index)" @clickMinus="skuNameMinusRecommend(item2.index)" @countChange="skuNameChangeRecommend($event,item2.index)" ></PlusMinus>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<view v-if="!isMaterial" style="background:#fff;margin-top:20rpx" :style="{'background-color':topGoodsStatus === 'loading'?'#f4f4f4':'#fff'}">
|
||||
<uni-load-more :status="topGoodsStatus" ></uni-load-more>
|
||||
</view>
|
||||
|
||||
<!-- <div
|
||||
class="nearlyStores"
|
||||
v-for="(item, index) in nearlyStores"
|
||||
:key="index"
|
||||
@click="clickMore(item)"
|
||||
>
|
||||
商家信息
|
||||
<div class="storeInfo">
|
||||
<div style="display: flex;align-items: center;">
|
||||
<image :src="$filters.urlToHttps(item.storeInfo.brandLogo)" class="storeImg" alt="" />
|
||||
</div>
|
||||
<div v-if="item.storeInfo.status===-1" class="storeStatus">休息中</div>
|
||||
<div class="storeRight">
|
||||
<div class="storeName" style="display: flex;">
|
||||
<div >{{item.storeInfo.brandName}}</div>
|
||||
<div>{{item.storeInfo.storeName }}</div>
|
||||
<div>--</div>
|
||||
<div>{{ item.storeInfo.brandName }}</div>
|
||||
</div>
|
||||
营业时间
|
||||
<span class="storeTime">营业时间:</span>
|
||||
<span class="storeTime1" v-if="item.storeInfo.openTime1 && item.storeInfo.closeTime1">{{$filters.processingHours(item.storeInfo.openTime1)}}-{{$filters.processingHours(item.storeInfo.closeTime1)}}</span>
|
||||
<span class="storeTime2" v-if="item.storeInfo.openTime2 && item.storeInfo.closeTime2">{{$filters.processingHours(item.storeInfo.openTime2)}}-{{$filters.processingHours(item.storeInfo.closeTime2)}}</span>
|
||||
评分
|
||||
<div class="storeRate">
|
||||
<div>门店评分:</div>
|
||||
<div v-if="item.storeInfo && item.storeInfo.storeWeeklyScore">
|
||||
<uni-rate :size="20" allow-half :value="(item.storeInfo.storeWeeklyScore *5) /100" />
|
||||
</div>
|
||||
<div v-else>暂无评分</div>
|
||||
</div>
|
||||
满减
|
||||
<div class="fullReduce">
|
||||
<div v-if="item.StoreDeductionInfo[0].deliveryFeeDeductionFee && item.StoreDeductionInfo[0].deliveryFeeDeductionSill" class="fullReduceFee">
|
||||
满{{item.StoreDeductionInfo[0].deliveryFeeDeductionSill/100}}减{{item.StoreDeductionInfo[0].deliveryFeeDeductionFee/100}}
|
||||
</div>
|
||||
距离
|
||||
<div v-if="String(item.storeInfo.distance).length<=3">距您{{item.storeInfo.distance}}m</div>
|
||||
<div v-else>距您{{(item.storeInfo.distance/1000).toFixed(2)}}km</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
商品
|
||||
<div class="storeGood" v-if="item.StoreSkuInfo!==null" @click.stop="clickStop">
|
||||
<div v-for="(ite,i) in item.StoreSkuInfo" :key="i" class="storeGoodItem" @click="toDetail(ite)">
|
||||
<img :src="$filters.urlToHttps(ite.img,'img120')" class="storeGoodImg">
|
||||
<image :src="$filters.urlToHttps(ite.img)" class="storeGoodImg" alt="" />
|
||||
<div class="storeGoodName" >{{ite.skuName}}</div>
|
||||
<div class="storeGoodPrice" >{{(ite.price/100).toFixed(2)}}元/{{ite.unit}}</div>
|
||||
</div>
|
||||
<div class="storeGoodMore" @click="clickMore(item)">
|
||||
查看更多
|
||||
</div>
|
||||
</div>
|
||||
<div class="enterStore" v-else >
|
||||
<div style="padding:20rpx;background:rgba(78, 179, 49, 0.9);color:#fff;border-radius: 10rpx;border:1rpx solid red;"> </div>
|
||||
</div>
|
||||
</div> -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PlusMinus from "@/components/goodCmp/plus-minus/plus-minus";
|
||||
import { mapGetters } from "vuex";
|
||||
import { jumpPage } from "@/utils/uniapi.js";
|
||||
export default {
|
||||
props: {
|
||||
value: Array,
|
||||
column: { // 列的数量
|
||||
type: [String, Number],
|
||||
default: 2
|
||||
},
|
||||
maxColumn: { // 最大列数
|
||||
type: [String, Number],
|
||||
default: 5
|
||||
},
|
||||
columnSpace: { // 列之间的间距 百分比
|
||||
type: [String, Number],
|
||||
default: 2
|
||||
},
|
||||
imageKey: { // 图片key
|
||||
type: [String],
|
||||
default: 'image'
|
||||
},
|
||||
hideImageKey: { // 隐藏图片key
|
||||
type: [String],
|
||||
default: 'hide'
|
||||
},
|
||||
seat: { // 文本的位置,1图片之上 2图片之下
|
||||
type: [String, Number],
|
||||
default: 2
|
||||
},
|
||||
listStyle: { // 单个展示项的样式:eg:{'background':'red'}
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
components: {
|
||||
PlusMinus
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
data: {
|
||||
list: this.value ? this.value : [],
|
||||
column: this.column < 2 ? 2 : this.column,
|
||||
columnSpace: this.columnSpace <= 5 ? this.columnSpace : 5,
|
||||
imageKey: this.imageKey,
|
||||
seat: this.seat
|
||||
},
|
||||
msg: 0,
|
||||
listInitStyle: {
|
||||
'border-radius': '12rpx',
|
||||
'margin-bottom': '20rpx',
|
||||
'background-color': '#fff'
|
||||
},
|
||||
adds: [], //预置数据
|
||||
isLoaded: true,
|
||||
curIndex: 0,
|
||||
isRefresh: true,
|
||||
flag: false,
|
||||
refreshDatas: [],
|
||||
skunameMsg: '',
|
||||
topGoodsStatus:'loading',
|
||||
actTypeArr:['','','','直降','秒杀','折扣']
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
isB2B: 'indexPage/isB2B',
|
||||
isMaterial: "indexPage/isMaterial",
|
||||
storeID:"indexPage/storeID",
|
||||
isShowShop: "isShowShop"
|
||||
}),
|
||||
// 计算列宽
|
||||
w() {
|
||||
const column_rate = `${100 / this.data.column - (+this.data.columnSpace)}%`;
|
||||
return column_rate;
|
||||
},
|
||||
// 计算margin
|
||||
m() {
|
||||
const column_margin = `${(100 - (100 / this.data.column - (+this.data.columnSpace)).toFixed(5) * this.data.column) / (this.data.column - 1)}%`;
|
||||
return column_margin;
|
||||
},
|
||||
// list样式
|
||||
s1() {
|
||||
return { ...this.listInitStyle, ...this.listStyle };
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 初始化
|
||||
this.refresh();
|
||||
},
|
||||
methods: {
|
||||
// 添加
|
||||
skuNamePlusRecommend(index) {
|
||||
this.$emit('clickPlus',index)
|
||||
},
|
||||
// 减少
|
||||
skuNameMinusRecommend(index) {
|
||||
this.$emit('clickMinus',index)
|
||||
},
|
||||
// 商品数量发生改变
|
||||
skuNameChangeRecommend(e,index) {
|
||||
this.$emit('countChange',e,index)
|
||||
},
|
||||
// 预加载图片
|
||||
loadImages(idx = 0) {
|
||||
let count = 0;
|
||||
const newList = this.data.list.filter((item, index) => index >= idx);
|
||||
for (let i = 0; i < newList.length; i++) {
|
||||
// #ifndef APP-PLUS || APP
|
||||
uni.getImageInfo({
|
||||
src: `${newList[i][this.imageKey]}.jpg`,
|
||||
complete: res => {
|
||||
count++;
|
||||
if (count == newList.length) this.initValue(idx);
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-PLUS || APP
|
||||
plus.io.getImageInfo({
|
||||
src: `${newList[i][this.imageKey]}.jpg`,
|
||||
complete: res => {
|
||||
count++;
|
||||
if (count == newList.length) this.initValue(idx);
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
// 刷新
|
||||
refresh() {
|
||||
if (!this.isLoaded) {
|
||||
this.refreshDatas = this.value;
|
||||
return false;
|
||||
};
|
||||
this.topGoodsStatus = 'loading'
|
||||
this.refreshDatas = [];
|
||||
this.isRefresh = true;
|
||||
this.adds = [];
|
||||
this.data.list = this.value ? this.value : [];
|
||||
this.data.column = this.column < 2 ? 2 : this.column >= this.maxColumn ? this.maxColumn : this.column;
|
||||
this.data.columnSpace = this.columnSpace <= 5 ? this.columnSpace : 5;
|
||||
this.data.imageKey = this.imageKey;
|
||||
this.data.seat = this.seat;
|
||||
this.curIndex = 0;
|
||||
// 每列的数据初始化
|
||||
for (let i = 1; i <= this.data.column; i++) {
|
||||
this.data[`column_${i}_values`] = [];
|
||||
this.msg++;
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.initValue(this.curIndex, 'refresh==>');
|
||||
})
|
||||
},
|
||||
columnValue(index) {
|
||||
return this.data[`column_${index + 1}_values`]
|
||||
},
|
||||
change(newValue) {
|
||||
console.log('this.data9999999999',this.data)
|
||||
for (let i = 0; i < this.data.list.length; i++) {
|
||||
console.log(i,'i',this.data.list[i],'属于哪一列',this.data.list[i].column)
|
||||
const cv = this.data[`column_${this.data.list[i].column}_values`];
|
||||
for (let j = 0; j < cv.length; j++) {
|
||||
if (newValue[i] && i === cv[j].index) {
|
||||
this.data[`column_${this.data.list[i].column}_values`][j] = Object.assign(cv[j], newValue[i]);
|
||||
this.msg++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
getMin(a, s) {
|
||||
let m = a[0][s];
|
||||
let mo = a[0];
|
||||
for (var i = a.length - 1; i >= 0; i--) {
|
||||
if (a[i][s] < m) {
|
||||
m = a[i][s];
|
||||
}
|
||||
}
|
||||
mo = a.filter(i => i[s] == m);
|
||||
return mo[0];
|
||||
},
|
||||
// 计算每列的高度
|
||||
getMinColumnHeight() {
|
||||
return new Promise(resolve => {
|
||||
const heightArr = [];
|
||||
for (let i = 1; i <= this.data.column; i++) {
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
query.select(`#waterfalls_flow_column_${i}`).boundingClientRect(data => {
|
||||
heightArr.push({ column: i, height: data.height });
|
||||
}).exec(() => {
|
||||
if (this.data.column <= heightArr.length) {
|
||||
resolve(this.getMin(heightArr, 'height'));
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
async initValue(i, from) {
|
||||
this.isLoaded = false;
|
||||
if (i >= this.data.list.length || this.refreshDatas.length) {
|
||||
this.msg++;
|
||||
this.loaded();
|
||||
return false;
|
||||
}
|
||||
const minHeightRes = await this.getMinColumnHeight();
|
||||
const c = this.data[`column_${minHeightRes.column}_values`];
|
||||
this.data.list[i].column = minHeightRes.column;
|
||||
c.push({ ...this.data.list[i], cIndex: c.length, index: i, o: 0 });
|
||||
this.msg++;
|
||||
this.topGoodsStatus = 'noMore'
|
||||
},
|
||||
// 图片加载完成
|
||||
imgLoad(item, c) {
|
||||
const i = item.index;
|
||||
item.o = 1;
|
||||
this.$set(this.data[`column_${c}_values`], item.cIndex, JSON.parse(JSON.stringify(item)));
|
||||
this.initValue(i + 1);
|
||||
},
|
||||
// 图片加载失败
|
||||
imgError(item, c) {
|
||||
const i = item.index;
|
||||
item.o = 1;
|
||||
item[this.data.imageKey] = null;
|
||||
this.$set(this.data[`column_${c}_values`], item.cIndex, JSON.parse(JSON.stringify(item)));
|
||||
this.initValue(i + 1);
|
||||
},
|
||||
// 渲染结束
|
||||
loaded() {
|
||||
if (this.refreshDatas.length) {
|
||||
this.isLoaded = true;
|
||||
this.refresh();
|
||||
return false;
|
||||
}
|
||||
this.curIndex = this.data.list.length;
|
||||
if (this.adds.length) {
|
||||
this.data.list = this.adds[0];
|
||||
this.adds.splice(0, 1);
|
||||
this.initValue(this.curIndex);
|
||||
} else {
|
||||
if (this.data.list.length) this.$emit('loaded');
|
||||
this.isLoaded = true;
|
||||
this.isRefresh = false;
|
||||
}
|
||||
},
|
||||
// 单项点击事件
|
||||
wapperClick(item) {
|
||||
jumpPage('navigateTo',`/pagesGoods/good-detail/index?skuID=${item.id}&storeID=${this.storeID[0]}`)
|
||||
// this.$emit('wapperClick', item);
|
||||
},
|
||||
// 图片点击事件
|
||||
imageClick(item) {
|
||||
jumpPage('navigateTo',`/pagesGoods/good-detail/index?skuID=${item.id}&storeID=${this.storeID[0]}`)
|
||||
// this.$emit('imageClick', item);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
deep: true,
|
||||
handler(newValue, oldValue) {
|
||||
setTimeout(() => {
|
||||
this.$nextTick(() => {
|
||||
if (this.isRefresh) return false;
|
||||
if (this.isLoaded) {
|
||||
// if (newValue.length <= this.curIndex) return this.refresh();
|
||||
if (newValue.length <= this.curIndex) return this.change(newValue);
|
||||
this.data.list = newValue;
|
||||
this.$nextTick(() => {
|
||||
this.initValue(this.curIndex, 'watch==>');
|
||||
})
|
||||
} else {
|
||||
this.adds.push(newValue);
|
||||
}
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
},
|
||||
column(newValue) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use "./index.scss";
|
||||
</style>
|
||||
Reference in New Issue
Block a user