增加基本项目配置

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
+77
View File
@@ -0,0 +1,77 @@
<template>
<div class="lottie-bg">
<div id="lottie"><img src="../../assets/images/live-logo.gif" rel="preload" style="width: 100%;" /></div>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex';
// 组件
// import request from "@//api/request";
import { wxappAuth, getUser } from '@/api/user';
import dayjs from 'dayjs';
import cookie from '@/utils/store/cookie';
import { parseQuery, login, handleQrCode } from '@/utils';
export default {
name: 'Loading',
data() {
return {};
},
mounted() {
var url = handleQrCode();
// 判断是否是分销
if (url) {
var spread = cookie.get('spread');
let urlSpread = parseInt(url.spread);
if (!Number.isNaN(urlSpread) && spread !== urlSpread) {
cookie.set('spread', urlSpread || 0);
} else if (spread === 0 || typeof spread !== 'number') {
cookie.set('spread', urlSpread || 0);
}
}
this.toLaunch();
// login({
// fail: () => {
// this.toLaunch();
// }
// });
},
methods: {
...mapActions(['changeAuthorization', 'changeUserInfo']),
toLaunch() {
console.log(this);
this.changeAuthorization(false);
this.$yrouter.switchTab({
path: '/pages/home/index',
});
}
}
};
</script>
<style scoped>
.lottie-bg {
position: fixed;
left: 0;
top: 0;
background-color: #fff;
width: 100%;
height: 100%;
z-index: 999;
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
}
#lottie {
width: 35%;
display: block;
overflow: hidden;
transform: translate3d(0, 0, 0);
margin: auto;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+54
View File
@@ -0,0 +1,54 @@
<template>
<div class="not-defined">
<img :src="$VUE_APP_RESOURCES_URL+'/images/404.png'" />
<div class="content">
<h3 class="title">页面未找到</h3>
<span
>抱歉您访问的页面不存在请返回上一级或点击下方按钮返回首页...</span
>
</div>
<div class="btn" @click="$yrouter.replace({ path: '/' })">
返回首页
</div>
</div>
</template>
<script>
export default {
name: "NotDefined"
};
</script>
<style scoped>
.not-defined img {
width: 100%;
margin-top: 18%;
}
.content {
padding: 0 1rem;
text-align: center;
color: #44405e;
font-size: 15px;
}
.title {
margin-bottom: 0.6rem;
color: #302c48;
font-size: 20px;
}
.btn {
color: #fff;
background-color: #ef4c4c;
font-size: 16px;
padding: 0.16rem;
border-radius: 25px;
text-align: center;
width: 2.4rem;
margin: 0 auto;
margin-top: 1rem;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+131
View File
@@ -0,0 +1,131 @@
<template>
<div class="bargain-record" ref="container">
<div class="item" v-for="(item, bargainrecordIndex) in bargain" :key="bargainrecordIndex">
<div class="picTxt acea-row row-between-wrapper">
<div class="pictrue">
<img :src="item.image" />
</div>
<div class="text acea-row row-column-around">
<div class="line1">{{ item.title }}</div>
<count-down
:is-day="true"
:tip-text="'倒计时 '"
:day-text="' '"
:hour-text="' '"
:minute-text="' '"
:second-text="' '"
:datatime="item.datatime"
></count-down>
<div class="money font-color-red">
已砍至
<span class="symbol"></span>
<span class="num">{{ item.residuePrice }}</span>
</div>
</div>
</div>
<div class="bottom acea-row row-between-wrapper">
<div class="purple" v-if="item.status === 1">活动进行中</div>
<div class="success" v-else-if="item.status === 3">砍价成功</div>
<div class="end" v-else>活动已结束</div>
<div class="acea-row row-middle row-right">
<div
class="bnt cancel"
v-if="item.status === 1"
@click="getBargainUserCancel(item.bargainId)"
>取消活动</div>
<div
class="bnt bg-color-red"
v-if="item.status === 1"
@click="goDetail(item.bargainId)"
>继续砍价</div>
<div class="bnt bg-color-red" v-else @click="goList">重开一个</div>
</div>
</div>
</div>
<Loading :loaded="status" :loading="loadingList"></Loading>
</div>
</template>
<script>
import CountDown from "@/components/CountDown";
import { getBargainUserList, getBargainUserCancel } from "@/api/activity";
import Loading from "@/components/Loading";
export default {
name: "BargainRecord",
components: {
CountDown,
Loading
},
props: {},
data: function() {
return {
bargain: [],
status: false, //砍价列表是否获取完成 false 未完成 true 完成
loadingList: false, //当前接口是否请求完成 false 完成 true 未完成
page: 1, //页码
limit: 20 //数量
};
},
mounted: function() {
this.getBargainUserList();
},
onReachBottom() {
!this.loadingList && this.getBargainUserList();
},
methods: {
goDetail: function(id) {
this.$yrouter.push({
path: "/pages/activity/DargainDetails/main",
query: { id, partake: 0 }
});
},
goList: function() {
this.$yrouter.push({
path: "/pages/activity/GoodsBargain/main"
});
},
getBargainUserList: function() {
var that = this;
if (that.loadingList) return;
if (that.status) return;
getBargainUserList({ page: that.page, limit: that.limit })
.then(res => {
that.status = res.data.length < that.limit;
that.bargain.push.apply(that.bargain, res.data);
that.page++;
that.loadingList = false;
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
getBargainUserCancel: function(bargainId) {
var that = this;
getBargainUserCancel({ bargainId: bargainId })
.then(res => {
wx.showToast({
title: res.msg,
icon: "success",
duration: 2000
});
that.status = false;
that.loadingList = false;
that.page = 1;
that.bargain = [];
that.getBargainUserList();
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+509
View File
@@ -0,0 +1,509 @@
<template>
<div class="bargain">
<!-- 在header上加 on 为请求支援 -->
<div :class="[bargainPartake != userInfo.uid ? 'header on' : 'header']">
<div class="people">{{ lookCount }}人查看 {{ shareCount }}人分享 {{ userCount }}人参与</div>
<!-- 帮助砍价帮砍成功-->
<div class="pictxt acea-row row-center-wrapper" v-if="bargainPartake != userInfo.uid">
<div class="pictrue">
<img :src="bargainUserInfo.avatar" />
</div>
<div class="text">
{{ bargainUserInfo.nickname }}
<span>邀请您帮忙砍价</span>
</div>
</div>
<count-down
:is-day="true"
:tip-text="'倒计时 '"
:day-text="' '"
:hour-text="' '"
:minute-text="' '"
:second-text="' '"
:datatime="datatime"
></count-down>
</div>
<div class="wrapper">
<div class="pictxt acea-row row-between-wrapper">
<div class="pictrue">
<img :src="bargain.image" />
</div>
<div class="text acea-row row-column-around">
<div class="line2" v-text="bargain.title"></div>
<div class="money font-color-red">
已砍至:
<span class="num" v-text="price"></span>
</div>
<div class="acea-row row-middle">
<div class="successNum" v-text="'原价' + bargain.price"></div>
<div class="successNum" v-text="'已有' + bargainSumCount + '人砍价成功'"></div>
</div>
</div>
</div>
<div class="cu-progress acea-row row-middle round margin-top">
<div
class="acea-row row-middle bg-red"
:style="{ width: loading ? pricePercent + '%' : '' }"
></div>
</div>
<div class="balance acea-row row-between-wrapper">
<div v-text="'已砍' + alreadyPrice + '元'"></div>
<div v-if="surplusPrice === 0">砍价成功</div>
<div v-else v-text="'还剩' + surplusPrice + '元'"></div>
</div>
<!-- 帮助砍价帮砍成功-->
<!--<div class='bargainSuccess'><span class='iconfont icon-xiaolian'></span>已成功帮助好友砍价</div>-->
<div class="bargainBnts">
<div
class="bargainBnt"
@click="goPoster"
v-if="bargainPartake === userInfo.uid && surplusPrice > 0"
>邀请好友帮砍价</div>
<div
class="bargainBnt"
@click="getBargainHelp"
v-else-if="bargainPartake != userInfo.uid"
>帮好友砍一刀</div>
<div class="bargainBnt" @click="getBargainStart" v-if="bargainPartake != userInfo.uid">开启砍价</div>
<div
class="bargainBnt"
@click="goPay"
v-if="surplusPrice === 0 && bargainPartake === userInfo.uid && userBargainStatus === 1"
>立即支付</div>
<div class="bargainBnt on" @click="goList">抢更多商品</div>
</div>
<div class="tip">
已有
<span class="font-color-red" v-text="helpCount"></span>
位好友成功帮您砍价
</div>
<div class="lock"></div>
</div>
<div class="bargainGang">
<div class="title font-color-red acea-row row-center-wrapper">
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/left.png'" />
</div>
<div class="titleCon">砍价帮</div>
<div class="pictrue on">
<img :src="$VUE_APP_RESOURCES_URL+'/images/left.png'" />
</div>
</div>
<div class="list">
<div
class="item acea-row row-between-wrapper"
v-for="(item, bargainHelpListIndex) in bargainHelpList"
:key="bargainHelpListIndex"
>
<div class="pictxt acea-row row-between-wrapper">
<div class="pictrue">
<img :src="item.avatar" />
</div>
<div class="text">
<div class="name line1" v-text="item.nickname"></div>
<div class="line1" v-text="item.add_time"></div>
</div>
</div>
<div class="money font-color-red">
<span class="iconfont icon-kanjia"></span>
砍掉{{ item.price }}
</div>
</div>
</div>
<div
class="load font-color-red"
v-if="!helpListStatus && !helpListLoading"
@click="getBargainHelpList"
>点击加载更多</div>
<div class="lock"></div>
</div>
<div class="goodsDetails">
<div class="title font-color-red acea-row row-center-wrapper">
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/left.png'" />
</div>
<div class="titleCon">商品详情</div>
<div class="pictrue on">
<img :src="$VUE_APP_RESOURCES_URL+'/images/left.png'" />
</div>
</div>
<div class="conter" v-html="bargain.description"></div>
<div class="lock"></div>
</div>
<div class="goodsDetails">
<div class="title font-color-red acea-row row-center-wrapper">
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/left.png'" />
</div>
<div class="titleCon">活动规则</div>
<div class="pictrue on">
<img :src="$VUE_APP_RESOURCES_URL+'/images/left.png'" />
</div>
</div>
<div class="conter" v-html="bargain.rule"></div>
</div>
<div class="bargainTip" :class="active === true ? 'on' : ''">
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/bargainBg.jpg'" />
<div class="iconfont icon-guanbi" @click="close"></div>
</div>
<div class="cutOff" v-if="bargainPartake === userInfo.uid">
您已砍掉
<span class="font-color-red" v-text="bargainHelpPrice"></span>听说分享次数越多砍价成功的机会越大哦
</div>
<div class="cutOff on" v-else>
<div class="help font-color-red" v-text="'成功帮砍' + bargainHelpPrice + '元'"></div>您也可以砍价低价拿哦快去挑选心仪的商品吧~
</div>
<div class="tipBnt" @click="goPoster" v-if="bargainPartake === userInfo.uid">邀请好友帮砍价</div>
<div class="tipBnt" @click="getBargainStart" v-else>我也要参与</div>
</div>
<div class="mask" @touchmove.prevent :hidden="active === false" @click="close"></div>
</div>
</template>
<script>
import CountDown from "@/components/CountDown";
import {
getBargainDetail,
getBargainShare,
getBargainStart,
getBargainHelp,
getBargainHelpPrice,
getBargainHelpList,
getBargainHelpCount,
getBargainStartUser
} from "@/api/activity";
import { postCartAdd } from "@/api/store";
import { mapGetters } from "vuex";
import {} from "@/libs/wechat";
import { isWeixin, parseQuery, handleQrCode } from "@/utils/index";
const NAME = "DargainDetails";
export default {
name: "DargainDetails",
components: {
CountDown
},
props: {},
data: function() {
return {
price: 0,
bargainId: 0, //砍价编号
bargainPartake: 0, //参与砍价
bargain: [], //砍价产品信息
partake: null,
bargainSumCount: 0, //砍价成功人数
activeMsg: "",
active: false,
loading: false,
datatime: 0,
lookCount: 0, //查看人数
shareCount: 0, //分享人数
userCount: 0, //参与人数
bargainHelpPrice: 0, //砍掉金额
bargainHelpList: [],
helpListStatus: false, //砍价列表是否获取完成 false 未完成 true 完成
helpListLoading: false, //当前接口是否请求完成 false 完成 true 未完成
page: 1, //页码
limit: 2, //数量
helpCount: 0, //砍价帮总人数
surplusPrice: 0, //剩余金额
alreadyPrice: 0, //已砍掉价格
pricePercent: 0, //砍价进度条
bargainUserInfo: [], //砍价 开启砍价用户信息
userBargainStatus: 2 //砍价状态
};
},
computed: mapGetters(["userInfo", "isLogin"]),
// watch: {
// $yroute: function(n) {
// var that = this;
// if (n.name === NAME) {
// that.mountedStart();
// }
// }
// },
mounted: function() {
var that = this;
that.mountedStart();
setTimeout(function() {
that.loading = true;
}, 500);
},
methods: {
mountedStart: function() {
var that = this;
let url = handleQrCode();
if (url) {
that.bargainId = url.bargainId;
that.partake = url.uid;
} else {
that.bargainId = that.$yroute.query.id;
that.partake = parseInt(that.$yroute.query.partake);
}
if (
this.partake === undefined ||
this.partake <= 0 ||
isNaN(this.partake)
) {
that.bargainPartake = that.userInfo.uid;
// that.$yrouter.push({
// path: "/pages/activity/DargainDetails/main",
// query: { id: that.bargainId, partake: that.bargainPartake }
// });
} else {
that.bargainPartake = parseInt(this.partake);
}
that.getBargainHelpCountStart();
that.getBargainDetail();
that.getBargainShare(0);
if (that.bargainPartake === that.userInfo.uid) that.getBargainStart();
else that.getBargainStartUser();
},
updateTitle() {
// document.title = this.bargain.title || this.$yroute.meta.title;
},
goPay: function() {
var data = {};
var that = this;
data.productId = that.bargain.productId;
data.cartNum = that.bargain.num;
data.uniqueId = "";
data.bargainId = that.bargainId;
data.new = 1;
postCartAdd(data)
.then(res => {
that.$yrouter.push({
path: "/pages/order/OrderSubmission/main",
query: { id: res.data.cartId }
});
})
.catch(err => {
this.$dialog.error(err.msg || err.response.data.msg);
});
},
goPoster: function() {
var that = this;
that.getBargainShare(that.bargainId);
this.$yrouter.push({
path: "/pages/activity/Poster/main",
query: { id: that.bargainId, type: 2 }
});
},
goList: function() {
this.$yrouter.push({
path: "/pages/activity/GoodsBargain/main"
});
},
//砍价分享
//bargainId 0 获取 查看人数 分享人数 参与人数
//bargainId 砍价产品编号 添加分享次数 获取 查看人数 分享人数 参与人数
getBargainShare: function(bargainId) {
var that = this;
getBargainShare({ bargainId: bargainId }).then(res => {
that.lookCount = res.data.lookCount;
that.shareCount = res.data.shareCount;
that.userCount = res.data.userCount;
});
},
// 获取产品详情
getBargainDetail: function() {
var that = this;
getBargainDetail(that.bargainId)
.then(res => {
that.$set(that, "bargain", res.data.bargain);
that.updateTitle();
that.datatime = that.bargain.stopTime;
that.getBargainHelpCount();
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
//开启砍价
getBargainStart: function() {
var that = this;
getBargainStart({ bargainId: that.bargainId })
.then(() => {
that.bargainPartake = that.userInfo.uid;
that.getBargainHelp();
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
//参与砍价
getBargainHelp: function() {
var that = this;
if (
that.surplusPrice === 0 &&
that.bargainPartake !== that.userInfo.uid
) {
return wx.showToast({
title: "好友已经砍价成功",
icon: "success",
duration: 2000
});
}
var data = {
bargainId: that.bargainId,
bargainUserUid: that.bargainPartake
};
getBargainHelp(data)
.then(res => {
that.activeMsg = res.data.status;
if (
res.data.status === "SUCCESSFUL" &&
that.bargainPartake !== that.userInfo.uid
) {
return that.$dialog.toast({ mes: "您已经砍过了" });
}
that.helpListStatus = false;
that.page = 1;
that.bargainHelpList = [];
that.getBargainHelpPrice();
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
//获取砍掉的金额
getBargainHelpPrice: function() {
var that = this;
getBargainHelpPrice({
bargainId: that.bargainId,
bargainUserUid: that.bargainPartake
})
.then(res => {
that.bargainHelpPrice = res.data.price;
that.getBargainHelpCount();
that.getBargainHelpList();
switch (that.activeMsg) {
case "SUCCESSFUL":
break;
case "SUCCESS":
that.active = true;
break;
}
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
//砍价帮
getBargainHelpList: function() {
var that = this;
if (that.helpListLoading === true) return;
if (that.helpListStatus === true) return;
that.helpListLoading = true;
getBargainHelpList({
bargainId: that.bargainId,
bargainUserUid: that.bargainPartake,
page: that.page,
limit: that.limit
})
.then(res => {
that.helpListStatus = res.data.length < that.limit;
that.helpListLoading = false;
that.page++;
that.bargainHelpList.push.apply(that.bargainHelpList, res.data);
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
getBargainHelpCountStart: function() {
var that = this;
getBargainHelpCount({
bargainId: that.bargainId,
bargainUserUid: that.bargainPartake
})
.then(() => {})
.catch(() => {
// that.$yrouter.push({
// path: "/pages/activity/DargainDetails/main",
// query: { id: that.bargainId, partake: that.userInfo.uid }
// });
});
},
getBargainHelpCount: function() {
var that = this;
getBargainHelpCount({
bargainId: that.bargainId,
bargainUserUid: that.bargainPartake
})
.then(res => {
that.userBargainStatus = res.data.status;
that.helpCount = res.data.count;
that.surplusPrice = res.data.price;
that.alreadyPrice = res.data.alreadyPrice;
that.pricePercent = res.data.pricePercent;
that.price = (that.bargain.price - that.alreadyPrice).toFixed(2);
})
.catch(() => {
that.bargainPartake = that.userInfo.uid;
// that.$yrouter.push({
// path: "/pages/activity/DargainDetails/main",
// query: { id: that.bargainId, partake: that.userInfo.uid }
// });
});
},
getBargainStartUser: function() {
var that = this;
getBargainStartUser({
bargainId: that.bargainId,
bargainUserUid: that.bargainPartake
})
.then(res => {
that.bargainUserInfo = res.data;
that.getBargainHelpList();
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
close: function() {
this.active = false;
}
},
onShareAppMessage() {
return {
path: `/pages/activity/DargainDetails/main/?id=${
this.$yroute.query.id
}&partake=${this.userInfo.uid}`
};
}
};
</script>
<style>
.bargainBnts {
display: flex;
align-items: center;
flex-direction: column;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+81
View File
@@ -0,0 +1,81 @@
<template>
<div class="bargain-list">
<!-- <div class="header">
<img :src="$VUE_APP_RESOURCES_URL+'/images/cut-bg.png'" alt="">
</div>-->
<div class="list" v-if="bargainLis.length > 0">
<div
class="item acea-row row-between-wrapper"
v-for="(item, bargainLisIndex) in bargainLis"
:key="bargainLisIndex"
>
<div class="pictrue">
<img :src="item.image" />
</div>
<div class="text acea-row row-column-around">
<div class="line1" v-text="item.title"></div>
<div class="num">
<span class="iconfont icon-pintuan"></span>
{{ item.people }}人正在参与
</div>
<div class="money font-color-red">
可砍至:
<span class="price">{{item.minPrice}}</span>
</div>
</div>
<div class="cutBnt bg-color-red" @click="goDetail(item.id)">
<span class="iconfont icon-kanjia"></span>参与砍价
</div>
</div>
<div class="load font-color-red" v-if="!status" @click="getBargainList">点击加载更多</div>
</div>
<div class="noCommodity" style="background-color: #fff;" v-if="bargainLis.length === 0">
<div class="noPictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/noGood.png'" class="image" />
</div>
</div>
</div>
</template>
<script>
import { getBargainList } from "@/api/activity";
export default {
name: "GoodsBargain",
components: {},
props: {},
data: function() {
return {
bargainLis: [], //砍价列表
status: false, //砍价列表是否获取完成 false 未完成 true 完成
loading: false, //当前接口是否请求完成 false 完成 true 未完成
page: 1, //页码
limit: 20 //数量
};
},
mounted: function() {
this.getBargainList();
},
methods: {
getBargainList: function() {
var that = this;
if (that.loading) return;
if (that.status) return;
that.loading = true;
getBargainList({ page: that.page, limit: that.limit }).then(res => {
that.status = res.data.length < that.limit;
that.bargainLis.push.apply(that.bargainLis, res.data);
that.page++;
that.loading = false;
});
},
goDetail: function(id) {
this.$yrouter.push({
path: "/pages/activity/DargainDetails/main",
query: { id, partake: 0 }
});
}
}
};
</script>
<style >
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+93
View File
@@ -0,0 +1,93 @@
<template>
<div class="group-list" ref="container">
<!-- <div class="header">
<img :src="$VUE_APP_RESOURCES_URL+'/images/group.png'" class="image" />
</div>-->
<div class="list" v-if="combinationList.length>0">
<div
class="item acea-row row-between-wrapper"
v-for="(item, combinationListIndex) in combinationList"
:key="combinationListIndex"
@click="link(item.id)"
>
<div class="pictrue">
<img :src="item.image" />
</div>
<div class="text">
<div class="line1" v-text="item.title"></div>
<div class="acea-row">
<div class="team acea-row row-middle cart-color">
<div class="iconfont icon-pintuan"></div>
<div class="num" v-text="item.people + '人团'"></div>
</div>
</div>
<div class="bottom acea-row row-between-wrapper">
<div class="money">
<span class="num" v-text="item.price"></span>
<span class="y-money" v-text="'¥' + item.productPrice"></span>
</div>
<div class="groupBnt bg-color-red">
去拼团
<span class="iconfont icon-jiantou"></span>
</div>
</div>
</div>
</div>
<Loading :loaded="status" :loading="loadingList"></Loading>
</div>
<div class="noCommodity" style="background-color: #fff;" v-if="combinationList.length === 0">
<div class="noPictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/noGood.png'" class="image" />
</div>
</div>
</div>
</template>
<script>
import { getCombinationList } from "@/api/activity";
import Loading from "@/components/Loading";
export default {
name: "GoodsGroup",
components: {
Loading
},
props: {},
data: function() {
return {
combinationList: [],
status: false, //砍价列表是否获取完成 false 未完成 true 完成
loading: false, //当前接口是否请求完成 false 完成 true 未完成
page: 1, //页码
limit: 20, //数量
loadingList: false
};
},
mounted: function() {
// document.querySelector('body').setAttribute('style', 'background-color:#73CBB6');
this.getCombinationList();
},
onReachBottom() {
!this.loadingList && this.getCombinationList();
},
methods: {
getCombinationList: function() {
var that = this;
if (that.loading) return;
if (that.status) return;
getCombinationList({ page: that.page, limit: that.limit }).then(res => {
that.status = res.data.length < that.limit;
that.combinationList.push.apply(that.combinationList, res.data);
that.page++;
that.loading = false;
});
},
link: function(id) {
this.$yrouter.push({
path: "/pages/activity/GroupDetails/main",
query: { id }
});
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+223
View File
@@ -0,0 +1,223 @@
<template>
<div class="flash-sale" ref="container">
<div class="header" v-if="headerImg">
<img :src="headerImg" />
</div>
<vant-tabs
:active="active"
@change="setTime"
:sticky="sticky"
animated
line-height="2"
:ellipsis="false"
>
<vant-tab
:ellipsis="false"
:title="[title[index]]"
v-for="(item, index) in timeList"
:key="index"
>
<div slot="title" class="timeItem">
<div class="time">{{ item.time }}</div>
<div class="state">{{ item.state }}</div>
</div>
<div class="countDown font-color-red acea-row row-center-wrapper">
<div v-if="item.status === 0" class="activity">活动已结束</div>
<count-down
:is-day="false"
:tip-text="'距结束仅剩 '"
:day-text="''"
:hour-text="' : '"
:minute-text="' : '"
:second-text="''"
:datatime="datatime"
v-if="item.status === 1"
></count-down>
<div v-if="item.status === 2" class="activity">活动即将开始</div>
</div>
<div class="list">
<div
class="item acea-row row-between-wrapper"
v-for="(itemSeckill, indexSeckill) in seckillList"
:key="indexSeckill"
>
<div class="pictrue">
<img :src="itemSeckill.image" />
</div>
<div class="text acea-row row-column-around">
<div class="line1" v-text="itemSeckill.title"></div>
<div class="money">
限时价
<span class="num font-color-red" v-text="'¥' + itemSeckill.price"></span>
</div>
<div class="progress cart-color">
<div class="bg-red" :style="{ width: loading ? itemSeckill.percent + '%' : '' }"></div>
<div class="piece font-color-red" v-text="'仅剩' + itemSeckill.stock + '件'"></div>
</div>
</div>
<div
class="grab bg-color-red"
v-if="item.status === 1 && itemSeckill.stock > 0"
@click="goDetail(itemSeckill.id)"
>马上抢</div>
<div class="grab" v-if="item.status === 1 && itemSeckill.stock <= 0">已售磬</div>
<div class="grab bg-color-red" v-if="item.status === 2">即将开始</div>
<div class="grab bg-color-red" v-if="item.status === 0">已结束</div>
</div>
</div>
<div
class="noCommodity"
style="background-color: #fff;"
v-if="seckillList.length === 0 && page > 1"
>
<div class="noPictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/noGood.png'" class="image" />
</div>
</div>
</vant-tab>
</vant-tabs>
</div>
</template>
<script>
import { getSeckillConfig, getSeckillList } from "@/api/activity";
import CountDown from "@/components/CountDown";
// import { Tab, Tabs } from "vant-weapp";
import Loading from "@/components/Loading";
export default {
name: "GoodsSeckill",
components: {
CountDown
},
props: {},
data: function() {
return {
headerImg: "",
timeList: [],
sticky: false,
loading: false,
datatime: 0,
active: 0,
seckillList: [],
status: false, //砍价列表是否获取完成 false 未完成 true 完成
loadingList: false, //当前接口是否请求完成 false 完成 true 未完成
page: 1, //页码
limit: 5, //数量
title: []
};
},
mounted: function() {
this.mountedStart();
},
onReachBottom() {
!this.loadingList && this.getSeckillList();
},
methods: {
mountedStart: function() {
var that = this;
wx.showLoading();
getSeckillConfig().then(res => {
that.$set(that, "headerImg", res.data.lovely);
that.$set(that, "timeList", res.data.seckillTime);
that.$set(that, "active", res.data.seckillTimeIndex);
let title = [];
title = res.data.seckillTime.map((item, index) => {
return {
name: "div",
attrs: {
class: "timeItem"
},
children: [
{
name: "div",
attrs: {
class: "time"
},
children: [
{
type: "text",
text: item.time
}
]
},
{
name: "div",
attrs: {
class: "state"
},
children: [
{
type: "text",
text: item.state
}
]
}
]
};
});
that.$set(that, "title", title);
that.datatime = that.timeList[that.active].stop;
that.getSeckillList();
that.$nextTick(function() {
that.sticky = true;
wx.hideLoading();
});
});
},
setTime: function(event) {
var that = this;
that.active = event.mp.detail.index;
that.datatime = that.timeList[that.active].stop;
that.getSeckillList();
},
getSeckillList: function() {
var that = this;
if (that.loadingList) return;
if (that.status) return;
var time = that.timeList[that.active].id;
getSeckillList(time, { page: that.page, limit: that.limit }).then(res => {
that.status = res.data.length < that.limit;
that.seckillList.push.apply(that.seckillList, res.data);
that.page++;
wx.hideLoading();
});
},
goDetail: function(id) {
var that = this;
var time = that.timeList[that.active].stop;
this.$yrouter.push({
path: "/pages/activity/SeckillDetails/main",
query: { id, time }
});
}
}
};
</script>
<style scoped>
.timeItem {
font-size: 0.22rem;
color: #282828;
width: 100%;
text-align: center;
padding: 0.11rem 0;
height: 0.96rem;
background-color: #efc58f;
}
.timeItem .time {
font-size: 0.32rem;
font-weight: bold;
height: 0.37rem;
line-height: 0.37rem;
}
.timeItem .state {
height: 0.37rem;
line-height: 0.37rem;
}
.activity {
color: #333;
}
.flash-sale .list .item .grab {
background-color: #999;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+330
View File
@@ -0,0 +1,330 @@
<template>
<div :class="[posterImageStatus ? 'noscroll product-con' : 'product-con']" v-show="domStatus">
<product-con-swiper :imgUrls="imgUrls"></product-con-swiper>
<div class="wrapper">
<div class="share acea-row row-between row-bottom">
<div class="money font-color-red">
<span class="num" v-text="storeInfo.price"></span>
<span class="y-money" v-text="'¥' + storeInfo.productPrice"></span>
</div>
</div>
<div class="introduce" v-text="storeInfo.title"></div>
<div class="label acea-row row-between-wrapper">
<div v-text="'类型:' + storeInfo.people + '人团'"></div>
<div v-text="'库存:' + storeInfo.stock + storeInfo.unitName"></div>
<div v-text="'已拼:' + storeInfo.sales + storeInfo.unitName"></div>
</div>
</div>
<div class="notice acea-row row-middle">
<div class="num font-color-red">
<span class="iconfont icon-laba"></span>
已拼{{ storeInfo.sales
}}{{ storeInfo.unitName }}
<span class="line">|</span>
</div>
<div class="swiper-no-swiping swiper">
<swiper class="swiper-wrapper" :options="swiperTip" :autoplay="true" :interval="3000">
<block v-for="(item, itemNewIndex) in itemNew" :key="itemNewIndex">
<swiper-item>
<div class="line1">{{ item }}</div>
</swiper-item>
</block>
</swiper>
</div>
</div>
<div class="assemble">
<div v-for="(item, groupListindex) in groupList" :key="groupListindex">
<div class="item acea-row row-between-wrapper" v-if="groupListindex < groupListCount">
<div class="pictxt acea-row row-between-wrapper">
<div class="pictrue">
<img :src="item.avatar" class="image" />
</div>
<div class="text line1" v-text="item.nickname"></div>
</div>
<div class="right acea-row row-middle">
<div>
<div class="lack">
还差
<span class="font-color-red" v-text="item.count"></span>人成团
</div>
<count-down
:is-day="false"
:tip-text="'剩余 '"
:day-text="''"
:hour-text="':'"
:minute-text="':'"
:second-text="''"
:datatime="item.stopTime"
></count-down>
</div>
<div class="spellBnt" @click="groupRule(item.id)">
去拼单
<span class="iconfont icon-jiantou"></span>
</div>
</div>
</div>
</div>
<div class="more" v-if="groupList.length > groupListCount" @click="setGroupListCount">
查看更多
<span class="iconfont icon-xiangxia"></span>
</div>
</div>
<div class="playWay">
<div class="title acea-row row-between-wrapper">
<div>拼团玩法</div>
</div>
<div class="way acea-row row-middle">
<div class="item">
<span class="num"></span>开团/参团
</div>
<div class="iconfont icon-arrow"></div>
<div class="item">
<span class="num"></span>邀请好友
</div>
<div class="iconfont icon-arrow"></div>
<div class="item">
<div>
<span class="num"></span>满员发货
</div>
</div>
</div>
</div>
<div class="userEvaluation">
<div class="title acea-row row-between-wrapper">
<div v-text="'用户评价(' + replyCount + ')'"></div>
<div class="praise" @click="goReply">
<span class="font-color-red" v-text="replyChance + '%'"></span>好评率
<span class="iconfont icon-jiantou"></span>
</div>
</div>
<UserEvaluation :reply="reply"></UserEvaluation>
</div>
<div class="product-intro">
<div class="title">产品介绍</div>
<div class="conter" v-html="storeInfo.description"></div>
</div>
<div style="height:100rpx;"></div>
<div class="footer-group acea-row row-between-wrapper">
<div class="customerSer acea-row row-center-wrapper row-column">
<div class="iconfont icon-kefu"></div>
<div>客服</div>
</div>
<div class="bnt bg-color-violet" @click="openAlone">单独购买</div>
<div class="bnt bg-color-red" @click="openTeam">立即开团</div>
</div>
<ProductWindow v-on:changeFun="changeFun" :attr="attr" :cartNum="cartNum"></ProductWindow>
<StorePoster
v-on:setPosterImageStatus="setPosterImageStatus"
:posterImageStatus="posterImageStatus"
:posterData="posterData"
></StorePoster>
</div>
</template>
<style scoped>
.noscroll {
height: 100%;
overflow: hidden;
}
.product-con .footer-group .bnt {
width: 43%;
}
.product-con .footer-group .bnt.bg-color-violet {
background-color: #fa8013;
}
</style>
<script>
// import { swiper, swiperSlide } from "vue-awesome-swiper";
import ProductConSwiper from "@/components/ProductConSwiper";
import CountDown from "@/components/CountDown";
import UserEvaluation from "@/components/UserEvaluation";
import ProductWindow from "@/components/ProductWindow";
import StorePoster from "@/components/StorePoster";
import { getCombinationDetail } from "@/api/activity";
import { postCartAdd } from "@/api/store";
import { imageBase64 } from "@/api/public";
const NAME = "GroupDetails";
export default {
name: "GroupDetails",
components: {
ProductConSwiper,
CountDown,
UserEvaluation,
// swiper,
// swiperSlide,
ProductWindow,
StorePoster
},
props: {},
data: function() {
return {
domStatus: false,
posterData: {
image: "",
title: "",
price: "",
code: ""
},
posterImageStatus: false,
reply: [],
replyCount: 0,
replyChance: 0,
imgUrls: [],
storeInfo: {},
itemNew: {},
groupListCount: 2,
groupList: {},
swiperTip: {
direction: "vertical",
autoplay: {
disableOnInteraction: false,
delay: 2000
},
loop: true,
speed: 1000,
observer: true,
observeParents: true
},
attr: {
cartAttr: false,
productSelect: {
image: "",
store_name: "",
price: "",
stock: "",
unique: "",
cart_num: 1
}
},
cartNum:1
};
},
watch: {
$yroute: function(n) {
var that = this;
if (n.name === NAME) {
that.mountedStart();
}
}
},
mounted: function() {
this.mountedStart();
},
methods: {
openAlone: function() {
this.$yrouter.replace({ path: "/detail/" + this.storeInfo.productId });
},
mountedStart: function() {
var that = this;
let id = that.$yroute.query.id;
getCombinationDetail(id).then(res => {
that.$set(that, "storeInfo", res.data.storeInfo);
that.$set(that, "imgUrls", res.data.storeInfo.sliderImageArr);
that.$set(that, "itemNew", res.data.pinkOkList);
that.$set(that, "groupList", res.data.pink);
that.$set(that, "reply", [res.data.reply]);
that.$set(that, "replyCount", res.data.replyCount);
that.$set(that, "replyChance", res.data.replyChance);
that.setProductSelect();
that.posterData.image = that.storeInfo.image;
if (that.storeInfo.title.length > 30) {
that.posterData.title = that.storeInfo.title.substring(0, 30) + "...";
} else {
that.posterData.title = that.storeInfo.title;
}
that.posterData.price = that.storeInfo.price;
that.posterData.code = that.storeInfo.code_base;
that.domStatus = true;
//that.getImageBase64();
});
},
getImageBase64: function() {
let that = this;
imageBase64(this.posterData.image, that.posterData.code).then(res => {
that.posterData.image = res.data.image;
that.posterData.code = res.data.code;
});
},
setPosterImageStatus: function() {
// var sTop = document.body || document.documentElement;
// sTop.scrollTop = 0;
this.posterImageStatus = !this.posterImageStatus;
},
groupRule: function(id) {
var that = this;
that.$yrouter.push({
path: "/pages/activity/GroupRule/main",
query: { id }
});
},
goReply: function() {
var that = this;
that.$yrouter.push({
path: "/pages/shop/EvaluateList/main",
query: { id: that.storeInfo.product_id }
});
},
setGroupListCount: function() {
this.groupListCount = this.groupListCount + 2;
},
//将父级向子集多次传送的函数合二为一;
changeFun: function(opt) {
if (typeof opt !== "object") opt = {};
let action = opt.action || "";
let value = opt.value === undefined ? "" : opt.value;
this[action] && this[action](value);
},
changeattr: function(res) {
var that = this;
that.attr.cartAttr = res;
},
ChangeCartNum: function(res) {
var that = this;
that.attr.productSelect.cart_num = 1;
that.cartNum = 1;
that.$dialog.message("每人每次限购1" + that.storeInfo.unitName);
},
setProductSelect: function() {
var that = this;
var attr = that.attr;
attr.productSelect.image = that.storeInfo.image;
attr.productSelect.store_name = that.storeInfo.title;
attr.productSelect.price = that.storeInfo.price;
attr.productSelect.stock = that.storeInfo.stock;
attr.cartAttr = false;
that.$set(that, "attr", attr);
},
openTeam: function() {
var that = this;
if (that.attr.cartAttr == false) {
that.attr.cartAttr = !this.attr.cartAttr;
} else {
var data = {};
data.productId = that.storeInfo.productId;
data.cartNum = that.attr.productSelect.cart_num;
data.uniqueId = that.attr.productSelect.unique;
data.combinationId = that.storeInfo.id;
data.new = 1;
postCartAdd(data)
.then(res => {
that.$yrouter.push({
path: "/pages/order/OrderSubmission/main",
query: { id: res.data.cartId }
});
})
.catch(err => {
this.$dialog.error(err.msg||err.response.data.msg);
});
}
}
}
};
</script>
<style scoped>
.product-con .wrapper {
padding-bottom: 0.26rem;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+224
View File
@@ -0,0 +1,224 @@
<template>
<div class="group-con">
<div class="header acea-row row-between-wrapper">
<div class="pictrue">
<img :src="storeCombination.image" />
</div>
<div class="text">
<div class="line1" v-text="storeCombination.title"></div>
<div class="money">
<span class="num" v-text="storeCombination.price"></span>
<span class="team cart-color" v-text="storeCombination.people + '人拼'"></span>
</div>
</div>
<div v-if="pinkBool === -1" class="iconfont icon-pintuanshibai"></div>
<div v-else-if="pinkBool === 1" class="iconfont icon-pintuanchenggong font-color-red"></div>
</div>
<div class="wrapper">
<div class="title acea-row row-center-wrapper">
<div class="line"></div>
<div class="name acea-row row-center-wrapper">
剩余
<count-down
:is-day="false"
:tip-text="''"
:day-text="''"
:hour-text="' : '"
:minute-text="' : '"
:second-text="''"
:datatime="pinkT.stopTime"
></count-down>结束
</div>
<div class="line"></div>
</div>
<div class="tips font-color-red" v-if="pinkBool === 1">恭喜您拼团成功</div>
<div class="tips" v-else-if="pinkBool === -1">还差{{ count }}拼团失败</div>
<div class="tips font-color-red" v-else-if="pinkBool === 0">拼团中还差{{ count }}人拼团成功</div>
<div
class="list acea-row row-middle"
:class="[
pinkBool === 1 || pinkBool === -1 ? 'result' : '',
iShidden ? 'on' : ''
]"
>
<div class="pictrue">
<img :src="pinkT.avatar" />
</div>
<div class="acea-row row-middle" v-if="pinkAll.length > 0">
<div class="pictrue" v-for="(item, pinkAllIndex) in pinkAll" :key="pinkAllIndex">
<img :src="item.avatar" />
</div>
</div>
<div class="pictrue" v-for="countIndex in count" :key="countIndex">
<img class="img-none" :src="$VUE_APP_RESOURCES_URL+'/images/vacancy.png'" />
</div>
</div>
<div
v-if="(pinkBool === 1 || pinkBool === -1) && count > 9"
class="lookAll acea-row row-center-wrapper"
@click="lookAll"
>
{{ iShidden ? "收起" : "查看全部" }}
<span
class="iconfont"
:class="iShidden ? 'icon-xiangshang' : 'icon-xiangxia'"
></span>
</div>
<div
class="teamBnt bg-color-red"
v-if="userBool === 1 && isOk == 0 && pinkBool === 0"
@click="goPoster"
>邀请好友参团</div>
<div
class="teamBnt bg-color-red"
v-else-if="userBool === 0 && pinkBool === 0 && count > 0"
@click="pay"
>我要参团</div>
<div
class="teamBnt bg-color-red"
v-if="pinkBool === 1 || pinkBool === -1"
@click="goDetail(storeCombination.id)"
>再次开团</div>
<div class="cancel" @click="getCombinationRemove" v-if="pinkBool === 0 && userBool === 1">
<span class="iconfont icon-guanbi3"></span>取消开团
</div>
<div class="lookOrder" v-if="pinkBool === 1" @click="goOrder">
查看订单信息
<span class="iconfont icon-xiangyou"></span>
</div>
</div>
</div>
</template>
<script>
import CountDown from "@/components/CountDown";
import { getCombinationPink, getCombinationRemove } from "@/api/activity";
import { postCartAdd } from "@/api/store";
import { isWeixin, parseQuery, handleQrCode } from "@/utils/index";
const NAME = "GroupRule";
export default {
name: NAME,
components: {
CountDown
},
props: {},
data: function() {
return {
currentPinkOrder: "", //当前拼团订单
isOk: 0, //判断拼团是否完成
pinkBool: 0, //判断拼团是否成功|0=失败,1=成功
userBool: 0, //判断当前用户是否在团内|0=未在,1=在
pinkAll: [], //团员
pinkT: [], //团长信息
storeCombination: [], //拼团产品
pinkId: 0,
count: 0, //拼团剩余人数
iShidden: false
};
},
watch: {
$yroute(n) {
var that = this;
if (n.name === NAME) {
that.pinkId = that.$yroute.query.id;
that.getCombinationPink();
}
}
},
mounted: function() {
var that = this;
let url = handleQrCode();
if (url) {
that.pinkId = url.pinkId;
} else {
that.pinkId = that.$yroute.query.id;
}
that.getCombinationPink();
},
methods: {
pay: function() {
var that = this;
var data = {};
data.productId = that.storeCombination.productId;
data.cartNum = that.pinkT.totalNum;
data.uniqueId = "";
data.combinationId = that.storeCombination.id;
data.new = 1;
postCartAdd(data)
.then(res => {
that.$yrouter.push({
path: "/pages/order/OrderSubmission/main",
query: { id: res.data.cartId, pinkid: that.pinkId }
});
})
.catch(err => {
this.$dialog.error(err.msg||err.response.data.msg);
});
},
goPoster: function() {
var that = this;
this.$yrouter.push({
path: "/pages/activity/Poster/main",
query: { id: that.pinkId, type: 1 }
});
},
goOrder: function() {
var that = this;
this.$yrouter.push({
path: "/pages/order/OrderDetails/main",
query: { id: that.currentPinkOrder }
});
},
//拼团列表
goList: function() {
this.$yrouter.push({
path: "/pages/activity/GoodsGroup/main"
});
},
//拼团详情
goDetail: function(id) {
this.$yrouter.push({
path: "/pages/activity/GroupDetails/main",
query: { id }
});
},
//拼团信息
getCombinationPink: function() {
var that = this;
getCombinationPink(that.pinkId).then(res => {
that.$set(that, "storeCombination", res.data.storeCombination);
that.$set(that, "pinkT", res.data.pinkT);
that.$set(that, "pinkAll", res.data.pinkAll);
that.$set(that, "count", res.data.count);
that.$set(that, "userBool", res.data.userBool);
that.$set(that, "pinkBool", res.data.pinkBool);
that.$set(that, "isOk", res.data.isOk);
that.$set(that, "currentPinkOrder", res.data.currentPinkOrder);
});
},
//拼团取消
getCombinationRemove: function() {
var that = this;
getCombinationRemove({ id: that.pinkId, cid: that.storeCombination.id })
.then(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
lookAll: function() {
this.iShidden = !this.iShidden;
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+76
View File
@@ -0,0 +1,76 @@
<template>
<div class="poster-poster" v-if="status === false">
<div class="tip">
<span class="iconfont icon-shuoming"></span>提示长按图片保存至手机相册
</div>
<div class="poster">
<img :src="image" mode="widthFix" show-menu-by-longpress />
</div>
</div>
</template>
<style scoped>
.poster-poster {
height: unset !important;
}
</style>
<script>
import { getBargainPoster, getCombinationPoster } from "@/api/activity";
export default {
name: "Poster",
components: {},
props: {},
data: function() {
return {
status: true,
id: 0,
image: ""
};
},
mounted: function() {
var that = this;
var id = that.$yroute.query.id;
var type = that.$yroute.query.type;
that.id = id;
if (type == 2) {
that.getBargainPoster();
} else {
that.getCombinationPoster();
}
},
methods: {
getBargainPoster: function() {
var that = this;
getBargainPoster({ bargainId: that.id, from: "wechat" })
.then(res => {
that.image = res.data.url;
that.status = false;
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
// 拼团海报
getCombinationPoster: function() {
var that = this;
getCombinationPoster({ id: that.id, from: "wechat" })
.then(res => {
that.image = res.data.url;
that.status = false;
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+227
View File
@@ -0,0 +1,227 @@
<template>
<div :class="[posterImageStatus ? 'noscroll product-con' : 'product-con']" v-show="domStatus">
<product-con-swiper :imgUrls="imgUrls"></product-con-swiper>
<div class="nav acea-row row-between-wrapper">
<div class="money">
<span class="num" v-text="storeInfo.price"></span>
<span class="y-money" v-text="'¥' + storeInfo.price"></span>
</div>
<div class="acea-row row-middle">
<div class="times">
<div>距秒杀结束仅剩</div>
<count-down
:is-day="false"
:tip-text="''"
:day-text="''"
:hour-text="' : '"
:minute-text="' : '"
:second-text="''"
:datatime="datatime"
></count-down>
</div>
<div class="iconfont icon-jiantou"></div>
</div>
</div>
<div class="wrapperRush">
<div class="introduce acea-row row-between">
<div class="infor" v-text="storeInfo.title"></div>
<div class="iconfont icon-fenxiang" @click="setPosterImageStatus"></div>
</div>
<div class="label acea-row row-middle">
<div class="stock" v-text="'库存:' + storeInfo.stock + '件'"></div>
<div v-text="'销量:' + storeInfo.sales + '件'"></div>
</div>
</div>
<div class="product-intro">
<div class="title">产品介绍</div>
<div class="conter" v-html="storeInfo.description"></div>
</div>
<div style="height:100rpx;"></div>
<div class="footerRush acea-row row-between-wrapper">
<div
class="customerSer acea-row row-center-wrapper row-column"
@click="$yrouter.push({ path: '/pages/user/CustomerList/index' })"
>
<div class="iconfont icon-kefu"></div>
<div>客服</div>
</div>
<div class="bnt bg-color-red" @click="tapBuy">立即购买</div>
</div>
<ProductWindow v-on:changeFun="changeFun" :attr="attr" :cartNum="cartNum"></ProductWindow>
<StorePoster
v-on:setPosterImageStatus="setPosterImageStatus"
:posterImageStatus="posterImageStatus"
:posterData="posterData"
></StorePoster>
</div>
</template>
<style scoped>
.noscroll {
height: 100%;
overflow: hidden;
}
</style>
<script>
import ProductConSwiper from "@/components/ProductConSwiper";
import CountDown from "@/components/CountDown";
import ProductWindow from "@/components/ProductWindow";
import StorePoster from "@/components/StorePoster";
import { getSeckillDetail } from "@/api/activity";
import { postCartAdd } from "@/api/store";
import { imageBase64 } from "@/api/public";
const NAME = "SeckillDetails";
export default {
name: "SeckillDetails",
components: {
ProductConSwiper,
CountDown,
ProductWindow,
StorePoster
},
props: {},
data: function() {
return {
domStatus: false,
posterData: {
image: "",
title: "",
price: "",
code: ""
},
posterImageStatus: false,
action: "",
imgUrls: [],
storeInfo: [],
replyCount: 0,
reply: [],
cartNum: 1,
attr: {
cartAttr: false,
productSelect: {
image: "",
store_name: "",
price: "",
stock: "",
unique: "",
cart_num: 1
}
},
datatime: 0
};
},
watch: {
$yroute: function(n) {
var that = this;
if (n.name === NAME) {
that.mountedStart();
}
}
},
mounted: function() {
this.mountedStart();
},
methods: {
mountedStart: function() {
var that = this;
let id = that.$yroute.query.id;
that.datatime = parseInt(that.$yroute.query.time);
getSeckillDetail(id).then(res => {
that.$set(that, "storeInfo", res.data.storeInfo);
that.$set(that, "imgUrls", res.data.storeInfo.sliderImageArr);
that.$set(that, "replyCount", res.data.replyCount);
that.$set(that, "reply", res.data.reply);
that.posterData.image = that.storeInfo.image_base;
that.updateTitle();
if (that.storeInfo.title.length > 30) {
that.posterData.title = that.storeInfo.title.substring(0, 30) + "...";
} else {
that.posterData.title = that.storeInfo.title;
}
that.posterData.price = that.storeInfo.price;
that.posterData.code = that.storeInfo.code_base;
that.setProductSelect();
that.domStatus = true;
});
},
updateTitle() {
// document.title = this.storeInfo.title || this.$yroute.meta.title;
},
setPosterImageStatus: function() {
// var sTop = document.body || document.documentElement;
// sTop.scrollTop = 0;
this.posterImageStatus = !this.posterImageStatus;
},
//将父级向子集多次传送的函数合二为一;
changeFun: function(opt) {
if (typeof opt !== "object") opt = {};
let action = opt.action || "";
let value = opt.value === undefined ? "" : opt.value;
this[action] && this[action](value);
},
changeattr: function(res) {
var that = this;
that.attr.cartAttr = res;
},
ChangeCartNum: function(res) {
var that = this;
if (res) {
if (that.attr.productSelect.cart_num < that.storeInfo.stock) {
that.attr.productSelect.cart_num++;
this.cartNum++;
}
} else {
if (that.attr.productSelect.cart_num > 1) {
that.attr.productSelect.cart_num--;
this.cartNum--;
}
}
},
setProductSelect: function() {
var that = this;
var attr = that.attr;
attr.productSelect.image = that.storeInfo.image;
attr.productSelect.store_name = that.storeInfo.title;
attr.productSelect.price = that.storeInfo.price;
attr.productSelect.stock = that.storeInfo.stock;
attr.cartAttr = false;
that.$set(that, "attr", attr);
},
selecAttrTap: function() {
this.cartAttr = true;
},
tapBuy: function() {
var that = this;
if (that.attr.cartAttr == false) {
that.attr.cartAttr = !this.attr.attrcartAttr;
} else {
console.log(that.storeInfo)
var data = {};
data.productId = that.storeInfo.productId;
data.cartNum = that.attr.productSelect.cart_num;
data.uniqueId = that.attr.productSelect.unique;
data.secKillId = that.storeInfo.id;
data.new = 1;
postCartAdd(data)
.then(res => {
console.log(res);
that.$yrouter.push({
path: "/pages/order/OrderSubmission/main",
query: { id: res.data.cartId }
});
})
.catch(err => {
console.log(err);
this.$dialog.error(err.msg || err.response.data.msg);
});
}
}
}
};
</script>
<style scoped>
.product-con .nav {
padding: 0 0.2rem;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+188
View File
@@ -0,0 +1,188 @@
<template>
<div class="container">
<div v-if="!isAuthorization">
<div class="getUserInfo">
<p>您还未允许微信登录授权请点击下方按钮允许微信授权登录</p>
<vant-button type="primary" open-type="getUserInfo" @getuserinfo="getUserInfo">允许微信登录授权</vant-button>
<div class="sp-cell"></div>
<vant-button type="default" @click="back">取消微信登录授权</vant-button>
</div>
</div>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from "vuex";
// 组件
// import request from "@//api/request";
import { wxappAuth, getUser } from "@/api/user";
import dayjs from "dayjs";
import cookie from "@/utils/store/cookie";
import { login } from "@/utils";
export default {
data() {
return {};
},
computed: {
...mapState(["isAuthorization"])
},
onShow() {
this.UPDATE_AUTHORIZATIONPAGE(false);
},
onHide() {
this.changeAuthorization(false);
},
onUnload() {
this.changeAuthorization(false);
},
methods: {
...mapActions(["changeAuthorization", "changeUserInfo"]),
...mapMutations(["UPDATE_AUTHORIZATIONPAGE", "CHANGE_TABTAR"]),
back() {
// if (this.$yroute.query.redirect) {
// this.$yrouter.replace({
// path: this.$yroute.query.redirect
// });
// } else {
// this.$yrouter.replace({
// path: "/pages/launch/main",
// query: { type: 0 }
// });
// }
this.CHANGE_TABTAR(0);
this.$yrouter.replace({
path: "/pages/launch/main",
query: { type: 0 }
});
},
getUserInfo(data) {
wx.showLoading({
title: "登录中"
});
login();
}
},
onUnload() {},
mounted() {}
};
</script>
<style lang="less">
.sp-cell {
height: 20rpx;
}
.getUserInfo {
display: flex;
align-items: center;
flex-direction: column;
padding: 30px;
p {
margin-bottom: 20px;
}
}
.container {
flex: 1;
display: flex;
flex-direction: column;
justify-content: flex-start;
position: relative;
}
.tab-bar {
font-size: 0;
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.9);
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 99;
border-top: 1px solid rgba(248, 248, 248, 1);
.tab-bar-item {
flex: 1;
height: 49px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
&.active {
text {
color: #ee7559;
}
.tab-bar-pic {
display: none;
background: #f9f9f9;
&.active {
display: block;
}
}
}
.tab-bar-pic {
display: block;
background: #f9f9f9;
&.active {
display: none;
}
}
}
.tab-bar-pic {
width: 25px;
height: 25px;
background: #f9f9f9;
image {
width: 25px;
height: 25px;
}
}
.tab-bar-pic-active {
}
text {
font-size: 10px;
color: rgb(160, 160, 160);
line-height: 10px;
margin-top: 5px;
}
}
.tab-bar-bg {
padding-top: 46px;
width: 100%;
}
.view-item {
display: none;
width: 100%;
}
.view-item-active {
display: block;
}
.getUserInfo {
display: flex;
align-items: center;
flex-direction: column;
padding: 30px;
p {
margin-bottom: 20px;
}
}
._van-dialog {
z-index: 99999999999;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+297
View File
@@ -0,0 +1,297 @@
<template>
<div class="index">
<div class="header acea-row row-center-wrapper">
<div @click="$yrouter.push('/pages/shop/GoodSearch/index')" class="search acea-row row-middle">
<span class="iconfont icon-xiazai5"></span>搜索商品
</div>
</div>
<div class="slider-banner banner">
<swiper indicatorDots="true" v-if="banner.length > 0">
<block v-for="(item, bannerIndex) in banner" :key="bannerIndex">
<swiper-item>
<div @click="item.url?$yrouter.push('/'+item.url) : ''" class="swiper-item">
<img :src="item.pic" />
</div>
</swiper-item>
</block>
</swiper>
</div>
<div class="news acea-row row-between-wrapper">
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/news.png'" />
</div>
<div class="swiper-no-swiping new-banner">
<swiper
class="swiper-wrapper"
v-if="roll.length > 0"
:indicator-dots="false"
autoplay
circular
vertical
>
<block v-for="(item, rollIndex) in roll" :key="rollIndex">
<swiper-item class="swiper-slide">
<div
@click="item.wxapp_url?$yrouter.push(item.wxapp_url) : ''"
class="swiper-item acea-row row-between-wrapper"
>
<div class="text acea-row row-between-wrapper">
<div class="label" v-if="item.show === '是'">最新</div>
<div class="newsTitle line1">{{ item.info }}</div>
</div>
<div class="iconfont icon-xiangyou"></div>
</div>
</swiper-item>
</block>
</swiper>
</div>
</div>
<div class="nav acea-row">
<div
@click="$yrouter.push(item.wxapp_url)"
class="item"
v-for="(item, menusIndex) in menus"
:key="menusIndex"
>
<div class="pictrue">
<img :src="item.pic" />
</div>
<div>{{ item.name }}</div>
</div>
</div>
<div class="wrapper hot" v-if="bastList.length > 0">
<img class="bg" src="../../assets/images/index-bg.png" mode="widthFix" />
<div class="title acea-row row-between-wrapper">
<div class="text">
<div class="name line1">热门榜单</div>
</div>
<div
@click="$yrouter.push({ path: '/pages/shop/HotNewGoods/index',query:{type:2} })"
class="more"
>
更多
<span class="iconfont icon-jiantou"></span>
</div>
</div>
<div class="newProducts">
<scroll-view scroll-y="false" scroll-x="true">
<div class="newProductsScroll">
<div
@click="$yrouter.push({ path: '/pages/shop/GoodsCon/index',query:{id:item.id} })"
class="newProductsItem"
v-for="(item, likeInfoIndex) in likeInfo"
:key="likeInfoIndex"
>
<div class="img-box">
<img :src="item.image" />
</div>
<div class="pro-info line1">{{ item.storeName }}</div>
<div class="money font-color-red">{{ item.price }}</div>
</div>
</div>
</scroll-view>
</div>
</div>
<div class="wrapper" v-if="bastList.length > 0">
<div class="title acea-row row-between-wrapper">
<div class="text">
<div class="name line1">精品推荐</div>
</div>
<div
@click="$yrouter.push({ path: '/pages/shop/HotNewGoods/index',query:{type:1} })"
class="more"
>
更多
<span class="iconfont icon-jiantou"></span>
</div>
</div>
<Good-list :good-list="bastList" :is-sort="false"></Good-list>
</div>
<div class="wrapper" v-if="firstList.length > 0">
<div class="title acea-row row-between-wrapper">
<div class="text">
<div class="name line1">
首发新品
<span class="new font-color-red">NEW~</span>
</div>
</div>
<div
@click="$yrouter.push({ path: '/pages/shop/HotNewGoods/index',query:{type:3} })"
class="more"
>
更多
<span class="iconfont icon-jiantou"></span>
</div>
</div>
<div class="newProducts">
<scroll-view scroll-y="false" scroll-x="true">
<div class="newProductsScroll">
<div
@click="$yrouter.push({ path: '/pages/shop/GoodsCon/index',query:{id:item.id} })"
class="newProductsItem"
v-for="(item, firstListIndex) in firstList"
:key="firstListIndex"
>
<div class="img-box">
<img :src="item.image" />
</div>
<div class="pro-info line1">{{ item.storeName }}</div>
<div class="money font-color-red">{{ item.price }}</div>
</div>
</div>
</scroll-view>
</div>
</div>
<div class="wrapper" v-if="benefit.length > 0">
<div class="title acea-row row-between-wrapper">
<div class="text">
<div class="name line1">促销单品</div>
</div>
<div @click="$yrouter.push('/pages/shop/GoodsPromotion/index')" class="more">
更多
<span class="iconfont icon-jiantou"></span>
</div>
</div>
</div>
<Promotion-good :benefit="benefit"></Promotion-good>
<Coupon-window
:coupon-list="couponList"
v-if="showCoupon"
@checked="couponClose"
@close="couponClose"
></Coupon-window>
<div style="height:3rem;"></div>
</div>
</template>
<script>
// import { swiper, swiperSlide } from "vue-awesome-swiper";
import GoodList from "@/components/GoodList";
import PromotionGood from "@/components/PromotionGood";
import CouponWindow from "@/components/CouponWindow";
import { getHomeData, getShare } from "@/api/public";
import cookie from "@/utils/store/cookie";
import { isWeixin } from "@/utils/index";
const HAS_COUPON_WINDOW = "has_coupon_window";
export default {
name: "Index",
components: {
// swiper,
// swiperSlide,
GoodList,
PromotionGood,
CouponWindow
},
props: {},
data: function() {
return {
showCoupon: false,
logoUrl: "",
banner: [],
menus: [],
roll: [],
activity: [],
activityOne: {},
bastList: [],
firstList: [],
info: {
fastList: [],
bastBanner: [],
bastList: []
},
likeInfo: [],
lovely: [],
benefit: [],
couponList: [],
swiperOption: {
pagination: {
el: ".swiper-pagination",
clickable: true
},
autoplay: {
disableOnInteraction: false,
delay: 2000
},
loop: true,
speed: 1000,
observer: true,
observeParents: true
},
swiperRoll: {
direction: "vertical",
autoplay: {
disableOnInteraction: false,
delay: 2000
},
loop: true,
speed: 1000,
observer: true,
observeParents: true
},
swiperScroll: {
freeMode: true,
freeModeMomentum: false,
slidesPerView: "auto",
observer: true,
observeParents: true
},
swiperBoutique: {
pagination: {
el: ".swiper-pagination",
clickable: true
},
autoplay: {
disableOnInteraction: false,
delay: 2000
},
loop: true,
speed: 1000,
observer: true,
observeParents: true
},
swiperProducts: {
freeMode: true,
freeModeMomentum: false,
slidesPerView: "auto",
observer: true,
observeParents: true
}
};
},
mounted: function() {
let that = this;
getHomeData().then(res => {
that.logoUrl = res.data.logoUrl;
that.$set(that, "banner", res.data.banner);
that.$set(that, "menus", res.data.menus);
that.$set(that, "roll", res.data.roll);
that.$set(that, "activity", res.data.activity);
var activityOne = res.data.activity.shift();
that.$set(that, "activityOne", activityOne);
that.$set(that, "info", res.data.info);
that.$set(that, "firstList", res.data.firstList);
that.$set(that, "bastList", res.data.bastList);
that.$set(that, "likeInfo", res.data.likeInfo);
that.$set(that, "lovely", res.data.lovely);
that.$set(that, "benefit", res.data.benefit);
that.$set(that, "couponList", res.data.couponList);
that.setOpenShare();
});
},
methods: {
setOpenShare: function() {}
}
};
</script>
<style scoped>
.index {
background-color: #fff;
}
.swiper-item {
height: 100%;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index.vue'
const app = new Vue(App)
app.$mount()
+94
View File
@@ -0,0 +1,94 @@
<template>
<div class="page">
<div :class="tabtarIndex==0?'page':''" v-show="tabtarIndex==0">
<home></home>
</div>
<div :class="tabtarIndex==1?'page':''" v-show="tabtarIndex==1">
<goods-class></goods-class>
</div>
<div :class="tabtarIndex==2?'page':''" v-if="tabtarIndex==2">
<shopping-cart></shopping-cart>
</div>
<div :class="tabtarIndex==3?'page':''" v-if="tabtarIndex==3">
<user></user>
</div>
<footer-components></footer-components>
</div>
</template>
<script>
import Home from "@/pages/home/index";
import GoodsClass from "@/pages/shop/GoodsClass/index";
import ShoppingCart from "@/pages/shop/ShoppingCart/index";
import User from "@/pages/user/User/index";
import FooterComponents from "@/components/Footer";
import { mapState, mapMutations, mapActions } from "vuex";
export default {
name: "Launch",
data() {
return {
history: [],
};
},
components: {
Home,
GoodsClass,
ShoppingCart,
User,
FooterComponents
},
computed: {
...mapState(["tabtarIndex"])
},
methods: {
...mapActions(["changeTabtar"])
},
mounted() {
let type = this.$yroute.query.type;
console.log(2222)
if (type) {
this.changeTabtar(type);
}
// if (!this.tabtarIndex) {
// this.changeTabtar(0);
// }
},
onHide() {
console.log("清除状态");
// this.changeTabtar(0);
}
};
</script>
<style scoped>
.lottie-bg {
position: fixed;
left: 0;
top: 0;
background-color: #fff;
width: 100%;
height: 100%;
z-index: 999;
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
}
#lottie {
width: 35%;
display: block;
overflow: hidden;
transform: translate3d(0, 0, 0);
margin: auto;
}
.iphonex {
height: 68rpx;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+124
View File
@@ -0,0 +1,124 @@
<template>
<div class="apply-return">
<div class="goodsStyle acea-row row-between" v-for="cart in orderInfo.cartInfo" :key="cart.id">
<div class="pictrue">
<img :src="cart.productInfo.image" class="image" />
</div>
<div class="text acea-row row-between">
<div class="name line2">{{ cart.productInfo.storeName }}</div>
<div class="money">
<div>
{{
cart.productInfo.attrInfo
? cart.productInfo.attrInfo.price
: cart.productInfo.price
}}
</div>
<div class="num">x{{ cart.cartNum }}</div>
</div>
</div>
</div>
<div class="list">
<div class="item acea-row row-between-wrapper">
<div>退货件数</div>
<div class="num">{{ orderInfo.totalNum }}</div>
</div>
<div class="item acea-row row-between-wrapper">
<div>退款金额</div>
<div class="num">{{ orderInfo.payPrice }}</div>
</div>
<picker :value="reason" :range="reasonList" @change="changeReason">
<div class="item acea-row row-between-wrapper">
<div>退款原因</div>
<div class="num">{{reason}}</div>
<span class="iconfont icon-jiantou"></span>
</div>
</picker>
<div class="item textarea acea-row row-between">
<div>备注说明</div>
<textarea placeholder="填写备注信息,100字以内" class="num" v-model="refund_reason_wap_explain"></textarea>
</div>
</div>
<div class="returnBnt bg-color-red" @click="submit">申请退款</div>
</div>
</template>
<script>
import { orderDetail, getRefundReason, postOrderRefund } from "@/api/order";
import { trim } from "@/utils";
import { VUE_APP_API_URL } from "@/config";
export default {
name: "goodsReturn",
components: {
// VueCoreImageUpload
},
data() {
return {
url: `${VUE_APP_API_URL}/upload/image`,
headers: {
Authorization: "Bearer " + this.$store.state.token
},
id: 0,
orderInfo: {},
reasonList: [],
reason: "",
refund_reason_wap_explain: "",
refund_reason_wap_img: []
};
},
methods: {
changeReason(e) {
this.reason = this.reasonList[e.mp.detail.value];
},
imageuploaded(res) {
if (res.status !== 200)
return this.$dialog.error(res.msg || "上传图片失败");
this.refund_reason_wap_img.push(res.data.url);
},
getOrderDetail() {
orderDetail(this.id)
.then(res => {
this.orderInfo = res.data;
})
.catch(err => {
this.$dialog.error(err.response.data.msg || "获取订单失败");
});
},
getRefundReason() {
getRefundReason().then(res => {
this.reasonList = res.data;
});
},
submit() {
const refund_reason_wap_explain = trim(this.refund_reason_wap_explain),
text = this.reason;
if (!text) return this.$dialog.toast({ mes: "请选择退款原因" });
postOrderRefund({
text,
uni: this.orderInfo.orderId,
refund_reason_wap_img: this.refund_reason_wap_img.join(","),
refund_reason_wap_explain
})
.then(res => {
wx.showToast({
title: res.msg,
icon: "success",
duration: 2000
});
setTimeout(() => {
this.$yrouter.back();
}, 1500);
})
.catch(err => {
this.$dialog.error(err.msg||err.response.data.msg);
});
}
},
mounted() {
this.id = this.$yroute.query.id || 0;
this.getOrderDetail();
this.getRefundReason();
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+350
View File
@@ -0,0 +1,350 @@
<template>
<div class="logistics">
<div class="header acea-row row-between row-top" v-for="cart in cartInfo" :key="cart.id">
<div class="pictrue">
<img :src="cart.productInfo.image" />
</div>
<div class="text acea-row row-between">
<div class="name line2">{{ cart.productInfo.store_name }}</div>
<div class="money">
<div>{{ cart.truePrice }}</div>
<div>x{{ cart.cart_num }}</div>
</div>
</div>
</div>
<div class="logisticsCon" style="margin-bottom: 5px">
<div class="company acea-row row-between-wrapper">
<div class="picTxt acea-row row-between-wrapper">
<div class="iconfont icon-wuliu"></div>
<div class="text">
<div>
<span class="name line1">物流公司</span>
{{ orderInfo.deliveryName }}
</div>
<div class="express line1">
<span class="name">快递单号</span>
{{ orderInfo.deliveryId }}
</div>
</div>
</div>
<div
class="copy acea-row row-center-wrapper copy-data"
@click="copyClipboard(orderInfo.deliveryId)"
>复制单号</div>
</div>
<div class="item" v-for="(express, expressListIndex) in expressList" :key="expressListIndex">
<div class="circular" :class="expressListIndex === 0 ? 'on' : ''"></div>
<div class="text">
<div :class="expressListIndex === 0 ? 'font-color-red' : ''">{{ express.status }}</div>
<div class="data">{{ express.time }}</div>
</div>
</div>
</div>
<!-- 物流进度条 -->
<div class="div-bg bg-white" style="font-size:12px; background:#fff;">
<!--物流跟踪-->
<div style="margin-bottom:5px;">
<div
class="bg-white"
style="width: 92%; margin-left: 4%;margin: auto;padding-left: 15px;padding-right: 15px;padding-top: 10px"
>
<div style="font-size: .26rem;color: #111111; margin: 5px 0">
物流跟踪
<!--物流跟踪-->
</div>
<div>
<div class="track-rcol">
<div class="track-list">
<ul>
<div v-for="(item,logisticsListindex) in logisticsList" :key="logisticsListindex">
<li class="active" v-if="logisticsListindex===0">
<div></div>
<i class="node-icon"></i>
<span class="txt">{{item.acceptStation}}</span>
<span class="time">{{item.acceptTime}}</span>
</li>
<li
v-if="logisticsListindex > 0 && logisticsListindex !== logisticsList.length-1"
>
<i class="node-icon"></i>
<span class="txt">{{item.acceptStation}}</span>
<span class="time">{{item.acceptTime}}</span>
</li>
<li v-if="logisticsListindex === logisticsList.length-1" class="finall">
<i class="div-spilander"></i>
<i class="node-icon"></i>
<span class="txt">{{item.acceptStation}}</span>
<span class="time">{{item.acceptTime}}</span>
</li>
</div>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="no-express" v-if="loaded && !expressList.length">
<img :src="$VUE_APP_RESOURCES_URL+'/images/noExpress.png'" />
</div>
<Recommend></Recommend>
</div>
</template>
<script>
import Recommend from "@/components/Recommend";
import { express, orderDetail } from "@/api/order";
import { copyClipboard } from "@/utils";
const NAME = "Logistics";
export default {
name: NAME,
components: {
Recommend
},
data: function() {
return {
id: "",
cartInfo: [],
orderInfo: {},
expressList: [],
loaded: false,
logisticsList: [
{
message: "暂无数据",
messageDate: ""
}
]
};
},
watch: {
$yroute(n) {
if (n.name === NAME && this.$yroute.query.id !== this.id) {
this.id = this.$yroute.query.id;
this.getExpress();
}
}
},
mounted: function() {
this.id = this.$yroute.query.id;
this.getExpress();
},
methods: {
copyClipboard,
getExpressInfo() {
let params = {
orderCode: this.id,
shipperCode: this.orderInfo.deliverySn,
logisticCode: this.orderInfo.deliveryId
};
express(params)
.then(res => {
this.logisticsList = res.data.traces.reverse();
})
.catch(err => {
this.$dialog.error(err.response.data.msg || "加载失败");
});
},
getExpress() {
if (!this.id) return this.$dialog.error("订单不存在");
this.loaded = false;
orderDetail(this.id)
.then(res => {
this.orderInfo = {
deliveryId: res.data.deliveryId,
deliveryName: res.data.deliveryName,
deliverySn: res.data.deliverySn
};
this.getExpressInfo();
// const result = res.data.express.result || {};
// this.cartInfo = res.data.order.cartInfo;
// this.expressList = result.list || [];
// this.loaded = true;
})
.catch(err => {
this.$dialog.error(err.response.data.msg || "加载失败");
});
}
}
};
</script>
<style scoped>
.no-express {
margin: 1.5rem 0;
}
.no-express img {
width: 6rem;
margin: 0 auto;
display: block;
}
.message-text {
font-family: MicrosoftYaHei;
font-size: 1rem;
font-weight: normal;
font-stretch: normal;
line-height: 3rem;
letter-spacing: 0rem;
color: #333333;
width: 50%;
}
.fontblack {
color: #999999;
}
.img2 {
width: 0.81rem;
height: 0.8rem;
float: right;
}
.addressshow2 {
height: auto;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
width: 75%;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
white-space: normal;
word-wrap: break-word;
word-break: break-all;
font-size: 1rem;
}
.addressshow1 {
height: auto;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
width: 75%;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
white-space: normal;
word-wrap: break-word;
word-break: break-all;
font-size: 1rem;
}
.orderTitle {
font-size: 1rem;
color: #333333;
height: auto;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
white-space: normal;
word-wrap: break-word;
word-break: break-all;
height: 2.5rem;
}
.orderDetail {
font-size: 0.26rem;
color: #666666;
text-align: left;
}
.border-ceter {
width: 92%;
padding-left: 15px;
padding-right: 15px;
}
.pay-button {
width: 88%;
height: 2.6rem;
position: relative;
background-color: red;
color: white;
margin-left: 6%;
}
ul li {
list-style: none;
font-size: 0.24rem;
}
ul {
}
.track-rcol {
}
.track-list {
position: relative;
}
.track-list li {
position: relative;
padding: 0 0 0.5rem 5px;
line-height: 0.3rem;
border-left: 1px solid #d9d9d9;
color: #999;
}
.track-list li.first {
color: red;
padding-top: 0;
width: 100%;
text-align: left;
border-left: 1px solid #d9d9d9;
}
.track-list li .node-icon {
position: absolute;
left: -6.5px;
border-radius: 50%;
width: 0.2rem;
height: 0.2rem;
top: 4px;
background-color: #b2b2b2;
}
.track-list li.active .node-icon {
background-position: 0-72px;
background-color: #ea7c0a;
width: 0.3rem;
z-index: 2;
height: 0.3rem;
position: absolute;
left: -0.19rem;
top: 0;
border-radius: 50%;
}
.track-list li .time {
margin-right: 20px;
position: relative;
top: 4px;
display: inline-block;
vertical-align: middle;
color: #999;
width: 100%;
text-align: left;
}
.track-list li .txt {
position: relative;
display: inline-block;
vertical-align: top;
color: #999;
left: 0.2rem;
top: 0.04rem;
}
.track-list li.first .time {
text-align: left;
width: 94%;
color: red;
}
.track-list li.first .txt {
color: red;
text-align: left;
width: 94%;
}
.track-list li.finall {
position: relative;
padding: 0px 0 0.5rem 5px;
line-height: 18px;
border-color: white;
border-left: 1px solid #ffffff;
color: #999;
}
.track-list li.finall .div-spilander {
width: 1px;
position: absolute;
left: -1.5px;
height: 0.5rem;
background-color: #d9d9d9;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+347
View File
@@ -0,0 +1,347 @@
<template>
<div class="my-order" ref="container">
<div class="header bg-color-red">
<div class="picTxt acea-row row-between-wrapper">
<div class="text">
<div class="name">订单信息</div>
<div>
累计订单{{ orderData.orderCount || 0 }} 总消费{{
orderData.sumPrice || 0
}}
</div>
</div>
</div>
</div>
<div class="nav acea-row row-around">
<div class="item" :class="{ on: type === 0 }" @click="changeType(0)">
<div>待付款</div>
<div class="num">{{ orderData.unpaidCount || 0 }}</div>
</div>
<div class="item" :class="{ on: type === 1 }" @click="changeType(1)">
<div>待发货</div>
<div class="num">{{ orderData.unshippedCount || 0 }}</div>
</div>
<div class="item" :class="{ on: type === 2 }" @click="changeType(2)">
<div>待收货</div>
<div class="num">{{ orderData.receivedCount || 0 }}</div>
</div>
<div class="item" :class="{ on: type === 3 }" @click="changeType(3)">
<div>待评价</div>
<div class="num">{{ orderData.evaluatedCount || 0 }}</div>
</div>
<div class="item" :class="{ on: type === 4 }" @click="changeType(4)">
<div>已完成</div>
<div class="num">{{ orderData.completeCount || 0 }}</div>
</div>
</div>
<div class="list">
<div class="item" v-for="(order,orderListIndex) in orderList" :key="orderListIndex">
<div class="title acea-row row-between-wrapper">
<div class="acea-row row-middle">
<span
class="sign cart-color acea-row row-center-wrapper"
v-if="order.combinationId > 0"
>拼团</span>
<span class="sign cart-color acea-row row-center-wrapper" v-if="order.seckillId > 0">秒杀</span>
<span class="sign cart-color acea-row row-center-wrapper" v-if="order.bargainId > 0">砍价</span>
<data-format :data="order.addTime"></data-format>
</div>
<div class="font-color-red">{{ getStatus(order) }}</div>
</div>
<div
@click="$yrouter.push({ path: '/pages/order/OrderDetails/index',query:{id:order.orderId} })"
>
<div
class="item-info acea-row row-between row-top"
v-for="(cart,cartInfoIndex) in order.cartInfo"
:key="cartInfoIndex"
>
<div class="pictrue">
<img
:src="cart.productInfo.image"
@click.stop="
$yrouter.push({ path: '/pages/shop/GoodsCon/index',query:{id:cart.productInfo.id} })
"
v-if="cart.combinationId === 0 && cart.bargainId === 0 &&cart.seckillId === 0"
/>
<img
:src="cart.productInfo.image"
@click.stop="
$yrouter.push({
path: '/pages/activity/GroupDetails/index',query:{id:cart.combinationId}
})
"
v-else-if="cart.combinationId > 0"
/>
<img
:src="cart.productInfo.image"
@click.stop="
$yrouter.push({
path: '/pages/activity/DargainDetails/index',query:{id:cart.bargainId}
})
"
v-else-if="cart.bargainId > 0"
/>
<img
:src="cart.productInfo.image"
@click.stop="
$yrouter.push({
path: '/pages/activity/SeckillDetails/index',query:{id:cart.seckillId}
})
"
v-else-if="cart.seckillId > 0"
/>
</div>
<div class="text acea-row row-between">
<div class="name line2">{{ cart.productInfo.storeName }}</div>
<div class="money">
<div>
{{
cart.productInfo.attrInfo
? cart.productInfo.attrInfo.price
: cart.productInfo.price
}}
</div>
<div>x{{ cart.cartNum }}</div>
</div>
</div>
</div>
</div>
<div class="totalPrice">
{{ order.cartInfo.length || 0 }}件商品总金额
<span
class="money font-color-red"
>{{ order.payPrice }}</span>
</div>
<div class="bottom acea-row row-right row-middle">
<template v-if="order._status._type == 0">
<div class="bnt cancelBnt" @click="cancelOrder(order)">取消订单</div>
<div
class="bnt bg-color-red"
@click="$yrouter.push({ path: '/pages/order/OrderDetails/index',query:{id:order.orderId} })"
>立即付款</div>
</template>
<template v-if="order._status._type == 1 || order._status._type == 9">
<div
class="bnt bg-color-red"
@click="$yrouter.push({ path: '/pages/order/OrderDetails/index',query:{id:order.orderId} })"
>查看详情</div>
</template>
<template v-if="order._status._type == 2">
<div
class="bnt default"
@click="
$yrouter.push({ path: '/pages/order/Logistics/index',query:{id:order.orderId}})
"
>查看物流</div>
<div class="bnt bg-color-red" @click="takeOrder(order)">确认收货</div>
</template>
<template v-if="order._status._type == 3">
<!--<div-->
<!--class="bnt default"-->
<!--@click="-->
<!--$yrouter.push({ path: '/pages/order/Logistics/index',query:{id:order.orderId}})-->
<!--"-->
<!--v-if="order.deliveryType == 'express'"-->
<!--&gt;-->
<!--查看物流-->
<!--</div>-->
<div
class="bnt bg-color-red"
@click="$yrouter.push({ path: '/pages/order/OrderDetails/index',query:{id:order.orderId} })"
>去评价</div>
</template>
<template v-if="order._status._type === 4">
<div
class="bnt bg-color-red"
@click="$yrouter.push({ path: '/pages/order/OrderDetails/index',query:{id:order.orderId} })"
>查看订单</div>
</template>
</div>
</div>
</div>
<div class="noCart" v-if="orderList.length === 0 && page > 1">
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/noOrder.png'" />
</div>
</div>
<Loading :loaded="loaded" :loading="loading"></Loading>
<Payment v-model="pay" :types="payType" @checked="toPay" :balance="userInfo.nowMoney"></Payment>
</div>
</template>
<script>
import { getOrderData, getOrderList } from "@/api/order";
import {
cancelOrderHandle,
payOrderHandle,
takeOrderHandle
} from "@/libs/order";
import Loading from "@/components/Loading";
import Payment from "@/components/Payment";
import DataFormat from "@/components/DataFormat";
import { mapGetters } from "vuex";
import { isWeixin, dataFormat } from "@/utils";
const STATUS = [
"待付款",
"待发货",
"待收货",
"待评价",
"已完成",
"",
"",
"",
"",
"待付款"
];
const NAME = "MyOrder";
export default {
name: NAME,
data() {
return {
offlinePayStatus: 2,
orderData: {},
type: "",
page: 1,
limit: 20,
loaded: false,
loading: false,
orderList: [],
pay: false,
payType: ["yue", "weixin"],
from: isWeixin() ? "weixin" : "weixinh5"
};
},
components: {
Loading,
Payment,
DataFormat
},
computed: mapGetters(["userInfo"]),
watch: {
$yroute(n) {
if (n.name === NAME) {
const type = parseInt(this.$yroute.query.type) || 0;
if (this.type !== type) {
this.changeType(type);
}
this.getOrderData();
}
},
type() {}
},
methods: {
dataFormat,
setOfflinePayStatus: function(status) {
var that = this;
that.offlinePayStatus = status;
if (status === 1) {
if (that.payType.indexOf("offline") < 0) {
that.payType.push("offline");
}
}
},
getOrderData() {
getOrderData().then(res => {
this.orderData = res.data;
});
},
takeOrder(order) {
takeOrderHandle(order.orderId).finally(() => {
this.reload();
this.getOrderData();
});
},
reload() {
this.changeType(this.type);
},
changeType(type) {
this.type = type;
this.orderList = [];
this.page = 1;
this.loaded = false;
this.loading = false;
this.getOrderList();
},
getOrderList() {
if (this.loading || this.loaded) return;
this.loading = true;
const { page, limit, type } = this;
getOrderList({
page,
limit,
type
}).then(res => {
this.orderList = this.orderList.concat(res.data);
this.page++;
this.loaded = res.data.length < this.limit;
this.loading = false;
});
},
getStatus(order) {
return STATUS[order._status._type];
},
cancelOrder(order) {
cancelOrderHandle(order.orderId)
.then(() => {
this.getOrderData();
this.orderList.splice(this.orderList.indexOf(order), 1);
})
.catch(() => {
this.reload();
});
},
paymentTap: function(order) {
var that = this;
if (
!(order.combinationId > 0 || order.bargainId > 0 || order.seckillId > 0)
) {
that.setOfflinePayStatus(order.offlinePayStatus);
}
this.pay = true;
this.toPay = type => {
payOrderHandle(order.orderId, type, that.from)
.then(() => {
const type = parseInt(this.$yroute.query.type) || 0;
that.changeType(type);
that.getOrderData();
})
.catch(() => {
const type = parseInt(that.$yroute.query.type) || 0;
that.changeType(type);
that.getOrderData();
});
};
},
toPay() {}
},
mounted() {
this.type = parseInt(this.$yroute.query.type) || 0;
this.getOrderData();
this.getOrderList();
},
onReachBottom() {
!this.loading && this.getOrderList();
}
};
</script>
<style scoped>
.noCart {
margin-top: 0.17rem;
padding-top: 0.1rem;
}
.noCart .pictrue {
width: 4rem;
height: 3rem;
margin: 0.7rem auto 0.5rem auto;
}
.noCart .pictrue img {
width: 100%;
height: 100%;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+629
View File
@@ -0,0 +1,629 @@
<template>
<div class="order-details">
<!-- 给header上与data上加on为退款订单-->
<div class="header bg-color-red acea-row row-middle" :class="refundOrder ? 'on' : ''">
<div class="data" :class="refundOrder ? 'on' : ''">
<div class="state">{{ orderInfo._status._msg }}</div>
<div>
<data-format :data="orderInfo.addTime"></data-format>
</div>
</div>
</div>
<template v-if="!refundOrder">
<div class="nav">
<div class="navCon acea-row row-between-wrapper">
<div :class="{ on: status.type === 0 || status.type === 9 }">待付款</div>
<div :class="{ on: status.type === 1 }" v-if="orderInfo.shippingType === 2">待核销</div>
<div :class="{ on: status.type === 1 }" v-else>待发货</div>
<div :class="{ on: status.type === 2 }" v-if="orderInfo.shippingType === 1">待收货</div>
<div :class="{ on: status.type === 3 }">待评价</div>
<div :class="{ on: status.type === 4 }">已完成</div>
</div>
<div class="progress acea-row row-between-wrapper">
<div
class="iconfont"
:class="[
status.type === 0 || status.type === 9
? 'icon-webicon318'
: 'icon-yuandianxiao',
status.type >= 0 ? 'font-color-red' : ''
]"
></div>
<div class="line" :class="{ 'bg-color-red': status.type > 0 && status.type != 9 }"></div>
<div
class="iconfont"
:class="[
status.type === 1 ? 'icon-webicon318' : 'icon-yuandianxiao',
status.type >= 1 && status.type != 6 && status.type != 9
? 'font-color-red'
: ''
]"
></div>
<div
class="line"
:class="{
'bg-color-red':
status.type > 1 && status.type != 6 && status.type != 9
}"
v-if="orderInfo.shipping_type === 1"
></div>
<div
class="iconfont"
:class="[
status.type === 2 ? 'icon-webicon318' : 'icon-yuandianxiao',
status.type >= 2 && status.type != 6 && status.type != 9
? 'font-color-red'
: ''
]"
v-if="orderInfo.shippingType === 1"
></div>
<div
class="line"
:class="{
'bg-color-red':
status.type > 2 && status.type != 6 && status.type != 9
}"
></div>
<div
class="iconfont"
:class="[
status.type === 3 ? 'icon-webicon318' : 'icon-yuandianxiao',
status.type >= 3 && status.type != 6 && status.type != 9
? 'font-color-red'
: ''
]"
></div>
<div
class="line"
:class="{
'bg-color-red':
status.type > 3 && status.type != 6 && status.type != 9
}"
></div>
<div
class="iconfont"
:class="[
status.type == 4 ? 'icon-webicon318' : 'icon-yuandianxiao',
status.type >= 4 && status.type != 6 && status.type != 9
? 'font-color-red'
: ''
]"
></div>
</div>
</div>
<!--<div-->
<!--class="writeOff"-->
<!--v-if="orderInfo.shipping_type === 2 && orderInfo.paid === 1"-->
<!--&gt;-->
<!--<div class="title">核销信息</div>-->
<!--<div class="grayBg">-->
<!--<div class="pictrue"><img :src="orderInfo.code" /></div>-->
<!--</div>-->
<!--<div class="gear"><img :src="$VUE_APP_RESOURCES_URL+'/images/writeOff.jpg'" /></div>-->
<!--<div class="num">{{ orderInfo._verify_code }}</div>-->
<!--<!--<!--<!--<span class="rules">-->
<!--<!--<!--<span class="item">-->
<!--<!--<span class="rulesTitle acea-row row-middle">-->
<!--<span class="iconfont icon-shijian"></span>核销时间-->
<!--</!--<span>-->
<!--<div class="info">-->
<!--{{ system_store._valid_time-->
<!--}}<span class="time">{{ system_store.day_time }}</span>-->
<!--</div>-->
<!--</!--<!--<span>-->
<!--<div class="item">-->
<!--<div class="rulesTitle acea-row row-middle">-->
<!--<span class="iconfont icon-shuoming1"></span>使用说明-->
<!--</div>-->
<!--<div class="info">可将二维码出示给店员扫描或提供数字核销码</div>-->
<!--</div>-->
<!--</!--<!--<!--<span>-->
<!--</!--<!--<!--<!--<span>-->
<!--<div-->
<!--class="map acea-row row-between-wrapper"-->
<!--v-if="orderInfo.shipping_type === 2 && orderInfo.paid === 1"-->
<!--&gt;-->
<!--<div>自提地址信息</div>-->
<!--<div-->
<!--class="place cart-color acea-row row-center-wrapper"-->
<!--@click="showChang"-->
<!--&gt;-->
<!--<span class="iconfont icon-weizhi"></span>查看位置-->
<!--</div>-->
<!--</div>-->
<div class="address" v-if="orderInfo.shippingType === 1">
<div class="name">
{{ orderInfo.realName
}}
<span class="phone">{{ orderInfo.userPhone }}</span>
<span class="iconfont icon-tonghua font-color-red"></span>
</div>
<div>{{ orderInfo.userAddress }}</div>
</div>
<!--<div class="address" v-else>-->
<!--<div class="name">-->
<!--{{ system_store.name-->
<!--}}<span class="phone">{{ system_store.phone }}</span>-->
<!--<a-->
<!--class="iconfont icon-tonghua font-color-red"-->
<!--:href="'tel:' + system_store.phone"-->
<!--&gt;</a>-->
<!--</div>-->
<!--<div>{{ system_store._detailed_address }}</div>-->
<!--</div>-->
<div class="line" v-if="orderInfo.shippingType === 1">
<img :src="$VUE_APP_RESOURCES_URL+'/images/line.jpg'" />
</div>
</template>
<OrderGoods :evaluate="status.type || 0" :cartInfo="orderInfo.cartInfo || []"></OrderGoods>
<div class="wrapper">
<div class="item acea-row row-between">
<div>订单编号</div>
<div class="conter acea-row row-middle row-right">
{{ orderInfo.orderId
}}
<span
class="copy copy-data"
@click="copyClipboard(orderInfo.orderId)"
>复制</span>
</div>
</div>
<div class="item acea-row row-between">
<div>下单时间</div>
<div class="conter">
<data-format :data="orderInfo.addTime"></data-format>
</div>
</div>
<div class="item acea-row row-between">
<div>订单类型</div>
<div class="conter">{{ orderTypeName }}</div>
</div>
<div class="item acea-row row-between">
<div>支付状态</div>
<div class="conter">{{ orderInfo.paid ? "已支付" : "未支付" }}</div>
</div>
<div class="item acea-row row-between">
<div>支付方式</div>
<div class="conter">{{ orderInfo._status._payType }}</div>
</div>
<div class="item acea-row row-between" v-if="orderInfo.mark">
<div>买家留言</div>
<div class="conter">{{ orderInfo.mark }}</div>
</div>
</div>
<div v-if="orderInfo.status != 0">
<div class="wrapper" v-if="orderInfo.deliveryType === 'express'">
<div class="item acea-row row-between">
<div>配送方式</div>
<div class="conter">发货</div>
</div>
<div class="item acea-row row-between">
<div>快递公司</div>
<div class="conter">{{ orderInfo.deliveryName || "" }}</div>
</div>
<div class="item acea-row row-between">
<div>快递号</div>
<div class="conter">{{ orderInfo.deliveryId || "" }}</div>
</div>
</div>
<div class="wrapper" v-else>
<div class="item acea-row row-between">
<div>配送方式</div>
<div class="conter">送货</div>
</div>
<div class="item acea-row row-between">
<div>配送人</div>
<div class="conter">{{ orderInfo.deliveryName || "" }}</div>
</div>
<div class="item acea-row row-between">
<div>配送电话</div>
<div class="conter acea-row row-middle row-right">
{{ orderInfo.deliveryId || "" }}
<span class="copy">拨打</span>
</div>
</div>
</div>
</div>
<!-- 退款订单详情 -->
<div class="wrapper" v-if="refundOrder">
<div class="item acea-row row-between">
<div>收货人</div>
<div class="conter">{{ orderInfo.realName }}</div>
</div>
<div class="item acea-row row-between">
<div>联系电话</div>
<div class="conter">{{ orderInfo.userPhone }}</div>
</div>
<div class="item acea-row row-between">
<div>收货地址</div>
<div class="conter">{{ orderInfo.userAddress }}</div>
</div>
</div>
<div class="wrapper">
<div class="item acea-row row-between">
<div>支付金额</div>
<div class="conter">{{ orderInfo.totalPrice }}</div>
</div>
<div class="item acea-row row-between" v-if="orderInfo.couponPrice > 0">
<div>优惠券抵扣</div>
<div class="conter">-{{ orderInfo.couponPrice }}</div>
</div>
<div class="item acea-row row-between" v-if="orderInfo.useIntegral > 0">
<div>积分抵扣</div>
<div class="conter">-{{ orderInfo.deductionPrice }}</div>
</div>
<div class="item acea-row row-between" v-if="orderInfo.payPostage > 0">
<div>运费</div>
<div class="conter">{{ orderInfo.payPostage }}</div>
</div>
<div class="actualPay acea-row row-right">
实付款
<span class="money font-color-red">{{ orderInfo.payPrice }}</span>
</div>
</div>
<div style="height:100rpx;" v-if="!refundOrder && offlineStatus"></div>
<div class="footer acea-row row-right row-middle" v-if="!refundOrder && offlineStatus">
<template v-if="status.type == 0">
<div class="bnt cancel" @click="cancelOrder">取消订单</div>
<div class="bnt bg-color-red" @click="pay = true">立即付款</div>
</template>
<template v-if="status.type == 1">
<div
class="bnt cancel"
@click="$yrouter.push({ path: '/pages/order/GoodsReturn/index',query:{id:orderInfo.orderId } })"
>申请退款</div>
</template>
<template v-if="status.type == 2">
<div
class="bnt default"
@click="
$yrouter.push({ path: '/pages/order/Logistics/index' ,query:{id:orderInfo.orderId }})
"
>查看物流</div>
<div class="bnt bg-color-red" @click="takeOrder">确认收货</div>
</template>
<template v-if="status.type == 3 && orderInfo.deliveryType == 'express'">
<div
class="bnt default"
@click="
$yrouter.push({ path: '/pages/order/Logistics/index' ,query:{id:orderInfo.orderId }})
"
>查看物流</div>
</template>
<template v-if="status.type == 4">
<div class="bnt cancel" @click="delOrder">删除订单</div>
<div
class="bnt default"
@click="
$yrouter.push({ path: '/pages/order/Logistics/index' ,query:{id:orderInfo.orderId }})
"
>查看物流</div>
</template>
<template v-if="status.type == 6">
<div
class="bnt bg-color-red"
@click="
$yrouter.push({ path: '/pages/activity/GroupRule/index',query:{id:orderInfo.pinkId} })
"
>查看拼团</div>
</template>
</div>
<Payment v-model="pay" :types="payType" @checked="toPay" :balance="userInfo.nowMoney"></Payment>
<div class="geoPage" v-if="mapShow">
<iframe
width="100%"
height="100%"
frameborder="0"
scrolling="no"
:src="'https://apis.map.qq.com/uri/v1/geocoder?coord=' + system_store.latitude + ',' +system_store.longitude +'&referer=' +mapKey"
></iframe>
</div>
</div>
</template>
<style scoped>
.geoPage {
position: fixed;
width: 100%;
height: 100%;
top: 0;
z-index: 10000;
}
.order-details .writeOff {
background-color: #fff;
margin-top: 0.13rem;
padding-bottom: 0.3rem;
}
.order-details .writeOff .title {
font-size: 0.3rem;
color: #282828;
height: 0.87rem;
border-bottom: 1px solid #f0f0f0;
padding: 0 0.3rem;
line-height: 0.87rem;
}
.order-details .writeOff .grayBg {
background-color: #f2f5f7;
width: 5.9rem;
height: 3.84rem;
border-radius: 0.2rem 0.2rem 0 0;
margin: 0.5rem auto 0 auto;
padding-top: 0.55rem;
}
.order-details .writeOff .grayBg .pictrue {
width: 2.9rem;
height: 2.9rem;
margin: 0 auto;
}
.order-details .writeOff .grayBg .pictrue img {
width: 100%;
height: 100%;
display: block;
}
.order-details .writeOff .gear {
width: 5.9rem;
height: 0.3rem;
margin: 0 auto;
}
.order-details .writeOff .gear img {
width: 100%;
height: 100%;
display: block;
}
.order-details .writeOff .num {
background-color: #f0c34c;
width: 5.9rem;
height: 0.84rem;
color: #282828;
font-size: 0.48rem;
margin: 0 auto;
border-radius: 0 0 0.2rem 0.2rem;
text-align: center;
padding-top: 0.04rem;
}
.order-details .writeOff .rules {
margin: 0.46rem 0.3rem 0 0.3rem;
border-top: 0.01rem solid #f0f0f0;
padding-top: 0.1rem;
}
.order-details .writeOff .rules .item {
margin-top: 0.15rem;
}
.order-details .writeOff .rules .item .rulesTitle {
font-size: 0.28rem;
color: #282828;
}
.order-details .writeOff .rules .item .rulesTitle .iconfont {
font-size: 0.3rem;
color: #333;
margin-right: 0.08rem;
margin-top: 0.05rem;
}
.order-details .writeOff .rules .item .info {
font-size: 0.28rem;
color: #999;
margin-top: 0.05rem;
}
.order-details .writeOff .rules .item .info .time {
margin-left: 0.2rem;
}
.order-details .map {
height: 0.86rem;
font-size: 0.3rem;
color: #282828;
line-height: 0.86rem;
border-bottom: 0.01rem solid #f0f0f0;
margin-top: 0.13rem;
background-color: #fff;
padding: 0 0.3rem;
}
.order-details .map .place {
font-size: 0.26rem;
width: 1.76rem;
height: 0.5rem;
border-radius: 0.25rem;
line-height: 0.5rem;
text-align: center;
}
.order-details .map .place .iconfont {
font-size: 0.27rem;
height: 0.27rem;
line-height: 0.27rem;
margin: 0.02rem 0.03rem 0 0;
}
.order-details .address .name .iconfont {
font-size: 0.34rem;
margin-left: 0.1rem;
}
</style>
<script>
import OrderGoods from "@/components/OrderGoods";
import { orderDetail } from "@/api/order";
import Payment from "@/components/Payment";
import DataFormat from "@/components/DataFormat";
import { isWeixin, copyClipboard } from "@/utils";
import { mapGetters } from "vuex";
import {
cancelOrderHandle,
takeOrderHandle,
delOrderHandle,
payOrderHandle
} from "@/libs/order";
// import { wechatEvevt } from "@/libs/wechat";
const NAME = "OrderDetails";
export default {
name: NAME,
components: {
OrderGoods,
Payment,
DataFormat
},
props: {},
data: function() {
return {
offlinePayStatus: 2,
orderTypeName: "普通订单",
orderTypeNameStatus: true,
offlineStatus: true,
id: "",
orderInfo: {
_status: {}
},
status: {},
pay: false,
payType: ["yue", "weixin"],
from: "routine",
system_store: {},
mapKay: "",
mapShow: false
};
},
computed: {
refundOrder() {
return this.orderInfo.refund_status > 0;
},
...mapGetters(["userInfo"])
},
onShow() {
this.id = this.$yroute.query.id;
this.getDetail();
},
inject: ["app"],
mounted: function() {
this.id = this.$yroute.query.id;
// this.getDetail();
},
methods: {
copyClipboard,
showChang: function() {
if (isWeixin()) {
let config = {
latitude: this.system_store.latitude,
longitude: this.system_store.longitude,
name: this.system_store.name,
address: this.system_store._detailed_address
};
// wechatEvevt("openLocation", config)
// .then(res => {
// })
// .catch(res => {
// if (res.is_ready) {
// res.wx.openLocation(config);
// }
// });
} else {
if (!this.mapKey)
return this.$dialog.error(
"暂无法使用查看地图,请配置您的腾讯地图key"
);
this.mapShow = true;
}
},
goBack() {
const history = this.app.history,
last = history[history.length - 1] || {};
if (last.name === "MyOrder") return this.$yrouter.back();
else return this.$yrouter.replace({ path: "/order/list/" });
},
cancelOrder() {
cancelOrderHandle(this.orderInfo.orderId)
.then(() => {
setTimeout(() => this.goBack(), 300);
})
.catch(() => {
this.getDetail();
});
},
takeOrder() {
takeOrderHandle(this.orderInfo.orderId).finally(() => {
this.getDetail();
});
},
delOrder() {
delOrderHandle(this.orderInfo.orderId).then(() => {
setTimeout(() => this.goBack(), 300);
});
},
setOfflinePayStatus: function(status) {
var that = this;
that.offlinePayStatus = status;
if (status === 1 && that.orderTypeNameStatus === true) {
that.payType.push("offline");
}
},
getOrderStatus: function() {
let orderInfo = this.orderInfo || {},
_status = orderInfo._status || { _type: 0 },
status = {};
let type = parseInt(_status._type),
delivery_type = orderInfo.deliveryType,
seckill_id = orderInfo.seckillId ? parseInt(orderInfo.seckillId) : 0,
bargain_id = orderInfo.bargainId ? parseInt(orderInfo.bargainId) : 0,
combination_id = orderInfo.combinationId
? parseInt(orderInfo.combinationId)
: 0;
status = {
type: type,
class_status: 0
};
if (type == 1 && combination_id > 0) {
status.type = 6;
status.class_status = 1;
} //查看拼团
if (type == 2 && delivery_type == "express") status.class_status = 2; //查看物流
if (type == 2) status.class_status = 3; //确认收货
if (type == 4 || type === 0) status.class_status = 4; //删除订单
if (
!seckill_id &&
!bargain_id &&
!combination_id &&
(type == 3 || type == 4)
)
status.class_status = 5; //再次购买
if (type == 9) {
//线下付款
status.class_status = 0;
this.offlineStatus = false;
}
this.status = status;
},
getDetail() {
const id = this.id;
if (!id) return this.$dialog.error("订单不存在");
orderDetail(id)
.then(res => {
this.orderInfo = res.data;
this.getOrderStatus();
if (this.orderInfo.combinationId > 0) {
this.orderTypeName = "拼团订单";
this.orderTypeNameStatus = false;
} else if (this.orderInfo.bargainId > 0) {
this.orderTypeName = "砍价订单";
this.orderTypeNameStatus = false;
} else if (this.orderInfo.seckillId > 0) {
this.orderTypeName = "秒杀订单";
this.orderTypeNameStatus = false;
}
this.system_store = res.data.system_store || {};
this.mapKey = res.data.mapKay;
this.setOfflinePayStatus(this.orderInfo.offlinePayStatus);
})
.catch(err => {
wx.showToast({
title: err.response.data.msg,
icon: "none",
duration: 2000
});
});
},
async toPay(type) {
var that = this;
await payOrderHandle(this.orderInfo.orderId, type, that.from);
that.getDetail();
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+518
View File
@@ -0,0 +1,518 @@
<template>
<div class="order-submission">
<div class="allAddress">
<div class="nav acea-row">
<div
class="item font-color-red"
:class="shipping_type === 0 ? 'on' : 'on2'"
@click="addressType(0)"
></div>
<div
class="item font-color-red"
:class="shipping_type === 1 ? 'on' : 'on2'"
@click="addressType(1)"
v-if="storeSelfMention"
></div>
</div>
<div
class="address acea-row row-between-wrapper"
v-if="shipping_type === 0"
@click="addressTap"
>
<div class="addressCon" v-if="addressInfo.realName">
<div class="name">
{{ addressInfo.realName }}
<span class="phone">{{ addressInfo.phone }}</span>
</div>
<div>
<span class="default font-color-red" v-if="addressInfo.isDefault">[默认]</span>
{{ addressInfo.province }}{{ addressInfo.city
}}{{ addressInfo.district }}{{ addressInfo.detail }}
</div>
</div>
<div class="addressCon" v-else>
<div class="setaddress">设置收货地址</div>
</div>
<div class="iconfont icon-jiantou"></div>
</div>
<!--<div class="address acea-row row-between-wrapper" v-else>-->
<!--<div class="addressCon">-->
<!--<div class="name">-->
<!--{{ systemStore.name }}-->
<!--<span class="phone">{{ systemStore.phone }}</span>-->
<!--</div>-->
<!--<div>-->
<!--{{ systemStore._detailed_address }}-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<div class="line">
<img :src="$VUE_APP_RESOURCES_URL+'/images/line.jpg'" />
</div>
</div>
<OrderGoods :evaluate="0" :cartInfo="orderGroupInfo.cartInfo"></OrderGoods>
<div class="wrapper">
<div class="item acea-row row-between-wrapper" @click="couponTap" v-if="deduction === false">
<div>优惠券</div>
<div class="discount">
{{ usableCoupon.couponTitle || "请选择" }}
<span class="iconfont icon-jiantou"></span>
</div>
</div>
<div class="item acea-row row-between-wrapper" v-if="deduction === false">
<div>积分抵扣</div>
<div class="discount">
<div class="select-btn">
<div class="checkbox-wrapper">
<!-- <input type="checkbox" v-model="useIntegral" @click="changeUseIntegral"/> -->
<checkbox-group @change="changeUseIntegral">
<label class="well-check">
<span class="integral">
当前积分
<span class="num font-color-red">{{ userInfo.integral || 0 }}</span>
</span>
<checkbox value :checked="useIntegral ? true : false"></checkbox>
</label>
</checkbox-group>
</div>
</div>
</div>
</div>
<div class="item acea-row row-between-wrapper" v-if="shipping_type === 0">
<div>快递费用</div>
<div class="discount">
{{
orderGroupInfo.priceGroup.storePostage > 0
? orderGroupInfo.priceGroup.storePostage
: "免运费"
}}
</div>
</div>
<div v-else>
<div class="item acea-row row-between-wrapper">
<div>联系人</div>
<div class="discount">
<input type="text" placeholder="请填写您的联系姓名" v-model="contacts" />
</div>
</div>
<div class="item acea-row row-between-wrapper">
<div>联系电话</div>
<div class="discount">
<input type="text" placeholder="请填写您的联系电话" v-model="contactsTel" />
</div>
</div>
</div>
<div class="item">
<div>备注信息</div>
<textarea placeholder="请添加备注(150字以内)" v-model="mark"></textarea>
</div>
</div>
<div class="wrapper">
<div class="item">
<div>支付方式</div>
<div class="list">
<div
class="payItem acea-row row-middle"
:class="active === 'weixin' ? 'on' : ''"
@click="payItem('weixin')"
v-show="isWeixin"
>
<div class="name acea-row row-center-wrapper">
<div class="iconfont icon-weixin2" :class="active === 'weixin' ? 'bounceIn' : ''"></div>微信支付
</div>
<div class="tip">微信快捷支付</div>
</div>
<div
class="payItem acea-row row-middle"
:class="active === 'weixin' ? 'on' : ''"
@click="payItem('weixin')"
v-show="!isWeixin"
>
<div class="name acea-row row-center-wrapper">
<div class="iconfont icon-weixin2" :class="active === 'weixin' ? 'bounceIn' : ''"></div>微信支付
</div>
<div class="tip">微信快捷支付</div>
</div>
<div
class="payItem acea-row row-middle"
:class="active === 'yue' ? 'on' : ''"
@click="payItem('yue')"
>
<div class="name acea-row row-center-wrapper">
<div class="iconfont icon-icon-test" :class="active === 'yue' ? 'bounceIn' : ''"></div>余额支付
</div>
<div class="tip">可用余额{{ userInfo.nowMoney || 0 }}</div>
</div>
</div>
</div>
</div>
<div class="moneyList">
<div class="item acea-row row-between-wrapper" v-if="orderPrice.totalPrice !== undefined">
<div>商品总价</div>
<div class="money">{{ orderPrice.totalPrice }}</div>
</div>
<div class="item acea-row row-between-wrapper" v-if="orderPrice.payPostage > 0">
<div>运费</div>
<div class="money">{{ orderPrice.payPostage }}</div>
</div>
<div class="item acea-row row-between-wrapper" v-if="orderPrice.couponPrice > 0">
<div>优惠券抵扣</div>
<div class="money">-{{ orderPrice.couponPrice }}</div>
</div>
<div class="item acea-row row-between-wrapper" v-if="orderPrice.deductionPrice > 0">
<div>积分抵扣</div>
<div class="money">-{{ orderPrice.deductionPrice }}</div>
</div>
</div>
<div style="height:120rpx"></div>
<div class="footer acea-row row-between-wrapper">
<div>
合计:
<span class="font-color-red">{{ orderPrice.payPrice }}</span>
</div>
<div class="settlement" @click="createOrder">立即结算</div>
</div>
<CouponListWindow
v-on:couponchange="changecoupon($event)"
v-model="showCoupon"
:price="orderPrice.totalPrice"
:checked="usableCoupon.id"
@checked="changeCoupon"
></CouponListWindow>
<AddressWindow
@checked="changeAddress"
@redirect="addressRedirect"
v-model="showAddress"
:checked="addressInfo.id"
ref="mychild"
></AddressWindow>
</div>
</template>
<style scoped>
.order-submission .wrapper .shipping select {
color: #999;
padding-right: 0.15rem;
}
.order-submission .wrapper .shipping .iconfont {
font-size: 0.3rem;
color: #515151;
}
.order-submission .allAddress {
width: 100%;
background-image: linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
background-image: -webkit-linear-gradient(
to bottom,
#e93323 0%,
#f5f5f5 100%
);
background-image: -moz-linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
padding-top: 0.2rem;
}
.order-submission .allAddress .nav {
width: 7.1rem;
margin: 0 auto;
}
.order-submission .allAddress .nav .item {
width: 3.55rem;
}
.order-submission .allAddress .nav .item.on {
position: relative;
width: 2.5rem;
}
.order-submission .allAddress .nav .item.on:before {
position: absolute;
bottom: 0;
/*content: "快递配送";*/
font-size: 0.28rem;
display: block;
height: 0;
width: 3.55rem;
border-width: 0 0.2rem 0.8rem 0;
border-style: none solid solid;
border-color: transparent transparent #fff;
z-index: 9;
border-radius: 0.07rem 0.3rem 0 0;
text-align: center;
line-height: 0.8rem;
}
.order-submission .allAddress .nav .item:nth-of-type(2).on:before {
content: "到店自提";
border-width: 0 0 0.8rem 0.2rem;
border-radius: 0.3rem 0.07rem 0 0;
}
.order-submission .allAddress .nav .item.on2 {
position: relative;
}
.order-submission .allAddress .nav .item.on2:before {
position: absolute;
bottom: 0;
content: "到店自提";
font-size: 0.28rem;
display: block;
height: 0;
width: 4.6rem;
border-width: 0 0 0.6rem 0.6rem;
border-style: none solid solid;
border-color: transparent transparent #f7c1bd;
border-radius: 0.4rem 0.06rem 0 0;
text-align: center;
line-height: 0.6rem;
}
.order-submission .allAddress .nav .item:nth-of-type(1).on2:before {
content: "快递配送";
border-width: 0 0.6rem 0.6rem 0;
border-radius: 0.06rem 0.4rem 0 0;
}
.order-submission .allAddress .address {
box-sizing: border-box;
width: 100%;
height: 1.5rem;
margin: 0 auto;
}
.order-submission .allAddress .line {
box-sizing: border-box;
width: 100%;
margin: 0 auto;
}
.order-submission .wrapper .item .discount input::placeholder {
color: #ccc;
}
</style>
<script>
import OrderGoods from "@/components/OrderGoods";
import CouponListWindow from "@/components/CouponListWindow";
import AddressWindow from "@/components/AddressWindow";
import { postOrderConfirm, postOrderComputed, createOrder } from "@/api/order";
import { mapGetters } from "vuex";
import { weappPay } from "@/libs/wechat";
import { isWeixin } from "@/utils";
const NAME = "OrderSubmission",
_isWeixin = isWeixin();
export default {
name: NAME,
components: {
OrderGoods,
CouponListWindow,
AddressWindow
},
props: {},
data: function() {
return {
offlinePayStatus: 2,
from: "routine",
// from: _isWeixin ? "weixin" : "weixinh5",
deduction: true,
isWeixin: _isWeixin,
pinkId: 0,
active: "weixin",
showCoupon: false,
showAddress: false,
addressInfo: {},
couponId: 0,
orderGroupInfo: {
priceGroup: {}
},
usableCoupon: {},
addressLoaded: false,
useIntegral: false,
orderPrice: {
payPrice: "计算中"
},
mark: "",
system_store: {},
shipping_type: 0,
contacts: "",
contactsTel: "",
store_self_mention: 0
};
},
computed: mapGetters(["userInfo"]),
watch: {
useIntegral() {
this.computedPrice();
},
$yroute(n) {
if (n.name === NAME) this.getCartInfo();
},
shipping_type() {
this.computedPrice();
}
},
mounted: function() {
let that = this;
that.getCartInfo();
if (that.$yroute.query.pinkid !== undefined)
that.pinkId = that.$yroute.query.pinkid;
},
methods: {
addressType: function(index) {
if (index && !this.system_store.id)
return this.$dialog.error("暂无门店信息,您无法选择到店自提!");
this.shipping_type = index;
},
changeUseIntegral: function(e) {
// this.computedPrice();
this.useIntegral = e.mp.detail.value[0];
},
computedPrice() {
let shipping_type = this.shipping_type;
postOrderComputed(this.orderGroupInfo.orderKey, {
addressId: this.addressInfo.id,
useIntegral: this.useIntegral ? 1 : 0,
couponId: this.usableCoupon.id || 0,
shipping_type: parseInt(shipping_type) + 1
}).then(res => {
const data = res.data;
if (data.status === "EXTEND_ORDER") {
this.$yrouter.replace({
path: "/pages/order/OrderDetails/main",
query: { id: data.result.orderId }
});
} else {
this.orderPrice = data.result;
}
});
},
getCartInfo() {
const cartIds = this.$yroute.query.id;
if (!cartIds) {
this.$dialog.error("参数有误");
return this.$yrouter.back();
}
postOrderConfirm(cartIds)
.then(res => {
this.offlinePayStatus = res.data.offline_pay_status;
this.orderGroupInfo = res.data;
this.deduction = res.data.deduction;
this.usableCoupon = res.data.usableCoupon || {};
this.addressInfo = res.data.addressInfo || {};
this.system_store = res.data.system_store || {};
this.store_self_mention = res.data.store_self_mention;
this.computedPrice();
})
.catch(() => {
this.$dialog.error("加载订单数据失败");
});
},
addressTap: function() {
this.showAddress = true;
if (!this.addressLoaded) {
this.addressLoaded = true;
this.$refs.mychild.getAddressList();
}
},
addressRedirect() {
this.addressLoaded = false;
this.showAddress = false;
},
couponTap: function() {
this.showCoupon = true;
},
changeCoupon: function(coupon) {
if (!coupon) {
this.usableCoupon = { couponTitle: "不使用优惠券", id: 0 };
} else {
this.usableCoupon = coupon;
}
this.computedPrice();
},
payItem: function(index) {
this.active = index;
},
changeAddress(addressInfo) {
this.addressInfo = addressInfo;
},
createOrder() {
let shipping_type = this.shipping_type;
if (!this.active) return this.$dialog.toast({ mes: "请选择支付方式" });
if (!this.addressInfo.id && !this.shipping_type)
return this.$dialog.toast({ mes: "请选择收货地址" });
if (this.shipping_type) {
if (
(this.contacts === "" || this.contactsTel === "") &&
this.shipping_type
)
return this.$dialog.toast({ mes: "请填写联系人或联系人电话" });
if (!/^1(3|4|5|7|8|9|6)\d{9}$/.test(this.contactsTel)) {
return this.$dialog.toast({ mes: "请填写正确的手机号" });
}
if (!/^[\u4e00-\u9fa5\w]{2,16}$/.test(this.contacts)) {
return this.$dialog.toast({ mes: "请填写您的真实姓名" });
}
}
wx.showLoading({ title: "生成订单中" });
createOrder(this.orderGroupInfo.orderKey, {
realName: this.contacts,
phone: this.contactsTel,
addressId: this.addressInfo.id,
useIntegral: this.useIntegral ? 1 : 0,
couponId: this.usableCoupon.id || 0,
payType: this.active,
pinkId: this.pinkId,
seckillId: this.orderGroupInfo.seckill_id,
combinationId: this.orderGroupInfo.combination_id,
bargainId: this.orderGroupInfo.bargain_id,
from: this.from,
mark: this.mark || "",
shippingType: parseInt(shipping_type) + 1
})
.then(res => {
wx.hideLoading();
const data = res.data;
switch (data.status) {
case "ORDER_EXIST":
case "EXTEND_ORDER":
case "PAY_DEFICIENCY":
case "PAY_ERROR":
this.$dialog.toast({ mes: res.msg });
this.$yrouter.replace({
path: "/pages/order/OrderDetails/main",
query: { id: data.result.orderId }
});
break;
case "SUCCESS":
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
this.$yrouter.replace({
path: "/pages/order/OrderDetails/main",
query: { id: data.result.orderId }
});
break;
case "WECHAT_H5_PAY":
this.$yrouter.replace({
path: "/pages/order/OrderDetails/main",
query: { id: data.result.orderId }
});
setTimeout(() => {
// location.href = data.result.jsConfig.mweb_url;
}, 100);
break;
case "WECHAT_PAY":
weappPay(data.result.jsConfig).then(res => {
this.$yrouter.replace({
path: "/pages/order/OrderDetails/main",
query: { id: data.result.orderId }
});
});
// 下面为原先微信支付方式,
// pay(data.result.jsConfig).finally(() => {
// this.$yrouter.replace({
// path: "/pages/order/OrderDetails/main" ,query: { id: data.result.orderId}
// });
// });
}
})
.catch(err => {
wx.hideLoading();
this.$dialog.error(err.response.data.msg || "创建订单失败");
});
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+34
View File
@@ -0,0 +1,34 @@
<template>
<div class="payment-status">
<!--失败时 用icon-iconfontguanbi fail替换icon-duihao2 bg-color-red-->
<div class="iconfont icon-duihao2 bg-color-red"></div>
<!-- 失败时订单支付失败 -->
<div class="status">订单支付成功</div>
<div class="wrapper">
<div class="item acea-row row-between-wrapper">
<div>订单编号</div>
<div class="itemCom">wx3265361456134568</div>
</div>
<div class="item acea-row row-between-wrapper">
<div>下单时间</div>
<div class="itemCom">2019-01-09 18:05</div>
</div>
<div class="item acea-row row-between-wrapper">
<div>支付方式</div>
<div class="itemCom">微信支付</div>
</div>
<div class="item acea-row row-between-wrapper">
<div>支付金额</div>
<div class="itemCom">2222.00</div>
</div>
<!--失败时加上这个 -->
<!--<div class='item acea-row row-between-wrapper'>-->
<!--<div>失败原因</div>-->
<!--<div class='itemCom'>账户余额不足</div>-->
<!--</div>-->
</div>
<!--失败时 重新购买 -->
<div class="returnBnt bg-color-red">返回查看订单</div>
<div class="returnBnt cart-color">返回首页</div>
</div>
</template>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+93
View File
@@ -0,0 +1,93 @@
<template>
<div class="return-list" ref="container">
<div class="goodWrapper" v-for="(order,orderListIndex) in orderList" :key="orderListIndex">
<div class="iconfont icon-tuikuanzhong powder" v-if="order._status._type === -1"></div>
<div class="iconfont icon-yituikuan" v-if="order._status._type === -2"></div>
<div class="orderNum">订单号{{ order.orderId }}</div>
<div
class="item acea-row row-between-wrapper"
v-for="(cart,cartInfoIndex) in order.cartInfo"
:key="cartInfoIndex"
@click="$yrouter.push({ path: '/pages/order/OrderDetails/index',query:{id:order.orderId} })"
>
<div class="pictrue">
<img
:src="cart.productInfo.image"
class="image"
@click.stop="
$yrouter.push({ path: '/pages/shop/GoodsCon/index',query: { id: cart.productInfo.id } })
"
/>
</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="attr line1" v-else>{{ cart.productInfo.storeName }}</div>
<div class="money">{{ cart.productInfo.price }}</div>
</div>
</div>
<div class="totalSum">
{{ order.cartInfo.length || 0 }}件商品总金额
<span
class="font-color-red price"
>{{ order.payPrice }}</span>
</div>
</div>
<div class="noCart" v-if="orderList.length === 0 && page > 1">
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/noOrder.png'" />
</div>
</div>
<Loading :loaded="loaded" :loading="loading"></Loading>
</div>
</template>
<script>
import { getOrderList } from "@/api/order";
import Loading from "@/components/Loading";
export default {
name: "ReturnList",
components: {
Loading
},
data() {
return {
orderList: [],
page: 1,
limit: 20,
loading: false,
loaded: false
};
},
methods: {
getOrderList() {
const { page, limit } = this;
if (this.loading || this.loaded) return;
this.loading = true;
getOrderList({
page,
limit,
type: -3
}).then(res => {
this.orderList = this.orderList.concat(res.data);
this.loading = false;
this.loaded = res.data.length < limit;
this.page++;
});
}
},
mounted() {
this.getOrderList();
},
onReachBottom() {
!this.loading && this.getOrderList();
},
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+352
View File
@@ -0,0 +1,352 @@
<template>
<div class="order-details pos-order-details">
<div class="header acea-row row-middle">
<div class="state">{{ title }}</div>
<div class="data">
<div class="order-num">订单{{ orderInfo.orderId }}</div>
<div>
<span class="time">
<data-format :data="orderInfo.addTime"></data-format>
</span>
</div>
</div>
</div>
<div class="orderingUser acea-row row-middle">{{ orderInfo.nickname }}</div>
<div class="address">
<div class="name">
{{ orderInfo.realName}}
<span class="phone">{{ orderInfo.userPhone }}</span>
</div>
<div>{{ orderInfo.userAddress }}</div>
</div>
<div class="line">
<img :src="$VUE_APP_RESOURCES_URL+'/images/line.jpg'" />
</div>
<div class="pos-order-goods">
<div
class="goods acea-row row-between-wrapper"
v-for="(item, orderInfoIndex) in orderInfo.cartInfo"
:key="orderInfoIndex"
>
<div class="picTxt acea-row row-between-wrapper">
<div class="pictrue">
<img :src="item.productInfo.image" />
</div>
<div class="text acea-row row-between row-column">
<div class="info line2">{{ item.productInfo.storeName }}</div>
<div class="attr">{{ item.productInfo.suk }}</div>
</div>
</div>
<div class="money">
<div class="x-money">{{ item.productInfo.price }}</div>
<div class="num">x{{ item.cartNum }}</div>
<div class="y-money">{{ item.productInfo.otPrice ? item.productInfo.otPrice : 0 }}</div>
</div>
</div>
</div>
<div class="public-total">
{{ orderInfo.totalNum }}件商品应支付
<span class="money">{{ orderInfo.payPrice }}</span>
( 邮费 ¥{{
orderInfo.payPostage
}}
)
</div>
<div class="wrapper">
<div class="item acea-row row-between">
<div>订单编号</div>
<div class="conter acea-row row-middle row-right">
{{ orderInfo.orderId
}}
<span
class="copy copy-data"
@click="copyClipboard(orderInfo.orderId)"
>复制</span>
</div>
</div>
<div class="item acea-row row-between">
<div>下单时间</div>
<div class="conter">
<data-format :data="orderInfo.addTime"></data-format>
</div>
</div>
<div class="item acea-row row-between">
<div>支付状态</div>
<div class="conter">{{ orderInfo.paid == 1 ? "已支付" : "未支付" }}</div>
</div>
<div class="item acea-row row-between">
<div>支付方式</div>
<div class="conter">{{ payType }}</div>
</div>
<div class="item acea-row row-between">
<div>买家留言</div>
<div class="conter">{{ orderInfo.mark }}</div>
</div>
</div>
<div class="wrapper">
<div class="item acea-row row-between">
<div>支付金额</div>
<div class="conter">{{ orderInfo.totalPrice }}</div>
</div>
<div class="item acea-row row-between">
<div>优惠券抵扣</div>
<div class="conter">-{{ orderInfo.couponPrice }}</div>
</div>
<div class="actualPay acea-row row-right">
实付款
<span class="money font-color-red">{{ orderInfo.payPrice }}</span>
</div>
</div>
<div
class="wrapper"
v-if="orderInfo.delivery_type != 'fictitious' && orderInfo._status._type === 2"
>
<div class="item acea-row row-between">
<div>配送方式</div>
<div class="conter" v-if="orderInfo.delivery_type === 'express'">快递</div>
<div class="conter" v-if="orderInfo.delivery_type === 'send'">送货</div>
</div>
<div class="item acea-row row-between">
<div v-if="orderInfo.delivery_type === 'express'">快递公司</div>
<div v-if="orderInfo.delivery_type === 'send'">送货人</div>
<div class="conter">{{ orderInfo.delivery_name }}</div>
</div>
<div class="item acea-row row-between">
<div v-if="orderInfo.delivery_type === 'express'">快递单号</div>
<div v-if="orderInfo.delivery_type === 'send'">送货人电话</div>
<div class="conter">
{{ orderInfo.delivery_id
}}
<span
class="copy copy-data"
@click="copyClipboard(orderInfo.delivery_id)"
>复制</span>
</div>
</div>
</div>
<div style="height:100rpx;"></div>
<div class="footer acea-row row-right row-middle">
<div class="more"></div>
<div class="bnt cancel" @click="modify(0)" v-if="types == 0">一键改价</div>
<div class="bnt cancel" @click="modify(0)" v-if="types == -1">立即退款</div>
<div
class="bnt cancel"
v-if="orderInfo.pay_type === 'offline' && orderInfo.paid === 0"
@click="offlinePay"
>确认付款</div>
<div
class="bnt delivery"
v-if="types == 1"
@click="$yrouter.push({path:'/pages/orderAdmin/GoodsDeliver/index',query: { id : orderInfo.orderId}})"
>去发货</div>
</div>
<PriceChange
:change="change"
:orderInfo="orderInfo"
v-on:closechange="changeclose($event)"
v-on:savePrice="savePrice"
:status="status"
></PriceChange>
</div>
</template>
<script>
import PriceChange from "@/components/PriceChange";
import DataFormat from "@/components/DataFormat";
import {
getAdminOrderDetail,
setAdminOrderPrice,
setAdminOrderRemark,
setOfflinePay,
setOrderRefund
} from "@/api/admin";
import { required, num } from "@/utils/validate";
import { validatorDefaultCatch } from "@/utils/dialog";
import { copyClipboard } from "@/utils";
export default {
name: "AdminOrder",
components: {
PriceChange,
DataFormat
},
props: {},
data: function() {
return {
order: false,
change: false,
order_id: "",
orderInfo: {
_status: {}
},
status: "",
title: "",
payType: "",
types: ""
};
},
watch: {
"$yroute.query.oid": function(newVal) {
let that = this;
if (newVal != undefined) {
that.order_id = newVal;
that.getIndex();
}
}
},
mounted: function() {
this.order_id = this.$yroute.query.oid;
this.getIndex();
},
methods: {
copyClipboard,
more: function() {
this.order = !this.order;
},
modify: function(status) {
this.change = true;
this.status = status;
},
changeclose: function(msg) {
this.change = msg;
},
getIndex: function() {
let that = this;
getAdminOrderDetail(that.order_id).then(
res => {
that.orderInfo = res.data;
that.types = res.data._status._type;
that.title = res.data._status._title;
that.payType = res.data._status._payType;
},
err => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
}
);
},
async savePrice(opt) {
let that = this,
data = {},
price = opt.price,
remark = opt.remark,
refund_price = opt.refund_price.toString();
data.orderId = that.orderInfo.orderId;
if (that.status == 0 && that.orderInfo.refundStatus === 0) {
try {
await this.$validator({
price: [
required(required.message("金额")),
num(num.message("金额"))
]
}).validate({ price });
} catch (e) {
return validatorDefaultCatch(e);
}
data.price = price;
setAdminOrderPrice(data).then(
function() {
that.change = false;
wx.showToast({
title: "改价成功",
icon: "success",
duration: 2000
});
that.getIndex();
},
function() {
that.change = false;
wx.showToast({
title: "改价失败",
icon: "none",
duration: 2000
});
}
);
} else if (that.status == 0 && that.orderInfo.refundStatus === 1) {
try {
await this.$validator({
refund_price: [
required(required.message("金额")),
num(num.message("金额"))
]
}).validate({ refund_price });
} catch (e) {
return validatorDefaultCatch(e);
}
data.price = refund_price;
data.type = opt.type;
setOrderRefund(data).then(
res => {
that.change = false;
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.getIndex();
},
err => {
that.change = false;
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.getIndex();
}
);
} else {
try {
await this.$validator({
remark: [required(required.message("备注"))]
}).validate({ remark });
} catch (e) {
return validatorDefaultCatch(e);
}
data.remark = remark;
setAdminOrderRemark(data).then(
res => {
that.change = false;
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.getIndex();
},
err => {
that.change = false;
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
}
);
}
},
offlinePay: function() {
setOfflinePay({ order_id: this.orderInfo.order_id }).then(
res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
this.getIndex();
},
err => {
wx.showToast({
title: err.msg,
icon: "none",
duration: 2000
});
}
);
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+316
View File
@@ -0,0 +1,316 @@
<template>
<div class="pos-order-list" ref="container">
<div class="nav acea-row row-around row-middle">
<div class="item" :class="where.status == 0 ? 'on' : ''" @click="changeStatus(0)">待付款</div>
<div class="item" :class="where.status == 1 ? 'on' : ''" @click="changeStatus(1)">待发货</div>
<div class="item" :class="where.status == 2 ? 'on' : ''" @click="changeStatus(2)">待收货</div>
<div class="item" :class="where.status == 3 ? 'on' : ''" @click="changeStatus(3)">待评价</div>
<div class="item" :class="where.status == 4 ? 'on' : ''" @click="changeStatus(4)">已完成</div>
<div class="item" :class="where.status == -3 ? 'on' : ''" @click="changeStatus(-3)">退款</div>
</div>
<div class="list">
<div class="item" v-for="(item, listIndex) in list" :key="listIndex">
<div class="order-num acea-row row-middle" @click="toDetail(item)">
<span>订单号{{ item.orderId }}</span>
<span class="time">
<span>下单时间</span>
<data-format :data="item.addTime"></data-format>
</span>
</div>
<div class="pos-order-goods" v-for="(val, key) in item.cartInfo" :key="key">
<div class="goods acea-row row-between-wrapper" @click="toDetail(item)">
<div class="picTxt acea-row row-between-wrapper">
<div class="pictrue">
<img :src="val.productInfo.image" />
</div>
<div class="text acea-row row-between row-column">
<div class="info line2">{{ val.productInfo.storeName }}</div>
<div class="attr" v-if="val.productInfo.suk">{{ val.productInfo.suk }}</div>
</div>
</div>
<div class="money">
<div class="x-money">{{ val.productInfo.price }}</div>
<div class="num">x{{ val.cartNum }}</div>
<div class="y-money">{{ val.productInfo.otPrice }}</div>
</div>
</div>
</div>
<div class="public-total">
{{ item.totalNum }}件商品应支付
<span class="money">{{ item.payPrice }}</span>
( 邮费 ¥{{
item.totalPostage
}}
)
</div>
<div class="operation acea-row row-between-wrapper">
<div class="more">
<!-- <div class="iconfont icon-gengduo" @click="more(index)"></div>-->
<!-- <div class="order" v-show="current === index">-->
<!-- <div class="items">-->
<!-- {{ where.status > 0 ? "删除" : "取消" }}订单-->
<!-- </div>-->
<!-- <div class="arrow"></div>-->
<!-- </div>-->
</div>
<div class="acea-row row-middle">
<div class="bnt" @click="modify(item, 0)" v-if="where.status == 0">一键改价</div>
<div
class="bnt"
@click="modify(item, 0)"
v-if="where.status == -3 && item.refundStatus === 1"
>立即退款</div>
<div
class="bnt cancel"
v-if="item.pay_type === 'offline' && item.paid === 0"
@click="offlinePay(item)"
>确认付款</div>
<div
class="bnt"
v-if="where.status == 1"
@click="$yrouter.push({path:'/pages/orderAdmin/GoodsDeliver/index',query: { id:item.orderId }})"
>去发货</div>
</div>
</div>
</div>
</div>
<Loading :loaded="loaded" :loading="loading"></Loading>
<PriceChange
:change="change"
:orderInfo="orderInfo"
v-on:closechange="changeclose($event)"
v-on:savePrice="savePrice"
:status="status"
></PriceChange>
</div>
</template>
<script>
import PriceChange from "@/components/PriceChange";
import Loading from "@/components/Loading";
import DataFormat from "@/components/DataFormat";
import {
getAdminOrderList,
setAdminOrderPrice,
setAdminOrderRemark,
setOfflinePay,
setOrderRefund
} from "@/api/admin";
import { required, num } from "@/utils/validate";
import { validatorDefaultCatch } from "@/utils/dialog";
export default {
name: "AdminOrderList",
components: {
PriceChange,
Loading,
DataFormat
},
props: {},
data: function() {
return {
current: "",
change: false,
types: 0,
where: {
page: 1,
limit: 5,
status: 0
},
list: [],
loaded: false,
loading: false,
orderInfo: {},
status: ""
};
},
watch: {
"$yroute.query.types": function(newVal) {
let that = this;
if (newVal != undefined) {
that.where.status = newVal;
that.init();
}
},
types: function() {
this.getIndex();
}
},
mounted: function() {
let that = this;
that.where.status = that.$yroute.query.types;
that.current = "";
that.getIndex();
},
onReachBottom() {
!that.loading && that.getIndex();
},
methods: {
more: function(index) {
if (this.current === index) this.current = "";
else this.current = index;
},
modify: function(item, status) {
this.change = true;
this.orderInfo = item;
this.status = status;
},
changeclose: function(msg) {
this.change = msg;
},
async savePrice(opt) {
let that = this,
data = {},
price = opt.price.toString(),
refund_price = opt.refund_price.toString(),
refund_status = that.orderInfo.refundStatus,
remark = opt.remark;
data.orderId = that.orderInfo.orderId;
if (that.status == 0 && refund_status === 0) {
try {
await this.$validator({
price: [
required(required.message("金额")),
num(num.message("金额"))
]
}).validate({ price });
} catch (e) {
return validatorDefaultCatch(e);
}
data.price = price;
setAdminOrderPrice(data).then(
function() {
that.change = false;
wx.showToast({
title: "改价成功",
icon: "success",
duration: 2000
});
that.init();
},
function() {
that.change = false;
wx.showToast({
title: "改价失败",
icon: "none",
duration: 2000
});
}
);
} else if (that.status == 0 && refund_status === 1) {
try {
await this.$validator({
refund_price: [
required(required.message("金额")),
num(num.message("金额"))
]
}).validate({ refund_price });
} catch (e) {
return validatorDefaultCatch(e);
}
data.price = refund_price;
data.type = opt.type;
setOrderRefund(data).then(
res => {
that.change = false;
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.init();
},
err => {
that.change = false;
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
}
);
} else {
try {
await this.$validator({
remark: [required(required.message("备注"))]
}).validate({ remark });
} catch (e) {
return validatorDefaultCatch(e);
}
data.remark = remark;
setAdminOrderRemark(data).then(
res => {
that.change = false;
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.init();
},
err => {
that.change = false;
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
}
);
}
},
init: function() {
this.list = [];
this.where.page = 1;
this.loaded = false;
this.loading = false;
this.getIndex();
this.current = "";
},
getIndex: function() {
let that = this;
if (that.loading || that.loaded) return;
that.loading = true;
getAdminOrderList(that.where).then(
res => {
that.loading = false;
that.loaded = res.data.length < that.where.limit;
that.list.push.apply(that.list, res.data);
that.where.page = that.where.page + 1;
},
err => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
}
);
},
changeStatus: function(val) {
if (this.where.status != val) {
this.where.status = val;
this.init();
}
},
toDetail: function(item) {
this.$yrouter.push({
path: "/pages/orderAdmin/AdminOrder/main",
query: { oid: item.orderId }
});
},
offlinePay: function(item) {
setOfflinePay({ order_id: item.order_id }).then(
res => {
this.$wx.showToast({ title: res.msg, icon: "none", duration: 2000 });
this.init();
},
error => {
this.$dialog.error(error.msg);
}
);
}
}
};
</script>
<style>
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+206
View File
@@ -0,0 +1,206 @@
<template>
<div class="deliver-goods">
<header>
<div class="order-num acea-row row-between-wrapper">
<div class="num line1">订单号{{ delivery.orderId }}</div>
<div class="name line1">{{ delivery.nickname }}</div>
</div>
<div class="address">
<div class="name">
{{ delivery.realName
}}
<span class="phone">{{ delivery.userPhone }}</span>
</div>
<div>{{ delivery.userAddress }}</div>
</div>
<div class="line">
<img :src="$VUE_APP_RESOURCES_URL+'/images/line.jpg'" />
</div>
</header>
<div class="wrapper">
<div class="item acea-row row-between-wrapper">
<div>发货方式</div>
<div class="mode acea-row row-middle row-right">
<div
class="goods"
:class="active === typesIndex ? 'on' : ''"
v-for="(item, typesIndex) in types"
:key="typesIndex"
@click="changeType(item, typesIndex)"
>
{{ item.title }}
<span class="iconfont icon-xuanzhong2"></span>
</div>
</div>
</div>
<div class="list" v-show="active === 0">
<div class="item acea-row row-between-wrapper">
<div>快递公司</div>
<input type="text" placeholder="填写快递公司" v-model="delivery_name" class="mode" />
</div>
<div class="item acea-row row-between-wrapper">
<div>快递单号</div>
<input type="text" placeholder="填写快递单号" v-model="delivery_id" class="mode" />
</div>
</div>
<div class="list" v-show="active === 1">
<div class="item acea-row row-between-wrapper">
<div>送货人</div>
<input type="text" placeholder="填写送货人" v-model="delivery_name" class="mode" />
</div>
<div class="item acea-row row-between-wrapper">
<div>送货电话</div>
<input type="text" placeholder="填写送货电话" v-model="delivery_id" class="mode" />
</div>
</div>
</div>
<div style="height:100rpx;"></div>
<div class="confirm" @click="saveInfo">确认提交</div>
</div>
</template>
<script>
import { getAdminOrderDelivery, setAdminOrderDelivery } from "@/api/admin";
import { getLogistics } from "@/api/public";
import { required } from "@/utils/validate";
import { validatorDefaultCatch } from "@/utils/dialog";
export default {
name: "GoodsDeliver",
components: {},
props: {},
data: function() {
return {
types: [
{
type: "express",
title: "发货"
}
// {
// type: "send",
// title: "送货"
// },
// {
// type: "fictitious",
// title: "无需发货"
// }
],
active: 0,
order_id: "",
delivery: [],
logistics: [],
delivery_type: "express",
delivery_name: "",
delivery_id: ""
};
},
watch: {
"$yroute.query.oid": function(newVal) {
let that = this;
if (newVal != undefined) {
that.order_id = newVal;
that.getIndex();
}
}
},
mounted: function() {
this.order_id = this.$yroute.query.oid;
this.getIndex();
//this.getLogistics();
},
methods: {
changeType: function(item, index) {
this.active = index;
this.delivery_type = item.type;
this.delivery_name = "";
this.delivery_id = "";
},
getIndex: function() {
let that = this;
getAdminOrderDelivery(that.order_id).then(
res => {
that.delivery = res.data;
},
error => {
wx.showToast({
title: error.msg,
icon: "none",
duration: 2000
});
}
);
},
getLogistics: function() {
let that = this;
getLogistics().then(
res => {
that.logistics = res.data;
},
error => {
wx.showToast({
title: error.msg,
icon: "none",
duration: 2000
});
}
);
},
async saveInfo() {
let that = this,
delivery_type = that.delivery_type,
delivery_name = that.delivery_name,
delivery_id = that.delivery_id,
save = {};
save.orderId = that.order_id;
save.deliveryType = that.delivery_type;
switch (delivery_type) {
case "send":
try {
await this.$validator({
delivery_name: [required(required.message("快递公司"))],
delivery_id: [required(required.message("快递单号"))]
}).validate({ delivery_name, delivery_id });
} catch (e) {
return validatorDefaultCatch(e);
}
save.delivery_name = delivery_name;
save.delivery_id = delivery_id;
that.setInfo(save);
break;
case "express":
try {
await this.$validator({
delivery_name: [required(required.message("发货人姓名"))],
delivery_id: [required(required.message("发货人电话"))]
}).validate({ delivery_name, delivery_id });
} catch (e) {
return validatorDefaultCatch(e);
}
save.deliveryName = delivery_name;
save.deliveryId = delivery_id;
that.setInfo(save);
break;
}
},
setInfo: function(item) {
let that = this;
setAdminOrderDelivery(item).then(
res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.$yrouter.go(-1);
},
error => {
wx.showToast({
title: error.msg,
icon: "none",
duration: 2000
});
}
);
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
@@ -0,0 +1,161 @@
<template>
<div class="OrderCancellation">
<div class="header"></div>
<div class="whiteBg">
<div class="input">
<input type="number" placeholder="0" v-model="verify_code" />
</div>
<div class="bnt" @click="storeCancellation">立即核销</div>
</div>
<div class="scan" v-if="iswechat">
<img :src="$VUE_APP_RESOURCES_URL+'/images/scan.gif'" @click="openQRCode" />
</div>
<WriteOff :iShidden="iShidden" :orderInfo="orderInfo" @cancel="cancel" @confirm="confirm"></WriteOff>
</div>
</template>
<style scoped>
.OrderCancellation .header {
background: url("https://h5.dayouqiantu.cn/static/images/writeOffBg.jpg") no-repeat;
width: 100%;
height: 3rem;
background-size: 100% 100%;
}
.OrderCancellation .whiteBg {
width: 6.9rem;
background-color: #fff;
margin: -0.93rem auto 0 auto;
padding-top: 0.8rem;
border-radius: 0.06rem 0.06rem 0 0;
}
.OrderCancellation .whiteBg .input {
width: 5.8rem;
margin: 0 auto;
border-bottom: 0.01rem solid #eee;
}
.OrderCancellation .whiteBg .input input {
padding-bottom: 0.25rem;
font-size: 0.6rem;
color: #282828;
width: 100%;
text-align: center;
}
.OrderCancellation .whiteBg .bnt {
font-size: 0.32rem;
color: #fff;
width: 5.8rem;
height: 0.86rem;
border-radius: 0.43rem;
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%);
text-align: center;
line-height: 0.86rem;
margin: 0.55rem auto 0 auto;
}
.OrderCancellation .scan {
width: 3rem;
height: 3rem;
margin: 1.1rem auto 0 auto;
}
.OrderCancellation .scan img {
width: 100%;
height: 100%;
display: block;
}
</style>
<script>
import WriteOff from "@/components/WriteOff";
import { isWeixin } from "@/utils";
// import { wechatEvevt } from "@/libs/wechat";
import { orderVerific } from "@/api/order";
const NAME = "OrderCancellation";
export default {
name: NAME,
components: {
WriteOff
},
props: {},
data: function() {
return {
iShidden: true,
iswechat: isWeixin(),
orderInfo: {},
verify_code: ""
};
},
mounted: function() {},
methods: {
cancel: function(res) {
this.iShidden = res;
},
confirm: function() {
orderVerific(this.verify_code, 1)
.then(res => {
this.iShidden = true;
this.verify_code = "";
this.$wx.showToast({ title: res.msg, icon: 'none', duration: 2000 });
})
.catch(res => {
this.$dialog.error(res.msg);
});
},
storeCancellation: function() {
let ref = /[0-9]{12}/;
if (!this.verify_code) return this.$dialog.error("请输入核销码");
if (!ref.test(this.verify_code))
return this.$dialog.error("请输入正确的核销码");
wx.showLoading({ title: "查询中" });
orderVerific(this.verify_code, 0)
.then(res => {
wx.hideLoading();
this.orderInfo = res.data;
this.iShidden = false;
})
.catch(() => {
wx.hideLoading();
});
},
openQRCode: function() {
let that = this;
// wechatEvevt("scanQRCode", {
// needResult: 1,
// scanType: ["qrCode", "barCode"]
// })
// .then(res => {
// if (res.resultStr) {
// that.verify_code = res.resultStr;
// that.storeCancellation();
// } else {
// wx.showToast({
// title: '没有扫描到什么!',
// icon: "none",
// duration: 2000
// });
// }
// })
// .catch(res => {
// if (res.is_ready) {
// res.wx.scanQRCode({
// needResult: 1,
// scanType: ["qrCode", "barCode"],
// success: function(res) {
// that.verify_code = res.resultStr;
// that.storeCancellation();
// },
// fail: function(res) {
// if (res.errMsg == "scanQRCode:permission denied") {
// wx.showToast({
// title: '没有权限',
// icon: "none",
// duration: 2000
// });
// }
// }
// });
// }
// });
}
}
};
</script>
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+176
View File
@@ -0,0 +1,176 @@
<template>
<div class="order-index" ref="container">
<div class="header acea-row">
<div
class="item"
@click="$yrouter.push({path:'/pages/orderAdmin/AdminOrderList/index',query:{types:0}})"
>
<div class="num">{{ census.orderCount.unpaidCount }}</div>
<div>待付款</div>
</div>
<div
class="item"
@click="$yrouter.push({path:'/pages/orderAdmin/AdminOrderList/index',query:{types:1}})"
>
<div class="num">{{ census.orderCount.unshippedCount }}</div>
<div>待发货</div>
</div>
<div
class="item"
@click="$yrouter.push({path:'/pages/orderAdmin/AdminOrderList/index',query:{types:2}})"
>
<div class="num">{{ census.orderCount.receivedCount }}</div>
<div>待收货</div>
</div>
<div
class="item"
@click="$yrouter.push({path:'/pages/orderAdmin/AdminOrderList/index',query:{types:3}})"
>
<div class="num">{{ census.orderCount.evaluatedCount }}</div>
<div>待评价</div>
</div>
<div
class="item"
@click="$yrouter.push({path:'/pages/orderAdmin/AdminOrderList/index',query:{types:3}})"
>
<div class="num">{{ census.orderCount.refundCount }}</div>
<div>退款</div>
</div>
</div>
<div class="wrapper">
<div class="title">
<span class="iconfont icon-shujutongji"></span>数据统计
</div>
<div class="list acea-row">
<div
class="item"
@click="$yrouter.push({path:'/pages/orderAdmin/Statistics/index',query:{type:'price',time:'today'}})"
>
<div class="num">{{ census.orderTimeCount.todayPrice }}</div>
<div>今日成交额</div>
</div>
<div
class="item"
@click="$yrouter.push({path:'/pages/orderAdmin/Statistics/index',query:{type:'price',time:'yesterday'}})"
>
<div class="num">{{ census.orderTimeCount.proPrice }}</div>
<div>昨日成交额</div>
</div>
<div
class="item"
@click="$yrouter.push({path:'/pages/orderAdmin/Statistics/index',query:{type:'price',time:'month'}})"
>
<div class="num">{{ census.orderTimeCount.monthPrice }}</div>
<div>本月成交额</div>
</div>
<div
class="item"
@click="$yrouter.push({path:'/pages/orderAdmin/Statistics/index',query:{type:'order',time:'today'}})"
>
<div class="num">{{ census.orderTimeCount.todayCount }}</div>
<div>今日订单数</div>
</div>
<div
class="item"
@click="$yrouter.push({path:'/pages/orderAdmin/Statistics/index',query:{type:'order',time:'yesterday'}})"
>
<div class="num">{{ census.orderTimeCount.proCount }}</div>
<div>昨日订单数</div>
</div>
<div
class="item"
@click="$yrouter.push({path:'/pages/orderAdmin/Statistics/index',query:{type:'order',time:'month'}})"
>
<div class="num">{{ census.orderTimeCount.monthCount }}</div>
<div>本月订单数</div>
</div>
</div>
</div>
<div class="public-wrapper">
<div class="title">
<span class="iconfont icon-xiangxishuju"></span>详细数据
</div>
<div class="nav acea-row row-between-wrapper">
<div class="data">日期</div>
<div class="browse">订单数</div>
<div class="turnover">成交额</div>
</div>
<div class="conter">
<div
class="item acea-row row-between-wrapper"
v-for="(item, orderListIndex) in list"
:key="orderListIndex"
>
<div class="data">{{ item.time }}</div>
<div class="browse">{{ item.count }}</div>
<div class="turnover">{{ item.price }}</div>
</div>
</div>
</div>
<Loading :loaded="loaded" :loading="loading"></Loading>
</div>
</template>
<script>
import { getStatisticsInfo, getStatisticsMonth } from "@/api/admin";
import Loading from "@/components/Loading";
export default {
name: "OrderIndex",
components: {
Loading
},
props: {},
data: function() {
return {
census: {
orderCount: {},
orderTimeCount: {}
},
list: [],
where: {
page: 1,
limit: 15
},
loaded: false,
loading: false
};
},
mounted: function() {
this.getIndex();
this.getList();
},
onReachBottom() {
!this.loading && this.getList();
},
methods: {
getIndex: function() {
var that = this;
getStatisticsInfo().then(
res => {
that.census = res.data;
that.census.unpaidCount = that.census.orderCount.unpaidCount;
},
err => {
that.$dialog.message(err.msg);
}
);
},
getList: function() {
var that = this;
if (that.loading || that.loaded) return;
that.loading = true;
getStatisticsMonth(that.where).then(
res => {
that.loading = false;
that.loaded = res.data.length < that.where.limit;
that.list.push.apply(that.list, res.data);
that.where.page = that.where.page + 1;
},
error => {
that.$dialog.message(error.msg);
},
300
);
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+432
View File
@@ -0,0 +1,432 @@
<template>
<div class="statistical-page" ref="container">
<div class="navs">
<div class="list">
<div class="item" :class="time == 'today' ? 'on' : ''" @click="setTime('today')">今天</div>
<div class="item" :class="time == 'yesterday' ? 'on' : ''" @click="setTime('yesterday')">昨天</div>
<div class="item" :class="time == 'seven' ? 'on' : ''" @click="setTime('seven')">最近7天</div>
<div class="item" :class="time == 'month' ? 'on' : ''" @click="setTime('month')">本月</div>
</div>
</div>
<div class="wrapper">
<div class="title">{{ title }}{{ this.where.type == 1 ? "营业额(元)" : "订单量(份)" }}</div>
<div class="money">{{ time_price }}</div>
</div>
<!-- <div class="chart">
<div class="company">{{ where.type === 1 ? "单位(元)" : "单位(份)" }}</div>
<ECharts :options="polar"></ECharts>
</div> -->
<div class="public-wrapper">
<div class="title">
<span class="iconfont icon-xiangxishuju"></span>详细数据
</div>
<div class="nav acea-row row-between-wrapper">
<div class="data">日期</div>
<div class="browse">订单量</div>
<div class="turnover">成交额</div>
</div>
<div class="conter">
<div
class="item acea-row row-between-wrapper"
v-for="(item, statisticalIndex) in list"
:key="statisticalIndex"
>
<div class="data">{{ item.time }}</div>
<div class="browse">{{ item.count }}</div>
<div class="turnover">{{ item.price }}</div>
</div>
</div>
</div>
<!-- <div class="calendar-wrapper" :class="current === true ? 'on' : ''">
<div class="calendar">
<Calendar
:clean="clean"
:lunar="lunar"
ref="calendar"
:range="isrange"
:multi="ismulti"
@select="select"
@next="next"
@prev="prev"
:value="value"
:weekSwitch="weekSwitch"
:monthRange="monthRange"
rangeMonthFormat="yyyy年MM月"
monFirst
responsive
:begin="[1992, 5, 20]"
:end="[2049, 5, 20]"
/>
</div>
</div> -->
<div class="mask" @touchmove.prevent v-show="current === true" @click="close"></div>
<Loading :loaded="loaded" :loading="loading"></Loading>
</div>
</template>
<script>
// import ECharts from "vue-echarts";
// import "echarts/lib/chart/line";
// import "echarts/lib/component/polar";
// import Calendar from "mpvue-calendar";
// import "mpvue-calendar/src/browser-style.css";
import { getStatisticsMonth, getStatisticsTime } from "@/api/admin";
import Loading from "@/components/Loading";
const year = new Date().getFullYear();
const month = new Date().getMonth() + 1;
const day = new Date().getDate();
export default {
name: "Statistics",
components: {
// ECharts,
// Calendar,
Loading
},
props: {},
data: function() {
return {
polar: {
tooltip: {
trigger: "axis"
},
legend: {
data: [""]
},
toolbox: {
show: false,
feature: {
mark: { show: true },
dataView: { show: true, readOnly: false },
magicType: { show: true, type: ["line"] },
restore: { show: true },
saveAsImage: { show: true }
}
},
calculable: true,
xAxis: [
{
type: "category",
boundaryGap: false,
data: ["周一", "周二", "周三", "周四", "周五", "周六", "周日"],
splitLine: {
show: false
},
axisLine: {
lineStyle: {
color: "#999",
width: 1 //这里是为了突出显示加上的
}
}
}
],
yAxis: [
{
type: "value",
splitLine: {
show: true,
lineStyle: {
color: ["#f5f5f5"],
width: 1,
type: "solid"
}
},
axisLine: {
lineStyle: {
color: "#999",
width: 1 //这里是为了突出显示加上的
}
}
}
],
series: [
{
name: "邮件营销",
type: "line",
stack: "总量",
itemStyle: {
normal: {
color: "#2291f8", //折点颜色
lineStyle: {
color: "#2291f8" //折线颜色
}
}
},
data: [120, 132.5, 101, 134, 90, 150, 30]
}
],
grid: {
x: 30,
x2: 10,
y: 20,
y2: 110
},
animationDuration: 2000
},
value: [[year, month, day - 1], [year, month, day]],
isrange: true,
weekSwitch: false,
ismulti: false,
monFirst: true,
clean: false, //简洁模式
lunar: false, //显示农历
renderValues: [],
monthRange: [],
current: false,
where: {
start: "",
stop: "",
type: "",
cate: 1
},
types: "", //类型|order=订单数|price=营业额
time: "", //时间|today=今天|yesterday=昨天|month=本月
title: "", //时间|today=今天|yesterday=昨天|month=本月
growth_rate: "", //增长率
increase_time: "", //增长率
increase_time_status: "", //增长率
time_price: "", //增长率
loaded: false,
loading: false,
filter: {
page: 1,
limit: 10
},
list: []
};
},
watch: {
"$yroute.params": function(newVal) {
var that = this;
if (newVal != undefined) {
that.setType(newVal.type);
that.setTime(newVal.time);
that.getIndex();
}
}
},
mounted: function() {
this.handelRenderValues();
this.setTime(this.$yroute.query.time);
this.setType(this.$yroute.query.type);
// this.getIndex();
this.getInfo();
},
onReachBottom() {
!this.loading && this.getInfo();
},
computed: {
monthRangeText() {
return this.monthRange.length ? "固定" : "指定范围";
}
},
methods: {
getIndex: function() {
var that = this;
getStatisticsTime(that.where).then(
res => {
var _info = res.data.chart,
day = [],
num = [];
_info.forEach(function(item) {
day.push(item.time);
num.push(item.num);
});
that.polar.xAxis[0].data = day;
that.polar.series[0].data = num;
that.growth_rate = res.data.growth_rate;
that.increase_time = res.data.increase_time;
that.increase_time_status = res.data.increase_time_status;
that.time_price = res.data.time;
},
error => {
wx.showToast({
title: error.msg,
icon: "none",
duration: 2000
});;
}
);
},
setTime: function(time) {
this.time = time;
var year = new Date().getFullYear(),
month = new Date().getMonth() + 1,
day = new Date().getDate();
switch (time) {
case "today":
this.where.cate = 1;
this.title = "今日";
this.getIndex();
break;
case "yesterday":
this.where.cate = 2;
this.title = "昨日";
this.getIndex();
break;
case "month":
this.where.cate = 4;
this.title = "本月";
this.getIndex();
break;
case "seven":
this.where.cate = 3;
this.title = "七日";
this.getIndex();
break;
}
},
setType: function(type) {
switch (type) {
case "price":
this.where.type = 1;
break;
case "order":
this.where.type = 2;
break;
}
},
clickSomeThing(data) {
this.value = [[2019, 4, 1], [2019, 4, 8]];
},
setMonthRange() {
this.monthRange = this.monthRange.length ? [] : ["2019-4", "2020-1"];
},
switchMode() {
this.weekSwitch = !this.weekSwitch;
setTimeout(() => {
// this.$refs.calendar.renderer(2019, 1); //渲染2018年8月份
}, 0);
},
handelRenderValues(data) {
if (this.ismulti) {
this.renderValues = this.value.map(v => v.join("-"));
} else if (this.isrange) {
const values = [];
data || this.value;
this.value.forEach((v, i) => {
values.push(v.join("-"));
if (!i) {
values.push("~");
}
});
this.renderValues = values;
} else {
this.renderValues = [this.value.join("-")];
}
},
multiMode() {
this.ismulti = true;
this.isrange = false;
this.value = [[year, month, 16], [year, month, 18]];
this.handelRenderValues();
// this.$refs.calendar.renderer(year, month);
},
rangeMode() {
this.ismulti = false;
this.isrange = true;
this.value = [[year, month, 16], [year, month, 22]];
this.handelRenderValues();
// this.$refs.calendar.renderer(year, month);
},
valueMode() {
this.ismulti = false;
this.isrange = false;
this.value = [year, month, 16];
this.handelRenderValues();
// this.$refs.calendar.renderer(year, month);
},
selectMonth(month, year) {
},
prev(y, m, w) {
},
next(year, month, week) {
},
selectYear(year) {
},
setToday() {
// this.$refs.calendar.setToday();
},
dateInfo() {
// const info = this.$refs.calendar.dateInfo(2018, 8, 23);
},
renderer() {
if (this.monthRange.length) {
this.monthRange = ["2018-8", "2018-8"];
}
// this.$refs.calendar.renderer(2018, 8); //渲染2018年8月份
},
select(val, val2) {
if (this.isrange) {
this.handelRenderValues([val, val2]);
} else if (this.ismulti) {
this.handelRenderValues(val);
} else {
this.handelRenderValues([val]);
}
if (
this.where.start != new Date(val) / 1000 ||
this.where.stop != new Date(val2) / 1000 + 24 * 60 * 60 - 1
) {
this.time = "date";
this.title = "";
this.where.start =
new Date(Date.parse(val[0] + "/" + val[1] + "/" + val[2])).getTime() /
1000;
this.where.stop =
new Date(
Date.parse(val2[0] + "/" + val2[1] + "/" + val2[2])
).getTime() /
1000 +
24 * 60 * 60 -
1;
this.getIndex();
}
},
dateTitle: function() {
this.current = true;
},
close: function() {
this.current = false;
},
getInfo: function() {
var that = this;
if (that.loading || that.loaded) return;
that.loading = true;
getStatisticsMonth(that.filter).then(
res => {
that.loading = false;
that.loaded = res.data.length < that.filter.limit;
that.list.push.apply(that.list, res.data);
that.filter.page = that.filter.page + 1;
},
error => {
that.$dialog.message(error.msg);
}
);
}
}
};
</script>
<style scoped>
.echarts {
width: 100%;
height: 5.5rem;
}
.calendar-wrapper {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
z-index: 66;
transform: translate3d(0, 100%, 0);
transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
}
.calendar-wrapper.on {
transform: translate3d(0, 0, 0);
}
.statistical-page .wrapper .increase {
font-size: 0.26rem;
}
.statistical-page .wrapper .increase .iconfont {
margin-left: 0;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+115
View File
@@ -0,0 +1,115 @@
<template>
<div class="evaluate-list" ref="container">
<div class="header">
<div class="generalComment acea-row row-between-wrapper">
<div class="acea-row row-middle font-color-red">
<div class="evaluate">评分</div>
<div class="start" :class="'star' + replyData.replyStar"></div>
</div>
<div>
<span class="font-color-red">{{ replyData.replyChance || 0 }}%</span
>好评率
</div>
</div>
<div class="nav acea-row row-middle">
<div
class="acea-row row-center-wrapper"
v-for="(item, navListIndex) in navList"
:key="navListIndex"
@click="changeType(navListIndex)"
>
<div
class="item"
:class="currentActive === navListIndex ? 'bg-color-red' : ''"
v-if="item.num"
>
{{ item.evaluate }}({{ item.num }})
</div>
</div>
</div>
</div>
<UserEvaluation :reply="reply"></UserEvaluation>
<Loading :loaded="loadend" :loading="loading"></Loading>
</div>
</template>
<script>
import UserEvaluation from "@/components/UserEvaluation";
import { getReplyConfig, getReplyList } from "@/api/store";
import Loading from "@/components/Loading";
export default {
name: "EvaluateList",
components: {
UserEvaluation,
Loading
},
props: {},
data: function() {
return {
product_id: 0,
replyData: {},
navList: [
{ evaluate: "全部", num: 0 },
{ evaluate: "好评", num: 0 },
{ evaluate: "中评", num: 0 },
{ evaluate: "差评", num: 0 }
],
currentActive: 0,
page: 1,
limit: 8,
reply: [],
loadTitle: "",
loading: false,
loadend: false
};
},
mounted: function() {
this.product_id = this.$yroute.query.id;
this.getProductReplyCount();
this.getProductReplyList();
},
onReachBottom() {
!this.loading && this.getProductReplyList();
},
methods: {
getProductReplyCount: function() {
let that = this;
getReplyConfig(that.product_id).then(res => {
that.$set(that, "replyData", res.data);
that.navList[0].num = res.data.sumCount;
that.navList[1].num = res.data.goodCount;
that.navList[2].num = res.data.inCount;
that.navList[3].num = res.data.poorCount;
});
},
getProductReplyList: function() {
let that = this;
if (that.loading) return; //阻止下次请求(false可以进行请求);
if (that.loadend) return; //阻止结束当前请求(false可以进行请求);
that.loading = true;
let q = { page: that.page, limit: that.limit, type: that.currentActive };
getReplyList(that.product_id, q).then(res => {
that.loading = false;
//apply();js将一个数组插入另一个数组;
that.reply.push.apply(that.reply, res.data);
that.loadend = res.data.length < that.limit; //判断所有数据是否加载完成;
that.page = that.page + 1;
});
},
changeType: function(index) {
let that = this;
that.currentActive = index;
that.page = 1;
that.loadend = false;
that.$set(that, "reply", []);
that.getProductReplyList();
}
}
};
</script>
<style scoped>
.noCommodity {
height: 8rem;
background-color: #fff;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+77
View File
@@ -0,0 +1,77 @@
<template>
<div>
<div class="searchGood">
<div class="search acea-row row-between-wrapper">
<div class="input acea-row row-between-wrapper">
<span class="iconfont icon-sousuo2"></span>
<!-- <form @submit.prevent="submit"></form> -->
<input type="text" placeholder="点击搜索商品" v-model="search" />
</div>
<div class="bnt" @click="submit">搜索</div>
</div>
<div v-if="keywords.length">
<div class="title">热门搜索</div>
<div class="list acea-row">
<div
class="item"
v-for="keywordsKey of keywords"
:key="keywordsKey"
@click="toSearch(keywordsKey)"
>{{ keywordsKey }}</div>
</div>
</div>
<div class="line"></div>
<!-- <GoodList></GoodList>-->
</div>
<!--<div class="noCommodity">-->
<!--<div class="noPictrue">-->
<!--<img :src="$VUE_APP_RESOURCES_URL+'/images/noSearch.png'" class="image" />-->
<!--</div>-->
<!--<recommend></recommend>-->
<!--</div>-->
</div>
</template>
<script>
// import GoodList from "@/components/GoodList";
import { getSearchKeyword } from "@/api/store";
import { trim } from "@/utils";
// import Recommend from "@/components/Recommend";
export default {
name: "GoodSearch",
components: {
// Recommend,
// GoodList
},
props: {},
data: function() {
return {
keywords: [],
search: ""
};
},
mounted: function() {
this.getData();
},
methods: {
submit() {
const search = trim(this.search) || "";
if (!search) return;
this.toSearch(search);
},
toSearch(s) {
this.$yrouter.push({ path: "/pages/shop/GoodsList/main", query: { s } });
},
getData() {
getSearchKeyword().then(res => {
this.keywords = res.data;
});
}
}
};
</script>
<style >
.noCommodity {
border-top: 0.05rem solid #f5f5f5;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+125
View File
@@ -0,0 +1,125 @@
<template>
<div class="productSort">
<form @submit.prevent="submitForm">
<div class="header acea-row row-center-wrapper" ref="header">
<div class="acea-row row-between-wrapper input">
<span class="iconfont icon-sousuo"></span>
<input type="text" placeholder="搜索商品信息" v-model="search" />
</div>
</div>
</form>
<div class="aside">
<div
class="item acea-row row-center-wrapper"
:class="categoryDivindex === navActive ? 'on' : ''"
v-for="(item, categoryDivindex) in category"
:key="categoryDivindex"
@click="asideTap(categoryDivindex)"
>
<span>{{ item.cateName }}</span>
</div>
</div>
<div class="conter">
<div class="listw" v-for="(item, eq) in category" :key="eq">
<div v-if="eq === navActive">
<div class="title acea-row row-center-wrapper" ref="title">
<div class="line"></div>
<div class="name">{{ item.cateName }}</div>
<div class="line"></div>
</div>
<div class="list acea-row">
<div
class="item acea-row row-column row-middle"
v-for="(child, categoryIndex) in item.children"
:key="categoryIndex"
@click="$yrouter.push({path: '/pages/shop/GoodsList/index',query: { id: child.id, title: child.cateName }})"
>
<div class="picture">
<img :src="child.pic" />
</div>
<div class="name line1">{{ child.cateName }}</div>
</div>
</div>
</div>
</div>
</div>
<div style="height:100rpx;"></div>
</div>
</template>
<script>
import debounce from "lodash.debounce";
import { getCategory } from "@/api/store";
import { trim } from "@/utils";
export default {
name: "GoodsClass",
components: {},
props: {},
data: function() {
return {
category: [],
navActive: 0,
search: "",
lock: false
};
},
watch: {
"$yroute.query.id": function(n) {
if (n) {
this.activeCateId(n);
}
}
},
mounted: function() {
// document.addEventListener("scroll", this.onScroll, false);
this.loadCategoryData();
},
methods: {
activeCateId(n) {
let index = 0;
n = parseInt(n);
if (!n) return;
this.category.forEach((cate, i) => {
if (cate.id === n) index = i;
});
if (index !== this.navActive) {
this.asideTap(index);
}
},
loadCategoryData() {
getCategory().then(res => {
this.category = res.data;
this.$nextTick(() => {
if (this.$yroute.query.id) {
this.activeCateId(this.$yroute.query.id);
}
});
});
},
submitForm: function() {
var val = trim(this.search);
if (val) {
this.$yrouter.push({
path: "/pages/shop/GoodsList/main",
query: { s: val }
});
setTimeout(() => (this.search = ""), 500);
}
},
asideTap(index) {
this.navActive = index;
}
},
beforeDestroy: function() {
// document.removeEventListener("scroll", this.onScroll, false);
}
};
</script>
<style >
.productSort{
height:100%
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+93
View File
@@ -0,0 +1,93 @@
<template>
<div ref="container">
<div class="collectionGoods" v-if="collectProductList.length > 0">
<div
@click="$yrouter.push({ path: '/pages/shop/GoodsCon/index',query:{id:item.pid} })"
class="item acea-row row-between-wrapper"
v-for="(item, collectProductListIndex) in collectProductList"
:key="collectProductListIndex"
>
<div class="pictrue">
<img :src="item.image" />
</div>
<div class="text acea-row row-column-between">
<div class="infor line1">{{ item.storeName }}</div>
<div class="acea-row row-between-wrapper">
<div class="money font-color-red">{{ item.price }}</div>
<div class="delete" @click.prevent="delCollection(collectProductListIndex)">删除</div>
</div>
</div>
</div>
</div>
<Loading :loaded="loadend" :loading="loading"></Loading>
<div
class="noCommodity"
style="background-color:#fff;"
v-if="collectProductList.length < 1 && page > 1"
>
<div class="noPictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/noCollection.png'" class="image" />
</div>
<Recommend></Recommend>
</div>
</div>
</template>
<script>
import Recommend from "@/components/Recommend";
import { getCollectUser, getCollectDel } from "@/api/user";
import Loading from "@/components/Loading";
export default {
name: "GoodsCollection",
components: {
Recommend,
Loading
},
props: {},
data: function() {
return {
page: 1,
limit: 20,
collectProductList: [],
loadTitle: "",
loading: false,
loadend: false
};
},
mounted: function() {
this.get_user_collect_product();
},
onReachBottom() {
!this.loading && this.get_user_collect_product();
},
methods: {
get_user_collect_product: function() {
let that = this;
if (that.loading) return; //阻止下次请求(false可以进行请求);
if (that.loadend) return; //阻止结束当前请求(false可以进行请求);
that.loading = true;
getCollectUser(that.page, that.limit).then(res => {
that.loading = false;
//apply();js将一个数组插入另一个数组;
that.collectProductList.push.apply(that.collectProductList, res.data);
that.loadend = res.data.length < that.limit; //判断所有数据是否加载完成;
that.page = that.page + 1;
});
},
//删除收藏;
delCollection: function(index) {
let that = this,
id = that.collectProductList[index].pid,
category = that.collectProductList[index].category;
getCollectDel(id, category).then(function() {
that.$dialog.toast({
mes: "删除收藏成功!",
callback: () => {
that.collectProductList.splice(index, 1);
that.$set(that, "collectProductList", that.collectProductList);
}
});
});
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+801
View File
@@ -0,0 +1,801 @@
<template>
<div :class="[posterImageStatus ? 'noscroll product-con' : 'product-con']">
<product-con-swiper :img-urls="storeInfo.sliderImageArr"></product-con-swiper>
<div class="wrapper">
<div class="share acea-row row-between row-bottom">
<div class="money font-color-red">
<span class="num">{{ storeInfo.price }}</span>
<span
class="vip-money"
v-if="storeInfo.vipPrice && storeInfo.vipPrice > 0"
>{{ storeInfo.vipPrice }}</span>
<img
:src="$VUE_APP_RESOURCES_URL+'/images/vip.png'"
class="image"
v-if="storeInfo.vipPrice && storeInfo.vipPrice > 0"
/>
</div>
<div class="iconfont icon-fenxiang" @click="listenerActionSheet"></div>
</div>
<div class="introduce">{{ storeInfo.storeName }}</div>
<div class="label acea-row row-between-wrapper">
<div>原价:{{ storeInfo.otPrice }}</div>
<div>库存:{{ storeInfo.stock }}{{ storeInfo.unitName }}</div>
<div>销量:{{ storeInfo.sales }}{{ storeInfo.unitName }}</div>
</div>
<div class="coupon acea-row row-between-wrapper" @click="couponTap" v-if="couponList.length">
<div class="hide line1 acea-row">
优惠券
<div
class="activity"
v-for="(item, couponListEq) in couponList"
:key="couponListEq"
>{{ item.use_min_price }}{{ item.coupon_price }}</div>
</div>
<div class="iconfont icon-jiantou"></div>
</div>
</div>
<div class="attribute acea-row row-between-wrapper" @click="selecAttrTap">
<div>
{{ attrTxt }}
<span class="atterTxt">{{ attrValue }}</span>
</div>
<div class="iconfont icon-jiantou"></div>
</div>
<div class="store-info" v-if="system_store.id !== undefined">
<div class="title">门店信息</div>
<div class="info acea-row row-between-wrapper">
<div class="picTxt acea-row row-between-wrapper">
<div class="pictrue">
<img :src="system_store.image" />
</div>
<div class="text">
<div class="name line1">{{ system_store.name }}</div>
<div class="address acea-row row-middle" @click="showChang">
<span class="addressTxt line1">
{{
system_store._detailed_address
}}
</span>
<span class="iconfont icon-youjian"></span>
</div>
</div>
</div>
<!-- <a class="iconfont icon-dadianhua01 font-color-red" :href="'tel:' + system_store.phone"></a> -->
</div>
</div>
<div class="userEvaluation" v-if="replyCount">
<div class="title acea-row row-between-wrapper">
<div>用户评价({{ replyCount }})</div>
<div
@click="$yrouter.push({ path: '/pages/shop/EvaluateList/index',query:{id}})"
class="praise"
>
<span class="font-color-red">{{ replyChance }}%</span>好评率
<span class="iconfont icon-jiantou"></span>
</div>
</div>
<user-evaluation :reply="reply"></user-evaluation>
</div>
<div class="superior">
<div class="title acea-row row-center-wrapper">
<img :src="$VUE_APP_RESOURCES_URL+'/images/ling.png'" />
<div class="titleTxt">优品推荐</div>
<img :src="$VUE_APP_RESOURCES_URL+'/images/ling.png'" />
</div>
<template>
<div class="slider-banner banner">
<swiper :options="swiperRecommend" v-if="goodList.length > 0">
<swiper-slide v-for="(item, eq2) in goodList" :key="eq2">
<div class="list acea-row row-middle">
<div class="item" v-for="val in item.list" :key="val.image">
<div class="pictrue">
<img :src="val.image" />
</div>
<div class="name line1">{{ val.store_name }}}</div>
<div class="money font-color-red">¥{{ val.price }}</div>
</div>
</div>
</swiper-slide>
<div class="swiper-pagination" slot="pagination"></div>
</swiper>
</div>
</template>
</div>
<div class="product-intro">
<div class="title">产品介绍</div>
<div class="conter" v-html="storeInfo.description"></div>
</div>
<div style="height:100rpx;"></div>
<div class="footer acea-row row-between-wrapper">
<!--<div class="item" @click="$yrouter.push({ path: '/pages/user/CustomerList/index' })">-->
<!--<div class="iconfont icon-kefu"></div>-->
<!--<div>客服</div>-->
<!--</div>-->
<div class="item" @click="setCollect">
<div class="iconfont" :class="storeInfo.userCollect ? 'icon-shoucang1' : 'icon-shoucang'"></div>
<div>收藏</div>
</div>
<div
@click="$yrouter.push('/pages/shop/ShoppingCart/index')"
class="item animated"
:class="animated === true ? 'bounceIn' : ''"
>
<div class="iconfont icon-gouwuche1">
<span class="num bg-color-red" v-if="CartCount > 0">
{{
CartCount
}}
</span>
</div>
<div>购物车</div>
</div>
<div class="bnt acea-row">
<div class="joinCart" @click="joinCart">加入购物车</div>
<div class="buy" @click="tapBuy">立即购买</div>
</div>
</div>
<CouponPop v-on:changeFun="changeFun" :coupon="coupon"></CouponPop>
<ProductWindow v-on:changeFun="changeFun" :attr="attr" :cartNum="cart_num"></ProductWindow>
<StorePoster
v-on:setPosterImageStatus="setPosterImageStatus"
:posterImageStatus="posterImageStatus"
:posterData="posterData"
></StorePoster>
<ShareInfo v-on:setShareInfoStatus="setShareInfoStatus" :shareInfoStatus="shareInfoStatus"></ShareInfo>
<div class="generate-posters acea-row row-middle" :class="posters ? 'on' : ''">
<div class="item" v-if="weixinStatus === true" @click="setShareInfoStatus">
<div class="iconfont icon-weixin3"></div>
<div class>发送给朋友</div>
</div>
<div class="item" @click="setPosterImageStatus">
<div class="iconfont icon-haibao"></div>
<div class>生成海报</div>
</div>
</div>
<div class="mask" @touchmove.prevent @click="listenerActionClose" v-show="posters"></div>
<div class="geoPage" v-if="mapShow">
<iframe
width="100%"
height="100%"
frameborder="0"
scrolling="no"
:src="'https://apis.map.qq.com/uri/v1/geocoder?coord=' +system_store.latitude +',' +system_store.longitude +'&referer=' +mapKey"
></iframe>
</div>
</div>
</template>
<style scoped>
.geoPage {
position: fixed;
width: 100%;
height: 100%;
top: 0;
z-index: 10000;
}
.product-con .store-info {
margin-top: 0.2rem;
background-color: #fff;
}
.product-con .store-info .title {
padding: 0 0.3rem;
font-size: 0.28rem;
color: #282828;
height: 0.8rem;
line-height: 0.8rem;
border-bottom: 0.01rem solid #f5f5f5;
}
.product-con .store-info .info {
padding: 0 0.3rem;
height: 1.26rem;
}
.product-con .store-info .info .picTxt {
width: 6.15rem;
}
.product-con .store-info .info .picTxt .pictrue {
width: 0.76rem;
height: 0.76rem;
}
.product-con .store-info .info .picTxt .pictrue img {
width: 100%;
height: 100%;
border-radius: 0.06rem;
}
.product-con .store-info .info .picTxt .text {
width: 5.22rem;
}
.product-con .store-info .info .picTxt .text .name {
font-size: 0.3rem;
color: #282828;
}
.product-con .store-info .info .picTxt .text .address {
font-size: 0.24rem;
color: #666;
margin-top: 0.03rem;
}
.product-con .store-info .info .picTxt .text .address .iconfont {
color: #707070;
font-size: 0.18rem;
margin-left: 0.1rem;
}
.product-con .store-info .info .picTxt .text .address .addressTxt {
width: 4.8rem;
}
.product-con .store-info .info .iconfont {
font-size: 0.4rem;
}
.product-con .superior {
background-color: #fff;
margin-top: 0.2rem;
}
.product-con .superior .title {
height: 0.98rem;
}
.product-con .superior .title img {
width: 0.3rem;
height: 0.3rem;
}
.product-con .superior .title .titleTxt {
margin: 0 0.2rem;
font-size: 0.3rem;
background-image: linear-gradient(to right, #f57a37 0%, #f21b07 100%);
background-image: -webkit-linear-gradient(to right, #f57a37 0%, #f21b07 100%);
background-image: -moz-linear-gradient(to right, #f57a37 0%, #f21b07 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.product-con .superior .slider-banner {
width: 6.9rem;
margin: 0 auto;
padding-bottom: 0.2rem;
}
.product-con .superior .slider-banner .list {
width: 100%;
padding-bottom: 0.2rem;
}
.product-con .superior .slider-banner .list .item {
width: 2.15rem;
margin: 0 0.22rem 0.3rem 0;
font-size: 0.26rem;
}
.product-con .superior .slider-banner .list .item:nth-of-type(3n) {
margin-right: 0;
}
.product-con .superior .slider-banner .list .item .pictrue {
width: 100%;
height: 2.15rem;
}
.product-con .superior .slider-banner .list .item .pictrue img {
width: 100%;
height: 100%;
border-radius: 0.06rem;
}
.product-con .superior .slider-banner .list .item .name {
color: #282828;
margin-top: 0.12rem;
}
.product-con .superior .slider-banner .swiper-pagination-bullet {
background-color: #999;
}
.product-con .superior .slider-banner .swiper-pagination-bullet-active {
background-color: #e93323;
}
.mask {
-webkit-filter: blur(2px);
-moz-filter: blur(2px);
-ms-filter: blur(2px);
filter: blur(2px);
}
.footer .icon-shoucang1 {
color: #73cbb6;
}
.product-con .product-intro .conter div {
width: 100% !important;
}
.generate-posters {
width: 100%;
height: 1.7rem;
background-color: #fff;
position: fixed;
left: 0;
bottom: 0;
z-index: 99;
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);
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);
}
.generate-posters.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);
}
.generate-posters .item {
flex: 50%;
-webkit-flex: 50%;
-ms-flex: 50%;
text-align: center;
}
.generate-posters .item .iconfont {
font-size: 0.8rem;
color: #5eae72;
}
.generate-posters .item .iconfont.icon-haibao {
color: #5391f1;
}
.noscroll {
height: 100%;
overflow: hidden;
}
</style>
<script>
// import { swiper, swiperSlide } from "vue-awesome-swiper";
import ProductConSwiper from "@/components/ProductConSwiper";
import UserEvaluation from "@/components/UserEvaluation";
import CouponPop from "@/components/CouponPop";
import ProductWindow from "@/components/ProductWindow";
import StorePoster from "@/components/StorePoster";
import ShareInfo from "@/components/ShareInfo";
import {
getProductDetail,
postCartAdd,
getCartCount,
getProductCode
} from "@/api/store";
import {
getCoupon,
getCollectAdd,
getCollectDel,
getUserInfo
} from "@/api/user";
import { isWeixin, PosterCanvas, handleQrCode } from "@/utils";
// import { wechatEvevt } from "@/libs/wechat";
import { imageBase64 } from "@/api/public";
import { mapGetters } from "vuex";
export default {
name: "GoodsCon",
components: {
// swiper,
// swiperSlide,
ProductConSwiper,
UserEvaluation,
CouponPop,
ProductWindow,
StorePoster,
ShareInfo
},
data: function() {
return {
shareInfoStatus: false,
weixinStatus: false,
mapShow: false,
mapKey: "",
posterData: {
image: "",
title: "",
price: "",
code: ""
},
posterImageStatus: false,
animated: false,
coupon: {
coupon: false,
list: []
},
attr: {
cartAttr: false,
productAttr: [],
productSelect: {}
},
isOpen: false, //是否打开属性组件
productValue: [],
id: 0,
storeInfo: {},
couponList: [],
attrTxt: "请选择",
attrValue: "",
cart_num: 1, //购买数量
replyCount: "",
replyChance: "",
reply: [],
priceName: 0,
CartCount: 0,
posters: false,
banner: [{}, {}],
swiperRecommend: {
pagination: {
el: ".swiper-pagination",
clickable: true
},
autoplay: false,
loop: false,
speed: 1000,
observer: true,
observeParents: true
},
goodList: [],
system_store: {},
qqmapsdk: null
};
},
computed: mapGetters(["isLogin"]),
mounted: function() {
let url = handleQrCode();
console.log(url);
if (url && url.productId) {
this.id = url.productId;
} else {
this.id = this.$yroute.query.id;
}
this.productCon();
},
methods: {
showChang: function() {
if (isWeixin()) {
let config = {
latitude: this.system_store.latitude,
longitude: this.system_store.longitude,
name: this.system_store.name,
address: this.system_store._detailed_address
};
// wechatEvevt("openLocation", config)
// .then(res => {
// })
// .catch(res => {
// if (res.is_ready) {
// res.wx.openLocation(config);
// }
// });
} else {
if (!this.mapKey)
return this.$dialog.error(
"暂无法使用查看地图,请配置您的腾讯地图key"
);
this.mapShow = true;
}
},
updateTitle() {
// document.title = this.storeInfo.storeName || this.$yroute.meta.title;
},
setShareInfoStatus: function() {
this.shareInfoStatus = !this.shareInfoStatus;
this.posters = false;
},
shareCode: function() {
var that = this;
getProductCode(that.id).then(res => {
that.posterData.code = res.data.code;
that.listenerActionSheet();
});
},
setPosterImageStatus: function() {
this.posterImageStatus = !this.posterImageStatus;
this.posters = false;
},
//产品详情接口;
productCon: function() {
let that = this;
getProductDetail(that.id)
.then(res => {
that.$set(that, "storeInfo", res.data.storeInfo);
that.$set(that.attr, "productAttr", res.data.productAttr);
that.$set(that, "productValue", res.data.productValue);
that.$set(that, "replyCount", res.data.replyCount);
that.$set(that, "replyChance", res.data.replyChance);
that.reply = res.data.reply ? [res.data.reply] : [];
that.$set(that, "reply", that.reply);
that.$set(that, "priceName", res.data.priceName);
that.posterData.image = that.storeInfo.image;
if (that.storeInfo.storeName.length > 30) {
that.posterData.title =
that.storeInfo.storeName.substring(0, 30) + "...";
} else {
that.posterData.title = that.storeInfo.storeName;
}
that.posterData.price = that.storeInfo.price;
that.posterData.code = that.storeInfo.codeBase;
// that.system_store = res.data.system_store;
let good_list = res.data.goodList || [];
let goodArray = [];
let count = Math.ceil(good_list.length / 6);
for (let i = 0; i < count; i++) {
var list = good_list.slice(i * 6, 6);
if (list.length) goodArray.push({ list: list });
}
that.mapKay = res.data.mapKay;
that.$set(that, "goodList", goodArray);
that.updateTitle();
that.DefaultSelect();
that.getCartCount();
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
//默认选中属性;
DefaultSelect: function() {
let productAttr = this.attr.productAttr;
let value = [];
for (let i = 0; i < productAttr.length; i++) {
this.$set(productAttr[i], "index", 0);
value.push(productAttr[i].attrValueArr[0]);
}
//sort();排序函数:数字-英文-汉字;
let productSelect = this.productValue[value.sort().join(",")];
if (productSelect && productAttr.length) {
this.$set(
this.attr.productSelect,
"store_name",
this.storeInfo.storeName
);
this.$set(this.attr.productSelect, "image", productSelect.image);
this.$set(this.attr.productSelect, "price", productSelect.price);
this.$set(this.attr.productSelect, "stock", productSelect.stock);
this.$set(this.attr.productSelect, "unique", productSelect.unique);
this.$set(this.attr.productSelect, "cart_num", 1);
this.$set(this, "attrValue", value.sort().join(","));
this.$set(this, "attrTxt", "已选择");
} else if (!productSelect && productAttr.length) {
this.$set(
this.attr.productSelect,
"store_name",
this.storeInfo.storeName
);
this.$set(this.attr.productSelect, "image", this.storeInfo.image);
this.$set(this.attr.productSelect, "price", this.storeInfo.price);
this.$set(this.attr.productSelect, "stock", 0);
this.$set(this.attr.productSelect, "unique", "");
this.$set(this.attr.productSelect, "cart_num", 0);
this.$set(this, "attrValue", "");
this.$set(this, "attrTxt", "请选择");
} else if (!productSelect && !productAttr.length) {
this.$set(
this.attr.productSelect,
"store_name",
this.storeInfo.storeName
);
this.$set(this.attr.productSelect, "image", this.storeInfo.image);
this.$set(this.attr.productSelect, "price", this.storeInfo.price);
this.$set(this.attr.productSelect, "stock", this.storeInfo.stock);
this.$set(
this.attr.productSelect,
"unique",
this.storeInfo.unique || ""
);
this.$set(this.attr.productSelect, "cart_num", 1);
this.$set(this, "attrValue", "");
this.$set(this, "attrTxt", "请选择");
}
},
//购物车;
ChangeCartNum: function(changeValue) {
//changeValue:是否 加|减
//获取当前变动属性
let productSelect = this.productValue[this.attrValue];
//如果没有属性,赋值给商品默认库存
if (productSelect === undefined && !this.attr.productAttr.length) {
productSelect = this.attr.productSelect;
}
//无属性值即库存为0;不存在加减;
if (productSelect === undefined) return;
let stock = productSelect.stock || 0;
let num = this.attr.productSelect;
if (changeValue) {
num.cart_num++;
if (num.cart_num > stock) {
this.$set(this.attr.productSelect, "cart_num", stock);
this.$set(this, "cart_num", stock);
} else {
this.$set(this.attr.productSelect, "cart_num", num.cart_num);
this.$set(this, "cart_num", num.cart_num);
}
} else {
num.cart_num--;
if (num.cart_num < 1) {
this.$set(this.attr.productSelect, "cart_num", 1);
this.$set(this, "cart_num", 1);
}
}
},
//将父级向子集多次传送的函数合二为一;
changeFun: function(opt) {
if (typeof opt !== "object") opt = {};
let action = opt.action || "";
let value = opt.value === undefined ? "" : opt.value;
this[action] && this[action](value);
},
//打开优惠券插件;
couponTap: function() {
let that = this;
that.coupons();
that.coupon.coupon = true;
},
changecoupon: function(msg) {
this.coupon.coupon = msg;
this.coupons();
},
currentcoupon: function(res) {
let that = this;
that.coupon.coupon = false;
that.$set(that.coupon.list[res], "is_use", true);
},
//可领取优惠券接口;
coupons: function() {
let that = this,
q = { page: 1, limit: 20 };
getCoupon(q).then(res => {
that.$set(that, "couponList", res.data || []);
that.$set(that.coupon, "list", res.data);
});
},
//打开属性插件;
selecAttrTap: function() {
this.attr.cartAttr = true;
this.isOpen = true;
},
changeattr: function(msg) {
this.attr.cartAttr = msg;
console.log(this.attr, msg);
this.isOpen = false;
},
//选择属性;
ChangeAttr: function(res) {
let productSelectValue = this.productValue[res];
if (productSelectValue) {
let productSelect = {
...this.attr.productSelect,
image: productSelectValue.image,
price: productSelectValue.price,
stock: productSelectValue.stock,
unique: productSelectValue.unique,
cart_num: 1
};
let attr = {
...this.attr,
productSelect
};
this.attr = attr;
// this.$set(this.attr.productSelect, "image", productSelect.image);
// this.$set(this.attr.productSelect, "price", productSelect.price);
// this.$set(this.attr.productSelect, "stock", productSelect.stock);
// this.$set(this.attr.productSelect, "unique", productSelect.unique);
// this.$set(this.attr.productSelect, "cart_num", 1);
this.$set(this, "attrValue", res);
this.$set(this, "attrTxt", "已选择");
} else {
this.$set(this.attr.productSelect, "image", this.storeInfo.image);
this.$set(this.attr.productSelect, "price", this.storeInfo.price);
this.$set(this.attr.productSelect, "stock", 0);
this.$set(this.attr.productSelect, "unique", "");
this.$set(this.attr.productSelect, "cart_num", 0);
this.$set(this, "attrValue", "");
this.$set(this, "attrTxt", "请选择");
}
},
//收藏商品
setCollect: function() {
let that = this,
id = that.storeInfo.id,
category = "product";
if (that.storeInfo.userCollect) {
getCollectDel(id, category).then(function() {
that.storeInfo.userCollect = !that.storeInfo.userCollect;
});
} else {
getCollectAdd(id, category).then(function() {
that.storeInfo.userCollect = !that.storeInfo.userCollect;
});
}
},
// 点击加入购物车按钮
joinCart: function() {
//0=加入购物车
this.goCat(0);
},
// 加入购物车;
goCat: function(news) {
let that = this,
productSelect = that.productValue[this.attrValue];
//打开属性
if (that.attrValue) {
//默认选中了属性,但是没有打开过属性弹窗还是自动打开让用户查看默认选中的属性
that.attr.cartAttr = !that.isOpen ? true : false;
} else {
if (that.isOpen) that.attr.cartAttr = true;
else that.attr.cartAttr = !that.attr.cartAttr;
}
//只有关闭属性弹窗时进行加入购物车
if (that.attr.cartAttr === true && that.isOpen === false)
return (that.isOpen = true);
//如果有属性,没有选择,提示用户选择
if (
that.attr.productAttr.length &&
productSelect === undefined &&
that.isOpen === true
)
return that.$dialog.toast({ mes: "产品库存不足,请选择其它" });
let q = {
productId: that.id,
cartNum: that.attr.productSelect.cart_num,
new: news,
uniqueId:
that.attr.productSelect !== undefined
? that.attr.productSelect.unique
: ""
};
postCartAdd(q)
.then(function(res) {
that.isOpen = false;
that.attr.cartAttr = false;
if (news) {
that.$yrouter.push({
path: "/pages/order/OrderSubmission/main",
query: { id: res.data.cartId }
});
} else {
that.$dialog.toast({
mes: "添加购物车成功",
callback: () => {
that.getCartCount(true);
}
});
}
})
.catch(error => {
that.isOpen = false;
wx.showToast({
title: error.response.data.msg,
icon: "none",
duration: 2000
});
});
},
//获取购物车数量
getCartCount: function(isAnima) {
let that = this;
const isLogin = that.isLogin;
if (isLogin) {
getCartCount({ numType: 0 }).then(res => {
that.CartCount = res.data.count;
//加入购物车后重置属性
if (isAnima) {
that.animated = true;
setTimeout(function() {
that.animated = false;
}, 500);
}
});
}
},
//立即购买;
tapBuy: function() {
// 1=直接购买
this.goCat(1);
},
listenerActionSheet: function() {
if (isWeixin() === true) {
this.weixinStatus = true;
}
this.posters = true;
},
listenerActionClose: function() {
this.posters = false;
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+206
View File
@@ -0,0 +1,206 @@
<template>
<div class="evaluate-con">
<div class="goodsStyle acea-row row-between" v-if="orderCon.productInfo">
<div class="pictrue">
<img :src="orderCon.productInfo.image" class="image" />
</div>
<div class="text acea-row row-between">
<div class="name line2">{{ orderCon.productInfo.storeName }}</div>
<div class="money">
<div>{{ orderCon.productInfo.price }}</div>
<div class="num">x{{ orderCon.cartNum }}</div>
</div>
</div>
</div>
<div class="score">
<div
class="item acea-row row-middle"
v-for="(item, scoreListIndexw) in scoreList"
:key="scoreListIndexw"
>
<div>{{ item.name }}</div>
<div class="starsList">
<span
@click="stars(starsIndexn, scoreListIndexw)"
v-for="(itemn, starsIndexn) in item.stars"
:key="starsIndexn"
class="iconfont"
:class="
item.index >= starsIndexn
? 'icon-shitixing font-color-red'
: 'icon-kongxinxing'
"
></span>
</div>
<span class="evaluate">
{{
item.index === -1 ? "" : item.index + 1 + "分"
}}
</span>
</div>
<div class="textarea">
<textarea placeholder="商品满足你的期待么?说说你的想法,分享给想买的他们吧~" v-model="expect"></textarea>
<div class="list acea-row row-middle">
<div
class="pictrue"
v-for="(item, uploadPicturesIndex) in uploadPictures"
:key="uploadPicturesIndex"
>
<img :src="item" />
<span
class="iconfont icon-guanbi1 font-color-red"
@click="uploadPictures.splice(uploadPicturesIndex, 1)"
></span>
</div>
<!-- <VueCoreImageUpload
class="btn btn-primary"
:crop="false"
compress="80"
@imageuploaded="imageuploaded"
:headers="headers"
:max-file-size="5242880"
:credentials="false"
inputAccept="image/*"
inputOfFile="file"
:url="url"
v-if="uploadPictures.length < 8"
>
<div
class="pictrue uploadBnt acea-row row-center-wrapper row-column"
>
<span class="iconfont icon-icon25201"></span>
<div>上传图片</div>
</div>
</VueCoreImageUpload>-->
</div>
</div>
<div class="evaluateBnt bg-color-red" @click="submit">立即评价</div>
</div>
</div>
</template>
<style scoped>
.evaluate-con .score .textarea .list .pictrue.uploadBnt {
border: 1px solid #ddd;
}
</style>
<script>
import { postOrderProduct, postOrderComment } from "@/api/store";
import { trim } from "@/utils";
import { VUE_APP_API_URL } from "@/config";
import { required } from "@/utils/validate";
import { validatorDefaultCatch } from "@/utils/dialog";
const NAME = "GoodsEvaluate";
export default {
name: NAME,
components: {
// VueCoreImageUpload
},
props: {},
data: function() {
return {
orderCon: {
cartProduct: {
productInfo: {}
}
},
scoreList: [
{
name: "商品质量",
stars: ["", "", "", "", ""],
index: -1
},
{
name: "服务态度",
stars: ["", "", "", "", ""],
index: -1
}
],
url: `${VUE_APP_API_URL}/api/qiNiuContent`,
headers: {
Authorization: "Bearer " + this.$store.state.token
},
uploadPictures: [],
expect: "",
unique: ""
};
},
mounted: function() {
this.unique = this.$yroute.query.id;
this.getOrderProduct();
},
watch: {
$yroute(n) {
if (n.name === NAME && this.unique !== n.params.id) {
this.unique = n.params.id;
this.$set(this.scoreList[0], "index", -1);
this.$set(this.scoreList[1], "index", -1);
this.expect = "";
this.uploadPictures = [];
this.getOrderProduct();
}
}
},
methods: {
getOrderProduct: function() {
let that = this,
unique = that.unique;
postOrderProduct(unique).then(res => {
that.orderCon = res.data;
});
},
stars: function(indexn, indexw) {
this.scoreList[indexw].index = indexn;
},
imageuploaded(res) {
if (res.errno !== 0) return this.$dialog.error(res.msg || "上传图片失败");
this.uploadPictures.push(res.data[0]);
},
async submit() {
const expect = trim(this.expect),
product_score =
this.scoreList[0].index + 1 === 0 ? "" : this.scoreList[0].index + 1,
service_score =
this.scoreList[1].index + 1 === 0 ? "" : this.scoreList[1].index + 1;
try {
await this.$validator({
product_score: [
required("请选择商品质量分数", {
type: "number"
})
],
service_score: [
required("请选择服务态度分数", {
type: "number"
})
]
}).validate({ product_score, service_score });
} catch (e) {
return validatorDefaultCatch(e);
}
postOrderComment({
productScore: product_score,
serviceScore: service_score,
unique: this.unique,
pics: this.uploadPictures.join(","),
comment: expect
})
.then(() => {
wx.showToast({
title: "评价成功",
icon: "success",
duration: 2000
});
this.$yrouter.push({
path: "/pages/order/OrderDetails/main",
query: { id: this.orderCon.orderId }
});
})
.catch(res => {
this.$dialog.error(res.msg);
});
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+268
View File
@@ -0,0 +1,268 @@
<template>
<div class="productList" ref="container">
<form @submit.prevent="submitForm">
<div class="search bg-color-red acea-row row-between-wrapper">
<div class="input acea-row row-between-wrapper">
<span class="iconfont icon-sousuo"></span>
<input placeholder="搜索商品信息" v-model="where.keyword" />
</div>
<div
class="iconfont"
:class="Switch === true ? 'icon-pailie' : 'icon-tupianpailie'"
@click="switchTap"
></div>
</div>
</form>
<div class="nav acea-row row-middle">
<div
class="item"
:class="title ? 'font-color-red' : ''"
@click="set_where(0)"
>{{ title ? title : "默认" }}</div>
<div class="item" @click="set_where(1)">
价格
<img :src="$VUE_APP_RESOURCES_URL+'/images/horn.png'" v-if="price === 0" />
<img :src="$VUE_APP_RESOURCES_URL+'/images/up.png'" v-if="price === 1" />
<img :src="$VUE_APP_RESOURCES_URL+'/images/down.png'" v-if="price === 2" />
</div>
<div class="item" @click="set_where(2)">
销量
<img :src="$VUE_APP_RESOURCES_URL+'/images/horn.png'" v-if="stock === 0" />
<img :src="$VUE_APP_RESOURCES_URL+'/images/up.png'" v-if="stock === 1" />
<img :src="$VUE_APP_RESOURCES_URL+'/images/down.png'" v-if="stock === 2" />
</div>
<!-- down -->
<div class="item" :class="nows ? 'font-color-red' : ''" @click="set_where(3)">新品</div>
</div>
<div
class="list acea-row row-between-wrapper"
:class="Switch === true ? '' : 'on'"
ref="container"
>
<div
@click="$yrouter.push({path: '/pages/shop/GoodsCon/index',query:{id:item.id}})"
class="item"
:class="Switch === true ? '' : 'on'"
v-for="(item, productListIndex) in productList"
:key="productListIndex"
:title="item.storeName"
>
<div class="pictrue" :class="Switch === true ? '' : 'on'">
<img :src="item.image" :class="Switch === true ? '' : 'on'" />
</div>
<div class="text" :class="Switch === true ? '' : 'on'">
<div class="name line1">{{ item.storeName }}</div>
<div class="money font-color-red" :class="Switch === true ? '' : 'on'">
<span class="num">{{ item.price }}</span>
</div>
<div class="vip acea-row row-between-wrapper" :class="Switch === true ? '' : 'on'">
<div class="vip-money">{{ item.otPrice }}</div>
<div>已售{{ item.sales }}</div>
</div>
</div>
</div>
</div>
<Loading :loaded="loadend" :loading="loading"></Loading>
<div
class="noCommodity"
style="background-color: #fff;"
v-if="productList.length === 0 && where.page > 1"
>
<div class="noPictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/noGood.png'" class="image" />
</div>
</div>
<Recommend v-if="productList.length === 0 && where.page > 1"></Recommend>
</div>
</template>
<script>
import Recommend from "@/components/Recommend";
import { getProducts } from "@/api/store";
import debounce from "lodash.debounce";
import Loading from "@/components/Loading";
export default {
name: "GoodsList",
components: {
Recommend,
Loading
},
props: {},
data: function() {
// const { s = "", id = 0, title = "" } = this.$yroute.query;
const s = "",
id = 0,
title = "";
return {
hostProduct: [],
productList: [],
Switch: true,
where: {
page: 1,
limit: 8,
keyword: s,
sid: id, //二级分类id
news: 0,
priceOrder: "",
salesOrder: ""
},
title: title && id ? title : "",
loadTitle: "",
loading: false,
loadend: false,
price: 0,
stock: 0,
nows: false
};
},
watch: {
title() {
this.updateTitle();
},
$yroute(to) {
// if (to.name !== "GoodsList") return;
// const { s = "", id = 0, title = "" } = to.query;
// if (s !== this.where.keyword || id !== this.where.sid) {
// this.where.keyword = s;
// this.loadend = false;
// this.loading = false;
// this.where.page = 1;
// this.where.sid = id;
// this.title = title && id ? title : "";
// this.nows = false;
// this.$set(this, "productList", []);
// this.price = 0;
// this.stock = 0;
// this.get_product_list();
// }
}
},
mounted: function() {
const { s = "", id = 0, title = "" } = this.$yroute.query;
this.updateTitle();
this.get_product_list();
},
onReachBottom() {
!this.loading && this.get_product_list();
},
onHide() {
this.hostProduct = [];
this.productList = [];
this.Switch = true;
this.where = {
page: 1,
limit: 8,
keyword: s,
sid: id, //二级分类id
news: 0,
priceOrder: "",
salesOrder: ""
};
this.loadTitle = "";
this.loading = false;
this.loadend = false;
this.price = 0;
this.stock = 0;
this.nows = fals;
},
methods: {
updateTitle() {
// document.title = this.title || this.$yroute.meta.title;
},
get_product_list() {
console.log("请求李贝奥");
var that = this;
this.setWhere();
// if (to.name !== "GoodsList") return;
const { s = "", id = 0, title = "" } = this.$yroute.query;
if (s !== this.where.keyword || id !== this.where.sid) {
this.where.keyword = s;
this.loadend = false;
this.loading = false;
this.where.page = 1;
this.where.sid = id;
this.title = title && id ? title : "";
this.nows = false;
this.$set(this, "productList", []);
this.price = 0;
this.stock = 0;
// this.get_product_list();
}
let q = that.where;
getProducts(q).then(res => {
that.loading = false;
that.productList.push.apply(that.productList, res.data);
that.loadend = res.data.length < that.where.limit; //判断所有数据是否加载完成;
that.where.page = that.where.page + 1;
});
},
submitForm: function() {
this.$set(this, "productList", []);
this.where.page = 1;
this.loadend = false;
this.loading = false;
this.get_product_list();
},
//点击事件处理
set_where: function(index) {
let that = this;
switch (index) {
case 0:
return that.$yrouter.push({ path: "/pages/shop/GoodsClass/main" });
case 1:
if (that.price === 0) that.price = 1;
else if (that.price === 1) that.price = 2;
else if (that.price === 2) that.price = 0;
that.stock = 0;
break;
case 2:
if (that.stock === 0) that.stock = 1;
else if (that.stock === 1) that.stock = 2;
else if (that.stock === 2) that.stock = 0;
that.price = 0;
break;
case 3:
that.nows = !that.nows;
break;
default:
break;
}
that.$set(that, "productList", []);
that.where.page = 1;
that.loadend = false;
that.get_product_list();
},
//设置where条件
setWhere: function() {
let that = this;
if (that.price === 0) {
that.where.priceOrder = "";
} else if (that.price === 1) {
that.where.priceOrder = "asc";
} else if (that.price === 2) {
that.where.priceOrder = "desc";
}
if (that.stock === 0) {
that.where.salesOrder = "";
} else if (that.stock === 1) {
that.where.salesOrder = "asc";
} else if (that.stock === 2) {
that.where.salesOrder = "desc";
}
that.where.news = that.nows ? "1" : "0";
},
switchTap: function() {
let that = this;
that.Switch = !that.Switch;
}
}
};
</script>
<style scoped>
.noCommodity {
border-top: 3px solid #f5f5f5;
padding-bottom: 1px;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+72
View File
@@ -0,0 +1,72 @@
<template>
<div class="quality-recommend">
<div class="slider-banner swiper">
<swiper indicatorDots="true" v-if="banner.length > 0">
<block v-for="(item, imgUrlsIndex) in imgUrls" :key="imgUrlsIndex">
<swiper-item>
<img :src="item.img" class="slide-image" />
</swiper-item>
</block>
</swiper>
</div>
<div class="title acea-row row-center-wrapper">
<div class="line"></div>
<div class="name">
<span class="iconfont icon-cuxiaoguanli"></span>促销单品
</div>
<div class="line"></div>
</div>
<Promotion-good :benefit="goodsList"></Promotion-good>
</div>
</template>
<script>
// import { swiper, swiperSlide } from "vue-awesome-swiper";
import PromotionGood from "@/components/PromotionGood";
import { getGroomList } from "@/api/store";
export default {
name: "GoodsPromotion",
components: {
// swiper,
// swiperSlide,
PromotionGood
},
props: {},
data: function() {
return {
imgUrls: [],
goodsList: [],
RecommendSwiper: {
pagination: {
el: ".swiper-pagination",
clickable: true
},
autoplay: {
disableOnInteraction: false,
delay: 2000
},
loop: true,
speed: 1000,
observer: true,
observeParents: true
}
};
},
mounted: function() {
this.getIndexGroomList();
},
methods: {
getIndexGroomList: function() {
let that = this;
getGroomList(4)
.then(res => {
that.imgUrls = res.data.banner;
that.goodsList = res.data.list;
})
.catch(function(res) {
this.$dialog.toast({ mes: res.msg });
});
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+80
View File
@@ -0,0 +1,80 @@
<template>
<div class="quality-recommend">
<div class="title acea-row row-center-wrapper">
<div class="line"></div>
<div class="name">
<span class="iconfont" :class="icon"></span>{{ name }}
</div>
<div class="line"></div>
</div>
<GoodList :good-list="goodsList" :is-sort="false"></GoodList>
</div>
</template>
<script>
import GoodList from "@/components/GoodList";
import { getGroomList } from "@/api/store";
export default {
name: "HotNewGoods",
components: {
GoodList
},
props: {},
data: function() {
return {
imgUrls: [],
goodsList: [],
name: "",
icon: "",
RecommendSwiper: {
pagination: {
el: ".swiper-pagination",
clickable: true
},
autoplay: {
disableOnInteraction: false,
delay: 2000
},
loop: true,
speed: 1000,
observer: true,
observeParents: true
}
};
},
mounted: function() {
this.titleInfo();
this.getIndexGroomList();
},
methods: {
titleInfo: function() {
let type = this.$yroute.query.type;
if (type === "1") {
this.name = "精品推荐";
this.icon = "icon-jingpintuijian";
// document.title = "精品推荐";
} else if (type === "2") {
this.name = "热门榜单";
this.icon = "icon-remen";
document.title = "热门榜单";
} else if (type === "3") {
this.name = "首发新品";
this.icon = "icon-xinpin";
// document.title = "首发新品";
}
},
getIndexGroomList: function() {
let that = this;
let type = this.$yroute.query.type;
getGroomList(type)
.then(res => {
that.imgUrls = res.data.banner;
that.goodsList = res.data.list;
})
.catch(function(res) {
this.$dialog.toast({ mes: res.msg });
});
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+485
View File
@@ -0,0 +1,485 @@
<template>
<div class="shoppingCart">
<div class="labelNav acea-row row-around row-middle">
<div class="item">
<span class="iconfont icon-xuanzhong"></span>100%正品保证
</div>
<div class="item">
<span class="iconfont icon-xuanzhong"></span>所有商品精挑细选
</div>
<div class="item">
<span class="iconfont icon-xuanzhong"></span>售后无忧
</div>
</div>
<div class="nav acea-row row-between-wrapper">
<div>
购物数量
<span class="num font-color-red">{{ count }}</span>
</div>
<div
v-if="cartList.valid.length > 0"
class="administrate acea-row row-center-wrapper"
@click="manage"
>{{ footerswitch ? "取消" : "管理" }}</div>
</div>
<div v-if="validList.length > 0 || cartList.invalid.length > 0">
<div class="list">
<div
class="item acea-row row-between-wrapper"
v-for="(item, cartListValidIndex) in validList"
:key="cartListValidIndex"
>
<div class="select-btn">
<div class="checkbox-wrapper">
<checkbox-group @change="switchSelect(cartListValidIndex)">
<label class="well-check">
<checkbox value :checked="item.checked"></checkbox>
</label>
</checkbox-group>
</div>
</div>
<div class="picTxt acea-row row-between-wrapper">
<div
class="pictrue"
@click="$yrouter.push({ path: '/pages/shop/GoodsCon/index',query:{id:item.productId }})"
>
<img :src="item.productInfo.attrInfo.image" v-if="item.productInfo.attrInfo" />
<img :src="item.productInfo.image" v-else />
</div>
<div class="text">
<div class="line1">{{ item.productInfo.storeName }}</div>
<div
class="infor line1"
v-if="item.productInfo.attrInfo"
>属性{{ item.productInfo.attrInfo.suk }}</div>
<div class="money">{{ item.truePrice }}</div>
</div>
<div class="carnum acea-row row-center-wrapper">
<div
class="reduce"
:class="validList[cartListValidIndex].cartNum <= 1 ? 'on' : ''"
@click.prevent="reduce(cartListValidIndex)"
>-</div>
<div class="num">{{ item.cartNum }}</div>
<div
class="plus"
v-if="validList[cartListValidIndex].attrInfo"
:class="
validList[cartListValidIndex].cartNum >=
validList[cartListValidIndex].attrInfo.stock
? 'on'
: ''
"
@click.prevent="plus(cartListValidIndex)"
>+</div>
<div
class="plus"
v-else
:class="
validList[cartListValidIndex].cartNum >= validList[cartListValidIndex].stock
? 'on'
: ''
"
@click.prevent="plus(cartListValidIndex)"
>+</div>
</div>
</div>
</div>
</div>
<div class="invalidGoods" v-if="cartList.invalid.length > 0">
<div class="goodsNav acea-row row-between-wrapper">
<div @click="goodsOpen">
<span
class="iconfont"
:class="goodsHidden === true ? 'icon-xiangyou' : 'icon-xiangxia'"
></span>失效商品
</div>
<div class="del" @click="delInvalidGoods">
<span class="iconfont icon-shanchu1"></span>清空
</div>
</div>
<div class="goodsList" :hidden="goodsHidden">
<div v-for="(item, cartListinvalidIndex) in cartList.invalid" :key="cartListinvalidIndex">
<div
@click="$yrouter.push({ path: '/pages/shop/GoodsCon/index',query:{id:item.productId }})"
class="item acea-row row-between-wrapper"
v-if="item.productInfo"
>
<div class="invalid acea-row row-center-wrapper">失效</div>
<div class="pictrue">
<img :src="item.productInfo.attrInfo.image" v-if="item.productInfo.attrInfo" />
<img :src="item.productInfo.image" v-else />
</div>
<div class="text acea-row row-column-between">
<div class="line1">{{ item.productInfo.storeName }}</div>
<div
class="infor line1"
v-if="item.productInfo.attrInfo"
>属性{{ item.productInfo.attrInfo.suk }}</div>
<div class="acea-row row-between-wrapper">
<div class="end">该商品已下架</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!--购物车暂无商品-->
<div class="noCart" v-if="cartList.valid.length === 0 && cartList.invalid.length === 0">
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/noCart.png'" />
</div>
<Recommend></Recommend>
</div>
<div style="height:2.1rem"></div>
<div
:class="['footer acea-row row-between-wrapper',isIpx?'iphonex-footer':'']"
v-if="cartList.valid.length > 0"
>
<div>
<div class="select-btn">
<div class="checkbox-wrapper">
<!-- <label class="well-check">
<input
type="checkbox"
name
value
:checked="isAllSelect && cartCount > 0"
@click="allChecked"
/>
<i class="icon"></i>
<span class="checkAll">全选 ({{ cartCount }})</span>
</label>-->
<checkbox-group @change="allChecked">
<label class="well-check">
<checkbox value :checked="isAllSelect && cartCount > 0"></checkbox>
<span class="checkAll">全选 ({{ cartCount }})</span>
</label>
</checkbox-group>
</div>
</div>
</div>
<div class="money acea-row row-middle" v-if="footerswitch === false">
<span class="font-color-red">{{ countmoney }}</span>
<div class="placeOrder bg-color-red" @click="placeOrder">立即下单</div>
</div>
<div class="button acea-row row-middle" v-else>
<div class="bnt cart-color" @click="collectAll">收藏</div>
<div class="bnt" @click="delgoods">删除</div>
</div>
</div>
</div>
</template>
<script>
import Recommend from "@/components/Recommend";
import {
getCartList,
postCartDel,
changeCartNum,
getCartCount
} from "@/api/store";
import { postCollectAll } from "@/api/user";
import { mul, add } from "@/utils/bc";
import cookie from "@/utils/store/cookie";
import debounce from "lodash.debounce";
const CHECKED_IDS = "cart_checked";
export default {
name: "ShoppingCart",
components: {
Recommend
},
props: {},
data: function() {
return {
isIpx: false,
cartList: { invalid: [], valid: [] },
validList: [],
isAllSelect: false,
cartCount: 0,
countmoney: 0,
goodsHidden: true,
footerswitch: false,
count: 0,
checkedIds: [],
loaded: false
};
},
watch: {
$yroute(n) {
if (n.name === "ShoppingCart") {
this.carnum();
this.countMoney();
this.getCartList();
this.gainCount();
this.goodsHidden = true;
this.footerswitch = false;
}
},
cartList(list) {
this.validList = list.valid;
}
},
mounted: function() {
let that = this;
that.carnum();
that.countMoney();
that.getCartList();
that.gainCount();
wx.getSystemInfo({
success: function(res) {
console.log(res);
var name = "iPhone X";
if (res.model.indexOf(name) > -1) {
that.isIpx = true;
}
}
});
},
methods: {
getCartList: function() {
let that = this;
getCartList().then(res => {
that.cartList = res.data;
let checkedIds = cookie.get(CHECKED_IDS) || [];
if (!Array.isArray(checkedIds)) checkedIds = [];
this.cartList.valid.forEach(cart => {
if (checkedIds.indexOf(cart.id) !== -1) cart.checked = true;
});
if (checkedIds.length) {
that.checkedIds = checkedIds;
that.isAllSelect = checkedIds.length === this.cartList.valid.length;
that.carnum();
that.countMoney();
}
this.loaded = true;
});
},
//删除商品;
delgoods: function() {
let that = this,
id = [],
valid = [],
list = that.cartList.valid;
list.forEach(function(val) {
if (val.checked === true) {
id.push(val.id);
}
});
if (id.length === 0) {
that.$dialog.toast({ mes: "请选择产品" });
return;
}
postCartDel(id).then(function() {
list.forEach(function(val, i) {
if (val.checked === false || val.checked === undefined)
valid.push(list[i]);
});
that.$set(that.cartList, "valid", valid);
that.carnum();
that.countMoney();
that.gainCount();
that.getCartList();
});
},
// //获取数量
gainCount: function() {
let that = this;
getCartCount().then(res => {
that.count = res.data.count;
});
},
//清除失效产品;
delInvalidGoods: function() {
let that = this,
id = [],
list = that.cartList.invalid;
list.forEach(function(val) {
id.push(val.id);
});
postCartDel(id).then(function() {
list.splice(0, list.length);
that.gainCount();
that.getCartList();
});
},
//批量收藏;
collectAll: function() {
let that = this,
data = { id: [], category: "" },
list = that.cartList.valid;
list.forEach(function(val) {
if (val.checked === true) {
data.id.push(val.product_id);
data.category = val.type;
}
});
if (data.id.length === 0) {
that.$dialog.toast({ mes: "请选择产品" });
return;
}
postCollectAll(data).then(function() {
that.$dialog.toast({ mes: "收藏成功!" });
});
},
//立即下单;
placeOrder: function() {
let that = this,
list = that.cartList.valid,
id = [];
list.forEach(function(val) {
if (val.checked === true) {
id.push(val.id);
}
});
if (id.length === 0) {
that.$dialog.toast({ mes: "请选择产品" });
return;
}
console.log(id);
this.$yrouter.push({
path: "/pages/order/OrderSubmission/main",
query: { id: id.join(",") }
});
},
manage: function() {
let that = this;
that.footerswitch = !that.footerswitch;
},
goodsOpen: function() {
let that = this;
that.goodsHidden = !that.goodsHidden;
},
//加
plus: function(index) {
let that = this;
let list = that.cartList.valid[index];
list.cartNum++;
if (list.attrInfo) {
if (list.cartNum >= list.attrInfo.stock) {
that.$set(list, "cart_num", list.attrInfo.stock);
}
} else {
if (list.cartNum >= list.stock) {
that.$set(list, "cart_num", list.stock);
}
}
that.carnum();
that.countMoney();
that.syncCartNum(list);
},
//减
reduce: function(index) {
let that = this;
let list = that.cartList.valid[index];
if (list.cartNum <= 1) {
that.$dialog.toast({ mes: "已经是底线啦!" });
return;
}
list.cartNum--;
if (list.cartNum < 1) {
that.$set(list, "cart_num", 1);
}
that.carnum();
that.countMoney();
that.syncCartNum(list);
},
syncCartNum(cart) {
if (!cart.sync) {
changeCartNum(cart.id, Math.max(cart.cartNum, 1) || 1)
.then(res => {
this.getCartList();
})
.catch(error => {
wx.showToast({
title: error.response.data.msg,
icon: "none",
duration: 2000
});
});
}
},
//单选
switchSelect: function(index) {
let that = this,
cart = that.cartList.valid[index],
i = this.checkedIds.indexOf(cart.id);
cart.checked = !cart.checked;
if (i !== -1) this.checkedIds.splice(i, 1);
if (cart.checked) {
this.checkedIds.push(cart.id);
}
let len = that.cartList.valid.length;
let selectnum = [];
for (let i = 0; i < len; i++) {
if (that.cartList.valid[i].checked === true) {
selectnum.push(true);
}
}
that.isAllSelect = selectnum.length === len;
that.$set(that, "cartList", that.cartList);
that.$set(that, "isAllSelect", that.isAllSelect);
cookie.set(CHECKED_IDS, that.checkedIds);
that.carnum();
that.countMoney();
},
//全选
allChecked: function(e) {
let that = this;
let selectAllStatus = e.mp.detail.value[0] ? true : false;
// let selectAllStatus = that.isAllSelect;
let checkedIds = [];
// for (let i = 0; i < array.length; i++) {
// array[i].checked = selectAllStatus;
// checked.push()
// }
that.cartList.valid.forEach(cart => {
cart.checked = selectAllStatus;
if (selectAllStatus) {
checkedIds.push(cart.id);
}
});
let cartList = {
...that.cartList
};
that.cartList = [];
that.cartList = cartList;
this.$set(this, "cartList", this.cartList);
this.$set(this, "isAllSelect", selectAllStatus);
this.checkedIds = checkedIds;
cookie.set(CHECKED_IDS, checkedIds);
that.carnum();
that.countMoney();
this.$forceUpdate();
},
//数量
carnum: function() {
let that = this;
var carnum = 0;
var array = that.cartList.valid;
for (let i = 0; i < array.length; i++) {
if (array[i].checked === true) {
carnum += parseInt(array[i].cartNum);
}
}
that.$set(that, "cartCount", carnum);
},
//总共价钱;
countMoney: function() {
let that = this;
let carmoney = 0;
let array = that.cartList.valid;
for (let i = 0; i < array.length; i++) {
if (array[i].checked === true) {
carmoney = add(carmoney, mul(array[i].cartNum, array[i].truePrice));
}
}
that.countmoney = carmoney;
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+127
View File
@@ -0,0 +1,127 @@
<template>
<div class="newsDetail">
<div class="title">{{ articleInfo.title }}</div>
<div class="list acea-row row-middle">
<div class="label cart-color line1">新闻专区</div>
<div class="item">
<span class="iconfont icon-shenhezhong"></span>{{ articleInfo.addTime }}
</div>
<div class="item">
<span class="iconfont icon-liulan"></span>{{ articleInfo.visit }}
</div>
</div>
<div class="conter" v-html="articleInfo.content"></div>
</div>
</template>
<style scoped>
.newsDetail .picTxt {
width: 6.9rem;
height: 2rem;
border-radius: 0.2rem;
border: 1px solid #e1e1e1;
position: relative;
margin: 0.3rem auto 0 auto;
}
.newsDetail .picTxt .pictrue {
width: 2rem;
height: 2rem;
}
.newsDetail .picTxt .pictrue img {
width: 100%;
height: 100%;
border-radius: 0.2rem 0 0 0.2rem;
display: block;
}
.newsDetail .picTxt .text {
width: 4.6rem;
}
.newsDetail .picTxt .text .name {
font-size: 0.3rem;
color: #282828;
}
.newsDetail .picTxt .text .money {
font-size: 0.24rem;
margin-top: 0.4rem;
font-weight: bold;
}
.newsDetail .picTxt .text .money .num {
font-size: 0.36rem;
}
.newsDetail .picTxt .text .y_money {
font-size: 0.26rem;
color: #999;
text-decoration: line-through;
}
.newsDetail .picTxt .label {
position: absolute;
background-color: #303131;
width: 1.6rem;
height: 0.5rem;
right: -0.07rem;
border-radius: 0.25rem 0 0.06rem 0.25rem;
text-align: center;
line-height: 0.5rem;
bottom: 0.24rem;
}
.newsDetail .picTxt .label .span {
background-image: linear-gradient(to right, #fff71e 0%, #f9b513 100%);
background-image: -webkit-linear-gradient(to right, #fff71e 0%, #f9b513 100%);
background-image: -moz-linear-gradient(to right, #fff71e 0%, #f9b513 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.newsDetail .picTxt .label:after {
content: " ";
position: absolute;
width: 0;
height: 0;
border-bottom: 0.08rem solid #303131;
border-right: 0.08rem solid transparent;
top: -0.08rem;
right: 0;
}
.newsDetail .bnt {
color: #fff;
font-size: 0.3rem;
width: 6.9rem;
height: 0.9rem;
border-radius: 0.45rem;
margin: 0.48rem auto 0 auto;
text-align: center;
line-height: 0.9rem;
}
</style>
<script>
import { getArticleDetails } from "@/api/public";
export default {
name: "NewsDetail",
components: {},
props: {},
data: function() {
return {
articleInfo: {}
};
},
watch: {
$yroute(to) {
if (to.name === "NewsDetail") this.articleDetails();
}
},
mounted: function() {
this.articleDetails();
},
methods: {
updateTitle() {
// document.title = this.articleInfo.title || this.$yroute.meta.title;
},
articleDetails: function() {
let that = this,
id = this.$yroute.query.id;
getArticleDetails(id).then(res => {
that.articleInfo = res.data;
that.updateTitle();
});
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+106
View File
@@ -0,0 +1,106 @@
<template>
<div class="newsList" ref="container">
<div class="list" v-for="(item, articleListIndex) in articleList" :key="articleListIndex">
<div
@click="$yrouter.push({ path: '/pages/shop/news/NewsDetail/index',query:{id:item.id }})"
class="item acea-row row-between-wrapper"
>
<div class="text acea-row row-column-between">
<div class="name line2">{{ item.title }}</div>
<div>{{ item.addTime }}</div>
</div>
<div class="pictrue">
<img :src="item.imageInput" />
</div>
</div>
</div>
<!--暂无新闻-->
<div class="noCommodity" v-if="articleList.length === 0 && page > 1">
<div class="noPictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/noNews.png'" class="image" />
</div>
</div>
<!--</Tab>-->
<!--</Tabs>-->
</div>
</template>
<script>
import { getArticleList } from "@/api/public";
export default {
name: "NewsList",
components: {},
props: {},
data: function() {
return {
page: 1,
limit: 20,
loadTitle: "",
loading: false,
loadend: false,
imgUrls: [],
navLsit: [],
articleList: [],
active: 0,
cid: 0,
swiperNew: {
pagination: {
el: ".swiper-pagination",
clickable: true
},
autoplay: {
disableOnInteraction: false,
delay: 2000
},
loop: true,
speed: 1000,
observer: true,
observeParents: true
}
};
},
mounted: function() {
// this.articleBanner();
//this.articleCategory();
this.getArticleLists();
// this.$scroll(this.$refs.container, () => {
// !this.loading && this.getArticleLists();
// });
},
onReachBottom() {
!this.loading && this.getArticleLists();
},
methods: {
getArticleLists: function() {
let that = this;
if (that.loading) return; //阻止下次请求(false可以进行请求);
if (that.loadend) return; //阻止结束当前请求(false可以进行请求);
that.loading = true;
let q = {
page: that.page,
limit: that.limit
};
getArticleList(q).then(res => {
that.loading = false;
//apply();js将一个数组插入另一个数组;
that.articleList.push.apply(that.articleList, res.data);
that.loadend = res.data.length < that.limit; //判断所有数据是否加载完成;
that.page = that.page + 1;
});
},
onClick: function(name) {
if (name === 0) this.articleHotList();
else {
this.cid = this.navLsit[name].id;
this.articleList = [];
this.page = 1;
this.loadend = false;
this.loading = false;
this.getArticleLists(name);
}
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+172
View File
@@ -0,0 +1,172 @@
<template>
<div class="ChangePassword">
<div class="list">
<div class="item">
<input type="number" placeholder="填写手机号码" v-model="phone" />
</div>
<div class="item acea-row row-between-wrapper">
<input type="text" placeholder="填写验证码" class="codeIput" v-model="captcha" />
<button
class="code font-color-red"
:disabled="disabled"
:class="disabled === true ? 'on' : ''"
@click="code"
>{{ text }}</button>
</div>
</div>
<div class="confirmBnt bg-color-red" @click="confirm">确认绑定</div>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import sendVerifyCode from "@/mixins/SendVerifyCode";
import { required, alpha_num, chs_phone } from "@/utils/validate";
import { validatorDefaultCatch } from "@/utils/dialog";
import { registerVerify, bindingPhone } from "@/api/user";
export default {
name: "BindingPhone",
components: {},
props: {},
data: function() {
return {
captcha: "",
phone: "" //手机号
};
},
mixins: [sendVerifyCode],
computed: mapGetters(["userInfo"]),
mounted: function() {},
methods: {
async confirm() {
let that = this;
const { phone, captcha } = that;
try {
await that
.$validator({
phone: [
chs_phone(chs_phone.message("手机号码")),
alpha_num(alpha_num.message())
],
captcha: [
required(required.message("验证码")),
alpha_num(alpha_num.message("验证码"))
]
})
.validate({ phone, captcha });
} catch (e) {
return validatorDefaultCatch(e);
}
bindingPhone({
phone: this.phone,
captcha: this.captcha
})
.then(res => {
if (res.data !== undefined && res.data.is_bind) {
that.$dialog.confirm({
mes: res.msg,
opts: [
{
txt: "确认绑定",
color: false,
callback: () => {
bindingPhone({
phone: this.phone,
captcha: this.captcha,
step: 1
})
.then(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.$yrouter.replace({
path: "/pages/user/PersonalData/main"
});
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.$yrouter.replace({
path: "/pages/user/PersonalData/main"
});
});
}
},
{
txt: "取消",
color: false,
callback: () => {
wx.showToast({
title: "已取消绑定",
icon: "none",
duration: 2000
});
that.$yrouter.replace({
path: "/pages/user/PersonalData/main"
});
}
}
]
});
} else {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.$yrouter.replace({ path: "/pages/user/PersonalData/main" });
}
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
async code() {
let that = this;
const { phone } = that;
try {
await that
.$validator({
phone: [
required(required.message("手机号码")),
chs_phone(chs_phone.message())
]
})
.validate({ phone });
} catch (e) {
return validatorDefaultCatch(e);
}
registerVerify({ phone: phone })
.then(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.sendCode();
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
<style lang="">
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+149
View File
@@ -0,0 +1,149 @@
<template>
<div class="ChangePassword">
<div class="phone">
当前手机号:
<input type="text" v-model="phone" disabled />
</div>
<div class="list">
<div class="item">
<input type="password" placeholder="设置新密码" v-model="password" />
</div>
<div class="item">
<input type="password" placeholder="确认新密码" v-model="password2" />
</div>
<div class="item acea-row row-between-wrapper">
<input type="text" placeholder="填写验证码" class="codeIput" v-model="captcha" />
<button
class="code font-color-red"
:disabled="disabled"
:class="disabled === true ? 'on' : ''"
@click="code"
>{{ text }}</button>
</div>
</div>
<div class="confirmBnt bg-color-red" @click="confirm">确认修改</div>
</div>
</template>
<style scoped>
.ChangePassword .phone input {
width: 2rem;
text-align: center;
}
</style>
<script>
// import { mapGetters } from "vuex";
import sendVerifyCode from "@/mixins/SendVerifyCode";
import attrs, { required, alpha_num, chs_phone } from "@/utils/validate";
import { validatorDefaultCatch } from "@/utils/dialog";
import { registerReset, registerVerify, getUserInfo } from "@/api/user";
export default {
name: "ChangePassword",
components: {},
props: {},
data: function() {
return {
password: "",
password2: "",
captcha: "",
phone: "", //隐藏几位数的手机号;
yphone: "" //手机号;
};
},
mixins: [sendVerifyCode],
// computed: mapGetters(["userInfo"]),
mounted: function() {
this.getUserInfo();
},
methods: {
getUserInfo: function() {
let that = this;
getUserInfo().then(res => {
that.yphone = res.data.phone;
let reg = /^(\d{3})\d*(\d{4})$/;
that.phone = that.yphone.replace(reg, "$1****$2");
});
},
async confirm() {
let that = this;
const { password, password2, captcha } = that;
try {
await that
.$validator({
password: [
required(required.message("密码")),
attrs.range([6, 16], attrs.range.message("密码")),
alpha_num(alpha_num.message("密码"))
],
captcha: [
required(required.message("验证码")),
alpha_num(alpha_num.message("验证码"))
]
})
.validate({ password, captcha });
} catch (e) {
return validatorDefaultCatch(e);
}
if (password !== password2) return wx.showToast({
title: '两次密码不一致',
icon: "none",
duration: 2000
});
registerReset({
account: that.yphone,
captcha: that.captcha,
password: that.password
})
.then(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
// that.$yrouter.push({ path: "/pages/user/Login/index" });
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
async code() {
let that = this;
const { yphone } = that;
try {
await that
.$validator({
yphone: [
required(required.message("手机号码")),
chs_phone(chs_phone.message())
]
})
.validate({ yphone });
} catch (e) {
return validatorDefaultCatch(e);
}
registerVerify({ phone: yphone })
.then(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.sendCode();
})
.catch(res => {
wx.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+67
View File
@@ -0,0 +1,67 @@
<template>
<div class="CustomerList">
<div
class="item acea-row row-between-wrapper"
v-for="item in list"
:key="item.id"
@click="$yrouter.push({path:'/pages/user/CustomerService/index',query:{id:item.uid}})"
>
<div class="pictrue">
<img :src="item.avatar" />
</div>
<div class="text line1">{{ item.nickname }}</div>
</div>
</div>
</template>
<script>
import { serviceList } from "@/api/user";
export default {
name: "CustomerList",
data() {
return {
list: []
};
},
methods: {
getList() {
serviceList().then(res => {
this.list = res.data;
});
}
},
mounted() {
this.getList();
}
};
</script>
<style scoped>
.CustomerList {
margin-top: 0.13rem;
}
.CustomerList .item {
height: 1.38rem;
border-bottom: 1px solid #eee;
padding: 0 0.24rem;
background-color: #fff;
}
.CustomerList .item .pictrue {
width: 0.9rem;
height: 0.9rem;
border-radius: 50%;
border: 0.03rem solid #fff;
box-shadow: 0 0 0.1rem 0.05rem #f3f3f3;
-webkit-box-shadow: 0 0 0.1rem 0.05rem #f3f3f3;
-moz-box-shadow: 0 0 0.1rem 0.05rem #f3f3f3;
}
.CustomerList .item .pictrue img {
width: 100%;
height: 100%;
border-radius: 50%;
}
.CustomerList .item .text {
width: 5.82rem;
font-size: 0.32rem;
color: #000;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+302
View File
@@ -0,0 +1,302 @@
<template>
<div class="register absolute">
<div class="shading">
<div class="pictrue acea-row row-center-wrapper">
<img src="@/assets/images/logo.png" />
</div>
</div>
<div class="whiteBg" v-if="formItem === 1">
<div class="title acea-row row-center-wrapper">
<div
class="item"
:class="current === index ? 'on' : ''"
v-for="(item, index) in navList"
@click="navTap(index)"
:key="index"
>
{{ item }}
</div>
</div>
<div class="list" :hidden="current !== 0">
<form @submit.prevent="submit">
<div class="item">
<div class="acea-row row-between-wrapper">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-phone_"></use>
</svg>
<input
type="text"
placeholder="输入手机号码"
v-model="account"
required
/>
</div>
</div>
<div class="item">
<div class="acea-row row-between-wrapper">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_"></use>
</svg>
<input
type="password"
placeholder="填写登录密码"
v-model="password"
required
/>
</div>
</div>
</form>
</div>
<div class="list" :hidden="current !== 1">
<div class="item">
<div class="acea-row row-between-wrapper">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-phone_"></use>
</svg>
<input type="text" placeholder="输入手机号码" v-model="account" />
</div>
</div>
<div class="item">
<div class="align-left">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_1"></use>
</svg>
<input
type="text"
placeholder="填写验证码"
class="codeIput"
v-model="captcha"
/>
<button
class="code"
:disabled="disabled"
:class="disabled === true ? 'on' : ''"
@click="code"
>
{{ text }}
</button>
</div>
</div>
</div>
<div class="logon" @click="loginMobile" :hidden="current !== 1">登录</div>
<div class="logon" @click="submit" :hidden="current === 1">登录</div>
<div class="tip">
没有账号?
<span @click="formItem = 2" class="font-color-red">立即注册</span>
</div>
</div>
<div class="whiteBg" v-else>
<div class="title">注册账号</div>
<div class="list">
<div class="item">
<div>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-phone_"></use>
</svg>
<input type="text" placeholder="输入手机号码" v-model="account" />
</div>
</div>
<div class="item">
<div class="align-left">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_1"></use>
</svg>
<input
type="text"
placeholder="填写验证码"
class="codeIput"
v-model="captcha"
/>
<button
class="code"
:disabled="disabled"
:class="disabled === true ? 'on' : ''"
@click="code"
>
{{ text }}
</button>
</div>
</div>
<div class="item">
<div>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_"></use>
</svg>
<input
type="password"
placeholder="填写您的登录密码"
v-model="password"
/>
</div>
</div>
</div>
<div class="logon" @click="register">注册</div>
<div class="tip">
已有账号?
<span @click="formItem = 1" class="font-color-red">立即登录</span>
</div>
</div>
<div class="bottom"></div>
</div>
</template>
<script>
import sendVerifyCode from "@/mixins/SendVerifyCode";
import { login, loginMobile, registerVerify, register } from "@/api/user";
import attrs, { required, alpha_num, chs_phone } from "@/utils/validate";
import { validatorDefaultCatch } from "@/utils/dialog";
import dayjs from "dayjs";
import cookie from "@/utils/store/cookie";
const BACK_URL = "login_back_url";
export default {
name: "Login",
mixins: [sendVerifyCode],
data: function() {
return {
navList: ["账号登录"],
current: 0,
account: "",
password: "",
captcha: "",
formItem: 1,
type: "login"
};
},
methods: {
async loginMobile() {
var that = this;
const { account, captcha } = that;
try {
await that
.$validator({
account: [
required(required.message("手机号码")),
chs_phone(chs_phone.message())
],
captcha: [
required(required.message("验证码")),
alpha_num(alpha_num.message("验证码"))
]
})
.validate({ account, captcha });
} catch (e) {
return validatorDefaultCatch(e);
}
loginMobile({
phone: that.account,
captcha: that.captcha,
spread: cookie.get("spread")
})
.then(res => {
var data = res.data;
that.$store.commit("LOGIN", data.token, dayjs(data.expires_time));
const backUrl = cookie.get(BACK_URL) || "/";
cookie.remove(BACK_URL);
that.$yrouter.replace({ path: backUrl });
})
.catch(res => {
that.$dialog.error(res.msg);
});
},
async register() {
var that = this;
const { account, captcha, password } = that;
try {
await that
.$validator({
account: [
required(required.message("手机号码")),
chs_phone(chs_phone.message())
],
captcha: [
required(required.message("验证码")),
alpha_num(alpha_num.message("验证码"))
],
password: [
required(required.message("密码")),
attrs.range([6, 16], attrs.range.message("密码")),
alpha_num(alpha_num.message("密码"))
]
})
.validate({ account, captcha, password });
} catch (e) {
return validatorDefaultCatch(e);
}
register({
account: that.account,
captcha: that.captcha,
password: that.password,
spread: cookie.get("spread")
})
.then(res => {
that.$dialog.success(res.msg);
that.formItem = 1;
})
.catch(res => {
that.$dialog.error(res.msg);
});
},
async code() {
var that = this;
const { account } = that;
try {
await that
.$validator({
account: [
required(required.message("手机号码")),
chs_phone(chs_phone.message())
]
})
.validate({ account });
} catch (e) {
return validatorDefaultCatch(e);
}
if (that.formItem == 2) that.type = "register";
await registerVerify({ phone: that.account, type: that.type })
.then(res => {
that.$dialog.success(res.msg);
that.sendCode();
})
.catch(res => {
that.$dialog.error(res.msg);
});
},
navTap: function(index) {
this.current = index;
},
async submit() {
console.log('spread:'+cookie.get("spread") )
const { account, password } = this;
try {
await this.$validator({
account: [
required(required.message("账号")),
attrs.range([5, 16], attrs.range.message("账号")),
alpha_num(alpha_num.message("账号"))
],
password: [
required(required.message("密码")),
attrs.range([6, 16], attrs.range.message("密码")),
alpha_num(alpha_num.message("密码"))
]
}).validate({ account, password });
} catch (e) {
return validatorDefaultCatch(e);
}
login({ username: account, password, spread: cookie.get("spread") })
.then(({ data }) => {
this.$store.commit("LOGIN", data.token, dayjs(data.expires_time));
const backUrl = cookie.get(BACK_URL) || "/";
cookie.remove(BACK_URL);
this.$yrouter.replace({ path: backUrl });
})
.catch(e => {
this.$dialog.error(e.msg);
});
}
}
};
</script>
+246
View File
@@ -0,0 +1,246 @@
<template>
<div class="personal-data">
<div class="wrapper">
<div class="title">管理我的账号</div>
<div class="wrapList">
<div
class="item acea-row row-between-wrapper"
:class="item.uid === userInfo.uid ? 'on' : ''"
v-for="(item, switchUserInfoIndex) in switchUserInfo"
:key="switchUserInfoIndex"
>
<div class="picTxt acea-row row-between-wrapper">
<div class="pictrue">
<!-- <VueCoreImageUpload
class="btn btn-primary"
:crop="false"
compress="80"
@imageuploaded="imageuploaded"
:headers="headers"
:max-file-size="5242880"
:credentials="false"
inputAccept="image/*"
inputOfFile="file"
:url="url"
ref="upImg"
v-if="item.uid === userInfo.uid"
>
<div class="pictrue">
<img :src="item.avatar" />
</div>
</VueCoreImageUpload>-->
<!-- <div class="pictrue" v-else>
<img :src="item.avatar" />
</div>-->
<img
:src="$VUE_APP_RESOURCES_URL+'/images/alter.png'"
class="alter"
v-if="item.uid === userInfo.uid"
/>
</div>
<div class="text">
<div class="name line1">{{ item.nickname }}</div>
<div class="phone">绑定手机号{{ item.phone }}</div>
</div>
</div>
<div
class="currentBnt acea-row row-center-wrapper font-color-red"
v-if="item.uid === userInfo.uid"
>当前账号</div>
<div
class="bnt font-color-red acea-row row-center-wrapper"
v-else
@click="switchAccounts(index)"
>使用账号</div>
</div>
</div>
</div>
<div class="list">
<div class="item acea-row row-between-wrapper">
<div>昵称</div>
<div class="input">
<input type="text" v-model="userInfo.nickname" />
</div>
</div>
<div class="item acea-row row-between-wrapper">
<div>ID号</div>
<div class="input acea-row row-between-wrapper">
<input type="text" :value="userInfo.uid" disabled class="id" />
<span class="iconfont icon-suozi"></span>
</div>
</div>
<div class="item acea-row row-between-wrapper">
<div>手机号</div>
<div class="input">
<input type="text" v-if="userInfo.phone" v-model="userInfo.phone" />
<input type="text" v-else value="未绑定" disabled class="id" />
</div>
</div>
<!--<div v-if="!userInfo.phone">-->
<!--<div-->
<!--@click="$yrouter.push('/pages/user/BindingPhone/index')"-->
<!--class="item acea-row row-between-wrapper"-->
<!--&gt;-->
<!--<div>绑定手机号</div>-->
<!--<div class="input">-->
<!--点击绑定手机号<span class="iconfont icon-xiangyou"></span>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--<div class="item acea-row row-between-wrapper" v-else-if="userInfo.phone">-->
<!--<div>手机号码</div>-->
<!--<div class="input acea-row row-between-wrapper">-->
<!--<div class="input acea-row row-between-wrapper">-->
<!--<input-->
<!--type="text"-->
<!--:value="userInfo.phone"-->
<!--disabled-->
<!--class="id"-->
<!--/><span class="iconfont icon-suozi"></span>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--<div v-if="userInfo.phone && userInfo.user_type === 'h5'">-->
<!--<div-->
<!--@click="$yrouter.push('/pages/user/ChangePassword/index')"-->
<!--class="item acea-row row-between-wrapper"-->
<!--&gt;-->
<!--<div>密码</div>-->
<!--<div class="input">-->
<!--点击修改密码<span class="iconfont icon-xiangyou"></span>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
</div>
<!--<div class="modifyBnt bg-color-red" @click="submit">保存修改</div>-->
<!-- <div
class="logOut cart-color acea-row row-center-wrapper"
@click="logout"
v-if="!isWeixin"
>
退出登录
</div>-->
</div>
</template>
<script>
import { mapGetters } from "vuex";
import { trim, isWeixin } from "@/utils";
import { VUE_APP_API_URL } from "@/config";
import { postUserEdit, getLogout, switchH5Login, getUser } from "@/api/user";
import cookie from "@/utils/store/cookie";
import store from "@//store";
import dayjs from "dayjs";
export default {
name: "PersonalData",
components: {
// VueCoreImageUpload
},
data: function() {
return {
url: `${VUE_APP_API_URL}/upload/image`,
headers: {
Authorization: "Bearer " + this.$store.state.token
},
avatar: "",
isWeixin: false,
currentAccounts: 0,
switchUserInfo: [],
userIndex: 0
};
},
watch: {
$yroute(n) {
if (n.name === "PersonalData") this.$store.dispatch("USERINFO", true);
}
},
computed: mapGetters(["userInfo"]),
mounted: function() {
this.avatar = this.userInfo.avatar;
this.isWeixin = isWeixin();
this.getUserInfo();
},
methods: {
switchAccounts: function(index) {
let that = this;
this.userIndex = index;
let userInfo = this.switchUserInfo[this.userIndex];
if (this.switchUserInfo.length <= 1) return true;
if (userInfo === undefined)
return this.$dialog.toast({ mes: "切换的账号不存在" });
if (userInfo.user_type === "h5") {
switchH5Login()
.then(({ data }) => {
wx.hideLoading();
const expires_time = dayjs(data.expires_time);
store.commit("LOGIN", data.token, expires_time);
that.$emit("changeswitch", false);
location.reload();
})
.catch(err => {
wx.hideLoading();
return that.$dialog.toast({ mes: err });
});
} else {
cookie.set("loginType", "wechat", 60);
wx.hideLoading();
this.$store.commit("LOGOUT");
this.$emit("changeswitch", false);
}
},
getUserInfo: function() {
let that = this;
getUser().then(res => {
let switchUserInfo = res.data.switchUserInfo;
for (let i = 0; i < switchUserInfo.length; i++) {
if (switchUserInfo[i].uid == that.userInfo.uid) that.userIndex = i;
if (
!that.isWeixin &&
switchUserInfo[i].user_type != "h5" &&
switchUserInfo[i].phone === ""
)
switchUserInfo.splice(i, 1);
}
that.$set(this, "switchUserInfo", switchUserInfo);
});
},
imageuploaded(res) {
if (res.status !== 200)
return this.$dialog.error(res.msg || "上传图片失败");
if (this.switchUserInfo[this.userIndex] === undefined) return;
this.$set(this.switchUserInfo[this.userIndex], "avatar", res.data.url);
},
submit: function() {
let userInfo = this.switchUserInfo[this.userIndex];
postUserEdit({
nickname: trim(this.userInfo.nickname),
avatar: userInfo.avatar
}).then(
res => {
this.$store.dispatch("USERINFO", true);
this.$wx.showToast({ title: res.msg, icon: "none", duration: 2000 });
this.$yrouter.back();
},
error => {
this.$dialog.error(error.msg);
}
);
},
logout: function() {
this.$dialog.confirm({
mes: "确认退出登录?",
opts: () => {
getLogout()
.then(res => {
this.$store.commit("LOGOUT");
clearAuthStatus();
location.href = location.origin;
})
.catch(err => {});
}
});
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+239
View File
@@ -0,0 +1,239 @@
<template>
<div>
<div class="recharge">
<div class="nav acea-row row-around row-middle">
<div
class="item"
:class="active === navRechargeIndex ? 'on' : ''"
v-for="(item, navRechargeIndex) in navRecharge"
:key="navRechargeIndex"
@click="navRecharges(navRechargeIndex)"
>{{ item }}</div>
</div>
<div class="info-wrapper">
<div class="money">
<span></span>
<input type="number" placeholder="0.00" v-model="money" />
</div>
<div class="tips" v-if="!active">
提示当前余额为
<span>{{ now_money || 0 }}</span>
</div>
<div class="pay-btn bg-color-red" @click="recharge">{{ active ? "立即转入" : "立即充值" }}</div>
</div>
</div>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import { weapppay } from "@/libs/wechat";
import { isWeixin } from "@/utils";
import { rechargeWechat } from "@/api/user";
import { add, sub } from "@/utils/bc";
export default {
name: "Recharge",
components: {},
props: {},
data: function() {
return {
navRecharge: ["账户充值"],
active: 0,
payType: ["weixin"],
from: isWeixin() ? "weixin" : "weixinh5",
money: "",
now_money: ""
};
},
computed: mapGetters(["userInfo"]),
mounted: function() {
this.now_money = this.userInfo.now_money;
},
methods: {
navRecharges: function(index) {
this.active = index;
},
recharge: function() {
let that = this,
price = Number(this.money);
if (that.active) {
if (price === 0) {
return that.$dialog.toast({ mes: "请输入您要转入的金额" });
} else if (price < 0.01) {
return that.$dialog.toast({ mes: "转入金额不能低于0.01" });
}
this.$dialog.confirm({
mes: "转入余额无法在转出,请确认转入",
title: "转入余额",
opts: [
{
txt: "确认",
color: false,
callback: () => {
rechargeWechat({ price: price, from: that.from, type: 1 })
.then(res => {
that.now_money = add(
price,
parseInt(that.userInfo.now_money)
);
that.userInfo.brokerage_price = sub(
that.userInfo.brokerage_price,
price
);
that.money = "";
return that.$dialog.toast({ mes: res.msg });
})
.catch(res => {
that.$dialog.toast({ mes: res.msg });
});
}
},
{
txt: "取消",
color: false,
callback: () => {
return that.$dialog.toast({ mes: "已取消" });
}
}
]
});
} else {
if (price === 0) {
return that.$dialog.toast({ mes: "请输入您要充值的金额" });
} else if (price < 0.01) {
return that.$dialog.toast({ mes: "充值金额不能低于0.01" });
}
rechargeWechat({ price: price, from: that.from })
.then(res => {
var data = res.data;
if (data.type == "weixinh5") {
location.replace(data.data.mweb_url);
this.$dialog.confirm({
mes: "充值余额",
opts: [
{
txt: "已充值",
color: false,
callback: () => {
that.$yrouter.replace({
path: "/user/account"
});
}
},
{
txt: "查看余额",
color: false,
callback: () => {
that.$yrouter.replace({
path: "/user/account"
});
}
}
]
});
} else {
weappPay(data.data)
.then(res => {
that.now_money = add(
price,
parseInt(that.userInfo.now_money)
);
that.$dialog.toast({ mes: "支付成功" });
})
.catch(function() {
that.$dialog.toast({ mes: "支付失败" });
});
}
})
.catch(res => {
that.$dialog.toast({ mes: res.msg });
});
}
}
}
};
</script>
<style scoped>
#iframe {
display: none;
}
.recharge {
width: 7.03rem;
padding: 0.5rem 0.63rem 0.45rem;
background-color: #fff;
margin: 0.2rem auto 0 auto;
border-radius: 0.1rem;
}
.recharge .nav {
height: 0.75rem;
line-height: 0.75rem;
padding: 0 1rem;
}
.recharge .nav .item {
font-size: 0.3rem;
color: #333;
}
.recharge .nav .item.on {
font-weight: bold;
border-bottom: 0.04rem solid #e83323;
}
.recharge .info-wrapper {
text-align: center;
}
.recharge .info-wrapper .money {
margin-top: 0.6rem;
padding-bottom: 0.2rem;
border-bottom: 1px dashed #ddd;
}
.recharge .info-wrapper .money span {
font-size: 0.56rem;
color: #333;
font-weight: bold;
}
.recharge .info-wrapper .money input {
display: inline-block;
width: 3rem;
font-size: 0.84rem;
text-align: center;
color: #282828;
font-weight: bold;
padding-right: 0.7rem;
}
.recharge .info-wrapper .money input::placeholder {
color: #ddd;
}
.recharge .info-wrapper .money input::-webkit-input-placeholder {
color: #ddd;
}
.recharge .info-wrapper .money input:-moz-placeholder {
color: #ddd;
}
.recharge .info-wrapper .money input::-moz-placeholder {
color: #ddd;
}
.recharge .info-wrapper .money input:-ms-input-placeholder {
color: #ddd;
}
.recharge .info-wrapper .tips {
font-size: 0.26rem;
color: #888;
margin: 0.25rem auto 0 auto;
line-height: 1.5;
padding: 0 0.3rem;
}
.recharge .info-wrapper .tips span {
color: #ef4a49;
}
.recharge .info-wrapper .pay-btn {
display: block;
width: 5.5rem;
height: 0.86rem;
margin: 0.5rem auto 0 auto;
line-height: 0.86rem;
text-align: center;
color: #fff;
border-radius: 0.5rem;
font-size: 0.3rem;
font-weight: bold;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+68
View File
@@ -0,0 +1,68 @@
<template>
<div class="register absolute">
<div class="shading">
<div class="pictrue acea-row row-center-wrapper">
<img src="@/assets/images/logo.png" />
</div>
</div>
<div class="whiteBg">
<div class="title">注册账号</div>
<div class="list">
<div class="item">
<div>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-phone_"></use>
</svg>
<input type="text" placeholder="输入手机号码" />
</div>
</div>
<div class="item">
<div class="align-left">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_1"></use>
</svg>
<input type="text" placeholder="填写验证码" class="codeIput" />
<button
class="code"
:disabled="disabled"
:class="disabled === true ? 'on' : ''"
@click="code"
>
{{ text }}
</button>
</div>
</div>
<div class="item">
<div>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_"></use>
</svg>
<input type="text" placeholder="填写您的登录密码" />
</div>
</div>
</div>
<div class="logon">注册</div>
<div class="tip">
已有账号?
<span @click="$yrouter.push({ name: 'Login' })" class="font-color-red"
>立即登录</span
>
</div>
</div>
<div class="bottom"></div>
</div>
</template>
<script>
import sendVerifyCode from "@/mixins/SendVerifyCode";
export default {
name: "Register",
mixins: [sendVerifyCode],
methods: {
code: function() {
this.sendCode();
}
}
};
</script>
+145
View File
@@ -0,0 +1,145 @@
<template>
<div class="register absolute">
<div class="shading">
<div class="pictrue acea-row row-center-wrapper">
<img src="@/assets/images/logo.png" />
</div>
</div>
<div class="whiteBg">
<div class="title">找回密码</div>
<div class="list">
<div class="item">
<div>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-phone_"></use>
</svg>
<input type="text" placeholder="输入手机号码" v-model="account" />
</div>
</div>
<div class="item">
<div class="align-left">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_1"></use>
</svg>
<input
type="text"
placeholder="填写验证码"
class="codeIput"
v-model="captcha"
/>
<button
class="code"
:disabled="disabled"
:class="disabled === true ? 'on' : ''"
@click="code"
>
{{ text }}
</button>
</div>
</div>
<div class="item">
<div>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_"></use>
</svg>
<input
type="password"
placeholder="填写您的登录密码"
v-model="password"
/>
</div>
</div>
</div>
<div class="logon" @click="registerReset">确认</div>
<div class="tip">
<span @click="$yrouter.push({ name: 'Login' })" class="font-color-red"
>立即登录</span
>
</div>
</div>
<div class="bottom"></div>
</div>
</template>
<script>
import sendVerifyCode from "@/mixins/SendVerifyCode";
import { registerVerify, registerReset } from "@/api/user";
import { validatorDefaultCatch } from "@/utils/dialog";
import attrs, { required, alpha_num, chs_phone } from "@/utils/validate";
export default {
name: "RetrievePassword",
data: function() {
return {
account: "",
password: "",
captcha: ""
};
},
mixins: [sendVerifyCode],
methods: {
async registerReset() {
var that = this;
const { account, captcha, password } = that;
try {
await that
.$validator({
account: [
required(required.message("手机号码")),
chs_phone(chs_phone.message())
],
captcha: [
required(required.message("验证码")),
alpha_num(alpha_num.message("验证码"))
],
password: [
required(required.message("密码")),
attrs.range([6, 16], attrs.range.message("密码")),
alpha_num(alpha_num.message("密码"))
]
})
.validate({ account, captcha, password });
} catch (e) {
return validatorDefaultCatch(e);
}
registerReset({
account: that.account,
captcha: that.captcha,
password: that.password
})
.then(res => {
that.$dialog.success(res.msg).then(() => {
that.$yrouter.push({ name: "Login" });
});
})
.catch(res => {
that.$dialog.error(res.msg);
});
},
async code() {
var that = this;
const { account } = that;
try {
await that
.$validator({
account: [
required(required.message("手机号码")),
chs_phone(chs_phone.message())
]
})
.validate({ account });
} catch (e) {
return validatorDefaultCatch(e);
}
registerVerify({ phone: that.account })
.then(res => {
that.$dialog.success(res.msg);
that.sendCode();
})
.catch(res => {
that.$dialog.error(res.msg);
});
}
}
};
</script>
+319
View File
@@ -0,0 +1,319 @@
<template>
<div class="user">
<div class="header bg-color-red acea-row row-between-wrapper">
<div class="picTxt acea-row row-between-wrapper">
<div class="pictrue">
<img :src="userInfo.avatar" />
</div>
<div class="text">
<div class="acea-row row-middle">
<div class="name line1">{{ userInfo.nickname }}</div>
<div class="member acea-row row-middle" v-if="userInfo.vip">
<img :src="userInfo.vipIcon" />
{{ userInfo.vipName }}
</div>
</div>
<div
@click="$yrouter.push('/pages/user/PersonalData/index')"
class="id"
v-if="userInfo.phone"
>
ID{{ userInfo.uid || 0
}}
<span class="iconfont icon-bianji1"></span>
</div>
<button
open-type="getPhoneNumber"
@getphonenumber="getPhoneNumber"
class="binding"
v-else
>
<span>绑定手机号</span>
</button>
</div>
</div>
<span
class="iconfont icon-shezhi"
@click="$yrouter.push({ path: '/pages/user/PersonalData/index' })"
></span>
</div>
<div class="wrapper">
<div class="nav acea-row row-middle">
<div @click="$yrouter.push({ path: '/pages/user/UserAccount/index' })" class="item">
<div>我的余额</div>
<div class="num">{{ userInfo.nowMoney || 0 }}</div>
</div>
<div
@click="$yrouter.push('/pages/user/promotion/UserPromotion/index')"
class="item"
v-if="userInfo.isPromoter === 1 || userInfo.statu === 2"
>
<div>当前佣金</div>
<div class="num">{{ userInfo.brokeragePrice || 0 }}</div>
</div>
<div @click="$yrouter.push('/pages/user/signIn/Integral/index')" class="item" v-else>
<div>当前积分</div>
<div class="num">{{ userInfo.integral || 0 }}</div>
</div>
<div @click="$yrouter.push('/pages/user/coupon/UserCoupon/index')" class="item">
<div>优惠券</div>
<div class="num">{{ userInfo.couponCount || 0 }}</div>
</div>
</div>
<div class="myOrder">
<div class="title acea-row row-between-wrapper">
<div>我的订单</div>
<div @click="$yrouter.push('/pages/order/MyOrder/index')" class="allOrder">
全部订单
<span class="iconfont icon-jiantou"></span>
</div>
</div>
<div class="orderState acea-row row-middle">
<div
@click="$yrouter.push({ path: '/pages/order/MyOrder/index',query:{type:0}})"
class="item"
>
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL + '/images/dfk.png'" />
<span
class="order-status-num"
v-if="orderStatusNum.unpaidCount > 0"
>{{ orderStatusNum.unpaidCount }}</span>
</div>
<div>待付款</div>
</div>
<div
@click="$yrouter.push({ path: '/pages/order/MyOrder/index',query:{type:1} })"
class="item"
>
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/dfh.png'" />
<span
class="order-status-num"
v-if="orderStatusNum.unshippedCount > 0"
>{{ orderStatusNum.unshippedCount }}</span>
</div>
<div>待发货</div>
</div>
<div
@click="$yrouter.push({ path: '/pages/order/MyOrder/index',query:{type:2}})"
class="item"
>
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/dsh.png'" />
<span
class="order-status-num"
v-if="orderStatusNum.receivedCount > 0"
>{{ orderStatusNum.receivedCount }}</span>
</div>
<div>待收货</div>
</div>
<div
@click="$yrouter.push({ path: '/pages/order/MyOrder/index',query:{type:3} })"
class="item"
>
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/dpj.png'" />
<span
class="order-status-num"
v-if="orderStatusNum.evaluatedCount > 0"
>{{ orderStatusNum.evaluatedCount }}</span>
</div>
<div>待评价</div>
</div>
<div @click="$yrouter.push('/pages/order/ReturnList/index')" class="item">
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/sh.png'" />
<span
class="order-status-num"
v-if="orderStatusNum.refundCount > 0"
>{{ orderStatusNum.refundCount }}</span>
</div>
<div>售后/退款</div>
</div>
</div>
</div>
<div class="myService">
<div class="title acea-row row-middle">我的服务</div>
<div class="serviceList acea-row row-middle">
<template v-for="(item, MyMenusIndex) in MyMenus">
<div class="item" :key="MyMenusIndex" @click="goPages(MyMenusIndex)" v-if="item.url">
<div class="pictrue">
<img :src="item.pic" />
</div>
<div>{{ item.name }}</div>
</div>
</template>
<!--<div-->
<!--class="item"-->
<!--@click="changeswitch(true)"-->
<!--v-if="userInfo.phone && isWeixin"-->
<!--&gt;-->
<!--<div class="pictrue"><img :src="$VUE_APP_RESOURCES_URL+'/images/switch.png'" /></div>-->
<!--<div>账号切换</div>-->
<!--</div>-->
</div>
</div>
</div>
<p style="text-align: center;margin-top: 1rem">By@意象</p>
<div class="footer-line-height"></div>
<SwitchWindow
v-on:changeswitch="changeswitch"
:switchActive="switchActive"
:login_type="userInfo.login_type"
></SwitchWindow>
</div>
</template>
<script>
import { getUser, getMenuUser, bindingPhone } from "@/api/user";
import { isWeixin, VUE_APP_RESOURCES_URL } from "@/utils";
import SwitchWindow from "@/components/SwitchWindow";
import { mapGetters } from "vuex";
const NAME = "User";
export default {
name: NAME,
components: {
SwitchWindow
},
props: {},
data: function() {
return {
userInfo: {},
MyMenus: [],
orderStatusNum: {},
switchActive: false,
isWeixin: false
};
},
computed: mapGetters(["wxCode"]),
watch: {
$yroute(n) {
if (n.name === NAME) this.User();
}
},
mounted: function() {
console.log('这个是个人中心')
this.User();
this.MenuUser();
this.isWeixin = isWeixin();
},
methods: {
getPhoneNumber: function(e) {
console.log(e.mp.detail);
if (e.mp.detail.errMsg == "getPhoneNumber:ok") {
wx.showLoading({ title: "绑定中" });
wx.login({
success: loginRes => {
bindingPhone({
code: loginRes.code,
encryptedData: e.mp.detail.encryptedData,
iv: e.mp.detail.iv
})
.then(res => {
this.User();
wx.hideLoading();
wx.showToast({
title: res.msg,
icon: "success",
duration: 2000
});
})
.catch(error => {
wx.showToast({
title: error.msg || error.response.data.msg,
icon: "none",
duration: 2000
});
});
}
});
} else {
wx.showToast({
title: "已拒绝授权",
icon: "none",
duration: 2000
});
}
},
changeswitch: function(data) {
this.switchActive = data;
},
User: function() {
let that = this;
getUser().then(res => {
that.userInfo = res.data;
that.orderStatusNum = res.data.orderStatusNum;
});
},
MenuUser: function() {
let that = this;
getMenuUser().then(res => {
that.MyMenus = res.data.routine_my_menus;
});
},
goPages: function(index) {
let url = this.MyMenus[index].wxapp_url;
if (
url === "/pages/user/promotion/UserPromotion/main" &&
this.userInfo.statu === 1
) {
if (!this.userInfo.isPromoter)
return this.$dialog.toast({ mes: "您还没有推广权限!!" });
}
if (
url === "/pages/orderAdmin/OrderIndex/main" &&
!this.userInfo.adminid
) {
return this.$dialog.toast({ mes: "您还不是管理员!!" });
}
this.$yrouter.push({ path: this.MyMenus[index].wxapp_url });
}
},
onShow() {
this.User();
this.MenuUser();
this.isWeixin = isWeixin();
}
};
</script>
<style>
.footer-line-height {
height: 1rem;
}
.order-status-num {
min-width: 0.33rem;
background-color: #fff;
color: #73cbb6;
border-radius: 15px;
position: absolute;
right: -0.14rem;
top: -0.15rem;
font-size: 0.2rem;
padding: 0 0.08rem;
border: 1px solid #73cbb6;
}
.pictrue {
position: relative;
}
.switch-h5 {
margin-left: 0.2rem;
}
.binding {
margin-top: 0.1rem;
display: inline-block;
padding: 0.05rem 0.2rem;
background-color: #ca1f10;
border-radius: 50px;
font-size: 0.22rem;
line-height: 1.5;
border: 1px solid #e8695e;
color: #ffffff;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+93
View File
@@ -0,0 +1,93 @@
<template>
<div class="my-account">
<div class="wrapper">
<div class="header">
<div class="headerCon">
<div class="account acea-row row-top row-between">
<div class="assets">
<div>总资产()</div>
<div class="money">{{ now_money }}</div>
</div>
</div>
<div class="cumulative acea-row row-top">
<div class="item">
<div>累计消费()</div>
<div class="money">{{ orderStatusSum }}</div>
</div>
</div>
</div>
</div>
<div class="nav acea-row row-middle">
<div class="item" @click="$yrouter.push({path:'/pages/user/UserBill/index',query:{id:0}})">
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/record1.png'" />
</div>
<div>账单记录</div>
</div>
<div class="item" @click="$yrouter.push({path:'/pages/user/UserBill/index',query:{id:1}})">
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/record2.png'" />
</div>
<div>消费记录</div>
</div>
</div>
<div class="advert acea-row row-between-wrapper"></div>
</div>
<Recommend></Recommend>
</div>
</template>
<script>
import Recommend from "@/components/Recommend";
import { getActivityStatus, getBalance } from "@/api/user";
export default {
name: "UserAccount",
components: {
Recommend
},
props: {},
data: function() {
return {
now_money: 0,
orderStatusSum: 0,
recharge: 0,
activity: {
is_bargin: false,
is_pink: false,
is_seckill: false
}
};
},
mounted: function() {
this.getIndex();
this.getActivity();
},
methods: {
getIndex: function() {
let that = this;
getBalance().then(
res => {
that.now_money = res.data.now_money;
that.orderStatusSum = res.data.orderStatusSum;
that.recharge = res.data.recharge;
},
err => {
that.$dialog.message(err.msg);
}
);
},
getActivity: function() {
let that = this;
getActivityStatus().then(
res => {
that.activity.is_bargin = res.data.is_bargin;
that.activity.is_pink = res.data.is_pink;
that.activity.is_seckill = res.data.is_seckill;
},
error => {
that.$dialog.message(error.msg);
}
);
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+105
View File
@@ -0,0 +1,105 @@
<template>
<div class="bill-details" ref="container">
<div class="nav acea-row">
<div class="item" :class="types == 0 ? 'on' : ''" @click="changeTypes(0)">全部</div>
<div class="item" :class="types == 1 ? 'on' : ''" @click="changeTypes(1)">消费</div>
</div>
<div class="sign-record">
<div class="list">
<div class="item" v-for="(item, listIndex) in list" :key="listIndex">
<div class="data">{{ item.time }}</div>
<div class="listn" v-for="(val, key) in item.list" :key="key">
<div class="itemn acea-row row-between-wrapper">
<div>
<div class="name line1">{{ val.title }}</div>
<div>{{ val.add_time }}</div>
</div>
<div
class="num"
:class="val.pm == 0 ? 'font-color-red' : ''"
>{{ val.pm == 0 ? "-" : "+" }}{{ val.number }}</div>
</div>
</div>
</div>
</div>
</div>
<Loading :loaded="loaded" :loading="loading"></Loading>
</div>
</template>
<script>
import { getCommissionInfo } from "@/api/user";
import Loading from "@/components/Loading";
export default {
name: "UserBill",
components: {
Loading
},
props: {},
data: function() {
return {
types: "",
where: {
page: 1,
limit: 5
},
list: [],
loaded: false,
loading: false
};
},
watch: {
"$yroute.query.types": function(newVal) {
let that = this;
if (newVal != undefined) {
that.types = newVal;
that.list = [];
that.where.page = 1;
that.loaded = false;
that.loading = false;
that.getIndex();
}
},
types: function() {
this.getIndex();
}
},
mounted: function() {
let that = this;
that.types = that.$yroute.query.types;
that.getIndex();
},
onReachBottom() {
!that.loading && that.getIndex();
},
methods: {
code: function() {
this.sendCode();
},
changeTypes: function(val) {
if (val != this.types) {
this.types = val;
this.list = [];
this.where.page = 1;
this.loaded = false;
this.loading = false;
}
},
getIndex: function() {
let that = this;
if (that.loaded == true || that.loading == true) return;
that.loading = true;
getCommissionInfo(that.where, that.types).then(
res => {
that.loading = false;
that.loaded = res.data.length < that.where.limit;
that.where.page = that.where.page + 1;
that.list.push.apply(that.list, res.data);
},
error => {
that.$dialog.message(error.msg);
}
);
}
}
};
</script>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+203
View File
@@ -0,0 +1,203 @@
<template>
<div class="member-center">
<div class="header">
<div class="slider-banner banner">
<swiper indicatorDots="true" @change="swiperChange">
<block v-for="(item, vipListIndex) in vipList" :key="vipListIndex">
<swiper-item>
<div class="swiper-slide" :style="{ backgroundImage: 'url(' + item.image + ')' }">
<!-- <img :src="item.icon" />-->
<div class="name">{{ item.name }}</div>
<div class="discount">
可享受商品折扣: {{ item.discount / 10 }}
<span class="iconfont icon-zhekou"></span>
</div>
<div class="nav acea-row" v-if="item.grade == grade">
<div class="item" v-for="(val, indexn) in vipComplete" :key="indexn">
<div class="num">{{ val.newNumber }}</div>
<div>{{ val.realName }}</div>
</div>
</div>
<div class="lock" v-if="item.grade > grade">
<span class="iconfont icon-quanxianguanlisuozi"></span>该会员等级尚未解锁
</div>
<div class="lock" v-if="item.grade < grade">
<span class="iconfont icon-xuanzhong1"></span>已解锁更高等级
</div>
</div>
</swiper-item>
</block>
</swiper>
</div>
</div>
<div class="wrapper">
<div class="title acea-row row-between-wrapper">
<div>
<span class="iconfont icon-jingyanzhi"></span>会员升级要求
</div>
<div class="num">
<span class="current">{{ taskCount }}</span>
/{{ vipRequire.length }}
</div>
</div>
<div class="list">
<div class="item" v-for="(item, vipCompleteIndex) in vipComplete" :key="vipCompleteIndex">
<div class="top acea-row row-between-wrapper">
<div class="name">
{{ item.name
}}
<span
class="iconfont icon-wenti"
v-if="item.illustrate"
@click="showGrow(item)"
></span>
</div>
<div>{{ item.finish ? "已满足条件" : "未满足条件" }}</div>
</div>
<div class="cu-progress">
<div class="bg-red" :style="{ width: item.speed + '%' }"></div>
</div>
<div class="experience acea-row row-between-wrapper">
<div>{{ item.taskTypeTitle }}</div>
<div>
<span class="num">{{ item.newNumber }}</span>
/{{ item.number }}
</div>
</div>
</div>
</div>
</div>
<Recommend></Recommend>
<div class="growthValue" :class="growthValue === false ? 'on' : ''">
<div class="pictrue">
<img :src="$VUE_APP_RESOURCES_URL+'/images/value.jpg'" />
<span class="iconfont icon-guanbi3" @click="growthTap"></span>
</div>
<div class="conter">{{ illustrate }}</div>
</div>
<div class="mask" :hidden="growthValue" @click="growthTap"></div>
</div>
</template>
<script>
// import { swiper, swiperSlide } from "vue-awesome-swiper";
import Recommend from "@/components/Recommend";
import { getVipInfo, getVipTask, setDetection } from "@/api/user";
export default {
name: "Poster",
components: {
// swiper,
// swiperSlide,
Recommend
},
props: {},
data: function() {
return {
vipList: [], //等级列表
vipRequire: [], //等级要求
vipComplete: [], //完成情况
taskCount: 0, //任务数
grade: 0, //当前会员等级
swiperVip: {
speed: 1000,
effect: "coverflow",
slidesPerView: "auto",
centeredSlides: true,
// loop: true,
coverflowEffect: {
rotate: 0, // 旋转的角度
stretch: -20, // 拉伸 图片间左右的间距和密集度
depth: 100, // 深度 切换图片间上下的间距和密集度
modifier: 2, // 修正值 该值越大前面的效果越明显
slideShadows: false // 页面阴影效果
},
observer: true,
observeParents: true
},
loading: false,
growthValue: true,
illustrate: "",
activeIndex: 0
};
},
watch: {
vipList: function() {
let that = this;
if (that.vipList.length > 0) {
that.vipList.forEach(function(item, index) {
if (item.isClear === false) {
// that.swiper.slideTo(index);
that.activeIndex = index;
that.grade = item.grade;
}
});
}
}
},
computed: {
swiper() {
// return this.$refs.mySwiper.swiper;
}
},
mounted: function() {
let that = this;
setDetection();
that.getInfo();
// that.swiper.on("slideChange", function() {
// that.activeIndex = that.swiper.activeIndex;
// that.getTask();
// });
},
methods: {
swiperChange: function(e) {
let that = this;
that.activeIndex = e.mp.detail.current;
that.getTask();
},
growthTap: function() {
this.growthValue = true;
},
getInfo: function() {
let that = this;
getVipInfo().then(
res => {
that.vipList = res.data.list;
that.vipRequire = res.data.task.list;
that.vipComplete = res.data.task.task;
that.taskCount = res.data.task.reachCount;
},
err => {
that.$dialog.message(err.msg);
}
);
},
getTask: function() {
let that = this;
getVipTask(that.vipList[that.activeIndex].id).then(
res => {
that.vipRequire = res.data.list;
that.vipComplete = res.data.task;
that.taskCount = res.data.reach_count;
},
err => {
that.$dialog.message(err.msg);
}
);
},
showGrow: function(item) {
if (this.illustrate != item.illustrate) this.illustrate = item.illustrate;
this.growthValue = false;
}
}
};
</script>
<style>
.banner swiper {
height: 328rpx;
}
.swiper-slide {
margin: 0 auto;
}
</style>
+5
View File
@@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
+158
View File
@@ -0,0 +1,158 @@
<template>
<div class="addAddress absolute">
<div class="list">
<div class="item acea-row row-between-wrapper">
<div class="name">姓名</div>
<input type="text" placeholder="请输入姓名" v-model="userAddress.realName" required />
</div>
<div class="item acea-row row-between-wrapper">
<div class="name">联系电话</div>
<input type="text" placeholder="请输入联系电话" v-model="userAddress.phone" required />
</div>
<div class="item acea-row row-between-wrapper">
<div class="name">所在地区</div>
<div class="picker acea-row row-between-wrapper select-value form-control">
<div class="address">
<div slot="right" @click.stop="show2 = true">{{ model2 || "请选择收货地址" }}</div>
<vant-popup :show="show2" position="bottom" @close="closeaArea">
<vant-area
:area-list="district"
columns-num="3"
:columns-placeholder="['请选择', '请选择', '请选择']"
title="请选择"
@confirm="result2"
/>
</vant-popup>
</div>
<div class="iconfont icon-dizhi font-color-red"></div>
</div>
</div>
<div class="item acea-row row-between-wrapper">
<div class="name">详细地址</div>
<input type="text" placeholder="请填写具体地址" v-model="userAddress.detail" required />
</div>
</div>
<div class="default acea-row row-middle">
<div class="select-btn">
<div class="checkbox-wrapper">
<checkbox-group @change="ChangeIsDefault">
<label class="well-check">
<checkbox value :checked="userAddress.isDefault ? true : false"></checkbox>
<span class="def">设置为默认地址</span>
</label>
</checkbox-group>
</div>
</div>
</div>
<div></div>
<div class="keepBnt bg-color-red" @click="submit">立即保存</div>
<div class="wechatAddress" v-if="isWechat && !id" @click="getAddress">导入微信地址</div>
</div>
</template>
<script type="text/babel">
// import { CitySelect } from "vue-ydui/dist/lib.rem/cityselect";
// import District from "@/utils/area";
import { getAddress, postAddress, district } from "@/api/user";
import attrs, { required, chs_phone } from "@/utils/validate";
import { validatorDefaultCatch } from "@/utils/dialog";
// import { openAddress } from "@/libs/wechat";
import { isWeixin } from "@/utils";
export default {
components: {
// CitySelect
},
data() {
return {
show2: false,
model2: "",
district: {},
id: 0,
userAddress: { isDefault: 0 },
address: {},
isWechat: isWeixin()
};
},
mounted: function() {
let id = this.$yroute.query.id;
this.id = id;
// document.title = !id ? "添加地址" : "修改地址";
this.getUserAddress();
district().then(res => {
this.district = res.data;
});
},
methods: {
getUserAddress: function() {
if (!this.id) return false;
let that = this;
getAddress(that.id).then(res => {
that.userAddress = res.data;
that.model2 =
res.data.province + " " + res.data.city + " " + res.data.district;
that.address.province = res.data.province;
that.address.city = res.data.city;
that.address.district = res.data.district;
});
},
getAddress() {},
async submit() {
let name = this.userAddress.realName,
phone = this.userAddress.phone,
model2 = this.model2,
detail = this.userAddress.detail,
isDefault = this.userAddress.isDefault;
try {
await this.$validator({
name: [
required(required.message("姓名")),
attrs.range([2, 16], attrs.range.message("姓名"))
],
phone: [
required(required.message("联系电话")),
chs_phone(chs_phone.message())
],
model2: [required("请选择地址")],
detail: [required(required.message("具体地址"))]
}).validate({ name, phone, model2, detail });
} catch (e) {
return validatorDefaultCatch(e);
}
try {
let that = this,
data = {
id: that.id,
real_name: name,
phone: phone,
address: this.address,
detail: detail,
is_default: isDefault,
post_code: ""
};
postAddress(data).then(function() {
if (that.id) that.$dialog.toast({ mes: "修改成功" });
else that.$dialog.toast({ mes: "添加成功" });
that.$yrouter.go(-1);
});
} catch (e) {
this.$dialog.error(e.msg);
}
},
ChangeIsDefault: function() {
this.userAddress.isDefault = !this.userAddress.isDefault;
},
closeaArea() {
this.show2 = false;
},
result2(ret) {
let values = ret.mp.detail.values;
this.closeaArea();
this.address.province = values[0].name || "";
this.address.city = values[1].name || "";
this.address.district = values[2].name || "";
this.model2 =
this.address.province + this.address.city + this.address.district;
}
}
};
</script>

Some files were not shown because too many files have changed in this diff Show More