增加基本项目配置

This commit is contained in:
Gao xiaosong
2020-03-15 13:59:43 +08:00
commit 397082cdaf
1117 changed files with 105700 additions and 0 deletions

View 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
View 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>

View 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
View 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>

View 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
View 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>

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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>

View 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>

View 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>

View 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
View 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
View 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>

View 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
View 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
View 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>

View 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
View 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>