Feat(时令尝鲜):接口对接

This commit is contained in:
lifizer
2023-09-27 16:13:33 +08:00
parent 2d73c2fe46
commit 986aee1fdb
13 changed files with 331 additions and 1005 deletions
+2 -2
View File
@@ -46,7 +46,7 @@ export function getStoryDetail(id) {
* 时令尝鲜首页 * 时令尝鲜首页
* */ * */
export function seasonHomeData() { export function seasonHomeData() {
return request.get("/seasonalFood/index", {}, {login: true}) return request.get("/seasonalFood/index", {}, {login: false})
} }
/** /**
@@ -57,7 +57,7 @@ export function getSeason(id) {
} }
/** /**
* 时令尝鲜 * 时令尝鲜海报
* */ * */
export function getSeasonPoster(id) { export function getSeasonPoster(id) {
return request.get("/seasonalFood/poster/" + id, {}, {login: true}) return request.get("/seasonalFood/poster/" + id, {}, {login: true})
+5 -4
View File
@@ -10,6 +10,10 @@
</view> </view>
</view> </view>
<!-- <view class="page-content">-->
<!-- <view class="title">历史搜索</view>-->
<!-- </view>-->
<view class="page-content" v-if="keywords.length"> <view class="page-content" v-if="keywords.length">
<view class="title">热门搜索</view> <view class="title">热门搜索</view>
<view class="list acea-row"> <view class="list acea-row">
@@ -62,12 +66,9 @@ export default {
</script> </script>
<style lang="less"> <style lang="less">
page { .good-search {
min-height: 100vh; min-height: 100vh;
background: #fff !important; background: #fff !important;
}
.good-search {
.header { .header {
padding: 40rpx 32rpx 32rpx; padding: 40rpx 32rpx 32rpx;
+1 -1
View File
@@ -14,7 +14,7 @@
<!-- 原模块 --> <!-- 原模块 -->
<view class="change-section bg-white" v-if="from===''"> <view class="change-section bg-white" v-if="from===''">
<view class="introduce bold">{{ storeInfo.storeName }}</view> <view class="introduce bold">{{ storeInfo.storeName }}</view>
<view class="subInfo" v-if="storeInfo.storeInfo">{{ storeInfo.storeInfo }}</view> <rich-text class="subInfo" :nodes="storeInfo.storeInfo" v-if="storeInfo.storeInfo"/>
<view class="share acea-row row-between row-middle" style="flex-wrap: nowrap;"> <view class="share acea-row row-between row-middle" style="flex-wrap: nowrap;">
<view class="money font-color-lightred acea-row ai-end"> <view class="money font-color-lightred acea-row ai-end">
<text class="num">{{ attr.productSelect.price }}</text> <text class="num">{{ attr.productSelect.price }}</text>
+52 -23
View File
@@ -32,23 +32,33 @@
</view> </view>
<view class="textarea"> <view class="textarea">
<textarea placeholder="商品满足你的期待么?说说你的想法,分享给想买的他们吧~" v-model="expect"></textarea> <textarea placeholder="商品满足你的期待么?说说你的想法,分享给想买的他们吧~" v-model="expect"></textarea>
<view class="list acea-row row-middle">
<view <u-upload
class="pictrue" :fileList="uploadPictures"
v-for="(item, uploadPicturesIndex) in uploadPictures" @afterRead="afterRead"
:key="uploadPicturesIndex" @delete="deletePic"
> name="uploadPictures"
<image :src="item"/> multiple
<text :maxCount="9"
class="iconfont icon-guanbi1 font-color-red" ></u-upload>
@click="uploadPictures.splice(uploadPicturesIndex, 1)" <!-- <view class="list acea-row row-middle">-->
></text> <!-- <view-->
</view> <!-- class="pictrue"-->
<view class="pictrue uploadBnt acea-row row-center-wrapper row-column" @tap="chooseImage"> <!-- v-for="(item, uploadPicturesIndex) in uploadPictures"-->
<text class="iconfont icon-icon25201"></text> <!-- :key="uploadPicturesIndex"-->
<view>上传图片</view> <!-- >-->
</view> <!-- <image :src="item"/>-->
</view> <!-- <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>
<view class="evaluateBnt bg-color-red" @click="submit">立即评价</view> <view class="evaluateBnt bg-color-red" @click="submit">立即评价</view>
</view> </view>
@@ -61,7 +71,7 @@
</style> </style>
<script> <script>
import {postOrderComment, postOrderProduct} from "@/api/store"; import {postOrderComment, postOrderProduct} from "@/api/store";
import {chooseImage, trim} from "@/utils"; import {trim, uploadImage} from "@/utils";
import {required} from "@/utils/validate"; import {required} from "@/utils/validate";
import {validatorDefaultCatch} from "@/utils/dialog"; import {validatorDefaultCatch} from "@/utils/dialog";
@@ -124,10 +134,26 @@ export default {
stars: function (indexn, indexw) { stars: function (indexn, indexw) {
this.scoreList[indexw].index = indexn; this.scoreList[indexw].index = indexn;
}, },
chooseImage() { // chooseImage() {
chooseImage(img => { // chooseImage(img => {
this.uploadPictures.push(img); // this.uploadPictures.push(img);
}); // });
// },
// 删除图片
deletePic(event) {
this[`${event.name}`].splice(event.index, 1)
},
afterRead(event) {
let that = this;
if (event.file.length > 0) {
event.file.map(item => {
uploadImage(item.url, img => {
that.uploadPictures.push({url: img})
})
})
}
}, },
async submit() { async submit() {
const expect = trim(this.expect), const expect = trim(this.expect),
@@ -154,11 +180,14 @@ export default {
} catch (e) { } catch (e) {
return validatorDefaultCatch(e); return validatorDefaultCatch(e);
} }
let temp = this.uploadPictures.map(item => item.url)
let pics = temp.join(",")
postOrderComment({ postOrderComment({
productScore: product_score, productScore: product_score,
serviceScore: service_score, serviceScore: service_score,
unique: this.unique, unique: this.unique,
pics: this.uploadPictures.join(","), pics,
comment: expect comment: expect
}) })
.then(() => { .then(() => {
+8 -6
View File
@@ -63,7 +63,9 @@
<view v-if="inn.desc != null && inn.desc.length>0" class="" style="padding: 0 32rpx;margin-top: 30rpx;"> <view v-if="inn.desc != null && inn.desc.length>0" class="" style="padding: 0 32rpx;margin-top: 30rpx;">
<view class="desc-box"> <view class="desc-box">
<view v-html="handleRichText(inn.desc)"></view> <text class="fixed">简介</text>
<rich-text :nodes="inn.desc"/>
<!-- <view v-html="handleRichText(inn.desc)"></view>-->
</view> </view>
</view> </view>
@@ -521,7 +523,6 @@ export default {
}, },
handleRichText: function (str) { handleRichText: function (str) {
if (str != null) { if (str != null) {
return `<span class="fixed">简介:</span>` + str.replace(/<\/?[^>]*>/g, ''); return `<span class="fixed">简介:</span>` + str.replace(/<\/?[^>]*>/g, '');
} else { } else {
return ''; return '';
@@ -529,7 +530,6 @@ export default {
}, },
fetchInnDetail: function () { fetchInnDetail: function () {
let that = this; let that = this;
if (this.isMyInn) { if (this.isMyInn) {
getHotelDetail(that.id).then((res) => { getHotelDetail(that.id).then((res) => {
that.inn = res.data; that.inn = res.data;
@@ -681,19 +681,21 @@ export default {
.cover-box { .cover-box {
position: relative; position: relative;
.full-img { .full-img {
width: 750rpx; width: 750rpx;
} }
.box-mask{
.box-mask {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
right: 0; right: 0;
width: 596rpx; width: 596rpx;
box-sizing: border-box; box-sizing: border-box;
padding: 0 20rpx 12rpx; padding: 0 20rpx 12rpx;
background: linear-gradient(180deg, rgba(0,0,0,0) 0%, #000000 100%); background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000000 100%);
.city-section{ .city-section {
width: 256rpx; width: 256rpx;
margin-left: 20rpx; margin-left: 20rpx;
} }
-387
View File
@@ -1,387 +0,0 @@
<template>
<view class="container">
<hx-navbar
title=" "
:fixed="true"
statusBarFontColor="#ffffff"
barPlaceholder="hidden"
transparent="auto"
color="#FFFFFF"
:background-color="[[254,150,107],[255, 88, 75]]"
:pageScroll.sync="scrollData"/>
<!-- <block slot="right">
<view class="">
<text class="iconfont icon-fenxiang" style="font-size: 48rpx;"></text>
<view class="" @click="like">
<image v-if="innInfo.isLike==0" style="width: 48rpx;height: 48rpx;" :src="webUrl+'/20210302161110012686.png'" mode=""></image>
<image v-if="innInfo.isLike>0" style="width: 48rpx;height: 48rpx;" :src="webUrl+'/20210302161135069143.png'" mode=""></image>
</view>
</view>
</block> -->
</hx-navbar>
<block v-if="innInfo">
<view v-if="innInfo.type=='NT_TEXT'" class="banner">
<swiper :current="swiperCurrentIndex" indicatorDots="true" indicator-active-color='rgba(255, 255, 255, 1)' indicator-color='rgba(255, 255, 255, 0.3)' v-if="innInfo.resources.length > 0" autoplay circular>
<block v-for="(imgUrl, index) in innInfo.resources" :key="index">
<swiper-item>
<view class="swiper-item">
<image class="swiper-item-content" :src="imgUrl" style="object-fit: cover;" mode="aspectFill" />
</view>
</swiper-item>
</block>
</swiper>
<!-- <view class="share-section" style="position: absolute;left: 0;right: 0;">
<view class="acea-row row-middle row-right pad20" style="flex-shrink: 0;">
<view class="" style="margin-right: 20rpx;"><image @click="shareInfo" style="width: 48rpx;height: 48rpx;" :src="webUrl+'/20210304153545482917.png'" mode=""></image></view>
<view class="" @click="likeInfo">
<image v-if="innInfo.isLike == null || parseInt(innInfo.isLike)==0" style="width: 48rpx;height: 48rpx;" :src="webUrl+'/20210302161110012686.png'" mode=""></image>
<image v-if="innInfo.isLike != null && parseInt(innInfo.isLike)==1" style="width: 48rpx;height: 48rpx;" :src="webUrl+'/20210302161135069143.png'" mode=""></image>
</view>
</view>
</view> -->
<view class="cover">
</view>
<view class="title-section acea-row row-middle">
<view class="" style="font-size: 32rpx;color: #ffffff;flex-grow: 1;">{{innInfo.name}}</view>
<!-- <view class="acea-row row-column pad20" style="flex-shrink: 0;">
<image @click="shareInfo" style="width: 48rpx;height: 48rpx;" :src="webUrl+'/20210304153545482917.png'" mode=""></image>
<view class="" @click="likeInfo">
<image v-if="innInfo.isLike == null || parseInt(innInfo.isLike)==0" style="width: 48rpx;height: 48rpx;" :src="webUrl+'/20210302161110012686.png'" mode=""></image>
<image v-else style="width: 48rpx;height: 48rpx;" :src="webUrl+'/20210302161135069143.png'" mode=""></image>
</view>
</view> -->
</view>
<!-- <image style="width: 750rpx;position: absolute;left: 0;bottom: 0;" :src="webUrl+'/20210227115029488890.png'" mode="widthFix"></image> -->
</view>
<view v-if="innInfo.type=='NT_VIDEO'" class="banner">
<block v-if="innInfo.resources.length > 0">
<video style="width: 100%;height: 100%;" autoplay :src="innInfo.resources[0]"></video>
</block>
</view>
<view class="hotel-section acea-row row-center">
<view class="hotel-logo">
<image :src="innInfo.hotelLogo" mode=""></image>
</view>
<view class="acea-row row-column" style="flex-grow: 1;">
<view class="hotel-name">{{innInfo.hotelName}}</view>
<view class="hotel-date">{{formattedDateStr(innInfo.createdTime)}}</view>
</view>
<view class="enrollInnBtn acea-row row-center row-middle" @click="enrollInn">进入主页</view>
</view>
<view class="detail-section" v-html="innInfo.content">
<!-- {{innInfo.content}} -->
</view>
<view class="bottom-holder acea-row row-middle row-right savebottom">
<view class="acea-row row-middle">
<view class="acea-row row-middle">
<image style="width: 28rpx;height: 28rpx;margin-right: 4rpx;" :src="webUrl+'/20220901224017781784.png'" mode=""></image>
<text class="seeNum-txt">{{innInfo.pv}}</text>
</view>
<view class="acea-row row-middle" style="margin-left: 20rpx;" @click="likeInfo">
<block v-if="innInfo.zanVo != null">
<image style="width: 28rpx;height: 28rpx;margin-right: 4rpx;" :src="webUrl+'/20210302161135069143.png'" mode=""></image>
</block>
<block v-else>
<image style="width: 28rpx;height: 28rpx;margin-right: 4rpx;" :src="webUrl+'/20220901224304100136.png'" mode=""></image>
</block>
<text class="likeNum-txt">{{innInfo.zan}}</text>
</view>
</view>
</view>
</block>
<ShareInfo v-on:setShareInfoStatus="setShareInfoStatus" :shareInfoStatus="shareInfoStatus"></ShareInfo>
</view>
</template>
<script>
import { getHotelNewsDetail,getHotelNewsZan} from "@/api/inn.js";
import { formatDateTime,isNullOrEmpty} from "@/utils";
import ShareInfo from "@/components/ShareInfo";
var that;
export default {
components:{
ShareInfo
},
data() {
return {
webUrl:this.$VUE_APP_RESOURCES_URL,
scrollData: {},
shareInfoStatus: false,
innInfo:null,
swiperHeight:300,
swiperCurrentIndex:0,
// innInfo:{
// isLike:0,
// type:'NT_TEXT',
// resources:[
// 'http://resource.xdd618.com/黄精.jpg',
// 'http://resource.xdd618.com/黄精.jpg',
// ]
// },
innId:0
}
},
//必须在页面加 onPageScroll(e){} ,才能滑动显示背景
onPageScroll(e){
this.scrollData = e;
},
onLoad:function(e){
that = this;
this.innId = e.id;
this.fetchInnInfoDetail();
},
methods: {
// changeSwiper:function(e){
// this.swiperCurrentIndex = e.detail.current;
// this.getCurrentSwiperHeight('.swiper-item-content');
// },
// getCurrentSwiperHeight(element) {
// let query = uni.createSelectorQuery().in(this);
// query.selectAll(element).boundingClientRect();
// query.exec((res) => {
// that.swiperHeight = res[0][this.swiperCurrentIndex].height;
// console.log("swiperHeight:"+that.swiperHeight);
// })
// },
setShareInfoStatus: function() {
this.shareInfoStatus = !this.shareInfoStatus;
},
shareInfo:function(){
this.setShareInfoStatus();
},
likeInfo:function(){
var id = this.innId;
uni.showLoading();
getHotelNewsZan(id).then((res)=>{
uni.hideLoading();
var msg = '操作成功!';
if(res.msg.length>0){
msg = res.msg;
}
uni.showToast({
title: msg,
mask: false,
duration: 1500
});
setTimeout(function(){
//刷新界面
that.fetchInnInfoDetail();
},1500);
}).catch((err)=>{
uni.hideLoading()
uni.showToast({
title: err.msg+'',
icon:'none',
mask: false,
duration: 1500
});
}).finally(()=>{
})
},
enrollInn:function(){
//this.$yrouter.redirectTo('');
var id = this.innInfo.hotelId;
var pages = getCurrentPages();
if (pages.length>1) {
var prePage = pages[pages.length - 2];
//判断上一页是不是客栈主页
if(prePage.route == 'pagesInn/inn/innHome'){
this.$yrouter.back();
}else{
this.$yrouter.replace({
path: "/pagesInn/inn/innHome",
query: { id: id }
});
}
}else{
this.$yrouter.replace({
path: "/pagesInn/inn/innHome",
query: { id: id }
});
}
},
formattedDateStr:function(str){
return formatDateTime(str,'yyyy/MM/dd HH:mm:ss');
},
fetchInnInfoDetail:function(){
getHotelNewsDetail(this.innId).then((res)=>{
that.innInfo = res.data;
}).catch((err)=>{
uni.showToast({
title: err.msg+'',
icon:'none',
mask: false,
duration: 1500
});
}).finally(()=>{
})
},
like:function(){
uni.showLoading();
getHotelNewsZan(this.innId).then((res)=>{
uni.hideLoading();
//刷新界面
that.fetchInnDetail();
}).catch((err)=>{
uni.hideLoading();
uni.showToast({
title: err+'',
icon:'none',
mask: false,
duration: 1500
});
}).finally(()=>{
})
}
}
}
</script>
<style lang="less" scoped>
.container{
position: relative;
background: #ffffff;
}
.cover{
width: 100%;
height: 218rpx;
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000000 100%);
opacity: 0.6;
// background-color:transparent;
position: absolute;
bottom: 0;
left: 0;
right: 0;
}
.title-section{
padding: 32rpx;
// width: 100%;
// height: 218rpx;
background-color: transparent;
position: absolute;
bottom: 0;
left: 0;
right: 0;
z-index: 1;
}
.banner {
height: 750rpx;
-webkit-transform:rotate(0);
position: relative;
width: 100%;
overflow: hidden;
}
.banner swiper{
// height: 600rpx;
height: 100%;
}
.banner .swiper-item{
height: 100%;
width: 100%;
}
.banner image{
width: 100%;
// height: 600rpx;
height: 100%;
}
.hotel-section{
padding: 32rpx;
}
.hotel-logo{
width: 72rpx;
height: 72rpx;
flex-shrink: 0;
margin-right: 20rpx;
}
.hotel-logo image{
width: 100%;
height: 100%;
border-radius: 50%;
}
.hotel-name{
font-size: 28rpx;
color: #080F1A;
}
.hotel-date{
font-size: 22rpx;
color: #C2C5CC;
}
.enrollInnBtn{
text-align: center;
flex-shrink: 0;
width: 122rpx;
height: 48rpx;
background: #0DC5C5;
opacity: 1;
border-radius: 8rpx;
font-size: 22rpx;
color: #FFFFFF;
}
.likeNum-txt{
font-size: 22rpx;
color: #080F1A;
}
.seeNum-txt{
font-size: 22rpx;
color: #080F1A;
}
.detail-section{
padding: 32rpx;
font-size: 28rpx;
font-weight: 400;
color: #080F1A;
margin-bottom: 114rpx;
}
.bottom-holder{
position: fixed;
background-color: transparent;
left: 0;
right: 0;
height: 114rpx;
padding: 32rpx;
box-sizing: border-box;
}
.share-section{
top: var(--status-bar-height);
padding-top: 44px;
}
</style>
-160
View File
@@ -1,160 +0,0 @@
<template>
<view class="pkg-product-list">
<swiper class="swiper-box" indicator-dots indicator-color="rgba(255,255,255,.3)" indicator-active-color="#fff"
autoplay circular v-if="bannerList.length>0">
<swiper-item v-for="(item,index) in bannerList" :key="index">
<image :src="item.pic" mode="scaleToFill" @click="$global.commonJump(item.uniappUrl)"/>
</swiper-item>
</swiper>
<view class="search-box flex jc-between ai-center">
<input type="text" v-model="keyword" placeholder="搜索商品" placeholder-style="color:#949494" @confirm="search">
<image class="icon" :src="webUrl+'/20220903142935869059.png'" mode="scaleToFill" @click="search"></image>
</view>
<view class="body-box">
<view class="aside-box flex-0">
<view class="item flex jc-center ai-center" :class="index === asideIndex ? 'active' : ''"
v-for="(item, index) in asideList" :key="index" @click="asideTap(index)">
<text class="one-t">{{ item.label }}</text>
</view>
</view>
<view class="article-box">
<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="list flex flex-wrap">
<view v-for="(item, index) in dataList" :key="index">
<view class="item" @click="goGoods(item.id)">
<image class="cover" :src="item.image" mode="scaleToFill"/>
<view class="name more-t">{{ item.storeName }}</view>
<view class="price">{{ item.price }}</view>
</view>
</view>
</view>
</mescroll-body>
</view>
</view>
</view>
</template>
<script>
import MescrollMixins from "@/mixins/mescroll-mixins.js";
import MescrollBody from "@/components/mescroll-uni/mescroll-body.vue";
import {customizedGift} from "@/api/product";
import {fetchCity} from "@/api/wenwan";
import {getProducts} from "@/api/store";
export default {
name: "giftList",
components: {
MescrollBody
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
keyword: "",
bannerList: [],
asideList: [],
asideIndex: 0,
dataList: [], // 列表数据
upOption: {
noMoreSize: 10, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
auto: true,
empty: {
tip: '暂无商品' // 提示
}
},
downOption: {
auto: false
}
}
},
mixins: [
MescrollMixins({
getPageData(mescroll) {
let that = this;
// 此时mescroll会携带page的参数:
let pageNum = mescroll.num; // 页码, 默认从1开始
console.log(pageNum,"test")
let timer = setInterval(() => {
if (that.asideList.length > 0) {
clearInterval(timer);
let param = {
isCustomizedGift: 1,
page: pageNum,
limit: 10,
keyword: that.keyword,
provinceId: that.asideList.length > 0 ? that.asideList[that.asideIndex].provinceId : ""
}
getProducts(param).then(({data}) => {
if (mescroll.num === 1) {
that.dataList = [];
}
that.dataList = that.dataList.concat(data);
mescroll.endSuccess(data.length);
}).catch(err => {
mescroll.endErr();
uni.showToast({
title: err + '',
icon: 'none',
mask: false,
duration: 1500
});
});
}
},500)
}
})
],
onLoad() {
customizedGift().then(({data}) => this.bannerList = data.banner);
fetchCity(3).then(({data}) => this.asideList = data.group);
},
methods: {
search() {
//触发加载请求
this.mescroll.scrollTo(0, 0);
this.mescroll && this.mescroll.resetUpScroll(false);
},
asideTap(index) {
this.asideIndex = index;
this.search();
},
goGoods(id) {
uni.navigateTo({
url: "/pages/shop/GoodsCon/index?id=" + id
})
}
}
}
</script>
<style scoped lang="less">
@import "@/assets/css/product.less";
.pkg-product-list {
min-height: 100vh;
box-sizing: border-box;
padding-top: 20rpx;
background: #fff;
.search-box {
margin-top: 14rpx;
}
.body-box {
position: fixed;
top: 472rpx;
height: calc(100vh - 472rpx);
}
/deep/ .u-list {
}
}
</style>
-217
View File
@@ -1,217 +0,0 @@
<template>
<view class="pkg-product-list">
<view class="fixed-header">
<swiper class="swiper-box" indicator-dots indicator-color="rgba(255,255,255,.3)" indicator-active-color="#fff"
autoplay circular v-if="bannerList.length>0">
<swiper-item v-for="(item,index) in bannerList" :key="index">
<image :src="item.pic" mode="scaleToFill" @click="$global.commonJump(item.uniappUrl)"/>
</swiper-item>
</swiper>
<view class="search-box flex jc-between ai-center">
<input type="text" v-model="keyword" placeholder="搜索商品" placeholder-style="color:#949494" @confirm="search">
<image class="icon" :src="webUrl+'/20220903142935869059.png'" mode="scaleToFill" @click="search"></image>
</view>
</view>
<!-- <view class="body-box">-->
<view class="aside flex-0">
<view class="item flex jc-center ai-center" :class="index === asideIndex ? 'active' : ''"
v-for="(item, index) in asideList" :key="index" @click="asideTap(index)">
<text class="one-t">{{ item.label }}</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="list flex flex-wrap">
<view v-for="(item, index) in dataList" :key="index">
<view class="item" @click="goGoods(item.id)">
<image class="cover" :src="item.image" mode="scaleToFill"/>
<view class="name more-t">{{ item.storeName }}</view>
<view class="price">{{ item.price }}</view>
</view>
</view>
</view>
</mescroll-body>
</view>
<!-- <view class="article-box">-->
<!-- <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="list flex flex-wrap">-->
<!-- <view v-for="(item, index) in dataList" :key="index">-->
<!-- <view class="item" @click="goGoods(item.id)">-->
<!-- <image class="cover" :src="item.image" mode="scaleToFill"/>-->
<!-- <view class="name more-t">{{ item.storeName }}</view>-->
<!-- <view class="price">{{ item.price }}</view>-->
<!-- </view>-->
<!-- </view>-->
<!-- </view>-->
<!-- </mescroll-body>-->
<!-- </view>-->
<!-- </view>-->
</view>
</template>
<script>
import MescrollMixins from "@/mixins/mescroll-mixins.js";
import MescrollBody from "@/components/mescroll-uni/mescroll-body.vue";
import {customizedGift} from "@/api/product";
import {fetchCity} from "@/api/wenwan";
import {getProducts} from "@/api/store";
export default {
name: "giftList",
components: {
MescrollBody
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
keyword: "",
bannerList: [],
asideList: [],
asideIndex: 0,
dataList: [], // 列表数据
upOption: {
noMoreSize: 10, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
auto: true,
empty: {
tip: '暂无商品' // 提示
}
},
downOption: {
auto: false
}
}
},
mixins: [
MescrollMixins({
getPageData(mescroll) {
let that = this;
// 此时mescroll会携带page的参数:
let pageNum = mescroll.num; // 页码, 默认从1开始
let timer = setInterval(() => {
if (that.asideList.length > 0) {
clearInterval(timer);
let param = {
isCustomizedGift: 1,
page: pageNum,
limit: 10,
keyword: that.keyword,
provinceId: that.asideList.length > 0 ? that.asideList[that.asideIndex].provinceId : ""
}
getProducts(param).then(({data}) => {
if (mescroll.num === 1) {
that.dataList = [];
}
that.dataList = that.dataList.concat(data);
mescroll.endSuccess(data.length);
}).catch(err => {
mescroll.endErr();
uni.showToast({
title: err + '',
icon: 'none',
mask: false,
duration: 1500
});
});
}
}, 500)
}
})
],
onLoad() {
customizedGift().then(({data}) => this.bannerList = data.banner);
fetchCity(3).then(({data}) => this.asideList = data.group);
},
methods: {
search() {
//触发加载请求
this.mescroll.scrollTo(0, 0);
this.mescroll && this.mescroll.resetUpScroll(false);
},
asideTap(index) {
this.asideIndex = index;
this.search();
},
goGoods(id) {
uni.navigateTo({
url: "/pages/shop/GoodsCon/index?id=" + id
})
}
}
}
</script>
<style scoped lang="less">
@import "@/assets/css/product.less";
.pkg-product-list {
min-height: 100vh;
box-sizing: border-box;
padding-top: 20rpx;
background: #fff;
.fixed-header {
position: fixed;
top: 0;
left: 0;
width: 100%;
background: #fff;
z-index: 9;
}
.search-box {
margin-top: 14rpx;
}
.body-box {
position: fixed;
top: 472rpx;
height: calc(100vh - 472rpx);
}
.aside {
position: fixed;
width: 194rpx;
left: 0;
top: 472rpx;
bottom: 0 !important;
box-sizing: border-box;
border-right: 2rpx solid #DADCE0;
background-color: #fff;
overflow-y: auto;
overflow-x: hidden;
overflow-scrolling: touch;
.item {
height: 94rpx;
box-sizing: border-box;
border-bottom: 2rpx solid #D2D2D2;
color: #033333;
text {
font-size: 28rpx;
}
}
.active {
border-left: 6rpx solid #FD574B;
color: #FD574B;
font-weight: bold;
}
}
.conter {
margin-left: 194rpx;
margin-top: 472rpx;
}
}
</style>
+2
View File
@@ -101,6 +101,7 @@ export default {
changeTab(index) { changeTab(index) {
if (this.asideList.length === 0) return; if (this.asideList.length === 0) return;
if (index === this.tabIndex) return; if (index === this.tabIndex) return;
this.page = 1;
this.dataList = []; this.dataList = [];
this.tabIndex = index; this.tabIndex = index;
this.search(); this.search();
@@ -151,6 +152,7 @@ export default {
asideTap(index) { asideTap(index) {
this.asideIndex = index; this.asideIndex = index;
this.page = 1; this.page = 1;
this.dataList = [];
this.search(); this.search();
}, },
goStore(id) { goStore(id) {
-191
View File
@@ -1,191 +0,0 @@
<template>
<view class="pkg-product-list">
<view class="top-box">
<view class="search-box flex jc-between ai-center">
<input type="text" v-model="keyword" placeholder="搜索商品" placeholder-style="color:#949494" @confirm="search">
<image class="icon" :src="webUrl+'/20220903142935869059.png'" mode="scaleToFill" @click="search"></image>
</view>
<u-tabs :list="tabList" keyName="cateName" lineColor="#D30808" :activeStyle="{color:'#FFFFFF',fontWeight:'bold'}"
:inactiveStyle="{color:'rgba(255,255,255,.6)'}"
lineWidth="120rpx" @click="tabsTap"></u-tabs>
</view>
<view class="body-box">
<view class="aside-box flex-0">
<view class="item flex jc-center ai-center" :class="index === asideIndex ? 'active' : ''"
v-for="(item, index) in asideList" :key="index" @click="asideTap(index)">
<text class="one-t">{{ item.cateName }}</text>
</view>
</view>
<view class="article-box">
<view class="line-location flex ai-center">
<image :src="webUrl+'/20220903142929759087.png'" mode="scaleToFill"></image>
<text class="bold" @click="goCity">当前城市{{ cityName }}</text>
</view>
<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 flex flex-wrap">
<view v-for="(item, index) in dataList" :key="index">
<view class="item" @click="$global.navToGoods(item.id)">
<image class="cover" :src="item.image" mode="scaleToFill"/>
<view class="name more-t">{{ item.storeName }}</view>
<view class="price bold">{{ item.price }}</view>
</view>
</view>
</view>
</mescroll-body>
</view>
</view>
</view>
</template>
<script>
import MescrollMixins from "@/mixins/mescroll-mixins.js";
import MescrollBody from "@/components/mescroll-uni/mescroll-body.vue";
import {fetchNormal, getCategory} from "@/api/store";
export default {
name: "nativeList",
components: {
MescrollBody
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
keyword: "",
asideList: [],
asideIndex: 0,
dataList: [], // 列表数据
tabList: [],
cityId: null,
cityName: "桂林市",
upOption: {
noMoreSize: 10, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
auto: true,
empty: {
tip: '暂无商品' // 提示
}
},
downOption: {
auto: false
}
}
},
mixins: [
MescrollMixins({
getPageData(mescroll) {
console.log("test", mescroll)
let that = this;
// 此时mescroll会携带page的参数:
let pageNum = mescroll.num; // 页码, 默认从1开始
let timer = setInterval(() => {
if (that.asideList.length > 0) {
clearInterval(timer);
let param = {
isGood: 1,
page: pageNum,
keyword: that.keyword,
cityName: that.cityName,
sid: that.asideList[that.asideIndex].id
};
fetchNormal(param).then(({data}) => {
if (mescroll.num === 1) {
that.dataList = [];
}
that.dataList = that.dataList.concat(data);
mescroll.endSuccess(data.length);
}).catch(err => {
mescroll.endErr();
uni.showToast({
title: err + '',
icon: 'none',
mask: false,
duration: 1500
});
})
}
}, 500);
}
})
],
onLoad(option) {
this.cityId = option.cityId;
this.init();
},
methods: {
init() {
getCategory(0, 35, this.cityId, true).then(({data}) => {
this.tabList = data;
this.asideList = data[0].children;
let memCityName = uni.getStorageSync("cityName")
if (memCityName.length) {
this.cityName = memCityName;
uni.removeStorageSync("cityName")
}
});
},
goCity() {
uni.redirectTo({
url: `/components/chose-city/chose-city?type=0&city=${this.cityName}`
})
},
search() {
//触发加载请求
this.mescroll.scrollTo(0, 0);
this.mescroll && this.mescroll.resetUpScroll(false);
},
tabsTap(item) {
this.asideList = item.children;
this.asideIndex = 0;
this.search();
},
asideTap(index) {
this.asideIndex = index;
this.search();
}
}
}
</script>
<style scoped lang="less">
@import "@/assets/css/product.less";
.pkg-product-list {
height: 100vh;
overflow-y: hidden;
.top-box {
height: 142rpx;
background: #FF564A;
}
.line-location {
padding: 20rpx;
font-size: 28rpx;
image {
width: 36rpx;
height: 36rpx;
margin-right: 4rpx;
}
}
.body-box {
height: calc(100vh - 142rpx);
.article-box {
.item {
height: 362rpx
}
}
}
}
</style>
+246
View File
@@ -0,0 +1,246 @@
<script setup>
import {getSeason, getSeasonPoster} from "@/api/product";
import cookie from "@/utils/store/cookie";
export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
id: null,
partnerId: null,
info: null,
current: 0,
showShare: false,
posterUrl: "", // 分享海报
}
},
onLoad(options) {
if (options.id) {
this.id = options.id || null;
this.partnerId = options.partnerId || null;
} else {
let obj = uni.getEnterOptionsSync();
if (options.scene || obj.query.scene) {
let query = options ? decodeURIComponent(options.scene) : decodeURIComponent(obj.query.scene);
this.id = getUrlParam(query, "id") || null;
this.partnerId = getUrlParam(query, "partnerId") || null;
}
}
if (this.partnerId) cookie.set("spread", this.partnerId);
this.init();
},
methods: {
init() {
getSeason(this.id).then(({data}) => {
if (data.sliderImages) data.swiper = data.sliderImages.split(",");
this.info = data;
});
getSeasonPoster(this.id).then(({data}) => this.posterUrl = data);
},
tapLeft() {
if (this.current === 0) return;
this.current--;
},
tapRight() {
if (this.current + 1 === this.info.swiper.length) return;
this.current++;
},
downloadImage() {
let that = this;
const randomID = () => Math.random().toString(36).substring(2);
uni.downloadFile({
url: this.posterUrl, //网络图片的地址
filePath: wx.env.USER_DATA_PATH + "/share_" + randomID() + ".png", //指定的本地文件路径
success: downRes => {
console.log(typeof downRes, downRes, "down")
uni.saveImageToPhotosAlbum({
filePath: downRes.filePath, //临时文件地址
success: function () {
uni.showToast({
title: "保存成功",
icon: "success",
success() {
that.showShare = false;
}
})
},
fail: function (err) {
uni.showToast({
title: err,
icon: "none"
})
}
})
},
fail: function (err) {
uni.showToast({
title: err.errMsg,
icon: "error"
})
}
})
},
},
}
</script>
<template>
<view class="product-season">
<template v-if="info">
<view class="scroll-item section">
<image class="section" :src="info.topImage" mode="scaleToFill"/>
<view class="share-label flex jc-center ai-center" @click="showShare=true" v-if="posterUrl.length>0">
<image class="icon-share" :src="webUrl+'/20230911105727684131.png'" mode="scaleToFill"/>
分享好友
</view>
</view>
<u-popup :show="showShare" mode="center" bgColor="transparent">
<view class="box-share">
<view class="box-img">
<image class="icon" :src="webUrl+'/20230608112219219303.png'" @click="showShare=false"/>
<image class="main-img" :src="posterUrl"/>
</view>
<image class="btn" :src="webUrl+'/20230608112210135038.png'" @click="saveImg"/>
</view>
</u-popup>
<view class="scroll-item section">
<u-swiper :autoplay="false" :current="current" :list="info.swiper" height="100vh" indicator
imgMode="scaleToFill"></u-swiper>
<image class="icon-direction icon-left" :src="webUrl+'/20230911105736198247.png'" mode="scaleToFill"
@click="tapLeft"/>
<image class="icon-direction icon-right" :src="webUrl+'/20230911105742958676.png'" mode="scaleToFill"
@click="tapRight"/>
</view>
<view class="scroll-item">
<scroll-view scroll-y class="product-list" :style="{backgroundImage:'url(' + info.productImage + ')'}">
<view class="item" v-for="(item,index) in info.products" :key="index">
<image class="item-img" :src="item.image" mode="widthFix"/>
<view class="content">
<view class="name bold one-t">{{ item.storeName }}</view>
<view class="flex jc-between ai-end">
<view class="price">活动价:
<text class="bold">{{ item.price }}</text>
</view>
<image class="btn-done" :src="webUrl+'/20230911105720914329.png'" mode="scaleToFill"
@click="$global.navToGoods(item.id)"/>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
</view>
</template>
<style scoped lang="less">
@import "@/assets/css/store.less";
.product-season {
width: 100vw;
height: 100vh;
overflow: hidden scroll;
scroll-snap-type: y mandatory;
image {
vertical-align: middle;
}
.scroll-item {
position: relative;
box-sizing: border-box;
scroll-snap-align: start;
}
.section {
width: 100vw;
height: 100vh;
}
.share-label {
position: absolute;
top: 674rpx;
right: 32rpx;
width: 200rpx;
height: 56rpx;
background: rgba(255, 255, 255, 0.39);
border-radius: 8rpx;
color: #333333;
font-size: 28rpx;
.icon-share {
width: 32rpx;
height: 32rpx;
margin-right: 4rpx;
}
}
.icon-direction {
position: absolute;
top: 50%;
width: 40rpx;
height: 74rpx;
}
.icon-left {
left: 32rpx;
}
.icon-right {
right: 32rpx;
}
.product-list {
padding: 200rpx 32rpx 0;
background-size: 100vw auto;
.item {
position: relative;
width: 686rpx;
margin-bottom: 46rpx;
border-radius: 40rpx;
overflow: hidden;
.item-img {
width: 686rpx;
}
.content {
position: absolute;
bottom: 0;
width: 100%;
box-sizing: border-box;
padding: 32rpx 40rpx;
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000000 100%);
color: #FFFFFF;
line-height: 64rpx;
.name {
font-size: 44rpx;
}
.price {
font-size: 32rpx;
text {
font-size: 60rpx;
}
}
.btn-done {
width: 220rpx;
height: 64rpx;
}
}
}
}
}
</style>
+14 -13
View File
@@ -108,8 +108,8 @@ export default {
</view> </view>
</u-popup> </u-popup>
<view class="scroll-item section"> <view class="scroll-item">
<u-swiper :autoplay="false" :current="current" :list="info.swiper" height="100vh" indicator <u-swiper :autoplay="false" :current="current" :list="info.swiper" height="1200rpx" indicator
imgMode="scaleToFill"></u-swiper> imgMode="scaleToFill"></u-swiper>
<image class="icon-direction icon-left" :src="webUrl+'/20230911105736198247.png'" mode="scaleToFill" <image class="icon-direction icon-left" :src="webUrl+'/20230911105736198247.png'" mode="scaleToFill"
@click="tapLeft"/> @click="tapLeft"/>
@@ -118,8 +118,10 @@ export default {
</view> </view>
<view class="scroll-item"> <view class="scroll-item">
<scroll-view scroll-y class="product-list" :style="{backgroundImage:'url(' + info.productImage + ')'}"> <image class="bg-img" :src="info.productImage" mode="widthFix"/>
<image class="item" :src="item.image" mode="scaleToFill" @click="$global.navToGoods(item.id)" <!-- <scroll-view scroll-y class="product-list" :style="{backgroundImage:'url(' + info.productImage + ')'}">-->
<scroll-view scroll-y class="product-list">
<image class="item" :src="item.image" mode="widthFix" @click="$global.navToGoods(item.id)"
v-for="(item,index) in info.products" :key="index"/> v-for="(item,index) in info.products" :key="index"/>
</scroll-view> </scroll-view>
</view> </view>
@@ -143,11 +145,6 @@ export default {
box-sizing: border-box; box-sizing: border-box;
} }
.section {
width: 100vw;
height: 100vh;
}
.img-top { .img-top {
width: 100vw; width: 100vw;
} }
@@ -187,15 +184,19 @@ export default {
} }
.product-list { .product-list {
padding: 200rpx 32rpx 0; position: absolute;
background-size: 100vw auto; top: 0;
left: 0;
padding: 280rpx 32rpx 0;
.item { .item {
width: 686rpx; width: 686rpx;
height: 400rpx;
margin-bottom: 46rpx; margin-bottom: 46rpx;
border-radius: 20rpx;
} }
} }
.bg-img {
width: 100vw;
}
} }
</style> </style>
+1 -1
View File
@@ -129,7 +129,7 @@ export default {
tabName: "", // 跳转初始分类名 tabName: "", // 跳转初始分类名
lock: false, lock: false,
upOption: { upOption: {
noMoreSize: 10, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5 noMoreSize: 5, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
auto: false, auto: false,
empty: { empty: {
tip: '暂无商品' // 提示 tip: '暂无商品' // 提示