增加基本项目配置
This commit is contained in:
77
components/AddressWindow.vue
Normal file
77
components/AddressWindow.vue
Normal file
@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="address-window" :class="value === true ? 'on' : ''">
|
||||
<div class="title">
|
||||
选择地址
|
||||
<span class="iconfont icon-guanbi" @click="closeAddress"></span>
|
||||
</div>
|
||||
<div class="list" v-if="addressList.length">
|
||||
<div
|
||||
class="item acea-row row-between-wrapper"
|
||||
:class="item.id === checked ? 'font-color-red' : ''"
|
||||
v-for="(item, addressIndex) in addressList"
|
||||
@click="tapAddress(addressIndex)"
|
||||
:key="addressIndex"
|
||||
>
|
||||
<span class="iconfont icon-ditu" :class="item.id === checked ? 'font-color-red' : ''"></span>
|
||||
<div class="addressTxt">
|
||||
<div class="name" :class="item.id === checked ? 'font-color-red' : ''">
|
||||
{{ item.realName }}
|
||||
<span class="phone">{{ item.phone }}</span>
|
||||
</div>
|
||||
<div class="line1">
|
||||
{{ item.province }}{{ item.city }}{{ item.district
|
||||
}}{{ item.detail }}
|
||||
</div>
|
||||
</div>
|
||||
<span class="iconfont icon-complete" :class="item.id === checked ? 'font-color-red' : ''"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pictrue" v-if="addressList.length < 1">
|
||||
<img :src="$VUE_APP_RESOURCES_URL+'/images/noAddress.png'" class="image" />
|
||||
</div>
|
||||
<div class="addressBnt bg-color-red" @click="goAddressPages">新加地址</div>
|
||||
</div>
|
||||
<div class="mask" @touchmove.prevent :hidden="value === false" @click="closeAddress"></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getAddressList } from "@/api/user";
|
||||
|
||||
export default {
|
||||
name: "AddressWindow",
|
||||
props: {
|
||||
value: Boolean,
|
||||
checked: Number
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
addressList: [],
|
||||
current: 0,
|
||||
cartId: 0,
|
||||
pinkId: 0,
|
||||
couponId: 0
|
||||
};
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {
|
||||
getAddressList: function() {
|
||||
let that = this;
|
||||
getAddressList().then(res => {
|
||||
that.addressList = res.data;
|
||||
});
|
||||
},
|
||||
closeAddress() {
|
||||
this.$emit("input", false);
|
||||
},
|
||||
goAddressPages: function() {
|
||||
this.$yrouter.push({ path: "/pages/user/address/AddAddress/main" });
|
||||
this.$emit("redirect");
|
||||
},
|
||||
tapAddress: function(index) {
|
||||
this.$emit("checked", this.addressList[index]);
|
||||
this.$emit("input", false);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
106
components/CountDown.vue
Normal file
106
components/CountDown.vue
Normal file
@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<div class="time">
|
||||
{{ tipText }}
|
||||
<span class="styleAll" v-if="isDay === true">{{ day }}</span>
|
||||
<span class="timeTxt">{{ dayText }}</span>
|
||||
<span class="styleAll">{{ hour }}</span>
|
||||
<span class="timeTxt">{{ hourText }}</span>
|
||||
<span class="styleAll">{{ minute }}</span>
|
||||
<span class="timeTxt">{{ minuteText }}</span>
|
||||
<span class="styleAll">{{ second }}</span>
|
||||
<span class="timeTxt">{{ secondText }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "CountDown",
|
||||
props: {
|
||||
//距离开始提示文字
|
||||
tipText: {
|
||||
type: String,
|
||||
default: "倒计时"
|
||||
},
|
||||
dayText: {
|
||||
type: String,
|
||||
default: "天"
|
||||
},
|
||||
hourText: {
|
||||
type: String,
|
||||
default: "时"
|
||||
},
|
||||
minuteText: {
|
||||
type: String,
|
||||
default: "分"
|
||||
},
|
||||
secondText: {
|
||||
type: String,
|
||||
default: "秒"
|
||||
},
|
||||
datatime: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
isDay: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
day: "00",
|
||||
hour: "00",
|
||||
minute: "00",
|
||||
second: "00"
|
||||
};
|
||||
},
|
||||
created: function() {
|
||||
// this.show_time();
|
||||
},
|
||||
mounted: function() {
|
||||
this.show_time();
|
||||
},
|
||||
methods: {
|
||||
show_time: function() {
|
||||
let that = this;
|
||||
this.runTime();
|
||||
setInterval(this.runTime, 1000);
|
||||
},
|
||||
runTime() {
|
||||
let that = this;
|
||||
//时间函数
|
||||
let intDiff = that.datatime - Date.parse(new Date()) / 1000; //获取数据中的时间戳的时间差;
|
||||
let day = 0,
|
||||
hour = 0,
|
||||
minute = 0,
|
||||
second = 0;
|
||||
if (intDiff > 0) {
|
||||
//转换时间
|
||||
if (that.isDay === true) {
|
||||
day = Math.floor(intDiff / (60 * 60 * 24));
|
||||
} else {
|
||||
day = 0;
|
||||
}
|
||||
hour = Math.floor(intDiff / (60 * 60)) - day * 24;
|
||||
minute = Math.floor(intDiff / 60) - day * 24 * 60 - hour * 60;
|
||||
second =
|
||||
Math.floor(intDiff) -
|
||||
day * 24 * 60 * 60 -
|
||||
hour * 60 * 60 -
|
||||
minute * 60;
|
||||
if (hour <= 9) hour = "0" + hour;
|
||||
if (minute <= 9) minute = "0" + minute;
|
||||
if (second <= 9) second = "0" + second;
|
||||
that.day = day;
|
||||
that.hour = hour;
|
||||
that.minute = minute;
|
||||
that.second = second;
|
||||
} else {
|
||||
that.day = "00";
|
||||
that.hour = "00";
|
||||
that.minute = "00";
|
||||
that.second = "00";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
117
components/CouponListWindow.vue
Normal file
117
components/CouponListWindow.vue
Normal file
@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="coupon-list-window" :class="value === true ? 'on' : ''">
|
||||
<div class="title">
|
||||
优惠券
|
||||
<span class="iconfont icon-guanbi" @click="close"></span>
|
||||
</div>
|
||||
<div v-if="couponList.length > 0">
|
||||
<div class="coupon-list">
|
||||
<div
|
||||
class="item acea-row row-center-wrapper"
|
||||
v-for="coupon in couponList"
|
||||
:key="coupon.id"
|
||||
@click="click(coupon)"
|
||||
>
|
||||
<div class="money">
|
||||
¥
|
||||
<span class="num">{{ coupon.couponPrice }}</span>
|
||||
</div>
|
||||
<div class="text">
|
||||
<div class="condition line1">{{ coupon.couponTitle }}</div>
|
||||
<div class="data acea-row row-between-wrapper">
|
||||
<div v-if="coupon.endTime === 0">不限时</div>
|
||||
<div v-else><data-format-t :data="coupon.addTime"></data-format-t> - <data-format-t :data="coupon.endTime"></data-format-t></div>
|
||||
<div
|
||||
class="iconfont icon-xuanzhong1 font-color-red"
|
||||
v-if="checked === coupon.id"
|
||||
></div>
|
||||
<div class="iconfont icon-weixuanzhong" v-else></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="couponNo bg-color-red" @click="couponNo">不使用优惠券</div>
|
||||
</div>
|
||||
<div v-if="!couponList.length && loaded">
|
||||
<div class="pictrue">
|
||||
<img :src="$VUE_APP_RESOURCES_URL+'/images/noCoupon.png'" class="image" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mask"
|
||||
@touchmove.prevent
|
||||
:hidden="value === false"
|
||||
@click="close"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.coupon-list-window .iconfont {
|
||||
font-size: 0.4rem;
|
||||
}
|
||||
.couponNo {
|
||||
font-size: 0.3rem;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
width: 6.9rem;
|
||||
height: 0.86rem;
|
||||
border-radius: 0.43rem;
|
||||
text-align: center;
|
||||
line-height: 0.86rem;
|
||||
margin: 0.6rem auto;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import { getOrderCoupon } from "@/api/order";
|
||||
import DataFormatT from "@/components/DataFormatT";
|
||||
|
||||
export default {
|
||||
name: "CouponListWindow",
|
||||
components: {
|
||||
DataFormatT
|
||||
},
|
||||
props: {
|
||||
value: Boolean,
|
||||
checked: Number,
|
||||
price: {
|
||||
type: [Number, String],
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
couponList: [],
|
||||
loaded: false
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
price(n) {
|
||||
if (n === undefined || n == null) return;
|
||||
this.getCoupon();
|
||||
}
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {
|
||||
close: function() {
|
||||
this.$emit("input", false);
|
||||
this.$emit("close");
|
||||
},
|
||||
getCoupon() {
|
||||
getOrderCoupon(this.price).then(res => {
|
||||
this.couponList = res.data;
|
||||
this.loaded = true;
|
||||
});
|
||||
},
|
||||
click(coupon) {
|
||||
this.$emit("checked", coupon);
|
||||
this.$emit("input", false);
|
||||
},
|
||||
couponNo: function() {
|
||||
this.$emit("checked", null);
|
||||
this.$emit("input", false);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
78
components/CouponPop.vue
Normal file
78
components/CouponPop.vue
Normal file
@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="coupon-list-window" :class="coupon.coupon === true ? 'on' : ''">
|
||||
<div class="title">
|
||||
优惠券<span class="iconfont icon-guanbi" @click="close"></span>
|
||||
</div>
|
||||
<div class="coupon-list" v-if="coupon.list.length > 0">
|
||||
<div
|
||||
class="item acea-row row-center-wrapper"
|
||||
v-for="(item, couponpopIndex) in coupon.list"
|
||||
:key="couponpopIndex"
|
||||
@click="getCouponUser(couponpopIndex, item.id)"
|
||||
>
|
||||
<div class="money">
|
||||
¥<span class="num">{{ item.coupon_price }}</span>
|
||||
</div>
|
||||
<div class="text">
|
||||
<div class="condition line1">
|
||||
购物满{{ item.use_min_price }}元可用
|
||||
</div>
|
||||
<div class="data acea-row row-between-wrapper">
|
||||
<div v-if="item.end_time === 0">不限时</div>
|
||||
<div v-else>{{ item.start_time }}-{{ item.end_time }}</div>
|
||||
<div
|
||||
class="bnt acea-row row-center-wrapper"
|
||||
:class="!item.is_use ? 'bg-color-red' : 'gray'"
|
||||
>
|
||||
{{ !item.is_use ? "立即领取" : "已领取" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--无优惠券-->
|
||||
<div class="pictrue" v-else>
|
||||
<img :src="$VUE_APP_RESOURCES_URL+'/images/noCoupon.png'" class="image" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mask"
|
||||
@touchmove.prevent
|
||||
:hidden="coupon.coupon === false"
|
||||
@click="close"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getCouponReceive } from "@/api/user";
|
||||
export default {
|
||||
name: "CouponPop",
|
||||
props: {
|
||||
coupon: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {};
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {
|
||||
close: function() {
|
||||
this.$emit("changeFun", { action: "changecoupon", value: false }); //$emit():注册事件;
|
||||
},
|
||||
getCouponUser: function(index, id) {
|
||||
let that = this,
|
||||
list = that.coupon.list;
|
||||
if (list[index].is_use === true) return;
|
||||
getCouponReceive(id).then(function() {
|
||||
that.$dialog.toast({ mes: "已领取" });
|
||||
that.$set(list[index], "is_use", true);
|
||||
that.$emit("changefun", { action: "currentcoupon", value: index });
|
||||
that.$emit("changeFun", { action: "changecoupon", value: false });
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
80
components/CouponWindow.vue
Normal file
80
components/CouponWindow.vue
Normal file
@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div v-if="couponList.length > 0">
|
||||
<div class="coupon-window" :class="value ? 'on' : ''">
|
||||
<div class="couponWinList">
|
||||
<div
|
||||
class="item acea-row row-between-wrapper"
|
||||
v-for="(item, couponwindiwIndex) in couponList"
|
||||
:key="couponwindiwIndex"
|
||||
>
|
||||
<div class="money font-color-red">
|
||||
¥<span class="num">{{ item.coupon_price }}</span>
|
||||
</div>
|
||||
<div class="text">
|
||||
<div class="name">
|
||||
购物买{{ item.use_min_price }}减{{ item.coupon_price }}
|
||||
</div>
|
||||
<div v-if="item.end_time">
|
||||
{{ item.start_time }}-{{ item.end_time }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height:1.2rem"></div>
|
||||
</div>
|
||||
<div class="lid">
|
||||
<div class="bnt font-color-red" @click="checked">立即领取</div>
|
||||
<div class="iconfont icon-guanbi3" @click="close"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mask" @touchmove.prevent :hidden="!value"></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from "vuex";
|
||||
import toLogin from "@/libs/login";
|
||||
import { couponReceiveBatch } from "@/api/user";
|
||||
|
||||
export default {
|
||||
name: "CouponWindow",
|
||||
props: {
|
||||
couponList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
computed: mapGetters(["isLogin"]),
|
||||
data: function() {
|
||||
return {
|
||||
value: true
|
||||
};
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {
|
||||
checked() {
|
||||
const isLogin = this.isLogin;
|
||||
if (!isLogin) return toLogin();
|
||||
|
||||
const ids = this.couponList.reduce((initial, coupon) => {
|
||||
initial.push(coupon.id);
|
||||
return initial;
|
||||
}, []);
|
||||
couponReceiveBatch(ids)
|
||||
.then(() => {
|
||||
this.$emit("success");
|
||||
this.$dialog.toast({ mes: "领取成功" });
|
||||
})
|
||||
.catch(() => {
|
||||
this.$dialog.toast({ mes: "已领取" });
|
||||
});
|
||||
if (isLogin) {
|
||||
this.value = false;
|
||||
this.$emit("checked");
|
||||
}
|
||||
},
|
||||
close: function() {
|
||||
this.value = false;
|
||||
this.$emit("close");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
24
components/DataFormat.vue
Normal file
24
components/DataFormat.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<span>{{time}}</span>
|
||||
</template>
|
||||
<script>
|
||||
import { dataFormat } from "@/utils";
|
||||
|
||||
export default {
|
||||
name: "DataFormat",
|
||||
props: ["data"],
|
||||
data: function() {
|
||||
return {
|
||||
time: ""
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.time = dataFormat(this.data);
|
||||
},
|
||||
watch: {
|
||||
"$props.data"(props) {
|
||||
this.time = dataFormat(this.data);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
24
components/DataFormatT.vue
Normal file
24
components/DataFormatT.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<span>{{time}}</span>
|
||||
</template>
|
||||
<script>
|
||||
import { dataFormatT } from "@/utils";
|
||||
|
||||
export default {
|
||||
name: "DataFormatT",
|
||||
props: ["data"],
|
||||
data: function() {
|
||||
return {
|
||||
time: ""
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.time = dataFormatT(this.data);
|
||||
},
|
||||
watch: {
|
||||
"$props.data"(props) {
|
||||
this.time = dataFormatT(this.data);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
78
components/Footer.vue
Normal file
78
components/Footer.vue
Normal file
@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="isIpx" class="iphonex-footer-bg"></div>
|
||||
<div v-else class="footer-bg"></div>
|
||||
<div id="footer" :class="[isIpx ? 'iphonex-footer' : '', 'acea-row row-middle'] ">
|
||||
<div
|
||||
@click="changeTabtar(footerIndex)"
|
||||
class="item"
|
||||
:class="{ on: footerIndex == tabtarIndex }"
|
||||
v-for="(item, footerIndex) in footerList"
|
||||
:key="footerIndex"
|
||||
>
|
||||
<div
|
||||
class="iconfont"
|
||||
:class="item.icon1 + ' ' + (footerIndex == tabtarIndex ? item.icon2 : '')"
|
||||
></div>
|
||||
<div>{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapState, mapMutations, mapActions } from "vuex";
|
||||
export default {
|
||||
name: "Footer",
|
||||
props: {},
|
||||
data: function() {
|
||||
return {
|
||||
footerList: [
|
||||
{
|
||||
name: "首页",
|
||||
icon1: "icon-shouye-xianxing",
|
||||
icon2: "icon-shouye",
|
||||
url: "/pages/home/main"
|
||||
},
|
||||
{
|
||||
name: "分类",
|
||||
icon1: "icon-yingyongchengxu-xianxing",
|
||||
icon2: "icon-yingyongchengxu",
|
||||
url: "/pages/shop/GoodsClass/main"
|
||||
},
|
||||
{
|
||||
name: "购物车",
|
||||
icon1: "icon-caigou-xianxing",
|
||||
icon2: "icon-caigou",
|
||||
url: "/pages/shop/ShoppingCart/main"
|
||||
},
|
||||
{
|
||||
name: "我的",
|
||||
icon1: "icon-yonghu-xianxing",
|
||||
icon2: "icon-yonghu",
|
||||
url: "/pages/user/User/main"
|
||||
}
|
||||
],
|
||||
isIpx: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["tabtarIndex"])
|
||||
},
|
||||
methods: {
|
||||
...mapActions(["changeTabtar"])
|
||||
},
|
||||
mounted() {
|
||||
let that = this;
|
||||
this.changeTabtar(this.$yroute.query.type);
|
||||
wx.getSystemInfo({
|
||||
success: function(res) {
|
||||
console.log(res);
|
||||
var name = "iPhone X";
|
||||
if (res.model.indexOf(name) > -1) {
|
||||
that.isIpx = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
52
components/GoodList.vue
Normal file
52
components/GoodList.vue
Normal file
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div class="goodList">
|
||||
<div
|
||||
@click="$yrouter.push({ path: '/pages/shop/GoodsCon/index',query:{id:item.id} })"
|
||||
class="item acea-row row-between-wrapper"
|
||||
v-for="(item, goodlistIndex) in goodList"
|
||||
:key="goodlistIndex"
|
||||
>
|
||||
<div class="pictrue">
|
||||
<img :src="item.image" class="image" />
|
||||
<img :src="$VUE_APP_RESOURCES_URL+'/images/one.png'" class="numPic" v-if="isSort === true && index === 0" />
|
||||
<img :src="$VUE_APP_RESOURCES_URL+'/images/two.png'" class="numPic" v-if="isSort === true && index === 1" />
|
||||
<img :src="$VUE_APP_RESOURCES_URL+'/images/three.png'" class="numPic" v-if="isSort === true && index === 2" />
|
||||
</div>
|
||||
<div class="underline">
|
||||
<div class="text">
|
||||
<div class="line1">{{ item.storeName }}</div>
|
||||
<div class="money font-color-red">
|
||||
¥
|
||||
<span class="num">{{ item.price }}</span>
|
||||
</div>
|
||||
<div class="vip-money acea-row row-middle">
|
||||
<div class="vip">
|
||||
¥{{ item.otPrice || 0
|
||||
}}
|
||||
</div>
|
||||
<span class="num">已售{{ item.sales }}{{ item.unitName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="iconfont icon-gouwuche cart-color acea-row row-center-wrapper"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "GoodList",
|
||||
props: {
|
||||
goodList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
isSort: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
</script>
|
69
components/Home.vue
Normal file
69
components/Home.vue
Normal file
@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div
|
||||
class="home"
|
||||
:style="{ top: top + 'px' }"
|
||||
style="position:fixed;"
|
||||
id="right-nav"
|
||||
@touchmove="touchmove($event)"
|
||||
>
|
||||
<div class="homeCon bg-color-red1" :class="homeActive === true ? 'on' : ''">
|
||||
<div
|
||||
@click="$yrouter.switchTab('/pages/home/index')"
|
||||
class="iconfont icon-shouye-xianxing "
|
||||
style="color: green;"
|
||||
></div>
|
||||
<div
|
||||
@click="$yrouter.switchTab('/pages/shop/ShoppingCart/index')"
|
||||
class="iconfont icon-caigou-xianxing"
|
||||
style="color: green;"
|
||||
></div>
|
||||
<!--<div @click="$yrouter.push('/pages/user/User/index'" class="iconfont icon-yonghu1"></div>-->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from "vuex";
|
||||
export default {
|
||||
name: "Home",
|
||||
props: {},
|
||||
data: function() {
|
||||
return {
|
||||
top: "",
|
||||
homeActive: true
|
||||
};
|
||||
},
|
||||
computed: mapGetters(["homeActive"]),
|
||||
methods: {
|
||||
touchmove(event) {
|
||||
// event.preventDefault();
|
||||
// let top =
|
||||
// event.touches[0].pageY -
|
||||
// (document.documentElement.scrollTop || document.body.scrollTop) -
|
||||
// this.$el.clientHeight;
|
||||
|
||||
// if (top > 390) top = 390;
|
||||
// else if (top < 55) top = 55;
|
||||
this.top = 55;
|
||||
},
|
||||
open: function() {
|
||||
this.homeActive
|
||||
? this.$store.commit("CLOSE_HOME")
|
||||
: this.$store.commit("OPEN_HOME");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.mystyl {
|
||||
display: inline-block;
|
||||
width: 0.64rem;
|
||||
height: 0.64rem;
|
||||
margin-top: 0.12rem;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #e1e1e1;
|
||||
border-radius: 50%;
|
||||
background-size: 1.24rem auto;
|
||||
background-repeat: no-repeat;
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
</style>
|
27
components/Loading.vue
Normal file
27
components/Loading.vue
Normal file
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<div
|
||||
class="Loads acea-row row-center-wrapper"
|
||||
v-if="loading || !loaded"
|
||||
style="margin-top: .2rem;"
|
||||
>
|
||||
<template v-if="loading">
|
||||
<div
|
||||
class="iconfont icon-jiazai loading acea-row row-center-wrapper"
|
||||
></div>
|
||||
正在加载中
|
||||
</template>
|
||||
<template v-else>
|
||||
上拉加载更多
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Loading",
|
||||
props: {
|
||||
loaded: Boolean,
|
||||
loading: Boolean
|
||||
}
|
||||
};
|
||||
</script>
|
45
components/OrderGoods.vue
Normal file
45
components/OrderGoods.vue
Normal file
@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<div class="orderGoods">
|
||||
<div class="total">共{{ cartInfo.length }}件商品</div>
|
||||
<div class="goodWrapper">
|
||||
<div class="item acea-row row-between-wrapper" v-for="cart in cartInfo" :key="cart.id">
|
||||
<div class="pictrue">
|
||||
<img :src="cart.productInfo.image" class="image" />
|
||||
</div>
|
||||
<div class="text">
|
||||
<div class="acea-row row-between-wrapper">
|
||||
<div class="name line1">{{ cart.productInfo.storeName }}</div>
|
||||
<div class="num">x {{ cart.cartNum }}</div>
|
||||
</div>
|
||||
<div
|
||||
class="attr line1"
|
||||
v-if="cart.productInfo.attrInfo"
|
||||
>{{ cart.productInfo.attrInfo.suk }}</div>
|
||||
<div class="money font-color-red">¥{{ cart.truePrice }}</div>
|
||||
<div
|
||||
class="evaluate"
|
||||
v-if="evaluate == 3"
|
||||
@click="$yrouter.push({ path: '/pages/shop/GoodsEvaluate/index',query:{id:cart.unique} })"
|
||||
>评价</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "OrderGoods",
|
||||
props: {
|
||||
evaluate: Number,
|
||||
cartInfo: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {};
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
202
components/Payment.vue
Normal file
202
components/Payment.vue
Normal file
@ -0,0 +1,202 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="payment" :class="value === true ? 'on' : ''">
|
||||
<div class="title acea-row row-center-wrapper">
|
||||
选择付款方式<span class="iconfont icon-guanbi" @click="close"></span>
|
||||
</div>
|
||||
<div
|
||||
class="item acea-row row-between-wrapper"
|
||||
v-if="types.indexOf('weixin') !== -1"
|
||||
@click="checked('weixin')"
|
||||
>
|
||||
<div class="left acea-row row-between-wrapper">
|
||||
<div class="iconfont icon-weixinzhifu"></div>
|
||||
<div class="text">
|
||||
<div class="name">微信支付</div>
|
||||
<div class="info">使用微信快捷支付</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="iconfont icon-xiangyou"></div>
|
||||
</div>
|
||||
<!-- <div
|
||||
class="item acea-row row-between-wrapper"
|
||||
v-if="types.indexOf('alipay') !== -1"
|
||||
@click="checked('alipay')"
|
||||
>
|
||||
<div class="left acea-row row-between-wrapper">
|
||||
<div class="iconfont icon-zhifubao"></div>
|
||||
<div class="text">
|
||||
<div class="name">支付宝支付</div>
|
||||
<div class="info">使用线上支付宝支付</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="iconfont icon-xiangyou"></div>
|
||||
</div> -->
|
||||
<div
|
||||
class="item acea-row row-between-wrapper"
|
||||
v-if="types.indexOf('yue') !== -1"
|
||||
@click="checked('yue')"
|
||||
>
|
||||
<div class="left acea-row row-between-wrapper">
|
||||
<div class="iconfont icon-yuezhifu"></div>
|
||||
<div class="text">
|
||||
<div class="name">余额支付</div>
|
||||
<div class="info">
|
||||
当前可用余额:<span class="money">{{ balance }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="iconfont icon-xiangyou"></div>
|
||||
</div>
|
||||
<!-- <div
|
||||
class="item acea-row row-between-wrapper"
|
||||
v-if="types.indexOf('offline') !== -1"
|
||||
@click="checked('offline')"
|
||||
>
|
||||
<div class="left acea-row row-between-wrapper">
|
||||
<div class="iconfont icon-yuezhifu1"></div>
|
||||
<div class="text">
|
||||
<div class="name">线下支付</div>
|
||||
<div class="info">选择线下付款方式</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="iconfont icon-xiangyou"></div>
|
||||
</div> -->
|
||||
</div>
|
||||
<div class="mask" v-show="value" @click="close"></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "Payment",
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
balance: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
types: {
|
||||
type: Array,
|
||||
default: () => ["weixin", "alipay", "yue", "offline"]
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {};
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {
|
||||
checked: function(type) {
|
||||
this.$emit("checked", type);
|
||||
this.close();
|
||||
},
|
||||
close: function() {
|
||||
this.$emit("input", false);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.payment {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
border-radius: 0.16rem 0.16rem 0 0;
|
||||
background-color: #fff;
|
||||
padding-bottom: 0.6rem;
|
||||
z-index: 99;
|
||||
transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
|
||||
-webkit-transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
|
||||
-moz-transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
|
||||
-o-transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
|
||||
transform: translate3d(0, 100%, 0);
|
||||
-webkit-transform: translate3d(0, 100%, 0);
|
||||
-ms-transform: translate3d(0, 100%, 0);
|
||||
-moz-transform: translate3d(0, 100%, 0);
|
||||
-o-transform: translate3d(0, 100%, 0);
|
||||
}
|
||||
|
||||
.payment.on {
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
-ms-transform: translate3d(0, 0, 0);
|
||||
-moz-transform: translate3d(0, 0, 0);
|
||||
-o-transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
.payment .title {
|
||||
text-align: center;
|
||||
height: 1.23rem;
|
||||
font-size: 0.32rem;
|
||||
color: #282828;
|
||||
font-weight: bold;
|
||||
padding-right: 0.3rem;
|
||||
margin-left: 0.3rem;
|
||||
position: relative;
|
||||
border-bottom: 0.01rem solid #eee;
|
||||
}
|
||||
|
||||
.payment .title .iconfont {
|
||||
position: absolute;
|
||||
right: 0.3rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 0.43rem;
|
||||
color: #8a8a8a;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.payment .item {
|
||||
border-bottom: 0.01rem solid #eee;
|
||||
height: 1.3rem;
|
||||
margin-left: 0.3rem;
|
||||
padding-right: 0.3rem;
|
||||
}
|
||||
|
||||
.payment .item .left {
|
||||
width: 6.1rem;
|
||||
}
|
||||
|
||||
.payment .item .left .text {
|
||||
width: 5.4rem;
|
||||
}
|
||||
|
||||
.payment .item .left .text .name {
|
||||
font-size: 0.32rem;
|
||||
color: #282828;
|
||||
}
|
||||
|
||||
.payment .item .left .text .info {
|
||||
font-size: 0.24rem;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.payment .item .left .text .info .money {
|
||||
color: #ff9900;
|
||||
}
|
||||
|
||||
.payment .item .left .iconfont {
|
||||
font-size: 0.45rem;
|
||||
color: #09bb07;
|
||||
}
|
||||
|
||||
.payment .item .left .iconfont.icon-zhifubao {
|
||||
color: #00aaea;
|
||||
}
|
||||
|
||||
.payment .item .left .iconfont.icon-yuezhifu {
|
||||
color: #ff9900;
|
||||
}
|
||||
|
||||
.payment .item .left .iconfont.icon-yuezhifu1 {
|
||||
color: #eb6623;
|
||||
}
|
||||
|
||||
.payment .item .iconfont {
|
||||
font-size: 0.3rem;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
133
components/PriceChange.vue
Normal file
133
components/PriceChange.vue
Normal file
@ -0,0 +1,133 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="priceChange" :class="change === true ? 'on' : ''">
|
||||
<div class="priceTitle">
|
||||
<span v-if="status==0">
|
||||
<span v-if="orderInfo.refundStatus == 1">立即退款</span>
|
||||
<span v-if="orderInfo.refundStatus != 1">一键改价</span>
|
||||
</span>
|
||||
<span v-if="status!=0">订单备注</span>
|
||||
<span class="iconfont icon-guanbi" @click="close"></span>
|
||||
</div>
|
||||
<div class="listChange" v-if="status == 0">
|
||||
<div class="item acea-row row-between-wrapper" v-if="orderInfo.refundStatus === 0">
|
||||
<div>商品总价(¥)</div>
|
||||
<div class="money">
|
||||
{{ orderInfo.totalPrice }}
|
||||
<span class="iconfont icon-suozi"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item acea-row row-between-wrapper" v-if="orderInfo.refundStatus === 0">
|
||||
<div>原始邮费(¥)</div>
|
||||
<div class="money">
|
||||
{{ orderInfo.payPostage }}
|
||||
<span class="iconfont icon-suozi"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item acea-row row-between-wrapper" v-if="orderInfo.refundStatus === 0">
|
||||
<div>实际支付(¥)</div>
|
||||
<div class="money">
|
||||
<input
|
||||
type="text"
|
||||
v-model="price"
|
||||
:class="focus === true ? 'on' : ''"
|
||||
@focus="priceChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item acea-row row-between-wrapper" v-if="orderInfo.refundStatus === 1">
|
||||
<div>实际支付(¥)</div>
|
||||
<div class="money">
|
||||
{{ orderInfo.payPrice }}
|
||||
<span class="iconfont icon-suozi"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item acea-row row-between-wrapper" v-if="orderInfo.refundStatus === 1">
|
||||
<div>退款金额(¥)</div>
|
||||
<div class="money">
|
||||
<input
|
||||
type="text"
|
||||
v-model="refund_price"
|
||||
:class="focus === true ? 'on' : ''"
|
||||
@focus="priceChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="listChange" v-else>
|
||||
<textarea
|
||||
:placeholder="'请填写备注信息...'"
|
||||
v-model="remark"
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="modify" @click="save">{{ orderInfo.refundStatus === 0 ? "立即修改" : "确认退款" }}</div>
|
||||
<div class="modify1" @click="refuse" v-if="orderInfo.refundStatus === 1">拒绝退款</div>
|
||||
</div>
|
||||
<div class="mask" @touchmove.prevent v-show="change === true"></div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.priceChange .listChange textarea {
|
||||
border: 1px solid #eee;
|
||||
width: 100%;
|
||||
height: 2rem;
|
||||
margin-top: 0.5rem;
|
||||
border-radius: 0.1rem;
|
||||
color: #333;
|
||||
padding: 0.2rem;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
export default {
|
||||
name: "PriceChange",
|
||||
components: {},
|
||||
props: {
|
||||
change: Boolean,
|
||||
orderInfo: Object,
|
||||
status: String
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
focus: false,
|
||||
price: 0,
|
||||
refund_price: 0,
|
||||
remark: ""
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
orderInfo: function() {
|
||||
this.price = this.orderInfo.payPrice;
|
||||
this.refund_price = this.orderInfo.payPrice;
|
||||
this.remark = "";
|
||||
}
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {
|
||||
priceChange: function() {
|
||||
this.focus = true;
|
||||
},
|
||||
close: function() {
|
||||
this.price = this.orderInfo.payPrice;
|
||||
this.$emit("closechange", false);
|
||||
},
|
||||
save: function() {
|
||||
let that = this;
|
||||
that.$emit("savePrice", {
|
||||
price: that.price,
|
||||
refund_price: that.refund_price,
|
||||
type: 1,
|
||||
remark: that.remark
|
||||
});
|
||||
},
|
||||
refuse: function() {
|
||||
let that = this;
|
||||
that.$emit("savePrice", {
|
||||
price: that.price,
|
||||
refund_price: that.refund_price,
|
||||
type: 2,
|
||||
remark: that.remark
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
61
components/ProductConSwiper.vue
Normal file
61
components/ProductConSwiper.vue
Normal file
@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<div class="slider-banner product-bg">
|
||||
<swiper class="swiper-wrapper" @change="handleChange" v-if="imgUrls.length > 0">
|
||||
<block v-for="(item, imgUrlsIndex) in imgUrls" :key="imgUrlsIndex">
|
||||
<swiper-item>
|
||||
<img :src="item" class="slide-image" />
|
||||
</swiper-item>
|
||||
</block>
|
||||
</swiper>
|
||||
<!-- <swiper class="swiper-wrapper" :options="ProductConSwiper" v-if="imgUrls.length > 0">
|
||||
<swiperSlide class="swiper-slide" v-for="item in imgUrls" :key="item" ref="goodSwiper">
|
||||
<img :src="item" class="slide-image" />
|
||||
</swiperSlide>
|
||||
</swiper>-->
|
||||
<div class="pages">{{ currents || 1 }}/{{ imgUrls.length || 1 }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// import { swiper, swiperSlide } from "vue-awesome-swiper";
|
||||
|
||||
export default {
|
||||
name: "ProductConSwiper",
|
||||
components: {
|
||||
// swiper,
|
||||
// swiperSlide
|
||||
},
|
||||
props: {
|
||||
imgUrls: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
let that = this;
|
||||
return {
|
||||
currents: 1,
|
||||
ProductConSwiper: {
|
||||
autoplay: {
|
||||
disableOnInteraction: false,
|
||||
delay: 2000
|
||||
},
|
||||
loop: true,
|
||||
speed: 1000,
|
||||
observer: true,
|
||||
observeParents: true,
|
||||
on: {
|
||||
slideChangeTransitionStart: function() {
|
||||
that.currents = this.realIndex + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {
|
||||
handleChange(event) {
|
||||
this.currents = event.mp.detail.current + 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
113
components/ProductWindow.vue
Normal file
113
components/ProductWindow.vue
Normal file
@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="product-window" :class="attr.cartAttr === true ? 'on' : ''">
|
||||
<div class="textpic acea-row row-between-wrapper">
|
||||
<div class="pictrue">
|
||||
<img :src="attr.productSelect.image" class="image" />
|
||||
</div>
|
||||
<div class="text">
|
||||
<div class="line1">{{ attr.productSelect.store_name }}</div>
|
||||
<div class="money font-color-red">
|
||||
¥
|
||||
<span class="num">{{ attr.productSelect.price }}</span>
|
||||
<span class="stock">库存: {{ attr.productSelect.stock }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="iconfont icon-guanbi" @click="closeAttr"></div>
|
||||
</div>
|
||||
<div class="productWinList">
|
||||
<div class="item" v-for="(item, indexw) in attr.productAttr" :key="indexw">
|
||||
<div class="title">{{ item.attrName }}</div>
|
||||
<div class="listn acea-row row-middle">
|
||||
<div
|
||||
class="itemn"
|
||||
:class="item.index == indexn ? 'on' : ''"
|
||||
v-for="(itemn, indexn) in item.attrValue"
|
||||
@click="tapAttr(indexw, indexn)"
|
||||
:key="indexn"
|
||||
>{{ itemn.attr }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cart">
|
||||
<div class="title">数量</div>
|
||||
<div class="carnum acea-row row-left">
|
||||
<div class="item reduce" :class="cartNum <= 1 ? 'on' : ''" @click="CartNumDes">-</div>
|
||||
<div class="item num">{{ cartNum }}</div>
|
||||
<div
|
||||
class="item plus"
|
||||
:class="
|
||||
cartNum >= attr.productSelect.stock
|
||||
? 'on'
|
||||
: ''
|
||||
"
|
||||
@click="CartNumAdd"
|
||||
>+</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mask" @touchmove.prevent :hidden="attr.cartAttr === false" @click="closeAttr"></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "ProductWindow",
|
||||
props: {
|
||||
attr: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
cartNum: {
|
||||
type: String,
|
||||
default: () => 1
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {};
|
||||
},
|
||||
watch: {
|
||||
attr:function(ne){
|
||||
console.log(ne)
|
||||
}
|
||||
},
|
||||
mounted: function() {
|
||||
console.log(this.attr)
|
||||
},
|
||||
methods: {
|
||||
closeAttr: function() {
|
||||
this.$emit("changeFun", { action: "changeattr", value: false });
|
||||
},
|
||||
CartNumDes: function() {
|
||||
this.$emit("changeFun", { action: "ChangeCartNum", value: false });
|
||||
},
|
||||
CartNumAdd: function() {
|
||||
this.$emit("changeFun", { action: "ChangeCartNum", value: 1 });
|
||||
},
|
||||
tapAttr: function(indexw, indexn) {
|
||||
let that = this;
|
||||
console.log(that.attr.productAttr);
|
||||
console.log(that.attr.productAttr[indexw], indexw, indexn);
|
||||
that.attr.productAttr[indexw].index = indexn;
|
||||
let value = that
|
||||
.getCheckedValue()
|
||||
.sort()
|
||||
.join(",");
|
||||
console.log(value);
|
||||
that.$emit("changeFun", { action: "ChangeAttr", value: value });
|
||||
},
|
||||
//获取被选中属性;
|
||||
getCheckedValue: function() {
|
||||
let productAttr = this.attr.productAttr;
|
||||
let value = [];
|
||||
for (let i = 0; i < productAttr.length; i++) {
|
||||
for (let j = 0; j < productAttr[i].attrValueArr.length; j++) {
|
||||
if (productAttr[i].index === j) {
|
||||
value.push(productAttr[i].attrValueArr[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
41
components/PromotionGood.vue
Normal file
41
components/PromotionGood.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div class="promotionGood" v-if="benefit.length > 0">
|
||||
<div
|
||||
@click="$yrouter.push({ path: '/pages/shop/GoodsCon/index',query:{id:item.id} })"
|
||||
class="item acea-row row-between-wrapper"
|
||||
v-for="(item, promotionGoodIndex) in benefit"
|
||||
:key="promotionGoodIndex"
|
||||
>
|
||||
<div class="pictrue">
|
||||
<img :src="item.image" class="image" />
|
||||
</div>
|
||||
<div class="text">
|
||||
<div class="name line1">{{ item.storeName }}</div>
|
||||
<div class="sp-money acea-row">
|
||||
<div class="moneyCon">
|
||||
促销价: ¥
|
||||
<span class="num">{{ item.price }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="acea-row row-between-wrapper">
|
||||
<div class="money">日常价:¥{{ item.otPrice }}</div>
|
||||
<div>仅剩:{{ item.stock }}{{ item.unitName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "PromotionGood",
|
||||
props: {
|
||||
benefit: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
</script>
|
69
components/Recommend.vue
Normal file
69
components/Recommend.vue
Normal file
@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div class="recommend" ref="container">
|
||||
<div class="title acea-row row-center-wrapper">
|
||||
<span class="iconfont icon-zhuangshixian"></span>
|
||||
<span class="name">为你推荐</span>
|
||||
<span class="iconfont icon-zhuangshixian lefticon"></span>
|
||||
</div>
|
||||
<div class="recommendList acea-row row-between-wrapper">
|
||||
<div
|
||||
@click="$yrouter.push({ path: '/pages/shop/GoodsCon/index',query:{id:item.id} })"
|
||||
class="item"
|
||||
v-for="(item, recommendIndex) in hostProduct"
|
||||
:key="recommendIndex"
|
||||
>
|
||||
<div class="pictrue">
|
||||
<img :src="item.image" class="image" />
|
||||
</div>
|
||||
<div class="name line1">{{ item.storeName }}</div>
|
||||
<div class="money font-color-red">
|
||||
¥
|
||||
<span class="num">{{ item.price }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Loading :loaded="loadend" :loading="loading"></Loading>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getHostProducts } from "@/api/store";
|
||||
import Loading from "@/components/Loading";
|
||||
export default {
|
||||
name: "Recommend",
|
||||
props: {},
|
||||
components: {
|
||||
Loading
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
hostProduct: [],
|
||||
page: 1,
|
||||
limit: 20,
|
||||
loadTitle: "",
|
||||
loading: false,
|
||||
loadend: false
|
||||
};
|
||||
},
|
||||
mounted: function() {
|
||||
this.hostProducts();
|
||||
},
|
||||
methods: {
|
||||
hostProducts: function() {
|
||||
let that = this;
|
||||
if (that.loading) return; //阻止下次请求(false可以进行请求);
|
||||
if (that.loadend) return; //阻止结束当前请求(false可以进行请求);
|
||||
that.loading = true;
|
||||
getHostProducts(that.page, that.limit).then(res => {
|
||||
that.loading = false;
|
||||
//apply();js将一个数组插入另一个数组;
|
||||
that.hostProduct.push.apply(that.hostProduct, res.data);
|
||||
that.loadend = res.data.length < that.limit; //判断所有数据是否加载完成;
|
||||
that.page = that.page + 1;
|
||||
});
|
||||
}
|
||||
},
|
||||
onReachBottom() {
|
||||
!this.loading && this.hostProducts();
|
||||
}
|
||||
};
|
||||
</script>
|
40
components/ShareInfo.vue
Normal file
40
components/ShareInfo.vue
Normal file
@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<div v-if="shareInfoStatus" class="poster-first">
|
||||
<div class="mask-share">
|
||||
<img :src="$VUE_APP_RESOURCES_URL+'/images/share-info.png'" @click="shareInfoClose" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.poster-first {
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
.mask-share {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 999;
|
||||
}
|
||||
.mask-share img {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
export default {
|
||||
name: "ShareInfo",
|
||||
props: {
|
||||
shareInfoStatus: Boolean
|
||||
},
|
||||
data: function() {
|
||||
return {};
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {
|
||||
shareInfoClose: function() {
|
||||
this.$emit("setShareInfoStatus");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
43
components/ShareRedPackets.vue
Normal file
43
components/ShareRedPackets.vue
Normal file
@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="sharing-packets" :class="state === true ? 'on' : ''">
|
||||
<div
|
||||
class="iconfont icon-guanbi acea-row row-center-wrapper"
|
||||
@click="closeShare"
|
||||
></div>
|
||||
<div class="line"></div>
|
||||
<div class="sharing-con" @click="goShare">
|
||||
<img :src="$VUE_APP_RESOURCES_URL+'/images/red-packets.png'" class="image" />
|
||||
<div class="text font-color-red">
|
||||
<div>会员分享返</div>
|
||||
<div class="money"><span class="label">¥</span>{{ priceName }}</div>
|
||||
<div class="tip">下单即返佣金</div>
|
||||
<div class="shareBut">立即分享</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "ShareRedPackets",
|
||||
props: {
|
||||
priceName: {
|
||||
type: [String, Number],
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
state: false
|
||||
};
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {
|
||||
goShare: function() {
|
||||
this.$emit("changeFun", { action: "shareCode", value: false });
|
||||
},
|
||||
closeShare: function() {
|
||||
this.state = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
171
components/StorePoster.vue
Normal file
171
components/StorePoster.vue
Normal file
@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<div v-if="posterImageStatus" class="poster-first">
|
||||
<canvas style="width:747px;height:1326px" canvas-id="myCanvas"></canvas>
|
||||
<!-- <div class="poster-pop" v-show="!canvasStatus">
|
||||
<img
|
||||
:src="$VUE_APP_RESOURCES_URL+'/images/poster-close.png'"
|
||||
class="close"
|
||||
@click="posterImageClose"
|
||||
/>
|
||||
<div class="canvas" ref="poster">
|
||||
<img class="image" :src="posterData.image" alt="商品图片" />
|
||||
<div class="text black">
|
||||
<span v-text="posterData.title"></span>
|
||||
</div>
|
||||
<div class="text rad">
|
||||
<span v-text="'¥' + posterData.price"></span>
|
||||
</div>
|
||||
<div class="code">
|
||||
<div class="code-img">
|
||||
<img :src="posterData.code" show-menu-by-longpress mode="widthFix" alt="二维码" />
|
||||
</div>
|
||||
<div class="code-text">
|
||||
<span>长按识别二维码 立即购买</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="save-poster" @click="savePosterPath">生成图片</div>
|
||||
</div> -->
|
||||
<div class="poster-pop" v-show="canvasStatus">
|
||||
<img
|
||||
:src="$VUE_APP_RESOURCES_URL+'/images/poster-close.png'"
|
||||
class="close"
|
||||
@click="posterImageClose"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<img :src="posterImage" alt="tp" class="poster-image" show-menu-by-longpress mode="widthFix" />
|
||||
<div class="keep">长按图片可以保存到手机</div>
|
||||
</div>
|
||||
<div class="mask"></div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.poster-first {
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
.poster-pop {
|
||||
width: 4.5rem;
|
||||
height: 8rem;
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 99;
|
||||
top: 50%;
|
||||
margin-top: -4.6rem;
|
||||
}
|
||||
.poster-pop .canvas {
|
||||
background-color: #ffffff;
|
||||
height: 8rem;
|
||||
}
|
||||
.poster-pop .poster-image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.poster-pop .canvas .image {
|
||||
width: 4.5rem;
|
||||
height: 4.5rem;
|
||||
display: block;
|
||||
}
|
||||
.poster-pop .canvas .text {
|
||||
text-align: center;
|
||||
color: #000000;
|
||||
margin-top: 0.32rem;
|
||||
}
|
||||
.poster-pop .canvas .text.black {
|
||||
height: 0.68rem;
|
||||
}
|
||||
.poster-pop .canvas .text.rad {
|
||||
color: #ff0000;
|
||||
}
|
||||
.poster-pop .canvas .code {
|
||||
height: 1.4rem;
|
||||
display: flex;
|
||||
}
|
||||
.poster-pop .canvas .code .code-img {
|
||||
width: 33%;
|
||||
padding: 0.06rem;
|
||||
}
|
||||
.poster-pop .canvas .code .code-img img {
|
||||
width: 100%;
|
||||
}
|
||||
.poster-pop .canvas .code .code-text {
|
||||
width: 60%;
|
||||
font-size: 0.12rem;
|
||||
line-height: 1.64rem;
|
||||
}
|
||||
.poster-pop .close {
|
||||
width: 0.46rem;
|
||||
height: 0.75rem;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: -0.73rem;
|
||||
display: block;
|
||||
}
|
||||
.poster-pop .save-poster {
|
||||
background-color: #df2d0a;
|
||||
font-size: 0.22rem;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
height: 0.76rem;
|
||||
line-height: 0.76rem;
|
||||
width: 100%;
|
||||
margin-top: -0.04rem;
|
||||
}
|
||||
.poster-pop .keep {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
font-size: 0.25rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
.mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
z-index: 9;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
// import html2canvas from "html2canvas";
|
||||
import { PosterCanvas } from "@/utils";
|
||||
|
||||
export default {
|
||||
name: "StorePoster",
|
||||
props: {
|
||||
posterImageStatus: Boolean,
|
||||
posterData: Object
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
canvasStatus: false,
|
||||
posterImage: ""
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
posterImageStatus: function() {
|
||||
var that = this;
|
||||
if (that.posterImageStatus === true) {
|
||||
that.$nextTick(function() {
|
||||
that.savePosterPath();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {
|
||||
posterImageClose: function() {
|
||||
this.posterImageStatus = false;
|
||||
this.canvasStatus = false;
|
||||
this.$emit("setPosterImageStatus");
|
||||
},
|
||||
savePosterPath: function() {
|
||||
PosterCanvas(this.posterData, posterImage => {
|
||||
this.canvasStatus = true;
|
||||
this.posterImage = posterImage;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
146
components/SwitchWindow.vue
Normal file
146
components/SwitchWindow.vue
Normal file
@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="switchWindow" :class="switchActive === true ? 'on' : ''">
|
||||
<!-- @/assets/images/public.png -->
|
||||
<div class="pictrue">
|
||||
<img v-if="login_type === 'h5'" :src="$VUE_APP_RESOURCES_URL+'/images/h5.png'" />
|
||||
<img :src="$VUE_APP_RESOURCES_URL+'/images/h5.png'" alt="" v-else />
|
||||
</div>
|
||||
<!-- 是否选择切换到小程序账户? -->
|
||||
<div class="info">
|
||||
是否选择切换到<span class="font-color" v-if="login_type === 'h5'"
|
||||
>微信账号</span
|
||||
>
|
||||
<span class="font-color" v-else>手机用户</span>?
|
||||
</div>
|
||||
<div class="switchBnt" @click="switchH5">切换</div>
|
||||
<div class="switchBnt cancelBnt" @click="switchClose">取消</div>
|
||||
</div>
|
||||
<div
|
||||
class="mask"
|
||||
@touchmove.prevent
|
||||
v-show="switchActive === true"
|
||||
@click="switchClose"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
.switchWindow {
|
||||
width: 5.6rem;
|
||||
border-radius: 0.2rem;
|
||||
-webkit-border-radius: 0.2rem;
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -2.8rem;
|
||||
margin-top: -3rem;
|
||||
z-index: 99;
|
||||
padding: 0.5rem 0.3rem 0.4rem 0.3rem;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
transition: all 0.3s ease-in-out 0s;
|
||||
-webkit-transition: all 0.3s ease-in-out 0s;
|
||||
-moz-transition: all 0.3s ease-in-out 0s;
|
||||
-o-transition: all 0.3s ease-in-out 0s;
|
||||
opacity: 0;
|
||||
transform: scale(0);
|
||||
}
|
||||
.switchWindow.on {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
-webkit-transform: scale(1);
|
||||
-ms-transform: scale(1);
|
||||
-moz-transform: scale(1);
|
||||
-o-transform: scale(1);
|
||||
}
|
||||
.switchWindow .pictrue {
|
||||
width: 2.36rem;
|
||||
height: 2.36rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.switchWindow .pictrue img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
.switchWindow .info {
|
||||
font-size: 0.32rem;
|
||||
color: #282828;
|
||||
margin-top: 0.44rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
.switchWindow .switchBnt {
|
||||
font-size: 0.32rem;
|
||||
color: #fff;
|
||||
width: 3.6rem;
|
||||
height: 0.82rem;
|
||||
border-radius: 0.41rem;
|
||||
-webkit-border-radius: 0.41rem;
|
||||
margin: 0.57rem auto 0 auto;
|
||||
line-height: 0.82rem;
|
||||
background-image: linear-gradient(to right, #f67a38 0%, #f11b09 100%);
|
||||
background-image: -webkit-linear-gradient(to right, #f67a38 0%, #f11b09 100%);
|
||||
background-image: -moz-linear-gradient(to right, #f67a38 0%, #f11b09 100%);
|
||||
}
|
||||
.switchWindow .switchBnt.cancelBnt {
|
||||
background-color: #fff;
|
||||
color: #999;
|
||||
background-image: none;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import { switchH5Login } from "@/api/user";
|
||||
import cookie from "@/utils/store/cookie";
|
||||
import store from "@//store";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
export default {
|
||||
name: "SwitchWindow",
|
||||
props: {
|
||||
switchActive: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
login_type: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {};
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {
|
||||
switchClose: function() {
|
||||
this.$emit("changeswitch", false); //$emit():注册事件;
|
||||
},
|
||||
switchH5() {
|
||||
let that = this;
|
||||
wx.showLoading({title: '正在切换中'})
|
||||
if (that.login_type === "h5") {
|
||||
cookie.set("loginType", "wechat", 60);
|
||||
wx.hideLoading()
|
||||
this.$store.commit("LOGOUT");
|
||||
this.$emit("changeswitch", false);
|
||||
location.reload();
|
||||
} else {
|
||||
switchH5Login()
|
||||
.then(({ data }) => {
|
||||
wx.hideLoading()
|
||||
const expires_time = dayjs(data.expires_time);
|
||||
store.commit("LOGIN", data.token, expires_time);
|
||||
this.$emit("changeswitch", false);
|
||||
location.reload();
|
||||
})
|
||||
.catch(err => {
|
||||
wx.hideLoading()
|
||||
return that.$dialog.toast({ mes: err });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
43
components/UserEvaluation.vue
Normal file
43
components/UserEvaluation.vue
Normal file
@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="evaluateWtapper">
|
||||
<div class="evaluateItem" v-for="(item, evaluateWtapperIndex) in reply" :key="evaluateWtapperIndex">
|
||||
<div class="pic-text acea-row row-middle">
|
||||
<div class="pictrue">
|
||||
<img :src="item.avatar" class="image" />
|
||||
</div>
|
||||
<div class="acea-row row-middle">
|
||||
<div class="name line1">{{ item.nickname }}</div>
|
||||
<div class="start" :class="'star' + item.star"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="time">{{ item.add_time }} {{ item.suk }}</div>
|
||||
<div class="evaluate-infor">{{ item.comment }}</div>
|
||||
<div class="imgList acea-row">
|
||||
<div class="pictrue" v-for="(itemn, eq) in item.picturesArr" :key="eq">
|
||||
<img :src="itemn" class="image" />
|
||||
</div>
|
||||
</div>
|
||||
<!--<div class="reply" v-if="item.merchant_reply_content">-->
|
||||
<!--<span class="font-color-red">店小二</span>:{{-->
|
||||
<!--item.merchant_reply_content-->
|
||||
<!--}}-->
|
||||
<!--</div>-->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "UserEvaluation",
|
||||
props: {
|
||||
reply: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {};
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
128
components/WriteOff.vue
Normal file
128
components/WriteOff.vue
Normal file
@ -0,0 +1,128 @@
|
||||
<template>
|
||||
<div v-show="iShidden === false">
|
||||
<div class="WriteOff">
|
||||
<div class="pictrue"><img :src="orderInfo.image" /></div>
|
||||
<div class="num acea-row row-center-wrapper">
|
||||
{{ orderInfo.order_id }}
|
||||
</div>
|
||||
<div class="tip">确定要核销此订单吗?</div>
|
||||
<div class="sure" @click="confirm">确定核销</div>
|
||||
<div class="sure cancel" @click="cancel">取消</div>
|
||||
</div>
|
||||
<div class="mask" @touchmove.prevent></div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.WriteOff {
|
||||
width: 5.6rem;
|
||||
height: 8rem;
|
||||
background-color: #fff;
|
||||
border-radius: 0.2rem;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -4rem;
|
||||
margin-left: -2.8rem;
|
||||
z-index: 99;
|
||||
padding-top: 0.55rem;
|
||||
}
|
||||
.WriteOff .pictrue {
|
||||
width: 3.4rem;
|
||||
height: 3.4rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.WriteOff .pictrue img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
border-radius: 0.1rem;
|
||||
}
|
||||
.WriteOff .num {
|
||||
font-size: 0.3rem;
|
||||
color: #666;
|
||||
margin: 0.28rem 0 0.3rem 0;
|
||||
}
|
||||
.WriteOff .num .see {
|
||||
font-size: 0.16rem;
|
||||
color: #fff;
|
||||
border-radius: 0.04rem;
|
||||
background-color: #c68937;
|
||||
padding-left: 0.05rem;
|
||||
margin-left: 0.12rem;
|
||||
}
|
||||
.WriteOff .num .see .iconfont {
|
||||
font-size: 0.15rem;
|
||||
}
|
||||
.WriteOff .tip {
|
||||
font-size: 0.36rem;
|
||||
color: #282828;
|
||||
text-align: center;
|
||||
border-top: 1px dashed #ccc;
|
||||
padding-top: 0.4rem;
|
||||
position: relative;
|
||||
}
|
||||
.WriteOff .tip:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 0.25rem;
|
||||
height: 0.25rem;
|
||||
border-radius: 50%;
|
||||
background-color: #7f7f7f;
|
||||
right: -0.125rem;
|
||||
top: -0.125rem;
|
||||
}
|
||||
.WriteOff .tip:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 0.25rem;
|
||||
height: 0.25rem;
|
||||
border-radius: 50%;
|
||||
background-color: #7f7f7f;
|
||||
left: -0.125rem;
|
||||
top: -0.125rem;
|
||||
}
|
||||
.WriteOff .sure {
|
||||
font-size: 0.32rem;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 0.82rem;
|
||||
height: 0.82rem;
|
||||
width: 4.6rem;
|
||||
border-radius: 0.41rem;
|
||||
margin: 0.4rem auto 0 auto;
|
||||
background-image: linear-gradient(to right, #f67a38 0%, #f11b09 100%);
|
||||
background-image: -webkit-linear-gradient(to right, #f67a38 0%, #f11b09 100%);
|
||||
background-image: -moz-linear-gradient(to right, #f67a38 0%, #f11b09 100%);
|
||||
}
|
||||
.WriteOff .sure.cancel {
|
||||
background-image: none;
|
||||
color: #999;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
export default {
|
||||
name: "WriteOff",
|
||||
props: {
|
||||
iShidden: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
orderInfo: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {};
|
||||
},
|
||||
mounted: function() {},
|
||||
methods: {
|
||||
cancel: function() {
|
||||
this.$emit("cancel", true);
|
||||
},
|
||||
confirm: function() {
|
||||
this.$emit("confirm", true);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
Reference in New Issue
Block a user