Init project

This commit is contained in:
lifizer
2023-09-20 21:49:33 +08:00
parent 85a5989c96
commit c9ceac9f37
710 changed files with 125705 additions and 0 deletions
@@ -0,0 +1,266 @@
<template>
<view class="container">
<view class="section-header acea-row row-middle row-between">
<view class="section-title">直播</view>
<view class="section-more" @click="toMoreLive()">更多>></view>
</view>
<view class="video-list" v-if="liveList.length>0">
<view class="video-list-item acea-row row-column" v-for="(video,index) in liveList" :key="index" @click="liveClick(video)">
<view class="video-img">
<image :src="video.coverImge || webUrl+'/20230304100226088424.jpg'" mode="scaleToFill"></image>
<view class="live-status-tag acea-row row-center">
<text style="color: #FFFFFF;font-size: 28rpx;font-weight: bold;">{{liveStatusText(video.liveStatus)}}</text>
</view>
</view>
<view class="video-title line2">{{video.name}}</view>
<view class="video-shop acea-row row-middle row-between" style="flex-wrap: nowrap;">
<view class="acea-row row-middle" style="flex-wrap: nowrap;">
<image style="width: 48rpx;height: 48rpx;border-radius: 50%;margin-right: 8rpx;" src="http://image.xdd618.com/logo.png" mode=""></image>
<!-- <text>{{video.storeName}}</text> -->
<text>香道滇官方商城</text>
</view>
<image style="width: 48rpx;height: 48rpx;border-radius: 50%;flex-shrink: 0;" :src="webUrl+'/20210203151253323822.png.png'" mode=""></image>
</view>
</view>
</view>
<view class="section-header acea-row row-middle row-between">
<view class="section-title">视频</view>
<view class="section-more" @click="toMoreVideo()">更多>></view>
</view>
<view class="video-list" v-if="videoList.length>0">
<view class="video-list-item acea-row row-column" v-for="(video,index) in videoList" :key="index" @click="videoClick(video)">
<view class="video-img">
<image :src="video.cover || webUrl+'/20230304100226088424.jpg'" mode="scaleToFill"></image>
</view>
<view class="video-title line2">{{video.title}}</view>
<view class="video-shop acea-row row-middle row-between" style="flex-wrap: nowrap;">
<view class="acea-row row-middle" style="flex-wrap: nowrap;">
<image style="width: 48rpx;height: 48rpx;border-radius: 50%;margin-right: 8rpx;" :src="video.storeLogo" mode=""></image>
<text>{{video.storeName}}</text>
</view>
<image style="width: 48rpx;height: 48rpx;border-radius: 50%;flex-shrink: 0;" :src="webUrl+'/20210203151253323822.png.png'" mode=""></image>
</view>
</view>
</view>
<uni-popup ref="popup" type="center">
<video id="myVideo" autoplay :src="curPlayVideoUrl" @error="videoErrorCallback" controls></video>
</uni-popup>
</view>
</template>
<script>
import uniPopup from '@/components/uni-popup/uni-popup.vue';
import { getVideoList } from "@/api/user";
import {
getWxLiveList
} from '@/api/public';
export default {
components:{
uniPopup
},
data() {
return {
webUrl:this.$VUE_APP_RESOURCES_URL,
liveList:[],//直播列表
videoList:[],//短视频列表
curPlayVideoUrl:'',
isVideoPopupShow:false
}
},
onLoad:function(e){
},
onReady: function(res) {
this.getLiveList();
this.getVideoList();
},
methods: {
getLiveList:function(){
var _this = this;
var params = {
page: 0,
size: 2
}
getWxLiveList(params)
.then(res => {
_this.liveList = res.data.content;
})
.catch(err => {
})
},
getVideoList:function(){
var _this = this;
var params = {
page: 1,
limit: 2
}
getVideoList(params)
.then(res => {
_this.videoList = res.data.list;
})
.catch(err => {
})
},
toMoreLive:function(){
this.$yrouter.push('/pages/LiveBroadcastList/LiveBroadcastList');
},
toMoreVideo:function(){
this.$yrouter.push('/pages/VideoPlayBackList/VideoPlayBackList');
},
videoClick:function(video){
// this.curPlayVideoUrl = video.video;
// this.$refs.popup.open();
// this.videoContext = uni.createVideoContext('myVideo');
// this.videoContext.requestFullScreen();
this.$yrouter.push('/pages/VideoPlayBackList/VideoPlayBackDetail?videoUrl='+video.video);
},
liveClick:function(video){
var liveAppId = this.$WX_LIVE_APPID;
wx.navigateTo({
url: `plugin-private://${liveAppId}/pages/live-player-plugin?room_id=${video.roomId}`
});
},
emptyClick:function(){
},
liveStatusText:function(liveStatus){
//直播间状态 101:直播中,102:未开始,103 已结束,104 禁播,105:暂停,106:异常,107:已过期
var txt = '';
switch (liveStatus){
case 101:
txt = '直播中';
break;
case 102:
txt = '未开始';
break;
case 103:
txt = '已结束';
break;
case 104:
txt = '已禁播';
break;
case 105:
txt = '暂停中';
break;
case 106:
txt = '直播异常';
break;
case 107:
txt = '已过期';
break;
default:
break;
}
return txt;
},
videoErrorCallback: function(e) {
uni.showModal({
content: e.target.errMsg,
showCancel: false
})
}
}
}
</script>
<style>
page{
background-color: #F6F6F6;
}
.video-list{
margin: 32rpx;
box-sizing: border-box;
column-count: 2;
column-width: 327rpx;
column-gap: 32rpx;
break-inside: avoid;
}
.video-list-item{
/* width: 327rpx; */
position: relative;
/* margin-right: 32rpx; */
margin-bottom: 32rpx;
background-color: #fff;
height: 100%;
overflow: hidden;
}
.video-title{
font-size: 28rpx;
font-weight: bold;
color: #080F1A;
margin-top: 4rpx;
/* min-height: 80rpx; */
margin-left: 10rpx;
margin-right: 10rpx;
}
.video-shop{
font-size: 24rpx;
color: #080F1A;
margin-top: 18rpx;
margin-left: 10rpx;
margin-right: 10rpx;
margin-bottom: 24rpx;
}
/* .video-list:nth-child(even){
margin-right: 0rpx;
} */
.video-img{
/* width: 327rpx; */
position: relative;
}
.video-img image{
width: 100%;
height: 327rpx;
}
.live-status-tag{
position: absolute;
left: 10rpx;
top: 10rpx;
border-radius: 8rpx;
background-color: #000000;
opacity: 0.5;
padding: 8rpx;
}
.section-header{
padding: 32rpx 32rpx 0rpx 32rpx;
}
.section-title{
font-size: 32rpx;
font-weight: bold;
}
.section-more{
font-size: 28rpx;
color:#1CD1DC;
}
</style>
@@ -0,0 +1,246 @@
<template>
<view class="container">
<mescroll-body ref="mescrollRef" top="0" bottom="0" class='cotent-scroll' :up="upOption" :down="downOption" @up="upCallback" @down="downCallback" @init="mescrollInit" @emptyclick="emptyClick">
<view class="video-list">
<view class="video-list-item acea-row row-column" v-for="(video,index) in videoList" :key="index" @click="videoClick(video)">
<view class="video-img">
<image :src="video.coverImge || webUrl+'/20230304100226088424.jpg'" mode="scaleToFill"></image>
<view class="live-status-tag acea-row row-center">
<text style="color: #FFFFFF;font-size: 28rpx;font-weight: bold;">{{liveStatusText(video.liveStatus)}}</text>
</view>
</view>
<view class="video-title line2">{{video.name}}</view>
<view class="video-shop acea-row row-middle row-between" style="flex-wrap: nowrap;">
<view class="acea-row row-middle" style="flex-wrap: nowrap;">
<image style="width: 48rpx;height: 48rpx;border-radius: 50%;margin-right: 8rpx;" src="http://image.xdd618.com/logo.png" mode=""></image>
<!-- <text>{{video.storeName}}</text> -->
<text>香道滇官方商城</text>
</view>
<image style="width: 48rpx;height: 48rpx;border-radius: 50%;flex-shrink: 0;" :src="webUrl+'/20210203151253323822.png.png'" mode=""></image>
</view>
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixins from "@/mixins/mescroll-mixins.js";
import MescrollBody from "@/components/mescroll-uni/mescroll-body.vue";
import uniPopup from '@/components/uni-popup/uni-popup.vue';
import { getVideoList } from "@/api/user";
import {
getWxLiveList
} from '@/api/public';
export default {
components:{
MescrollBody,
uniPopup
},
mixins:[
MescrollMixins({
getPageData(mescroll){
// 此时mescroll会携带page的参数:
let pageNum = Math.max(mescroll.num-1,0); // 页码, 默认从1开始
let pageSize = mescroll.size; // 页长, 默认每页10条
var params = {
page: pageNum,
size: pageSize
}
var _this = this;
// mescroll.endSuccess(5, 0);
getWxLiveList(params)
.then(res => {
console.log('res:'+JSON.stringify(res));
//mescroll.endByPage(res.data.length, res.data.total_pages);
if(mescroll.num == 1) {
_this.videoList = []; //如果是第一页需手动制空列表
//_this.adjustPage();
}
_this.videoList = _this.videoList.concat(res.data.content);//追加新数据
mescroll.endSuccess(res.data.content.length, res.data.content.length>pageSize);
})
.catch(err => {
mescroll.endErr();
//uni.hideLoading();
uni.showToast({
title: err + '',
icon: 'none',
mask: false,
duration: 1500
});
})
}
})
],
data() {
return {
webUrl:this.$VUE_APP_RESOURCES_URL,
videoList:[],
upOption:{
noMoreSize: 10, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
auto:true,
empty:{
tip: '暂无直播' // 提示
// btnText:'点击刷新'
}
},
downOption:{
auto:true
},
curPlayVideoUrl:'',
isVideoPopupShow:false
}
},
onReady: function(res) {
},
methods: {
videoClick:function(video){
// this.curPlayVideoUrl = video.video;
// this.$refs.popup.open();
// this.videoContext = uni.createVideoContext('myVideo');
// this.videoContext.requestFullScreen();
// this.$yrouter.push('/pages/VideoPlayBackList/VideoPlayBackDetail?videoUrl='+video.video);
var liveAppId = this.$WX_LIVE_APPID;
wx.navigateTo({
url: `plugin-private://${liveAppId}/pages/live-player-plugin?room_id=${video.roomId}`
});
},
emptyClick:function(){
},
liveStatusText:function(liveStatus){
//直播间状态 101:直播中,102:未开始,103 已结束,104 禁播,105:暂停,106:异常,107:已过期
var txt = '';
switch (liveStatus){
case 101:
txt = '直播中';
break;
case 102:
txt = '未开始';
break;
case 103:
txt = '已结束';
break;
case 104:
txt = '已禁播';
break;
case 105:
txt = '暂停中';
break;
case 106:
txt = '直播异常';
break;
case 107:
txt = '已过期';
break;
default:
break;
}
return txt;
}
}
}
</script>
<style>
page{
background-color: #F6F6F6;
}
.video-list{
margin: 32rpx;
box-sizing: border-box;
-moz-column-count:2; /* Firefox */
-webkit-column-count:2; /* Safari and Chrome */
column-count: 2;
column-width: 327rpx;
-webkit-column-width:327rpx;
-moz-column-width:327rpx;
column-gap: 32rpx;
-webkit-column-gap: 32rpx;
-moz-column-gap: 32rpx;
break-inside: avoid;
-webkit-column-break-inside:avoid;
-moz-column-break-inside:avoid;
}
.video-list-item{
/* width: 327rpx; */
position: relative;
/* margin-right: 32rpx; */
margin-bottom: 32rpx;
background-color: #fff;
height: 100%;
overflow: hidden;
break-inside: avoid;
-webkit-column-break-inside:avoid;
-moz-column-break-inside:avoid;
}
.video-title{
font-size: 28rpx;
font-weight: bold;
color: #080F1A;
margin-top: 4rpx;
/* min-height: 80rpx; */
margin-left: 10rpx;
margin-right: 10rpx;
}
.video-shop{
font-size: 24rpx;
color: #080F1A;
margin-top: 18rpx;
margin-left: 10rpx;
margin-right: 10rpx;
margin-bottom: 24rpx;
}
/* .video-list:nth-child(even){
margin-right: 0rpx;
} */
.video-img{
/* width: 327rpx; */
position: relative;
}
.video-img image{
width: 100%;
height: 327rpx;
}
.live-status-tag{
position: absolute;
left: 10rpx;
top: 10rpx;
border-radius: 8rpx;
background-color: #000000;
opacity: 0.5;
padding: 8rpx;
}
</style>
+144
View File
@@ -0,0 +1,144 @@
<template>
<view class="lottie-bg">
<img class="start-img" :src="webUrl+'/20220929145109969605.png'" mode="scaleToFill">
</view>
</template>
<script>
import {
mapState,
mapMutations,
mapActions
} from "vuex";
import {
wxappAuth,
getUser,
userBindParent
} from "@/api/user";
import dayjs from "dayjs";
import cookie from "@/utils/store/cookie";
import {
parseQuery,
login,
handleQrCode,
getCurrentPageUrl,
handleUrlParam,
checkAuth
} from "@/utils";
export default {
name: "Loading",
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
staticUrl: this.$STATIC_RESOURCE_URL
};
},
onShow() {
var url = handleQrCode();
if (!url) {
url = handleUrlParam(getCurrentPageUrl())
}
// 判断是否是分销
if (url) {
var spread = cookie.get("spread");
let urlSpread = parseInt(url.spread);
// if (!Number.isNaN(urlSpread) && spread !== urlSpread) {
if (!Number.isNaN(urlSpread)) {
cookie.set("spread", urlSpread || 0);
//绑定上级
userBindParent({
spread: urlSpread
}).finally(() => {
this.$yrouter.switchTab({
path: "/pages/home/index"
});
})
return;
// //如果是分销强制跳转到授权界面,来绑定关系
// var path = "/pages/authorization/index";
// this.$yrouter.reLaunch({path:path});
// cookie.set('redirect', path)
// return;
} else if (spread === 0 || typeof spread !== "number") {
cookie.set("spread", urlSpread || 0);
}
}
if (this.$store.getters.token) {
// 注释下面一行,会停留在启动页
setTimeout(() => {
this.toLaunch();
}, 2000)
return;
}
cookie.get("spread");
// this.toLaunch();
if (this.$deviceType == "app") {
// this.toLaunch();
this.$yrouter.switchTab({
path: "/pages/home/index"
});
return;
}
//检查授权信息
this.checkUserInfo();
},
methods: {
...mapActions(["changeAuthorization", "setUserInfo"]),
toLaunch() {
this.changeAuthorization(false);
this.$yrouter.switchTab({
path: "/pages/home/index"
});
},
checkUserInfo: async function() {
//检查是否有授权信息
var loginInfo = null;
let authUserInfo = await checkAuth().catch(err => {});
console.log('authUserInfo:' + JSON.stringify(authUserInfo));
if (authUserInfo) {
loginInfo = {
userInfo: authUserInfo,
iv: '',
encryptedData: ''
}
}
login(loginInfo).finally(() => {
this.$yrouter.switchTab({
path: "/pages/home/index"
});
});
}
}
};
</script>
<style scoped lang="less">
.lottie-bg {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #C9151E;
}
.start-img {
position: fixed;
bottom: 200rpx;
left: 50%;
transform: translate(-50%, 0);
width: 190rpx;
height: 212rpx;
}
</style>
+60
View File
@@ -0,0 +1,60 @@
<template>
<view class="not-defined">
<image :src="webUrl+'/20200729163505245839.png'" />
<view class="content">
<h3 class="title">页面未找到</h3>
<text>抱歉您访问的页面不存在请返回上一级或点击下方按钮返回首页...</text>
</view>
<view class="btn" @click="homeGo()">
返回首页
</view>
</view>
</template>
<script>
export default {
name: "NotDefined",
data:function(){
return{
webUrl:this.$VUE_APP_RESOURCES_URL
};
},
methods: {
homeGo() {
this.$yrouter.switchTab('/pages/home/index');
},
},
};
</script>
<style scoped lang="less">
.not-defined image{
width: 100%;
margin-top: 18%;
}
.content {
padding: 0 1*100rpx;
text-align: center;
color: #44405e;
font-size: 15px;
}
.title {
margin-bottom: 0.6*100rpx;
color: #302c48;
font-size: 20px;
}
.btn {
color: #fff;
background-color: #ef4c4c;
font-size: 16px;
padding: 0.16*100rpx;
border-radius: 25px;
text-align: center;
width: 2.4*100rpx;
margin: 0 auto;
margin-top: 1*100rpx;
}
</style>
@@ -0,0 +1,47 @@
<template>
<view class="">
<video class="video" :show-fullscreen-btn="false" id="myVideo" autoplay :src="curPlayVideoUrl" @error="videoErrorCallback" controls></video>
</view>
</template>
<script>
import uniPopup from '@/components/uni-popup/uni-popup.vue';
export default {
components:{
uniPopup
},
data() {
return {
curPlayVideoUrl:'',
isVideoPopupShow:false
}
},
onReady: function(res) {
this.videoContext = uni.createVideoContext('myVideo');
this.videoContext.requestFullScreen();
},
onLoad:function(e){
this.curPlayVideoUrl = e.videoUrl;
//this.$refs.popup.open();
},
methods: {
videoErrorCallback: function(e) {
uni.showModal({
content: e.target.errMsg,
showCancel: false
})
}
}
};
</script>
<style scoped>
.video{
height: 100vh;
width: 100vw;
}
</style>
@@ -0,0 +1,175 @@
<template>
<view>
<view class="type-list flex ai-center">
<view class="item" :class="{'active':type===item.value}" v-for="(item,index) in typeList" :key="index"
@click="changeType(item)">{{ item.label }}
</view>
</view>
<view class="list" v-if="list.length">
<custom-waterfalls-flow :value="list" imageKey="cover">
<view class="item" v-for="(item,index) in list" :key="index" slot="slot{{index}}" @click="goDetail(item)">
<image class="cover" :src="item.cover" mode="widthFix"></image>
<view class="content">
<view class="title more-t">{{ item.title }}</view>
<view class="footer flex jc-between ai-center">
<view class="visit flex ai-center">
<image class="icon" style="margin-right: 8rpx" :src="item.storeLogo" mode="scaleToFill"></image>
{{ item.storeName }}
</view>
<image class="icon flex-0" :src="webUrl+'/20210806121203835373.png'" mode="scaleToFill"></image>
</view>
</view>
</view>
</custom-waterfalls-flow>
</view>
<view class="v4-nodata" v-else>
<image src="@/static/images/img_nodata.png" mode="scaleToFill"/>
<view class="text">暂无数据</view>
</view>
</view>
</template>
<script>
import {getStoreVideoType, getArticleList} from "@/api/public";
import {getVideoList} from "@/api/user";
export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
typeList: [{"label": "全部", "value": ""}],
type: "",
page: 1,
limit: 10,
keyword: "",
list: [],
isWait: false
}
},
onLoad() {
this.getType();
this.fetchList();
},
onReachBottom() {
this.page++;
this.fetchList();
},
methods: {
getType() {
getStoreVideoType().then(({data}) => {
if (data.length > 0) {
data.forEach(item => {
this.typeList.push(item);
})
}
});
},
changeType(item) {
this.type = item.value;
this.page = 1;
this.list = [];
this.fetchList();
},
fetchList() {
if (this.isWait) return;
this.isWait = true;
let params = {
type: this.type,
page: this.page,
limit: this.limit
};
getVideoList(params).then(res => {
if (res.status === 200) {
for (let i = 0; i < res.data.length; i++) {
res.data[i].hide = true;
this.list.push(res.data[i])
}
}
this.isWait = false;
});
},
goDetail(item) {
this.$yrouter.push("/pages/VideoPlayBackList/VideoPlayBackDetail?videoUrl=" + item.video);
}
}
}
</script>
<style lang="less">
.type-list {
margin: 28rpx 32rpx;
.item {
margin-right: 20rpx;
padding: 12rpx 16rpx;
border-radius: 20rpx;
background: #fff;
font-size: 26rpx;
}
.active {
background: #f66;
color: #fff;
}
}
.list {
margin: 28rpx 32rpx;
.item {
border-radius: 4rpx;
background: #fff;
.cover {
width: 332rpx;
//height: 200rpx;
vertical-align: middle;
}
.title {
padding: 12rpx 16rpx;
font-size: 26rpx;
font-weight: bold;
line-height: 38rpx;
color: #333;
}
.mark {
margin: 14rpx 16rpx;
font-size: 22rpx;
line-height: 32rpx;
color: #999;
}
.footer {
padding: 12rpx 16rpx 16rpx;
border-top: 1rpx solid #E1E1E1;
font-size: 22rpx;
}
.icon {
width: 40rpx;
height: 40rpx;
vertical-align: middle;
border-radius: 50%;
}
.visit {
width: 100%;
color: #333;
overflow: hidden;
}
.time {
color: #999;
}
}
}
</style>
+131
View File
@@ -0,0 +1,131 @@
<template>
<view class="bargain-record" ref="container">
<view class="item" v-for="(item, bargainrecordIndex) in bargain" :key="bargainrecordIndex">
<view class="picTxt acea-row row-between-wrapper">
<view class="pictrue">
<image :src="item.image" />
</view>
<view class="text acea-row row-column-around">
<view class="line1">{{ item.title }}</view>
<count-down
:isDay="true"
:tipText="'倒计时 '"
:dayText="' 天 '"
:hourText="' 时 '"
:minuteText="' 分 '"
:secondText="' 秒'"
:datatime="item.datatime"
></count-down>
<view class="money font-color-red">
已砍至
<text class="symbol"></text>
<text class="num">{{ item.residuePrice }}</text>
</view>
</view>
</view>
<view class="bottom acea-row row-between-wrapper">
<view class="purple" v-if="item.status === 1">活动进行中</view>
<view class="success" v-else-if="item.status === 3">砍价成功</view>
<view class="end" v-else>活动已结束</view>
<view class="acea-row row-middle row-right">
<view
class="bnt cancel"
v-if="item.status === 1"
@click="getBargainUserCancel(item.bargainId)"
>取消活动</view>
<view
class="bnt bg-color-red"
v-if="item.status === 1"
@click="goDetail(item.bargainId)"
>继续砍价</view>
<view class="bnt bg-color-red" v-else @click="goList">重开一个</view>
</view>
</view>
</view>
<Loading :loaded="status" :loading="loadingList"></Loading>
</view>
</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/index",
query: { id, partake: 0 }
});
},
goList: function() {
this.$yrouter.push({
path: "/pages/activity/GoodsBargain/index"
});
},
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 => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
getBargainUserCancel: function(bargainId) {
var that = this;
getBargainUserCancel({ bargainId: bargainId })
.then(res => {
uni.showToast({
title: res.msg,
icon: "success",
duration: 2000
});
that.status = false;
that.loadingList = false;
that.page = 1;
that.bargain = [];
that.getBargainUserList();
})
.catch(res => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
+617
View File
@@ -0,0 +1,617 @@
<template>
<view class="bargain">
<!-- 在header上加 on 为请求支援 -->
<view :class="[bargainPartake != userInfo.uid ? 'header on' : 'header']">
<view class="people">{{ lookCount }}人查看 {{ shareCount }}人分享 {{ userCount }}人参与</view>
<!-- 帮助砍价帮砍成功-->
<view class="pictxt acea-row row-center-wrapper" v-if="bargainPartake != userInfo.uid">
<view class="pictrue">
<image :src="bargainUserInfo.avatar" />
</view>
<view class="text">
{{ bargainUserInfo.nickname }}
<text>邀请您帮忙砍价</text>
</view>
</view>
<count-down
:isDay="true"
:tipText="'倒计时 '"
:dayText="' 天 '"
:hourText="' 时 '"
:minuteText="' 分 '"
:secondText="' 秒'"
:datatime="datatime"
></count-down>
</view>
<view class="wrapper">
<view class="pictxt acea-row row-between-wrapper" @click="openAlone">
<view class="pictrue">
<image :src="bargain.image" />
<view class="bargain_view">
查看商品
<view class="iconfont icon-jiantou iconfonts"></view>
</view>
</view>
<view class="text acea-row row-column-around">
<view class="line2" v-text="bargain.title"></view>
<view class="money font-color-red">
已砍至:
<text class="num" v-text="price"></text>
</view>
<view class="acea-row row-middle">
<view class="successNum" v-text="'原价' + bargain.price"></view>
<view class="successNum" v-text="'已有' + bargainSumCount + '人砍价成功'"></view>
</view>
</view>
</view>
<view class="cu-progress acea-row row-middle round margin-top">
<view
class="acea-row row-middle bg-red"
:style="{ width: loading ? pricePercent + '%' : '' }"
></view>
</view>
<view class="balance acea-row row-between-wrapper">
<view v-text="'已砍' + alreadyPrice + '元'"></view>
<view v-if="surplusPrice === 0">砍价成功</view>
<view v-else v-text="'还剩' + surplusPrice + '元'"></view>
</view>
<!-- 帮助砍价帮砍成功-->
<view
class="bargainSuccess"
v-if="bargainPartake != userInfo.uid && !statusUser && !helpListLoading"
>
<span class="iconfont icon-xiaolian"></span>已成功帮助好友砍价
</view>
<!-- 砍价成功-->
<view
class="bargainSuccess"
v-if="
surplusPrice === 0 &&
bargainPartake === userInfo.uid &&
userBargainStatus === 1 &&
!helpListLoading
"
>
<span class="iconfont icon-xiaolian"></span>恭喜您砍价成功,快去支付吧~
</view>
<view
v-if="userBargainStatus == 0 && bargainPartake === userInfo.uid"
class="bargainBnt"
@click="goParticipate"
>立即参与砍价</view>
<view
class="bargainBnt"
@click="goPoster"
v-if="
surplusPrice > 0 &&
bargainPartake === userInfo.uid &&
userBargainStatus === 1 &&
!helpListLoading
"
>邀请好友帮砍价</view>
<view
class="bargainBnt"
@click="getBargainHelp"
v-else-if="
bargainPartake != userInfo.uid &&
userBargainStatus == 1 &&
statusUser &&
!helpListLoading
"
>帮好友砍一刀</view>
<view
class="bargainBnt"
@click="getBargainStart"
v-if="bargainPartake != userInfo.uid && !statusUser && !helpListLoading"
>我也要参与</view>
<view
class="bargainBnt"
@click="goPay"
v-if="
surplusPrice === 0 &&
bargainPartake === userInfo.uid &&
userBargainStatus === 1
"
>立即支付</view>
<view class="bargainBnt on" @click="goList">抢更多商品</view>
<view class="tip">
已有
<span class="font-color-red" v-text="helpCount"></span>
位好友成功帮您砍价
</view>
<view class="lock"></view>
</view>
<view class="bargainGang">
<view class="title font-color-red acea-row row-center-wrapper">
<view class="pictrue">
<image :src="webUrl+'/20230304134450627525.png'" />
</view>
<view class="titleCon">砍价帮</view>
<view class="pictrue on">
<image :src="webUrl+'/20230304134450627525.png'" />
</view>
</view>
<view class="list">
<view
class="item acea-row row-between-wrapper"
v-for="(item, bargainHelpListIndex) in bargainHelpList"
:key="bargainHelpListIndex"
>
<view class="pictxt acea-row row-between-wrapper">
<view class="pictrue">
<image :src="item.avatar" />
</view>
<view class="text">
<view class="name line1" v-text="item.nickname"></view>
<view class="line1" v-text="item.add_time"></view>
</view>
</view>
<view class="money font-color-red">
<text class="iconfont icon-kanjia"></text>
砍掉{{ item.price }}元
</view>
</view>
</view>
<view
class="load font-color-red"
v-if="!helpListStatus && !helpListLoading"
@click="getBargainHelpList"
>点击加载更多</view>
<view class="lock"></view>
</view>
<view class="goodsDetails">
<view class="title font-color-red acea-row row-center-wrapper">
<view class="pictrue">
<image :src="webUrl+'/20230304134450627525.png'" />
</view>
<view class="titleCon">商品详情</view>
<view class="pictrue on">
<image :src="webUrl+'/20230304134450627525.png'" />
</view>
</view>
<view class="conter" v-html="bargain.description"></view>
<view class="lock"></view>
</view>
<view class="goodsDetails">
<view class="title font-color-red acea-row row-center-wrapper">
<view class="pictrue">
<image :src="webUrl+'/20230304134450627525.png'" />
</view>
<view class="titleCon">活动规则</view>
<view class="pictrue on">
<image :src="webUrl+'/20230304134450627525.png'" />
</view>
</view>
<view class="conter" v-html="bargain.rule"></view>
</view>
<view class="bargainTip" :class="active === true ? 'on' : ''">
<!-- <view class="pictrue">
<image src="@/static/images/bargainBg.jpg" />
<view class="iconfont icon-guanbi" @click="close"></view>
</view>-->
<view class="cutOff" v-if="bargainPartake === userInfo.uid">
您已砍掉
<text class="font-color-red" v-text="bargainHelpPrice"></text>元,听说分享次数越多砍价成功的机会越大哦!
</view>
<view class="cutOff on" v-else>
<view class="help font-color-red" v-text="'成功帮砍' + bargainHelpPrice + '元'"></view>,您也可以砍价低价拿哦,快去挑选心仪的商品吧~
</view>
<view class="tipBnt" @click="goPoster" v-if="bargainPartake === userInfo.uid">邀请好友帮砍价</view>
<view class="tipBnt" @click="getBargainStart" v-else>我也要参与</view>
</view>
<view class="mask" @touchmove.prevent :hidden="active === false" @click="close"></view>
</view>
</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 {
webUrl: this.$VUE_APP_RESOURCES_URL,
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, //砍价状态
statusUser: false ,// 是否帮别人砍,没砍是true,砍了false
share:{
title:'',
path: `/pages/activity/DargainDetails/index/?id=${this.$yroute.query.id}&partake=${this.userInfo.uid}`,
imageUrl:'',
desc:'',
content:''
}
};
},
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: {
//参与砍价
goParticipate() {
if (this.bargainPartake === this.userInfo.uid) this.getBargainStart();
else this.getBargainStartUser();
this.getBargainHelpCount();
},
openAlone: function() {
this.$yrouter.push({ path: "/detail/" + this.bargain.productId });
},
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/index",
// 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.getBargainStartUser();
if (that.bargainPartake === that.userInfo.uid) {
// that.getBargainStart();
} else {
that.getBargainStartUser();
}
},
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/index",
query: { id: res.data.cartId }
});
})
.catch(err => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
});
},
goPoster: function() {
var that = this;
that.getBargainShare(that.bargainId);
this.$yrouter.push({
path: "/pages/activity/Poster/index",
query: { id: that.bargainId, type: 2 }
});
},
goList: function() {
this.$yrouter.push({
path: "/pages/activity/GoodsBargain/index"
});
},
//砍价分享
//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 => {
res.data.bargain = res.data.bargain.replace(
/\<img/gi,
'<img style="max-width:100%;height:auto;"'
);
that.bargain = res.data.bargain;
that.datatime = that.bargain.stopTime / 1000;
that.getBargainHelpCount();
})
.catch(res => {
uni.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 => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
//参与砍价
getBargainHelp: function() {
var that = this;
if (
that.surplusPrice === 0 &&
that.bargainPartake !== that.userInfo.uid
) {
return uni.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
) {
uni.showToast({
title: "您已经砍过了",
icon: "none",
duration: 2000
});
return;
}
that.helpListStatus = false;
that.page = 1;
that.bargainHelpList = [];
that.getBargainHelpPrice();
})
.catch(res => {
uni.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 => {
uni.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 => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
getBargainHelpCountStart: function() {
var that = this;
getBargainHelpCount({
bargainId: that.bargainId,
bargainUserUid: that.bargainPartake
})
.then(() => {})
.catch(() => {
this.$yrouter.push({
path: "/pages/activity/DargainDetails/index",
query: { id: that.bargainId, partake: that.userInfo.uid }
});
// that.$router.push({
// path:
// "/activity/dargain_detail/" +
// that.bargainId +
// "/" +
// 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);
console.log(that);
})
.catch(() => {
that.bargainPartake = that.userInfo.uid;
// that.$yrouter.push({
// path: "/pages/activity/DargainDetails/index",
// 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 => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
close: function() {
this.active = false;
}
}
// ,
// onShareAppMessage() {
// return {
// path: `/pages/activity/DargainDetails/index/?id=${this.$yroute.query.id}&partake=${this.userInfo.uid}`
// };
// }
};
</script>
<style lang="less">
page {
background-color: #eb3729;
}
.bargainBnt_hui {
font-size: 0.3 * 100rpx;
font-weight: bold;
color: #fff;
width: 6 * 100rpx;
height: 0.8 * 100rpx;
border-radius: 0.4 * 100rpx;
background: #bbb;
text-align: center;
line-height: 0.8 * 100rpx;
margin-top: 0.32 * 100rpx;
}
.bargain_view {
left: 0;
right: 0;
height: 0.48 * 100rpx;
background: rgba(0, 0, 0, 0.5);
opacity: 1;
border-radius: 0 0 0.06 * 100rpx 0.06 * 100rpx;
position: absolute;
bottom: 0;
font-size: 0.22 * 100rpx;
color: #fff;
text-align: center;
line-height: 0.48 * 100rpx;
}
.iconfonts {
font-size: 0.22 * 100rpx;
}
</style>
+84
View File
@@ -0,0 +1,84 @@
<template>
<view class="bargain-list">
<!-- <view class="header">
<image src="@/static/images/cut-bg.png" alt="">
</view>-->
<view class="list" v-if="bargainLis.length > 0">
<view class="item acea-row row-between-wrapper" v-for="(item, bargainLisIndex) in bargainLis"
:key="bargainLisIndex">
<view class="pictrue">
<image :src="item.image" />
</view>
<view class="text acea-row row-column-around">
<view class="line1" v-text="item.title"></view>
<view class="num">
<text class="iconfont icon-pintuan"></text>
{{ item.people }}人正在参与
</view>
<view class="money font-color-red">
可砍至:
<text class="price">{{item.minPrice}}</text>
</view>
</view>
<view class="cutBnt bg-color-red" @click="goDetail(item.id)">
<text class="iconfont icon-kanjia"></text>参与砍价
</view>
</view>
<view class="load font-color-red" v-if="!status" @click="getBargainList">点击加载更多</view>
</view>
</view>
</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/index",
query: {
id,
partake: 0
}
});
}
}
};
</script>
<style>
page {
background-color: rgb(245, 245, 245);
}
</style>
+91
View File
@@ -0,0 +1,91 @@
<template>
<view class="group-list" ref="container">
<view class="list" v-if="combinationList.length>0">
<view
class="item acea-row row-between-wrapper"
v-for="(item, combinationListIndex) in combinationList"
:key="combinationListIndex"
@click="link(item.id)"
>
<view class="pictrue">
<image :src="item.image" />
</view>
<view class="text">
<view class="line1" v-text="item.title"></view>
<view class="acea-row">
<view class="team acea-row row-middle cart-color">
<view class="iconfont icon-pintuan"></view>
<view class="num" v-text="item.people + '人团'"></view>
</view>
</view>
<view class="bottom acea-row row-between-wrapper">
<view class="money">
<text class="num" v-text="item.price"></text>
<text class="y-money" v-text="'¥' + item.productPrice"></text>
</view>
<view class="groupBnt bg-color-red">
去拼团
<text class="iconfont icon-jiantou"></text>
</view>
</view>
</view>
</view>
<Loading :loaded="status" :loading="loadingList"></Loading>
</view>
<view class="noCommodity" style="background-color: #fff;" v-if="combinationList.length === 0">
<view class="noPictrue">
<image :src="webUrl+'/20210203153900181449.png'" class="image" />
</view>
</view>
</view>
</template>
<script>
import { getCombinationList } from "@/api/activity";
import Loading from "@/components/Loading";
export default {
name: "GoodsGroup",
components: {
Loading
},
props: {},
data: function() {
return {
webUrl:this.$VUE_APP_RESOURCES_URL,
combinationList: [],
status: false, //砍价列表是否获取完成 false 未完成 true 完成
loading: false, //当前接口是否请求完成 false 完成 true 未完成
page: 1, //页码
limit: 20, //数量
loadingList: false
};
},
mounted: function() {
// document.querySelector('body').setAttribute('style', 'background-color:#eb3729');
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/index",
query: { id }
});
}
}
};
</script>
+261
View File
@@ -0,0 +1,261 @@
<template>
<view class="flash-sale" ref="container">
<view class="header" v-if="headerImg">
<image :src="headerImg"/>
</view>
<scroll-view scroll-y="false" scroll-x="true">
<view class="timeScroll">
<view v-for="(item, index) in timeList" :key="index">
<view v-if="active==index" class="timeItem active" @click="setTime(index)">
<view class="time">{{ item.time }}</view>
<view class="state">{{ item.state }}</view>
</view>
<view v-if="active!=index" class="timeItem" @click="setTime(index)">
<view class="time">{{ item.time }}</view>
<view class="state">{{ item.state }}</view>
</view>
</view>
</view>
</scroll-view>
<view v-for="(item, index) in timeList" :key="index">
<view v-if="active == index">
<view class="countDown font-color-red acea-row row-center-wrapper">
<view v-if="item.status === 0" class="activity">活动已结束</view>
<count-down
:isDay="false"
:tipText="'距结束仅剩 '"
:dayText="false"
:hourText="' : '"
:minuteText="' : '"
:secondText="false"
:datatime="datatime"
v-if="item.status === 1"
></count-down>
<view v-if="item.status === 2" class="activity">活动即将开始</view>
</view>
<view class="list">
<view
class="item acea-row row-between-wrapper"
v-for="(itemSeckill, indexSeckill) in seckillList"
:key="indexSeckill"
>
<view class="pictrue">
<image :src="itemSeckill.image"/>
</view>
<view class="text acea-row row-column-around">
<view class="line1" v-text="itemSeckill.title"></view>
<view class="money">
限时价
<text class="num font-color-red" v-text="'¥' + itemSeckill.price"></text>
</view>
<view class="progress cart-color">
<view class="bg-red" :style="{ width: loading ? itemSeckill.percent + '%' : '' }"></view>
<view class="piece font-color-red" v-text="'仅剩' + itemSeckill.stock + '件'"></view>
</view>
</view>
<view
class="grab bg-color-red"
v-if="item.status === 1 && itemSeckill.stock > 0"
@click="goDetail(itemSeckill.id)"
>马上抢
</view>
<view class="grab" v-if="item.status === 1 && itemSeckill.stock <= 0">已售磬</view>
<view class="grab bg-color-red" v-if="item.status === 2">即将开始</view>
<view class="grab bg-color-red" v-if="item.status === 0">已结束</view>
</view>
</view>
<view
class="noCommodity"
style="background-color: #fff;"
v-if="seckillList.length === 0 && page > 1"
>
<view class="noPictrue">
<image :src="webUrl+'/20210203153900181449.png'" class="image"/>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import {getSeckillConfig, getSeckillList} from "@/api/activity";
import CountDown from "@/components/CountDown";
export default {
name: "GoodsSeckill",
components: {
CountDown
},
props: {},
data: function () {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
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: {
changeTime: function (index) {
this.active = index;
this.getSeckillList();
},
mountedStart: function () {
var that = this;
uni.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;
uni.hideLoading();
});
});
},
setTime: function (index) {
var that = this;
that.page = 1;
that.loadingList = false;
that.status = false;
that.active = index;
that.datatime = that.timeList[that.active].stop;
this.seckillList = [];
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++;
uni.hideLoading();
});
},
goDetail: function (id) {
var that = this;
var time = that.timeList[that.active].stop;
this.$yrouter.push({
path: "/pages/activity/SeckillDetails/index",
query: {
id,
time
}
});
}
}
};
</script>
<style scoped lang="less">
.timeScroll {
display: flex;
align-items: center;
flex-direction: row;
}
.timeItem {
font-size: 0.22 * 100rpx;
color: #282828;
width: 150rpx;
text-align: center;
padding: 0.11 * 100rpx 0;
background-color: none;
&.active {
.time {
color: #eb3729;
}
.state {
background-color: #eb3729;
color: #fff;
opacity: 1;
border-radius: 30rpx;
padding: 0 0.2 * 100rpx;
font-weight: 800;
height: 0.37 * 100rpx;
line-height: 0.37 * 100rpx;
}
}
}
.timeItem .time {
font-size: 0.32 * 100rpx;
font-weight: bold;
height: 0.37 * 100rpx;
line-height: 0.37 * 100rpx;
}
.timeItem .state {
height: 0.37 * 100rpx;
line-height: 0.37 * 100rpx;
}
.activity {
color: #333;
}
.flash-sale .list .item .grab {
background-color: #999;
}
</style>
+375
View File
@@ -0,0 +1,375 @@
<template>
<view :class="[posterImageStatus ? 'noscroll product-con' : 'product-con']" v-show="domStatus">
<product-con-swiper :imgUrls="imgUrls"></product-con-swiper>
<view class="wrapper">
<view class="share acea-row row-between row-bottom">
<view class="money font-color-red">
<text class="num" v-text="storeInfo.price"></text>
<text class="y-money" v-text="'¥' + storeInfo.productPrice"></text>
</view>
</view>
<view class="introduce" v-text="storeInfo.title"></view>
<view class="label acea-row row-between-wrapper">
<view v-text="'类型:' + storeInfo.people + '人团'"></view>
<view v-text="'库存:' + storeInfo.stock + storeInfo.unitName"></view>
<view v-text="'已拼:' + storeInfo.sales + storeInfo.unitName"></view>
</view>
</view>
<view class="notice acea-row row-middle">
<view class="num font-color-red">
<text class="iconfont icon-laba"></text>
已拼{{ storeInfo.sales
}}{{ storeInfo.unitName }}
<text class="line">|</text>
</view>
<view 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>
<view class="line1">{{ item }}</view>
</swiper-item>
</block>
</swiper>
</view>
</view>
<view class="assemble">
<view v-for="(item, groupListindex) in groupList" :key="groupListindex">
<view class="item acea-row row-between-wrapper" v-if="groupListindex < groupListCount">
<view class="pictxt acea-row row-between-wrapper">
<view class="pictrue">
<image :src="item.avatar" class="image" />
</view>
<view class="text line1" v-text="item.nickname"></view>
</view>
<view class="right acea-row row-middle">
<view>
<view class="lack">
<text>还差</text>
<text class="font-color-red" v-text="item.count"></text>
<text>人成团</text>
</view>
<count-down
:isDay="false"
:tipText="'剩余 '"
:dayText="false"
:hourText="':'"
:minuteText="':'"
:secondText="false"
:datatime="item.stopTime/1000"
></count-down>
</view>
<view class="spellBnt" @click="groupRule(item.id)">
去拼单
<text class="iconfont icon-jiantou"></text>
</view>
</view>
</view>
</view>
<view class="more" v-if="groupList.length > groupListCount" @click="setGroupListCount">
查看更多
<text class="iconfont icon-xiangxia"></text>
</view>
</view>
<view class="playWay">
<view class="title acea-row row-between-wrapper">
<view>拼团玩法</view>
</view>
<view class="way acea-row row-middle">
<view class="item">
<text class="num"></text>开团/参团
</view>
<view class="iconfont icon-arrow"></view>
<view class="item">
<text class="num"></text>邀请好友
</view>
<view class="iconfont icon-arrow"></view>
<view class="item">
<view>
<text class="num"></text>满员发货
</view>
</view>
</view>
</view>
<view class="userEvaluation">
<view class="title acea-row row-between-wrapper">
<view v-text="'用户评价(' + replyCount + ')'"></view>
<view class="praise" @click="goReply">
<text class="font-color-red" v-text="replyChance + '%'"></text>好评率
<text class="iconfont icon-jiantou"></text>
</view>
</view>
<UserEvaluation :reply="reply"></UserEvaluation>
</view>
<view class="product-intro">
<view class="title">产品介绍</view>
<view class="conter" v-html="storeInfo.description"></view>
<!-- <view class="conter" v-html=""></view> -->
</view>
<view style="height:100rpx;"></view>
<view class="footer-group acea-row row-between-wrapper">
<!-- <view class="customerSer acea-row row-center-wrapper row-column">
<view class="iconfont icon-kefu"></view>
<view>客服</view>
</view>-->
<view class="customerSer acea-row row-center-wrapper row-column" @click="setCollect">
<view class="iconfont" :class="userCollect ? 'icon-shoucang1' : 'icon-shoucang'"></view>
<text>收藏</text>
</view>
<view class="bnt bg-color-violet" @click="openAlone">单独购买</view>
<view class="bnt bg-color-red" @click="openTeam">立即开团</view>
</view>
<ProductWindow v-if="cartNum" v-on:changeFun="changeFun" :attr="attr" :cartNum="cartNum"></ProductWindow>
<StorePoster
v-on:setPosterImageStatus="setPosterImageStatus"
:posterImageStatus="posterImageStatus"
:posterData="posterData"
></StorePoster>
</view>
</template>
<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";
import {
getCoupon,
getCollectAdd,
getCollectDel,
getUserInfo
} from "@/api/user";
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,
userCollect: false
};
},
watch: {
$yroute: function(n) {
var that = this;
if (n.name === NAME) {
that.mountedStart();
}
}
},
onShow: function() {
this.mountedStart();
},
methods: {
openAlone: function() {
this.$yrouter.push({
path: "/pages/shop/GoodsCon/index",
query: { id: this.storeInfo.productId }
});
// this.$yrouter.replace({ path: "/detail/" + this.storeInfo.productId });
},
//收藏商品
setCollect: function() {
let that = this,
id = that.storeInfo.id,
category = "product";
if (that.userCollect) {
getCollectDel(id, category).then(function() {
that.userCollect = !that.userCollect;
});
} else {
getCollectAdd(id, category).then(function() {
that.userCollect = !that.userCollect;
});
}
},
mountedStart: function() {
var that = this;
let id = that.$yroute.query.id;
getCombinationDetail(id).then(res => {
that.userCollect = res.data.userCollect;
res.data.storeInfo.description = res.data.storeInfo.description.replace(
/\<img/gi,
'<img style="max-width:100%;height:auto;"'
);
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/index",
query: { id }
});
},
goReply: function() {
var that = this;
that.$yrouter.push({
path: "/pages/shop/EvaluateList/index",
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;
uni.showToast({
title: "每人每次限购1" + that.storeInfo.unitName,
icon: "none",
duration: 2000
});
},
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/index",
query: { id: res.data.cartId }
});
})
.catch(err => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
});
}
}
}
};
</script>
<style scoped lang="less">
.product-con .wrapper {
padding-bottom: 0.26 * 100rpx;
}
.noscroll {
height: 100%;
overflow: hidden;
}
.product-con .footer-group .bnt {
// flex:1;
width: 43%;
}
.product-con .footer-group .bnt.bg-color-violet {
background-color: #fa8013;
}
</style>
+248
View File
@@ -0,0 +1,248 @@
<template>
<view class="group-con">
<view class="header acea-row row-between-wrapper">
<view class="pictrue">
<image :src="storeCombination.image" />
</view>
<view class="text">
<view class="line1" v-text="storeCombination.title"></view>
<view class="money">
<text></text>
<text class="num" v-text="storeCombination.price"></text>
<text class="team cart-color" v-text="storeCombination.people + '人拼'"></text>
</view>
</view>
<view v-if="pinkBool === -1" class="iconfont icon-pintuanshibai"></view>
<view v-else-if="pinkBool === 1" class="iconfont icon-pintuanchenggong font-color-red"></view>
</view>
<view class="wrapper">
<view class="title acea-row row-center-wrapper">
<view class="line"></view>
<view class="name acea-row row-center-wrapper">
<text>剩余</text>
<count-down
:isDay="false"
:tipText="false"
:dayText="false"
:hourText="' : '"
:minuteText="' : '"
:secondText="false"
:datatime="pinkT.stopTime/1000"
></count-down>
<text>结束</text>
</view>
<view class="line"></view>
</view>
<view class="tips-warp">
<text class="tips font-color-red" v-if="pinkBool === 1">恭喜您拼团成功</text>
<text class="tips" v-else-if="pinkBool === -1">还差{{ count }}拼团失败</text>
<text class="tips font-color-red" v-else-if="pinkBool === 0">拼团中还差{{ count }}人拼团成功</text>
</view>
<view
class="list acea-row row-middle"
:class="[pinkBool === 1 || pinkBool === -1 ? 'result' : '',iShidden ? 'on' : '']"
>
<view class="pictrue">
<image :src="pinkT.avatar" />
</view>
<view class="acea-row row-middle" v-if="pinkAll.length > 0">
<view class="pictrue" v-for="(item, pinkAllIndex) in pinkAll" :key="pinkAllIndex">
<image :src="item.avatar" />
</view>
</view>
<view class="pictrue" v-for="countIndex in count" :key="countIndex">
<image class="img-none" :src="webUrl+'/20230304204903336964.png'" />
</view>
</view>
<view
v-if="(pinkBool === 1 || pinkBool === -1) && count > 9"
class="lookAll acea-row row-center-wrapper"
@click="lookAll"
>
{{ iShidden ? "收起" : "查看全部" }}
<text class="iconfont" :class="iShidden ? 'icon-xiangshang' : 'icon-xiangxia'"></text>
</view>
<view
class="teamBnt bg-color-red"
v-if="userBool === 1 && isOk == 0 && pinkBool === 0"
@click="goPoster"
>邀请好友参团</view>
<view
class="teamBnt bg-color-red"
v-else-if="userBool === 0 && pinkBool === 0 && count > 0"
@click="pay"
>我要参团</view>
<view
class="teamBnt bg-color-red"
v-if="pinkBool === 1 || pinkBool === -1"
@click="goDetail(storeCombination.id)"
>再次开团</view>
<view class="cancel" @click="getCombinationRemove" v-if="pinkBool === 0 && userBool === 1">
<text class="iconfont icon-guanbi3"></text>
<text>取消开团</text>
</view>
<view class="lookOrder" v-if="pinkBool === 1" @click="goOrder">
<text>查看订单信息</text>
<text class="iconfont icon-xiangyou"></text>
</view>
</view>
</view>
</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 {
webUrl: this.$VUE_APP_RESOURCES_URL,
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/index",
query: {
id: res.data.cartId,
pinkid: that.pinkId
}
});
})
.catch(err => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
});
},
goPoster: function() {
var that = this;
this.$yrouter.push({
path: "/pages/activity/Poster/index",
query: {
id: that.pinkId,
type: 1
}
});
},
goOrder: function() {
var that = this;
this.$yrouter.push({
path: "/pages/order/OrderDetails/index",
query: {
id: that.currentPinkOrder
}
});
},
//拼团列表
goList: function() {
this.$yrouter.push({
path: "/pages/activity/GoodsGroup/index"
});
},
//拼团详情
goDetail: function(id) {
this.$yrouter.push({
path: "/pages/activity/GroupDetails/index",
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 => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
})
.catch(res => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
lookAll: function() {
this.iShidden = !this.iShidden;
}
}
};
</script>
<style lang="less">
.tips-warp {
text-align: center;
margin-top: 20rpx;
}
</style>
+79
View File
@@ -0,0 +1,79 @@
<template>
<view class="poster-poster" v-if="status === false">
<view class="tip">
<text class="iconfont icon-shuoming"></text>提示长按图片保存至手机相册
</view>
<view class="poster">
<image :src="image" mode="widthFix" show-menu-by-longpress />
</view>
</view>
</template>
<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 => {
uni.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 => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
<style scoped lang="less">
page {
background-color: #eb3729;
}
.poster-poster {
height: unset !important;
}
</style>
+235
View File
@@ -0,0 +1,235 @@
<template>
<view :class="[posterImageStatus ? 'noscroll product-con' : 'product-con']" v-show="domStatus">
<product-con-swiper :imgUrls="imgUrls"></product-con-swiper>
<view class="nav acea-row row-between-wrapper">
<view class="money">
<text class="num" v-text="storeInfo.price"></text>
<text class="y-money" v-text="'¥' + storeInfo.price"></text>
</view>
<view class="acea-row row-middle">
<view class="times">
<view>距秒杀结束仅剩</view>
<count-down
:isDay="false"
:tipText="false"
:dayText="false"
:hourText="' : '"
:minuteText="' : '"
:secondText="false"
:datatime="datatime"
></count-down>
</view>
<view class="iconfont icon-jiantou"></view>
</view>
</view>
<view class="wrapperRush">
<view class="introduce acea-row row-between">
<view class="infor" v-text="storeInfo.title"></view>
<!-- <view class="iconfont icon-fenxiang" @click="setPosterImageStatus"></view> -->
</view>
<view class="label acea-row row-middle">
<view class="stock" v-text="'库存:' + storeInfo.stock + '件'"></view>
<view v-text="'销量:' + storeInfo.sales + '件'"></view>
</view>
</view>
<view class="product-intro">
<view class="title">产品介绍</view>
<view class="conter" v-html="storeInfo.description"></view>
</view>
<view style="height:100rpx;"></view>
<view class="footerRush acea-row row-between-wrapper">
<!-- <view
class="customerSer acea-row row-center-wrapper row-column"
@click="routerGo()"
>
<view class="iconfont icon-kefu"></view>
<view>客服</view>
</view> -->
<view class="bnt bg-color-red" @click="tapBuy">立即购买</view>
</view>
<ProductWindow v-on:changeFun="changeFun" :attr="attr" :cartNum="cartNum"></ProductWindow>
<StorePoster
v-on:setPosterImageStatus="setPosterImageStatus"
:posterImageStatus="posterImageStatus"
:posterData="posterData"
></StorePoster>
</view>
</template>
<style scoped lang="less">
.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: {
routerGo(item) {
this.$yrouter.push({ path: '/pages/user/CustomerList/index' })
},
mountedStart: function() {
var that = this;
let id = that.$yroute.query.id;
that.datatime = parseInt(that.$yroute.query.time);
getSeckillDetail(id).then(res => {
res.data.storeInfo.description = res.data.storeInfo.description.replace(
/\<img/gi,
'<img style="max-width:100%;height:auto;"'
);
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 {
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 => {
that.$yrouter.push({
path: "/pages/order/OrderSubmission/index",
query: { id: res.data.cartId }
});
})
.catch(err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: 'none',
duration: 2000
});
});
}
}
}
};
</script>
<style scoped lang="less">
.product-con .nav {
padding: 0 0.2*100rpx;
}
</style>
+408
View File
@@ -0,0 +1,408 @@
<template>
<view class="pages-auth">
<view class="tip-1">为了提供更优质的服务需要获取</view>
<view class="tip-2">您的头像昵称</view>
<view class="wechat flex jc-between ai-center">
<view class="flex ai-end">
<image class="avatar" :src="avatarUrl"></image>
<view>
<view class="name">微信用户</view>
<view class="info">微信个人信息</view>
</view>
</view>
<image class="select" :src="webUrl+'/20220613104953149068.png'" mode="scaleToFill"/>
</view>
<view class="agree-box">
<checkbox-group @change="changeAgree">
<label>
<checkbox value="yes" style="transform:scale(0.8)"/>
</label>
<text @click="show=true">我已阅读并同意
<text class="btn-show">用户服务协议及隐私政策</text>
</text>
</checkbox-group>
</view>
<view class="dialog-mask" v-if="show">
<view class="dialog-body">
<image class="btn-close" :src="webUrl+'/20221230200935413332.png'" @click="show=false"/>
<view class="content">
<view class="title tc bold">用户协议及隐私政策</view>
<view class="popup-content" v-html="agreeInfo.privacyPolicy"></view>
<view class="title tc">
<button size="mini" @click="show=false">关闭</button>
</view>
</view>
</view>
</view>
<view class="dialog-mask" v-if="showFillOut">
<view class="dialog-fill flex flex-col ai-center">
<view class="title bold">请完善您的头像和昵称</view>
<button class="avatar-wrapper" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
<image class="avatar" :src="avatarUrl"></image>
</button>
<input type="nickname" class="input-wrapper" placeholder="请输入昵称" @input="inputName" @confirm="inputName"
@blur="inputName"/>
<view class="btn-submit" @click="onSubmit">确认</view>
</view>
</view>
<view class="btn-box">
<button class="btn-yes" type="default" v-if="canIUseGetUserProfile" @tap="getUserInfoProfile">同意</button>
<button class="btn-no" type="default" @tap="back">拒绝</button>
</view>
</view>
</template>
<script>
import {mapActions, mapMutations, mapState} from 'vuex'
import cookie from '@/utils/store/cookie'
import {login, uploadImage} from '@/utils'
import {getAgree} from "@/api/public";
import {postUserEdit} from "@/api/user";
const defaultAvatarUrl = "/20230506100714762257.png"
export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
authorize: false,
canIUseGetUserProfile: false,
agreeInfo: {},
isAgree: false,
show: false,
showFillOut: false,
nickname: "",
avatarUrl: this.$VUE_APP_RESOURCES_URL + defaultAvatarUrl,
}
},
computed: {
...mapState(['isAuthorization', '$deviceType', 'token']),
},
onLoad() {
if (wx.getUserProfile) {
this.canIUseGetUserProfile = true
}
// 先校验用户是否授权,如果没有授权,显示授权按钮
getAgree().then(({data}) => this.agreeInfo = data);
},
onHide() {
this.updateAuthorizationPage(false)
this.changeAuthorization(false)
},
onUnload() {
this.updateAuthorizationPage(false)
this.changeAuthorization(false)
},
methods: {
...mapActions(['changeAuthorization', 'setUserInfo']),
...mapMutations(['updateAuthorizationPage']),
changeAgree(event) {
this.isAgree = event.detail.value.length > 0
},
toLogin() {
this.$yrouter.push({
path: '/pages/user/Login/index',
query: {},
})
},
back() {
this.$yrouter.switchTab({
path: '/pages/home/index',
query: {},
})
},
doneRedirect() {
let redirectUrl = cookie.get('redirect') || "";
redirectUrl = redirectUrl.replace(/\ /g, '');
//如果已经是授权页,跳转主页
if (redirectUrl == '/pages/authorization/index' || redirectUrl.length === 0) {
redirectUrl = '/pages/home/index';
}
this.$yrouter.reLaunch({
path: redirectUrl,
})
},
getUserInfoProfile() {
if (!this.isAgree) {
uni.showToast({
title: "请先阅读并同意《用户服务协议及隐私政策》",
icon: "none",
duration: 5000
})
return
}
wx.getUserProfile({
lang: 'zh_CN',
desc: '需要获取您的信息用来展示',
success: res => {
uni.showLoading({
title: '登录中',
})
login(res).then(e => {
let db_nickname = e.data.nickname;
if (db_nickname === null || db_nickname === undefined || db_nickname === "" || db_nickname === "微信用户") {
this.showFillOut = true;
} else {
this.doneRedirect();
}
}).catch(error => {
uni.showToast({
title: error,
icon: 'none',
duration: 2000,
})
})
},
})
},
onChooseAvatar(e) {
const {avatarUrl} = e.detail;
this.avatarUrl = avatarUrl;
},
inputName(e) {
this.nickname = e.detail.value;
},
onSubmit() {
let that = this;
this.nickname = this.nickname.trim();
if (this.nickname.length === 0) {
uni.showToast({
title: "请输入您的昵称",
icon: "none",
duration: 5000
})
return
}
// 临时地址图片上传
if (that.avatarUrl.indexOf("/tmp/") > -1 || that.avatarUrl.indexOf("wxfile") > -1) {
uploadImage(this.avatarUrl, img => {
that.avatarUrl = img;
})
let timer = setInterval(() => {
if (that.avatarUrl.indexOf("/tmp/") === -1 && that.avatarUrl.indexOf("wxfile") === -1) {
clearInterval(timer);
that.saveUserInfo();
}
}, 100)
} else {
that.saveUserInfo();
}
},
saveUserInfo() {
let param = {
nickname: this.nickname,
avatar: this.avatarUrl
}
postUserEdit(param).then(res => {
this.doneRedirect()
}).catch(error => {
uni.showToast({
title: error,
icon: "none",
duration: 5000
})
})
}
}
}
</script>
<style lang="scss">
.pages-auth {
padding: 148rpx 48rpx;
.tip-1 {
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.tip-2 {
margin-top: 20rpx;
font-size: 40rpx;
line-height: 58rpx;
color: #333333;
}
.wechat {
margin-top: 80rpx;
.avatar {
width: 112rpx;
height: 112rpx;
margin-right: 24rpx;
border-radius: 8rpx;
}
.name {
font-size: 32rpx;
line-height: 48rpx;
color: #333333;
}
.info {
margin-top: 28rpx;
font-size: 24rpx;
line-height: 34rpx;
color: #CECECE;
}
.select {
width: 40rpx;
height: 40rpx;
}
}
.agree-box {
margin: 200rpx 0 60rpx;
font-size: 28rpx;
color: #666;
.btn-show {
color: #000;
}
}
.dialog-mask {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, .4);
z-index: 99;
.dialog-body {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 630rpx;
height: 70vh;
box-sizing: border-box;
padding: 60rpx;
border-radius: 10rpx;
background: #fff;
overflow: hidden;
.btn-close {
position: absolute;
top: 20rpx;
right: 20rpx;
width: 28rpx;
height: 28rpx;
}
.content {
height: 100%;
overflow-y: auto;
}
.title {
margin: 30rpx auto;
}
}
.dialog-fill {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
box-sizing: border-box;
overflow: hidden;
width: 516rpx;
height: 576rpx;
border-radius: 24rpx;
background: #fff;
.title {
margin-top: 60rpx;
color: #333;
font-size: 36rpx;
line-height: 1;
}
.avatar-wrapper {
width: 180rpx;
height: 180rpx;
margin-top: 38rpx;
padding: 0;
background: none;
.avatar {
width: 180rpx;
height: 180rpx;
border-radius: 50%;
}
}
.avatar-wrapper::after {
display: none;
}
.input-wrapper {
width: 360rpx;
height: 72rpx;
margin-top: 32rpx;
background: rgba(248, 249, 251, 1);
color: #999;
font-size: 32rpx;
text-align: center;
}
.btn-submit {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100rpx;
box-sizing: border-box;
border-top: 2rpx solid #E0E0E0;
color: #3A87FC;
font-size: 32rpx;
line-height: 100rpx;
text-align: center;
}
}
}
.btn-box {
width: 338rpx;
margin: 0 auto;
button::after {
border: none;
}
button {
height: 72rpx;
font-size: 30rpx;
}
.btn-yes {
background: #FF564A;
color: #fff;
}
.btn-no {
margin-top: 32rpx;
background: #eee;
color: #FF564A;
}
}
}
</style>
+310
View File
@@ -0,0 +1,310 @@
<template>
<view class="pages-auth">
<view class="tip-1">为了提供更优质的服务需要获取</view>
<view class="tip-2">您的头像昵称</view>
<view class="wechat flex jc-between ai-center">
<view class="flex ai-end">
<open-data class="avatar" type="userAvatarUrl"></open-data>
<view>
<open-data class="name" type="userNickName"></open-data>
<view class="info">微信个人信息</view>
</view>
</view>
<image class="select" :src="webUrl+'/20220613104953149068.png'" mode="scaleToFill"/>
</view>
<view class="agree-box">
<checkbox-group @change="changeAgree">
<label>
<checkbox value="yes" style="transform:scale(0.8)"/>
</label>
<text @click="show=true">我已阅读并同意
<text class="btn-show">用户服务协议及隐私政策</text>
</text>
</checkbox-group>
</view>
<view class="dialog-mask" v-if="show">
<view class="dialog-body">
<image class="btn-close" :src="webUrl+'/20221230200935413332.png'" @click="show=false"/>
<view class="content">
<view class="title tc bold">用户协议及隐私政策</view>
<view class="popup-content" v-html="agreeInfo.privacyPolicy"></view>
<view class="title tc">
<button size="mini" @click="show=false">关闭</button>
</view>
</view>
</view>
</view>
<view class="btn-box">
<button class="btn-yes" type="default" v-if="canIUseGetUserProfile" @tap="getUserInfoProfile">同意</button>
<button class="btn-yes" type="default" v-else @getuserinfo="getUserInfo" open-type="getUserInfo">同意</button>
<button class="btn-no" type="default" @tap="back">拒绝</button>
</view>
</view>
</template>
<script>
import {mapActions, mapMutations, mapState} from 'vuex'
import cookie from '@/utils/store/cookie'
import {login} from '@/utils'
import {getAgree} from "@/api/public";
export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
authorize: false,
canIUseGetUserProfile: false,
agreeInfo: {},
isAgree: false,
show: false
}
},
computed: {
...mapState(['isAuthorization', '$deviceType', 'token']),
},
onLoad() {
if (wx.getUserProfile) {
this.canIUseGetUserProfile = true
}
// // 先校验用户是否授权,如果没有授权,显示授权按钮
getAgree().then(({data}) => this.agreeInfo = data);
},
onHide() {
this.updateAuthorizationPage(false)
this.changeAuthorization(false)
},
onUnload() {
this.updateAuthorizationPage(false)
this.changeAuthorization(false)
},
methods: {
...mapActions(['changeAuthorization', 'setUserInfo']),
...mapMutations(['updateAuthorizationPage']),
changeAgree(event) {
this.isAgree = event.detail.value.length > 0
},
toLogin() {
this.$yrouter.push({
path: '/pages/user/Login/index',
query: {},
})
},
back() {
this.$yrouter.switchTab({
path: '/pages/home/index',
query: {},
})
},
getUserInfo(data) {
console.log("auth",data)
if (!this.isAgree) {
uni.showToast({
title: "请先阅读并同意《用户服务协议及隐私政策》",
icon: "none",
duration: 5000
})
return
}
if (data.detail.errMsg == 'getUserInfo:fail auth deny') {
uni.showToast({
title: '取消授权',
icon: 'none',
duration: 2000,
})
return
}
uni.showLoading({
title: '登录中',
})
login()
.then(e => {
uni.hideLoading()
this.$yrouter.reLaunch({
path: cookie.get('redirect').replace(/\ /g, ''),
})
})
.catch(error => {
uni.hideLoading()
uni.showToast({
title: error,
icon: 'none',
duration: 2000,
})
})
},
getUserInfoProfile(data) {
if (!this.isAgree) {
uni.showToast({
title: "请先阅读并同意《用户服务协议及隐私政策》",
icon: "none",
duration: 5000
})
return
}
wx.getUserProfile({
lang: 'zh_CN',
desc: '需要获取您的信息用来展示',
success: res => {
uni.showLoading({
title: '登录中',
})
login(res)
.then(e => {
var redirectUrl = cookie.get('redirect').replace(/\ /g, '');
//如果已经是授权页,跳转主页
if (redirectUrl == '/pages/authorization/index') {
redirectUrl = '/pages/home/index';
}
this.$yrouter.reLaunch({
path: redirectUrl,
})
})
.catch(error => {
uni.showToast({
title: error,
icon: 'none',
duration: 2000,
})
})
},
})
},
},
mounted() {
if (wx.getUserProfile) {
this.canIUseGetUserProfile = true
}
},
}
</script>
<style lang="scss">
.pages-auth {
padding: 148rpx 48rpx;
.tip-1 {
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.tip-2 {
margin-top: 20rpx;
font-size: 40rpx;
line-height: 58rpx;
color: #333333;
}
.wechat {
margin-top: 80rpx;
.avatar {
width: 112rpx;
height: 112rpx;
margin-right: 24rpx;
border-radius: 8rpx;
}
.name {
font-size: 32rpx;
line-height: 48rpx;
color: #333333;
}
.info {
margin-top: 28rpx;
font-size: 24rpx;
line-height: 34rpx;
color: #CECECE;
}
.select {
width: 40rpx;
height: 40rpx;
}
}
.agree-box {
margin: 200rpx 0 60rpx;
font-size: 28rpx;
color: #666;
.btn-show {
color: #000;
}
}
.dialog-mask {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, .4);
z-index: 99;
.dialog-body {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 630rpx;
height: 70vh;
box-sizing: border-box;
padding: 60rpx;
border-radius: 10rpx;
background: #fff;
overflow: hidden;
.btn-close{
position: absolute;
top: 20rpx;
right: 20rpx;
width: 28rpx;
height: 28rpx;
}
.content {
height: 100%;
overflow-y: auto;
}
.title {
margin: 30rpx auto;
}
}
}
.btn-box {
width: 338rpx;
margin: 0 auto;
button::after {
border: none;
}
button {
height: 72rpx;
font-size: 30rpx;
}
.btn-yes {
background: #FF564A;
color: #fff;
}
.btn-no {
margin-top: 32rpx;
background: #eee;
color: #FF564A;
}
}
}
</style>
+346
View File
@@ -0,0 +1,346 @@
<template>
<view class="pages-auth">
<view class="tip-1">为了提供更优质的服务</view>
<view class="tip-2">请完善您的头像和昵称</view>
<view class="flex flex-col ai-center">
<button class="avatar-wrapper" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
<image class="avatar" :src="avatarUrl"></image>
</button>
<input type="nickname" class="input-wrapper" placeholder="请输入昵称" @input="inputName" @confirm="inputName"
@blur="inputName"/>
</view>
<view class="agree-box">
<checkbox-group @change="changeAgree">
<label>
<checkbox value="yes" style="transform:scale(0.8)"/>
</label>
<text @click="show=true">我已阅读并同意
<text class="btn-show">用户服务协议及隐私政策</text>
</text>
</checkbox-group>
</view>
<view class="dialog-mask" v-if="show">
<view class="dialog-body">
<image class="btn-close" :src="webUrl+'/20221230200935413332.png'" @click="show=false"/>
<view class="content">
<view class="title tc bold">用户协议及隐私政策</view>
<view class="popup-content" v-html="agreeInfo.privacyPolicy"></view>
<view class="title tc">
<button size="mini" @click="show=false">关闭</button>
</view>
</view>
</view>
</view>
<view class="btn-box">
<button class="btn-yes" type="default" v-if="canIUseGetUserProfile" @tap="getUserInfoProfile">同意</button>
<!-- <button class="btn-yes" type="default" v-else @getuserinfo="getUserInfo" open-type="getUserInfo">同意</button>-->
<button class="btn-no" type="default" @tap="back">拒绝</button>
</view>
</view>
</template>
<script>
import {mapActions, mapMutations, mapState} from 'vuex'
import cookie from '@/utils/store/cookie'
import {login} from '@/utils'
import {getAgree} from "@/api/public";
import {postUserEdit} from "@/api/user";
const defaultAvatarUrl = "/20230506100714762257.png"
export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
authorize: false,
canIUseGetUserProfile: false,
agreeInfo: {},
isAgree: false,
show: false,
nickname: "",
avatarUrl: this.$VUE_APP_RESOURCES_URL + defaultAvatarUrl,
}
},
computed: {
...mapState(['isAuthorization', '$deviceType', 'token']),
},
onLoad() {
if (wx.getUserProfile) {
this.canIUseGetUserProfile = true
}
// 先校验用户是否授权,如果没有授权,显示授权按钮
getAgree().then(({data}) => this.agreeInfo = data);
},
onHide() {
this.updateAuthorizationPage(false)
this.changeAuthorization(false)
},
onUnload() {
this.updateAuthorizationPage(false)
this.changeAuthorization(false)
},
methods: {
...mapActions(['changeAuthorization', 'setUserInfo']),
...mapMutations(['updateAuthorizationPage']),
onChooseAvatar(e) {
const {avatarUrl} = e.detail;
this.avatarUrl = avatarUrl;
},
inputName(event) {
this.nickname = event.detail.value;
},
changeAgree(event) {
this.isAgree = event.detail.value.length > 0
},
toLogin() {
this.$yrouter.push({
path: '/pages/user/Login/index',
query: {},
})
},
back() {
this.$yrouter.switchTab({
path: '/pages/home/index',
query: {},
})
},
// getUserInfo(data) {
// let that = this;
// if (!this.isAgree) {
// uni.showToast({
// title: "请先阅读并同意《用户服务协议及隐私政策》",
// icon: "none",
// duration: 5000
// })
// return
// }
//
// this.nickname = this.nickname.trim();
// if (this.nickname.length === 0) {
// uni.showToast({
// title: "请输入您的昵称",
// icon: "none",
// duration: 5000
// })
// return
// }
//
// if (data.detail.errMsg == 'getUserInfo:fail auth deny') {
// uni.showToast({
// title: '取消授权',
// icon: 'none',
// duration: 2000,
// })
// return
// }
// uni.showLoading({
// title: '登录中',
// })
// login()
// .then(e => {
// uni.hideLoading()
// this.$yrouter.reLaunch({
// path: cookie.get('redirect').replace(/\ /g, ''),
// })
// })
// .catch(error => {
// uni.hideLoading()
// uni.showToast({
// title: error,
// icon: 'none',
// duration: 2000,
// })
// })
// },
getUserInfoProfile(data) {
let that = this;
if (!this.isAgree) {
uni.showToast({
title: "请先阅读并同意《用户服务协议及隐私政策》",
icon: "none",
duration: 5000
})
return
}
this.nickname = this.nickname.trim();
if (this.nickname.length === 0) {
uni.showToast({
title: "请输入您的昵称",
icon: "none",
duration: 5000
})
return
}
wx.getUserProfile({
lang: 'zh_CN',
desc: '需要获取您的信息用来展示',
success: res => {
uni.showLoading({
title: '登录中',
})
login(res)
.then(e => {
uni.hideLoading()
postUserEdit({
nickname: that.nickname,
avatar: that.avatarUrl
}).then(result => {
let redirectUrl = cookie.get('redirect') || "";
redirectUrl = redirectUrl.replace(/\ /g, '');
//如果已经是授权页,跳转主页
if (redirectUrl == '/pages/authorization/index' || redirectUrl.length === 0) {
redirectUrl = '/pages/home/index';
}
that.$yrouter.reLaunch({
path: redirectUrl,
})
}).catch(err => console.error(err))
})
.catch(error => {
uni.showToast({
title: error,
icon: 'none',
duration: 2000,
})
})
},
})
},
},
}
</script>
<style lang="scss">
.pages-auth {
height: 100vh;
box-sizing: border-box;
padding: 148rpx 48rpx;
background: #fff;
overflow: hidden;
.tip-1 {
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.tip-2 {
margin-top: 20rpx;
font-size: 40rpx;
line-height: 58rpx;
color: #333333;
}
.avatar-wrapper {
width: 180rpx;
height: 180rpx;
margin: 32rpx 0 0 0;
padding: 0;
background: none;
.avatar {
width: 180rpx;
height: 180rpx;
border-radius: 50%;
}
}
.avatar-wrapper::after {
display: none;
}
.input-wrapper {
width: 360rpx;
height: 72rpx;
margin-top: 30rpx;
background: rgba(248, 249, 251, 1);
color: #999;
font-size: 32rpx;
text-align: center;
}
.agree-box {
margin: 120rpx 0 60rpx;
font-size: 28rpx;
color: #666;
.btn-show {
color: #000;
}
}
.dialog-mask {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, .4);
z-index: 99;
.dialog-body {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 630rpx;
height: 70vh;
box-sizing: border-box;
padding: 60rpx;
border-radius: 10rpx;
background: #fff;
overflow: hidden;
.btn-close {
position: absolute;
top: 20rpx;
right: 20rpx;
width: 28rpx;
height: 28rpx;
}
.content {
height: 100%;
overflow-y: auto;
}
.title {
margin: 30rpx auto;
}
}
}
.btn-box {
width: 338rpx;
margin: 0 auto;
button::after {
border: none;
}
button {
height: 72rpx;
font-size: 30rpx;
}
.btn-yes {
background: #FF564A;
color: #fff;
}
.btn-no {
margin-top: 32rpx;
background: #eee;
color: #FF564A;
}
}
}
</style>
+376
View File
@@ -0,0 +1,376 @@
<template>
<view class="cloud-page">
<view class="search-box">
<uni-search-bar placeholder="输入搜索关键词" @confirm="search" @clear="clearName"></uni-search-bar>
</view>
<view class="nav-box">
<view class="item flex-0" v-for="(item,index) in typeList" @click="changeType(index)">
<image :src="item.icon" mode="scaleToFill"></image>
<view class="nav">{{item.name}}</view>
</view>
</view>
<view class="list-box">
<text class="type-name">{{typeList[type]['name']}}</text>
<view class="city-box" @click="goCity('cloud')">
<image :src="webUrl+'/20220903142929759087.png'" mode="scaleToFill"></image>
<text>{{cityName}}</text>
</view>
<view class="list" v-if="hotelList.length">
<custom-waterfalls-flow :value="hotelList" imageKey="cover">
<view class="item" v-for="(item,index) in hotelList" :key="index" slot="slot{{index}}"
@click="goInnDetail(item)">
<view class="cover-box">
<image class="cover" :src="item.cover" mode="scaleToFill"></image>
<view class="my-mask">
<image class="icon" :src="webUrl+'/20220510142728577618.png'" mode="scaleToFill"></image>
<text>{{item.cityName}}</text>
</view>
</view>
<view class="more-t">{{item.content}}</view>
<view class="flex ai-center" style="margin-bottom: 18rpx;">
<image class="logo" :src="item.logo" mode="scaleToFill"></image>
<text class="one-t">{{item.name}}</text>
</view>
</view>
</custom-waterfalls-flow>
</view>
<view class="v4-nodata" v-else>
<image src="@/static/images/img_nodata.png" mode="scaleToFill" />
<view class="text">暂无数据</view>
</view>
</view>
</view>
</template>
<script>
import config from '@/utils/mapConfig';
import {
getHotelTypeList,
getHotelList
} from "@/api/inn.js";
export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
typeList: [],
name: "",
page: 1,
type: 0,
tabName: "", // 跳转初始分类名
hotelList: [],
cityName: "丽江市",
paramCity: ""
}
},
onLoad(){
this.fetchTypeList()
},
onShow() {
let name = uni.getStorageSync("name");
if (name) {
this.tabName = name;
uni.removeStorageSync("name");
}
let memCityName = uni.getStorageSync("cityName")
if (memCityName.length) {
this.cityName = memCityName;
this.paramCity = memCityName;
this.page = 1;
this.hotelList = [];
this.fetchList();
uni.removeStorageSync("cityName")
}
},
onReachBottom() {
this.page++;
this.fetchList();
},
methods: {
goCity() {
uni.navigateTo({
url:`/components/chose-city/chose-city?type=2&city=${this.cityName}`
})
},
//获取当前定位地址
getCurAddress() {
var that = this;
//定位
uni.showLoading({
title: '定位中...'
});
uni.getLocation({
type: 'wgs84',
success: function(res) {
let latitude = res.latitude;
let longitude = res.longitude;
// #ifdef H5
Vue.jsonp(
'https://apis.map.qq.com/ws/geocoder/v1/?location=' + latitude + ',' + longitude + '&key=' +
config.key, {
output: 'jsonp',
}).then(json => {
// Success.
uni.hideLoading();
that.cityName = json.result.ad_info.city;
that.paramCity = json.result.ad_info.city;
//定位成功刷新数据
that.fetchList()
}).catch(err => {
uni.hideLoading();
})
// #endif
// #ifndef H5
uni.request({
url: 'https://apis.map.qq.com/ws/geocoder/v1/?location=' + latitude + ',' + longitude +
'&key=' + config.key,
success: function(res) {
uni.hideLoading();
that.cityName = res.data.result.ad_info.city;
that.paramCity = res.data.result.ad_info.city;
//定位成功刷新数据
that.fetchList()
},
fail: function(res) {
uni.hideLoading();
},
complete: function() {}
});
// #endif
},
fail: function(res) {
uni.hideLoading();
}
});
},
fetchTypeList() {
this.hotelList = []
getHotelTypeList().then(res => {
if (res.status === 200) {
for (let i = 0; i < res.data.length; i++) {
if (this.tabName == res.data[i].name) this.type = i;
}
this.typeList = res.data
let memCityName = uni.getStorageSync("cityName")
if (memCityName.length) {
this.cityName = memCityName;
this.paramCity = memCityName;
this.page = 1;
this.list = [];
this.fetchList();
uni.removeStorageSync("cityName")
} else {
this.getCurAddress();
}
}
})
},
search(e) {
this.name = e.value;
this.page = 1;
this.hotelList = [];
this.fetchList();
},
clearName() {
this.name = "";
this.page = 1;
this.hotelList = [];
this.fetchList();
},
changeType(index) {
this.type = index;
this.page = 1;
this.hotelList = [];
this.fetchList();
},
fetchList() {
getHotelList({
name: this.name,
page: this.page,
type: this.typeList[this.type].id,
cityName: this.paramCity
}).then(res => {
if (res.status === 200) {
this.paramCity = this.cityName;
for (let i = 0; i < res.data.length; i++) {
res.data[i].hide = true;
this.hotelList.push(res.data[i])
}
}
})
},
goInnDetail: function(item) {
//跳转到客栈详情
this.$yrouter.push({
path: "/pagesInn/inn/innHome",
query: {
id: item.id
}
});
},
}
}
</script>
<style scoped lang="less">
.cloud-page {
.search-box {
padding: 0 12rpx;
background: #fff;
/deep/.uni-searchbar__box {
border-radius: 44rpx !important;
}
}
.city-box {
position: absolute;
right: 30rpx;
display: inline-flex;
align-items: center;
margin-left: 32rpx;
padding: 8rpx 18rpx 8rpx 16rpx;
border-radius: 30px;
background: #fff;
image {
width: 32rpx;
height: 32rpx;
margin-right: 4rpx;
}
text {
color: #333;
font-size: 28rpx;
}
}
.nav-box {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16rpx 36rpx 24rpx;
background: #fff;
overflow-x: auto;
.item {
display: flex;
flex-direction: column;
align-items: center;
margin-left: 70rpx;
image {
width: 64rpx;
height: 64rpx;
}
.nav {
color: #666;
font-size: 24rpx;
line-height: 34rpx;
font-weight: bold;
}
}
.item:first-child {
margin-left: 0;
}
}
::-webkit-scrollbar {
display: none;
}
.list-box {
padding: 20rpx 32rpx;
.type-name {
position: relative;
font-size: 28rpx;
line-height: 40rpx;
color: #080F1A;
}
.type-name::before {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 10rpx;
background: rgba(253, 104, 93, 0.39);
z-index: -1;
}
.list {
margin-top: 20rpx;
.cover {
width: 332rpx;
height: 332rpx;
vertical-align: middle;
}
.icon {
width: 22rpx;
height: 22rpx;
margin-right: 10rpx;
vertical-align: middle;
}
.logo {
width: 36rpx;
height: 36rpx;
vertical-align: middle;
margin: 0 8rpx;
border-radius: 50%;
}
.cover-box {
position: relative;
height: auto;
.my-mask {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 56rpx;
line-height: 56rpx;
box-sizing: border-box;
padding: 0 24rpx;
background: linear-gradient(rgba(51, 51, 51, 0), rgba(0, 0, 0, 1));
color: #fff;
font-size: 22rpx;
}
}
.more-t {
margin: 10rpx;
}
}
}
}
</style>
+341
View File
@@ -0,0 +1,341 @@
<script>
import {getHotelList, getHotelTypeList} from "@/api/inn.js";
import {getCurAddress, getLocation} from "@/utils/common";
export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
name: "",
page: 1,
typeList: [],
typeIndex: 0,
cityName: "昆明市",
hotelList: [],
}
},
onLoad() {
this.getMapData();
getHotelTypeList().then(({data}) => {
this.typeList = data;
this.search();
});
},
onShow() {
let memCityName = uni.getStorageSync("cityName")
if (memCityName.length) {
this.cityName = memCityName;
uni.removeStorageSync("cityName")
this.search();
}
},
onReachBottom() {
this.page++;
this.fetchList();
},
methods: {
goCity() {
uni.navigateTo({
url: `/components/chose-city/chose-city?type=2&city=${this.cityName}`
})
},
goInnDetail(item) {
uni.navigateTo({
url: `/pagesInn/inn/innHome?id=${item.id}`
})
},
async getMapData() {
const map = await getLocation();
if (map.length > 1) {
const {latitude, longitude} = map[1];
const address = await getCurAddress(latitude, longitude);
this.cityName = address[1].data.result.ad_info.city;
}
},
// getCurAddress() {
// let that = this;
// //定位
// uni.showLoading({
// title: '定位中...'
// });
//
// uni.getLocation({
// type: 'wgs84',
// success: function (res) {
// let latitude = res.latitude;
// let longitude = res.longitude;
//
// // #ifndef H5
// uni.request({
// url: 'https://apis.map.qq.com/ws/geocoder/v1/?location=' + latitude + ',' + longitude +
// '&key=' + config.key,
// success: function (res) {
// uni.hideLoading();
//
// that.cityName = res.data.result.ad_info.city;
// //定位成功刷新数据
// that.search()
// },
// fail: function () {
// uni.hideLoading();
// },
// complete: function () {
// }
// });
// // #endif
// },
// fail: function (err) {
// console.log("test",err)
// uni.hideLoading();
// }
// });
// },
tapType(index) {
if (this.typeIndex === index) return;
this.typeIndex = index;
this.search();
},
search() {
this.page = 1;
this.hotelList = [];
this.fetchList();
},
fetchList() {
let param = {
page: this.page,
type: this.typeList[this.typeIndex].id,
cityName: this.cityName
};
let name = this.name.trim();
if (name.length > 0) param.name = name;
getHotelList(param).then(res => {
if (res.status === 200) {
for (let i = 0; i < res.data.length; i++) {
res.data[i].hide = true;
this.hotelList.push(res.data[i])
}
}
})
}
}
}
</script>
<template>
<view class="have-fun">
<u-navbar title="寻趣味" height="90rpx">
<view slot="left">&nbsp;</view>
</u-navbar>
<view class="top-box">
<view class="search-box flex jc-between ai-center">
<input type="text" v-model="name" placeholder="搜索店铺" placeholder-style="color:#949494"
@confirm="search">
<image class="icon" :src="webUrl+'/20220903142935869059.png'" mode="scaleToFill"
@click="search"/>
</view>
<scroll-view class="type-box flex" scroll-x enable-flex>
<view class="item flex-0 flex flex-col jc-center ai-center" :class="{'active':typeIndex===index}"
v-for="(item,index) in typeList" :key="index" @click="tapType(index)">
<image :src="item.icon" mode="scaleToFill"/>
<view class="name">{{ item.name }}</view>
</view>
</scroll-view>
</view>
<view class="body">
<view class="flex jc-end">
<view class="city-box" @click="goCity('cloud')">
<image :src="webUrl+'/20220903142929759087.png'" mode="scaleToFill"></image>
<text>{{ cityName }}</text>
</view>
</view>
<view class="list" v-if="hotelList.length">
<custom-waterfalls-flow :value="hotelList" imageKey="cover">
<view class="item" v-for="(item,index) in hotelList" slot="slot{{index}}"
@click="goInnDetail(item)">
<view class="cover-box">
<image class="cover" :src="item.cover" mode="scaleToFill"></image>
<view class="my-mask">
<image class="icon" :src="webUrl+'/20220510142728577618.png'"
mode="scaleToFill"></image>
<text>{{ item.cityName }}</text>
</view>
</view>
<view class="more-t">{{ item.content }}</view>
<view class="flex ai-center" style="margin-bottom: 18rpx;">
<image class="logo" :src="item.logo" mode="scaleToFill" v-if="item.logo"></image>
<image class="logo" :src="webUrl+'/20230609145651814148.png'" v-else/>
<text class="one-t">{{ item.name }}</text>
</view>
</view>
</custom-waterfalls-flow>
</view>
<view class="v4-nodata" v-else>
<image src="@/static/images/img_nodata.png" mode="scaleToFill"/>
<view class="text">暂无数据</view>
</view>
</view>
</view>
</template>
<style scoped lang="less">
.have-fun {
padding-top: 120rpx;
.top-box {
padding: 60rpx 0 20rpx;
background: #fff;
.search-box {
width: 686rpx;
height: 60rpx;
box-sizing: border-box;
margin: 0 auto;
padding: 0 24rpx 0 32rpx;
border: 2rpx solid #BBD2D2;
border-radius: 30rpx;
input {
font-size: 24rpx;
}
.icon {
width: 32rpx;
height: 32rpx;
}
}
.type-box {
height: 180rpx;
box-sizing: border-box;
white-space: nowrap;
padding: 20rpx 20rpx 0 48rpx;
.item {
width: 160rpx;
height: 160rpx;
margin-right: 20rpx;
border-radius: 26rpx;
image {
width: 72rpx;
height: 72rpx;
}
.name {
margin-top: 12rpx;
color: #949494;
font-size: 24rpx;
line-height: 34rpx;
}
}
.active {
background: #DCF2FE;
.name {
color: #333;
}
}
}
}
.body {
padding: 20rpx 32rpx;
background: #F9F9F9;
}
.city-box {
display: inline-flex;
align-items: center;
padding: 8rpx 18rpx 8rpx 16rpx;
border-radius: 30px;
background: #fff;
image {
width: 32rpx;
height: 32rpx;
margin-right: 4rpx;
}
text {
color: #333;
font-size: 28rpx;
}
}
.list {
margin-top: 20rpx;
.cover {
width: 328rpx;
height: 328rpx;
vertical-align: middle;
}
.icon {
width: 26rpx;
height: 26rpx;
margin-top: -6rpx;
margin-right: 6rpx;
vertical-align: middle;
}
.logo {
width: 36rpx;
height: 36rpx;
vertical-align: middle;
margin: 0 8rpx;
border-radius: 50%;
}
.item {
width: 328rpx;
box-sizing: border-box;
}
.cover-box {
position: relative;
width: 328rpx;
height: auto;
border-radius: 14rpx;
overflow: hidden;
.my-mask {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 60rpx;
line-height: 60rpx;
box-sizing: border-box;
padding: 0 24rpx;
background: linear-gradient(rgba(51, 51, 51, 0), rgba(0, 0, 0, 1));
color: #fff;
font-size: 24rpx;
}
}
.more-t {
margin: 10rpx;
}
.one-t {
color: #666;
font-size: 24rpx;
}
}
/deep/ .waterfalls-flow-column .column-value {
background-color: rgba(0, 0, 0, 0) !important;
}
}
</style>
+973
View File
@@ -0,0 +1,973 @@
<template>
<view class="newsList" ref="container">
<hx-navbar :back="false" :fixed="true" title="七彩云上" statusBarFontColor="#ffffff" color="#ffffff" :left-slot="true"
:background-color="[13,197,197]" :right-slot="true">
<block slot="left">
<view class="location acea-row row-center row-middle"
style="position: relative;height: 42rpx;margin-left: 35rpx;box-sizing: border-box;">
<image style="width: 30rpx;height: 30rpx;" :src="webUrl+'/20210807134107296760.png'" mode=""></image>
<view class="city-name" @click="cityNameClick">{{cityName}}</view>
</view>
</block>
</hx-navbar>
<view style="position: fixed;right: 0;width: 100%;z-index: 5;" :style="{top:navHeight}">
<drop-down :showDd="showCitySelect" :list="cityList" @select="selectCity" @close="closeCitySelect"></drop-down>
</view>
<view class="acea-row row-column"
style="position: fixed;left: 0;right: 0;background-color: #0DC5C5;z-index: 4;overflow-y: hidden;"
:style="{top:segTop+'px'}">
<!-- 搜索开始 -->
<view class="searchGood" style="margin-top: 10rpx;">
<view class="search acea-row row-between-wrapper">
<view class="input acea-row row-between-wrapper">
<text class="iconfont icon-sousuo2"></text>
<input style="color: #acacac !important;" type="text" placeholder="请输入搜索关键词" confirm-type="search"
v-model="search" @confirm="refreshData" />
</view>
</view>
</view>
<!-- 搜索结束 -->
<!-- tab开始 -->
<view class="top-tab acea-row row-middle" style="position: relative;">
<view class="tab acea-row row-middle row-center" @click="changeTab(0)">
<view :style="(activeIndex==0?'background:#F6F6F6':'')"
class="tab-wrap acea-row row-column row-middle row-center">
<image v-if="activeIndex==0" style="width: 36rpx;height:36rpx" :src="webUrl+'/20210824104937140590.png'"
mode=""></image>
<image v-else style="width: 36rpx;height:36rpx" :src="webUrl+'/20210807135928525293.png'"
mode="scaleToFill"></image>
<text :style="'font-size:22rpx;margin-top4rpx;color:'+(activeIndex==0?'#0DC5C5':'#ffffff')">#住在云上</text>
</view>
</view>
<view class="tab acea-row row-middle row-center" @click="changeTab(1)">
<view :style="(activeIndex==1?'background:#F6F6F6':'')"
class="tab-wrap acea-row row-column row-middle row-center">
<image v-if="activeIndex==1" style="width: 32rpx;height:36rpx" :src="webUrl+'/20210824104954282401.png'"
mode=""></image>
<image v-else style="width: 36rpx;height:36rpx" :src="webUrl+'/20210807140012422075.png'"
mode="scaleToFill"></image>
<text :style="'font-size:22rpx;margin-top4rpx;color:'+(activeIndex==1?'#0DC5C5':'#ffffff')">#逛在云上</text>
</view>
</view>
<view class="tab acea-row row-middle row-center" @click="changeTab(2)">
<view :style="(activeIndex==2?'background:#F6F6F6':'')"
class="tab-wrap acea-row row-column row-middle row-center">
<image v-if="activeIndex==2" style="width: 32rpx;height:36rpx" :src="webUrl+'/20210824105005945092.png'"
mode=""></image>
<image v-else style="width: 36rpx;height:36rpx" :src="webUrl+'/20210807140042265370.png'"
mode="scaleToFill"></image>
<text :style="'font-size:22rpx;margin-top4rpx;color:'+(activeIndex==2?'#0DC5C5':'#ffffff')">#吃在云上</text>
</view>
</view>
<view class="tab acea-row row-middle row-center" @click="changeTab(3)">
<view :style="(activeIndex==3?'background:#F6F6F6':'')"
class="tab-wrap acea-row row-column row-middle row-center">
<image v-if="activeIndex==3" style="width: 36rpx;height:36rpx" :src="webUrl+'/20210824105016005512.png'"
mode=""></image>
<image v-else style="width: 36rpx;height:36rpx" :src="webUrl+'/20210807140136696881.png'"
mode="scaleToFill"></image>
<text :style="'font-size:22rpx;margin-top4rpx;color:'+(activeIndex==3?'#0DC5C5':'#ffffff')">#彩云资讯</text>
</view>
</view>
</view>
<!-- tab结束 -->
<!-- <block v-if="activeIndex==3">
<view class="" style="padding:30rpx 30rpx 0 30rpx;background-color: #F5F5F5;">
<v-tabs v-model="current" :fixed="true" :tabs="tabs" bgColor="#f5f5f5" itemBorderRadius="14.5px" itemMarginRight="30rpx" activeItemBgColor="#ff0000" itemBgColor="RGB(232,232,232)" line-height="0" color="RGB(197,198,204)" activeColor="#fff" @change="changeArtileTab"></v-tabs>
</view>
</block> -->
</view>
<!-- 占位 -->
<!-- <view class="" :style="{height:activeIndex==3?'252rpx':'152rpx'}"></view> -->
<view class="" style="height: 252rpx;"></view>
<!-- 住在云上开始 -->
<block v-if="activeIndex==0">
<view class="wrapper hot" v-if="innArray.length > 0">
<view class="hotGoodsList acea-row">
<view :style="{width:hotInnColumnWidth}" @click="goInnDetail(item)" class="newProductsItem"
v-for="(item, innInfoIndex) in innArray" :key="innInfoIndex">
<view class="img-box">
<image style="border-radius: 8rpx;" :style="{width:hotInnColumnWidth,height:hotInnColumnWidth}"
:src="item.cover" />
<view class="like-btn" @click="likeInn(item)">
<image v-if="item.zanHistory==0" style="width: 100%;height: 100%;" :src="webUrl+'/20230304134637330341.png'"
mode=""></image>
<image v-if="item.zanHistory>0" style="width: 100%;height: 100%;" :src="webUrl+'/20230304134642958611.png'"
mode=""></image>
</view>
<view class="acea-row row-middle"
style="flex-wrap: nowrap;position: absolute;left: 24rpx;right: 24rpx;bottom: 20rpx;z-index: 2;"
v-if="item.cityName != undefined && item.cityName.length>0">
<image style="width: 22rpx;height: 22rpx;" :src="webUrl+'/20210609100715629446.png'" mode=""></image>
<text style="color: #fff;font-size: 22rpx;margin-left: 10rpx;">{{item.cityName}}</text>
</view>
</view>
<view class="pro-info line2" style="min-height: 80rpx;padding: 0 10rpx;"><text>{{ item.content }}</text>
</view>
<!-- <view class="inn-tag-wrap acea-row row-left row-middle" style="padding:0 10rpx">
<view class="zanmost-tag" v-if="item.zanMostTag>0">点赞最多</view>
<view class="latest-tag" v-if="item.newTag>0">最新发布</view>
<view class="location-tag" v-if="item.cityName != undefined && item.cityName.length>0">{{item.cityName}}</view>
</view> -->
<view class="inn-shop-info acea-row row-middle"
style="flex-wrap: nowrap;margin-bottom: 20rpx;padding: 10rpx;">
<view class="acea-row row-center row-middle" style="flex-shrink: 0;">
<image class="inn-shop-icon" :src="item.logo" mode=""></image>
</view>
<view class="acea-row row-column row-between" style="flex-grow: 1;margin-left: 10rpx;">
<view class="inn-shop-name">{{item.name}}</view>
<view class="inn-shop-date">{{ innOpenDateString(item.createdTime,'yyyy/MM/dd') }}</view>
</view>
</view>
</view>
</view>
</view>
</block>
<!-- 住在云上结束 -->
<!-- 逛在云上开始 -->
<block v-if="activeIndex==1">
<!-- <view class="wrapper hot" v-if="innArray.length > 0" >
<view class="hotGoodsList acea-row row-column" >
<view style="border-radius: 8rpx;background: #FFFFFF;flex-wrap: nowrap;margin: 35rpx 35rpx 0 35rpx;padding: 16rpx;" @click="goInnDetail(item)" class="acea-row" v-for="(item, innInfoIndex) in innArray" :key="innInfoIndex">
<view class="img-box" style="width: 164rpx;height: 164rpx;flex-shrink: 0;">
<image style="border-radius: 4rpx 4rpx 0px 0px;width: 100%;height: 100%;" :src="item.cover" />
</view>
<view class="acea-row row-column row-around" style="flex-grow: 1;">
<view class="pro-info line1" style="padding: 0 10rpx;border-radius: 4rpx;">{{ item.name }}</view>
<view class="pro-info acea-row line2" style="padding: 0 10rpx;line-height: 28rpx;">
<text class="" style="font-size: 24rpx;color: #a9a9a9;">{{item.content}}</text>
</view>
<view class="inn-shop-info acea-row row-middle" style="flex-wrap: nowrap;padding: 10rpx;">
<image class="" style="width: 28rpx;height: 28rpx;" :src="webUrl+'/20210402172346756674.png'" mode=""></image>
<text class="" style="font-size: 24rpx;color: #666666;">{{item.address}}</text>
</view>
</view>
</view>
</view>
</view> -->
<view class="wrapper hot" v-if="innArray.length > 0">
<view class="hotGoodsList acea-row" style="">
<view :style="{width:hotGoodsColumnWidth,background:'#ffffff'}" @click="goInnDetail(item)"
class="newProductsItem" v-for="(item, innInfoIndex) in innArray" :key="innInfoIndex">
<view class="img-box" style="position: relative;">
<image style="border-radius: 8rpx" :style="{width:hotInnColumnWidth,height:hotInnColumnWidth}"
:src="item.cover" />
<view class="acea-row row-column"
style="flex-wrap: nowrap;position: absolute;left: 8rpx;right: 8rpx;bottom: 20rpx;z-index: 2;">
<view class="acea-row row-middle"
style="padding-left: 6rpx;padding-right: 16rpx;align-self: flex-start;min-height: 42rpx;color: #ffffff;font-size: 22rpx;background-image: url(http://admin-api.xdd618.com/file/pic/20210609100647993289.png);background-repeat: no-repeat;background-size: 100% 100%;"
v-if="item.cityName != undefined && item.cityName.length>0">
{{item.cityName}}
</view>
<view class="acea-row row-middle line2"
style="padding: 10rpx;background: #fff;border-radius: 0px 12px 12px 12px;opacity: 0.9;color: #333333;font-size: 24rpx;">
{{ item.content }}
</view>
</view>
</view>
<!-- <view class="pro-info line2" style="min-height: 80rpx;padding: 0 10rpx;border-radius: 4rpx;margin-top: 6rpx;">{{ item.content }}</view> -->
<view class="inn-shop-info acea-row row-middle" style="flex-wrap: nowrap;padding: 10rpx;">
<view class="acea-row row-center row-middle" style="flex-shrink: 0;">
<image class="inn-shop-icon" :src="item.logo" mode=""></image>
</view>
<view class="acea-row row-column row-between" style="flex-grow: 1;margin-left: 10rpx;">
<view class="inn-shop-name">{{item.name}}</view>
<!-- <view class="inn-shop-date">{{innOpenDateString(item.createdTime,'yyyy/MM/dd')}}</view> -->
</view>
</view>
</view>
</view>
</view>
</block>
<!-- 逛在云上结束 -->
<!-- 吃在云上开始 -->
<block v-if="activeIndex==2">
<view class="wrapper hot" v-if="innArray.length > 0">
<view class="hotGoodsList acea-row row-column">
<view
style="border-radius: 8rpx;background: #FFFFFF;flex-wrap: nowrap;margin: 35rpx 35rpx 0 35rpx;padding: 16rpx;"
@click="goInnDetail(item)" class="acea-row row-column" v-for="(item, innInfoIndex) in innArray"
:key="innInfoIndex">
<view class="inn-shop-info acea-row row-middle" style="flex-wrap: nowrap;padding: 10rpx;">
<view class="acea-row row-center row-middle" style="flex-shrink: 0;">
<image class="inn-shop-icon" :src="item.logo" mode=""></image>
</view>
<view class="acea-row row-column row-between" style="flex-grow: 1;margin-left: 10rpx;">
<view class="inn-shop-name">{{item.name}}</view>
</view>
</view>
<view class="pro-info acea-row line2" style="padding: 0 10rpx;line-height: 28rpx;">
<text class="" style="font-size: 24rpx;color: #a9a9a9;">{{item.content}}</text>
</view>
<!-- <view class="" style="height: 319rpx;overflow: hidden;margin-bottom: 28rpx;border-radius: 12rpx;">
<img-box style="width: 100%;" :imgList='item.pics.slice(0,3)' :num='item.pics.slice(0,3).length'></img-box>
</view> -->
<block v-if="item.pics && item.pics.length>1">
<img-box style="width: 100%;" :imgList='item.pics.slice(0,3)' :num='item.pics.slice(0,3).length'
:imgRadius='12'></img-box>
</block>
<block v-else>
<view class="" style="height: 319rpx;overflow: hidden;margin-bottom: 28rpx;border-radius: 12rpx;">
<img-box style="width: 100%;" :imgList='item.pics.slice(0,3)' :num='item.pics.slice(0,3).length'
:imgRadius='12'></img-box>
</view>
</block>
<view class="pro-info acea-row" style="padding: 0;line-height: 28rpx;">
<image class="" style="width: 28rpx;height: 28rpx;" :src="webUrl+'/20210402172346756674.png'" mode="">
</image>
<text class="" style="font-size: 24rpx;color: #666666;">{{item.address}}</text>
</view>
<!-- <view class="inn-tag-wrap acea-row row-left row-middle" style="">
<view class="zanmost-tag" v-if="item.zanMostTag>0">点赞最多</view>
<view class="latest-tag" v-if="item.newTag>0">最新发布</view>
<view class="location-tag" v-if="item.cityName != undefined && item.cityName.length>0">{{item.cityName}}</view>
</view> -->
</view>
</view>
</view>
</block>
<!-- 吃在云上结束 -->
<!-- 彩云资讯开始 -->
<block v-if="activeIndex==3">
<view class="list" v-for="(item, articleListIndex) in articleList" :key="articleListIndex">
<view @click="goNewsDetail(item)" class="item acea-row" style="flex-wrap: nowrap;">
<view class="text acea-row row-column-between">
<view class="acea-row row-column" style="position: relative;">
<view class="name line2">{{ item.title }}</view>
<view class="summary line2" style="width: 322rpx;">{{ item.synopsis }}</view>
</view>
<view class="acea-row row-between">
<view class="see-num-box acea-row row-middle">
<image :src="webUrl+'/20230304131559277594.png'" class="eye-icon" mode=""></image>
<text class="see-num-text">{{item.visit||0}}</text>
</view>
<view class="">
{{ shortDateString(item.addTime) }}
</view>
</view>
</view>
<view class="pictrue">
<image :src="item.imageInput" />
</view>
</view>
</view>
</block>
<!-- 彩云资讯结束 -->
<!--暂无客栈-->
<block v-if="activeIndex!=3">
<view class="noCommodity" v-if="innArray.length === 0 && !loading">
<view class="noPictrue">
<image src="@/static/images/img_nodata.png" class="image" />
<!-- <image src="@/static/images/img_nodata.png" mode="widthFix"></image> -->
</view>
</view>
</block>
<block v-if="activeIndex==3">
<view class="noCommodity" v-if="articleList.length === 0 && !loading">
<view class="noPictrue">
<image :src="webUrl+'/20210203154951097926.png'" class="image" />
</view>
</view>
</block>
</view>
</template>
<script>
import {
getArticleList,
getHotelNewsCategory
} from "@/api/public";
import {
getHotelList,
getHotelCityList
} from "@/api/inn.js";
import {
formatDateTime,
isNullOrEmpty
} from "@/utils";
import dropDown from "@/components/drop-down/drop-down.vue";
import config from '@/utils/mapConfig';
import imgBox from '@/components/imageTypeSet/imagebox.vue'
var that;
//获取系统状态栏高度
// var statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
export default {
name: "FoodInfomation",
components: {
// choseCity,
dropDown,
imgBox
},
props: {},
data: function() {
return {
showCitySelect: false,
current: 0,
webUrl: this.$VUE_APP_RESOURCES_URL,
activeIndex: 3,
navHeight: 20 + 44 + 'px',
segTop: 20 + 64,
searchTop: 64 + 64 + 20,
hotInnColumnWidth: '325rpx',
cityName: "定位中...",
page: 1,
limit: 20,
search: "",
loadTitle: "",
loading: false,
loadend: false,
imgUrls: [],
navLsit: [],
articleList: [],
cityList: [], //有客栈入驻的城市列表
innArray: [],
active: 0,
cid: 0,
swiperNew: {
pagination: {
el: ".swiper-pagination",
clickable: true
},
autoplay: {
disableOnInteraction: false,
delay: 2000
},
loop: true,
speed: 1000,
observer: true,
observeParents: true
},
tabs: [],
newsTypeArray: [],
curSelectCategory: ''
};
},
onShow: function() {
this.getHotelCityList();
//进入时如果有jumpIndex
var initIdx = uni.getStorageSync('jumpIndex');
if (initIdx) {
this.activeIndex = parseInt(initIdx);
console.log('jumpIndex:' + initIdx);
uni.removeStorageSync('jumpIndex');
}
// this.getHotelList();
this.getArticleLists();
this.getHotelNewsCategory();
},
onLoad: function(e) {
that = this;
uni.getSystemInfo({
success: (e) => {
//两列商品宽度
that.hotInnColumnWidth = (e.screenWidth - uni.upx2px(90)) / 2 + 'px';
that.navHeight = e.statusBarHeight + 44 + 'px';
that.segTop = e.statusBarHeight + 44;
that.searchTop = e.statusBarHeight + 44 + uni.upx2px(64);
}
});
uni.$on('needRefresh', item => {
console.log(item, '第一页面数据');
this.cityName = item.cityName;
this.refreshData();
});
//this.getHotelList();
//this.getArticleLists();
//获取定位地址
this.getCurAddress();
},
onUnload: function() {
uni.$off('needRefresh');
},
mounted: function() {
// this.articleBanner();
//this.articleCategory();
// this.$scroll(this.$refs.container, () => {
// !this.loading && this.getArticleLists();
// });
//this.getHotelList();
//this.getArticleLists();
//获取定位地址
//this.getCurAddress();
},
onPullDownRefresh() {
this.refreshData();
},
onReachBottom() {
if (this.activeIndex != 3) {
!this.loading && this.getHotelList();
} else {
!this.loading && this.getArticleLists();
}
},
methods: {
isNullOrEmpty,
getHotelNewsCategory() {
var that = this;
getHotelNewsCategory()
.then(res => {
if (res.data && res.data.length > 0) {
that.newsTypeArray = res.data;
that.tabs = [];
that.newsTypeArray.unshift({
'label': '全部',
'value': ''
});
that.newsTypeArray.forEach((item) => {
that.tabs.push('#' + item.label);
});
}
})
.catch(err => {
})
},
changeArtileTab(index) {
console.log('当前选中索引:' + index)
console.log("this.newsTypeArray.length: " + this.newsTypeArray.length)
//获取分类
if (index < this.newsTypeArray.length) {
//获取切换分类并刷新列表
var curCategory = this.newsTypeArray[index];
this.curSelectCategory = curCategory.value;
this.page = 1;
this.loading = false;
this.loadend = false;
this.getArticleLists();
}
},
selectCity(city) {
this.showCitySelect = false;
//this.$refs.popup.close();
// console.log("selectCity:"+this.showCitySelect);
this.cityName = city;
this.refreshData();
},
closeCitySelect() {
this.showCitySelect = false;
//this.$refs.popup.close();
// console.log("closeCitySelect:"+this.showCitySelect);
},
getHotelCityList() {
getHotelCityList().then((res) => {
that.cityList = res.data;
var allItem = {
name: '全 国'
}
that.cityList.unshift(allItem);
}).catch((err) => {
}).finally(() => {
})
},
// popChange(e){
// this.showCitySelect = e.show;
// },
cityNameClick() {
this.showCitySelect = true;
},
refreshData: function() {
this.page = 1;
this.loading = false;
this.loadend = false;
if (this.activeIndex != 3) {
this.getHotelList();
} else {
this.getArticleLists();
}
},
changeTab: function(index) {
this.innArray = [];
this.activeIndex = index;
this.page = 1;
this.loading = false;
this.loadend = false;
//刷新数据
if (this.activeIndex != 3) {
this.getHotelList();
} else {
this.getArticleLists();
}
},
goInnDetail: function(item) {
//跳转到客栈详情
this.$yrouter.push({
path: "/pagesInn/inn/innHome",
query: {
id: item.id
}
});
},
likeInn: function(item) {
//喜欢操作
},
//获取当前定位地址
getCurAddress() {
var that = this;
//定位
uni.showLoading({
title: '定位中...'
});
//this.getLocation();
uni.getLocation({
type: 'wgs84',
success: function(res) {
let latitude = res.latitude;
let longitude = res.longitude;
console.log('latitude:' + latitude + 'longitude:' + longitude)
// #ifdef H5
Vue.jsonp(
'https://apis.map.qq.com/ws/geocoder/v1/?location=' + latitude + ',' + longitude + '&key=' +
config.key, {
//callbackName: 'QQmap',
output: 'jsonp',
}).then(json => {
// Success.
uni.hideLoading();
that.cityName = json.result.ad_info.city;
//定位成功刷新数据
if (that.activeIndex != 3) {
that.refreshData();
}
}).catch(err => {
// Failed.
console.log('地址解析失败:' + JSON.stringify(err));
uni.hideLoading();
})
// #endif
// #ifndef H5
uni.request({
url: 'https://apis.map.qq.com/ws/geocoder/v1/?location=' + latitude + ',' + longitude +
'&key=' + config.key,
success: function(res) {
// console.log('res:'+JSON.stringify(res.data));
uni.hideLoading();
that.cityName = res.data.result.ad_info.city;
//定位成功刷新数据
if (that.activeIndex != 3) {
that.refreshData();
}
},
fail: function(res) {
console.log('地址解析失败');
uni.hideLoading();
},
complete: function() {
}
});
// #endif
},
fail: function(res) {
uni.hideLoading();
// uni.showToast({
// title:'城市定位失败:'+JSON.stringify(res),
// icon:'none',
// duration:2000
// })
}
});
},
shortDateString(dataStr) {
var ret = '';
if (isNullOrEmpty(dataStr)) {
} else {
var s = dataStr.toString();
s = s.replace(/-/g, "/");
var date = new Date(s).getTime();
ret = formatDateTime(date, 'yyyy-MM-dd');
}
return ret;
},
innOpenDateString(str, format) {
return formatDateTime(str, format);
},
goNewsDetail(item) {
this.$yrouter.push({
path: "/pages/foodInfomation/foodInfomationDetail",
query: {
id: item.id
}
});
},
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,
name: that.search,
type: that.curSelectCategory
};
getArticleList(q).then(res => {
that.loading = false;
//apply();js将一个数组插入另一个数组;
if (that.page == 1) {
that.articleList = [];
}
that.articleList.push.apply(that.articleList, res.data);
that.loadend = res.data.length < that.limit; //判断所有数据是否加载完成;
that.page = that.page + 1;
}).catch((err) => {
}).finally(() => {
uni.stopPullDownRefresh();
});
},
getHotelList: function() {
let that = this;
if (that.loading) return; //阻止下次请求(false可以进行请求);
if (that.loadend) return; //阻止结束当前请求(false可以进行请求);
that.loading = true;
var q = {
page: that.page,
limit: that.limit,
type: that.activeIndex + 1,
name: that.search
};
//如果定位到了城市加入参数
if (this.cityName.length > 0 && this.cityName != '定位中...') {
q.cityName = this.cityName;
//全国传空字符串
if (this.cityName == '全 国') {
q.cityName = '';
}
}
getHotelList(q).then(res => {
that.loading = false;
//apply();js将一个数组插入另一个数组;
if (that.page == 1) {
that.innArray = [];
}
that.innArray.push.apply(that.innArray, res.data);
that.loadend = res.data.length < that.limit; //判断所有数据是否加载完成;
that.page = that.page + 1;
}).catch((err) => {
}).finally(() => {
uni.stopPullDownRefresh();
});
},
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>
<style scoped lang="less">
.searchGood .search .input {
background-color: #f6f6f6 !important;
}
.searchGood .search {
padding-left: 35rpx !important;
padding-right: 35rpx !important;
}
.pink-dot {
width: 24rpx;
height: 24rpx;
background: rgba(255, 86, 74, 0.4);
border-radius: 50%;
position: absolute;
z-index: 0;
bottom: 0;
right: -12rpx;
}
.main-title {
font-size: 36rpx;
line-height: 36rpx;
// color: #080F1A;
color: #FFFFFF;
position: relative;
}
.eye-icon {
width: 32rpx;
height: 32rpx;
margin-right: 8rpx;
}
.zan-icon {
width: 32rpx;
height: 32rpx;
margin-right: 8rpx;
}
.zan-num-text {
color: #080F1A;
font-size: 24rpx;
}
.see-num-text {
color: #080F1A;
font-size: 24rpx;
}
.newsList .list .item .text .name {
color: #080F1A !important;
font-size: 32rpx;
font-weight: bold;
}
.newsList .list .item .text {
margin-right: 10rpx;
width: auto !important;
height: auto !important;
}
.newsList .list .item .pictrue {
flex-shrink: 0;
width: 288rpx !important;
height: 216rpx !important;
}
.newsList .list .item {
background-color: #fff;
flex-wrap: nowrap;
padding: 35rpx !important;
margin: 35rpx 30rpx !important;
border-radius: 8rpx;
}
.summary {
color: #C2C5CC;
font-size: 24rpx;
}
.sub-title {
font-size: 14*2rpx;
margin-top: 10rpx;
color: rgba(252, 85, 179, 0.7);
}
.title .hot-title {
font-size: 18*2rpx;
color: #FF7900;
background: rgba(255, 255, 255, 1);
margin-left: 5*2rpx;
margin-right: 5*2rpx;
}
.hotGoodsList {
position: relative;
margin: 20rpx 0 35rpx 0;
background-color: transparent;
flex-wrap: wrap;
}
.hotGoodsList .newProductsItem {
margin-left: 35rpx;
margin-top: 20rpx;
background-color: #ffffff;
}
.img-box {
position: relative;
}
.price-tag {
position: absolute;
width: 39*2rpx;
height: 19*2rpx;
left: 0;
top: 0;
}
.like-btn {
position: absolute;
width: 24*2rpx;
height: 24*2rpx;
right: 0;
top: 0;
}
.inn-tag-wrap {
margin-top: 10rpx;
margin-bottom: 10rpx;
}
.zanmost-tag {
padding: 2rpx 8rpx 2rpx 8rpx;
background: #FF2D69;
font-size: 10*2rpx;
color: #FFFFFF;
}
.latest-tag {
padding: 2rpx 8rpx 2rpx 8rpx;
background: #0DC5C5;
font-size: 10*2rpx;
color: #FFFFFF;
margin-left: 8rpx;
}
.location-tag {
padding: 2rpx 8rpx 2rpx 8rpx;
background: #EBECF0;
font-size: 10*2rpx;
color: #333333;
margin-left: 8rpx;
}
.inn-shop-icon {
border-radius: 50%;
width: 24*2rpx;
height: 24*2rpx;
}
.inn-shop-name {
font-size: 28rpx;
color: #080F1A;
font-weight: 500;
}
.inn-shop-date {
font-size: 18rpx;
color: #C2C5CC;
}
.location {
padding: 4rpx 16rpx;
background: #EBECF0;
color: #41454D;
border-radius: 22rpx;
}
.city-name {
color: #41454D;
font-size: 24rpx;
margin-left: 4rpx;
line-height: 24rpx;
}
.btLine {
width: 100%;
height: 12rpx;
margin-top: -4rpx;
background: #FD685D;
}
.pro-info {
font-size: 14*2rpx;
}
.top-tab {
height: 104rpx;
margin-left: 35rpx;
margin-right: 35rpx;
margin-top: 20rpx;
// background: #E9E9E9;
// border-radius:22rpx;
}
.top-tab .tab {
position: relative;
// padding: 0 20rpx;
flex: 1;
text-align: center;
height: 100%;
}
.top-tab .tab .tab-title {
position: relative;
z-index: 1;
line-height: 84rpx;
}
.top-tab .tab .tab-bg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 54rpx;
z-index: 0;
}
.top-tab .tab .tab-wrap {
// background: linear-gradient(180deg, #56D4D4 0%, #0DC5C5 100%);
// background: #F6F6F6;
// box-shadow: 0px 6rpx 16rpx #91D5D5;
opacity: 1;
border-radius: 12rpx;
padding: 10rpx;
height: 100%;
width: 100%;
}
</style>
@@ -0,0 +1,210 @@
<template>
<view class="newsDetail">
<view class="title">{{ articleInfo.title }}</view>
<view class="list acea-row row-middle">
<view class="label line1" style="color: #999;">来源:{{articleInfo.author||"未知"}}</view>
<view class="item">
<!-- <text class="iconfont icon-shenhezhong"></text> -->
{{ articleInfo.addTime }}
</view>
<view class="item acea-row row-middle">
<image :src="webUrl+'/20230304131559277594.png'" class="eye-icon" mode=""></image>
<text class="see-num-text">{{articleInfo.visit||0}}</text>
</view>
</view>
<view class="conter" v-html="articleInfo.content"></view>
</view>
</template>
<style>
.conter>>>img{
display:block;
max-width:100% !important;
}
page{
background: #fff !important;
}
</style>
<style scoped lang="less">
.newsDetail .list .label{
padding: 0;
max-width: auto !important;
}
.eye-icon{
width: 32rpx;
height: 32rpx;
margin-right: 8rpx;
}
.zan-icon{
width: 32rpx;
height: 32rpx;
margin-right: 8rpx;
}
.zan-num-text{
color: #080F1A;
font-size: 24rpx;
}
.see-num-text{
color: #080F1A;
font-size: 24rpx;
}
.newsDetail .title{
font-size: 40rpx !important;
font-weight: bold;
color: #080F1A !important;
}
.newsDetail .picTxt {
width: 6.9*100rpx;
height: 2*100rpx;
border-radius: 0.2*100rpx;
border: 1px solid #e1e1e1;
position: relative;
margin: 0.3*100rpx auto 0 auto;
}
.newsDetail .picTxt .pictrue {
width: 2*100rpx;
height: 2*100rpx;
}
.newsDetail .picTxt .pictrue image{
width: 100%;
height: 100%;
border-radius: 0.2*100rpx 0 0 0.2*100rpx;
display: block;
}
.newsDetail .picTxt .text {
width: 4.6*100rpx;
}
.newsDetail .picTxt .text .name {
font-size: 0.3*100rpx;
color: #282828;
}
.newsDetail .picTxt .text .money {
font-size: 0.24*100rpx;
margin-top: 0.4*100rpx;
font-weight: bold;
}
.newsDetail .picTxt .text .money .num {
font-size: 0.36*100rpx;
}
.newsDetail .picTxt .text .y_money {
font-size: 0.26*100rpx;
color: #999;
text-decoration: line-through;
}
.newsDetail .picTxt .label {
position: absolute;
background-color: #303131;
width: 1.6*100rpx;
height: 0.5*100rpx;
right: -0.07*100rpx;
border-radius: 0.25*100rpx 0 0.06*100rpx 0.25*100rpx;
text-align: center;
line-height: 0.5*100rpx;
bottom: 0.24*100rpx;
}
.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.08*100rpx solid #303131;
border-right: 0.08*100rpx solid transparent;
top: -0.08*100rpx;
right: 0;
}
.newsDetail .bnt {
color: #fff;
font-size: 0.3*100rpx;
width: 6.9*100rpx;
height: 0.9*100rpx;
border-radius: 0.45*100rpx;
margin: 0.48*100rpx auto 0 auto;
text-align: center;
line-height: 0.9*100rpx;
}
</style>
<script>
import { getArticleDetails } from "@/api/public";
export default {
name: "FoodInfomationDetail",
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 => {
var data = res.data;
data.content = that.formatRichText(data.content);
that.articleInfo = data;
that.updateTitle();
console.log('current path:'+that.$yroute.path);
//动态配置share参数
that.$set(that, "share", {
title:that.articleInfo.title,
path:'/pages/foodInfomation/foodInfomationDetail?id='+that.$yroute.query.id,
imageUrl:'',
desc:'',
content:''
});
});
},
/**
* 处理富文本里的图片宽度自适应
* 1.去掉img标签里的style、width、height属性
* 2.img标签添加style属性:max-width:100%;height:auto
* 3.修改所有style里的width属性为max-width:100%
* 4.去掉<br/>标签
* @param html
* @returns {void|string|*}
*/
formatRichText:function(html){
let newContent= html.replace(/<img[^>]*>/gi,function(match,capture){
match = match.replace(/style="[^"]+"/gi, '').replace(/style='[^']+'/gi, '');
match = match.replace(/width="[^"]+"/gi, '').replace(/width='[^']+'/gi, '');
match = match.replace(/height="[^"]+"/gi, '').replace(/height='[^']+'/gi, '');
return match;
});
newContent = newContent.replace(/style="[^"]+"/gi,function(match,capture){
match = match.replace(/width:[^;]+;/gi, 'max-width:100%;').replace(/width:[^;]+;/gi, 'max-width:100%;');
return match;
});
newContent = newContent.replace(/<br[^>]*\/>/gi, '');
newContent = newContent.replace(/\<img/gi, '<img style="max-width:100%;height:auto;display:block;margin-top:0;margin-bottom:0;"');
return newContent;
}
}
};
</script>
+163
View File
@@ -0,0 +1,163 @@
<template>
<view>
<view class="search-box">
<uni-search-bar placeholder="输入搜索关键词" @confirm="search" @clear="clearName"></uni-search-bar>
</view>
<view class="list" v-if="list.length">
<custom-waterfalls-flow :value="list" imageKey="imageInput">
<view class="item" v-for="(item,index) in list" :key="index" slot="slot{{index}}" @click="goNewsDetail(item)">
<image class="cover" :src="item.imageInput" mode="scaleToFill"></image>
<view class="content">
<view class="title more-t">{{item.title}}</view>
<view class="mark more-t">{{item.synopsis}}</view>
<view class="footer flex jc-between ai-center">
<view class="visit flex ai-center">
<image class="icon" :src="webUrl+'/20220609111928828152.png'" mode="scaleToFill"></image>
{{item.visit}}
</view>
<view class="time">{{item.addTime.substring(0,10)}}</view>
</view>
</view>
</view>
</custom-waterfalls-flow>
</view>
<view class="v4-nodata" v-else>
<image src="@/static/images/img_nodata.png" mode="scaleToFill" />
<view class="text">暂无数据</view>
</view>
</view>
</template>
<script>
import {
getArticleList
} from "@/api/public";
export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
page: 1,
limit: 8,
keyword: "",
list: [],
isWait: false
}
},
onLoad() {
this.fetchList();
},
onReachBottom() {
this.page++;
this.fetchList();
},
methods: {
search(e) {
this.keyword = e.value;
this.page = 1;
this.list = [];
this.fetchList();
},
clearName() {
this.keyword = "";
this.page = 1;
this.list = [];
this.fetchList();
},
fetchList() {
if (this.isWait) return;
this.isWait = true;
let params = {
keyword: this.keyword,
page: this.page,
limit: this.limit
};
getArticleList(params).then(res => {
if (res.status === 200) {
for (let i = 0; i < res.data.length; i++) {
res.data[i].hide = true;
this.list.push(res.data[i])
}
}
this.isWait = false;
});
},
goNewsDetail(item) {
this.$yrouter.push({
path: "/pages/foodInfomation/foodInfomationDetail",
query: {
id: item.id
}
});
}
}
}
</script>
<style lang="less">
.search-box {
padding: 0 12rpx;
background: #fff;
/deep/.uni-searchbar__box {
border-radius: 44rpx !important;
}
}
.list {
margin: 28rpx 32rpx;
.item {
border-radius: 4rpx;
background: #fff;
.cover {
width: 332rpx;
height: 200rpx;
vertical-align: middle;
}
.title {
padding: 12rpx 16rpx 0;
font-size: 26rpx;
font-weight: bold;
line-height: 38rpx;
color: #333;
}
.mark {
margin: 14rpx 16rpx;
font-size: 22rpx;
line-height: 32rpx;
color: #999;
}
.footer {
padding: 12rpx 16rpx 16rpx;
border-top: 1rpx solid #E1E1E1;
font-size: 22rpx;
}
.icon {
width: 28rpx;
height: 28rpx;
vertical-align: middle;
margin-right: 4rpx;
}
.visit {
color: #333;
}
.time {
color: #999;
}
}
}
</style>
+2046
View File
File diff suppressed because it is too large Load Diff
+57
View File
@@ -0,0 +1,57 @@
<template>
<map
id="map"
:longitude="map.longitude"
:latitude="map.latitude"
:markers="mapConfig"
scale="15"
show-location
style="width: 100%; height: 100%;"
></map>
</template>
<script>
export default {
name: "Index",
components: {},
props: {},
data: function() {
return {
mapConfig: {
latitude: "",
longitude: "",
name: "",
address: ""
},
map: {
latitude: "",
longitude: ""
}
};
},
onShow: function() {
this.map = {
latitude: this.$yroute.query.latitude,
longitude: this.$yroute.query.longitude
};
this.mapConfig = [{
id: 1,
width: 50,
height: 50,
iconPath: this.$yroute.query.image,
latitude: this.$yroute.query.latitude,
longitude: this.$yroute.query.longitude,
title: this.$yroute.query.name,
name: this.$yroute.query.name,
address: this.$yroute.query.detailedAddress
}];
console.log(this.mapConfig);
},
methods: {}
};
</script>
<style lang="less">
page {
width: 100%;
height: 100%;
}
</style>
+140
View File
@@ -0,0 +1,140 @@
<template>
<view class="apply-return">
<view class="goodsStyle acea-row row-between" v-for="cart in orderInfo.cartInfo" :key="cart.id">
<view class="pictrue">
<image :src="cart.productInfo.image" class="image" />
</view>
<view class="text acea-row row-between">
<view class="name line2">{{ cart.productInfo.storeName }}</view>
<view class="money">
<view>
{{
cart.productInfo.attrInfo
? cart.productInfo.attrInfo.price
: cart.productInfo.price
}}
</view>
<view class="num">x{{ cart.cartNum }}</view>
</view>
</view>
</view>
<view class="list">
<view class="item acea-row row-between-wrapper">
<view>退货件数</view>
<view class="num">{{ orderInfo.totalNum }}</view>
</view>
<view class="item acea-row row-between-wrapper">
<view>退款金额</view>
<view class="num">{{ orderInfo.payPrice }}</view>
</view>
<picker :value="reason" :range="reasonList" @change="changeReason">
<view class="item acea-row row-between-wrapper">
<view>退款原因</view>
<view class="num">{{reason}}</view>
<text class="iconfont icon-jiantou"></text>
</view>
</picker>
<view class="item textarea acea-row row-between">
<view>备注说明</view>
<textarea placeholder="填写备注信息,100字以内" class="num" v-model="refundReasonWapExplain"></textarea>
</view>
</view>
<view class="returnBnt bg-color-red" @click="submit">申请退款</view>
</view>
</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: "",
refundReasonWapExplain: ""
};
},
methods: {
changeReason(e) {
this.reason = this.reasonList[e.mp.detail.value];
},
getOrderDetail() {
orderDetail(this.id)
.then(res => {
this.orderInfo = res.data;
})
.catch(err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: 'none',
duration: 2000
});
});
},
getRefundReason() {
getRefundReason().then(res => {
this.reasonList = res.data;
});
},
submit() {
const refundReasonWapExplain = trim(this.refundReasonWapExplain),
text = this.reason;
if (!text) {
uni.showToast({
title: "请选择退款原因",
icon: 'none',
duration: 2000
});
return
}
postOrderRefund({
text,
uni: this.orderInfo.orderId,
refundReasonWapExplain
})
.then(res => {
uni.showToast({
title: res.msg,
icon: "success",
duration: 2000
});
setTimeout(() => {
this.$yrouter.back();
}, 1500);
})
.catch(err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: 'none',
duration: 2000
});
});
}
},
mounted() {
this.id = this.$yroute.query.id || 0;
this.getOrderDetail();
this.getRefundReason();
}
};
</script>
+398
View File
@@ -0,0 +1,398 @@
<template>
<view class="logistics">
<view class="header acea-row row-between row-top" v-for="cart in cartInfo" :key="cart.id">
<view class="pictrue">
<image :src="cart.productInfo.image" />
</view>
<view class="text acea-row row-between">
<view class="name line2">{{ cart.productInfo.store_name }}</view>
<view class="money">
<view>{{ cart.truePrice }}</view>
<view>x{{ cart.cart_num }}</view>
</view>
</view>
</view>
<view class="logisticsCon" style="margin-bottom: 5px">
<view class="company acea-row row-between-wrapper">
<view class="picTxt acea-row row-between-wrapper">
<view class="iconfont icon-wuliu"></view>
<view class="text">
<view>
<text class="name line1">物流公司</text>
{{ orderInfo.deliveryName }}
</view>
<view class="express line1">
<text class="name">快递单号</text>
{{ orderInfo.deliveryId }}
</view>
</view>
</view>
<view
class="copy acea-row row-center-wrapper copy-data"
@click="copyClipboard(orderInfo.deliveryId)"
>复制单号</view>
</view>
<view class="item" v-for="(express, expressListIndex) in expressList" :key="expressListIndex">
<view class="circular" :class="expressListIndex === 0 ? 'on' : ''"></view>
<view class="text">
<view :class="expressListIndex === 0 ? 'font-color-red' : ''">{{ express.status }}</view>
<view class="data">{{ express.time }}</view>
</view>
</view>
</view>
<!-- 物流进度条 -->
<view class="div-bg bg-white" style="font-size:12px; background:#fff;">
<!--物流跟踪-->
<view style="margin-bottom:5px;">
<view
class="bg-white"
style="width: 92%; margin-left: 4%;margin: auto;padding-left: 15px;padding-right: 15px;padding-top: 10px"
>
<view style="font-size: 26rpx;color: #111111; margin: 5px 0">
物流跟踪
<!--物流跟踪-->
</view>
<view>
<view class="track-rcol">
<view class="track-list">
<view>
<view
class="track-list-item"
v-for="(item,logisticsListindex) in logisticsList"
:key="logisticsListindex"
>
<view class="active" v-if="logisticsListindex===0">
<view></view>
<i class="node-icon"></i>
<text class="txt">{{item.acceptStation}}</text>
<text class="time">{{item.acceptTime}}</text>
</view>
<view
v-if="logisticsListindex > 0 && logisticsListindex !== logisticsList.length-1"
>
<i class="node-icon"></i>
<text class="txt">{{item.acceptStation}}</text>
<text class="time">{{item.acceptTime}}</text>
</view>
<view v-if="logisticsListindex === logisticsList.length-1" class="finall">
<i class="div-spilander"></i>
<i class="node-icon"></i>
<text class="txt">{{item.acceptStation}}</text>
<text class="time">{{item.acceptTime}}</text>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="no-express" v-if="loaded && !expressList.length">
<image :src="webUrl+'/20210203153343122397.png'" />
</view>
<Recommend></Recommend>
</view>
</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 {
webUrl:this.$VUE_APP_RESOURCES_URL,
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 => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
});
},
getExpress() {
if (!this.id) {
uni.showToast({
title: err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
return;
}
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 => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
<style scoped lang="less">
.no-express {
margin: 1.5 * 100rpx 0;
}
.no-express image {
width: 6 * 100rpx;
margin: 0 auto;
display: block;
}
.message-text {
font-family: MicrosoftYaHei;
font-size: 1 * 100rpx;
font-weight: normal;
font-stretch: normal;
line-height: 3 * 100rpx;
letter-spacing: 0 * 100rpx;
color: #333333;
width: 50%;
}
.fontblack {
color: #999999;
}
.img2 {
width: 0.81 * 100rpx;
height: 0.8 * 100rpx;
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: 1 * 100rpx;
}
.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: 1 * 100rpx;
}
.orderTitle {
font-size: 1 * 100rpx;
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.5 * 100rpx;
}
.orderDetail {
font-size: 0.26 * 100rpx;
color: #666666;
text-align: left;
}
.border-ceter {
width: 92%;
padding-left: 15px;
padding-right: 15px;
}
.pay-button {
width: 88%;
height: 2.6 * 100rpx;
position: relative;
background-color: red;
color: white;
margin-left: 6%;
}
ul view {
list-style: none;
font-size: 0.24 * 100rpx;
}
ul {
}
.track-rcol {
}
.track-list {
position: relative;
}
.track-list > view {
position: relative;
padding: 0 0 0.5 * 100rpx 20rpx;
}
.track-list .track-list-item {
position: relative;
padding: 0 0 0.5 * 100rpx 20rpx;
line-height: 0.3 * 100rpx;
border-left: 1px solid #d9d9d9;
color: #999;
}
.track-list view.first {
color: red;
padding-top: 0;
width: 100%;
text-align: left;
border-left: 1px solid #d9d9d9;
}
.track-list view.node-icon {
position: absolute;
left: -6.5px;
border-radius: 50%;
width: 0.2 * 100rpx;
height: 0.2 * 100rpx;
top: 4px;
background-color: #b2b2b2;
padding: 0 !important;
}
.track-list view.active .node-icon {
background-position: 0 -72px;
background-color: #ea7c0a;
width: 0.3 * 100rpx;
z-index: 2;
height: 0.3 * 100rpx;
position: absolute;
left: -0.19 * 100rpx;
top: 0;
border-radius: 50%;
}
.track-list view.time {
margin-right: 20px;
position: relative;
top: 4px;
display: inline-block;
vertical-align: middle;
color: #999;
width: 100%;
text-align: left;
}
.track-list view.txt {
position: relative;
display: inline-block;
vertical-align: top;
color: #999;
left: 0.2 * 100rpx;
top: 0.04 * 100rpx;
}
.track-list view.first .time {
text-align: left;
width: 94%;
color: red;
}
.track-list view.first .txt {
color: red;
text-align: left;
width: 94%;
}
.track-list view.finall {
padding: 0px 0 0.5 * 100rpx 5px;
line-height: 18px;
border-color: white;
border-left: 1px solid #ffffff;
color: #999;
}
.track-list view.finall .div-spilander {
width: 1px;
position: absolute;
left: -1.5px;
height: 0.5 * 100rpx;
background-color: #d9d9d9;
}
</style>
+506
View File
@@ -0,0 +1,506 @@
<template>
<view class="my-order" ref="container">
<u-tabs lineColor="#FF564A" activeStyle="#FF564A" inactiveStyle="#C2C5CC" :current="type" :list="tabList"
@click="tabChange"></u-tabs>
<view class="list" style="padding: 80rpx 0 30rpx;">
<view class="item" v-for="(order,orderListIndex) in orderList" :key="orderListIndex">
<view class="shop-info flex jc-between ai-center" v-if="order.merName">
<view class="flex ai-center">
<image :src="webUrl+'/20221008152431059973.png'" style="width: 40rpx;height: 40rpx"/>
<text class="name">{{ order.merName }}</text>
</view>
<view class="flex ai-center">
<image :src="webUrl+'/20221008152418897577.png'" style="width: 24rpx;height: 24rpx"/>
<text class="address">{{ order.merCityName }}</text>
</view>
</view>
<view class="title acea-row row-between-wrapper" style="padding: 0 0 0 30rpx !important;">
<view 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>
<span class="sign cart-color acea-row row-center-wrapper" v-if="order.storeId > 0">门店</span>
订单号:{{ order.orderId }}
</view>
<view class="font-color-white statusTag" v-if="order.isTickets===1 && order._status._type === 1">
待核销
</view>
<view class="font-color-white statusTag" v-else>{{ getStatus(order) }}</view>
</view>
<view @click="goOrderDetails(order)">
<view class="item-info acea-row row-between row-top" v-for="(cart,cartInfoIndex) in order.cartInfo"
:key="cartInfoIndex">
<view class="pictrue">
<image :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"/>
<image :src="cart.productInfo.image" @click.stop="
$yrouter.push({
path: '/pages/activity/GroupDetails/index',query:{id:cart.combinationId}
})
" v-else-if="cart.combinationId > 0"/>
<image :src="cart.productInfo.image" @click.stop="
$yrouter.push({
path: '/pages/activity/DargainDetails/index',query:{id:cart.bargainId}
})
" v-else-if="cart.bargainId > 0"/>
<image :src="cart.productInfo.image" @click.stop="
$yrouter.push({
path: '/pages/activity/SeckillDetails/index',query:{id:cart.seckillId}
})
" v-else-if="cart.seckillId > 0"/>
</view>
<view class="text acea-row row-between">
<view class="acea-row row-column" style="width: 100%">
<view class="name line2">{{ cart.productInfo.storeName }}</view>
<view class="attr line1" style="color: #999999;" v-if="cart.productInfo.attrInfo">
属性{{ cart.productInfo.attrInfo.sku }}
</view>
</view>
<view class="money">
<view>{{ force2Decimal(cart.truePrice) }}</view>
<view>x{{ cart.cartNum }}</view>
</view>
</view>
</view>
</view>
<view class="totalPrice acea-row row-between row-middle">
<view class="" v-if="order.createTime"><span class="orderTime">{{ order.createTime }}</span></view>
<view class="">{{ order.totalNum || 0 }}件商品总金额
<text class="money font-color-lightred">{{ force2Decimal(order.payPrice) }}</text>
</view>
</view>
<view class="bottom flex jc-between ai-center">
<view class="group-btn"
v-if="(Number(order._status._type) === 2 || Number(order._status._type) === 3) &&
order.isTickets === 0">
<text class="btn-more" @click="tapShowMore(order,orderListIndex)">更多</text>
<view class="group-float" v-show="order.showMore">
<view class="btn btn-service flex jc-center ai-center" @click="goRoom(order)"
v-if="order.merName">联系客服
</view>
<view class="btn flex jc-center ai-center" @click="goRefund(order)">申请退款</view>
</view>
</view>
<template v-else>
<view class="bnt service" @click="goRoom(order)" v-if="order.merName">联系客服</view>
<view v-else></view>
</template>
<view class="flex">
<template v-if="order._status._type == 0">
<view class="bnt cancelBnt" @click="cancelOrder(order)">取消订单</view>
<view class="bnt bg-color-lightred" @click="goOrderDetails(order)">立即付款</view>
</template>
<template v-if="(order._status._type == 1 || order._status._type == 9) && order.isTickets==0">
<view class="bnt bg-color-lightred" @click="goOrderDetails(order)">查看详情</view>
</template>
<template v-if="order._status._type == 1 && order.isTickets == 1">
<view class="bnt bg-color-lightred" @click="goOrderDetails(order)">立即核销</view>
</template>
<template v-if="order._status._type == 2 && order.isTickets == 0">
<view class="bnt default" v-if="order.isExtendedDelivery==0"
@click="toDelay(order.orderId)">延长收货
</view>
<view class="bnt default" @click="goLogistics(order)">查看物流</view>
<view class="bnt bg-color-lightred" @click="takeOrder(order)">确认收货</view>
</template>
<template v-if="order._status._type == 3">
<view class="bnt bg-color-lightred" @click="goOrderDetails(order)">去评价</view>
</template>
<template v-if="order._status._type === 4">
<view class="bnt bg-color-lightred" @click="goOrderDetails(order)">查看订单</view>
</template>
</view>
</view>
</view>
</view>
<u-modal :show="showExtend" title="确认延长收货时间?" content='每笔订单只能延长一次哦' showCancelButton
@cancel="showExtend=false" @confirm="doneDelay"></u-modal>
<view class="noCart" v-if="orderList.length === 0 && page > 1">
<view class="pictrue">
<image :src="webUrl+'/20210203155245713983.png'"/>
</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
<Payment v-model="pay" :types="payType" @checked="toPay" :balance="userInfo.nowMoney"></Payment>
</view>
</template>
<script>
import {getOrderData, getOrderList, orderDelay} from "@/api/order";
import {cancelOrderHandle, payOrderHandle, takeOrderHandle} from "@/libs/order";
import Loading from "@/components/Loading";
import Payment from "@/components/Payment";
import {mapGetters} from "vuex";
export default {
name: "MyOrder",
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
tabList: [
{name: '全部'},
{name: '待付款'},
{name: '待发货'},
{name: '待收货/待核销'},
{name: '待评价'},
{name: '已完成'}],
offlinePayStatus: 2,
orderData: {},
type: 0,
page: 1,
limit: 20,
loaded: false,
loading: false,
orderList: [],
pay: false,
payType: ["yue", "weixin"],
from: this.$deviceType,
showExtend: false,
delayId: null,
};
},
components: {
Loading,
Payment
},
computed: mapGetters(["userInfo"]),
onShow: function () {
this.type = parseInt(this.$yroute.query.type) || 0;
this.changeType(this.type);
this.getOrderData();
this.getOrderList();
},
onHide: function () {
this.orderList = [];
this.page = 1;
this.limit = 20;
this.loaded = false;
this.loading = false;
},
methods: {
force2Decimal(v) {
return this.$force2Decimal(v);
},
goRoom(order) {
uni.navigateTo({
url: `/pkg_common/views/room?id=${order.merId}&name=${order.merName}`
})
},
goRefund(order) {
uni.navigateTo({
url: `/pkg_orders/views/refund?id=${order.orderId}`
})
},
goLogistics(order) {
this.$yrouter.push({
path: "/pages/order/Logistics/index",
query: {
id: order.orderId
}
});
},
goOrderDetails(order) {
this.$yrouter.push({
path: "/pages/order/OrderDetails/index",
query: {
id: order.orderId
}
});
},
setOfflinePayStatus: function (status) {
let 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) {
let that = this;
uni.showModal({
title: '是否确认收货?',
content: '',
showCancel: true,
cancelText: '取消',
confirmText: '确认',
success: res => {
if (res.confirm) {
takeOrderHandle(order.orderId).finally(() => {
that.reload();
that.getOrderData();
});
} else if (res.cancel) {
}
}
});
},
reload() {
this.changeType(this.type);
},
tabChange(item) {
this.type = item.index;
this.changeType();
},
changeType() {
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);
if (this.orderList.length > 0) {
this.orderList.forEach(item => {
item.showMore = false;
})
}
this.page++;
this.loaded = res.data.length < this.limit;
this.loading = false;
});
},
tapShowMore(order, index) {
order.showMore = !order.showMore;
this.$set(this.orderList, index, order);
},
getStatus(order) {
const type = Number(order._status._type);
let status = "";
switch (type) {
case 0:
status = "待付款";
break;
case 1:
status = "待发货";
break;
case 2:
status = "待收货";
break;
case 3:
status = "待评价";
break;
case 4:
status = "已完成";
break;
case -1:
status = "退款中";
break;
case -2:
status = "已退款";
break;
case -3:
status = "已驳回";
break;
}
return status;
},
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() {
},
toDelay(id) {
this.delayId = id;
this.showExtend = true;
},
doneDelay() {
orderDelay(this.delayId).then(() => {
this.showExtend = false;
this.reload()
});
}
},
onReachBottom() {
!this.loading && this.getOrderList();
}
};
</script>
<style scoped lang="less">
page {
background-color: #fff;
}
/deep/ .u-tabs {
position: fixed;
z-index: 1;
background-color: #fff;
left: 0;
top: 0
}
.list {
.item {
margin: 30rpx 0;
border-radius: 12rpx;
.shop-info {
padding: 20rpx 16rpx;
border-bottom: 2rpx solid #DADADA;
.name {
margin-left: 6rpx;
color: #333;
font-size: 24rpx;
line-height: 36rpx;
font-weight: bold;
}
.address {
margin-left: 4rpx;
color: #FD574B;
font-size: 22rpx;
line-height: 36rpx;
}
}
.title {
border-bottom: none;
}
.item-info {
margin: 0 30rpx;
padding: 22rpx 0 0;
border-top: 1rpx solid #eee;
}
.totalPrice {
border-bottom: none;
}
.bottom {
border-top: 2rpx solid #DADADA;
.bnt {
display: flex;
justify-content: center;
align-items: center;
width: 160rpx;
height: 56rpx;
box-sizing: border-box;
border-radius: 20rpx;
font-size: 24rpx;
}
.service {
border: 2rpx solid #0DC5C5;
color: #0DC5C5;
}
}
}
}
.noCart {
margin-top: 0.17 * 100rpx;
padding-top: 0.1 * 100rpx;
}
.noCart .pictrue {
width: 4 * 100rpx;
height: 3 * 100rpx;
overflow: hidden;
margin: 0.7 * 100rpx auto 0.5 * 100rpx auto;
}
.noCart .pictrue image {
width: 4 * 100rpx;
height: 3 * 100rpx;
}
.statusTag {
font-size: 20rpx;
color: #fff;
padding: 0 20rpx;
background: #0DC5C5;
height: 38rpx;
line-height: 38rpx;
border-radius: 20rpx 0px 0px 20rpx;
}
.group-btn {
position: relative;
.btn-more {
color: #999;
font-size: 28rpx;
}
.group-float {
position: absolute;
width: 196rpx;
box-sizing: border-box;
box-shadow: 0 2px 16px rgba(0, 0, 0, 0.16);
padding: 0 20rpx;
background: #fff;
.btn {
box-sizing: border-box;
padding: 20rpx 0;
color: #333;
font-size: 32rpx;
line-height: 1;
}
.btn-service {
border-bottom: 1rpx solid #F0F0F0;
}
}
}
</style>
+771
View File
@@ -0,0 +1,771 @@
<template>
<view class="order-details" style="padding: 30rpx;">
<!-- 给header上与data上加on为退款订单-->
<view class="header acea-row row-middle" :class="refundOrder ? 'on' : ''"
style="background: #0DC5C5;border-radius: 24rpx;">
<view class="status-img-box">
<image class="status-img" :src="getStatusImg(orderInfo)" mode=""></image>
</view>
<view class="data" :class="refundOrder ? 'on' : ''">
<view class="state" v-if="orderInfo.isTickets===1 && orderInfo._status._type == 2">待核销</view>
<view class="state" v-else>{{ getStatus(orderInfo) }}</view>
<view v-if="getStatus(orderInfo)!=='待付款'">{{ orderInfo._status._msg }}</view>
<view class="pending-payments flex ai-center" v-else>
<text>请在</text>
<u-count-down :time="$global.diffSSS(this.orderInfo.paymentTimeout)"/>
<text>内支付逾期订单将自动取消</text>
</view>
</view>
</view>
<view class="reject-reason" v-if="orderInfo._status._type==-3 && orderInfo.refundRejectReason">驳回原因{{ orderInfo.refundRejectReason }}</view>
<template v-if="!refundOrder">
<view class="code-box flex jc-center ai-center" v-if="orderInfo.isTickets===1 && orderInfo._status._type==2">
<image class="code-img" :src="orderInfo.code"/>
</view>
<template v-else>
<div class="writeOff" v-if="orderInfo.shippingType === 2 && orderInfo.paid === 1"
style="margin-top: 30rpx;border-radius: 24rpx;">
<div class="title">核销信息</div>
<div class="grayBg">
<div class="pictrue">
<img :src="orderInfo.code"/>
</div>
</div>
<div class="gear">
<img :src="webUrl+'/20230526114305172550.jpg'"/>
</div>
<div class="num">{{ orderInfo.verifyCode }}</div>
<div class="rules">
<div class="item">
<div class="rulesTitle acea-row row-middle">
<span class="iconfont icon-shijian"></span>核销时间
</div>
<div class="info">
每日
<span class="time">{{ system_store.dayTime }}</span>
</div>
</div>
<div class="item">
<div class="rulesTitle acea-row row-middle">
<span class="iconfont icon-shuoming1"></span>使用说明
</div>
<div class="info">可将二维码出示给店员扫描或提供数字核销码</div>
</div>
</div>
</div>
<div class="map acea-row row-between-wrapper" v-if="orderInfo.shippingType === 2 && orderInfo.paid === 1">
<div>自提地址信息</div>
<div class="place cart-color acea-row row-center-wrapper" @click="showChang(orderInfo.systemStore)">
<span class="iconfont icon-weizhi"></span>查看位置
</div>
</div>
<view class="address acea-row row-middle" style="margin-top: 30rpx;border-radius: 24rpx;flex-wrap: nowrap;"
v-if="orderInfo.shippingType === 1">
<view class="" style="flex-shrink: 0;margin-right: 20rpx;">
<image style="width: 48rpx;height: 48rpx;" :src="webUrl+'/20230304135530688212.png'" mode=""></image>
</view>
<view class="acea-row row-middle" style="flex-grow: 1;">
<view class="name acea-row row-middle row-between" style="flex-wrap: nowrap;width: 100%;">
<view class="acea-row row-middle">
{{ orderInfo.realName }}
<text class="phone">{{ orderInfo.userPhone }}</text>
</view>
<view class="acea-row row-middle">
<image style="width: 32rpx;height: 32rpx;" :src="webUrl+'/20210808005541949297.png'" mode=""
@click="call(orderInfo.userPhone)"></image>
</view>
</view>
<view>{{ orderInfo.userAddress }}</view>
</view>
</view>
<div class="address" v-else>
<div class="name">
{{ system_store.name }}
<span class="phone">{{ system_store.phone }}</span>
<span class="iconfont icon-tonghua font-color-red" :href="'tel:' + system_store.phone"></span>
</div>
<div>{{ system_store.address }}</div>
</div>
</template>
</template>
<view style="margin-top: 30rpx;border-radius:24rpx;overflow: hidden;">
<OrderGoods :evaluate="status.type || 0" :cartInfo="orderInfo.cartInfo || []" title="商品信息"></OrderGoods>
</view>
<view class="wrapper" style="margin-top: 30rpx;border-radius: 24rpx;">
<view class="item acea-row row-middle"
style="font-size: 40rpx;color: #080F1A;font-weight: bold;flex-wrap: nowrap;">
<image style="width: 32rpx;height: 32rpx;margin-right: 12rpx;" :src="webUrl+'/20210808003431044270.png'"
mode=""></image>
<text style="font-size: 26rpx;color: #080F1A;">订单信息</text>
</view>
<view class="item acea-row row-between">
<view class="flex-0">订单编号</view>
<view class="conter acea-row row-middle row-right">
{{ orderInfo.orderId }}
<image @click="copyClipboard(orderInfo.orderId)" style="width: 28rpx;height: 28rpx;margin-left: 10rpx;"
:src="webUrl+'/20210808003517657208.png'" mode=""></image>
</view>
</view>
<view class="item acea-row row-between">
<view class="flex-0">下单时间</view>
<view class="conter">
<text>{{ orderInfo.createTime }}</text>
</view>
</view>
<view class="item acea-row row-between">
<view class="flex-0">订单类型</view>
<view class="conter">{{ orderTypeName }}</view>
</view>
<view class="item acea-row row-between">
<view class="flex-0">支付状态</view>
<view class="conter">{{ orderInfo.paid ? "已支付" : "未支付" }}</view>
</view>
<view class="item acea-row row-between">
<view class="flex-0">支付方式</view>
<view class="conter">{{ orderInfo._status._payType }}</view>
</view>
<view class="item acea-row row-between" v-if="orderInfo.mark">
<view class="flex-0">买家留言</view>
<view class="conter">{{ orderInfo.mark }}</view>
</view>
</view>
<view v-if="orderInfo.status != 0">
<view class="wrapper" v-if="true">
<view class="item acea-row row-between">
<view class="flex-0">配送方式</view>
<view class="conter">发货</view>
</view>
<view class="item acea-row row-between">
<view class="flex-0">快递公司</view>
<view class="conter">{{ orderInfo.deliveryName || "" }}</view>
</view>
<view class="item acea-row row-between">
<view class="flex-0">快递号</view>
<view class="conter">{{ orderInfo.deliveryId || "" }}</view>
</view>
</view>
<view class="wrapper" v-else>
<view class="item acea-row row-between">
<view class="flex-0">配送方式</view>
<view class="conter">送货</view>
</view>
<view class="item acea-row row-between">
<view class="flex-0">配送人</view>
<view class="conter">{{ orderInfo.deliveryName || "" }}</view>
</view>
<view class="item acea-row row-between">
<view class="flex-0">配送电话</view>
<view class="conter acea-row row-middle row-right">
{{ orderInfo.deliveryId || "" }}
<text class="copy">拨打</text>
</view>
</view>
</view>
</view>
<!-- 退款订单详情 -->
<view class="wrapper" v-if="refundOrder">
<view class="item acea-row row-between">
<view>收货人</view>
<view class="conter">{{ orderInfo.realName }}</view>
</view>
<view class="item acea-row row-between">
<view>联系电话</view>
<view class="conter">{{ orderInfo.userPhone }}</view>
</view>
<view class="item acea-row row-between">
<view>收货地址</view>
<view class="conter">{{ orderInfo.userAddress }}</view>
</view>
</view>
<view class="wrapper" style="margin-top: 30rpx;border-radius: 24rpx;">
<view class="item acea-row row-between" style="flex-wrap: nowrap;">
<view class="acea-row row-middle" style="font-size: 40rpx;color: #080F1A;font-weight: bold;flex-wrap: nowrap;">
<image style="width: 32rpx;height: 32rpx;margin-right: 12rpx;" :src="webUrl+'/20210808003453973795.png'"
mode=""></image>
<text style="font-size: 26rpx;color: #080F1A;">支付金额</text>
</view>
<view class="conter" style="width: auto !important;">{{ force2Decimal(orderInfo.totalPrice) }}</view>
</view>
<view class="item acea-row row-between" v-if="orderInfo.couponPrice > 0">
<view>优惠券抵扣</view>
<view class="conter">-{{ force2Decimal(orderInfo.couponPrice) }}</view>
</view>
<view class="item acea-row row-between" v-if="orderInfo.useIntegral > 0">
<view>积分抵扣</view>
<view class="conter">-{{ force2Decimal(orderInfo.deductionPrice) }}</view>
</view>
<view class="item acea-row row-between" v-if="orderInfo.payPostage > 0">
<view>运费</view>
<view class="conter">{{ force2Decimal(orderInfo.payPostage) }}</view>
</view>
<view class="actualPay acea-row row-right row-middle">
<text style="font-size: 24rpx;">实付款</text>
<text class="money font-color-red">{{ force2Decimal(orderInfo.payPrice) }}</text>
</view>
</view>
<view style="height:100rpx;" v-if="!refundOrder && offlineStatus"></view>
<view class="footer acea-row row-right row-middle" v-if="!refundOrder && offlineStatus">
<template v-if="status.type == 0">
<view class="bnt cancel" @click="cancelOrder">取消订单</view>
<view class="bnt bg-color-red" @click="subscribePay">立即付款</view>
</template>
<template v-if="status.type == 1">
<view class="bnt cancel" @click="goGoodsReturn(orderInfo)">申请退款</view>
</template>
<template v-if="status.type == 2">
<view class="bnt default"
@click="$yrouter.push({ path: '/pages/order/Logistics/index' ,query:{id:orderInfo.orderId }})"
v-if="orderInfo.isTickets!==1">查看物流
</view>
<view class="bnt bg-color-red" @click="takeOrder">确认收货</view>
</template>
<template v-if="status.type == 3">
<view class="bnt default" @click="
$yrouter.push({ path: '/pages/order/Logistics/index' ,query:{id:orderInfo.orderId }})
" v-if="orderInfo.isTickets!==1">查看物流
</view>
</template>
<template v-if="status.type == 4">
<view class="bnt cancel" @click="delOrder">删除订单</view>
<view class="bnt default" @click="
$yrouter.push({ path: '/pages/order/Logistics/index' ,query:{id:orderInfo.orderId }})
" v-if="orderInfo.isTickets!==1">查看物流
</view>
</template>
<template v-if="status.type == 6">
<view class="bnt bg-color-red" @click="goGroupRule(orderInfo)">查看拼团</view>
</template>
</view>
<Payment v-model="pay" :types="payType" @checked="toPay" :balance="userInfo.nowMoney"></Payment>
<view 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>
</view>
<passkeyborad :money="orderInfo.payPrice" showMoney :show="isShowPayPwdPop" ref='payPwdPop' @close="pwdPopClose"
@finish="pwdPopFinish"></passkeyborad>
</view>
</template>
<script>
import passkeyborad from '@/components/yzc-paykeyboard/yzc-paykeyboard'
import OrderGoods from "@/components/OrderGoods";
import {orderDetail} from "@/api/order";
import Payment from "@/components/Payment";
import DataFormat from "@/components/DataFormat";
import {copyClipboard} from "@/utils";
import {mapGetters} from "vuex";
import {cancelOrderHandle, delOrderHandle, payOrderHandle, takeOrderHandle, yuePayOrderHandle} from "@/libs/order";
const STATUS = [
"待付款",
"待发货",
"待收货",
"待评价",
"已完成",
"",
"",
"",
"",
"待付款"
];
const NAME = "OrderDetails";
export default {
name: NAME,
components: {
OrderGoods,
Payment,
DataFormat,
passkeyborad
},
props: {},
data: function () {
return {
isShowPayPwdPop: false,
offlinePayStatus: 2,
orderTypeName: "普通订单",
orderTypeNameStatus: true,
offlineStatus: true,
id: "",
orderInfo: {
_status: {}
},
status: {},
pay: false,
payType: ["yue", "weixin"],
from: this.$deviceType,
system_store: {},
mapKay: "",
mapShow: false,
payPassword: null,
webUrl: this.$VUE_APP_RESOURCES_URL
};
},
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;
},
methods: {
copyClipboard,
force2Decimal(v) {
return this.$force2Decimal(v);
},
getStatus(order) {
const type = Number(order._status._type);
let status = "";
switch (type) {
case 0:
status = "待付款";
break;
case 1:
status = "待发货";
break;
case 2:
status = "待收货";
break;
case 3:
status = "待评价";
break;
case 4:
status = "已完成";
break;
case -1:
status = "退款中";
break;
case -2:
status = "已退款";
break;
case -3:
status = "已驳回";
break;
}
return status;
},
getStatusImg(order) {
const type = parseInt(order._status._type);
let imgUrl = "";
switch (type) {
case 0: //待付款
case 9:
imgUrl = this.webUrl + '/20230526114342425681.png';
break;
case 1: //待发货
imgUrl = this.webUrl + '/20230526114347797204.png';
break;
case 2: //待收货
imgUrl = this.webUrl + '/20230526114355462982.png';
break;
case 3: //待评价
imgUrl = this.webUrl + '/20230526114414134581.png';
break;
case 4: //已完成
imgUrl = this.webUrl + '/20230526114421118668.png';
break;
case -1: //退款中
imgUrl = this.webUrl + '/20230526114324286938.png';
break;
case -2: //已退款
imgUrl = this.webUrl + '/20230526114329894562.png';
break;
case -3: //已驳回
imgUrl = this.webUrl + '/20230526114336281750.png';
break;
}
return imgUrl;
},
subscribePay() {
uni.requestSubscribeMessage({
tmplIds: ['7O3wKw7_D4t7yfSOlvecKuOQP8QEPY88uBx2FJg43HE', 'TSmTnGibZ8IxWCiRWOvLxha6-0u7tE-V1-WbDCiPkKU', '9Q6xLHe6HyjkU5Zn5k_2zxYPf2y4MxVyUbOSW8pcZRU'],
complete: () => this.pay = true
})
},
goGoodsReturn(orderInfo) {
this.$yrouter.push({
path: "/pages/order/GoodsReturn/index",
query: {
id: orderInfo.orderId
}
});
},
goGroupRule(orderInfo) {
this.$yrouter.push({
path: "/pages/activity/GroupRule/index",
query: {
id: orderInfo.pinkId
}
});
},
showChang: function (data) {
// 这里判断是不是微信小程序
this.$yrouter.push({
path: "/pages/map/index",
query: data
});
},
async toYuePay(payPwd) {
var that = this;
//网络请求
await yuePayOrderHandle(this.orderInfo.orderId, "yue", that.from, payPwd);
that.getDetail();
this.payPassword = "";
},
pwdPopClose() {
this.isShowPayPwdPop = false;
},
pwdPopFinish(payPwd) {
this.payPassword = payPwd;
this.toYuePay(payPwd);
this.isShowPayPwdPop = false;
},
call: function (phone) {
uni.makePhoneCall({
// 手机号
phoneNumber: phone,
// 成功回调
success: (res) => {
console.log('调用成功!')
},
// 失败回调
fail: (res) => {
console.log('调用失败!')
}
});
},
goBack() {
if (this.name === "MyOrder") {
this.$yrouter.back();
return;
} else {
console.log(this);
this.$yrouter.replace({
path: "/pages/order/MyOrder/index"
});
return;
}
},
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) {
uni.showToast({
title: "订单不存在",
icon: "none",
duration: 2000
});
return;
}
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.systemStore || {};
this.mapKey = res.data.mapKay;
this.setOfflinePayStatus(this.orderInfo.offlinePayStatus);
})
.catch(err => {
uni.showToast({
title: err.response.data.msg,
icon: "none",
duration: 2000
});
});
},
async toPay(type) {
var that = this;
console.log(type, "支付方式");
//余额支付需要输入支付密码
if (type == "yue") {
this.isShowPayPwdPop = true;
return;
} else {
await payOrderHandle(this.orderInfo.orderId, type, that.from);
that.getDetail();
}
}
}
};
</script>
<style scoped lang="less">
.geoPage {
position: fixed;
width: 100%;
height: 100%;
top: 0;
z-index: 10000;
}
.order-details .writeOff {
background-color: #fff;
margin-top: 0.13 * 100rpx;
padding-bottom: 0.3 * 100rpx;
}
.order-details .writeOff .title {
font-size: 0.3 * 100rpx;
color: #282828;
height: 0.87 * 100rpx;
border-bottom: 1px solid #f0f0f0;
padding: 0 0.3 * 100rpx;
line-height: 0.87 * 100rpx;
}
.order-details .writeOff .grayBg {
background-color: #f2f5f7;
width: 5.9 * 100rpx;
height: 3.84 * 100rpx;
border-radius: 0.2 * 100rpx 0.2 * 100rpx 0 0;
margin: 0.5 * 100rpx auto 0 auto;
padding-top: 0.55 * 100rpx;
}
.order-details .writeOff .grayBg .pictrue {
width: 2.9 * 100rpx;
height: 2.9 * 100rpx;
margin: 0 auto;
}
.order-details .writeOff .grayBg .pictrue img {
width: 100%;
height: 100%;
display: block;
}
.order-details .writeOff .gear {
width: 5.9 * 100rpx;
height: 0.3 * 100rpx;
margin: 0 auto;
}
.order-details .writeOff .gear img {
width: 100%;
height: 100%;
display: block;
}
.order-details .writeOff .num {
background-color: #f0c34c;
width: 5.9 * 100rpx;
height: 0.84 * 100rpx;
color: #282828;
font-size: 0.48 * 100rpx;
margin: 0 auto;
border-radius: 0 0 0.2 * 100rpx 0.2 * 100rpx;
text-align: center;
padding-top: 0.04 * 100rpx;
}
.order-details .writeOff .rules {
margin: 0.46 * 100rpx 0.3 * 100rpx 0 0.3 * 100rpx;
border-top: 0.01 * 100rpx solid #f0f0f0;
padding-top: 0.1 * 100rpx;
}
.order-details .writeOff .rules .item {
margin-top: 0.15 * 100rpx;
}
.order-details .writeOff .rules .item .rulesTitle {
font-size: 0.28 * 100rpx;
color: #282828;
}
.order-details .writeOff .rules .item .rulesTitle .iconfont {
font-size: 0.3 * 100rpx;
color: #333;
margin-right: 0.08 * 100rpx;
margin-top: 0.05 * 100rpx;
}
.order-details .writeOff .rules .item .info {
font-size: 0.28 * 100rpx;
color: #999;
margin-top: 0.05 * 100rpx;
}
.order-details .writeOff .rules .item .info .time {
margin-left: 0.2 * 100rpx;
}
.order-details .map {
height: 0.86 * 100rpx;
font-size: 0.3 * 100rpx;
color: #282828;
line-height: 0.86 * 100rpx;
border-bottom: 0.01 * 100rpx solid #f0f0f0;
margin-top: 0.13 * 100rpx;
background-color: #fff;
padding: 0 0.3 * 100rpx;
}
.order-details .map .place {
font-size: 0.26 * 100rpx;
width: 1.76 * 100rpx;
height: 0.5 * 100rpx;
border-radius: 0.25 * 100rpx;
line-height: 0.5 * 100rpx;
text-align: center;
}
.order-details .map .place .iconfont {
font-size: 0.27 * 100rpx;
height: 0.27 * 100rpx;
line-height: 0.27 * 100rpx;
margin: 0.02 * 100rpx 0.03 * 100rpx 0 0;
}
.order-details .address .name .iconfont {
font-size: 0.34 * 100rpx;
margin-left: 0.1 * 100rpx;
}
.status-img-box {
width: 86rpx;
height: 86rpx;
background: rgba(255, 255, 255, 1);
border-radius: 50%;
position: relative;
}
.status-img {
width: 100%;
height: 100%;
}
.wrapper .item {
flex-wrap: nowrap;
.flex-0 {
flex-shrink: 0;
}
}
.code-box {
margin-top: 30rpx;
padding: 30rpx;
background: #fff;
.code-img {
width: 240rpx;
height: 240rpx;
}
}
/deep/ .pending-payments {
font-size: 26rpx;
.u-count-down__text {
color: #FF5C5C;
font-size: 26rpx;
line-height: 1;
}
}
.reject-reason {
margin-top: 20rpx;
padding: 20rpx 32rpx;
border-radius: 24rpx;
background: #fff;
color: #FE5261;
font-size: 26rpx;
}
</style>
+925
View File
@@ -0,0 +1,925 @@
<template>
<view class="order-submission" style="padding: 30rpx;">
<view class="allAddress" style="background-color: #f6f6f6;">
<!-- <view class="nav acea-row">
<view
class="item font-color-red"
:class="shipping_type === 0 ? 'on' : 'on2'"
@click="addressType(0)"
v-if="systemStore"
></view>
<view
class="item font-color-red"
:class="shipping_type === 1 ? 'on' : 'on2'"
@click="addressType(1)"
v-if="storeSelfMention"
></view>
</view> -->
<!-- <view class="acea-row" style="padding-left: 28rpx;">
<view v-if="systemStore" class="item" style="position: relative;" @click="addressType(0)">
<text :class="shipping_type === 0 ? 'on' :''" class="goods-detail-title">送货上门</text>
<text v-if="shipping_type === 0" class="pink-dot"></text>
</view>
<view v-if="storeSelfMention" class="item" style="position: relative;margin-left: 40rpx;" @click="addressType(1)">
<text :class="shipping_type === 1 ? 'on' :''" class="goods-detail-title">到店自取</text>
<text v-if="shipping_type === 1" class="pink-dot"></text>
</view>
</view> -->
<view
class="address acea-row row-middle"
style="flex-wrap: nowrap;margin: 0 0 30rpx 0;border-radius: 16rpx;"
v-if="shipping_type === 0"
@click="addressTap"
>
<image style="flex-shrink: 0;width: 48rpx;height: 48rpx;margin-right: 20rpx;"
:src="webUrl+'/20230304135530688212.png'" mode=""></image>
<view class="acea-row row-between-wrapper" style="flex-wrap: nowrap;flex-grow: 1;">
<view class="addressCon" v-if="addressInfo.realName">
<view class="name">
{{ addressInfo.realName }}
<text class="phone">{{ addressInfo.phone }}</text>
</view>
<view>
<!-- <text class="default font-color-lightred" v-if="addressInfo.isDefault">[默认]</text> -->
{{ addressInfo.province }}{{ addressInfo.city }}{{ addressInfo.district }}{{ addressInfo.detail }}
</view>
</view>
<view class="addressCon" v-else>
<view class="setaddress">设置收货地址</view>
</view>
<view class="iconfont icon-jiantou" style="flex-shrink: 0;"></view>
</view>
</view>
<div style="flex-wrap: nowrap;" class="address acea-row row-middle" v-else @click="showStoreList">
<image style="flex-shrink: 0;width: 48rpx;height: 48rpx;margin-right: 20rpx;"
:src="webUrl+'/20230304135530688212.png'" mode=""></image>
<view class="acea-row row-between-wrapper" style="flex-wrap: nowrap;flex-grow: 1;">
<div class="addressCon">
<div class="name">
{{ isNullOrEmpty(storeItems) ? systemStore.name : storeItems.name }}
<span
class="phone"
>{{ isNullOrEmpty(storeItems) ? systemStore.phone : storeItems.phone }}</span>
</div>
<div>{{ isNullOrEmpty(storeItems) ? systemStore.address : storeItems.address }}</div>
</div>
<div class="iconfont icon-jiantou"></div>
</view>
</div>
</view>
<OrderGoods :evaluate="0" :cartInfo="orderGroupInfo.cartInfo" title="商品列表"></OrderGoods>
<view class="wrapper" style="margin: 30rpx 0;border-radius: 16rpx;">
<!-- 优惠券开始 -->
<!-- <view class="item acea-row row-between-wrapper" @click="couponTap" v-if="deduction === false">
<view>优惠券</view>
<view class="discount">
{{ usableCoupon.couponTitle || "请选择" }}
<text class="iconfont icon-jiantou"></text>
</view>
</view> -->
<!-- 优惠券结束 -->
<!-- 积分抵扣开始 -->
<!-- <view
class="item acea-row row-between-wrapper"
v-if="deduction === false && enableIntegral === true"
>
<view>积分抵扣</view>
<view class="discount">
<view class="select-btn">
<view class="checkbox-wrapper">
<checkbox-group @change="changeUseIntegral">
<label class="well-check">
<text class="integral">
当前积分
<text class="num font-color-red">{{ userInfo.integral || 0 }}</text>
</text>
<checkbox value="true" :checked="useIntegral ? true : false"></checkbox>
</label>
</checkbox-group>
</view>
</view>
</view>
</view> -->
<!-- 积分抵扣结束 -->
<view class="item acea-row row-between-wrapper" style="flex-wrap: nowrap;" v-if="shipping_type === 0">
<view class="acea-row row-middle" style="flex-wrap: nowrap;">
<image style="width: 32rpx;height: 32rpx;margin-right: 12rpx;" :src="webUrl+'/20210807230820761721.png'"
mode=""></image>
<text class="">快递费用</text>
</view>
<!-- <view class="discount">
{{
orderGroupInfo.priceGroup.storePostage > 0
? force2Decimal(orderGroupInfo.priceGroup.storePostage)
: (orderPrice.payPostage>0?force2Decimal(orderPrice.payPostage):"免运费")
}}
</view> -->
<view class="discount" style="width: auto !important;">
{{ orderPrice.payPostage > 0 ? force2Decimal(orderPrice.payPostage) : "免运费" }}
</view>
</view>
<view v-else>
<view class="item acea-row row-between-wrapper">
<view>联系人</view>
<view class="discount">
<input type="text" placeholder="请填写您的联系姓名" v-model="contacts"/>
</view>
</view>
<view class="item acea-row row-between-wrapper">
<view>联系电话</view>
<view class="discount">
<input type="text" placeholder="请填写您的联系电话" v-model="contactsTel"/>
</view>
</view>
</view>
<view class="item">
<view class="acea-row row-middle">
<image style="width: 32rpx;height: 32rpx;margin-right: 12rpx;" :src="webUrl+'/20210807230836494421.png'"
mode=""></image>
<text class="">备注信息150字以内</text>
</view>
<textarea v-model="mark"></textarea>
</view>
</view>
<view class="wrapper" style="margin: 30rpx 0;border-radius: 16rpx;">
<view class="item">
<!-- <view>支付方式</view> -->
<view class="acea-row row-left row-middle">
<view class="acea-row row-middle" style="position: relative;">
<image style="width: 32rpx;height: 32rpx;margin-right: 12rpx;" :src="webUrl+'/20210807230846995104.png'"
mode=""></image>
<text class="pay-method-title">支付方式</text>
<!-- <text class="pink-dot"></text> -->
</view>
</view>
<view class="list">
<view
class="payItem acea-row row-middle"
:class="active === 'weixin' ? 'on' : ''"
@click="payItem('weixin')"
v-show="isWeixin"
style="flex-wrap: nowrap;"
>
<view class="name acea-row">
<view class="iconfont icon-weixin2" :class="active === 'weixin' ? 'bounceIn' : ''"></view>
微信支付
</view>
<view class="tip">微信快捷支付</view>
<label class="radio">
<radio style="transform: scale(0.7);" value="" :checked="active === 'weixin'" color="#FF0000"/>
<text></text>
</label>
</view>
<view
class="payItem acea-row row-middle"
:class="active === 'weixin' ? 'on' : ''"
@click="payItem('weixin')"
v-show="!isWeixin"
style="flex-wrap: nowrap;"
>
<view class="name acea-row ">
<view class="iconfont icon-weixin2" :class="active === 'weixin' ? 'bounceIn' : ''"></view>
微信支付
</view>
<view class="tip"></view>
<label class="radio">
<radio style="transform: scale(0.7);" value="" :checked="active === 'weixin'" color="#FF0000"/>
<text></text>
</label>
</view>
<view
class="payItem acea-row row-middle"
:class="active === 'yue' ? 'on' : ''"
@click="payItem('yue')"
style="flex-wrap: nowrap;"
>
<view class="name acea-row ">
<view style="background-color: #007AFF;" class="iconfont icon-icon-test"
:class="active === 'yue' ? 'bounceIn' : ''"></view>
余额支付
</view>
<view class="tip">可用余额{{ userInfo.nowMoney ? force2Decimal(userInfo.nowMoney) : 0.00 }}</view>
<label class="radio">
<radio style="transform: scale(0.7);" value="" :checked="active === 'yue'" color="#FF0000"/>
<text></text>
</label>
</view>
</view>
</view>
</view>
<view class="moneyList" style="margin-bottom:30rpx;border-radius: 16rpx;">
<view class="item acea-row row-between-wrapper" v-if="orderPrice.totalPrice !== undefined">
<view>商品总价</view>
<view class="money">{{ force2Decimal(orderPrice.totalPrice) }}</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="orderPrice.payPostage > 0">
<view>运费</view>
<view class="money">{{ force2Decimal(orderPrice.payPostage) }}</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="orderPrice.couponPrice > 0">
<view>优惠券抵扣</view>
<view class="money">-{{ force2Decimal(orderPrice.couponPrice) }}</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="orderPrice.deductionPrice > 0">
<view>积分抵扣</view>
<view class="money">-{{ force2Decimal(orderPrice.deductionPrice) }}</view>
</view>
</view>
<view style="height:80rpx"></view>
<view class="footer acea-row row-between-wrapper" style="height: 80rpx;">
<view style="margin-left: 30rpx;">
<text style="color: #000000;font-size: 24rpx;font-weight: bold;">合计:</text>
<text class="" style="color: #FF564A;font-size: 28rpx;font-weight: bold;">{{
force2Decimal(orderPrice.payPrice)
}}
</text>
</view>
<view class="settlement acea-row row-middle row-center" @click="subscribePay">立即结算</view>
</view>
<CouponListWindow
v-on:couponchange="changecoupon($event)"
v-model="showCoupon"
:price="orderPrice.totalPrice"
:checked="usableCoupon.id"
@checked="changeCoupon"
:cartid="cartid"
></CouponListWindow>
<AddressWindow
@checked="changeAddress"
@redirect="addressRedirect"
v-model="showAddress"
:checked="addressInfo.id"
ref="mychild"
></AddressWindow>
<!-- <uni-popup ref="popup" type="bottom">
<blPaymentPasswordInput hideTopBorder ref="secrity" @input="onInput" @confirm="onConfirm">
<block slot='header' style='width: 100%;'>
<view style="font-size: 36rpx;color: #8B8F99;margin: 10rpx 0;">请输入支付密码</view>
</block>
</blPaymentPasswordInput>
</uni-popup> -->
<passkeyborad :money="orderPrice.payPrice" showMoney :show="isShowPayPwdPop" ref='payPwdPop' @close="pwdPopClose"
@finish="pwdPopFinish"></passkeyborad>
</view>
</template>
<script>
import passkeyborad from '@/components/yzc-paykeyboard/yzc-paykeyboard'
import OrderGoods from "@/components/OrderGoods";
import CouponListWindow from "@/components/CouponListWindow";
import AddressWindow from "@/components/AddressWindow";
import {createOrder, postOrderComputed, postOrderConfirm} from "@/api/order";
import {mapGetters} from "vuex";
import {weappPay} from "@/libs/wechat";
import {isNullOrEmpty, isWeixin} from "@/utils";
import blPaymentPasswordInput from '@/components/blPaymentPasswordInput.vue';
import uniPopup from '@/components/uni-popup/uni-popup.vue';
const NAME = "OrderSubmission",
_isWeixin = isWeixin();
export default {
name: NAME,
components: {
OrderGoods,
CouponListWindow,
AddressWindow,
blPaymentPasswordInput,
uniPopup,
passkeyborad
},
props: {},
data: function () {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
isShowPayPwdPop: false,
offlinePayStatus: 2,
from: this.$deviceType,
deduction: true,
enableIntegral: true,
enableIntegralNum: 0,
isWeixin: _isWeixin,
pinkId: 0,
// active: _isWeixin ? "weixin" : "yue",
active: "weixin",
showCoupon: false,
showAddress: false,
addressInfo: {},
couponId: 0,
orderGroupInfo: {
priceGroup: {}
},
usableCoupon: {},
addressLoaded: false,
useIntegral: false,
orderPrice: {
payPrice: "计算中"
},
mark: "",
systemStore: {},
shipping_type: 0,
contacts: "",
contactsTel: "",
storeSelfMention: 0,
cartid: "",
payPassword: null
};
},
computed: mapGetters(["userInfo", "storeItems"]),
watch: {
useIntegral() {
this.computedPrice();
},
// $yroute(n) {
// if (n.name === NAME){
// this.getCartInfo();
// // this.$store.dispatch("getUser", true);
// }
// },
shipping_type() {
this.computedPrice();
}
},
// mounted: function() {
// let that = this;
// // this.$store.dispatch("getUser", true);
// that.getCartInfo();
// console.log(that.$yroute);
// if (that.$yroute.query.pinkid !== undefined) {
// that.pinkId = that.$yroute.query.pinkid;
// }
// if (that.$yroute.query.id !== undefined) {
// that.cartid = that.$yroute.query.id;
// console.log(that.cartid)
// }
// },
onLoad: function () {
//获取用户信息
// this.$store.dispatch("getUser", true);
let that = this;
uni.$on('chooseAddress', (res) => {
console.log('监听到选择收货地址:' + JSON.stringify(res));
that.addressInfo = res;
//地址切换也要重新计算一下
that.computedPrice();
})
that.getCartInfo();
console.log(that.$yroute);
if (that.$yroute.query.pinkid !== undefined) {
that.pinkId = that.$yroute.query.pinkid;
}
if (that.$yroute.query.id !== undefined) {
that.cartid = that.$yroute.query.id;
console.log(that.cartid)
}
},
onUnload: function () {
console.log('关闭监听选择收货地址');
uni.$off('chooseAddress');
},
onShow: function () {
//获取用户信息
this.$store.dispatch("getUser", true);
},
methods: {
isNullOrEmpty,
showStoreList() {
this.$store.commit("get_to", "orders");
this.$yrouter.push({
path: "/pages/shop/StoreList/index"
});
},
force2Decimal(value) {
return this.$force2Decimal(value);
},
addressType: function (index) {
if (index && !this.systemStore.id) {
uni.showToast({
title: "暂无门店信息,您无法选择到店自提!",
icon: "none",
duration: 2000
});
return;
}
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/index",
query: {
id: data.result.orderId
}
});
} else {
this.orderPrice = data.result;
}
});
},
getCartInfo() {
var that = this;
const cartIds = this.$yroute.query.id;
if (!cartIds) {
uni.showToast({
title: "参数有误",
icon: "none",
duration: 2000
});
return this.$yrouter.back();
}
postOrderConfirm(cartIds)
.then(res => {
that.offlinePayStatus = res.data.offline_pay_status;
that.orderGroupInfo = res.data;
that.deduction = res.data.deduction;
that.usableCoupon = res.data.usableCoupon || {};
that.addressInfo = res.data.addressInfo || {};
that.systemStore = res.data.systemStore || {};
that.storeSelfMention = res.data.storeSelfMention;
that.computedPrice();
})
.catch(err => {
uni.showToast({
title: err.msg,
icon: "none",
duration: 2000
});
});
},
addressTap: function () {
// this.showAddress = true;
// if (!this.addressLoaded) {
// this.addressLoaded = true;
// this.$refs.mychild.getAddressList();
// }
//改用跳转页面方式
this.$yrouter.push({
path: "/pages/user/address/AddressManagement/index",
query: {
choosMode: 1
}
});
},
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;
//地址切换也要重新计算一下
this.computedPrice();
},
pwdPopClose() {
this.isShowPayPwdPop = false;
},
pwdPopFinish(payPwd) {
this.payPassword = payPwd;
this.createOrder(true);
},
//支付密码输入监听
onInput(e) {
},
// 支付密码输入确认
onConfirm(e) {
let password = e.value;
// if(password)
console.log('password:' + password);
this.payPassword = password;
this.$refs.popup.close();//关闭支付密码弹窗
this.$refs.secrity.clear();//清空支付密码
this.createOrder(true);
},
subscribePay() {
uni.requestSubscribeMessage({
tmplIds: ['7O3wKw7_D4t7yfSOlvecKuOQP8QEPY88uBx2FJg43HE', 'TSmTnGibZ8IxWCiRWOvLxha6-0u7tE-V1-WbDCiPkKU', '9Q6xLHe6HyjkU5Zn5k_2zxYPf2y4MxVyUbOSW8pcZRU'],
complete: () => this.createOrder(false)
})
},
createOrder(isyue) {
let shipping_type = this.shipping_type;
if (!this.active) {
uni.showToast({
title: "请选择支付方式",
icon: "none",
duration: 2000
});
return;
}
if (!this.addressInfo.id && !this.shipping_type) {
uni.showToast({
title: "请选择收货地址",
icon: "none",
duration: 2000
});
return;
}
if (this.shipping_type) {
if (
(this.contacts === "" || this.contactsTel === "") &&
this.shipping_type
) {
uni.showToast({
title: "请填写联系人或联系人电话",
icon: "none",
duration: 2000
});
return;
}
if (!/^1(3|4|5|7|8|9|6)\d{9}$/.test(this.contactsTel)) {
uni.showToast({
title: "请填写正确的手机号",
icon: "none",
duration: 2000
});
return;
}
if (!/^[\u4e00-\u9fa5\w]{2,16}$/.test(this.contacts)) {
uni.showToast({
title: "请填写您的真实姓名",
icon: "none",
duration: 2000
});
return;
}
}
//判断如果是余额支付,先要输入支付密码
if (this.active == 'yue' && !isyue) {
//先判断用户是否绑定过手机
if (this.userInfo.phone) {
//再判断用户是否设置过支付密码
if (this.userInfo.hasPwdPay) {
//显示输入支付密码
this.isShowPayPwdPop = true;
} else {
//设置支付密码
this.$yrouter.push("/pkg_user/views/payPassword?isSetMode=true");
}
} else {
//跳转到绑定手机
this.$yrouter.push("/pkg_user/views/bindPhone");
}
return;
}
uni.showLoading({
title: "生成订单中"
});
let from = {};
if (this.$deviceType == "app") {
from.from = "app";
}
console.log(this.storeItems, this.systemStore);
var params = {
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,
storeId: this.storeItems ? this.storeItems.id : this.systemStore.id,
...from
}
//余额支付的支付密码
if (this.active == 'yue') {
params.passwordPay = this.payPassword;
}
var that = this;
createOrder(this.orderGroupInfo.orderKey, params)
.then(res => {
uni.hideLoading();
const data = res.data;
switch (data.status) {
case "ORDER_EXIST":
case "EXTEND_ORDER":
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
this.$yrouter.replace({
path: "/pages/order/OrderDetails/index",
query: {
id: data.result.orderId
}
});
break;
case "PAY_DEFICIENCY":
break;
case "PAY_ERROR":
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
this.$yrouter.replace({
path: "/pages/order/OrderDetails/index",
query: {
id: data.result.orderId
}
});
break;
case "SUCCESS":
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
this.$yrouter.replace({
path: "/pages/order/OrderDetails/index",
query: {
id: data.result.orderId
}
});
break;
case "WECHAT_H5_PAY":
// H5支付
this.$yrouter.replace({
path: "/pages/order/OrderDetails/index",
query: {
id: data.result.orderId
}
});
setTimeout(() => {
// location.href = data.result.jsConfig.mweb_url;
}, 100);
break;
case "WECHAT_PAY":
// 小程序支付
weappPay(data.result.jsConfig).finally(() => {
this.$yrouter.replace({
path: "/pages/order/OrderDetails/index",
query: {
id: data.result.orderId
}
});
});
break;
case "WECHAT_APP_PAY":
// APP支付
weappPay(data.result.jsConfig).finally(() => {
this.$yrouter.replace({
path: "/pages/order/OrderDetails/index",
query: {
id: data.result.orderId
}
});
});
break;
// 下面为原先微信支付方式,
// pay(data.result.jsConfig).finally(() => {
// this.$yrouter.replace({
// path: "/pages/order/OrderDetails/index" ,query: { id: data.result.orderId}
// });
// });
}
})
.catch(err => {
uni.hideLoading();
uni.showToast({
title:
err.msg ||
err.response.data.msg ||
err.response.data.message ||
"创建订单失败",
icon: "none",
duration: 2000
});
}).finally(function () {
that.isShowPayPwdPop = false;
that.$refs.payPwdPop.clear();//清空支付密码
that.$refs.payPwdPop.close();//关闭支付密码弹窗
});
}
}
};
</script>
<style scoped lang="less">
.pink-dot {
width: 24rpx;
height: 24rpx;
background: rgba(255, 86, 74, 0.4);
border-radius: 50%;
position: absolute;
z-index: 0;
bottom: 0;
right: -12rpx;
}
.pay-method-title {
font-size: 26rpx;
color: #080F1A;
font-weight: bold;
}
.goods-detail-title {
font-size: 36rpx;
color: #C2C5CC;
font-weight: bold;
}
.goods-detail-title.on {
color: #080F1A;
font-weight: normal;
}
.order-submission .footer {
background: #fff;
left: 0;
right: 0;
bottom: 0;
border-top: 1px solid #f6f6f6;
padding: 0 !important;
}
.order-submission .footer .settlement {
background-color: #FF564A;
color: #fff;
width: 198rpx;
height: 100%;
border-radius: 0 !important;
text-align: center;
}
.order-submission .wrapper .item .list .payItem {
border: none !important;
}
.order-submission .wrapper .item .list .payItem.on {
border-color: #eee !important;
color: inherit !important;
}
.order-submission .wrapper .shipping select {
color: #999;
padding-right: 0.15 * 100rpx;
}
.order-submission .wrapper .shipping .iconfont {
font-size: 0.3 * 100rpx;
color: #515151;
}
.order-submission .allAddress {
width: 100%;
// background-image: linear-gradient(to bottom, #00c17b 0%, #00c17b 100%);
// background-image: -webkit-linear-gradient(
// to bottom,
// #00c17b 0%,
// #00c17b 100%
// );
// background-image: -moz-linear-gradient(to bottom, #00c17b 0%, #00c17b 100%);
// padding-top: 1 * 100rpx;
// padding-top: 40rpx;
}
.order-submission .allAddress .nav {
margin: 0 auto;
padding: 0 30rpx;
width: 100%;
box-sizing: border-box;
}
.order-submission .address .addressCon {
width: auto !important;
}
.order-submission .allAddress .nav .item {
flex: 1;
position: relative;
}
.order-submission .allAddress .nav .item.on {
position: relative;
}
.order-submission .allAddress .nav .item.on:before {
position: absolute;
bottom: 0;
content: "快递配送";
font-size: 0.28 * 100rpx;
display: block;
height: 0;
left: 0;
right: 0;
border-width: 0.4 * 100rpx;
border-style: solid;
border-color: #fff;
z-index: 9;
text-align: center;
line-height: 0.14 * 100rpx;
}
.order-submission .allAddress .nav .item:nth-of-type(2).on:before {
content: "到店自提";
border-width: 0.4 * 100rpx;
}
.order-submission .allAddress .nav .item.on2 {
position: relative;
}
.order-submission .allAddress .nav .item.on2:before {
position: absolute;
bottom: 0;
content: "到店自提";
font-size: 0.28 * 100rpx;
display: block;
height: 0;
left: 0;
right: 0;
border-width: 0.4 * 100rpx;
border-style: solid;
border-color: #d5e6e6;
text-align: center;
line-height: 0.14 * 100rpx;
}
.order-submission .allAddress .nav .item:nth-of-type(1).on2:before {
content: "快递配送";
border-width: 0.4 * 100rpx;
}
.order-submission .allAddress .address {
width: 6.91 * 100rpx;
height: 1.5 * 100rpx;
margin: 0 auto;
box-sizing: border-box;
}
.order-submission .allAddress .line {
width: 7.1 * 100rpx;
margin: 0 auto;
}
.order-submission .wrapper .item .discount input::placeholder {
color: #ccc;
}
</style>
+34
View File
@@ -0,0 +1,34 @@
<template>
<view class="payment-status">
<!--失败时 用icon-iconfontguanbi fail替换icon-duihao2 bg-color-red-->
<view class="iconfont icon-duihao2 bg-color-red"></view>
<!-- 失败时订单支付失败 -->
<view class="status">订单支付成功</view>
<view class="wrapper">
<view class="item acea-row row-between-wrapper">
<view>订单编号</view>
<view class="itemCom">wx3265361456134568</view>
</view>
<view class="item acea-row row-between-wrapper">
<view>下单时间</view>
<view class="itemCom">2019-01-09 18:05</view>
</view>
<view class="item acea-row row-between-wrapper">
<view>支付方式</view>
<view class="itemCom">微信支付</view>
</view>
<view class="item acea-row row-between-wrapper">
<view>支付金额</view>
<view class="itemCom">2222.00</view>
</view>
<!--失败时加上这个 -->
<!--<view class='item acea-row row-between-wrapper'>-->
<!--<view>失败原因</view>-->
<!--<view class='itemCom'>账户余额不足</view>-->
<!--</view>-->
</view>
<!--失败时 重新购买 -->
<view class="returnBnt bg-color-red">返回查看订单</view>
<view class="returnBnt cart-color">返回首页</view>
</view>
</template>
+104
View File
@@ -0,0 +1,104 @@
<template>
<view class="return-list" ref="container">
<view class="goodWrapper" v-for="(order,orderListIndex) in orderList" :key="orderListIndex">
<view class="iconfont icon-tuikuanzhong powder" v-if="order._status._type === '-1'"></view>
<view class="iconfont icon-yituikuan" v-if="order._status._type === '-2'"></view>
<view class="orderNum">订单号{{ order.orderId }}</view>
<!-- <view class="acea-row row-between row-middle orderNum" style="flex-wrap: nowrap;">
<view class="orderNum">订单号{{ order.orderId }}</view>
<view class="font-color-red" style="flex-shrink: 0;font-size: 28rpx;">{{order._status._title}}</view>
</view> -->
<view
class="item acea-row row-between-wrapper"
v-for="(cart,cartInfoIndex) in order.cartInfo"
:key="cartInfoIndex"
@click="goOrderDetails(order)"
>
<view class="pictrue">
<image :src="cart.productInfo.image" class="image" @click.stop="goGoodsCon(cart)" />
</view>
<view class="text">
<view class="acea-row row-between-wrapper">
<view class="name line1">{{ cart.productInfo.storeName }}</view>
<view class="num">x {{ cart.cartNum }}</view>
</view>
<view
class="attr line1"
v-if="cart.productInfo.attrInfo"
>{{ cart.productInfo.attrInfo.sku }}</view>
<view class="attr line1" v-else>{{ cart.productInfo.storeName }}</view>
<view class="money">{{ cart.productInfo.price }}</view>
</view>
</view>
<view class="totalSum">
{{ order.cartInfo.length || 0 }}件商品总金额
<text
class="font-color-red price"
>{{ order.payPrice }}</text>
</view>
</view>
<view class="noCart" v-if="orderList.length === 0 && page > 1">
<view class="pictrue">
<image :src="webUrl+'/20210203155245713983.png'" />
</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
</view>
</template>
<script>
import { getOrderList } from "@/api/order";
import Loading from "@/components/Loading";
export default {
name: "ReturnList",
components: {
Loading
},
data() {
return {
webUrl:this.$VUE_APP_RESOURCES_URL,
orderList: [],
page: 1,
limit: 20,
loading: false,
loaded: false
};
},
methods: {
goGoodsCon(cart) {
this.$yrouter.push({
path: "/pages/shop/GoodsCon/index",
query: { id: cart.productInfo.id }
});
},
goOrderDetails(order) {
this.$yrouter.push({
path: "/pages/order/OrderDetails/index",
query: { id: order.orderId }
});
},
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>
+354
View File
@@ -0,0 +1,354 @@
<template>
<view class="order-details pos-order-details">
<view class="header acea-row row-middle">
<view class="state">{{ title }}</view>
<view class="data">
<view class="order-num">订单{{ orderInfo.orderId }}</view>
<view>
<text class="time">
<data-format :date="orderInfo.addTime"></data-format>
</text>
</view>
</view>
</view>
<view class="orderingUser acea-row row-middle">{{ orderInfo.nickname }}</view>
<view class="address">
<view class="name">
{{ orderInfo.realName}}
<text class="phone">{{ orderInfo.userPhone }}</text>
</view>
<view>{{ orderInfo.userAddress }}</view>
</view>
<view class="line">
<image :src="webUrl+'/20230304135025917856.png'" />
</view>
<view class="pos-order-goods">
<view
class="goods acea-row row-between-wrapper"
v-for="(item, orderInfoIndex) in orderInfo.cartInfo"
:key="orderInfoIndex"
>
<view class="picTxt acea-row row-between-wrapper">
<view class="pictrue">
<image :src="item.productInfo.image" />
</view>
<view class="text acea-row row-between row-column">
<view class="info line2">{{ item.productInfo.storeName }}</view>
<view class="attr">{{ item.productInfo.sku }}</view>
</view>
</view>
<view class="money">
<view class="x-money">{{ item.productInfo.price }}</view>
<view class="num">x{{ item.cartNum }}</view>
<view class="y-money">{{ item.productInfo.otPrice ? item.productInfo.otPrice : 0 }}</view>
</view>
</view>
</view>
<view class="public-total">
{{ orderInfo.totalNum }}件商品应支付
<text class="money">{{ orderInfo.payPrice }}</text>
( 邮费 ¥{{
orderInfo.payPostage
}}
)
</view>
<view class="wrapper">
<view class="item acea-row row-between">
<view>订单编号</view>
<view class="conter acea-row row-middle row-right">
{{ orderInfo.orderId
}}
<text
class="copy copy-data"
@click="copyClipboard(orderInfo.orderId)"
>复制</text>
</view>
</view>
<view class="item acea-row row-between">
<view>下单时间</view>
<view class="conter">
<data-format :date="orderInfo.addTime"></data-format>
</view>
</view>
<view class="item acea-row row-between">
<view>支付状态</view>
<view class="conter">{{ orderInfo.paid == 1 ? "已支付" : "未支付" }}</view>
</view>
<view class="item acea-row row-between">
<view>支付方式</view>
<view class="conter">{{ payType }}</view>
</view>
<view class="item acea-row row-between">
<view>买家留言</view>
<view class="conter">{{ orderInfo.mark }}</view>
</view>
</view>
<view class="wrapper">
<view class="item acea-row row-between">
<view>支付金额</view>
<view class="conter">{{ orderInfo.totalPrice }}</view>
</view>
<view class="item acea-row row-between">
<view>优惠券抵扣</view>
<view class="conter">-{{ orderInfo.couponPrice }}</view>
</view>
<view class="actualPay acea-row row-right">
实付款
<text class="money font-color-red">{{ orderInfo.payPrice }}</text>
</view>
</view>
<view
class="wrapper"
v-if="orderInfo.delivery_type != 'fictitious' && orderInfo._status._type === 2"
>
<view class="item acea-row row-between">
<view>配送方式</view>
<view class="conter" v-if="orderInfo.delivery_type === 'express'">快递</view>
<view class="conter" v-if="orderInfo.delivery_type === 'send'">送货</view>
</view>
<view class="item acea-row row-between">
<view v-if="orderInfo.delivery_type === 'express'">快递公司</view>
<view v-if="orderInfo.delivery_type === 'send'">送货人</view>
<view class="conter">{{ orderInfo.delivery_name }}</view>
</view>
<view class="item acea-row row-between">
<view v-if="orderInfo.delivery_type === 'express'">快递单号</view>
<view v-if="orderInfo.delivery_type === 'send'">送货人电话</view>
<view class="conter">
{{ orderInfo.delivery_id
}}
<text
class="copy copy-data"
@click="copyClipboard(orderInfo.delivery_id)"
>复制</text>
</view>
</view>
</view>
<view style="height:100rpx;"></view>
<view class="footer acea-row row-right row-middle">
<view class="more"></view>
<view class="bnt cancel" @click="modify(0)" v-if="types == 0">一键改价</view>
<view class="bnt cancel" @click="modify(0)" v-if="types == -1">立即退款</view>
<view
class="bnt cancel"
v-if="orderInfo.pay_type === 'offline' && orderInfo.paid === 0"
@click="offlinePay"
>确认付款</view>
<view class="bnt delivery" v-if="types == 1" @click="goGoodsDeliver(orderInfo)">去发货</view>
</view>
<PriceChange
:change="change"
:orderInfo="orderInfo"
v-on:closechange="changeclose($event)"
v-on:savePrice="savePrice"
:status="status"
></PriceChange>
</view>
</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: {
goGoodsDeliver(orderInfo) {
this.$yrouter.push({
path: "/pages/orderAdmin/GoodsDeliver/index",
query: { oid: orderInfo.orderId }
});
},
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 => {
uni.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;
uni.showToast({
title: "改价成功",
icon: "success",
duration: 2000
});
that.getIndex();
},
function() {
that.change = false;
uni.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;
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.getIndex();
},
err => {
that.change = false;
uni.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;
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.getIndex();
},
err => {
that.change = false;
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
}
);
}
},
offlinePay: function() {
setOfflinePay({ order_id: this.orderInfo.order_id }).then(
res => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
this.getIndex();
},
err => {
uni.showToast({
title: err.msg,
icon: "none",
duration: 2000
});
}
);
}
}
};
</script>
+330
View File
@@ -0,0 +1,330 @@
<template>
<view class="pos-order-list" ref="container">
<view class="nav acea-row row-around row-middle">
<view class="item" :class="where.status == 0 ? 'on' : ''" @click="changeStatus(0)">待付款</view>
<view class="item" :class="where.status == 1 ? 'on' : ''" @click="changeStatus(1)">待发货</view>
<view class="item" :class="where.status == 2 ? 'on' : ''" @click="changeStatus(2)">待收货</view>
<view class="item" :class="where.status == 3 ? 'on' : ''" @click="changeStatus(3)">待评价</view>
<view class="item" :class="where.status == 4 ? 'on' : ''" @click="changeStatus(4)">已完成</view>
<view class="item" :class="where.status == -3 ? 'on' : ''" @click="changeStatus(-3)">退款</view>
</view>
<view class="list">
<view class="item" v-for="(item, listIndex) in list" :key="listIndex">
<view class="order-num acea-row row-middle" @click="toDetail(item)">
<text>订单号{{ item.orderId }}</text>
<text class="time">
<text>下单时间</text>
<data-format :date="item.addTime"></data-format>
</text>
</view>
<view class="pos-order-goods" v-for="(val, key) in item.cartInfo" :key="key">
<view class="goods acea-row row-between-wrapper" @click="toDetail(item)">
<view class="picTxt acea-row row-between-wrapper">
<view class="pictrue">
<image :src="val.productInfo.image" />
</view>
<view class="text acea-row row-between row-column">
<view class="info line2">{{ val.productInfo.storeName }}</view>
<view class="attr" v-if="val.productInfo.sku">{{ val.productInfo.sku }}</view>
</view>
</view>
<view class="money">
<view class="x-money">{{ val.productInfo.price }}</view>
<view class="num">x{{ val.cartNum }}</view>
<view class="y-money">{{ val.productInfo.otPrice }}</view>
</view>
</view>
</view>
<view class="public-total">
{{ item.totalNum }}件商品应支付
<text class="money">{{ item.payPrice }}</text>
( 邮费 ¥{{
item.totalPostage
}}
)
</view>
<view class="operation acea-row row-between-wrapper">
<view class="more">
<!-- <view class="iconfont icon-gengduo" @click="more(index)"></view>-->
<!-- <view class="order" v-show="current === index">-->
<!-- <view class="items">-->
<!-- {{ where.status > 0 ? "删除" : "取消" }}订单-->
<!-- </view>-->
<!-- <view class="arrow"></view>-->
<!-- </view>-->
</view>
<view class="acea-row row-middle">
<view class="bnt" @click="modify(item, 0)" v-if="where.status == 0">一键改价</view>
<view class="bnt" @click="modify(item, 0)" v-if="where.status == -3 && item.refundStatus === 1">立即退款</view>
<view class="bnt cancel" v-if="item.pay_type === 'offline' && item.paid === 0" @click="offlinePay(item)">确认付款</view>
<view class="bnt" v-if="where.status == 1" @click="goGoodsDeliver(item)">去发货</view>
</view>
</view>
</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
<PriceChange :change="change" :orderInfo="orderInfo" v-on:closechange="changeclose($event)" v-on:savePrice="savePrice"
:status="status"></PriceChange>
</view>
</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() {
!this.loading && this.getIndex();
},
methods: {
goGoodsDeliver(item) {
this.$yrouter.push({
path: "/pages/orderAdmin/GoodsDeliver/index",
query: {
oid: item.orderId
}
});
},
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;
uni.showToast({
title: "改价成功",
icon: "success",
duration: 2000
});
that.init();
},
function() {
that.change = false;
uni.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;
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.init();
},
err => {
that.change = false;
uni.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;
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.init();
},
err => {
that.change = false;
uni.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 => {
uni.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/index",
query: {
oid: item.orderId
}
});
},
offlinePay: function(item) {
setOfflinePay({
order_id: item.order_id
}).then(
res => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
this.init();
},
error => {
uni.showToast({
title: error.msg,
icon: 'none',
duration: 2000
});
}
);
}
}
};
</script>
<style lang="less">
</style>
+231
View File
@@ -0,0 +1,231 @@
<template>
<view class="deliver-goods">
<header>
<view class="order-num acea-row row-between-wrapper">
<view class="num line1">订单号{{ delivery.orderId }}</view>
<view class="name line1">{{ delivery.nickname }}</view>
</view>
<view class="address">
<view class="name">
{{ delivery.realName }}
<text class="phone">{{ delivery.userPhone }}</text>
</view>
<view>{{ delivery.userAddress }}</view>
</view>
<view class="line">
<image :src="webUrl+'/20230304135025917856.png'" />
</view>
</header>
<view class="wrapper">
<view class="item acea-row row-between-wrapper">
<view>发货方式</view>
<view class="mode acea-row row-middle row-right">
<view
class="goods"
:class="active === typesIndex ? 'on' : ''"
v-for="(item, typesIndex) in types"
:key="typesIndex"
@click="changeType(item, typesIndex)"
>
{{ item.title }}
<text class="iconfont icon-xuanzhong2"></text>
</view>
</view>
</view>
<view class="list" v-show="active === 0">
<picker
mode="selector"
:range="logistics"
class="mode"
range-key="name"
@change="changeLog"
>
<view class="item acea-row row-between-wrapper">
<view>快递公司</view>
<input
type="text"
placeholder="填写快递公司"
disabled="disabled"
v-model="deliveryNames"
class="mode"
/>
<!-- <input type="text" placeholder="填写快递公司" v-model="deliveryName" class="mode" /> -->
</view>
</picker>
<view class="item acea-row row-between-wrapper">
<view>快递单号</view>
<input type="text" placeholder="填写快递单号" v-model="deliveryId" class="mode" />
</view>
</view>
<view class="list" v-show="active === 1">
<view class="item acea-row row-between-wrapper">
<view>送货人</view>
<input type="text" placeholder="填写送货人" v-model="deliveryName" class="mode" />
</view>
<view class="item acea-row row-between-wrapper">
<view>送货电话</view>
<input type="text" placeholder="填写送货电话" v-model="deliveryId" class="mode" />
</view>
</view>
</view>
<view style="height:100rpx;"></view>
<view class="confirm" @click="saveInfo">确认提交</view>
</view>
</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 {
webUrl: this.$VUE_APP_RESOURCES_URL,
types: [
{
type: "express",
title: "发货"
}
// {
// type: "send",
// title: "送货"
// },
// {
// type: "fictitious",
// title: "无需发货"
// }
],
active: 0,
order_id: "",
delivery: [],
logistics: [],
delivery_type: "express",
deliveryName: "",
deliveryId: "",
deliveryNames: "请选择"
};
},
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: {
changeLog: function(value) {
this.deliveryNames = this.logistics[value.detail.value].name;
this.deliveryName = this.logistics[value.detail.value].id;
},
changeType: function(item, index) {
this.active = index;
this.delivery_type = item.type;
this.deliveryName = "";
this.deliveryId = "";
},
getIndex: function() {
let that = this;
getAdminOrderDelivery(that.order_id).then(
res => {
that.delivery = res.data;
},
error => {
uni.showToast({
title: error.msg,
icon: "none",
duration: 2000
});
}
);
},
getLogistics: function() {
let that = this;
getLogistics().then(
res => {
console.log(res.data);
that.logistics = res.data;
},
error => {
uni.showToast({
title: error.msg,
icon: "none",
duration: 2000
});
}
);
},
async saveInfo() {
let that = this,
delivery_type = that.delivery_type,
deliveryName = that.deliveryName.toString(),
deliveryId = that.deliveryId,
save = {};
console.log(deliveryName);
save.orderId = that.order_id;
save.deliveryType = that.delivery_type;
switch (delivery_type) {
case "express":
try {
await this.$validator({
deliveryName: [required(required.message("快递公司"))],
deliveryId: [required(required.message("快递单号"))]
}).validate({ deliveryName, deliveryId });
} catch (e) {
return validatorDefaultCatch(e);
}
save.deliveryName = deliveryName;
save.deliveryId = deliveryId;
that.setInfo(save);
break;
case "send":
try {
await this.$validator({
deliveryName: [required(required.message("发货人姓名"))],
deliveryId: [required(required.message("发货人电话"))]
}).validate({ deliveryName, deliveryId });
} catch (e) {
return validatorDefaultCatch(e);
}
save.deliveryName = deliveryName;
save.deliveryId = deliveryId;
that.setInfo(save);
break;
}
},
setInfo: function(item) {
let that = this;
console.log(item);
setAdminOrderDelivery(item)
.then(res => {
console.log(res);
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.$yrouter.go(-1);
})
.catch(err => {
console.log(err);
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
@@ -0,0 +1,184 @@
<template>
<view class="OrderCancellation">
<view class="header">
<image mode="aspectFit" :src="`${staticUrl}/writeOffBg.jpg`" @click="openQRCode" />
</view>
<view class="whiteBg">
<view class="input">
<input type="number" placeholder="0" v-model="verify_code" />
</view>
<view class="bnt" @click="storeCancellation">立即核销</view>
</view>
<view class="scan" v-if="iswechat">
<image :src="webUrl+'/20200729154546061002.gif'" @click="openQRCode" />
</view>
<WriteOff :iShidden="iShidden" :orderInfo="orderInfo" @cancel="cancel" @confirm="confirm"></WriteOff>
</view>
</template>
<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 {
staticUrl:this.$STATIC_RESOURCE_URL,
webUrl: VUE_APP_RESOURCES_URL,
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 = "";
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
})
.catch(err => {
uni.showToast({
title: err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
});
},
storeCancellation: function() {
let ref = /[0-9]{12}/;
if (!this.verify_code) {
uni.showToast({
title: "请输入核销码",
icon: "none",
duration: 2000
});
return;
}
if (!ref.test(this.verify_code)) {
uni.showToast({
title: "请输入正确的核销码",
icon: "none",
duration: 2000
});
return;
}
uni.showLoading({
title: "查询中"
});
orderVerific(this.verify_code, 0)
.then(res => {
uni.hideLoading();
this.orderInfo = res.data;
this.iShidden = false;
uni.showToast({
title: res.msg,
icon: "success",
duration: 2000
});
})
.catch(error => {
uni.hideLoading();
uni.showToast({
title: error.msg ||
error.response.data.msg ||
error.response.data.message,
icon: "none",
duration: 2000
});
});
},
openQRCode: function() {
let that = this;
// 这里需要调用扫码功能
}
}
};
</script>
<style scoped lang="less">
.OrderCancellation .header {
width: 100%;
height: 3 * 100rpx;
background-size: 100% 100%;
image {
width: 100%;
height: 3 * 100rpx;
}
}
.OrderCancellation .whiteBg {
width: 6.9 * 100rpx;
background-color: #fff;
margin: -0.93 * 100rpx auto 0 auto;
padding-top: 0.8 * 100rpx;
padding-bottom: 30rpx;
z-index: 99;
position: relative;
border-radius: 0.06 * 100rpx 0.06 * 100rpx 0 0;
}
.OrderCancellation .whiteBg .input {
width: 5.8 * 100rpx;
margin: 0 auto;
border-bottom: 0.01 * 100rpx solid #eee;
}
.OrderCancellation .whiteBg .input input {
padding-bottom: 0.25 * 100rpx;
font-size: 0.6 * 100rpx;
height: auto;
color: #282828;
width: 100%;
text-align: center;
}
.OrderCancellation .whiteBg .bnt {
font-size: 0.32 * 100rpx;
color: #fff;
width: 5.8 * 100rpx;
height: 0.86 * 100rpx;
border-radius: 0.43 * 100rpx;
background-image: linear-gradient(to right, #eb3729 0%, #eb3729 100%);
background-image: -webkit-linear-gradient(to right, #eb3729 0%, #eb3729 100%);
background-image: -moz-linear-gradient(to right, #eb3729 0%, #eb3729 100%);
text-align: center;
line-height: 0.86 * 100rpx;
margin: 0.55 * 100rpx auto 0 auto;
}
.OrderCancellation .scan {
width: 3 * 100rpx;
height: 3 * 100rpx;
margin: 1.1 * 100rpx auto 0 auto;
}
.OrderCancellation .scan image {
width: 100%;
height: 100%;
display: block;
}
</style>
+167
View File
@@ -0,0 +1,167 @@
<template>
<view class="order-index" ref="container">
<image :src="webUrl+'/20230304202119869348.png'" mode="widthFix" class="image" />
<view class="header acea-row">
<view class="item" @click="goAdminOrderList(0)">
<view class="num">{{ census.orderCount.unpaidCount }}</view>
<view>待付款</view>
</view>
<view class="item" @click="goAdminOrderList(1)">
<view class="num">{{ census.orderCount.unshippedCount }}</view>
<view>待发货</view>
</view>
<view class="item" @click="goAdminOrderList(2)">
<view class="num">{{ census.orderCount.receivedCount }}</view>
<view>待收货</view>
</view>
<view class="item" @click="goAdminOrderList(3)">
<view class="num">{{ census.orderCount.evaluatedCount }}</view>
<view>待评价</view>
</view>
<view class="item" @click="goAdminOrderList(4)">
<view class="num">{{ census.orderCount.refundCount }}</view>
<view>退款</view>
</view>
</view>
<view class="wrapper">
<view class="title">
<text class="iconfont icon-shujutongji"></text>数据统计
</view>
<view class="list acea-row">
<view class="item" @click="goStatistics({type:'price',time:'today'})">
<view class="num">{{ census.orderTimeCount.todayPrice }}</view>
<view>今日成交额</view>
</view>
<view class="item" @click="goStatistics({type:'price',time:'yesterday'})">
<view class="num">{{ census.orderTimeCount.proPrice }}</view>
<view>昨日成交额</view>
</view>
<view class="item" @click="goStatistics({type:'price',time:'month'})">
<view class="num">{{ census.orderTimeCount.monthPrice }}</view>
<view>本月成交额</view>
</view>
<view class="item" @click="goStatistics({type:'order',time:'today'})">
<view class="num">{{ census.orderTimeCount.todayCount }}</view>
<view>今日订单数</view>
</view>
<view class="item" @click="goStatistics({type:'order',time:'yesterday'})">
<view class="num">{{ census.orderTimeCount.proCount }}</view>
<view>昨日订单数</view>
</view>
<view class="item" @click="goStatistics({type:'order',time:'month'})">
<view class="num">{{ census.orderTimeCount.monthCount }}</view>
<view>本月订单数</view>
</view>
</view>
</view>
<view class="public-wrapper">
<view class="title">
<text class="iconfont icon-xiangxishuju"></text>详细数据
</view>
<view class="nav acea-row row-between-wrapper">
<view class="data">日期</view>
<view class="browse">订单数</view>
<view class="turnover">成交额</view>
</view>
<view class="conter">
<view
class="item acea-row row-between-wrapper"
v-for="(item, orderListIndex) in list"
:key="orderListIndex"
>
<view class="data">{{ item.time }}</view>
<view class="browse">{{ item.count }}</view>
<view class="turnover">{{ item.price }}</view>
</view>
</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
</view>
</template>
<script>
import { getStatisticsInfo, getStatisticsMonth } from "@/api/admin";
import Loading from "@/components/Loading";
export default {
name: "OrderIndex",
components: {
Loading
},
props: {},
data: function() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
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: {
goStatistics(query) {
this.$yrouter.push({
path: "/pages/orderAdmin/Statistics/index",
query
});
},
goAdminOrderList(types) {
this.$yrouter.push({
path: "/pages/orderAdmin/AdminOrderList/index",
query: { types }
});
},
getIndex: function() {
var that = this;
getStatisticsInfo().then(
res => {
that.census = res.data;
that.census.unpaidCount = that.census.orderCount.unpaidCount;
},
err => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
}
);
},
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;
},
err => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
},
300
);
}
}
};
</script>
+446
View File
@@ -0,0 +1,446 @@
<template>
<view class="statistical-page" ref="container">
<view class="navs">
<view class="list">
<view class="item" :class="time == 'today' ? 'on' : ''" @click="setTime('today')">今天</view>
<view class="item" :class="time == 'yesterday' ? 'on' : ''" @click="setTime('yesterday')">昨天</view>
<view class="item" :class="time == 'seven' ? 'on' : ''" @click="setTime('seven')">最近7天</view>
<view class="item" :class="time == 'month' ? 'on' : ''" @click="setTime('month')">本月</view>
</view>
</view>
<view class="wrapper">
<view class="title">{{ title }}{{ this.where.type == 1 ? "营业额(元)" : "订单量(份)" }}</view>
<view class="money">{{ time_price }}</view>
</view>
<!-- <view class="chart">
<view class="company">{{ where.type === 1 ? "单位(元)" : "单位(份)" }}</view>
<ECharts :options="polar"></ECharts>
</view>-->
<view class="public-wrapper">
<view class="title">
<text class="iconfont icon-xiangxishuju"></text>详细数据
</view>
<view class="nav acea-row row-between-wrapper">
<view class="data">日期</view>
<view class="browse">订单量</view>
<view class="turnover">成交额</view>
</view>
<view class="conter">
<view
class="item acea-row row-between-wrapper"
v-for="(item, statisticalIndex) in list"
:key="statisticalIndex"
>
<view class="data">{{ item.time }}</view>
<view class="browse">{{ item.count }}</view>
<view class="turnover">{{ item.price }}</view>
</view>
</view>
</view>
<!-- <view class="calendar-wrapper" :class="current === true ? 'on' : ''">
<view 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]"
/>
</view>
</view>-->
<view class="mask" @touchmove.prevent v-show="current === true" @click="close"></view>
<Loading :loaded="loaded" :loading="loading"></Loading>
</view>
</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 => {
uni.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.list = res.data;
that.filter.page = that.filter.page + 1;
},
err => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
}
);
}
}
};
</script>
<style scoped lang="less">
.echarts {
width: 100%;
height: 5.5 * 100rpx;
}
.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.26 * 100rpx;
}
.statistical-page .wrapper .increase .iconfont {
margin-left: 0;
}
</style>
+115
View File
@@ -0,0 +1,115 @@
<template>
<view class="evaluate-list" ref="container">
<view class="header">
<view class="generalComment acea-row row-between-wrapper">
<view class="acea-row row-middle font-color-red">
<text class="evaluate">评分</text>
<view class="start" :class="'star' + replyData.replyStar"></view>
</view>
<view>
<text class="font-color-red">{{ replyData.replyChance || 0 }}%</text>
<text>好评率</text>
</view>
</view>
<view class="nav acea-row row-middle">
<view
class="acea-row row-center-wrapper"
v-for="(item, navListIndex) in navList"
:key="navListIndex"
@click="changeType(navListIndex)"
>
<view
class="item"
:class="currentActive === navListIndex ? 'bg-color-red' : ''"
v-if="item.num"
>
<text>{{ item.evaluate }}({{ item.num }})</text>
</view>
</view>
</view>
</view>
<UserEvaluation :reply="reply"></UserEvaluation>
<Loading :loaded="loadend" :loading="loading"></Loading>
</view>
</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 lang="less">
.noCommodity {
height: 8*100rpx;
background-color: #fff;
}
</style>
+131
View File
@@ -0,0 +1,131 @@
<template>
<view class="good-search">
<view class="header">
<view class="search-box flex jc-between ai-center">
<input v-model="search" type="text" placeholder="搜索商品" placeholder-style="color:#999"/>
<view class="btn flex-0 flex jc-center ai-center" @click="submit">
<text class="iconfont icon-sousuo2"></text>
<text>搜索</text>
</view>
</view>
</view>
<view class="page-content" v-if="keywords.length">
<view class="title">热门搜索</view>
<view class="list acea-row">
<view
class="item"
v-for="keywordsKey of keywords"
:key="keywordsKey"
@click="toSearch(keywordsKey)"
>{{ keywordsKey }}
</view>
</view>
</view>
<view class="line"></view>
</view>
</template>
<script>
import {getSearchKeyword} from "@/api/store";
import {trim} from "@/utils";
export default {
name: "GoodSearch",
props: {},
data: function () {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
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/index", query: {s}});
},
getData() {
getSearchKeyword().then(res => {
this.keywords = res.data;
});
}
}
};
</script>
<style lang="less">
page {
min-height: 100vh;
background: #fff !important;
}
.good-search {
.header {
padding: 40rpx 32rpx 32rpx;
background: #F9F9F9;
.search-box {
width: 686rpx;
height: 72rpx;
box-sizing: border-box;
padding: 0 8rpx 0 32rpx;
border-radius: 36rpx;
background: #fff;
font-size: 24rpx;
input{
width: 100%;
}
.btn {
width: 128rpx;
height: 54rpx;
background: #FD574B;
border-radius: 28rpx;
color: #fff;
font-weight: bold;
.icon-sousuo2 {
margin-right: 4rpx;
font-size: 28rpx;
}
}
}
}
.page-content {
padding: 0 32rpx;
.title {
margin: 22rpx 0 24rpx;
color: #333;
font-size: 28rpx;
line-height: 40rpx;
font-weight: bold;
letter-spacing: 4px;
}
.list {
.item {
height: 48rpx;
box-sizing: border-box;
margin-right: 24rpx;
padding: 0 24rpx;
border-radius: 28rpx;
background: #F1F0EE;
color: #666;
font-size: 24rpx;
line-height: 48rpx;
}
}
}
}
</style>
+578
View File
@@ -0,0 +1,578 @@
<template>
<view class="productSort">
<hx-navbar :back="false" :fixed="true" color="#080F1A" :left-slot="false" :right-slot="false">
<view class="acea-row row-center row-middle" style="width: 100%;">
<view class="main-title ">分类
<!-- <text class="pink-dot"></text> -->
</view>
</view>
</hx-navbar>
<view class="index">
<view class="header acea-row row-center-wrapper" :style="{top:headerTop}">
<view @click="goGoodSearch()" class="search acea-row row-middle">
<text class="iconfont icon-xiazai5"></text>
搜索商品
</view>
</view>
</view>
<view class="aside" :style="{top:contentTop}">
<view class="item acea-row row-center-wrapper" :class="categoryDivindex === navActive ? 'on' : ''"
v-for="(item, categoryDivindex) in category" :key="categoryDivindex" @click="asideTap(categoryDivindex)">
<text>{{ item.cateName }}</text>
</view>
</view>
<view class="conter">
<mescroll-body ref="mescrollRef" top="16rpx" bottom="0" class='cotent-scroll' :up="upOption" :down="downOption"
@up="upCallback" @down="downCallback" @init="mescrollInit" @emptyclick="emptyClick">
<view class="text acea-row row-center row-middle">
<view class="h-line"></view>
<view class="cate-name">
{{curCategoryName}}
</view>
<view class="h-line"></view>
</view>
<view class="acea-row">
<view @click="goodsDetail(item)" class="item acea-row cate-goods-item" v-for="(item, index) in goodsList"
:key="index" :style="{width:goodsColumnWidth}">
<view class="img-box">
<image :style="{width:goodsColumnWidth,height:goodsColumnWidth}" :src="item.image" />
<view v-if="item.vipPrice && item.vipPrice > 0" class="price-tag">
<!-- <image style="width: 100%;height: 100%;" :src="webUrl+'/20210806130336255505.png'" mode=""></image> -->
<image style="width: 94rpx;height: 42rpx;" :src="webUrl+'/20220525103739004011.png'" mode="scaleToFill"></image>
</view>
</view>
<view class="pro-info line2"><text>{{ item.storeName }}</text></view>
<!-- <view class="market-price">{{item.otPrice}}</view> -->
<view class="money acea-row row-middle row-between" style="width: 100%;">
<!-- <text>{{ item.price }}</text> -->
<text class="num" v-if="item.vipPrice && item.vipPrice > 0">{{item.vipPrice}}</text>
<text class="num" v-else>{{ item.price }}</text>
<!-- <view class="shoppingCart acea-row row-center row-middle">
</view> -->
</view>
</view>
</view>
</mescroll-body>
</view>
<view style="height:100rpx;"></view>
</view>
</template>
<script>
import {
getCategory,
fetchNormal
} from "@/api/store";
import MescrollMixins from "@/mixins/mescroll-mixins.js";
import MescrollBody from "@/components/mescroll-uni/mescroll-body.vue";
import NP from "number-precision";
import {
trim
} from "@/utils";
import {
mapGetters
} from 'vuex';
import hxNavbar from "@/components/hx-navbar/hx-navbar.vue"
var that;
export default {
name: "GoodsClass",
components: {
hxNavbar,
MescrollBody
},
props: {},
computed: mapGetters(["userInfo"]),
mixins: [
MescrollMixins({
getPageData(mescroll) {
// 此时mescroll会携带page的参数:
let pageNum = mescroll.num; // 页码, 默认从1开始
let pageSize = mescroll.size; // 页长, 默认每页10条
var params = {
page: pageNum,
// limit: pageSize,
// keyword: that.keyword,
sid: that.sid,
// news: 0,
// priceOrder: "",
// salesOrder: ""
}
var _this = this;
fetchNormal(params)
.then(res => {
//mescroll.endByPage(res.data.length, res.data.total_pages);
if (mescroll.num == 1) {
_this.goodsList = []; //如果是第一页需手动制空列表
//_this.adjustPage();
}
_this.goodsList = _this.goodsList.concat(res.data.map((goods) => {
goods.price = _this.$force2Decimal(goods.price);
// goods.vipPrice = _this.$force2Decimal(goods.vipPrice);
if (that.$store.getters.token && that.userInfo) {
var p = NP.times(goods.price, NP.divide(parseFloat(that.userInfo.discount), 100))
goods.vipPrice = that.$force2Decimal(p);
}
return goods;
})); //追加新数据
mescroll.endSuccess(res.data.length);
})
.catch(err => {
mescroll.endErr();
//uni.hideLoading();
uni.showToast({
title: err + '',
icon: 'none',
mask: false,
duration: 1500
});
})
}
})
],
data: function() {
return {
keyword: '',
sid: 0, //二给分类id
curCategoryName: '全部商品',
category: [],
navActive: 0,
tabName: "", // 跳转初始分类名
search: "",
lock: false,
upOption: {
noMoreSize: 10, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
auto: false,
empty: {
tip: '暂无商品' // 提示
// btnText:'点击刷新'
}
},
downOption: {
auto: true
},
goodsList: [],
headerTop: '128rpx',
goodsColumnWidth: '246rpx',
contentTop: '224rpx',
webUrl: this.$VUE_APP_RESOURCES_URL
};
},
watch: {
"$yroute.query.id": function(n) {
if (n) {
this.activeCateId(n);
}
}
},
onShow() {
let name=uni.getStorageSync("name");
if(name){
this.tabName = name;
uni.removeStorageSync("name");
}
this.loadCategoryData();
},
onLoad: function(option) {
that = this;
uni.getSystemInfo({
success: (e) => {
// this.compareVersion(e.SDKVersion, '2.5.0')
let statusBar = 0;
let customBar = 0;
// #ifdef MP
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + 45
if (e.platform === 'android') {
//this.$store.commit('SET_SYSTEM_IOSANDROID', false)
customBar = e.statusBarHeight + 50
}
// #endif
// #ifdef MP-WEIXIN
statusBar = e.statusBarHeight
// @ts-ignore
//uni.getMenuButtonBoundingClientRect();
const custom = uni.getMenuButtonBoundingClientRect()
customBar = custom.bottom + custom.top - e.statusBarHeight
// #endif
// #ifdef MP-ALIPAY
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + e.titleBarHeight
// #endif
// #ifdef APP-PLUS
console.log('app-plus', e)
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + 45
// #endif
// #ifdef H5
statusBar = 0
customBar = e.statusBarHeight + 45
// #endif
// 这里你可以自己决定存放方式,建议放在store中,因为store是实时变化的
// this.$store.commit('SET_STATUS_BAR', statusBar)
// this.$store.commit('SET_CUSTOM_BAR', customBar)
// this.$store.commit('SET_SYSTEM_INFO', e)
//两列商品宽度
that.goodsColumnWidth = (e.screenWidth - uni.upx2px(180 + 3 * 30)) / 2 + 'px';
console.log('goodsColumnWidth:' + that.goodsColumnWidth);
//状态栏图片高度
that.headerTop = statusBar + 44 + 'px';
that.contentTop = statusBar + 44 + uni.upx2px(96) + 'px';
}
});
},
// mounted: function() {
// document.addEventListener("scroll", this.onScroll, false);
// },
methods: {
goodsDetail: function(item) {
this.$yrouter.push({
path: '/pages/shop/GoodsCon/index',
query: {
id: item.id
}
})
},
emptyClick: function() {
//触发加载请求
this.mescroll && this.mescroll.triggerDownScroll()
},
goGoodSearch() {
this.$yrouter.push("/pages/shop/GoodSearch/index");
},
goGoodsList(child) {
this.$yrouter.push({
path: "/pages/shop/GoodsList/index",
query: {
id: child.id,
title: child.cateName
}
});
},
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() {
var that = this;
getCategory(0,35).then(res => {
//that.category = res.data;
that.category = [];
res.data.forEach(function(fcat, idx) {
if (fcat.children) {
fcat.children.forEach(function(sub, sidex) {
that.category.push(sub);
});
}
});
that.category.unshift({
"id": 0,
"pid": 0,
"cateName": "全部商品"
});
that.$nextTick(() => {
if (that.$yroute.query.id) {
that.activeCateId(that.$yroute.query.id);
}
for (let i = 0; i < that.category.length; i++) {
if (that.tabName == that.category[i].cateName)that.asideTap(i);
}
});
});
},
submitForm: function() {
var val = trim(this.search);
if (val) {
this.$yrouter.push({
path: "/pages/shop/GoodsList/index",
query: {
s: val
}
});
setTimeout(() => (this.search = ""), 500);
}
},
asideTap(index) {
this.navActive = index;
this.curCategoryName = this.category[index].cateName;
this.sid = this.category[index].id;
//触发加载请求
this.mescroll.scrollTo(0, 0);
this.mescroll && this.mescroll.resetUpScroll(false);
}
},
beforeDestroy: function() {
// document.removeEventListener("scroll", this.onScroll, false);
}
};
</script>
<style scoped lang="less">
/*产品分类*/
.productSort {
height: 100%;
background: #fff;
}
.productSort .header {
width: 100%;
height: 0.96*100rpx;
background-color: #fff;
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 9;
// border-bottom: 1px solid #f5f5f5;
border-bottom: 2rpx solid #DADCE0;
}
.productSort .header .input {
width: 7*100rpx;
height: 0.6*100rpx;
background-color: #f5f5f5;
border-radius: 0.5*100rpx;
padding: 0 0.25*100rpx;
}
.productSort .header .input .iconfont {
font-size: 0.35*100rpx;
color: #555;
}
.productSort .header .input input {
font-size: 0.26*100rpx;
height: 100%;
width: 5.97*100rpx;
}
.productSort .header .input input::placeholder {
color: #999;
}
.productSort .aside {
position: fixed;
width: 176rpx;
left: 0;
top: 0.96*100rpx;
bottom: 0 !important;
box-sizing: border-box;
border-right: 2rpx solid #DADCE0;
background-color: #fff;
overflow-y: auto;
overflow-x: hidden;
overflow-scrolling: touch;
}
.productSort .aside::-webkit-scrollbar {
width: 0 !important
}
.productSort .aside .item {
width: 100%;
height: 104rpx;
text{
display: inline-block;
width: 100%;
height: 28rpx;
font-size: 26rpx;
color: #666;
text-align: center;
}
}
.productSort .aside .item.on {
text{
border-left: 6rpx solid #FF564A;
color: #FF564A;
font-weight: bold;
}
}
.productSort .conter {
margin-left: 176rpx;
// padding: 0 0.14*100rpx;
// margin-top: 0.96*100rpx;
margin-top: 106rpx;
}
.productSort .conter .listw {
padding-top: 0.2*100rpx;
}
.productSort .conter .listw .title {
height: 0.9*100rpx;
}
.productSort .conter .listw .title .line {
width: 1*100rpx;
height: 0.02*100rpx;
background-color: #999;
}
.productSort .conter .listw .title .name {
font-size: 0.28*100rpx;
color: #333;
margin: 0 0.3*100rpx;
font-weight: bold;
}
.productSort .conter .list {
flex-wrap: wrap;
-ms-flex-wrap: wrap;
}
.productSort .conter .list .item {
width: 1.77*100rpx;
margin-top: 0.26*100rpx;
}
.productSort .conter .list .item .picture {
width: 1.2*100rpx;
height: 1.2*100rpx;
border-radius: 50%;
}
.productSort .conter .list .item .picture image {
width: 100%;
height: 100%;
border-radius: 50%;
}
.productSort .conter .list .item .name {
font-size: 0.24*100rpx;
color: #333;
height: 0.56*100rpx;
line-height: 0.56*100rpx;
width: 1.2*100rpx;
text-align: center;
}
.index .header .search {
display: flex;
justify-content: center;
background-color: #f6f6f6;
color: #C2C5CC;
font-size: 24rpx;
}
.conter .text {
margin-top: 20rpx;
}
.pink-dot {
width: 24rpx;
height: 24rpx;
background: rgba(255, 86, 74, 0.4);
border-radius: 50%;
position: absolute;
z-index: 0;
bottom: 0;
right: -12rpx;
}
.main-title {
font-size: 36rpx;
line-height: 36rpx;
color: #080F1A;
position: relative;
}
.h-line {
width: 56rpx;
height: 0px;
border: 1px solid #999999;
}
.cate-name {
font-size: 30rpx;
color: #999999; //rgba(255,45,105,1);
margin-left: 5*2rpx;
margin-right: 5*2rpx;
}
.shoppingCart {
width: 28*2rpx;
height: 28*2rpx;
background: rgba(255, 45, 105, 1);
border-radius: 50%;
}
.cart-icon {
width: 18*2rpx;
height: 18*2rpx;
}
.img-box {
position: relative;
}
.price-tag {
position: absolute;
top: 0;
left: 0;
// width: 48*2rpx;
// height: 33*2rpx;
// left: -14rpx;
// top: -20rpx;
}
.pro-info {
font-size: 14*2rpx;
}
.market-price {
font-size: 12*2rpx;
color: #C2C5CC;
text-decoration: line-through;
}
.cate-goods-item {
margin-left: 34rpx;
margin-top: 32rpx;
}
.money {
font-size: 24rpx;
color: #FF564A;
font-weight: bold;
}
</style>
+102
View File
@@ -0,0 +1,102 @@
<template>
<view ref="container">
<view class="collectionGoods" v-if="collectProductList.length > 0">
<view
class="item acea-row row-between-wrapper"
v-for="(item, collectProductListIndex) in collectProductList"
:key="collectProductListIndex"
@click="goGoodsCon(item)"
>
<view class="pictrue">
<image :src="item.image" />
</view>
<view class="text acea-row row-column-between">
<view class="infor line1">{{ item.storeName }}</view>
<view class="acea-row row-between-wrapper">
<view class="money font-color-red">{{ item.price }}</view>
<view class="delete" @tap.stop="delCollection(collectProductListIndex)">删除</view>
</view>
</view>
</view>
</view>
<Loading :loaded="loadend" :loading="loading"></Loading>
<view
class="noCommodity"
style="background-color:#fff;"
v-if="collectProductList.length < 1 && page > 1"
>
<view class="noPictrue">
<image :src="webUrl+'/20210203154659687348.png'" class="image" />
</view>
<Recommend></Recommend>
</view>
</view>
</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 {
webUrl:this.$VUE_APP_RESOURCES_URL,
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: {
goGoodsCon(item) {
this.$yrouter.push({
path: "/pages/shop/GoodsCon/index",
query: { id: item.pid }
});
},
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() {
uni.showToast({
title: "删除成功",
icon: "success",
duration: 2000,
complete: () => {
that.collectProductList.splice(index, 1);
that.$set(that, "collectProductList", that.collectProductList);
}
});
});
}
}
};
</script>
File diff suppressed because it is too large Load Diff
+198
View File
@@ -0,0 +1,198 @@
<template>
<view class="evaluate-con">
<view class="goodsStyle acea-row row-between" v-if="orderCon.productInfo">
<view class="pictrue">
<image :src="orderCon.productInfo.image" class="image"/>
</view>
<view class="text acea-row row-between">
<view class="name line2">{{ orderCon.productInfo.storeName }}</view>
<view class="money">
<view>{{ orderCon.productInfo.price }}</view>
<view class="num">x{{ orderCon.cartNum }}</view>
</view>
</view>
</view>
<view class="score">
<view
class="item acea-row row-middle"
v-for="(item, scoreListIndexw) in scoreList"
:key="scoreListIndexw"
>
<view>{{ item.name }}</view>
<view class="starsList">
<text
@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'"
></text>
</view>
<text class="evaluate">{{ item.index === -1 ? "" : item.index + 1 + "分" }}</text>
</view>
<view class="textarea">
<textarea placeholder="商品满足你的期待么?说说你的想法,分享给想买的他们吧~" v-model="expect"></textarea>
<view class="list acea-row row-middle">
<view
class="pictrue"
v-for="(item, uploadPicturesIndex) in uploadPictures"
:key="uploadPicturesIndex"
>
<image :src="item"/>
<text
class="iconfont icon-guanbi1 font-color-red"
@click="uploadPictures.splice(uploadPicturesIndex, 1)"
></text>
</view>
<view class="pictrue uploadBnt acea-row row-center-wrapper row-column" @tap="chooseImage">
<text class="iconfont icon-icon25201"></text>
<view>上传图片</view>
</view>
</view>
</view>
<view class="evaluateBnt bg-color-red" @click="submit">立即评价</view>
</view>
</view>
</template>
<style scoped lang="less">
.evaluate-con .score .textarea .list .pictrue.uploadBnt {
border: 1px solid #ddd;
}
</style>
<script>
import {postOrderComment, postOrderProduct} from "@/api/store";
import {chooseImage, trim} from "@/utils";
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
}
],
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;
},
chooseImage() {
chooseImage(img => {
this.uploadPictures.push(img);
});
},
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(() => {
uni.showToast({
title: "评价成功",
icon: "success",
duration: 2000
});
// ? 回跳到上一页
this.$yrouter.back();
// ? 默认跳转到详情页
// this.$yrouter.push({
// path: "/pages/order/OrderDetails/index",
// query: {
// id: this.orderCon.orderId
// }
// });
// ? 可选重定向到详情页,这时左上角会有一个返回首页的图标
// this.$yrouter.reLaunch({
// path: "/pages/home/index",
// });
})
.catch(err => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
+384
View File
@@ -0,0 +1,384 @@
<template>
<view class="productList" ref="container">
<form @submit.prevent="submitForm">
<view class="search bg-color-red acea-row row-between-wrapper">
<view class="input acea-row row-between-wrapper">
<text class="iconfont icon-sousuo"></text>
<input placeholder="搜索商品信息" v-model="where.keyword" confirm-type="search" @confirm="submitForm"/>
</view>
<view
class="iconfont"
:class="Switch === true ? 'icon-pailie' : 'icon-tupianpailie'"
@click="switchTap"
></view>
</view>
</form>
<view class="nav acea-row row-middle">
<view
class="item"
:class="title ? 'font-color-red' : ''"
@click="set_where(0)"
>{{ title ? title : "默认" }}
</view>
<view class="item" @click="set_where(1)">
价格
<image src="@/static/images/horn.png" v-if="price === 0"/>
<image src="@/static/images/up.png" v-if="price === 1"/>
<image src="@/static/images/down.png" v-if="price === 2"/>
</view>
<view class="item" @click="set_where(2)">
销量
<image src="@/static/images/horn.png" v-if="stock === 0"/>
<image src="@/static/images/up.png" v-if="stock === 1"/>
<image src="@/static/images/down.png" v-if="stock === 2"/>
</view>
<!-- down -->
<view class="item" :class="nows ? 'font-color-red' : ''" @click="set_where(3)">新品</view>
</view>
<view
class="list acea-row row-between-wrapper"
:class="Switch === true ? '' : 'on'"
ref="container"
>
<view
@click="goGoodsCon(item)"
class="item"
:class="Switch === true ? '' : 'on'"
v-for="(item, productListIndex) in productList"
:key="productListIndex"
:title="item.storeName"
>
<view class="pictrue" :class="Switch === true ? '' : 'on'">
<image :src="item.image" :class="Switch === true ? '' : 'on'"/>
</view>
<view class="text" :class="Switch === true ? '' : 'on'">
<view class="name more-t">{{ item.storeName }}</view>
<view class="vip acea-row row-between-wrapper" :class="Switch === true ? '' : 'on'">
<view class="flex ai-end">
<view class="money" :class="Switch === true ? '' : 'on'">
<text class="num" v-if="item.vipPrice && item.vipPrice>0">{{ force2Decimal(item.vipPrice) }}</text>
<text class="num" v-else>{{ force2Decimal(item.price) }}</text>
</view>
<view class="vip-money">{{ force2Decimal(item.otPrice) }}</view>
</view>
<view class="sale">已售{{ item.sales }}</view>
</view>
</view>
</view>
</view>
<Loading :loaded="loadend" :loading="loading"></Loading>
<view
class="noCommodity"
style="background-color: #fff;"
v-if="productList.length === 0 && where.page > 1"
>
<view class="noPictrue">
<image :src="webUrl+'/20210203153900181449.png'" class="image"/>
</view>
</view>
<Recommend v-if="productList.length === 0 && where.page > 1"></Recommend>
</view>
</template>
<script>
import Recommend from "@/components/Recommend";
import {getProducts} from "@/api/store";
import Loading from "@/components/Loading";
import {mapGetters} from 'vuex';
import NP from "number-precision";
export default {
name: "GoodsList",
components: {
Recommend,
Loading
},
props: {},
computed: mapGetters(["userInfo"]),
data: function () {
// const { s = "", id = 0, title = "" } = this.$yroute.query;
const s = "",
id = 0,
title = "";
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
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();
// }
}
},
onLoad: function (e) {
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();
}
this.updateTitle();
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: {
force2Decimal(price) {
return this.$force2Decimal(price);
},
goGoodsCon(item) {
this.$yrouter.push({
path: "/pages/shop/GoodsCon/index",
query: {id: item.id}
});
},
updateTitle() {
// document.title = this.title || this.$yroute.meta.title;
},
get_product_list() {
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.productList.push.apply(that.productList, res.data.map((item) => {
//如果已经登录获取用户信息
if (that.$store.getters.token && that.userInfo) {
var p = NP.times(item.price, NP.divide(parseFloat(that.userInfo.discount), 100))
item.vipPrice = p;
}
return item;
}));
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/index"});
that.nows = false;
that.price = 0;
that.stock = 0;
break;
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 lang="less">
.noCommodity {
border-top: 3px solid #f5f5f5;
padding-bottom: 1px;
}
.list {
.item {
.pictrue {
image {
border-radius: 8rpx;
}
}
.name {
color: #333;
font-size: 26rpx;
font-weight: bold;
}
.money {
font-size: 28rpx;
font-weight: bold;
line-height: 36rpx;
color: #DA0000;
}
.vip-money {
font-size: 22rpx !important;
color: #999 !important;
}
.sale {
font-size: 22rpx;
color: #666;
}
}
}
.list.on {
padding: 0 32rpx;
background: none;
.item {
box-sizing: border-box;
margin-top: 24rpx;
padding: 24rpx 22rpx;
border-bottom: none;
.pictrue {
width: 136rpx !important;
height: 136rpx !important;
}
.text {
display: flex;
flex-direction: column;
justify-content: space-between;
.money {
margin-top: 0;
}
.vip-money {
margin-left: 8rpx;
}
}
}
}
</style>
+78
View File
@@ -0,0 +1,78 @@
<template>
<view class="quality-recommend">
<!-- <view class="slider-banner swiper">
<swiper indicatorDots="true" v-if="banner.length > 0">
<block v-for="(item, imgUrlsIndex) in imgUrls" :key="imgUrlsIndex">
<swiper-item>
<image :src="item.img" class="slide-image" />
</swiper-item>
</block>
</swiper>
</view> -->
<view class="title acea-row row-center-wrapper">
<view class="line"></view>
<view class="name">
<text class="iconfont icon-cuxiaoguanli"></text>促销单品
</view>
<view class="line"></view>
</view>
<Promotion-good :benefit="goodsList"></Promotion-good>
</view>
</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((err) => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: 'none',
duration: 2000
});
});
}
}
};
</script>
+99
View File
@@ -0,0 +1,99 @@
<template>
<view class="quality-recommend">
<view class="title acea-row row-center-wrapper">
<view class="line"></view>
<view class="name">
<text class="iconfont" :class="icon"></text>
{{ name }}
</view>
<view class="line"></view>
</view>
<GoodList :good-list="goodsList" :is-sort="false"></GoodList>
</view>
</template>
<script>
import GoodList from "@/components/GoodList";
import {getGroomList} from "@/api/store";
import NP from "number-precision";
import {mapGetters} from 'vuex';
export default {
name: "HotNewGoods",
components: {
GoodList
},
props: {},
computed: mapGetters(["userInfo"]),
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;
that.goodsList = res.data.list.map((goods) => {
// goods.vipPrice = _this.$force2Decimal(goods.vipPrice);
if (that.$store.getters.token && that.userInfo) {
var p = NP.times(goods.price, NP.divide(parseFloat(that.userInfo.discount), 100))
goods.vipPrice = p;
}
return goods;
})
that.goodsList=[{storeName:3}]
})
.catch((err) => {
// uni.showToast({
// title: err.msg || err.response.data.msg || err.response.data.message,
// icon: 'none',
// duration: 2000
// });
});
}
}
};
</script>
+721
View File
@@ -0,0 +1,721 @@
<template>
<view class="shoppingCart">
<!-- <hx-navbar
title="购物车"
:fixed="true"
:back="false"
:left-slot="false"
:right-slot="false"
color="#ffffff"
statusBarFontColor="#ffffff"
:bgImgHeight="bgImgHeight"
:background-color="[254,82,97]"
:background-img="webUrl+'/20200729160752671638.png'"/> -->
<hx-navbar
title="购物车"
:fixed="true"
:back="false"
:left-slot="true"
:right-slot="true"
color="#333333"
statusBarFontColor="#ffffff"
:background-color="[255,255,255]"
>
<block slot="left">
<view style="padding-left: 30rpx;" class="top-delete-btn acea-row row-middle" @click="delgoods">
<image class="delete-icon" :src="webUrl+'/20210806133058078099.png'" mode=""></image>
</view>
</block>
</hx-navbar>
<view v-if="false" class="nav acea-row row-between-wrapper" style="border-top: 1px solid #f5f5f5">
<view>
<text class="num" style="color: #666666;">{{ count }}件商品</text>
</view>
<!-- <view
v-if="cartList.valid.length > 0"
class="administrate acea-row row-center-wrapper font-color-white"
@click="manage"
>{{ footerswitch ? '取消' : '管理' }}</view> -->
<view class="top-delete-btn acea-row row-middle" @click="delgoods">
<image class="delete-icon" :src="webUrl+'/20210806133058078099.png'" mode=""></image>
</view>
</view>
<view style="border-top: 1px solid #f5f5f5" v-if="$store.getters.token||userInfo.uid">
<!-- <view style="margin-top: 80rpx;" v-if="$store.getters.token||userInfo.uid"> -->
<!-- <view class="labelNav acea-row row-around row-middle">
<view class="item">
<text class="iconfont icon-xuanzhong"></text>100%正品保证
</view>
<view class="item">
<text class="iconfont icon-xuanzhong"></text>所有商品精挑细选
</view>
<view class="item">
<text class="iconfont icon-xuanzhong"></text>售后无忧
</view>
</view> -->
<view v-if="validList.length > 0 || cartList.invalid.length > 0">
<view class="list">
<view
class="item acea-row row-between-wrapper"
v-for="(item, cartListValidIndex) in validList"
:key="cartListValidIndex"
>
<view class="select-btn">
<view class="checkbox-wrapper">
<checkbox-group @change="switchSelect(cartListValidIndex)">
<label class="well-check">
<checkbox :checked="item.checked" color="#fff"
style="border-radius: 50%;transform:scale(0.7)"></checkbox>
</label>
</checkbox-group>
</view>
</view>
<view class="picTxt acea-row row-between">
<view class="pictrue" @click="goGoodsCon(item)">
<image :src="item.productInfo.attrInfo.image" v-if="item.productInfo.attrInfo.image"/>
<image :src="item.productInfo.image" v-else/>
</view>
<view class="text acea-row row-column-between">
<view class="line1">{{ item.productInfo.storeName }}</view>
<view class="acea-row row-middle row-left">
<!-- height: 38rpx; -->
<view
class="infor"
style="background-color: #FFF3F2;border-radius: 19rpx;padding: 4rpx 20rpx;"
v-if="item.productInfo.attrInfo"
>规格{{ item.productInfo.attrInfo.sku }}
</view>
</view>
<view class="money" style="color: #FF564A !important;">{{ force2Decimal(item.truePrice) }}</view>
</view>
<view class="carnum acea-row row-middle row-between">
<view
class="reduce"
:class="validList[cartListValidIndex].cartNum <= 1 ? 'on' : ''"
@click.prevent="reduce(cartListValidIndex)"
></view>
<view class="num">{{ item.cartNum }}</view>
<view
class="plus"
v-if="validList[cartListValidIndex].attrInfo"
:class="validList[cartListValidIndex].cartNum >= validList[cartListValidIndex].attrInfo.stock ? 'on' : ''"
@click.prevent="plus(cartListValidIndex)"
></view>
<view
class="plus"
v-else
:class="validList[cartListValidIndex].cartNum >= validList[cartListValidIndex].stock ? 'on' : ''"
@click.prevent="plus(cartListValidIndex)"
></view>
</view>
</view>
</view>
</view>
<!-- 失效商品开始 -->
<view class="invalidGoods" v-if="cartList.invalid.length > 0">
<view class="goodsNav acea-row row-between-wrapper">
<view @click="goodsOpen">
<text
class="iconfont"
:class="goodsHidden === true ? 'icon-xiangyou' : 'icon-xiangxia'"
></text>
失效商品
</view>
<view class="del" @click="delInvalidGoods">
<text class="iconfont icon-shanchu1"></text>
清空
</view>
</view>
<view class="goodsList" :hidden="goodsHidden">
<view
v-for="(item, cartListinvalidIndex) in cartList.invalid"
:key="cartListinvalidIndex"
>
<view
@click="goGoodsCon(item)"
class="item acea-row row-between-wrapper"
v-if="item.productInfo"
>
<view class="invalid acea-row row-center-wrapper">失效</view>
<view class="pictrue">
<image :src="item.productInfo.attrInfo.image" v-if="item.productInfo.attrInfo"/>
<image :src="item.productInfo.image" v-else/>
</view>
<view class="text acea-row row-column-between">
<view class="line1">{{ item.productInfo.storeName }}</view>
<view
class="infor line1"
v-if="item.productInfo.attrInfo"
>属性{{ item.productInfo.attrInfo.sku }}
</view>
<view class="acea-row row-between-wrapper">
<view class="end">该商品已下架</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 失效商品结束 -->
</view>
<!--购物车暂无商品-->
<view class="noCart" v-if="cartList.valid.length === 0 && cartList.invalid.length === 0">
<view class="pictrue">
<image :src="webUrl+'/20210203153734554332.png'"/>
</view>
<Recommend></Recommend>
</view>
<view style="height:210rpx"></view>
<view class="footer" v-if="cartList.valid.length > 0">
<view class="footer-content acea-row row-between-wrapper">
<view class="acea-row row-middle row-between" style="flex: 1;flex-wrap: nowrap;">
<view class="select-btn">
<view class="checkbox-wrapper">
<!-- <label class="well-check">
<input
type="checkbox"
name
value
:checked="isAllSelect && cartCount > 0"
@click="allChecked"
/>
<i class="icon"></i>
<text class="checkAll">全选 ({{ cartCount }})</text>
</label>-->
<checkbox-group @change="allChecked">
<label class="well-check">
<checkbox style="transform:scale(0.7)" value="allSelect" :checked="isAllSelect && cartCount > 0"
color="#fff"></checkbox>
<text class="checkAll" style="color: #666666;">全选 ({{ cartCount }})</text>
</label>
</checkbox-group>
</view>
</view>
<view class="acea-row row-middle" style="margin-left: 20rpx">
<text style="color: #000000;font-size: 28rpx;font-weight: bold;">合计:</text>
<text style="color: #FF564A;font-size: 24rpx;"></text>
<text class="" style="font-size: 32rpx;color: #FF564A;">{{ force2Decimal(countmoney) }}</text>
</view>
</view>
<!-- <view class="money acea-row row-middle" v-if="footerswitch === false"> -->
<view class="money acea-row row-center row-middle" style="background: #FF564A;
height: 100%;
width: 198rpx;
text-align: center;
margin-right: -30rpx;flex-shrink: 0;margin-left: 10rpx;">
<!-- <view class="vline"></view> -->
<view class="placeOrder" @click="placeOrder">结算</view>
</view>
<!-- <view class="button acea-row row-middle" style="position: relative;" v-else>
<view class="vline"></view>
<view class="bnt cart-color" @click="collectAll">收藏</view>
<view class="bnt" @click="delgoods">删除</view>
</view> -->
</view>
</view>
</view>
</view>
</template>
<script>
import Recommend from "@/components/Recommend";
import {mapGetters} from "vuex";
import {changeCartNum, getCartCount, getCartList, postCartDel} from "@/api/store";
import {postCollectAll} from "@/api/user";
import {add, mul} from "@/utils/bc";
import cookie from "@/utils/store/cookie";
const CHECKED_IDS = "cart_checked";
var that;
export default {
name: "ShoppingCart",
components: {
Recommend
},
props: {},
data: function () {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
cartList: {
invalid: [],
valid: []
},
bgImgHeight: '20px',
validList: [],
isAllSelect: false,
cartCount: 0,
countmoney: 0,
goodsHidden: true,
footerswitch: false,
count: 0,
checkedIds: [],
loaded: false
};
},
computed: mapGetters(["userInfo", "token"]),
// 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;
// }
// },
watch: {
userInfo(user) {
if (user.uid) {
this.carnum();
this.countMoney();
this.getCartList();
this.gainCount();
}
},
token(token) {
if (this.userInfo.uid) {
this.carnum();
this.countMoney();
this.getCartList();
this.gainCount();
}
},
cartList(list) {
this.validList = list.valid;
}
},
onShow: function () {
this.carnum();
this.countMoney();
this.getCartList();
this.gainCount();
},
onLoad: function () {
that = this;
uni.getSystemInfo({
success: (e) => {
// this.compareVersion(e.SDKVersion, '2.5.0')
let statusBar = 0;
let customBar = 0;
// #ifdef MP
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + 45
if (e.platform === 'android') {
//this.$store.commit('SET_SYSTEM_IOSANDROID', false)
customBar = e.statusBarHeight + 50
}
// #endif
// #ifdef MP-WEIXIN
statusBar = e.statusBarHeight
// @ts-ignore
//uni.getMenuButtonBoundingClientRect();
const custom = uni.getMenuButtonBoundingClientRect()
customBar = custom.bottom + custom.top - e.statusBarHeight
// #endif
// #ifdef MP-ALIPAY
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + e.titleBarHeight
// #endif
// #ifdef APP-PLUS
console.log('app-plus', e)
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + 45
// #endif
// #ifdef H5
statusBar = 0
customBar = e.statusBarHeight + 45
// #endif
// 这里你可以自己决定存放方式,建议放在store中,因为store是实时变化的
// this.$store.commit('SET_STATUS_BAR', statusBar)
// this.$store.commit('SET_CUSTOM_BAR', customBar)
// this.$store.commit('SET_SYSTEM_INFO', e)
// //两列商品宽度
// that.hotGoodsColumnWidth = (e.screenWidth - uni.upx2px(90))/2+'px';
//状态栏图片高度
that.bgImgHeight = statusBar + 'px';
}
});
},
methods: {
force2Decimal(v) {
return this.$force2Decimal(v);
},
goGoodsCon(item) {
this.$yrouter.push({
path: "/pages/shop/GoodsCon/index",
query: {
id: item.productId
}
});
},
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) {
uni.showToast({
title: "请选择产品",
icon: "none",
duration: 2000
});
return;
}
uni.showModal({
title: '确认删除已选商品?',
content: '',
showCancel: true,
cancelText: '取消',
confirmText: '确认',
success: res => {
uni.showLoading();
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();
}).finally(() => {
uni.hideLoading();
});
},
fail: () => {
},
complete: () => {
}
});
},
// //获取数量
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) {
uni.showToast({
title: "请选择产品",
icon: "none",
duration: 2000
});
return;
}
postCollectAll(data).then(function () {
uni.showToast({
title: "收藏成功!",
icon: "none",
duration: 2000
});
});
},
//立即下单;
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) {
uni.showToast({
title: "请选择产品",
icon: "none",
duration: 2000
});
return;
}
this.$yrouter.push({
path: "/pages/order/OrderSubmission/index",
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) {
uni.showToast({
title: "不能再少了!",
icon: "none",
duration: 2000
});
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();
this.gainCount();
})
.catch(error => {
this.gainCount();
uni.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.gainCount();
that.countMoney();
},
//全选
allChecked: function (e) {
console.log(e);
let that = this;
let selectAllStatus = e.mp.detail.value[0] == "allSelect" ? true : false;
console.log(selectAllStatus);
// 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;
console.log(this.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>
<style scoped lang="less">
.plus {
background-image: url("~@/static/images/num_plus_icon.png");
background-repeat: no-repeat;
background-size: 100% 100%;
border: none !important;
width: 38rpx !important;
height: 38rpx !important;
}
.reduce {
background-image: url("~@/static/images/num_minus_icon.png");
background-repeat: no-repeat;
background-size: 100% 100%;
border: none !important;
width: 38rpx !important;
height: 38rpx !important;
}
.shoppingCart .list .item .picTxt .text .money {
color: #feb655 !important;
}
.vline {
width: 0px;
height: 36rpx;
border-left: 1px solid rgba(255, 255, 255, 0.6);
margin: 26rpx 30rpx 26rpx 0;
}
.top-delete-btn {
padding: 10rpx;
//background:rgba(255,187,225,0.4);
//border-radius:12rpx;
}
.delete-icon {
width: 36rpx;
height: 36rpx;
}
.shoppingCart .footer-content {
background: #fff !important;
border-radius: 0 !important;
margin: 0 !important;
}
.shoppingCart .footer {
height: auto !important;
}
</style>
+196
View File
@@ -0,0 +1,196 @@
<template>
<view>
<view class="storeBox" ref="container">
<view
class="storeBox-box"
v-for="(item, index) in storeList"
:key="index"
@click="checked(item)"
>
<view class="store-img">
<img :src="item.image" lazy-load="true"/>
</view>
<view class="store-cent-left">
<text class="store-name">{{ item.name }}</text>
<text class="store-address line1">{{ item.address }}</text>
</view>
<view class="row-right">
<view>
<a class="store-phone" :href="'tel:' + item.phone">
<text class="iconfont icon-dadianhua01"></text>
</a>
</view>
<view class="store-distance" @click="showMaoLocation(item)">
<text class="addressTxt" v-if="item.distance">距离{{ item.distance }}千米</text>
<text class="addressTxt" v-else>查看地图</text>
<text class="iconfont icon-youjian"></text>
</view>
</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
</view>
</view>
</template>
<script>
import Loading from "@/components/Loading";
import {storeListApi} from "@/api/store";
import {mapGetters} from "vuex";
import cookie from "@/utils/store/cookie";
const LONGITUDE = "user_longitude";
const LATITUDE = "user_latitude";
const MAPKEY = "mapKey";
export default {
name: "storeList",
components: {Loading},
computed: mapGetters(["location", "goName"]),
data() {
return {
page: 1,
limit: 20,
loaded: false,
loading: false,
storeList: [],
mapShow: false,
system_store: {},
mapKey: cookie.get(MAPKEY),
locationShow: false
};
},
mounted() {
this.getList();
},
onReachBottom() {
!this.loading && this.getOrderList();
},
methods: {
showMaoLocation(data) {
this.$yrouter.push({
path: "/pages/map/index",
query: data
});
},
// 选中门店
checked(e) {
if (this.goName === "orders") {
this.$store.commit("get_store", e);
this.$yrouter.back();
}
},
// 获取门店列表数据
getList: function () {
if (this.loading || this.loaded) return;
this.loading = true;
let data = {
latitude: this.location.latitude, //纬度
longitude: this.location.longitude, //经度
page: this.page,
limit: this.limit
};
storeListApi(data)
.then(res => {
this.loading = false;
this.loaded = res.data.list.length < this.limit;
this.storeList.push.apply(this.storeList, res.data.list);
this.page = this.page + 1;
this.mapKey = res.data.mapKey;
})
.catch(err => {
this.$dialog.error(err.msg);
});
}
}
};
</script>
<style scoped lang="less">
.geoPage {
position: fixed;
width: 100%;
height: 100%;
top: 0;
z-index: 10000;
}
.storeBox {
background-color: #fff;
padding: 0 0.3 * 100rpx;
}
.storeBox-box {
width: 100%;
height: auto;
display: flex;
align-items: center;
padding: 0.23 * 100rpx 0;
justify-content: space-between;
border-bottom: 1px solid #eee;
}
.store-cent {
display: flex;
align-items: center;
width: 80%;
}
.store-cent-left {
width: 45%;
text {
display: block;
}
}
.store-img {
width: 1.2 * 100rpx;
height: 1.2 * 100rpx;
border-radius: 0.06 * 100rpx;
margin-right: 0.22 * 100rpx;
}
.store-img img {
width: 100%;
height: 100%;
}
.store-name {
color: #282828;
font-size: 0.3 * 100rpx;
margin-bottom: 0.22 * 100rpx;
font-weight: 800;
}
.store-address {
color: #666666;
font-size: 0.24 * 100rpx;
}
.store-phone {
width: 0.5 * 100rpx;
height: 0.5 * 100rpx;
color: #fff;
border-radius: 50%;
display: block;
text-align: center;
line-height: 0.5 * 100rpx;
background-color: #e83323;
margin-bottom: 0.22 * 100rpx;
}
.store-distance {
font-size: 0.22 * 100rpx;
color: #e83323;
}
.iconfont {
font-size: 0.2 * 100rpx;
}
.row-right {
display: flex;
flex-direction: column;
align-items: flex-end;
width: 33.5%;
}
</style>
+73
View File
@@ -0,0 +1,73 @@
<template>
<view class="CustomerList">
<view
class="item acea-row row-between-wrapper"
v-for="item in list"
:key="item.id"
@click="goCustomerService(item)"
>
<view class="pictrue">
<image :src="item.avatar" />
</view>
<view class="text line1">{{ item.nickname }}</view>
</view>
</view>
</template>
<script>
import { serviceList } from "@/api/user";
export default {
name: "CustomerList",
data() {
return {
list: []
};
},
methods: {
goCustomerService(item) {
this.$yrouter.push({
path: "/pages/user/CustomerService/index",
query: { id: item.uid }
});
},
getList() {
serviceList().then(res => {
this.list = res.data;
});
}
},
mounted() {
this.getList();
}
};
</script>
<style scoped lang="less">
.CustomerList {
margin-top: 0.13*100rpx;
}
.CustomerList .item {
height: 1.38*100rpx;
border-bottom: 1px solid #eee;
padding: 0 0.24*100rpx;
background-color: #fff;
}
.CustomerList .item .pictrue {
width: 0.9*100rpx;
height: 0.9*100rpx;
border-radius: 50%;
border: 0.03*100rpx solid #fff;
box-shadow: 0 0 0.1*100rpx 0.05*100rpx #f3f3f3;
-webkit-box-shadow: 0 0 0.1*100rpx 0.05*100rpx #f3f3f3;
-moz-box-shadow: 0 0 0.1*100rpx 0.05*100rpx #f3f3f3;
}
.CustomerList .item .pictrue image{
width: 100%;
height: 100%;
border-radius: 50%;
}
.CustomerList .item .text {
width: 5.82*100rpx;
font-size: 0.32*100rpx;
color: #000;
}
</style>
+332
View File
@@ -0,0 +1,332 @@
<template>
<view class="register absolute">
<view class="shading">
<view class="pictrue acea-row row-center-wrapper">
<image :src="`${staticUrl}/logo.png`" />
</view>
</view>
<view class="whiteBg" v-if="formItem === 1">
<view class="title acea-row row-center-wrapper">
<view
class="item"
:class="current === index ? 'on' : ''"
v-for="(item, index) in navList"
@click="navTap(index)"
:key="index"
>{{ item }}</view>
</view>
<view class="list" :hidden="current !== 0">
<form @submit.prevent="submit">
<view class="item">
<view class="acea-row row-between-wrapper">
<!-- <svg class="icon" aria-hidden="true">
<use xlink:href="#icon-phone_" />
</svg>-->
<input type="text" placeholder="输入手机号码" v-model="account" required />
</view>
</view>
<view class="item">
<view class="acea-row row-between-wrapper">
<!-- <svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_" />
</svg>-->
<input type="password" placeholder="填写登录密码" v-model="password" required />
</view>
</view>
</form>
</view>
<view class="list" :hidden="current !== 1">
<view class="item">
<view class="acea-row row-between-wrapper">
<!-- <svg class="icon" aria-hidden="true">
<use xlink:href="#icon-phone_" />
</svg>-->
<input type="text" placeholder="输入手机号码" v-model="account" />
</view>
</view>
<view class="item">
<view class="align-left">
<!-- <svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_1" />
</svg>-->
<input type="text" placeholder="填写验证码" class="codeIput" v-model="captcha" />
<button
class="code"
:disabled="disabled"
:class="disabled === true ? 'on' : ''"
@click="code"
>{{ text }}</button>
</view>
</view>
</view>
<view class="logon" @click="loginMobile" :hidden="current !== 1">登录</view>
<view class="logon" @click="submit" :hidden="current === 1">登录</view>
<view class="tip">
没有账号?
<text @click="formItem = 2" class="font-color-red">立即注册</text>
</view>
</view>
<view class="whiteBg" v-else>
<view class="title">注册账号</view>
<view class="list">
<view class="item">
<view>
<!-- <svg class="icon" aria-hidden="true">
<use xlink:href="#icon-phone_" />
</svg>-->
<input type="text" placeholder="输入手机号码" v-model="account" />
</view>
</view>
<view class="item">
<view class="align-left">
<!-- <svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_1" />
</svg>-->
<input type="text" placeholder="填写验证码" class="codeIput" v-model="captcha" />
<button
class="code"
:disabled="disabled"
:class="disabled === true ? 'on' : ''"
@click="code"
>{{ text }}</button>
</view>
</view>
<view class="item">
<view>
<!-- <svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_" />
</svg>-->
<input type="password" placeholder="填写您的登录密码" v-model="password" />
</view>
</view>
<view class="item">
<view>
<!-- <svg class="icon" aria-hidden="true">
<use xlink:href="#icon-phone_" />
</svg>-->
<input type="text" placeholder="输入邀请码" v-model="inviteCode" />
</view>
</view>
</view>
<view class="logon" @click="register">注册</view>
<view class="tip">
已有账号?
<text @click="formItem = 1" class="font-color-red">立即登录</text>
</view>
</view>
<view class="bottom"></view>
</view>
</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";
import { handleGetUserInfo } from "@/utils";
const BACK_URL = "login_back_url";
export default {
name: "Login",
mixins: [sendVerifyCode],
data: function() {
return {
staticUrl: this.$STATIC_RESOURCE_URL,
navList: ["账号登录"],
current: 0,
account: "",
password: "",
captcha: "",
inviteCode: "",
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));
handleGetUserInfo();
})
.catch(err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: "none",
duration: 2000
});
});
},
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,
inviteCode: that.inviteCode,
spread: cookie.get("spread")
})
.then(res => {
uni.showToast({
title: res.msg,
icon: "success",
duration: 2000
});
that.formItem = 1;
})
.catch(err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: "none",
duration: 2000
});
});
},
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 => {
uni.showToast({
title: res.msg,
icon: "success",
duration: 2000
});
that.sendCode();
})
.catch(err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: "none",
duration: 2000
});
});
},
navTap: function(index) {
this.current = index;
},
async submit() {
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));
handleGetUserInfo();
// let replace=this.$yroute.query.replace
// if(replace){
// }
// this.$yrouter.replace({
// path: this.$yroute.query.replace || '/pages/home/index'
// });
})
.catch(err => {
console.log(err);
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
@@ -0,0 +1,39 @@
<template>
<view class="container">
<view class="content">
<view v-if="userInfo && userInfo.levelExplain" v-html="userInfo.levelExplain"></view>
</view>
</view>
</template>
<script>
import { mapGetters } from "vuex";
export default {
data() {
return {
}
},
computed: mapGetters(["userInfo"]),
onLoad:function(e){
},
onShow:function(){
this.$store.dispatch("getUser", true);
},
methods: {
}
}
</script>
<style>
.content{
background-color: #fff;
margin: 20rpx;
padding:20rpx;
font-size: 30rpx;
font-weight: normal;
border-radius: 10rpx;
}
</style>
+164
View File
@@ -0,0 +1,164 @@
<template>
<view class="messageList">
<mescroll-body ref="mescrollRef" top="16rpx" bottom="0" class='cotent-scroll' :up="upOption" :down="downOption" @up="upCallback" @down="downCallback" @init="mescrollInit" @emptyclick="emptyClick">
<view class="acea-row row-column">
<view
@click="toDetail(msg.id)"
class="acea-row message-box"
v-for="(msg, index) in list"
:key="index"
>
<view class="acea-row row-between row-middle">
<view class="title line1">{{msg.noticeTitle}}</view>
<!-- <div class="date">{{dataFormat(msg.createdTime,true)}}</div> -->
<view class="date">{{dataFormat(msg.noticeTime/1000,true)}}</view>
</view>
<view class="acea-row row-middle row-between">
<view class="content line1" v-html="msg.noticeContent"></view>
<view v-if="msg.readFlag=='RF0'" class="unread-dot"></view>
</view>
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import { noticeList } from "@/api/user";
import { isWeixin, dataFormat } from "@/utils";
import MescrollMixins from "@/mixins/mescroll-mixins.js";
import MescrollBody from "@/components/mescroll-uni/mescroll-body.vue";
export default {
components:{
MescrollBody
},
data() {
return {
list:[
// {
// noticeTitle:'ddjifjiejfiejife',
// noticeTime:'2020-09-09',
// noticeContent:'djdifjeijfiejifef'
// }
],
upOption:{
noMoreSize: 10, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
auto:true,
empty:{
tip: '暂无消息' // 提示
// btnText:'点击刷新'
}
},
downOption:{
auto:false
}
}
},
mixins:[
MescrollMixins({
getPageData(mescroll){
var _this = this;
// 此时mescroll会携带page的参数:
let pageNum = mescroll.num; // 页码, 默认从1开始
let pageSize = mescroll.size; // 页长, 默认每页10条
var params = {
limit:pageSize,
page:pageNum
}
// mescroll.endByPage(0, 0);
// return;
noticeList(params)
.then(res => {
if(mescroll.num == 1) {
_this.list = []; //如果是第一页需手动制空列表
}
_this.list = _this.list.concat(res.data);//追加新数据
mescroll.endSuccess(res.data.length);
})
.catch(err => {
mescroll.endErr();
uni.showToast({
title: err + '',
icon: 'none',
mask: false,
duration: 1500
});
})
}
})
],
methods: {
dataFormat,
toDetail(mid){
this.$yrouter.push('/pages/user/MessageDetail/MessageDetail?id='+mid);
// this.$yrouter.push({
// path: "/pages/user/MessageDetail/MessageDetail",
// query: {
// id:mid
// }
// });
}
},
onLoad:function(e){
},
onShow:function(){
//静默刷新
this.mescroll && this.mescroll.resetUpScroll(false);
}
}
</script>
<style scoped lang="less">
page{
background-color: #fff;
}
.messageList{
padding: 0.32*100rpx;
background-color: #FFFFFF;
}
.message-box{
background:rgba(246,247,250,1);
border-radius:0.12*100rpx;
padding: 0.24*100rpx;
margin-bottom: 0.4*100rpx;
display: block;
// width: 100%;
}
.unread-dot{
position: absolute;
right: 0.2*100rpx;
top: auto;
flex-shrink: 0;
width:0.16*100rpx;
height:0.16*100rpx;
background:rgba(255,26,26,1);
border-radius:50%;
}
.content{
flex: 1;
color: #8B8F99;
font-size: 0.24*100rpx;
margin-top: 0.08*100rpx;
}
.date{
font-size:0.24*100rpx;
font-weight: bold;
color:rgba(139,143,153,1);
flex-shrink: 0;
color: #8B8F99;
}
.title{
flex: 1;
}
</style>
@@ -0,0 +1,90 @@
<template>
<view>
<view class="message">
<view class="title">{{messageInfo.noticeTitle}}</view>
<view class="date">{{dataFormat(messageInfo.noticeTime/1000,true)}}</view>
<view class="content" v-html="messageInfo.noticeContent"></view>
</view>
</view>
</template>
<script>
import { noticeDetail } from "@/api/user";
import { dataFormat } from "@/utils";
export default {
data() {
return {
id:0,
messageInfo:{}
}
},
methods: {
dataFormat,
getData:function(){
let that = this;
const id = this.id;
if (!id) {
uni.showToast({
title:"消息id不存在",
icon: "none",
duration: 2000
});
return;
}
noticeDetail({
id:this.id
}).then((res)=>{
that.messageInfo = res.data;
}).catch((err)=>{
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
})
}
},
onLoad:function(e){
this.id = e.id;
this.getData();
}
}
</script>
<style lang="less">
page{
background-color: #fff !important;
}
.message{
padding: 0.36*100rpx;
}
.title{
font-size:0.36*100rpx;
font-weight: bold;
color:rgba(8,15,26,1);
}
.date{
font-size:0.24*100rpx;
font-weight: bold;
color:rgba(139,143,153,1);
margin-top: 0.24*100rpx;
margin-bottom: 0.4*100rpx;
}
.content{
padding: 0.1*100rpx;
color: #080F1A;
}
</style>
@@ -0,0 +1,217 @@
<template>
<view class="container">
<view class="content acea-row row-column">
<input class="phone-input" type="text" :value="phone" disabled/>
<view class="acea-row row-middle" style="flex-wrap: nowrap;">
<input type="text" placeholder="填写验证码" placeholder-style="color:#DADCE0;font-size:28rpx;" class="codeIput" v-model="captcha" />
<button
class="code acea-row row-middle"
:disabled="disabled"
:class="disabled === true ? 'on' : ''"
@click="code"
>{{ text }}</button>
</view>
<input type="number" maxlength="6" password placeholder="请输新6位数字支付密码" placeholder-style="color:#DADCE0;font-size:28rpx" class="payPwdInput" v-model="payPwd" @input='inputPaypwdChange' />
</view>
<view class="confirmBnt bg-color-red" @click="confirm()">保存</view>
</view>
</view>
</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 { getUserInfo, registerVerify, bindingPhone,modifyUserPayPwd } from "@/api/user";
export default {
data() {
return {
captcha: "",
phone:'',
payPwd:''
}
},
mixins: [sendVerifyCode],
watch:{
userInfo(){
this.phone = this.userInfo.phone;
}
},
computed:{
...mapGetters(["userInfo"]),
},
onLoad:function(e){
if (e.isSetMode) {
uni.setNavigationBarTitle({
title: '设置支付密码'
});
} else{
uni.setNavigationBarTitle({
title: '修改支付密码'
});
}
//获取用户信息
if (this.$store.getters.token) {
this.$store.dispatch("getUser", true);
}
},
methods: {
inputPaypwdChange:function(event){
var value = event.target.value;
var filterValue = value.replace(/\D/g,"");
//console.log('value:'+filterValue);
this.payPwd = filterValue; // 不允许输入非数字字符
},
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 => {
uni.showToast({
title: res.data,
icon: "none",
duration: 2000
});
that.sendCode();
})
.catch(res => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
async confirm() {
let that = this;
const { phone, captcha, payPwd } = 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("验证码"))
],
payPwd: [
required(required.message("支付密码")),
alpha_num(alpha_num.message("支付密码"))
]
})
.validate({ phone, captcha,payPwd });
} catch (e) {
return validatorDefaultCatch(e);
}
//网络请求
uni.showLoading();
modifyUserPayPwd({
passwordPay:that.payPwd,
code:that.captcha,
phone:that.phone
}).then((res)=>{
//提示成功并返回
uni.hideLoading();
that.$dialog.toast({ mes: "保存成功" });
setTimeout(function(){
that.$yrouter.back();
},1000);
}).catch((err)=>{
uni.hideLoading();
that.$dialog.error(err.msg || "修改失败");
})
}
}
}
</script>
<style>
page{
background: #fff;
}
.container{
background: #fff;
}
.confirmBnt {
font-size: 32rpx;
width: 580rpx;
height: 90rpx;
border-radius: 45rpx;
color: #fff;
margin: 92rpx auto 0 auto;
text-align: center;
line-height: 90rpx;
}
.content{
margin: 114rpx;
}
.phone-input{
color: #8B8F99;
font-size: 36rpx;
height:88rpx;
background:rgba(247,247,249,1);
opacity:1;
border-radius:12rpx;
margin-bottom: 32rpx;
}
.codeIput{
font-size: 28rpx;
height:88rpx;
border:1px solid rgba(218,220,224,1);
opacity:1;
border-radius:12rpx;
flex-grow: 1;
}
.code{
/* width:224rpx; */
height:88rpx;
background:rgba(121,129,253,1);
opacity:1;
color: #fff;
font-size: 28rpx;
border-radius:12rpxpx;
flex-shrink: 0;
margin-left: 16rpx;
text-align: center;
padding-left: 24rpx;
padding-right: 24rpx;
}
.payPwdInput{
font-size: 28rpx;
height:88rpx;
border:1px solid rgba(218,220,224,1);
opacity:1;
border-radius:12rpx;
margin-top: 32rpx;
}
</style>
+335
View File
@@ -0,0 +1,335 @@
<template>
<view>
<view class="payment-top acea-row row-column row-center-wrapper">
<text class="name">我的余额</text>
<view class="pic">
<text>
<text class="pic-font">{{ now_money || 0 }}</text>
</text>
</view>
</view>
<view class="recharge">
<view class="nav acea-row row-around row-middle">
<view class="item on">账户充值</view>
</view>
<view class="info-wrapper">
<view class="picList acea-row row-between mt-20">
<view
class="pic-box pic-box-color acea-row row-center-wrapper row-column"
:class="activePic === index ? 'pic-box-color-active' : ''"
v-for="(item, index) in picList"
:key="index"
@click="picCharge(index, item)"
>
<view class="pic-number-pic">
<text>
{{ item.value.price }}
<text class="pic-number"></text>
</text>
</view>
<view class="pic-number" v-if="item.value.give_price > 0">赠送{{ item.value.give_price }} </view>
</view>
<!-- <view
class="pic-box pic-box-color acea-row row-center-wrapper"
@click="picCharge(picList.length, money)"
>
<input
type="number"
placeholder="其他"
v-model="money"
class="pic-box-money pic-number-pic"
/>
</view> -->
</view>
<view class="tip">提示充值后帐户的金额不能提现</view>
<view class="pay-btn bg-color-red" @click="recharge">立即充值</view>
</view>
</view>
</view>
</template>
<script>
import { mapGetters } from "vuex";
import { weappPay } from "@/libs/wechat";
import { rechargeWechat, getRechargeApi } from "@/api/user";
import { add, sub } from "@/utils/bc";
export default {
name: "Recharge",
components: {},
props: {},
data: function() {
return {
active: 0,
from: this.$deviceType,
money: "",
now_money: "",
picList: [],
activePic: 0,
numberPic: "",
paid_price: "",
rechar_id: 0
};
},
computed: mapGetters(["userInfo"]),
mounted: function() {
this.now_money = this.userInfo.nowMoney;
this.getRecharge();
},
methods: {
/**
* 充值额度选择
*/
getRecharge() {
getRechargeApi()
.then(res => {
this.picList = res.data.recharge_price_ways || [];
if (this.picList[0]) {
this.rechar_id = this.picList[0].id;
this.paid_price = this.picList[0].value.price;
this.numberPic = this.picList[0].value.give_price;
}
})
.catch(res => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
});
},
/**
* 选择金额
*/
picCharge(idx, item) {
this.activePic = idx;
if (idx == this.picList.length) {
this.rechar_id = 0;
this.paid_price = "";
this.numberPic = "";
} else {
this.money = "";
this.rechar_id = item.id;
this.paid_price = item.value.give_price;
this.numberPic = item.value.price;
}
},
recharge: function() {
let that = this,
price = Number(this.money);
if (this.picList.length == this.activePic && price === 0) {
uni.showToast({
title: "请输入您要充值的金额",
icon: "none",
duration: 2000
});
return;
} else if (this.picList.length == this.activePic && price < 0.01) {
uni.showToast({
title: "充值金额不能低于0.01",
icon: "none",
duration: 2000
});
return;
}
let prices = "",
paid_price = "";
if (price) {
prices = price;
paid_price = 0;
} else {
prices = that.numberPic;
paid_price = that.paid_price;
}
rechargeWechat({
price: prices,
from: that.from,
paid_price: paid_price,
rechar_id: that.rechar_id
})
.then(res => {
console.log(res);
var data = res.data.data;
weappPay(res.data.data)
.then(() => {
prices = add(prices, paid_price);
that.now_money = add(prices, parseFloat(that.userInfo.nowMoney));
uni.showToast({
title: "支付成功",
icon: "success",
duration: 2000
});
this.$yrouter.back();
})
.finally(res => {
//if(typeof(res) == "undefined") return
uni.showToast({
title: res,
icon: "none",
duration: 2000
});
})
.catch(function() {
uni.showToast({
title: "支付失败",
icon: "none",
duration: 2000
});
});
})
.catch(err => {
console.log(err);
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
<style scoped lang="less">
#iframe {
display: none;
}
.pic-box-color-active {
background-color: #eb3729 !important;
color: #fff !important;
}
.picList {
margin-bottom: 0.3 * 100rpx;
margin-top: 0.3 * 100rpx;
}
.font-color {
color: #e83323;
}
.recharge {
border-radius: 0.1 * 100rpx;
width: 100%;
background-color: #fff;
margin: 0.2 * 100rpx auto 0 auto;
padding: 0.3 * 100rpx;
border-top-right-radius: 0.39 * 100rpx;
border-top-left-radius: 0.39 * 100rpx;
margin-top: -0.45 * 100rpx;
box-sizing: border-box;
}
.recharge .nav {
height: 0.75 * 100rpx;
line-height: 0.75 * 100rpx;
padding: 0 1 * 100rpx;
}
.recharge .nav .item {
font-size: 0.3 * 100rpx;
color: #333;
}
.recharge .nav .item.on {
font-weight: bold;
border-bottom: 0.04 * 100rpx solid #e83323;
}
.recharge .info-wrapper {
}
.recharge .info-wrapper .money {
margin-top: 0.6 * 100rpx;
padding-bottom: 0.2 * 100rpx;
border-bottom: 1px dashed #ddd;
text-align: center;
}
.recharge .info-wrapper .money span {
font-size: 0.56 * 100rpx;
color: #333;
font-weight: bold;
}
.recharge .info-wrapper .money input {
display: inline-block;
width: 3 * 100rpx;
font-size: 0.84 * 100rpx;
text-align: center;
color: #282828;
font-weight: bold;
padding-right: 0.7 * 100rpx;
}
.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;
}
.tip {
font-size: 0.28 * 100rpx;
color: #333333;
font-weight: 800;
margin-bottom: 0.14 * 100rpx;
}
.recharge .info-wrapper .tips span {
color: #ef4a49;
}
.recharge .info-wrapper .pay-btn {
display: block;
width: 100%;
height: 0.86 * 100rpx;
margin: 0.5 * 100rpx auto 0 auto;
line-height: 0.86 * 100rpx;
text-align: center;
color: #fff;
border-radius: 0.5 * 100rpx;
font-size: 0.3 * 100rpx;
font-weight: bold;
}
.payment-top {
width: 100%;
height: 3.5 * 100rpx;
background-color: #eb3729;
}
.payment-top .name {
font-size: 0.26 * 100rpx;
color: rgba(255, 255, 255, 0.8);
margin-top: -0.38 * 100rpx;
margin-bottom: 0.3 * 100rpx;
}
.payment-top .pic {
font-size: 0.32 * 100rpx;
color: #fff;
}
.payment-top .pic-font {
font-size: 0.78 * 100rpx;
color: #fff;
}
.picList .pic-box {
width: 32%;
height: auto;
border-radius: 0.2 * 100rpx;
margin-top: 0.21 * 100rpx;
padding: 0.2 * 100rpx 0;
}
.pic-box-color {
background-color: #f4f4f4;
color: #656565;
}
.pic-number {
font-size: 0.22 * 100rpx;
}
.pic-number-pic {
font-size: 0.38 * 100rpx;
margin-right: 0.1 * 100rpx;
text-align: center;
}
.pic-box-money {
width: 100%;
display: block;
}
</style>
+153
View File
@@ -0,0 +1,153 @@
<template>
<view class="register absolute">
<view class="shading">
<view class="pictrue acea-row row-center-wrapper">
<image :src="`${staticUrl}/logo.png`" />
</view>
</view>
<view class="whiteBg">
<view class="title">找回密码</view>
<view class="list">
<view class="item">
<view>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-phone_" />
</svg>
<input type="text" placeholder="输入手机号码" v-model="account" />
</view>
</view>
<view class="item">
<view class="align-left">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_1" />
</svg>
<input type="text" placeholder="填写验证码" class="codeIput" v-model="captcha" />
<button
class="code"
:disabled="disabled"
:class="disabled === true ? 'on' : ''"
@click="code"
>{{ text }}</button>
</view>
</view>
<view class="item">
<view>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-code_" />
</svg>
<input type="password" placeholder="填写您的登录密码" v-model="password" />
</view>
</view>
</view>
<view class="logon" @click="registerReset">确认</view>
<view class="tip">
<text @click="goLogin()" class="font-color-red">立即登录</text>
</view>
</view>
<view class="bottom"></view>
</view>
</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 {
staticUrl: this.$STATIC_RESOURCE_URL,
account: "",
password: "",
captcha: ""
};
},
mixins: [sendVerifyCode],
methods: {
goLogin() {
this.$yrouter.push({ path: "/pages/user/Login/index" });
},
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 => {
uni.showToast({
title: res.msg,
icon: "success",
duration: 2000,
complete: () => {
that.$yrouter.push({ name: "Login" });
}
});
})
.catch(err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: "none",
duration: 2000
});
});
},
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 => {
uni.showToast({
title: res.msg,
icon: "success",
duration: 2000
});
that.sendCode();
})
.catch(err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
@@ -0,0 +1,368 @@
<template>
<view class="container">
<view class="content-box">
<view class="content">
<view v-if="userLevelInfo" class="verify-status-box acea-row row-center row-middle">
<img v-if="userLevelInfo.checkState==3" class="verify-status-img" :src="webUrl+'/20200824093220483259.png'"/>
<span class="verify-status-text">{{ getCheckState(userLevelInfo) }}</span>
</view>
<view v-if="userLevelInfo && userLevelInfo.checkState==4" class="reason">原因:{{ userLevelInfo.checkRemark }}
</view>
<view class="electronic-box acea-row row-middle row-center">
<view class="checkbox-wrapper">
<checkbox-group @change="toggleProtocolCheck()">
<label class="well-check">
<checkbox :checked="protocolChecked" color="#fff"
style="border-radius: 50%;transform:scale(0.7)"></checkbox>
</label>
</checkbox-group>
</view>
<view class="electronic-tip">
<span class="">我已同意</span>
<span @click="toggleProtocolPage()" class="electronic-protocol-text">香道滇股东协议</span>
</view>
</view>
<view class="upload-box acea-row row-column row-center">
<view class="idcard_pictrue">
<view @tap="chooseIdCardFrontImage">
<view class="pictrue">
<img v-if="idCardFrontImg.length>0" :src="idCardFrontImg"/>
<img v-else :src="webUrl+'/20200824092942325489.png'"/>
</view>
<view v-if="idCardFrontImg.length==0" class="add-icon">
<img :src="webUrl+'/20200824093150470953.png'"/>
</view>
</view>
</view>
<span class="upload-tip">上传身份证正面照</span>
<view class="idcard_pictrue">
<view class="" @tap="chooseIdCardBackImage">
<view class="pictrue">
<img v-if="idCardBackImg.length>0" :src="idCardBackImg"/>
<img v-else :src="webUrl+'/20200824093104069571.png'"/>
</view>
<view v-if="idCardBackImg.length==0" class="add-icon">
<img :src="webUrl+'/20200824093150470953.png'"/>
</view>
</view>
</view>
<span class="upload-tip">上传身份证反面照</span>
</view>
<view v-if="userLevelInfo && userLevelInfo.checkState!=3 && userLevelInfo.checkState!=2" class="submit-btn"
@click="submitBtnClick">保存
</view>
</view>
</view>
</view>
</template>
<script>
var that;
import {mapGetters} from "vuex";
import {chooseImage} from "@/utils";
import {getUserLevelInfo, saveUserProtocol} from "@/api/user"
import uniPopup from '@/components/uni-popup/uni-popup.vue';
export default {
components: {
uniPopup
},
props: {},
data: function () {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
idCardFrontImg: "",
idCardBackImg: "",
protocolChecked: true,
protocolShow: false,
verifyPass: 0,//是否审核通过
userLevelInfo: null,
avatar: ''
};
},
watch: {},
computed: mapGetters(["userInfo"]),
onShow() {
if (this.$store.getters.token) {
this.$store.dispatch("getUser", true);
}
},
onLoad: function () {
//setTimeout里的this不是页面的this
//所以这里要处理一下用that
that = this;
this.getUserLevelInfo();
},
methods: {
toggleProtocolCheck() {
this.protocolChecked = !this.protocolChecked;
},
//checkState:1-新增 2-待审核 3-已审核 4-已驳回
getCheckState(info) {
var status = '';
if (info) {
switch (info.checkState) {
case 1:
status = '新增';
break;
case 2:
status = '待审核';
break;
case 3:
status = '审核通过';
break;
case 4:
status = '审核驳回';
break;
default:
break;
}
}
return status;
},
//显示协议内容
toggleProtocolPage() {
//this.$refs.popup.open();
this.$yrouter.push('/pages/user/UpgradeProtocolDetail/UpgradeProtocolDetail')
},
chooseIdCardFrontImage() {
// if(this.userLevelInfo && this.userLevelInfo.checkState!=3){
// chooseImage(img => {
// console.log(img)
// this.avatar = img;
// });
// }
chooseImage(img => {
console.log(img)
that.idCardFrontImg = img;
});
},
chooseIdCardBackImage() {
chooseImage(img => {
console.log(img)
that.idCardBackImg = img;
});
},
//提交
submitBtnClick: function () {
//var that = this;
if (this.idCardFrontImg.length == 0) {
this.$dialog.toast({mes: '请上传身份证正面照片'});
return;
}
if (this.idCardBackImg.length == 0) {
this.$dialog.toast({mes: '请上传身份证反面面照片'});
return;
}
this.$dialog.loading.open();
saveUserProtocol({
uid: that.userInfo.uid,
idcardOne: that.idCardFrontImg,
idcardTwo: that.idCardBackImg
}).then((res) => {
that.$dialog.toast({mes: "保存成功!"});
//跳转回上一页
setTimeout(function () {
that.$yrouter.back();
}, 1000);
}).catch(err => {
that.$dialog.error(err.msg || "保存失败!");
}).finally(() => {
that.$dialog.loading.close();
});
},
// 获取用户等级信息
getUserLevelInfo: function () {
var that = this;
getUserLevelInfo().then((res) => {
if (res.data) {
that.userLevelInfo = res.data;
that.idCardFrontImg = res.data.idcardOne || "";
that.idCardBackImg = res.data.idcardTwo || "";
}
}).catch(err => {
}).finally(() => {
});
},
idCardFrontImageuploaded(res) {
if (res.errno !== 0)
return this.$dialog.error(res.msg || "上传图片失败");
this.idCardFrontImg = res.link;
//this.$set(this.idCardFrontImg, "avatar", res.link);
},
idCardBackImageuploaded(res) {
if (res.errno !== 0)
return this.$dialog.error(res.msg || "上传图片失败");
this.idCardBackImg = res.link;
//this.$set(this.idCardBackImg, "avatar", res.link);
},
onBackClick: function () {
this.$yrouter.back();
}
}
};
</script>
<style scoped>
.content-box {
background-color: #FFFAF5;
padding: 38rpx;
}
.content {
border: 1px solid rgba(195, 172, 149, 1);
padding: 54rpx;
}
.checkbox-wrapper {
/* width: 0.8rem; */
width: auto;
text-align: center;
}
.checkbox-wrapper .icon {
/* left: calc((0.8rem - 18px)/2); */
left: 0;
}
.checkbox-wrapper input:checked + .icon {
background-color: #FD2C4B !important;
border-color: #FD2C4B !important;
}
.electronic-tip {
color: #9B6E40;
font-size: 28rpx;
/* padding-left: 48rpx; */
}
.electronic-protocol-text {
color: #FF8D5B;
}
.protocol-wrapper {
/* display: flex; */
/* align-items: center; */
/* justify-content: center; */
height: 100%;
width: 100%;
}
.p-content {
background-color: #fff;
margin: 100rpx;
padding: 20rpx;
overflow-y: scroll;
border-radius: 16rpx;
height: calc(100% - 200rpx);
}
.p-content .title {
font-weight: bold;
color: #000;
font-size: 40rpx;
text-align: center;
}
.overlay-protocol {
z-index: 1000 !important;
}
.upload-box {
margin-top: 40rpx;
}
.upload-box .idcard_pictrue {
width: 568rpx;
height: 320rpx;
/* background:rgba(255,255,255,1); */
position: relative;
}
.upload-tip {
font-weight: bold;
font-size: 28rpx;
color: #C3AC95;
text-align: center;
margin-top: 20rpx;
width: 100%;
}
.upload-box .idcard_pictrue .pictrue {
width: 568rpx;
height: 320rpx;
position: relative;
}
.upload-box .idcard_pictrue .pictrue img {
width: 100%;
height: 100%;
}
.add-icon {
width: 92rpx;
height: 92rpx;
position: absolute;
left: calc((100% - 92rpx) / 2);
top: calc((100% - 92rpx) / 2);
}
.add-icon img {
width: 92rpx;
height: 92rpx;
}
.verify-status-box {
margin: 32rpx auto;
}
.verify-status-img {
width: 56rpx;
height: 56rpx;
}
.verify-status-text {
color: #9B6E40;
font-size: 36rpx;
font-weight: bold;
}
.submit-btn {
font-size: 32rpx;
color: #fff;
/* width:6.9rem; */
height: 90rpx;
border-radius: 50rpx;
text-align: center;
line-height: 90rpx;
background-color: #00AAEA;
margin: 76rpx auto 0 auto;
}
.reason {
margin-top: 20rpx;
margin-bottom: 20rpx;
font-size: 28rpx;
color: #FF0000;
text-align: center;
}
</style>
@@ -0,0 +1,211 @@
<template>
<view class="container">
<view class="WordSection1">
<!-- <view class="MsoNormal" align="center" style="text-align:center;text-indent:38.95rpx"><span style="font-size:18.0rpx;font-family:宋体">共享股东协议</span></view> -->
<view class="MsoNormal" align="center" style="text-align:center;text-indent:30.3rpx"><span lang="EN-US" style="font-size:28rpx">&nbsp;</span></view>
<view class="MsoNormal" style="text-indent:28.0rpx">
<span
style="font-size:28rpx;
font-family:宋体"
>
欢迎阅读香道滇官方商城服务条款
</span>
<span lang="EN-US" style="font-size:28rpx">(</span>
<span style="font-size:28rpx;font-family:宋体">下称本条款</span>
<span lang="EN-US" style="font-size:28rpx">)</span>
<span
style="font-size:28rpx;font-family:
宋体"
>
本条款阐述之条款和条件适用于您在香道滇官方商城平台无偿或有偿使用香道滇产品
</span>
</view>
<view class="MsoNormal" style="text-indent:30.3rpx">
<span lang="EN-US" style="font-size:30rpx">1.&nbsp;</span>
<span
style="font-size:28rpx;
font-family:宋体"
>
接受条款
</span>
</view>
<view class="MsoNormal" style="text-indent:30.3rpx">
<u>
<span style="font-size:28rpx;font-family:宋体">
以任何方式使用香道滇产品即表示您同意自己已经与香道滇公司就香道滇官方商城平台服务事项下称香道滇商城服务订立本条款且您将受本条款的条件约束
</span>
</u>
<span style="font-size:28rpx;font-family:宋体">
您应在第一次提出申请前仔细阅读本条款并有权选择停止或继续使用香道滇商城服务一旦您继续使用香道滇商城服务则表示您已接受本条款当您与香道滇商城发生争议时应以本条款作为约束双方的条款
</span>
</view>
<view class="MsoNormal" style="text-indent:30.3rpx">
<span lang="EN-US" style="font-size:30rpx">2.&nbsp;</span>
<span
style="font-size:28rpx;
font-family:宋体"
>
谁可成为
</span>
<span
style="font-size:28rpx;font-family:
宋体"
>
香道滇官方商城
<span>平台的共享股东</span>
</span>
</view>
<view class="MsoNormal" style="text-indent:28.0rpx">
<span
style="font-size:28rpx;
font-family:宋体"
>
必需是注册成为香道滇官方商城会员后对香道滇产品产生一定兴趣和拥有一定资源的合作伙伴
</span>
</view>
<view class="MsoNormal" style="text-indent:28.0rpx">
<span
style="font-size:28rpx;
font-family:宋体"
>
升级成为群主针对个人要求拥有吃货宣传带动力
</span>
</view>
<view class="MsoNormal" style="text-indent:28.0rpx">
<span
style="font-size:28rpx;
font-family:宋体"
>
升级成为团长针对个人要求具备一定的线上或线下实战带货力
</span>
</view>
<view class="MsoNormal" style="text-indent:28.0rpx">
<span
style="font-size:28rpx;
font-family:宋体"
>
升级成为特约合作方针对第三方合作要求具备一定实力的带货公司
</span>
<span lang="EN-US" style="font-size:28rpx">/</span>
<span
style="font-size:28rpx;
font-family:宋体"
>
平台
</span>
</view>
<view class="MsoNormal" style="text-indent:28.0rpx">
<span
style="font-size:28rpx;
font-family:宋体"
>
请您先与商城管理员进行信息交流让我们了解下您的资源情况同时也把相应匹配的共享股东的具体权益让您也具体了解待双方都明确的情况下在由您提出申请并提交相应资料信息后即可完成对应升级
</span>
</view>
<view class="MsoNormal" style="text-indent:30.3rpx">
<span lang="EN-US" style="font-size:30rpx">3.&nbsp;</span>
<span
style="font-size:28rpx;
font-family:宋体"
>
您的资料与隐私
</span>
</view>
<view class="MsoNormal" style="text-indent:28.0rpx">
<span
style="font-size:28rpx;
font-family:宋体"
>
需要到您提交个人或平台方的资料仅作为香道滇官方商城合作备案同时香道滇官方商城也保证不会泄露您的信息给第三方
</span>
</view>
<view class="MsoNormal" style="text-indent:30.3rpx">
<span lang="EN-US" style="font-size:28rpx">4.&nbsp;</span>
<span
style="font-size:28rpx;
font-family:宋体"
>
香道滇官方商城
<span>平台产品责任</span>
</span>
</view>
<view class="MsoNormal" style="text-indent:28.0rpx">
<span
style="font-size:28rpx;
font-family:宋体"
>
</span>
<span lang="EN-US" style="font-size:28rpx">1</span>
<span style="font-size:28rpx;font-family:宋体">所有从本商城发货出去的产品均有品质保证如因产品本身出现的质量问题均由本商城负责处理及承担相应责任</span>
</view>
<view class="MsoNormal" style="margin-left:8.0rpx;text-indent:20.45rpx">
<span style="font-size:28rpx;font-family:宋体"></span>
<span lang="EN-US" style="font-size:28rpx">2</span>
<span
style="font-size:28rpx;font-family:
宋体"
>
您作为香道滇官方商城产品的推广方用户需按照本商城给予的指导售价产品实际宣传内容以及有针对性的目标群体进行宣传推广
</span>
<span style="font-size:28rpx;font-family:宋体">不得进行虚假宣传或者促使消费者误解的方式进行宣传</span>
<span style="font-size:28rpx;font-family:宋体">如此造成目标客户群体的影响则由其自行承担相应责任</span>
</view>
<view class="MsoNormal" style="text-indent:30.3rpx">
<span lang="EN-US" style="font-size:30rpx">5.&nbsp;</span>
<span
style="font-size:28rpx;
font-family:宋体"
>
不可抗力
</span>
</view>
<view class="MsoNormal" style="text-indent:28.0rpx">
<span
style="font-size:28rpx;
font-family:宋体"
>
由于自然灾害暴动战争行为政府行为通电信网络黑客攻击尚无有效防御措施的计算机病毒的发作及其他各方不能预见并且对其发生和后果不能防止并避免的不可抗力原因致使凡香道滇官方商城延迟或未能履约的香道滇公司不对您承担任何责任
</span>
</view>
<view class="MsoNormal"><span lang="EN-US" style="font-size:28rpx">&nbsp;</span></view>
</view>
</view>
</template>
<scrirpx>
export default {
data() {
return {
}
},
methods: {
}
}
</scrirpx>
<style>
.container {
padding: 0 20rpx;
}
</style>
File diff suppressed because it is too large Load Diff
+111
View File
@@ -0,0 +1,111 @@
<template>
<view class="my-account">
<view class="wrapper">
<view class="header">
<view class="headerCon">
<view class="account acea-row row-top row-between">
<view class="assets">
<view style="color: #fff;">总资产()</view>
<view class="money">{{ now_money }}</view>
</view>
<!-- <navigator url="/pages/user/Recharge/index" class="recharge font-color-red">充值</navigator> -->
</view>
<view class="cumulative acea-row row-top">
<view class="item">
<view style="color: #fff;">累计消费()</view>
<view class="money">{{ orderStatusSum }}</view>
</view>
</view>
</view>
</view>
<view class="nav acea-row row-middle">
<view class="item" @click="goUserBill(0)">
<view class="pictrue">
<image :src="webUrl+'/20230304202916716809.png'" />
</view>
<view>账单记录</view>
</view>
<view class="item" @click="goUserBill(1)">
<view class="pictrue">
<image :src="webUrl+'/20230304202923197491.png'" />
</view>
<view>消费记录</view>
</view>
</view>
<view class="advert acea-row row-between-wrapper"></view>
</view>
<Recommend></Recommend>
</view>
</template>
<script>
import Recommend from "@/components/Recommend";
import { getActivityStatus, getBalance } from "@/api/user";
export default {
name: "UserAccount",
components: {
Recommend
},
props: {},
data: function() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
now_money: 0,
orderStatusSum: 0,
recharge: 0,
activity: {
is_bargin: false,
is_pink: false,
is_seckill: false
}
};
},
onShow: function() {
this.getIndex();
// this.getActivity();
},
methods: {
goUserBill(types) {
this.$yrouter.push({
path: "/pages/user/UserBill/index",
query: { types }
});
},
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 => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
}
);
},
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;
},
err => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
}
);
}
}
};
</script>
+114
View File
@@ -0,0 +1,114 @@
<template>
<view class="bill-details" ref="container">
<view class="nav acea-row">
<view class="item" :class="types == 0 ? 'on' : ''" @click="changeTypes(0)">全部</view>
<view class="item" :class="types == 1 ? 'on' : ''" @click="changeTypes(1)">消费</view>
<view class="item" :class="types == 2 ? 'on' : ''" @click="changeTypes(2)">充值</view>
</view>
<view class="sign-record">
<view class="list">
<view class="item" v-for="(item, listIndex) in list" :key="listIndex">
<view class="data">{{ item.time }}</view>
<view class="listn" v-for="(val, key) in item.list" :key="key">
<view class="itemn acea-row row-between-wrapper">
<view>
<view class="name line1">{{ val.title }}</view>
<view>{{ val.addTime }}</view>
</view>
<view
class="num"
:class="val.pm == 0 ? 'font-color-red' : ''"
>{{ val.pm == 0 ? "-" : "+" }}{{ force2Decimal(val.number) }}</view>
</view>
</view>
</view>
</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
</view>
</template>
<script>
import { getCommissionInfo } from "@/api/user";
import Loading from "@/components/Loading";
export default {
name: "UserBill",
components: {
Loading
},
props: {},
data: function() {
return {
types: 0,
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||0;
that.getIndex();
},
onReachBottom() {
!this.loading && this.getIndex();
},
methods: {
force2Decimal(v){
return this.$force2Decimal(v);
},
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);
},
err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: 'none',
duration: 2000
});
}
);
}
}
};
</script>
+316
View File
@@ -0,0 +1,316 @@
<template>
<view class="newsList" ref="container">
<mescroll-body ref="mescrollRef" top="0" bottom="0" class='cotent-scroll' :up="upOption" :down="downOption" @up="upCallback" @down="downCallback" @init="mescrollInit" @emptyclick="emptyClick">
<view class="list" v-for="(item, index) in list" :key="index">
<view @click="goNewsDetail(item)" class="item acea-row" style="flex-wrap: nowrap;">
<view class="text acea-row row-column-between">
<view class="acea-row row-column" style="position: relative;">
<view class="name line2">{{ item.name }}</view>
<view class="summary line1" style="width: 322rpx;">{{ shortDateString(item.createdTime) }}</view>
</view>
<view class="acea-row row-left row-middle">
<view class="see-num-box acea-row row-middle" style="margin-right: 20rpx;">
<image :src="webUrl+'/20230304131559277594.png'" class="eye-icon" mode=""></image>
<text class="see-num-text">{{item.pv||0}}</text>
</view>
<view class="zan-num-box acea-row row-middle">
<img class="zan-icon" :src="webUrl+'/20230304133322439350.png'" />
<text class="zan-num-text">{{item.zan||0}}</text>
</view>
</view>
</view>
<view class="pictrue">
<image v-if="item.type=='NT_TEXT'" style="width: 100%;height: 100%;" :src="item.resources[0]" />
<video v-if="item.type=='NT_VIDEO'" style="width: 100%;height: 100%;" :src="item.resources[0]"></video>
</view>
</view>
</view>
<view id="loading-more"></view>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixins from "@/mixins/mescroll-mixins.js";
import MescrollBody from "@/components/mescroll-uni/mescroll-body.vue";
import { getHotelNewsZanList } from "@/api/inn.js";
import { formatDateTime,isNullOrEmpty} from "@/utils";
var _this;
export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
list:[],
upOption:{
noMoreSize: 10, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
auto:true,
empty:{
tip: '暂无数据' // 提示
// btnText:'点击刷新'
}
},
downOption:{
auto:false
}
}
},
components:{
MescrollBody
},
mixins:[
MescrollMixins({
getPageData(mescroll){
var _this = this;
// 此时mescroll会携带page的参数:
let pageNum = mescroll.num; // 页码, 默认从1开始
let pageSize = mescroll.size; // 页长, 默认每页10条
var params = {
limit:pageNum,
page:pageSize
}
getHotelNewsZanList(params)
.then(res => {
if(mescroll.num == 1) {
_this.list = []; //如果是第一页需手动制空列表
}
_this.list = _this.list.concat(res.data);//追加新数据
mescroll.endSuccess(res.data.length);
})
.catch(err => {
console.log(err);
mescroll.endErr();
uni.showToast({
title: err.msg || '请求出错',
icon: 'none',
mask: false,
duration: 1500
});
})
}
})
],
onLoad:function(e){
_this = this;
//从query里取模式
//this.isSelectMode = this.$yroute.query.isSelected;
},
onShow:function(){
//静默刷新
this.mescroll && this.mescroll.resetUpScroll(false);
},
methods: {
isNullOrEmpty,
shortDateString(dateStr){
var ret = '';
if (isNullOrEmpty(dateStr)) {
} else{
// var s = dataStr;
// s = s.replace(/-/g,"/");
// var date = new Date(s).getTime();
ret = formatDateTime(dateStr,'yyyy-MM-dd HH:mm:ss');
}
return ret;
},
goNewsDetail:function(item){
this.$yrouter.push('/pagesInn/inn/innInfoDetail?id='+item.id);
}
}
}
</script>
<style scoped lang="less">
.pink-dot{
width:24rpx;
height:24rpx;
background:rgba(255,86,74,0.4);
border-radius:50%;
position: absolute;
z-index: 0;
bottom: 0;
right: -12rpx;
}
.main-title{
font-size: 36rpx;
line-height: 36rpx;
// color: #080F1A;
color: #FFFFFF;
position: relative;
}
.eye-icon{
width: 32rpx;
height: 32rpx;
margin-right: 8rpx;
}
.zan-icon{
width: 32rpx;
height: 32rpx;
margin-right: 8rpx;
}
.zan-num-text{
color: #080F1A;
font-size: 24rpx;
}
.see-num-text{
color: #080F1A;
font-size: 24rpx;
}
.newsList .list .item .text .name{
color: #080F1A !important;
font-size: 32rpx;
font-weight: bold;
}
.newsList .list .item .text{
margin-right: 10rpx;
width: auto !important;
height: auto !important;
}
.newsList .list .item .pictrue{
flex-shrink: 0;
width: 288rpx !important;
height: 216rpx !important;
}
.newsList .list .item{
background-color: #fff;
flex-wrap: nowrap;
padding: 35rpx !important;
margin: 35rpx 30rpx !important;
border-radius: 8rpx;
}
.summary{
color: #C2C5CC;
font-size: 24rpx;
}
.sub-title{
font-size:14*2rpx;
margin-top: 10rpx;
color:rgba(252,85,179,0.7);
}
.title .hot-title{
font-size: 18*2rpx;
color: #FF7900;
background:rgba(255,255,255,1);
margin-left: 5*2rpx;
margin-right: 5*2rpx;
}
.hotGoodsList{
position: relative;
margin: 35rpx 0;
background-color: #fff;
flex-wrap: wrap;
}
.hotGoodsList .newProductsItem{
margin-left: 35rpx;
margin-top: 20rpx;
}
.img-box{
position: relative;
}
.price-tag{
position: absolute;
width: 39*2rpx;
height: 19*2rpx;
left: 0;
top: 0;
}
.like-btn{
position: absolute;
width: 24*2rpx;
height: 24*2rpx;
right: 0;
top: 0;
}
.inn-tag-wrap{
margin-top: 10rpx;
margin-bottom: 10rpx;
}
.zanmost-tag{
padding: 2rpx 8rpx 2rpx 8rpx;
background: #FF2D69;
font-size: 10*2rpx;
color: #FFFFFF;
}
.latest-tag{
padding: 2rpx 8rpx 2rpx 8rpx;
background: #0DC5C5;
font-size: 10*2rpx;
color: #FFFFFF;
margin-left: 8rpx;
}
.location-tag{
padding: 2rpx 8rpx 2rpx 8rpx;
background: #FD685D;
font-size: 10*2rpx;
color: #FFFFFF;
margin-left: 8rpx;
}
.inn-shop-icon{
border-radius: 50%;
width: 24*2rpx;
height: 24*2rpx;
}
.inn-shop-name{
font-size: 24rpx;
color: #080F1A;
}
.inn-shop-date{
font-size: 18rpx;
color: #C2C5CC;
}
.location{
padding: 4rpx 16rpx;
background: #FFFFFF;
border-radius: 22rpx;
}
.city-name{
color: #FD685D;
font-size: 24rpx;
margin-left: 4rpx;
}
.btLine{
width: 100%;
height: 12rpx;
margin-top: -4rpx;
background: #FD685D;
}
.pro-info{
font-size: 14*2rpx;
}
</style>
+209
View File
@@ -0,0 +1,209 @@
<template>
<view class="member-center">
<view class="header">
<view class="slider-banner banner">
<swiper indicatorDots="true" @change="swiperChange">
<block v-for="(item, vipListIndex) in vipList" :key="vipListIndex">
<swiper-item>
<view class="swiper-slide" :style="{ backgroundImage: 'url(' + item.image + ')' }">
<!-- <image :src="item.icon" />-->
<view class="name">{{ item.name }}</view>
<view class="discount">
可享受商品折扣: {{ item.discount / 10 }}
<text class="iconfont icon-zhekou"></text>
</view>
<view class="nav acea-row" v-if="item.grade == grade">
<view class="item" v-for="(val, indexn) in vipComplete" :key="indexn">
<view class="num">{{ val.newNumber }}</view>
<view>{{ val.realName }}</view>
</view>
</view>
<view class="lock" v-if="item.grade > grade">
<text class="iconfont icon-quanxianguanlisuozi"></text>该会员等级尚未解锁
</view>
<view class="lock" v-if="item.grade < grade">
<text class="iconfont icon-xuanzhong1"></text>已解锁更高等级
</view>
</view>
</swiper-item>
</block>
</swiper>
</view>
</view>
<view class="wrapper">
<view class="title acea-row row-between-wrapper">
<view>
<text class="iconfont icon-jingyanzhi"></text>会员升级要求
</view>
<view class="num">
<text class="current">{{ taskCount }}</text>
/{{ vipRequire.length }}
</view>
</view>
<view class="list">
<view class="item" v-for="(item, vipCompleteIndex) in vipComplete" :key="vipCompleteIndex">
<view class="top acea-row row-between-wrapper">
<view class="name">
{{ item.name}}
<text class="iconfont icon-wenti" v-if="item.illustrate" @click="showGrow(item)"></text>
</view>
<view>{{ item.finish ? "已满足条件" : "未满足条件" }}</view>
</view>
<view class="cu-progress">
<view class="bg-red" :style="{ width: item.speed + '%' }"></view>
</view>
<view class="experience acea-row row-between-wrapper">
<view>{{ item.taskTypeTitle }}</view>
<view>
<text class="num">{{ item.newNumber }}</text>
/{{ item.number }}
</view>
</view>
</view>
</view>
</view>
<Recommend></Recommend>
<view class="growthValue" :class="growthValue === false ? 'on' : ''">
<view class="pictrue">
<image :src="webUrl+'/20200729164901293388.jpg'" />
<text class="iconfont icon-guanbi3" @click="growthTap"></text>
</view>
<view class="conter">{{ illustrate }}</view>
</view>
<view class="mask" :hidden="growthValue" @click="growthTap"></view>
</view>
</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 {
webUrl:this.$VUE_APP_RESOURCES_URL,
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 => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
}
);
},
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 => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
}
);
},
showGrow: function(item) {
if (this.illustrate != item.illustrate) this.illustrate = item.illustrate;
this.growthValue = false;
}
}
};
</script>
<style lang="less">
.banner swiper {
height: 328rpx;
}
.swiper-slide {
margin: 0 auto;
}
</style>
+375
View File
@@ -0,0 +1,375 @@
<template>
<view class="addAddress absolute">
<view class="list">
<view class="item acea-row row-between-wrapper">
<view class="name">姓名</view>
<input type="text" placeholder="请输入姓名" v-model="userAddress.realName" required/>
</view>
<view class="item acea-row row-between-wrapper">
<view class="name">联系电话</view>
<input type="text" placeholder="请输入联系电话" v-model="userAddress.phone" required :maxlength="11"/>
</view>
<view class="item acea-row row-between-wrapper">
<view class="name">所在地区</view>
<view class="picker acea-row row-between-wrapper select-value form-control">
<view class="address">
<CitySelect
ref="cityselect"
:defaultValue="addressText"
@callback="result"
:items="district"
></CitySelect>
</view>
<view class="iconfont icon-dizhi font-color-red" @click="getCurAddress()"></view>
</view>
</view>
<view class="item acea-row row-between-wrapper" style="flex-wrap: nowrap;">
<view class="name">详细地址</view>
<input type="text" placeholder="请填写具体地址" v-model="userAddress.detail" required/>
<!-- <textarea v-model="userAddress.detail" placeholder="请填写具体地址" /> -->
</view>
</view>
<view class="default acea-row row-middle">
<view class="select-btn">
<view class="checkbox-wrapper">
<checkbox-group @change="ChangeIsDefault">
<label class="well-check">
<checkbox :checked="userAddress.isDefault ? true : false"></checkbox>
<text class="def">设置为默认地址</text>
</label>
</checkbox-group>
</view>
</view>
</view>
<view></view>
<view class="keepBnt bg-color-red" @tap="submit">立即保存</view>
<view class="wechatAddress" v-if="isWechat && !id" @click="getAddress">导入微信地址</view>
</view>
</template>
<script type="text/babel">
import CitySelect from "@/components/CitySelect";
import config from '@/utils/mapConfig';
import {getAddress, getCity, postAddress} from "@/api/user";
import attrs, {chs_extphone, required} from "@/utils/validate";
import {validatorDefaultCatch} from "@/utils/dialog";
// import { openAddress } from "@/libs/wechat";
import {isWeixin} from "@/utils";
export default {
name: "AddAddress",
components: {
CitySelect
},
computed: {},
data() {
return {
district: [],
id: 0,
userAddress: {isDefault: 0},
address: {},
isWechat: isWeixin(),
addressText: ""
};
},
mounted: function () {
let id = this.$yroute.query.id;
this.id = id;
if (this.id) {
uni.setNavigationBarTitle({
title: '编辑地址'
})
}
this.getUserAddress();
this.getCityList();
},
watch: {
// addressText(nextModel2) {
// console.log(nextModel2, 8585858585);
// }
//定位成功后回调
// province(newVal,oldVal){
// uni.hideLoading();
// //if(newVal!=oldVal){
// this.addressText =
// this.province + " " + this.city + " " + this.county;
// this.address.province = this.province;
// this.address.city = this.city;
// this.address.district = this.county;
// this.userAddress.detail = this.detailAddress;
// //}
// }
},
methods: {
getIndex(value, arr) {
var idx = -1;
for (var i = 0; i < arr.length; i++) {
if (arr[i].n == value) {
idx = i;
break;
}
}
return idx;
},
//获取当前定位地址
getCurAddress() {
var that = this;
//定位
uni.showLoading({
title: '定位中...'
});
//this.getLocation();
uni.getLocation({
type: 'wgs84',
success: function (res) {
let latitude = res.latitude;
let longitude = res.longitude;
console.log('latitude:' + latitude + 'longitude:' + longitude)
// #ifdef H5
Vue.jsonp(
'https://apis.map.qq.com/ws/geocoder/v1/?location=' + latitude + ',' + longitude + '&key=' + config.key,
{
//callbackName: 'QQmap',
output: 'jsonp',
}).then(json => {
// Success.
uni.hideLoading();
that.addressText =
json.result.ad_info.province + " " + json.result.ad_info.city + " " + json.result.ad_info.district;
that.address.province = json.result.ad_info.province;
that.address.city = json.result.ad_info.city;
that.address.district = json.result.ad_info.district;
that.$set(that.userAddress, 'detail', json.result.formatted_addresses.recommend);
//that.userAddress.detail = json.result.formatted_addresses.recommend;
// that.$refs.cityselect.adjustDefaultValue();
//设置city_id
var pIdx = that.getIndex(that.address.province, that.district);
if (pIdx > -1) {
var citys = that.district[pIdx].c;
var cIdx = that.getIndex(that.address.city, citys);
if (cIdx > -1) {
var city = citys[cIdx];
that.address.city_id = city.v;
console.log('city_id:' + city.v);
}
}
}).catch(err => {
// Failed.
console.log('地址解析失败:' + JSON.stringify(err));
uni.hideLoading();
})
// #endif
// #ifndef H5
uni.request({
url: 'https://apis.map.qq.com/ws/geocoder/v1/?location=' + latitude + ',' + longitude + '&key=' + config.key,
success: function (res) {
// console.log('res:'+JSON.stringify(res.data));
uni.hideLoading();
that.addressText =
res.data.result.ad_info.province + " " + res.data.result.ad_info.city + " " + res.data.result.ad_info.district;
that.address.province = res.data.result.ad_info.province;
that.address.city = res.data.result.ad_info.city;
that.address.district = res.data.result.ad_info.district;
//that.userAddress.detail = res.data.result.formatted_addresses.recommend;
that.$set(that.userAddress, 'detail', res.data.result.formatted_addresses.recommend);
// that.$refs.cityselect.adjustDefaultValue();
//设置city_id
var pIdx = that.getIndex(that.address.province, that.district);
if (pIdx > -1) {
var citys = that.district[pIdx].c;
var cIdx = that.getIndex(that.address.city, citys);
if (cIdx > -1) {
var city = citys[cIdx];
that.address.city_id = city.v;
console.log('city_id:' + city.v);
}
}
},
fail: function (res) {
console.log('地址解析失败');
uni.hideLoading();
},
complete: function () {
}
});
// #endif
},
fail: function (res) {
uni.hideLoading();
// uni.showToast({
// title:'城市定位失败:'+JSON.stringify(res),
// icon:'none',
// duration:2000
// })
}
});
},
getCityList: function () {
let that = this;
getCity()
.then(res => {
that.district = res.data;
that.ready = true;
if (this.id) {
//设置city_id
var pIdx = that.getIndex(that.address.province, that.district);
if (pIdx > -1) {
var citys = that.district[pIdx].c;
var cIdx = that.getIndex(that.address.city, citys);
if (cIdx > -1) {
var city = citys[cIdx];
that.address.city_id = city.v;
console.log('city_id:' + city.v);
}
}
}
})
.catch(err => {
that.$dialog.error(err.msg);
});
},
getUserAddress: function () {
if (!this.id) return false;
let that = this;
getAddress(that.id).then(res => {
that.userAddress = res.data;
that.addressText =
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;
if (that.district.length > 0) {
//设置city_id
var pIdx = that.getIndex(that.address.province, that.district);
if (pIdx > -1) {
var citys = that.district[pIdx].c;
var cIdx = that.getIndex(that.address.city, citys);
if (cIdx > -1) {
var city = citys[cIdx];
that.address.city_id = city.v;
console.log('city_id:' + city.v);
}
}
}
});
},
getAddress() {
},
async submit() {
let name = this.userAddress.realName,
phone = this.userAddress.phone,
addressText = this.addressText,
detail = this.userAddress.detail,
isDefault = this.userAddress.isDefault;
if (phone.length < 11) {
uni.showToast({
title: "请输入11位手机号码",
icon: "none"
})
return;
}
try {
await this.$validator({
name: [
required(required.message("姓名")),
attrs.range([2, 16], attrs.range.message("姓名"))
],
phone: [
required(required.message("联系电话")),
chs_extphone(chs_extphone.message())
//chs_phone(chs_phone.message())
],
addressText: [required("请选择地址")],
detail: [required(required.message("具体地址"))]
}).validate({name, phone, addressText, 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 ? true : false,
post_code: ""
};
postAddress(data).then(function () {
if (that.id) {
uni.showToast({
title: "修改成功",
icon: "none",
duration: 2000
});
} else {
uni.showToast({
title: "已取消绑定",
icon: "none",
duration: 2000
});
}
that.$yrouter.back();
});
} catch (err) {
uni.showToast({
title: err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
}
},
ChangeIsDefault: function () {
this.userAddress.isDefault = !this.userAddress.isDefault;
},
result(values) {
console.log(this);
console.log(values);
this.address = {
province: values.province.name || "",
city: values.city.name || "",
district: values.district.name || "",
city_id: values.city.id
};
this.addressText = `${this.address.province} ${this.address.city} ${this.address.district}`;
// this.addressText =
// this.address.province + this.address.city + this.address.district;
}
}
};
</script>
<style lang="less">
.address {
text {
width: 100%;
display: block;
}
}
</style>
@@ -0,0 +1,273 @@
<template>
<view
class="address-management"
:class="addressList.length < 1 && page > 1 ? 'on' : ''"
ref="container"
>
<view style="margin-bottom: 12rpx;" class="line" v-if="addressList.length > 0">
<image :src="webUrl+'/20230304135025917856.png'"/>
</view>
<view style="position: relative;" class="item" v-for="(item, addressListIndex) in addressList"
:key="addressListIndex" @click="tapAddress(item)">
<view v-if="item.isDefault||item.isDefault=='1' ? true : false" class=""
style="position: absolute;top: 0;right: 0;">
<image style="width: 72rpx;height: 36rpx;" :src="webUrl+'/20210807165228290910.png'" mode=""></image>
</view>
<view class="address">
<view class="consignee">
收货人{{ item.realName }}
<text class="phone">{{ item.phone }}</text>
</view>
<view style="color: #8B8F99;">
收货地址{{ item.province }}{{ item.city }}{{
item.district
}}{{ item.detail }}
</view>
</view>
<view v-if="!chooseMode" class="operation acea-row row-between-wrapper">
<view class="select-btn">
<view class="checkbox-wrapper">
<checkbox-group @change.stop="radioChange(item.id)">
<label class="well-check acea-row row-middle">
<checkbox style="transform: scale(0.55);"
:checked="item.isDefault||item.isDefault=='1' ? true : false"></checkbox>
<text class="default" style="margin-left: -10rpx;">设为默认</text>
</label>
</checkbox-group>
</view>
</view>
<view class="acea-row row-middle">
<view @click.stop="editAddress(addressListIndex)" style="color: #B3BCBF;">
<text class="iconfont icon-bianji" style="color: #B3BCBF;"></text>
<text>修改</text>
</view>
<view @click.stop="delAddress(addressListIndex)" style="color: #B3BCBF;">
<text class="iconfont icon-shanchu" style="color: #B3BCBF;"></text>
<text>删除</text>
</view>
</view>
</view>
</view>
<Loading :loaded="loadend" :loading="loading"></Loading>
<view class="noCommodity" v-if="addressList.length < 1 && page > 1">
<view class="noPictrue">
<image :src="webUrl+'/20210203154438492268.png'" class="image"/>
</view>
</view>
<view style="height:100rpx;"></view>
<view class="footer acea-row row-between-wrapper">
<view class="addressBnt bg-color-lightred" v-if="isWechat" @click="addAddress">
<text class="iconfont icon-tianjiadizhi"></text>
添加新地址
</view>
<view class="addressBnt on bg-color-lightred" v-else @click="addAddress">
<text class="iconfont icon-tianjiadizhi"></text>
添加新地址
</view>
<!--<view class="addressBnt wxbnt" v-if="isWechat" @click="getAddress">-->
<!--<text class="iconfont icon-weixin2"></text>导入微信地址-->
<!--</view>-->
</view>
</view>
</template>
<style scoped lang="less">
.address-management.on {
background-color: #fff;
height: 100vh;
}
</style>
<script type="text/babel">
import {getAddressDefaultSet, getAddressList, getAddressRemove} from "@/api/user";
import Loading from "@/components/Loading";
import {isWeixin} from "@/utils";
export default {
components: {
Loading
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
page: 1,
limit: 20,
chooseMode: false,//是否选择地址模式
addressList: [],
loadTitle: "",
loading: false,
loadend: false,
isWechat: isWeixin()
};
},
mounted: function () {
this.AddressList();
},
onReachBottom() {
!this.loading && this.AddressList();
},
onLoad: function (e) {
//是否选择模式
if (this.$yroute.query.choosMode != undefined) {
this.chooseMode = true;
uni.setNavigationBarTitle({
title: '选择收货地址'
})
} else {
this.chooseMode = false;
}
},
onShow: function () {
this.refresh();
},
methods: {
tapAddress: function (item) {
if (this.chooseMode) {
//通知前一界面修改地址
uni.$emit('chooseAddress', item)
//关闭当前页面
this.$yrouter.back();
}
},
refresh: function () {
this.addressList = [];
this.page = 1;
this.loadend = false;
this.AddressList();
},
/**
* 获取地址列表
*
*/
AddressList: function () {
let that = this;
if (that.loading) return; //阻止下次请求(false可以进行请求);
if (that.loadend) return; //阻止结束当前请求(false可以进行请求);
that.loading = true;
getAddressList({page: that.page, limit: that.limit}).then(res => {
that.loading = false;
//apply();js将一个数组插入另一个数组;
that.addressList.push.apply(that.addressList, res.data);
that.loadend = res.data.length < that.limit; //判断所有数据是否加载完成;
that.page = that.page + 1;
});
},
/**
* 编辑地址
*/
editAddress: function (index) {
this.$yrouter.push({
path: "/pages/user/address/AddAddress/index",
query: {id: this.addressList[index].id}
});
},
/**
* 删除地址
*/
delAddress: function (index) {
let that = this;
let address = this.addressList[index];
let id = address.id;
uni.showModal({
title: '确认删除此收货地址?',
content: '',
showCancel: true,
cancelText: '取消',
confirmText: '确认',
success: res => {
if (res.confirm) {
getAddressRemove(id).then(function () {
uni.showToast({
title: "删除成功!",
icon: "success",
duration: 2000,
complete: () => {
that.addressList.splice(index, 1);
that.$set(that, "addressList", that.addressList);
}
});
});
}
},
fail: () => {
},
complete: () => {
}
});
},
/**
* 设置默认地址
*/
radioChange: function (id) {
getAddressDefaultSet(id).then(res => {
this.refresh();
uni.showToast({title: res.msg, icon: "none", duration: 2000});
});
},
/**
* 新增地址
*/
addAddress: function () {
this.$yrouter.push({
path: "/pages/user/address/AddAddress/index"
});
},
getAddress() {
// openAddress().then(userInfo => {
// uni.showLoading({ title: "加载中" });
// postAddress({
// real_name: userInfo.userName,
// phone: userInfo.telNumber,
// address: {
// province: userInfo.provinceName,
// city: userInfo.cityName,
// district: userInfo.countryName
// },
// detail: userInfo.detailInfo,
// post_code: userInfo.postalCode,
// wx_export: 1
// })
// .then(() => {
// this.page = 1;
// this.loading = false;
// this.loadend = false;
// this.addressList = [];
// this.AddressList();
// uni.hideLoading();
// uni.showToast({
// title: "添加成功",
// icon: 'success',
// duration: 2000
// });
// })
// .catch(err => {
// uni.hideLoading();
// uni.showToast({
// title: err.msg || err.response.data.msg|| err.response.data.message,
// icon: 'none',
// duration: 2000
// });
// });
// });
}
}
};
</script>
<style scoped lang="less">
.address-management .item {
box-shadow: 0px 6rpx 6rpx rgba(0, 0, 0, 0.1);
opacity: 1;
border-radius: 16rpx;
margin-left: 32rpx;
margin-right: 32rpx;
}
</style>
+107
View File
@@ -0,0 +1,107 @@
<template>
<view ref="container">
<div class="coupon-list" v-if="couponsList.length > 0">
<div
class="item acea-row row-center-wrapper"
v-for="(item, index) in couponsList"
:key="index"
>
<div class="money" :class="item.isUse ? 'moneyGray' : ''">
<div>
<span class="num">{{ item.couponPrice }}</span>
</div>
<div class="pic-num">{{ item.useMinPrice }}元可用</div>
</div>
<div class="text">
<div class="condition line1">
<span class="line-title bg-color-check" v-if="item.ctype === 0">通用劵</span>
<span class="line-title bg-color-check" v-else-if="item.ctype === 1">商品券</span>
<span class="line-title bg-color-check" v-else>未知</span>
<span>{{ item.cname }}</span>
</div>
<div class="data acea-row row-between-wrapper">
<div v-if="item.endTime !== 0">{{ item.startTime }}-{{ item.endTime }}</div>
<div v-else>不限时</div>
<div class="bnt gray" v-if="item.isUse === true">已领取</div>
<div class="bnt gray" v-else-if="item.isUse === 2">已领完</div>
<div class="bnt bg-color-red" v-else @click="getCoupon(item.id, index)">立即领取</div>
</div>
</div>
</div>
</div>
<Loading :loaded="loadend" :loading="loading"></Loading>
<!--暂无优惠券-->
<view class="noCommodity" v-if="couponsList.length === 0 && page > 1">
<view class="noPictrue">
<image src="http://admin-api.xdd618.com/file/pic/20210203154207179472.png" class="image" />
</view>
</view>
</view>
</template>
<script>
import { getCoupon, getCouponReceive } from "@/api/user";
import Loading from "@/components/Loading";
import DataFormatT from "@/components/DataFormatT";
export default {
name: "getCoupon",
components: {
Loading,
DataFormatT
},
props: {},
data: function() {
return {
page: 1,
limit: 10,
couponsList: [],
loading: false,
loadend: false
};
},
mounted: function() {
this.getUseCoupons();
},
onReachBottom() {
!this.loading && this.getUseCoupons();
},
methods: {
getCoupon: function(id, index) {
let that = this;
let list = that.couponsList;
getCouponReceive(id)
.then(function(res) {
list[index].isUse = true;
uni.showToast({
title: "领取成功",
icon: "success",
duration: 2000
});
})
.catch(function(err) {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
});
},
getUseCoupons: 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 };
getCoupon(q).then(res => {
that.loading = false;
//apply();js将一个数组插入另一个数组;
that.couponsList.push.apply(that.couponsList, res.data);
that.loadend = res.data.length < that.limit; //判断所有数据是否加载完成;
that.page = that.page + 1;
});
}
}
};
</script>
+79
View File
@@ -0,0 +1,79 @@
<template>
<view ref="container">
<div class="coupon-list" v-if="couponsList.length > 0">
<div
class="item acea-row row-center-wrapper"
v-for="(item, index) in couponsList"
:key="index"
>
<div class="money" :class="item._type === 0 ? 'moneyGray' : ''">
<div>
<span class="num">{{ item.couponPrice }}</span>
</div>
<div class="pic-num">{{ item.useMinPrice }}元可用</div>
</div>
<div class="text">
<div class="condition line1">
{{ item.couponTitle }}
</div>
<div class="data acea-row row-between-wrapper">
<div v-if="item.endTime === 0">不限时</div>
<div v-else>{{ item.createTime }}-{{ item.endTime }}</div>
<div class="bnt gray" v-if="item._type === 0">{{ item._msg }}</div>
<div class="bnt bg-color-red" v-else>{{ item._msg }}</div>
</div>
</div>
</div>
</div>
<!--暂无优惠券-->
<view
class="noCommodity"
v-if="couponsList.length === 0 && loading === true"
>
<view class="noPictrue">
<image src="http://admin-api.xdd618.com/file/pic/20210203154207179472.png" class="image"/>
</view>
</view>
</view>
</template>
<script>
import {getCouponsUser} from "@/api/user";
import DataFormatT from "@/components/DataFormatT";
const NAME = "UserCoupon";
export default {
name: "UserCoupon",
components: {
DataFormatT
},
props: {},
data: function () {
return {
couponsList: [],
loading: false
};
},
watch: {
$yroute: function (n) {
var that = this;
if (n.name === NAME) {
that.getUseCoupons();
}
}
},
mounted: function () {
this.getUseCoupons();
},
methods: {
getUseCoupons: function () {
let that = this,
type = 0;
getCouponsUser(type).then(res => {
that.couponsList = res.data;
that.loading = true;
});
}
}
};
</script>
+33
View File
@@ -0,0 +1,33 @@
<template>
<view class="cash-audit">
<view class="pictrue">
<image :src="`${staticUrl}/examine.png`" />
</view>
<view class="tip">提现申请已提交等待人工审核</view>
<view class="time">{{ time }}</view>
<view class="bnt bg-color-red" @click="goUserPromotion()">好的</view>
</view>
</template>
<script>
export default {
name: "CashAudit",
components: {},
props: {},
data: function() {
return {
staticUrl:this.$STATIC_RESOURCE_URL,
time: ""
};
},
mounted: function() {
let myData = new Date();
this.time = myData.toLocaleString();
},
methods: {
goUserPromotion() {
this.$yrouter.back();
// this.$yrouter.push({ path: "/pages/user/promotion/UserPromotion/index" });
}
}
};
</script>
+162
View File
@@ -0,0 +1,162 @@
<template>
<view class="commission-details" ref="container">
<view class="promoterHeader bg-color-red">
<view class="headerCon acea-row row-between-wrapper">
<view>
<view class="name">提现记录</view>
<view class="money">
<text class="num">{{ force2Decimal(commission) }}</text>
</view>
</view>
<view class="iconfont icon-jinbi1"></view>
</view>
</view>
<view class="sign-record" ref="content">
<view class="list">
<view class="item">
<view class="listn" v-for="(item, infoIndex) in info" :key="infoIndex">
<view class="itemn acea-row row-column row-center">
<view class="acea-row row-middle row-between">
<view class="txt">提现金额:<text class="font-color-red">{{ force2Decimal(item.extractPrice) }}</text></view>
<view class="txt">手续费:<text class="font-color-red">{{ force2Decimal(item.extractSxf) }}</text></view>
</view>
<view class="txt" v-if="item.status==-1">失败原因:{{item.failMsg}}</view>
<view class="acea-row row-middle row-between row-center">
<view class="txt">{{item.createTime}}</view>
<view class="txt font-color-green">{{item.statusText}}</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- <view class="sign-record" ref="content">
<view class="list">
<view class="item" v-for="(item, infoIndex) in info" :key="infoIndex">
<view class="data">{{ item.time }}</view>
<view class="listn" v-for="(val, indexn) in item.list" :key="indexn">
<view class="itemn acea-row row-between-wrapper">
<view>
<view class="name line1">{{ val.title }}</view>
<view>{{ val.addTime }}</view>
</view>
<view class="num" v-if="val.pm == 1">+{{ force2Decimal(val.number) }}</view>
<view class="num font-color-red" v-if="val.pm == 0">-{{ force2Decimal(val.number) }}</view>
</view>
</view>
</view>
</view>
</view> -->
<Loading :loaded="loaded" :loading="loading"></Loading>
</view>
</template>
<script>
import { getCommissionInfo, getSpreadInfo,getWithdrawalRecordList } from "@/api/user";
import Loading from "@/components/Loading";
import { formatDateTime,isNullOrEmpty} from "@/utils";
export default {
name: "CashRecord",
components: {
Loading
},
props: {},
data: function() {
return {
info: [],
commission: 0,
where: {
page: 1,
limit: 10
},
types: 4,
loaded: false,
loading: false
};
},
mounted: function() {
this.getCommission();
this.getIndex();
},
onReachBottom() {
this.loading === false && this.getIndex();
},
methods: {
fitDateString(str,format){
return formatDateTime(str,format);
},
force2Decimal(v){
return this.$force2Decimal(v);
},
getIndex: function() {
let that = this;
if (that.loading == true || that.loaded == true) return;
that.loading = true;
getWithdrawalRecordList(that.where).then(
//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.info.push.apply(that.info, res.data.map((item)=>{
switch (item.status){
case -1:
item.statusText = "提现未通过";
break;
case 0:
item.statusText = "提现审核中";
break;
case 1:
item.statusText = "提现已完成";
break;
case 2:
item.statusText = "提现待打款";
break;
default:
break;
}
return item;
}));
},
err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: 'none',
duration: 2000
});
}
);
},
getCommission: function() {
let that = this;
getSpreadInfo().then(
res => {
that.commission = res.data.commissionCount;
},
err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: "none",
duration: 2000
});
}
);
}
}
};
</script>
<style>
.txt{
font-size: 28rpx;
color: #282828;
margin-bottom: 10rpx;
}
.sign-record .list .item .listn .itemn{
height: auto;
padding-top: 10rpx;
}
</style>
@@ -0,0 +1,113 @@
<template>
<view class="commission-details" ref="container">
<view class="promoterHeader bg-color-red">
<view class="headerCon acea-row row-between-wrapper">
<view>
<view class="name">佣金明细</view>
<view class="money">
<text class="num">{{ force2Decimal(commission) }}</text>
</view>
</view>
</view>
</view>
<view class="sign-record" ref="content">
<view class="list">
<view class="item" v-for="(item, infoIndex) in info" :key="infoIndex">
<view class="data">{{ item.time }}</view>
<view class="listn" v-for="(val, indexn) in item.list" :key="indexn">
<view class="itemn acea-row row-between-wrapper">
<view>
<view class="name line1">{{ val.title }}</view>
<view>{{ val.addTime }}</view>
</view>
<view class="">
<view class="" style="flex-shrink: 0;text-align: right;">{{val.status==0?"待收货确定":(val.status==1?"有效":"无效")}}</view>
<view class="">
<view class="num" v-if="val.pm == 1">+{{ force2Decimal(val.number) }}</view>
<view class="num font-color-red" v-if="val.pm == 0">
-{{ force2Decimal(val.number) }}
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
</view>
</template>
<script>
import { getCommissionInfo, getSpreadInfo } from "@/api/user";
import Loading from "@/components/Loading";
export default {
name: "CommissionDetails",
components: {
Loading
},
props: {},
data: function() {
return {
info: [],
commission: 0,
where: {
page: 1,
limit: 3
},
types: 9,//3,
loaded: false,
loading: false
};
},
mounted: function() {
this.getCommission();
this.getIndex();
},
onReachBottom() {
this.loading === false && this.getIndex();
},
methods: {
force2Decimal(v){
return this.$force2Decimal(v);
},
getIndex: function() {
let that = this;
if (that.loading == true || that.loaded == true) return;
that.loading = true;
getCommissionInfo(that.where, that.types).then(
res => {
that.loading = false;
that.loaded = res.data.length < that.where.limit;
that.loadTitle = that.loaded ? "人家是有底线的" : "上拉加载更多";
that.where.page = that.where.page + 1;
that.info.push.apply(that.info, res.data);
},
err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: 'none',
duration: 2000
});
}
);
},
getCommission: function() {
let that = this;
getSpreadInfo().then(
res => {
that.commission = res.data.commissionCount;
},
err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: 'none',
duration: 2000
});
}
);
}
}
};
</script>
+160
View File
@@ -0,0 +1,160 @@
<template>
<view class="distribution-posters">
<view class="slider-banner banner">
<swiper indicatorDots="true">
<block v-for="(item, infoIndex) in info" :key="infoIndex">
<swiper-item>
<image
class="slide-image"
:src="item.wap_poster"
mode="widthFix"
show-menu-by-longpress
/>
</swiper-item>
</block>
</swiper>
</view>
<view class="keep bg-color-red" @click="saveImg">保存海报</view>
</view>
</template>
<script>
// import { swiper, swiperSlide } from "vue-awesome-swiper";
import { getSpreadImg } from "@/api/user";
export default {
name: "Poster",
components: {
// swiper,
// swiperSlide
},
props: {},
data: function() {
return {
swiperPosters: {
speed: 1000,
effect: "coverflow",
slidesPerView: "auto",
centeredSlides: true,
coverflowEffect: {
rotate: 0, // 旋转的角度
stretch: -20, // 拉伸 图片间左右的间距和密集度
depth: 100, // 深度 切换图片间上下的间距和密集度
modifier: 3, // 修正值 该值越大前面的效果越明显
slideShadows: false // 页面阴影效果
},
observer: true,
observeParents: true
},
info: [],
activeIndex: 0
};
},
mounted: function() {
this.getIndex();
let that = this;
// this.swiper.on("slideChange", function() {
// that.activeIndex = that.swiper.activeIndex;
// });
},
computed: {
swiper() {
// return this.$refs.mySwiper.swiper;
}
},
methods: {
getIndex: function() {
let that = this;
let from = {};
if (this.$deviceType == "app") {
from.from = "app";
}
getSpreadImg(from).then(
res => {
that.info = res.data;
},
err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: "none",
duration: 2000
});
}
);
},
downloadIamge: function(imgsrc, name) {
var that = this;
this.isDown = true;
var downloadUrl = imgsrc;
if (!wx.saveImageToPhotosAlbum) {
uni.showModal({
title: "提示",
content:
"当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。"
});
that.openDialogVisible = true;
return;
}
// 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.writePhotosAlbum" 这个 scope
wx.getSetting({
success(res) {
if (!res.authSetting["scope.writePhotosAlbum"]) {
that.openDialogVisible = true;
// 接口调用询问
wx.authorize({
scope: "scope.writePhotosAlbum",
success() {
that.downloadImage(downloadUrl);
},
fail() {
// 用户拒绝了授权
// 打开设置页面
wx.openSetting({
success: function(data) {},
fail: function(data) {}
});
}
});
} else {
that.downloadImage(downloadUrl);
}
},
fail(res) {
that.openDialogVisible = true;
}
});
},
saveImg: function() {
this.downloadIamge(
this.info[this.activeIndex].wap_poster,
"poster" + this.activeIndex
);
}
}
};
</script>
<style lang="less">
page {
height: 100%;
}
.distribution-posters {
height: 100%;
}
.banenr {
height: 100%;
}
.banner swiper {
height: 100%;
}
.banner .slide-image {
width: 100%;
height: auto;
}
</style>
+356
View File
@@ -0,0 +1,356 @@
<template>
<view class="promoter-list" ref="container">
<view class="header">
<!-- 搜索开始 -->
<view class="search acea-row row-between-wrapper" style="background-color: #F5F5F5 !important;margin-top: 22rpx;">
<form @submit.prevent="submitForm" style="width: 100% !important;">
<view class="input" style="text-align: left !important;background: #fff !important;width: auto !important;">
<text class="iconfont icon-sousuo2"
style="left: 28rpx !important;right: auto !important;margin-right: 10rpx;font-size: 32rpx !important;color: #9D9D9D !important;"></text>
<input style="margin-left: 70rpx !important;text-align: left !important;color: #CCCCCC !important;"
placeholder="点击搜索会员名称" placeholder-style="color:#CCCCCC" v-model="screen.keyword"
@confirm="submitForm"/>
<!-- <text class="iconfont icon-guanbi"></text> -->
</view>
</form>
</view>
<!-- 搜索结束 -->
<view class="promoterHeader" style="height: 160rpx !important;">
<view class="headerCon acea-row row-between-wrapper"
style="width: auto !important;padding: 0 32rpx !important;">
<view class="acea-row row-column">
<view class="name"
style="color: #000000 !important;font-size: 32rpx !important;font-weight: 500;margin-bottom: 20rpx;">
{{ first + second || '0' }}
</view>
<view style="color: #8C8C8C;font-size: 24rpx;"> 推广人数()</view>
</view>
<view class="acea-row row-middle">
<view class="dropDownBtn acea-row row-middle row-center" @click="changeGrade()">
<text style="color: #fff;font-size: 24rpx;margin-right: 28rpx;">
{{ screen.grade == 0 ? '一级' : '二级' }}
</text>
<image style="width: 24rpx;height: 12rpx;" :src="webUrl+'/20210819151908963957.png'" mode=""></image>
</view>
</view>
</view>
</view>
<!-- 一二级筛选 -->
<!-- <view class="nav acea-row row-around">
<view
class="item"
:class="screen.grade == 0 ? 'on' : ''"
@click="checkGrade(0)"
>一级({{ first||'0' }})</view>
<view
class="item"
:class="screen.grade == 1 ? 'on' : ''"
@click="checkGrade(1)"
>二级({{ second||'0' }})</view>
</view> -->
<!-- 一二级筛选 -->
</view>
<view class="list">
<view class="sortNav acea-row row-middle" :class="fixedState === true ? 'on' : ''">
<view class="sortItem" :style="(childCount === 1 || childCount === 3) ? 'color:#0DC5C5' : ''"
@click="sort('childCount')">
团队排序
<image :src="webUrl+'/20230304204227252460.png'" v-if="childCount == 1"/>
<image :src="webUrl+'/20230304204233362231.png'" v-if="childCount == 2"/>
<image :src="webUrl+'/20230304204240497772.png'" v-if="childCount == 3"/>
</view>
<view class="sortItem" :style="(numberCount === 1 || numberCount === 3) ? 'color:#0DC5C5' : ''"
@click="sort('numberCount')">
金额排序
<image :src="webUrl+'/20230304204227252460.png'" v-if="numberCount == 1"/>
<image :src="webUrl+'/20230304204233362231.png'" v-if="numberCount == 2"/>
<image :src="webUrl+'/20230304204240497772.png'" v-if="numberCount == 3"/>
</view>
<view class="sortItem" :style="(orderCount === 1 || orderCount === 3) ? 'color:#0DC5C5' : ''"
@click="sort('orderCount')">
订单排序
<image :src="webUrl+'/20230304204227252460.png'" v-if="orderCount == 1"/>
<image :src="webUrl+'/20230304204233362231.png'" v-if="orderCount == 2"/>
<image :src="webUrl+'/20230304204240497772.png'" v-if="orderCount == 3"/>
</view>
<view class="sortItem" :style="(levelCount === 1 || levelCount === 3) ? 'color:#0DC5C5' : ''"
@click="sort('levelCount')">
等级排序
<image :src="webUrl+'/20230304204227252460.png'" v-if="levelCount == 1"/>
<image :src="webUrl+'/20230304204233362231.png'" v-if="levelCount == 2"/>
<image :src="webUrl+'/20230304204240497772.png'" v-if="levelCount == 3"/>
</view>
</view>
<view :class="fixedState === true ? 'sortList' : ''">
<view
class="item acea-row row-between-wrapper"
v-for="(val, spreadListIndex) in spreadList"
:key="spreadListIndex"
>
<view class="picTxt acea-row row-between-wrapper" style="flex-wrap: nowrap;">
<view class="" style="width: 60rpx;word-wrap: break-word;text-align: center;margin-right: 8rpx;">
{{ spreadListIndex + 1 }}
</view>
<view class="pictrue" style="flex-shrink: 0;margin-right: 8rpx;">
<image :src="val.avatar"/>
</view>
<view class="text">
<view class="name line1 acea-row row-middle">{{ val.nickname }}
<text class="levelBox">{{ val.levelName }}</text>
</view>
<view style="color: #999999 !important;">加入时间: {{ val.time }}</view>
</view>
</view>
<view class="right">
<view>
<text class="font-color-red">{{ val.childCount }}</text>
</view>
<view>{{ val.orderCount }}</view>
<view>
<text class="font-color-red">{{ val.numberCount ? val.numberCount : 0 }}</text>
</view>
</view>
</view>
</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
</view>
</template>
<script>
import {getSpreadUser} from "@/api/user";
import Loading from "@/components/Loading";
export default {
name: "PromoterList",
components: {
Loading
},
props: {},
data: function () {
return {
fixedState: false,
screen: {
page: 1,
limit: 15,
grade: 0,
keyword: "",
sort: ""
},
childCount: 2,
numberCount: 2,
orderCount: 2,
levelCount: 2,
loaded: false,
loading: false,
spreadList: [],
loadTitle: "",
first: "",
second: "",
webUrl: this.$VUE_APP_RESOURCES_URL
};
},
mounted: function () {
this.getSpreadUsers();
},
onReachBottom() {
!this.loading && this.getSpreadUsers();
},
watch: {
"screen.sort": function () {
this.screen.page = 1;
this.loaded = false;
this.loading = false;
this.spreadList = [];
this.getSpreadUsers();
}
},
methods: {
changeGrade: function () {
var that = this;
uni.showActionSheet({
itemList: ['一级', '二级'],
success: function (res) {
console.log('选中了第' + (res.tapIndex + 1) + '个按钮');
that.checkGrade(res.tapIndex);
},
fail: function (res) {
}
});
},
handleScroll: function () {
// var scrollTop =
// document.documentElement.scrollTop || document.body.scrollTop;
// var offsetTop = document.querySelector(".header").clientHeight;
// if (scrollTop >= offsetTop) {
// this.fixedState = true;
// } else {
// this.fixedState = false;
// }
},
submitForm: function () {
this.screen.page = 1;
this.loaded = false;
this.loading = false;
this.spreadList = [];
this.getSpreadUsers();
},
getSpreadUsers: function () {
let that = this,
screen = that.screen;
if (that.loaded || that.loading) return;
that.loading = true;
getSpreadUser(screen).then(
res => {
that.loading = false;
that.spreadList.push.apply(that.spreadList, res.data.list);
that.loaded = res.data.list.length < that.screen.limit; //判断所有数据是否加载完成;
that.loadTitle = that.loaded ? "人家是有底线的" : "上拉加载更多";
that.screen.page = that.screen.page + 1;
that.first = res.data.total;
that.second = res.data.totalLevel;
},
err => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
},
300
);
},
checkGrade: function (val) {
if (val == this.screen.grade) return;
else {
this.screen.page = 1;
this.screen.grade = val;
this.loading = false;
this.loaded = false;
this.spreadList = [];
this.getSpreadUsers();
}
},
sort: function (types) {
let that = this;
switch (types) {
case "childCount":
if (that.childCount == 2) {
that.childCount = 1;
that.orderCount = 2;
that.numberCount = 2;
that.levelCount = 2;
that.screen.sort = "childCount DESC";
} else if (that.childCount == 1) {
that.childCount = 3;
that.orderCount = 2;
that.numberCount = 2;
that.levelCount = 2;
that.screen.sort = "childCount ASC";
} else if (that.childCount == 3) {
that.childCount = 2;
that.orderCount = 2;
that.numberCount = 2;
that.levelCount = 2;
that.screen.sort = "";
}
break;
case "numberCount":
if (that.numberCount == 2) {
that.numberCount = 1;
that.orderCount = 2;
that.childCount = 2;
that.levelCount = 2;
that.screen.sort = "numberCount DESC";
} else if (that.numberCount == 1) {
that.numberCount = 3;
that.orderCount = 2;
that.childCount = 2;
that.levelCount = 2;
that.screen.sort = "numberCount ASC";
} else if (that.numberCount == 3) {
that.numberCount = 2;
that.orderCount = 2;
that.childCount = 2;
that.levelCount = 2;
that.screen.sort = "";
}
break;
case "orderCount":
if (that.orderCount == 2) {
that.orderCount = 1;
that.numberCount = 2;
that.childCount = 2;
that.levelCount = 2;
that.screen.sort = "orderCount DESC";
} else if (that.orderCount == 1) {
that.orderCount = 3;
that.numberCount = 2;
that.childCount = 2;
that.levelCount = 2;
that.screen.sort = "orderCount ASC";
} else if (that.orderCount == 3) {
that.orderCount = 2;
that.numberCount = 2;
that.childCount = 2;
that.levelCount = 2;
that.screen.sort = "";
}
break;
case "levelCount":
if (that.levelCount == 2) {
that.levelCount = 1;
that.orderCount = 2;
that.numberCount = 2;
that.childCount = 2;
that.screen.sort = "level desc";
} else if (that.levelCount == 1) {
that.levelCount = 3;
that.orderCount = 2;
that.numberCount = 2;
that.childCount = 2;
that.screen.sort = "level ASC";
} else if (that.levelCount == 3) {
that.levelCount = 2;
that.orderCount = 2;
that.numberCount = 2;
that.childCount = 2;
that.screen.sort = "";
}
break;
default:
that.screen.sort = "";
}
}
}
};
</script>
<style scoped>
.dropDownBtn {
width: 176rpx;
height: 60rpx;
background: #0DC5C5;
box-shadow: 0px 8rpx 14rpx rgba(179, 188, 191, 0.6);
opacity: 1;
border-radius: 8rpx;
}
.levelBox {
padding: 0 10rpx;
font-size: 18rpx;
line-height: 28rpx;
height: 28rpx;
background: #FF564A;
color: #fff;
border-radius: 14rpx;
margin-left: 14rpx;
}
</style>
@@ -0,0 +1,123 @@
<template>
<view class="promoter-order" ref="container">
<view class="promoterHeader bg-color-red">
<view class="headerCon acea-row row-between-wrapper" style="flex-wrap: nowrap;">
<view style="flex-shrink: 0;margin-right: 40rpx;">
<text class="name">累计推广订单</text>
<view>
<text class="num">{{ count||'0' }}</text>
<text></text>
</view>
</view>
<view class="" style="flex-grow: 1;font-size: 24rpx;">
返佣说明1.下线客户下单成功后平台设置为默认7天收货成功佣金便自动计算添加到上线的返佣2.如过程中下单客户有退货退款则此订单返佣无效会自动取消或相应扣除
</view>
</view>
</view>
<view class="list">
<view class="item" v-for="(item, listIndex) in list" :key="listIndex">
<view class="title acea-row row-column row-center">
<view class="data">{{ item.time }}</view>
<text>本月累计推广订单{{ item.count ? item.count : 0 }}</text>
</view>
<view class="listn">
<view class="itenm" v-for="(val, indexn) in item.child" :key="indexn">
<view class="top acea-row row-between-wrapper">
<view class="pictxt acea-row row-between-wrapper">
<view class="pictrue">
<image :src="val.avatar" />
</view>
<text class="text line1">{{ val.nickname }}</text>
</view>
<view class="money">
<text>返佣</text>
<text class="font-color-red">{{ val.number ? val.number : 0 }}</text>
</view>
</view>
<view class="bottom">
<view class="acea-row row-between" style="flex-wrap: nowrap;">
<view style="flex-grow: 1;">
<text class="name">订单金额</text>
<text class="font-color-red">{{ val.payPrice || 0 }}({{ val.totalPrice || 0 }}+{{ val.totalPostage || 0 }}运费)</text>
</view>
<view class="" style="flex-shrink: 0;">{{val.billStatus==0?"待收货确定":(val.billStatus==1?"有效":"无效")}}</view>
</view>
<view>
<text class="name">订单号</text>
{{ val.orderId }}
</view>
<view>
<text class="name">下单时间</text>
{{ val.time }}
</view>
</view>
</view>
</view>
</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
</view>
</template>
<script>
import { getSpreadOrder } from "@/api/user";
import Loading from "@/components/Loading";
export default {
name: "PromoterOrder",
components: {
Loading
},
props: {},
data: function() {
return {
list: [],
where: {
page: 1,
limit: 15
},
loaded: false,
loading: false,
loadTitle: "",
count: ""
};
},
mounted: function() {
this.getIndex();
},
onReachBottom() {
!this.loading && this.getIndex();
},
methods: {
getIndex: function() {
let there = this;
if (there.loaded == true || there.loading == true) return;
there.loading = true;
getSpreadOrder(there.where).then(
res => {
there.loading = false;
there.loaded = res.data.list.length < there.where.limit;
there.loadTitle = there.loaded ? "人家是有底线的" : "上拉加载更多";
there.where.page = there.where.page + 1;
there.list.push.apply(there.list, res.data.list);
there.count = res.data.count;
},
err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: "none",
duration: 2000
});
},
300
);
}
}
};
</script>
<style>
.promoterHeader .headerCon{
width: auto !important;
padding: 0 20rpx 0 20rpx !important;
}
</style>
+212
View File
@@ -0,0 +1,212 @@
<template>
<view class="cash-withdrawal">
<view class="nav acea-row">
<view
v-for="(item, navListIndex) in navList"
class="item font-color-red"
@click="swichNav(navListIndex, item)"
:key="navListIndex"
>
<view class="line bg-color-red" :class="currentTab === navListIndex ? 'on' : ''"></view>
<view class="iconfont" :class="item.icon + ' ' + (currentTab === navListIndex ? 'on' : '')"></view>
<view>{{ item.name }}</view>
</view>
</view>
<view class="wrapper">
<view :hidden="currentTab !== 0" class="list">
<view class="item acea-row row-between-wrapper">
<view class="name">微信号</view>
<view class="input">
<input placeholder="请输入微信号" v-model="post.weixin" />
</view>
</view>
<view class="item acea-row row-between-wrapper">
<view class="name">提现</view>
<view class="input">
<input :placeholder="'最低提现金额' + minPrice" v-model="post.money" />
</view>
</view>
<view class="tip">当前可提现金额: {{ commissionCount }}</view>
<view class="bnt bg-color-red" @click="submitted">提现</view>
</view>
<view :hidden="currentTab !== 1" class="list">
<view class="item acea-row row-between-wrapper">
<view class="name">用户名</view>
<view class="input">
<input placeholder="请填写您的支付宝用户名" v-model="post.name" />
</view>
</view>
<view class="item acea-row row-between-wrapper">
<view class="name">账号</view>
<view class="input">
<input placeholder="请填写您的支付宝账号" v-model="post.alipay_code" />
</view>
</view>
<view class="item acea-row row-between-wrapper">
<view class="name">提现</view>
<view class="input">
<input :placeholder="'最低提现金额' + minPrice" v-model="post.money" />
</view>
</view>
<view class="tip">当前可提现金额: {{ commissionCount }}</view>
<view class="bnt bg-color-red" @click="submitted">提现</view>
</view>
</view>
</view>
</template>
<script>
import { getBank, postCashInfo } from "@/api/user";
import { required } from "@/utils/validate";
import { validatorDefaultCatch } from "@/utils/dialog";
export default {
name: "UserCash",
components: {},
props: {},
data: function() {
return {
navList: [
{ name: "微信", type: "weixin", icon: "icon-weixin2" },
{ name: "支付宝", type: "alipay", icon: "icon-icon34" }
],
post: {
extract_type: "weixin",
alipay_code: "",
money: "",
name: "",
bankname: "",
cardnum: "",
weixin: ""
},
currentTab: 0,
minPrice: 0,
banks: [],
commissionCount: 0
};
},
mounted: function() {
this.getBank();
},
methods: {
swichNav: function(index, item) {
console.log(item);
this.currentTab = index;
this.post.extract_type = item.type;
},
getBank: function() {
let that = this;
getBank().then(
res => {
that.banks = res.data.extractBank;
that.minPrice = res.data.minPrice;
that.commissionCount = res.data.commissionCount;
},
function(err) {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: "none",
duration: 2000
});
}
);
},
async submitted() {
let bankname = this.post.bankname,
alipay_code = this.post.alipay_code,
money = this.post.money,
name = this.post.name,
cardnum = this.post.cardnum,
weixin = this.post.weixin,
that = this;
// console.log(parseFloat(money))
if (
parseFloat(money) > parseFloat(that.commissionCount) ||
parseFloat(that.commissionCount) == 0
)
return that.$dialog.message("余额不足");
if (parseFloat(money) < parseFloat(that.minPrice))
return that.$dialog.message("最低提现金额" + that.minPrice);
//console.log(that.post.extract_type)
switch (that.post.extract_type) {
case "alipay":
// if (!name) {
// uni.showToast({
// title: "请输入支付宝用户名",
// icon: "none",
// duration: 2000
// });
// return;
// }
// if (!alipay_code) {
// uni.showToast({
// title: "请输入支付宝账号",
// icon: "none",
// duration: 2000
// });
// return;
// }
// if (!money) {
// uni.showToast({
// title: "请输入提现金额",
// icon: "none",
// duration: 2000
// });
// return;
// }
try {
await this.$validator({
name: [required(required.message("支付宝用户名"))],
alipay_code: [required(required.message("支付宝账号"))],
money: [required(required.message("提现金额"))]
}).validate({ name, alipay_code, money });
let save = {
extractType: that.post.extract_type,
alipayCode: alipay_code,
name: name,
money: money
};
that.save(save);
} catch (e) {
return validatorDefaultCatch(e);
}
break;
case "weixin":
try {
await this.$validator({
weixin: [required(required.message("提现微信号"))],
money: [required(required.message("提现金额"))]
}).validate({ weixin, money });
let save = {
extractType: that.post.extract_type,
weixin: weixin,
money: money
};
that.save(save);
} catch (e) {
return validatorDefaultCatch(e);
}
break;
}
},
save: function(info) {
postCashInfo(info).then(
res => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
this.router.push({ path: "/user/audit" });
},
err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: "none",
duration: 2000
});
}
);
}
}
};
</script>
@@ -0,0 +1,241 @@
<template>
<view class="my-promotion">
<view class="topBanner acea-row row-middle row-center">
<view class="item acea-row row-column">
<view class="itemValue">{{ force2Decimal(Info.commissionCount) }}</view>
<view class="itemTitle">当前佣金</view>
</view>
<view class="vline"></view>
<view class="item acea-row row-column">
<view class="itemValue">{{ force2Decimal(Info.lastDayCount) }}</view>
<view class="itemTitle">今日收益</view>
</view>
<view class="vline"></view>
<view class="item acea-row row-column">
<view class="itemValue">{{ force2Decimal(Info.extractCount) }}</view>
<view class="itemTitle">累计已提</view>
</view>
</view>
<view class="acea-row row-right">
<view class="withdrawRecordBtn acea-row row-middle row-center" @click="goCashRecord()">
<image :src="webUrl+'/20210819120620545726.png'" mode="" style="width: 24rpx;height: 24rpx;margin-right: 10rpx;"></image>
<text style="color: #fff;font-size: 24rpx;">提现记录</text>
</view>
</view>
<view class="menu-list acea-row row-column">
<view class="menu-item acea-row row-middle" @click="goPromoterList()">
<image class="menu-item-img" :src="webUrl+'/20210819120915878640.png'" mode=""></image>
<text class="menu-item-title">推广统计</text>
<text class="iconfont icon-jiantou" style="font-size: 24rpx;color: #999999;"></text>
</view>
<view class="menu-item acea-row row-middle" @click="goCommissionDetails()">
<image class="menu-item-img" :src="webUrl+'/20210819133737716135.png'" mode=""></image>
<text class="menu-item-title">佣金明细</text>
<text class="iconfont icon-jiantou" style="font-size: 24rpx;color: #999999;"></text>
</view>
<view class="menu-item acea-row row-middle" @click="goPromoterOrder()">
<image class="menu-item-img" :src="webUrl+'/20210819133751983817.png'" mode=""></image>
<text class="menu-item-title">推广人订单</text>
<text class="iconfont icon-jiantou" style="font-size: 24rpx;color: #999999;"></text>
</view>
<view class="menu-item acea-row row-middle" @click="toCash()">
<image class="menu-item-img" :src="webUrl+'/20210819133726059725.png'" mode=""></image>
<text class="menu-item-title">立即提现</text>
<text class="iconfont icon-jiantou" style="font-size: 24rpx;color: #999999;"></text>
</view>
</view>
<!-- <view class="header">
<view class="name acea-row row-center-wrapper">
<view>当前佣金</view>
<view class="record" @click="goCashRecord()">
提现记录
<text class="iconfont icon-xiangyou"></text>
</view>
</view>
<view class="num">{{ force2Decimal(Info.commissionCount) }}</view>
<view class="profit acea-row row-between-wrapper">
<view class="item">
<view>今日收益</view>
<view class="money">{{ force2Decimal(Info.lastDayCount) }}</view>
</view>
<view class="item">
<view>累积已提</view>
<view class="money">{{ force2Decimal(Info.extractCount) }}</view>
</view>
</view>
</view>
<view class="list acea-row row-between-wrapper">
<view class="item acea-row row-center-wrapper row-column" @click="goPoster()">
<text class="iconfont icon-erweima"></text>
<view>推广名片</view>
</view>
<view class="item acea-row row-center-wrapper row-column" @click="goPromoterList()">
<text class="iconfont icon-tongji"></text>
<view>推广人统计</view>
</view>
<view class="item acea-row row-center-wrapper row-column" @click="goCommissionDetails()">
<text class="iconfont icon-qiandai"></text>
<view>佣金明细</view>
</view>
<view class="item acea-row row-center-wrapper row-column" @click="goPromoterOrder()">
<text class="iconfont icon-dingdan"></text>
<view>推广人订单</view>
</view>
<view class="item acea-row row-center-wrapper row-column" @click="toCash()">
<text class="iconfont icon-chongzhi"></text>
<view>立即提现</view>
</view>
</view> -->
</view>
</template>
<script>
import { getSpreadInfo } from "@/api/user";
export default {
name: "UserPromotion",
components: {},
props: {},
data: function() {
return {
Info: {
lastDayCount: 0,
extractCount: 0,
commissionCount: 0
},
webUrl:this.$VUE_APP_RESOURCES_URL
};
},
mounted: function() {
},
onShow:function(){
this.getInfo();
},
methods: {
force2Decimal(v){
return this.$force2Decimal(v);
},
goPoster() {
this.$yrouter.push("/pages/user/promotion/Poster/index");
},
goCashRecord() {
this.$yrouter.push("/pages/user/promotion/CashRecord/index");
},
goPromoterList() {
this.$yrouter.push("/pages/user/promotion/PromoterList/index");
},
goCommissionDetails() {
this.$yrouter.push("/pages/user/promotion/CommissionDetails/index");
},
goPromoterOrder() {
this.$yrouter.push("/pages/user/promotion/PromoterOrder/index");
},
getInfo: function() {
let that = this;
getSpreadInfo().then(
res => {
that.Info = res.data;
},
function(err) {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: 'none',
duration: 2000
});
}
);
},
toCash: function() {
this.$yrouter.push("/pkg_user/views/withdrawal");
}
}
};
</script>
<style lang="less">
.my-promotion{
padding: 32rpx;
}
.my-promotion .header{
background-image: none !important;
background-color: #FE5261;
}
.my-promotion .list .item .iconfont{
color: #FE5261 !important;
}
.topBanner{
height: 180rpx;
background: #FFFFFF;
box-shadow: 0px 6rpx 16rpx rgba(232, 236, 241, 0.5);
border-radius: 16rpx;
padding: 32rpx;
}
.topBanner .item{
flex: 1;
}
.topBanner .item .itemValue{
color: #333333;
font-size: 36rpx;
text-align: center;
}
.topBanner .item .itemTitle{
color: #999999;
font-size: 22rpx;
text-align: center;
}
.vline{
background-color: #E3E3E3;
width: 1px;
height: 64rpx;
margin: 0 10rpx;
}
.withdrawRecordBtn{
width: 174rpx;
height: 60rpx;
background: #0DC5C5;
box-shadow: 0px 8rpx 14rpx rgba(179, 188, 191, 0.6);
border-radius: 8rpx;
margin: 32rpx 0;
}
.menu-list{
}
.menu-list .menu-item{
padding: 24rpx;
background: #FFFFFF;
box-shadow: 0px 6rpx 16rpx rgba(232, 236, 241, 0.5);
border-radius: 16rpx;
margin-bottom: 18rpx;
}
.menu-list .menu-item .menu-item-title{
font-size: 24rpx;
font-weight: 500;
color: #333333;
flex-grow: 1;
}
.menu-list .menu-item .menu-item-img{
width: 40rpx;
height: 40rpx;
flex-shrink:0;
margin-right: 16rpx;
}
</style>
+151
View File
@@ -0,0 +1,151 @@
<template>
<view class="integral-details" ref="container">
<view class="header">
<view class="currentScore">当前积分</view>
<view>{{ info.integral }}</view>
<view class="line"></view>
<!--<view class="nav acea-row">-->
<!--<view class="item">-->
<!--<view class="num">{{ info.sum_integral }}</view>-->
<!--<view>累计积分</view>-->
<!--</view>-->
<!--<view class="item">-->
<!--<view class="num">{{ info.deduction_integral }}</view>-->
<!--<view>累计消费</view>-->
<!--</view>-->
<!--<view class="item">-->
<!--<view class="num">{{ info.today_integral }}</view>-->
<!--<view>今日获得</view>-->
<!--</view>-->
<!--</view>-->
</view>
<view class="wrapper">
<view class="nav acea-row">
<view
class="item acea-row row-center-wrapper"
:class="current === navListIndex ? 'on' : ''"
v-for="(item, navListIndex) in navList"
:key="navListIndex"
@click="nav(navListIndex)"
>
<text class="iconfont" :class="item.icon"></text>
{{ item.name }}
</view>
</view>
<view class="list" :hidden="current !== 0">
<!--<view class="tip acea-row row-middle">-->
<!--<text class="iconfont icon-shuoming"><text-->
<!--&gt;提示积分数值的高低会直接影响您的会员等级-->
<!--</view>-->
<view
class="item acea-row row-between-wrapper"
v-for="(item, listIndex) in list"
:key="listIndex"
>
<view>
<text class="state">{{ item.title }}</text>
<view>
<data-format :date="item.addTime"></data-format>
</view>
</view>
<text class="num" v-if="item.pm == 1">+{{ item.number }}</text>
<text class="num font-color-red" v-if="item.pm == 0">-{{ item.number }}</text>
</view>
</view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
</view>
</template>
<script>
import { getIntegralList, postSignUser } from "@/api/user";
import Loading from "@/components/Loading";
import DataFormat from "@/components/DataFormat";
export default {
name: "Integral",
components: {
Loading,
DataFormat
},
props: {},
data: function() {
return {
navList: [
{ name: "分值明细", icon: "icon-mingxi" }
// { name: "分值提升", icon: "icon-tishengfenzhi" }
],
current: 0,
where: {
page: 1,
limit: 15
},
data: {
sign: 1,
integral: 1,
all: 1
},
list: [],
info: [],
loaded: false,
loading: false
};
},
mounted: function() {
this.getIntegral();
this.getInfo();
},
onReachBottom() {
!this.loading && this.getInfo();
},
methods: {
goSignIn() {
this.$yrouter.push("/pages/user/signIn/Sign/index");
},
goHome() {
this.$yrouter.switchTab("/pages/home/index");
},
nav: function(index) {
this.current = index;
},
getInfo: function() {
let that = this;
if (that.loaded == true || that.loading == true) return;
that.loading = true;
getIntegralList(that.where).then(
res => {
that.loading = false;
that.loaded = res.data.length < that.where.limit;
that.loadTitle = that.loaded ? "人家是有底线的" : "上拉加载更多";
that.where.page = that.where.page + 1;
that.list.push.apply(that.list, res.data);
},
err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: 'none',
duration: 2000
});
}
);
},
getIntegral: function() {
let that = this;
postSignUser(that.data).then(
res => {
that.info = res.data;
},
err => {
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: 'none',
duration: 2000
});
}
);
}
}
};
</script>
<style lang="less">
.list {
}
</style>
+186
View File
@@ -0,0 +1,186 @@
<template>
<view class="sign">
<view class="header bg-color-red">
<view class="headerCon acea-row row-between-wrapper">
<view class="left acea-row row-between-wrapper">
<view class="pictrue">
<image :src="userInfo.avatar" />
</view>
<view class="text">
<view class="line1">{{ userInfo.nickname }}</view>
<view class="integral acea-row">
<text>积分: {{ userInfo.integral }}</text>
</view>
</view>
</view>
<view @click="goSignRecord()" class="right acea-row row-middle">
<view class="iconfont icon-caidan"></view>
<view>明细</view>
</view>
</view>
</view>
<view class="wrapper">
<view class="list acea-row row-between-wrapper">
<view class="item" v-for="(item, signSystemListIndex) in signSystemList" :key="signSystemListIndex">
<view :class="signSystemListIndex + 1 === signSystemList.length ? 'rewardTxt' : ''">{{ item.day }}</view>
<view class="venus" :class=" (signSystemListIndex + 1 === signSystemList.length ? 'reward' : '') +' ' + (sign_index >= signSystemListIndex + 1 ? 'venusSelect' : '')"></view>
<view class="num" :class="sign_index >= signSystemListIndex + 1 ? 'on' : ''">+{{ item.sign_num }}</view>
</view>
</view>
<!--加在 but on 为已签到-->
<view class="but bg-color-red" :class="userInfo.is_day_sgin ? 'on' : ''" @click="goSign">{{ userInfo.isDaySign ? "已签到" : "立即签到" }}</view>
<view class="lock"></view>
</view>
<view class="wrapper wrapper2">
<view class="tip">已累计签到</view>
<view class="list2 acea-row row-center row-bottom">
<view class="item" v-for="(item, signCountIndex) in signCount" :key="signCountIndex">{{ item || 0 }}</view>
<view class="data"></view>
</view>
<view class="tip2">据说连续签到第{{ day }}天可获得超额积分一定要坚持签到哦~~~</view>
<view class="list3">
<view class="item acea-row row-between-wrapper" v-for="(item, signListIndex) in signList" :key="signListIndex">
<view>
<view class="name line1">{{ item.title }}</view>
<view class="data">{{ item.addTime }}</view>
</view>
<view class="num font-color-red">+{{ item.number }}</view>
</view>
<view @click="goSignRecord()" class="Loads acea-row row-center-wrapper" v-if="signList.length > 0">
点击加载更多
<view class="iconfont icon-xiangyou acea-row row-center-wrapper"></view>
</view>
</view>
</view>
<view class="signTip acea-row row-center-wrapper" :class="active === true ? 'on' : ''">
<view class="signTipLight loadingpic">
<image :src="webUrl+'/20200729163719734861.png'" />
</view>
<view class="signTipCon">
<view class="state">签到成功</view>
<view class="integral">获得{{ integral }}积分</view>
<view class="signTipBnt" @click="close">好的</view>
</view>
</view>
<view class="mask" @touchmove.prevent :hidden="active === false"></view>
</view>
</template>
<style scoped lang="less">
.Loads .iconfont {
font-size: 0.25*100rpx;
margin: 0.02*100rpx 0 0 0.1*100rpx;
}
</style>
<script>
import {
postSignUser,
getSignConfig,
postSignIntegral,
getSignList
} from "@/api/user";
import {
add
} from "@/utils/bc";
export default {
name: "Sign",
components: {},
props: {},
data: function() {
return {
webUrl:this.$VUE_APP_RESOURCES_URL,
userInfo: {},
integral: 0,
signCount: [],
sign_index: 0,
signSystemList: [],
signList: [],
page: 1,
limit: 3,
active: false,
day: ""
};
},
mounted: function() {
uni.showLoading({ title: "加载中", mask: true });
this.signUser();
this.signConfig();
this.getSignList();
},
methods: {
goSignRecord() {
this.$yrouter.push("/pages/user/signIn/SignRecord/index");
},
// js给数字补0num:需要补0的数字,length:长度(补到多少位);
PrefixInteger: function(num, length) {
return (Array(length).join("0") + num).slice(-length).split("");
},
//数字转中文
Rp: function(n) {
var cnum = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"];
var s = "";
n = "" + n; // 数字转为字符串
for (var i = 0; i < n.length; i++) {
s += cnum[parseInt(n.charAt(i))];
}
return s;
},
// 获取用户信息
signUser: function() {
let that = this;
postSignUser({
sign: 1
}).then(res => {
uni.hideLoading();
res.data.integral = parseInt(res.data.integral);
var sumSginDay = res.data.sumSignDay;
that.userInfo = res.data;
that.signCount = that.PrefixInteger(sumSginDay, 4);
that.sign_index = parseInt(res.data.signNum);
});
},
// 签到配置
signConfig: function() {
let that = this;
getSignConfig().then(res => {
that.signSystemList = res.data;
that.day = that.Rp(that.signSystemList.length);
});
},
// 用户签到
goSign: function() {
let that = this,
sumSginDay = that.userInfo.sumSignDay;
if (that.userInfo.is_day_sgin) {
uni.showToast({
title: "您今日已签到!",
icon: "none",
duration: 2000
});
return
}
postSignIntegral().then(res => {
that.active = true;
that.integral = res.data.integral;
let sign_index = parseInt(that.sign_index + 1);
that.sign_index =
sign_index > that.signSystemList.length ? 1 : sign_index;
that.signCount = that.PrefixInteger(sumSginDay + 1, 4);
that.userInfo.is_day_sgin = true;
that.userInfo.integral = add(that.userInfo.integral, res.data.integral);
that.getSignList();
});
},
// 获取签到列表;
getSignList: function() {
let that = this;
getSignList(that.page, that.limit).then(res => {
that.signList = res.data;
});
},
close: function() {
this.active = false;
}
}
};
</script>
+65
View File
@@ -0,0 +1,65 @@
<template>
<view class="sign-record" ref="container">
<view class="list">
<view class="item" v-for="(item, signListIndex) in signList" :key="signListIndex">
<view class="data">{{ item.time }}</view>
<view class="listn">
<view
class="itemn acea-row row-between-wrapper"
v-for="(itemn, indexn) in item.list"
:key="indexn"
>
<view>
<view class="name line1">{{ itemn.title }}</view>
<view>{{ itemn.addTime }}</view>
</view>
<view class="num font-color-red">+{{ itemn.number }}</view>
</view>
</view>
</view>
</view>
<Loading :loaded="loadend" :loading="loading"></Loading>
</view>
</template>
<script>
import { getSignMonth } from "@/api/user";
import Loading from "@/components/Loading";
export default {
name: "SignRecord",
components: {
Loading
},
props: {},
data: function() {
return {
page: 1,
limit: 3,
signList: [],
loading: false,
loadend: false,
active: false
};
},
mounted: function() {
this.signListTap();
},
onReachBottom() {
!this.loading && this.signListTap();
},
methods: {
signListTap: function() {
let that = this;
if (that.loading) return; //阻止下次请求(false可以进行请求);
if (that.loadend) return; //阻止结束当前请求(false可以进行请求);
that.loading = true;
getSignMonth(that.page, that.limit).then(res => {
that.loading = false;
//apply();js将一个数组插入另一个数组;
that.signList.push.apply(that.signList, res.data);
that.loadend = res.data.length < that.limit; //判断所有数据是否加载完成;
that.page = that.page + 1;
});
}
}
};
</script>