Initial commit: MSH System\n\n- msh_single_uniapp: Vue 2 + UniApp 前端(微信小程序/H5/App/支付宝小程序)\n- msh_crmeb_22: Spring Boot 2.2 后端(C端API/管理端/业务逻辑)\n- models-integration: AI服务集成(Coze/KieAI/腾讯ASR)\n- docs: 产品文档与设计稿

This commit is contained in:
2026-02-28 05:40:21 +08:00
commit 14d29d51c0
2182 changed files with 482509 additions and 0 deletions

View File

@@ -0,0 +1,352 @@
<template>
<view :data-theme="theme">
<block v-if="bargain.length>0">
<div class="bargain-record" ref="container">
<div class="item borRadius14" v-for="(item, index) in bargain" :key="index">
<div class="picTxt acea-row row-between-wrapper">
<div class="pictrue">
<image :src="item.image" />
</div>
<div class="text acea-row row-column-around">
<div class="line1" style="width: 100%;">{{ item.title }}</div>
<count-down :justify-left="'justify-content:left'" :bgColor="bgColor" :is-day="true" :tip-text="'倒计时 '" :day-text="'天'"
:hour-text="' '" :minute-text="' '"
:second-text="' '" :datatime="item.stopTime/1000" v-if="item.status === 1"></count-down>
<div class="successTxt font_color" v-else-if="item.status === 3 && item.isDel === false">砍价成功</div>
<div class="successTxt " v-else-if="item.status === 3 && item.isDel === true && item.isPay === false">砍价失败</div>
<div class="endTxt" v-else>活动已结束</div>
<div class="money">
已砍至<span class="symbol font_color"></span><span class="num font_color">{{ item.surplusPrice }}</span>
</div>
</div>
</div>
<div class="bottom acea-row row-between-wrapper">
<div class="purple" v-if="item.status === 1">活动进行中</div>
<div class="success" v-else-if="item.status === 3 && item.isDel === false">砍价成功</div>
<div class="end" v-else-if="item.status === 3 && item.isDel === true && item.isPay === false">砍价失败</div>
<div class="end" v-else>活动已结束</div>
<div class="acea-row row-middle row-right">
<div class="bnt bg_color" v-if="item.status === 3 && !item.isOrder" @click="goConfirm(item)">
去付款
</div>
<div class="bnt bg_color" v-if="item.status === 3 && !item.isDel && item.isOrder && !item.isPay" @click="goPay(item.surplusPrice,item.orderNo)">
立即付款
</div>
<div class="bnt bg_color" v-if="item.status === 1" @click="goDetail(item.id)">
继续砍价
</div>
<div class="bnt bg_color" v-if="item.status === 2" @click="goList">重开一个</div>
</div>
</div>
</div>
<Loading :loaded="status" :loading="loadingList"></Loading>
</div>
</block>
<block v-if="bargain.length == 0">
<emptyPage title="暂无砍价记录~"></emptyPage>
</block>
<payment :pay_close="pay_close" @onChangeFun='onChangeFun' :order_id="pay_order_id" :totalPrice='totalPrice'></payment>
</view>
</template>
<script>
import CountDown from "@/components/countDown";
import emptyPage from '@/components/emptyPage.vue'
import {
getBargainUserList,
getBargainUserCancel
} from "@/api/activity";
import Loading from "@/components/Loading";
import payment from '@/components/payment';
import {mapGetters} from "vuex";
import {setThemeColor} from '@/utils/setTheme.js'
import animationType from '@/utils/animationType.js'
let app = getApp();
export default {
name: "BargainRecord",
components: {
CountDown,
Loading,
emptyPage,
payment
},
props: {},
computed: mapGetters(['isLogin', 'userInfo', 'uid']),
data: function() {
return {
bgColor:{
'bgColor': '',
'Color': '#E93323',
'width': '40rpx',
'timeTxtwidth': '28rpx',
'isDay': false
},
bargain: [],
status: false, //砍价列表是否获取完成 false 未完成 true 完成
loadingList: false, //当前接口是否请求完成 false 完成 true 未完成
page: 1, //页码
limit: 20, //数量
payMode: [{
name: "微信支付",
icon: "icon-weixinzhifu",
value: 'weixin',
title: '微信快捷支付'
},
{
name: "余额支付",
icon: "icon-yuezhifu",
value: 'yue',
title: '可用余额:',
number: 0
}
],
pay_close: false,
pay_order_id: '',
totalPrice: '0',
theme:app.globalData.theme
};
},
onShow() {
if (this.isLogin) {
this.payMode[1].number = this.userInfo.nowMoney;
this.$set(this, 'payMode', this.payMode);
this.getBargainUserList();
this.bgColor.Color = setThemeColor();
} else {
toLogin();
}
},
methods: {
/**
* 打开支付组件
*
*/
goPay(pay_price, order_id) {
this.$set(this, 'pay_close', true);
this.$set(this, 'pay_order_id', order_id);
this.$set(this, 'totalPrice', pay_price);
},
/**
* 事件回调
*
*/
onChangeFun: function(e) {
let opt = e;
let action = opt.action || null;
let value = opt.value != undefined ? opt.value : null;
(action && this[action]) && this[action](value);
},
/**
* 关闭支付组件
*
*/
payClose: function() {
this.pay_close = false;
},
/**
* 支付成功回调
*
*/
pay_complete: function() {
this.status = false;
this.page = 1;
this.$set(this, 'bargain', []);
this.$set(this, 'pay_close', false);
this.getBargainUserList();
},
/**
* 支付失败回调
*
*/
pay_fail: function() {
this.pay_close = false;
},
goConfirm: function(item) { //立即支付
if (this.isLogin === false) {
toLogin();
} else {
uni.navigateTo({
animationType: animationType.type,
animationDuration: animationType.duration,
url: `/pages/activity/goods_bargain_details/index?id=${item.id}&startBargainUid=${this.uid}&storeBargainId=${item.bargainUserId}`
})
}
},
goDetail: function(id) {
uni.navigateTo({
animationType: animationType.type,
animationDuration: animationType.duration,
url: `/pages/activity/goods_bargain_details/index?id=${id}&startBargainUid=${this.uid}`
})
},
// 砍价列表
goList: function() {
uni.navigateTo({
animationType: animationType.type,
animationDuration: animationType.duration,
url: '/pages/activity/goods_bargain/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.list.length < that.limit;
that.bargain.push.apply(that.bargain, res.data.list);
that.page++;
that.loadingList = false;
})
.catch(res => {
that.$dialog.error(res);
});
},
getBargainUserCancel: function(bargainId) {
var that = this;
getBargainUserCancel({
bargainId: bargainId
})
.then(res => {
that.status = false;
that.loadingList = false;
that.page = 1;
that.bargain = [];
that.getBargainUserList();
that.$util.Tips({
title: res
})
})
.catch(res => {
that.$util.Tips({
title: res
})
});
}
},
onReachBottom() {
this.getBargainUserList();
}
};
</script>
<style lang="scss">
page {
@include main_bg_color(theme);
height: 100vh;
overflow: auto;
}
</style>
<style lang="scss" scoped>
/*砍价记录*/
.bargain-record{
padding: 0 30rpx 15rpx;
}
.bargain-record .item .picTxt .text .time {
height: 36rpx;
line-height: 36rpx;
.styleAll {
color: #fc4141;
font-size:24rpx;
}
}
.bargain-record .item .picTxt .text .time .red {
color: #999;
font-size:24rpx;
}
.bargain-record .item {
background-color: #fff;
margin-top: 15rpx;
padding: 30rpx 24rpx 0 24rpx;
}
.bargain-record .item .picTxt {
border-bottom: 1px solid #f0f0f0;
padding-bottom: 30rpx;
}
.bargain-record .item .picTxt .pictrue {
width: 150upx;
height: 150upx;
}
.bargain-record .item .picTxt .pictrue image {
width: 100%;
height: 100%;
border-radius: 6upx;
}
.bargain-record .item .picTxt .text {
width: 470rpx;
font-size: 30upx;
color: #333333;
height: 160rpx;
}
.bargain-record .item .picTxt .text .time {
font-size: 24upx;
color: #868686;
justify-content: left !important;
}
.bargain-record .item .picTxt .text .successTxt{
font-size:24rpx;
}
.bargain-record .item .picTxt .text .endTxt{
font-size:24rpx;
color: #999;
}
.bargain-record .item .picTxt .text .money {
font-size: 24upx;
color: #999999;
}
.bargain-record .item .picTxt .text .money .num {
font-size: 32upx;
font-weight: bold;
}
.bargain-record .item .picTxt .text .money .symbol {
font-weight: bold;
}
.bargain-record .item .bottom {
height: 100upx;
font-size: 27upx;
}
.bargain-record .item .bottom .purple {
color: #f78513;
}
.bargain-record .item .bottom .end {
color: #999;
}
.bargain-record .item .bottom .success {
color: $theme-color;
}
.bargain-record .item .bottom .bnt {
font-size: 27upx;
color: #fff;
width: 176upx;
height: 60upx;
border-radius: 32upx;
text-align: center;
line-height: 60upx;
}
.bg_color{
@include main_bg_color(theme);
}
.font_color{
@include price_color(theme);
}
.bargain-record .item .bottom .bnt.cancel {
color: #aaa;
border: 1px solid #ddd;
}
.bargain-record .item .bottom .bnt~.bnt {

View File

@@ -0,0 +1,464 @@
<template>
<view :data-theme="theme">
<view class="pageInfo">
<skeleton :show="showSkeleton" :isNodes="isNodes" ref="skeleton" loading="chiaroscuro" selector="skeleton"
></skeleton>
<view class='bargain-list skeleton' :style="{visibility: showSkeleton ? 'hidden' : 'visible'}">
<!-- #ifdef H5 -->
<view class='iconfont icon-xiangzuo' @tap='goBack' :style="'top:'+ (navH/2) +'rpx'" v-if="returnShow">
</view>
<!-- #endif -->
<view class='header skeleton-rect' :style="{backgroundImage:'url('+imgHost+backBg+')'}" v-show="imgHost">
<view class="pic">
<view class='swipers skeleton-rect'>
<swiper :indicator-dots="indicatorDots" :autoplay="autoplay" interval="2500" duration="500" vertical="true"
circular="true">
<block v-for="(item,index) in bargainSuccessList" :key='index'>
<swiper-item >
<view class="acea-row row-middle">
<image :src="item.avatar" class="mr9"></image>
<view class='mr9 nickName'>{{$util.formatName(item.nickName)}}</view>
<text class='mr9'>拿了</text>
<view class='line1'>{{item.title}}</view>
</view>
</swiper-item>
</block>
</swiper>
</view>
</view>
<view class="tit" v-show="bargainTotal > 0">已有{{bargainTotal}}人砍成功</view>
</view>
<view class='list' v-if="bargainList.length">
<block v-for="(item,index) in bargainList" :key="index">
<view class='item acea-row row-between-wrapper'
@tap="openSubscribe('/pages/activity/goods_bargain_details/index?id='+ item.id +'&startBargainUid='+ uid)">
<view class='pictrue skeleton-rect'>
<image :src='item.image'></image>
</view>
<view class='text acea-row row-column-around'>
<view class='name line2 skeleton-rect'>{{item.title}}</view>
<view v-if="item.quota>0" class="acea-row skeleton-rect" style="margin-bottom: 14rpx;">
<countDown :tipText="' '" :bgColor="bgColor" :dayText="':'" :hourText="':'"
:minuteText="':'" :secondText="' '" :datatime="item.stopTime/1000" :isDay="true"
></countDown>
<text class="txt">后结束</text>
</view>
<view v-if="new Date().getTime()- item.stopTime >=0">
<view style="font-size: 22rpx;" @tap='currentBargainUser'>已结束</view>
</view>
<view v-if="item.quota==0">
<view style="font-size: 22rpx;" @tap='currentBargainUser'>已售罄</view>
</view>
<!-- <view class='num'><text class='iconfont icon-pintuan'></text>{{item.countPeopleAll}}人正在参与
</view> -->
<view class='money skeleton-rect'>最低: <text :style="[{'font-size':item.minPrice.length>=7?'32rpx':'38rpx'}]" class='price'>{{item.minPrice}}</text></view>
</view>
<view v-if="item.quota>0" class='cutBnt bg_color'>参与砍价</view>
<view v-if="item.quota==0" class='cutBnt bg-color-hui'>已售罄</view>
</view>
</block>
<view class='loadingicon acea-row row-center-wrapper' v-if='bargainList.length > 0' style="color: #fff;">
<text class='loading iconfont icon-jiazai' :hidden='loading==false'></text>{{loadTitle}}
</view>
</view>
<view v-else class="flex-center no_shop">
<image :src="urlDomain+'crmebimage/perset/staticImg/noShopper.png'" mode="aspectFit" style="width: 400rpx;"></image>
</view>
</view>
</view>
</view>
</template>
<script>
let app = getApp();
import {
getBargainList,
bargainHeaderApi
} from '@/api/activity.js';
import {
openBargainSubscribe
} from '@/utils/SubscribeMessage.js';
import countDown from '@/components/countDown';
import {
toLogin
} from '@/libs/login.js';
import {
mapGetters
} from "vuex";
import animationType from '@/utils/animationType.js'
export default {
components: {
countDown
},
data() {
return {
urlDomain: this.$Cache.get("imgHost"),
showSkeleton: true, //骨架屏显示隐藏
isNodes: 0, //控制什么时候开始抓取元素节点,只要数值改变就重新抓取
bgColor: {
'bgColor': '#E93323',
'Color': '#fff',
'width': '44rpx',
'timeTxtwidth': '16rpx',
'isDay': true
},
bargainList: [],
page: 1,
limit: 10,
loading: false,
loadend: false,
navH: '',
isAuto: false, //没有授权的不会自动授权
isShowAuth: false, //是否隐藏授权
returnShow: true,
loadTitle: '加载更多',
bargainSuccessList: [],
bargainTotal: 0,
indicatorDots: false,
autoplay: true,
theme:app.globalData.theme,
imgHost:'',
backBg:'crmebimage/perset/bargain_header/bargain_header1.jpg',
navBgColor:'#e93323'
};
},
computed: mapGetters(['isLogin', 'uid']),
watch: {
isLogin: {
handler: function(newV, oldV) {
if (newV) {
this.getBargainList();
this.getBargainHeader();
}
},
deep: true
}
},
onLoad: function(options) {
let that = this;
that.$set(that,'imgHost',that.$Cache.get('imgHost'));
switch (app.globalData.theme) {
case 'theme1':
that.backBg = 'crmebimage/perset/bargain_header/bargain_header1.jpg';
that.bgColor.bgColor = '#e93323';
that.navBgColor = '#e93323';
break;
case 'theme2':
that.backBg = 'crmebimage/perset/bargain_header/bargain_header2.jpg';
that.bgColor.bgColor = '#FE5C2D';
that.navBgColor = '#FE5C2D';
break;
case 'theme3':
that.backBg = 'crmebimage/perset/bargain_header/bargain_header3.jpg';
that.bgColor.bgColor = '#42CA4D';
that.navBgColor = '#42CA4D';
break;
case 'theme4':
that.backBg = 'crmebimage/perset/bargain_header/bargain_header4.jpg';
that.bgColor.bgColor = '#1DB0FC';
that.navBgColor = '#1DB0FC';
break;
case 'theme5':
that.backBg = 'crmebimage/perset/bargain_header/bargain_header5.jpg';
that.bgColor.bgColor = '#FF448F';
that.navBgColor = '#FF448F';
break;
}
uni.setNavigationBarColor({
frontColor: '#ffffff',
backgroundColor:that.navBgColor,
});
setTimeout(() => {
this.isNodes++;
}, 500);
var pages = getCurrentPages();
this.returnShow = pages.length === 1 ? false : true;
uni.setNavigationBarTitle({
title: "砍价列表"
})
this.navH = app.globalData.navHeight;
if (this.isLogin) {
this.getBargainList();
this.getBargainHeader();
} else {
toLogin();
}
},
methods: {
getBargainHeader: function() {
bargainHeaderApi().then(res => {
this.bargainTotal = res.data.bargainTotal;
this.bargainSuccessList = res.data.bargainSuccessList;
}).catch(err => {
return this.$util.Tips({
title: err
});
})
},
// 授权关闭
authColse: function(e) {
this.isShowAuth = e
},
goBack: function() {
uni.switchTab({
url:'/pages/index/index'
})
},
openSubscribe: function(e) {
let page = e;
// #ifndef MP
uni.navigateTo({
animationType: animationType.type,
animationDuration: animationType.duration,
url: page
});
// #endif
// #ifdef MP
uni.showLoading({
title: '正在加载',
})
openBargainSubscribe().then(res => {
uni.hideLoading();
uni.navigateTo({
url: page,
});
}).catch((err) => {
uni.hideLoading();
});
// #endif
},
getBargainList: function() {
let that = this;
if (that.loadend) return;
if (that.loading) return;
that.loading = true;
that.loadTitle = '';
getBargainList({
page: that.page,
limit: that.limit
}).then(function(res) {
let list = res.data.list;
let bargainList = that.$util.SplitArray(list, that.bargainList);
let loadend = list.length < that.limit;
that.loadend = loadend;
that.loading = false;
// #ifdef H5
that.setShare();
// #endif
that.loadTitle = loadend ? '已全部加载' : '加载更多';
that.$set(that, 'bargainList', bargainList);
that.$set(that, 'page', that.page + 1);
setTimeout(() => {
that.showSkeleton = false
}, 1000)
}).catch(res => {
that.loading = false;
that.loadTitle = '加载更多';
});
},
setShare: function() {
this.$wechat.isWeixin() &&
this.$wechat.wechatEvevt([
"updateAppMessageShareData",
"updateTimelineShareData",
"onMenuShareAppMessage",
"onMenuShareTimeline"
], {
desc: this.bargainList[0].title,
title: this.bargainList[0].title,
link: location.href,
imgUrl:this.bargainList[0].image
}).then(res => {
}).catch(err => {
console.log(err);
});
},
},
onReachBottom: function() {
this.getBargainList();
},
}
</script>
<style lang="scss">
page {
@include main_bg_color(theme);
}
</style>
<style lang="scss" scoped>
.pageInfo{
/* #ifdef MP || APP-PLUS */
@include main_bg_color(theme);
/* #endif */
}
.mr9{
margin-right: 9rpx;
}
.swipers {
height: 100%;
width: 76%;
margin: auto;
overflow: hidden;
font-size: 22rpx;
color: #fff;
image{
width: 24rpx;
height: 24rpx;
border-radius: 50%;
overflow: hidden;
}
swiper {
height: 100%;
width: 100%;
overflow: hidden;
}
.line1{
width: 195rpx;
}
}
.bargain-list .icon-xiangzuo {
font-size: 40rpx;
color: #fff;
position: fixed;
left: 30rpx;
z-index: 99;
transform: translateY(-20%);
}
.bargain-list .header {
// @include bargain-list-header(theme);
babackground-repeat: no-repeat;
background-size: 100% 100%;
width: 750rpx;
height: 420rpx;
.acea-row{
height: 50rpx;
line-height: 50rpx;
left: 50rpx;
.nickName{
width: 65rpx;
overflow: hidden;
white-space: nowrap;
}
}
.pic {
width: 478rpx;
height: 50rpx;
margin: 0 auto;
}
.tit {
color: #FFFFFF;
font-size: 24rpx;
font-weight: 400;
text-align: center;
margin-top: 304rpx;
}
}
.bargain-list .list {
padding: 0 30rpx;
}
.bargain-list .list .item {
position: relative;
height: 250rpx;
background-color: #fff;
border-radius: 14rpx;
margin-bottom: 20rpx;
padding: 30rpx 25rpx;
}
.bargain-list .list .item .pictrue {
width: 190rpx;
height: 190rpx;
}
.bargain-list .list .item .pictrue image {
width: 100%;
height: 100%;
border-radius: 14rpx;
}
.bargain-list .list .item .text {
width: 432rpx;
font-size: 28rpx;
color: #333333;
.txt{
font-size: 22rpx;
margin-left: 4rpx;
color: #666666;
line-height: 36rpx;
}
}
.bargain-list .list .item .text .name {
width: 100%;
height: 68rpx;
line-height: 36rpx;
font-size: 28rpx;
margin-bottom: 26rpx;
}
.bargain-list .list .item .text .num {
font-size: 26rpx;
color: #999;
}
.bargain-list .list .item .text .num .iconfont {
font-size: 35rpx;
margin-right: 7rpx;
}
.bargain-list .list .item .text .money {
font-size: 24rpx;
font-weight: bold;
@include price_color(theme);
}
.bargain-list .list .item .text .money .price {
font-size: 38rpx;
}
.bargain-list .list .item .cutBnt {
position: absolute;
width: 162rpx;
height: 52rpx;
border-radius: 50rpx;
font-size: 24rpx;
color: #fff;
text-align: center;
line-height: 52rpx;
right: 24rpx;
bottom: 30rpx;
}
.bg_color{
@include linear-gradient(theme);
}
.bg-color-hui{
background-color: #CDCBCC;
}
.bargain-list .list .item .cutBnt .iconfont {
margin-right: 8rpx;
font-size: 30rpx;
}
.bargain-list .list .load {
font-size: 24rpx;
height: 85rpx;
text-align: center;
line-height: 85rpx;
}
.flex-center{
display: flex;
justify-content: center;
align-items: center;
}
.no_shop{
margin: 0 30rpx 0;
height: 700rpx;
border-radius: 10rpx;
background-color: #fff;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,453 @@
<template>
<view :data-theme="theme">
<skeleton :show="showSkeleton" :isNodes="isNodes" ref="skeleton" loading="chiaroscuro" selector="skeleton"
bgcolor="#FFF"></skeleton>
<view class="skeleton" :style="{visibility: showSkeleton ? 'hidden' : 'visible'}">
<view class="combinationBj"></view>
<view class='flash-sale'>
<!-- #ifdef H5 -->
<view class='iconfont icon-xiangzuo' @tap='goBack' :style="'top:'+ (navH/2) +'rpx'" v-if="returnShow"></view>
<!-- #endif -->
<view class="saleBox"></view>
<view class="header skeleton-rect" v-if="dataList.length">
<swiper indicator-dots="true" autoplay="true" :circular="circular" interval="3000" duration="1500"
indicator-color="rgba(255,255,255,0.6)" indicator-active-color="#fff">
<block v-for="(items,index) in dataList[active].slide" :key="index">
<swiper-item class="borRadius14">
<image :src="items.sattDir" class="slide-image borRadius14" lazy-load></image>
</swiper-item>
</block>
</swiper>
</view>
<view class="seckillList acea-row row-between-wrapper">
<view class="priceTag skeleton-rect">
<image :src="urlDomain+'crmebimage/perset/staticImg/priceTag.png'"></image>
</view>
<view class='timeLsit'>
<scroll-view class="scroll-view_x" scroll-x scroll-with-animation :scroll-left="scrollLeft"
style="width:auto;overflow:hidden;">
<block v-for="(item,index) in dataList" :key='index'>
<view @tap='settimeList(item,index)' class='item' :class="active == index?'on':''">
<view class='time'>{{item.time.split(',')[0]}}</view>
<view class="state">{{item.statusName}}</view>
</view>
</block>
</scroll-view>
</view>
</view>
<view class='list pad30' v-if='seckillList.length>0'>
<block v-for="(item,index) in seckillList" :key='index'>
<view class='item acea-row row-between-wrapper' @tap='goDetails(item)'>
<view class='pictrue skeleton-rect'>
<image :src='item.image'></image>
</view>
<view class='text acea-row row-column-around'>
<view class='name line1 skeleton-rect'>{{item.title}}</view>
<view class='money skeleton-rect'><text class="font_color">¥</text>
<text class='num font_color'>{{item.price}}</text>
<text class="y_money">¥{{item.otPrice}}</text>
</view>
<view class="limit skeleton-rect">限量 <text class="limitPrice">{{item.quota}} {{item.unitName}}</text>
</view>
<view class="progress skeleton-rect">
<view class='bg-reds' :style="'width:'+item.percent+'%;'"></view>
<view class='piece'>已抢{{item.percent}}%</view>
</view>
</view>
<view class='grab bg_color' v-if="status == 2">马上抢</view>
<view class='grab bg_color' v-else-if="status == 1">未开始</view>
<view class='grab bg-color-hui' v-else>已结束</view>
</view>
</block>
</view>
</view>
<view class='noCommodity' v-if="seckillList.length == 0 && (page != 1 || active== 0)">
<view class='pictrue'>
<image :src="urlDomain+'crmebimage/perset/staticImg/noShopper.png'"></image>
</view>
</view>
</view>
</view>
</template>
<script>
import {
getSeckillHeaderApi,
getSeckillList
} from '../../../api/activity.js';
import animationType from '@/utils/animationType.js'
let app = getApp();
export default {
data() {
return {
urlDomain: this.$Cache.get("imgHost"),
showSkeleton: true, //骨架屏显示隐藏
isNodes: 0, //控制什么时候开始抓取元素节点,只要数值改变就重新抓取
circular: true,
autoplay: true,
interval: 500,
topImage: '',
seckillList: [],
timeList: [],
active: 0,
scrollLeft: 0,
interval: 0,
status: 1,
countDownHour: "00",
countDownMinute: "00",
countDownSecond: "00",
page: 1,
limit: 10,
loading: false,
loadend: false,
pageloading: false,
dataList: [],
returnShow: true,
navH: '',
theme:app.globalData.theme
}
},
onLoad() {
let that = this;
setTimeout(() => {
this.isNodes++;
}, 500);
var pages = getCurrentPages();
this.returnShow = pages.length===1?false:true;
// #ifdef H5
this.navH = app.globalData.navHeight-18;
// #endif
this.getSeckillConfig();
},
methods: {
goBack: function() {
uni.navigateBack();
},
getSeckillConfig: function() {
let that = this;
//if(that.showSkeleton) that.dataList = [{slide:''}]
that.seckillList = [{image:'',otPrice:'',percent:'',price:'',title:''}];
getSeckillHeaderApi().then(res => {
if(res.data == ''){
this.$util.Tips({
title: '暂无秒杀活动'
}, {
url: '/pages/index/index'
});
return;
}
that.seckillList = [];
res.data.map(item => {
item.slide = JSON.parse(item.slide)
})
that.dataList = res.data;
that.page = 1;
that.status = that.dataList[that.active].status;
that.getSeckillList();
});
},
getSeckillList: function() {
var that = this;
var data = {
page: that.page,
limit: that.limit
};
if (that.loadend) return;
if (that.pageloading) return;
that.pageloading = true
getSeckillList(that.dataList[that.active].id, data).then(res => {
// that.seckillList = [];
var seckillList = res.data.list;
var loadend = seckillList.length < that.limit;
that.seckillList = that.seckillList.concat(seckillList);
that.page++;
that.page = that.page;
that.pageloading = false;
that.loadend = loadend;
// #ifdef H5
that.setShare();
// #endif
setTimeout(() => {
that.showSkeleton = false
}, 1000)
}).catch(err => {
that.pageloading = false
});
},
settimeList: function(item, index) {
if(index !== this.active){
var that = this;
this.active = index
if (that.interval) {
clearInterval(that.interval);
that.interval = null
}
that.interval = 0,
that.countDownHour = "00";
that.countDownMinute = "00";
that.countDownSecond = "00";
that.status = that.dataList[that.active].status;
that.loadend = false;
that.page = 1;
that.seckillList = [];
// wxh.time(e.currentTarget.dataset.stop, that);
that.getSeckillList();
}
},
goDetails(item) {
uni.navigateTo({
animationType: animationType.type, animationDuration: animationType.duration,
url: '/pages/activity/goods_seckill_details/index?id=' + item.id
})
},
setShare: function() {
this.$wechat.isWeixin() &&
this.$wechat.wechatEvevt([
"updateAppMessageShareData",
"updateTimelineShareData",
"onMenuShareAppMessage",
"onMenuShareTimeline"
], {
desc: this.seckillList[0].title,
title: this.seckillList[0].title,
link: location.href,
imgUrl:this.seckillList[0].image
}).then(res => {
}).catch(err => {
console.log(err);
});
},
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function() {
var that = this;
that.getSeckillList();
}
}
</script>
<style>
page {
background-color: #F5F5F5 !important;
}
</style>
<style scoped lang="scss">
.icon-xiangzuo {
font-size: 40rpx;
color: #fff;
position: fixed;
left: 30rpx;
z-index: 99;
transform: translateY(-20%);
}
.flash-sale .header {
width: 710rpx;
height: 330rpx;
margin: -276rpx auto 0 auto;
border-radius: 14rpx;
overflow: hidden;
swiper{
height: 330rpx !important;
border-radius: 14rpx;
overflow: hidden;
}
}
.flash-sale .header image {
width: 100%;
height: 100%;
border-radius: 14rpx;
overflow: hidden;
img{
border-radius: 14rpx;
}
}
.flash-sale .seckillList {
padding: 25rpx;
}
.flash-sale .seckillList .priceTag {
width: 75rpx;
height: 70rpx;
}
.flash-sale .seckillList .priceTag image {
width: 100%;
height: 100%;
}
.flash-sale .timeLsit {
width: 596rpx;
white-space: nowrap;
}
.flash-sale .timeLsit .item {
display: inline-block;
font-size: 20rpx;
color: #666;
text-align: center;
box-sizing: border-box;
margin-right: 30rpx;
width: 130rpx;
}
.flash-sale .timeLsit .item .time {
font-size: 36rpx;
font-weight: 600;
color: #333;
}
.flash-sale .timeLsit .item.on .time {
@include main_color(theme);
}
.flash-sale .timeLsit .item.on .state {
height: 30rpx;
line-height: 30rpx;
border-radius: 15rpx;
width: 128rpx;
@include main_bg_color(theme);
color: #fff;
}
.flash-sale .countDown {
height: 92rpx;
border-bottom: 1rpx solid #f0f0f0;
margin-top: -14rpx;
font-size: 28rpx;
color: #282828;
}
.flash-sale .countDown .num {
font-size: 28rpx;
font-weight: bold;
background-color: #ffcfcb;
padding: 4rpx 7rpx;
border-radius: 3rpx;
}
.flash-sale .countDown .text {
font-size: 28rpx;
color: #282828;
margin-right: 13rpx;
}
.flash-sale .list .item {
height: 230rpx;
position: relative;
/* width: 710rpx; */
margin: 0 auto 20rpx auto;
background-color: #fff;
border-radius: 14rpx;
padding: 25rpx 24rpx;
}
.flash-sale .list .item .pictrue {
width: 180rpx;
height: 180rpx;
border-radius: 10rpx;
background-color: #F5F5F5;
}
.flash-sale .list .item .pictrue image {
width: 100%;
height: 100%;
border-radius: 10rpx;
}
.flash-sale .list .item .text {
width: 440rpx;
font-size: 30rpx;
color: #333;
height: 166rpx;
}
.flash-sale .list .item .text .name {
width: 100%;
}
.flash-sale .list .item .text .money {
font-size: 30rpx;
@include price_color(theme);
}
.flash-sale .list .item .text .money .num {
font-size: 40rpx;
font-weight: 500;
font-family: 'Guildford Pro';
}
.flash-sale .list .item .text .money .y_money {
font-size: 24rpx;
color: #999;
text-decoration-line: line-through;
margin-left: 15rpx;
}
.flash-sale .list .item .text .limit {
font-size: 22rpx;
color: #999;
margin-bottom: 5rpx;
}
.flash-sale .list .item .text .limit .limitPrice {
margin-left: 10rpx;
}
.flash-sale .list .item .text .progress {
overflow: hidden;
background-color: #EEEEEE;
width: 260rpx;
border-radius: 18rpx;
height: 18rpx;
position: relative;
}
.flash-sale .list .item .text .progress .bg-reds {
width: 0;
height: 100%;
transition: width 0.6s ease;
@include second-gradient(theme);
}
.flash-sale .list .item .text .progress .piece {
position: absolute;
left: 8%;
transform: translate(0%, -50%);
top: 49%;
font-size: 16rpx;
color: #FFB9B9;
}
.flash-sale .list .item .grab {
font-size: 28rpx;
color: #fff;
width: 150rpx;
height: 54rpx;
border-radius: 27rpx;
text-align: center;
line-height: 54rpx;
position: absolute;
right: 30rpx;
bottom: 30rpx;
background: #bbbbbb;
}
.bg_color{
@include main_bg_color(theme);
}
.flash-sale .saleBox {
width: 100%;
height: 298rpx;
/* #ifdef MP */
height: 300rpx;
/* #endif */
@include main_bg_color(theme);
border-radius: 0 0 50rpx 50rpx;
}
</style>

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,280 @@
<template>
<view>
<view class='poster-poster'>
<view class='tip'><text class='iconfont icon-shuoming'></text>提示点击图片即可保存至手机相册 </view>
<view class='pictrue' v-if="canvasStatus">
<image :src='imagePath'></image>
</view>
<view class="canvas">
<canvas style="width:750px;height:1130px;" canvas-id="firstCanvas" id="firstCanvas"></canvas>
<canvas canvas-id="qrcode" :style="{width: `${qrcodeSize}px`, height: `${qrcodeSize}px`}" style="opacity: 0;"/>
</view>
</view>
</view>
</template>
<script>
import { getCombinationPink, getCombinationPoster } from '../../../api/activity.js';
import uQRCode from '@/js_sdk/Sansnn-uQRCode/uqrcode.js';
import { imageBase64 } from "@/api/public";
export default {
data() {
return {
parameter: {
'navbar': '1',
'return': '1',
'title': '拼团海报',
'color': true,
'class': '0'
},
type: 0,
id: 0,
image: '',
from:'',
storeCombination: {},
qrcodeSize: 600,
posterbackgd: `${this.$Cache.get("imgHost")}crmebimage/perset/staticImg/canbj.png`,
PromotionCode: '',//二维码
canvasStatus: false,
imgTop: '' //商品图base64位
}
},
onLoad(options) {
// #ifdef MP
this.from = 'routine'
// #endif
// #ifdef H5
this.from = 'wechat'
// #endif
var that = this;
if (options.hasOwnProperty('type') && options.hasOwnProperty('id')) {
this.type = options.type
this.id = options.id
if (options.type == 1) {
uni.setNavigationBarTitle({
title: '砍价海报'
})
} else {
uni.setNavigationBarTitle({
title: '拼团海报'
})
}
} else {
return app.Tips({
title: '参数错误',
icon: 'none'
}, {
tab: 3,
url: 1
});
}
},
onShow() {
this.getPosterInfo();
},
methods: {
getPosterInfo: function() {
var that = this,url = '';
let data = {
pinkId: parseFloat(that.id),
from: that.from
};
if (that.type == 1) {
} else {
this.getCombinationPink();
}
},
//拼团信息
getCombinationPink: function() {
var that = this;
getCombinationPink(this.id)
.then(res => {
this.storeCombination = res.data;
this.getImageBase64(res.data.storeCombination.image);
// #ifdef H5
that.make(res.data.userInfo.uid);
// #endif
})
.catch(err => {
this.$util.Tips({
title: err
});
uni.redirectTo({
success(){},
fail() {
uni.navigateTo({
url: '/pages/index/index',
})
}
})
});
},
getImageBase64:function(images){
let that = this;
imageBase64({url:images}).then(res=>{
that.imgTop = res.data.code
})
},
// 生成二维码;
make(uid) {
let href = location.protocol + '//' + window.location.host + '/pages/activity/goods_combination_status/index?id=' + this.id + "&spread=" + uid;
uQRCode.make({
canvasId: 'qrcode',
text: href,
size: this.qrcodeSize,
margin: 10,
success: res => {
this.PromotionCode = res;
let arrImages = [this.posterbackgd, this.imgTop, this.PromotionCode];
let storeName = this.storeCombination.storeCombination.title;
let price = this.storeCombination.storeCombination.price;
let people = this.storeCombination.storeCombination.people;
let otPrice = this.storeCombination.storeCombination.otPrice;
let count = this.storeCombination.count;
setTimeout(() => {
this.PosterCanvas(arrImages, storeName, price, people,otPrice,count);
}, 300);
},
complete: () => {
},
fail:res=>{
this.$util.Tips({
title: '海报二维码生成失败!'
});
}
})
},
// 生成海报
PosterCanvas:function(arrImages, storeName, price, people,otPrice,count){
uni.showLoading({
title: '海报生成中',
mask: true
});
let context = uni.createCanvasContext('firstCanvas')
context.clearRect(0, 0, 0, 0);
let that = this;
uni.getImageInfo({
src: arrImages[0],
success: function (image) {
context.drawImage(arrImages[0], 0, 0, 750, 1190);
context.setFontSize(36);
context.setTextAlign('center');
context.setFillStyle('#282828');
let maxText = 20;
let text = storeName;
let topText = '';
let bottomText = '';
let len = text.length;
if(len>maxText*2){
text = text.slice(0,maxText*2-4)+'......';
topText = text.slice(0,maxText-1);
bottomText = text.slice(maxText-1,len);
}else{
if(len>maxText){
topText = text.slice(0,maxText-1);
bottomText = text.slice(maxText-1,len);
}else{
topText = text;
bottomText = '';
}
}
context.fillText(topText, 750/2, 60);
context.fillText(bottomText, 750/2, 100);
context.drawImage(arrImages[1], 150, 350, 450, 450);
context.save();
context.drawImage(arrImages[2], 300, 950, 140, 140);
context.restore();
context.setFontSize(72);
context.setFillStyle('#fc4141');
context.fillText(price, 250, 210);
context.setFontSize(32);
context.setFillStyle('#FFFFFF');
context.fillText( people+'人团', 538, 198);
context.setFontSize(26);
context.setFillStyle('#3F3F3F');
context.setTextAlign('center');
context.fillText( '原价:¥'+otPrice +' 还差 ' + count + '人 拼团成功', 750 / 2, 275);
context.draw(true,function(){
uni.canvasToTempFilePath({
destWidth: 750,
destHeight: 1190,
canvasId: 'firstCanvas',
fileType: 'jpg',
success: function(res) {
// 在H5平台下tempFilePath 为 base64
uni.hideLoading();
that.imagePath = res.tempFilePath;
that.canvasStatus = true;
}
})
})
},
fail: function(err) {
uni.hideLoading();
that.$util.Tips({
title: '无法获取图片信息'
});
}
})
},
showImage: function() {
var that = this;
let imgArr = this.image.split(',')
uni.previewImage({
urls: imgArr,
longPressActions: {
itemList: ['发送给朋友', '保存图片', '收藏'],
success: function(data) {
console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
},
fail: function(err) {
console.log(err.errMsg);
}
}
});
},
}
}
</script>
<style>
page {
background-color: #d22516 !important;
}
.canvas {
position:fixed;
z-index: -5;
opacity: 0;
}
.poster-poster .tip {
height: 80rpx;
font-size: 26rpx;
color: #e8c787;
text-align: center;
line-height: 80rpx;
}
.poster-poster .tip .iconfont {
font-size: 36rpx;
vertical-align: -4rpx;
margin-right: 18rpx;
}
.poster-poster .pictrue {
width: 690rpx;
height: 1130rpx;
margin: 0 auto 50rpx auto;
}
.poster-poster .pictrue image {
width: 100%;
height: 100%;
}
</style>

View File

@@ -0,0 +1,264 @@
<template>
<div class="quality-recommend" :data-theme="theme">
<view class="saleBox" v-if="typeInfo.pic"></view>
<view class="header skeleton-rect" v-if="typeInfo.pic">
<view class="borRadius14">
<image :src="typeInfo.pic" class="slide-image borRadius14" lazy-load></image>
</view>
</view>
<div class="title acea-row row-center-wrapper">
<div class="line"></div>
<div class="name">
<span class="iconfont icon-jingpintuijian" ></span> {{typeInfo.name}}
</div>
<div class="line"></div>
</div>
<view class="wrapper">
<view class="list">
<view class="item acea-row row-middle" v-for="(item,index) in tempArr" :key="index" @click="toDetail(item.id)">
<view class="img_box">
<image class="pictrue" :src="item.image"></image>
<view :style="{ backgroundImage: `url(${item.activityStyle})` }" class="border-picture"></view>
</view>
<view class="ml_11 flex-column justify-between">
<view class="goods_name">{{item.storeName}}</view>
<view class="price flex justify-between">
<view>
<text class="price_bdg"></text>{{item.price}}
<text class="otPrice">{{item.otPrice}}</text>
</view>
</view>
</view>
</view>
</view>
<view class='loadingicon acea-row row-center-wrapper' v-if="goodScroll">
<text class='loading iconfont icon-jiazai' :hidden='loading==false'></text>
</view>
<view class="txt-bar" v-if="tempArr.length > 0">😕~我也是有底线的~</view>
<emptyPage title="暂无数据~" v-if="tempArr.length == 0"></emptyPage>
</view>
</div>
</template>
<script>
import emptyPage from '@/components/emptyPage.vue';
import GoodList from '@/components/goodList/index';
import {getGroomList} from '@/api/store';
import {goPage} from '@/libs/order.js';
import {productRank} from '@/api/api.js'
import Loading from '@/components/Loading/index.vue';
import animationType from '@/utils/animationType.js'
let app = getApp()
export default {
name: 'HotNewGoods',
components: {
GoodList,
emptyPage,
Loading
},
data: function() {
return {
circular:true,
theme:app.globalData.theme,
typeInfo:{},
loading:false,
params: { //精品推荐分页
page: 1,
limit: 10,
},
loading: false,
goodScroll: true, //精品推荐开关
tempArr:[],
};
},
onLoad: function(e) {
this.typeInfo = e;
uni.setNavigationBarTitle({
title: this.typeInfo.name
});
if(this.typeInfo.name == '商品排行'){
this.getProductRank();
}else{
this.getGroomList();
}
},
methods: {
getGroomList() {
this.loading = true
if (!this.goodScroll) return
getGroomList(this.typeInfo.type, this.params).then(({data}) => {
this.goodScroll = data.list.length >= this.params.limit
this.loading = false
this.params.page++
this.tempArr = this.tempArr.concat(data.list)
})
},
getProductRank(){
productRank().then(res=>{
this.tempArr = res.data;
})
},
toDetail(id){
uni.navigateTo({
animationType: animationType.type,
animationDuration: animationType.duration,
url:'/pages/goods/goods_details/index?id=' + id
})
}
},
onReachBottom() {
if (this.params.page != 1) {
this.getGroomList();
}
},
}
</script>
<style lang="scss">
::v-deep .quality-recommend {
background-color: #f5f5f5;
}
.saleBox{
width: 100%;
height: 298rpx;
/* #ifdef MP */
height: 300rpx;
/* #endif */
@include main_bg_color(theme);
border-radius: 0 0 50rpx 50rpx;
}
.quality-recommend .header {
width: 710rpx;
height: 330rpx;
margin: -276rpx auto 0 auto;
border-radius: 14rpx;
overflow: hidden;
.slide-image{
height: 330rpx !important;
border-radius: 14rpx;
overflow: hidden;
}
}
.quality-recommend .header image {
width: 100%;
height: 100%;
border-radius: 14rpx;
overflow: hidden;
img{
border-radius: 14rpx;
}
}
.quality-recommend {
.wrapper {
// background: #fff;
.list {
width: 690rpx;
border-radius: 20rpx;
background-color: #fff;
margin: 0rpx auto 0 auto;
padding: 20rpx 20rpx 30rpx;
box-sizing: border-box;
.item {
background: #fff;
margin-top: 26rpx;
.img_box{
width: 180rpx;
height: 180rpx;
background: #F3F3F3;
position: relative;
.pictrue{
width:100%;
height:100%;
border-radius: 10rpx;
}
.rank_bdg{
width: 100%;
height: 46rpx;
position: absolute;
bottom: 0;
left: 0;
right: 0;
margin: auto;
text-align: center;
color: #fff;
font-size: 24rpx;
line-height: 46rpx;
}
}
.ml_11{
margin-left: 22rpx;
border-bottom: 1px solid #eee;
padding-bottom: 20rpx;
}
.goods_name{
width: 420rpx;
height: 80rpx;
font-size: 30rpx;
font-weight: 400;
color: #333333;
line-height: 40rpx;
overflow: hidden;
text-overflow:ellipsis;
white-space: wrap;
}
}
}
}
.title {
height: 120rpx;
font-size: 32rpx;
color: #282828;
background-color: #f5f5f5;
.name {
margin: 0 20rpx;
.iconfont {
margin-right: 10rpx;
}
}
.line {
width: 230rpx;
height: 2rpx;
background-color: #e9e9e9;
}
}
}
.price{
margin-top: 60rpx;
font-size: 34rpx;
font-weight: 600;
@include price_color(theme);
.price_bdg{
font-size: 26rpx;
}
.otPrice{
font-size: 24rpx;
color: #999999;
font-weight: 400;
padding-left: 12rpx;
text-decoration: line-through;
}
.cart_icon{
width: 48rpx;
height: 48rpx;
border-radius: 50%;
@include main_bg_color(theme);
text-align: center;
line-height: 40rpx;
.iconfont{
font-size: 28rpx;
font-weight: 400;
color: #fff;
}
}
}
.txt-bar {
padding: 20rpx 0;
text-align: center;
font-size: 26rpx;
color: #666;
background-color: #f5f5f5;
}
</style>

View File

@@ -0,0 +1,403 @@
<template>
<view id="home" :style="[pageStyle]" class="smallBox" :data-theme="theme">
<!-- 组合组件 -->
<homeComb v-if="showHomeComb" :bgInfo="bgInfo" :dataConfig="homeCombData" @changeTab="changeTab" :isScrolled="isScrolled" :isSmallPage="isSmallPage"
:navIndex="navIndex"></homeComb>
<!-- 顶部搜索框 -->
<headerSearch :isSmallPage="isSmallPage" v-if="showHeaderSerch" :dataConfig="headerSerchCombData"></headerSearch>
<!-- 分类导航 -->
<cateNav v-if="showCateNav" :dataConfig="cateNavData" @changeTab="changeTab"></cateNav>
<view v-if="navIndex === 0">
<block v-for="(item, index) in styleConfig" :key="index">
<!-- 新闻简报 -->
<news v-if="item.name == 'news'" :dataConfig="item"></news>
<!-- menu -->
<menus v-if="item.name == 'menus'" :dataConfig="item"></menus>
<!-- 文章列表 -->
<articleList v-if="item.name == 'homeArticle'" :dataConfig="item"></articleList>
<!-- 秒杀 -->
<seckill-data v-if="item.name == 'seckill'" :dataConfig="item"></seckill-data>
<!-- 优惠券 -->
<coupon v-if="item.name == 'homeCoupons'" :dataConfig="item"></coupon>
<!-- 图片魔方 -->
<pictureCube v-if="item.name == 'pictureCube'" :dataConfig="item"></pictureCube>
<!-- 热区 -->
<hotSpot v-if="item.name == 'homeHotspot'" :dataConfig="item"></hotSpot>
<!-- 轮播图 -->
<swiperBg v-if="item.name == 'swiperBg'" :dataConfig="item"></swiperBg>
<!-- 视频 -->
<shortVideo v-if="item.name == 'video'" :dataConfig="item"></shortVideo>
<!-- 辅助线 -->
<guide v-if="item.name == 'guide'" :dataConfig="item"></guide>
<!-- 富文本-->
<rich-text-editor v-if="item.name == 'richTextEditor'" :dataConfig="item"></rich-text-editor>
<!-- 辅助空白-->
<blank-page v-if="item.name == 'blankPage'" :dataConfig="item"></blank-page>
<!-- 标题 -->
<home-title v-if="item.name == 'titles'" :dataConfig="item"></home-title>
<!-- 拼团 -->
<group v-if="item.name == 'group'" :dataConfig="item"></group>
<!-- 砍价 -->
<bargain v-if="item.name == 'bargain'" :dataConfig="item"></bargain>
<!-- 商品列表 -->
<goodList v-if="item.name == 'goodList'" :dataConfig="item" @detail="goDetail"></goodList>
<!-- 选项卡商品列表-->
<homeTab v-if="item.name == 'homeTab'" :dataConfig="item" @detail="goDetail"></homeTab>
<!-- 底部导航-->
<page-footer v-if="item.name == 'footer'" :dataConfig="item" :isSmallPage="isSmallPage"></page-footer>
</block>
</view>
<!-- 分类页-->
<view class="productList" v-if="navIndex > 0 && sortList.length>0">
<view class="sort acea-row" :class="sortList.length ? '' : 'no_pad'"
:style="{ marginTop: sortMarTop + 'px' }">
<navigator hover-class="none"
:url="'/pages/goods/goods_list/index?cid=' + item.id + '&title=' + item.name" class="item"
v-for="(item, index) in sortList" :key="index" v-if="index<9">
<view class="pictrue">
<!-- <easy-loadimage :image-src="item.icon" class='slide-image skeleton-rect'>
</easy-loadimage> -->
<image :src="item.extra" class='slide-image tui-skeleton-rect'></image>
</view>
<view class="text">{{ item.name }}</view>
</navigator>
<view class="item" @click="bindMore()" v-if="sortList.length >= 9">
<view class="pictrues acea-row row-center-wrapper">
<text class="iconfont icon-gengduo2"></text>
</view>
<view class="text">更多</view>
</view>
</view>
</view>
<!-- 推荐商品分类商品列表-->
<recommend v-if="categoryId>0" ref="recommendIndex" :categoryId='categoryId' :isShowTitle="isShowTitle"
@getRecommendLength="getRecommendLength"></recommend>
<view class='noCommodity' v-if="isNoCommodity&& navIndex > 0">
<view class='pictrue'>
<image :src="urlDomain+'crmebimage/presets/noShopper.png'"></image>
</view>
<text class="text-ccc">暂无商品</text>
</view>
<!-- <view v-if="bottomNavigationIsCustom" class="footerBottom"></view> -->
</view>
</template>
<script>
import {
pagediyInfoApi,
getCategoryTwo
} from '@/api/api.js';
import {
mapGetters
} from "vuex";
import tuiSkeleton from '@/components/base/tui-skeleton.vue';
import homeComb from '@/components/homeIndex/homeComb';
import seckillData from "@/components/homeIndex/seckill.vue";
import coupon from "@/components/homeIndex/coupon.vue";
import menus from "@/components/homeIndex/menus.vue";
import pictureCube from '@/components/homeIndex/pictureCube'
import news from '@/components/homeIndex/news'
import goodList from '@/components/homeIndex/goodList'
import guide from '@/components/homeIndex/guide';
import articleList from '@/components/homeIndex/articleList'
import swiperBg from '@/components/homeIndex/swiperBg'
import headerSearch from '@/components/homeIndex/headerSearch';
import cateNav from '@/components/homeIndex/cateNav';
import richTextEditor from '@/components/homeIndex/richTextEditor';
import shortVideo from '@/components/homeIndex/video';
import homeTab from '@/components/homeIndex/homeTab';
import blankPage from '@/components/homeIndex/blankPage';
import homeTitle from '@/components/homeIndex/title';
import pageFooter from '@/components/homeIndex/pageFoot';
import recommend from "@/components/base/recommend.vue";
import group from "@/components/homeIndex/group.vue";
import hotSpot from '@/components/homeIndex/hotSpot.vue';
import bargain from "@/components/homeIndex/bargain.vue";
import {
goProductDetail
} from "../../../libs/order";
let app = getApp();
export default {
data() {
return {
urlDomain: this.$Cache.get("imgHost"),
theme: app.globalData.theme,
isSmallPage: true, //是否是微页面true是false不是
styleConfig: [],
bgColor: '',
bgPic: '',
bgTabVal: '',
isFixed: true,
storeHeight: 0,
smallPage: false,
homeCombData: {},
headerSerchCombData: {},
sortList: [],
sortMarTop: 0,
showCateNav: false, //是否显示分类导航组件
cateNavData: {}, //分类导航组件数据
navIndex: 0,
pageStyle: null,
cateNavActive: 0,
categoryId: 0, //分类id
diyId: 0, //diyid
isNoCommodity: false,
showHomeComb: false,
showHeaderSerch: false,
domOffsetTop: 50,
isScrolled: false,
bgInfo:{
colorPicker:'#f5f5f5',
isBgColor:1,
},
}
},
components: {
homeComb,
tuiSkeleton,
seckillData,
coupon,
menus,
pictureCube,
news,
goodList,
articleList,
swiperBg,
headerSearch,
cateNav,
guide,
richTextEditor,
shortVideo,
homeTab,
blankPage,
homeTitle,
pageFooter,
recommend,
group,
hotSpot,
bargain
},
computed: mapGetters(['bottomNavigationIsCustom']),
onLoad(options) {
if (options.scene) {
let value = this.$util.getUrlParams(decodeURIComponent(options.scene));
if (value.id) this.diyId = Number(value.id);
}
if (options.id) {
this.diyId = Number(options.id);
}
this.diyData(this.diyId)
},
// 滚动监听
onPageScroll(e) {
// 传入scrollTop值并触发所有easy-loadimage组件下的滚动监听事件
uni.$emit('scroll');
if (e.scrollTop > this.domOffsetTop) {
this.isScrolled = true;
}
if (e.scrollTop < this.domOffsetTop) {
this.$nextTick(() => {
this.isScrolled = false;
});
}
},
methods: {
diyData(id) {
let that = this;
that.styleConfig = [];
uni.showLoading({
title: '加载中...'
});
pagediyInfoApi(id).then(res => {
uni.setNavigationBarTitle({
title: res.data.title
});
uni.setNavigationBarColor({
//必须要16进制小写
frontColor: res.data.titleColor,
backgroundColor: res.data.titleBgColor.toString().toLowerCase(),
})
let data = res.data;
this.bgInfo.isBgColor=data.isBgColor
this.bgInfo.colorPicker=data.colorPicker
that.styleConfig = that.$util.objToArr(res.data.value);
uni.hideLoading();
that.styleConfig.forEach((item) => {
if (item.name == 'tabNav') {
this.showCateNav = true;
this.cateNavData = item;
}
if (item.name === 'homeComb') {
that.showHomeComb = true
that.homeCombData = item;
}
if (item.name === 'headerSerch') {
that.showHeaderSerch = true
that.headerSerchCombData = item;
}
});
this.pageStyle = {
'background-color': data.isBgColor === 1 ? res.data.colorPicker : '',
'background-image': data.isBgPic === 1 ? `url(${res.data.bgPic})` : '',
'background-repeat': res.data.bgTabVal === 1 ? 'repeat-y' : 'no-repeat',
'background-size': res.data.bgTabVal === 2 ? 'cover' : 'contain'
};
setTimeout(() => {
this.isNodes++;
}, 100);
}).catch(err => {
return that.$util.Tips({
title: err
});
uni.hideLoading();
})
},
getRecommendLength(e) {
this.isNoCommodity = e == 0 ? true : false;
},
// 分类切换点击
changeTab(index, item) {
//type=0微页面1分类2首页
this.cateNavActive = index;
if (item.type == 1) {
this.navIndex = 1;
if (!item.val) {
this.sortList = [];
this.categoryId = 0;
this.$util.Tips({
title: "请在平台端选择商品分类!确保加载商品分类数据。"
});
return;
} else {
getCategoryTwo(item.val).then(res => {
this.sortList = res.data;
// #ifdef H5
self.sortMarTop = 10;
// #endif
});
this.categoryId = item.val;
this.isShowTitle = false;
}
} else if (item.type == 0) {
this.navIndex = 0;
this.isShowTitle = true;
this.categoryId = 0;
if (!item.val) {
return this.$util.Tips({
title: "请在平台端选择微页面链接!确保加载微页面数据。"
});
} else {
this.styleConfig = [];
this.diyData(item.val, true);
}
} else {
this.categoryId = 0;
this.navIndex = 0;
this.styleConfig = [];
this.diyData(this.diyId, false);
}
},
// 去商品详情页
goDetail(item) {
goProductDetail(item.id, 0, '')
},
bindMore(){
uni.switchTab({
url: `/pages/goods_cate/goods_cate`
})
}
},
}
</script>
<style lang="scss" scoped>
.smallBox {
padding-bottom: calc(130rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
padding-bottom: calc(130rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
}
.productList {
background-color: #F5F5F5;
margin-top: 20rpx;
.sort {
width: 710rpx;
max-height: 380rpx;
background: rgba(255, 255, 255, 1);
border-radius: 16rpx;
padding: 0rpx 0rpx 20rpx 0rpx !important;
flex-wrap: wrap;
margin: 25rpx auto 0 auto;
&.no_pad {
padding: 0;
}
.item {
width: 20%;
margin-top: 20rpx;
text-align: center;
.pictrues {
width: 90rpx;
height: 90rpx;
background: #F5F5F5;
border-radius: 50%;
margin: 0 auto;
}
.pictrue {
width: 90rpx;
height: 90rpx;
background: #F5F5F5;
border-radius: 50%;
margin: 0 auto;
}
.slide-image {
width: 90rpx;
height: 90rpx;
border-radius: 50%;
overflow: hidden;
}
::v-deep .easy-loadimage,
uni-image,
.easy-loadimage {
width: 90rpx;
height: 90rpx;
display: inline-block;
}
.text {
color: #272727;
font-size: 24rpx;
margin-top: 10rpx;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}
}
.productList .list.on {
background-color: #fff;
border-top: 1px solid #f6f6f6;
}
.productList .list .item {
width: 345rpx;
margin-top: 20rpx;
background-color: #fff;
border-radius: 10rpx;
.name {
display: flex;
align-items: center;
.name_text {
display: inline-block;
max-width: 200rpx;
}
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB