6
0
Fork 0

写充值会员的页面

hui.zhou
h30830569 2022-05-17 13:32:09 +08:00
parent 957c3eec59
commit 2fa2537f1a
11 changed files with 1947 additions and 297 deletions

View File

@ -0,0 +1,75 @@
<template>
<view >
<view class="bg-hex-303133 flex p-30rpx ">
<cu-avatar size="120" :src="user.avatar ? user.avatar : ''"></cu-avatar>
<view class="ml-20rpx mt-10rpx">
<image src="@/static/images/svip/no_svip.png" class="w-48rpx h-48rpx" mode=""></image>
<view class="text-hex-f5f5f5 text-22rpx mt-10rpx">您暂未开通会员</view>
</view>
</view>
<!-- -->
<view class="bg-white pb-40rpx">
<view class="p-30rpx text-32rpx ">尊享特权</view>
<view class="grid grid-cols-4 gap-30rpx">
<view class="flex items-center justify-center flex-col" v-for="(item,index) in 8 " :key="index">
<image src="@/static/images/user/share_friends.png" class="w-64rpx h-64rpx" mode=""></image>
<view class="mt-20rpx text-24rpx">会员折扣</view>
</view>
</view>
</view>
<!-- -->
<view class="bg-white mt-20rpx p-30rpx">
<!-- -->
<view class="grid grid-cols-3 gap-30rpx">
<view @click="choose(index)" :class="Index==index?'text-hex-f59e0b border-hex-f59e0b':'border-hex-F5F5F5'" class="rounded-15rpx py-50rpx flex items-center justify-center flex-col border border-solid " v-for="(item,index) in list" :key="index">
<view class="text-26rpx">{{item.name}}</view>
<view class="price-text text-34rpx font-medium mt-15rpx">{{item.money}}</view>
<view :class="Index==index?'text-hex-f59e0b':''" class="text-26rpx mt-15rpx text-hex-909399">{{item.time}}</view>
</view>
</view>
<!-- -->
<view class="mt-30rpx text-28rpx">
<view class="leading-40rpx">瞭男书店季卡</view>
<view class="leading-40rpx">咖啡饮品9折书籍9折免费咖啡饮品12杯</view>
<view class="leading-40rpx">通用现金卷100元 有限期90天</view>
</view>
<!-- -->
<view class="flex items-center mt-20rpx">
<u-checkbox v-model="checked" shape="circle" active-color="#f59e0b" size="28" icon-size="18"></u-checkbox>
<view class="text-22rpx -ml-15rpx mt-8rpx " >
已同意并阅读
<text class="text-hex-f59e0b">平台协议</text>
<text class="text-hex-f59e0b">价格说明</text>
</view>
</view>
<!-- -->
<view class="w-full mt-30rpx h-88rpx bg-hex-404040 rounded-full text-center text-hex-f59e0b leading-88rpx text-32rpx">立即开通</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
user: {},
list:[
{name:'年卡',money:'1288',time:'1年'},
{name:'季卡',money:'1288',time:'3月'},
{name:'月卡',money:'1288',time:'30天'}
],
Index:0,
checked:true
};
},
methods:{
choose(e){
this.Index=e
}
}
}
</script>
<style lang="scss">
</style>

View File

@ -271,8 +271,9 @@
{ {
"path": "pages/healthy/index", "path": "pages/healthy/index",
"style": { "style": {
"navigationBarTitleText": "健康首页", "navigationBarTitleText": "文章分类",
"enablePullDownRefresh": false "enablePullDownRefresh": false,
"navigationStyle": "default"
} }
}, },
{ {
@ -568,6 +569,14 @@
"navigationBarTitleText": "订单详情", "navigationBarTitleText": "订单详情",
"enablePullDownRefresh": false "enablePullDownRefresh": false
} }
},
{
"path": "svip/index",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "default"
}
} }
] ]
} }

View File

@ -1,95 +1,159 @@
<template> <template>
<view> <view>
<loading-view v-if="isFirstLoading"></loading-view> <loading-view v-if="isFirstLoading"></loading-view>
<!-- 导航栏 --> <!-- 顶部tabbar -->
<u-navbar :border-bottom="false" :is-back="false" :background="{ background: '#ffffff' }"> <view class="bg-white sticky top-0 z-9999">
<view class="pl-base w-full"> <u-tabs :list="list" active-color="#378264" inactive-color="#808080" :current="id" @change="change"></u-tabs>
<u-search @change="Change" @search="Search" placeholder="请输入内容" v-model="searchText" :show-action="false"></u-search> </view>
</view> <mescroll-body :height="height" ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback"
<template #right> :down="downOption" :up="upOption">
<view class="mx-base relative" @tap="$u.routeAuth('/pages/news/index')">
<u-icon name="chat" size="48"></u-icon>
<block v-if="news_num>0">
<u-badge :is-dot="true" size="16" :offset="[0, 2]" class="badge"></u-badge>
</block>
</view>
</template>
</u-navbar>
<!-- 广告位 --> <!-- 广告位 -->
<view v-if="cpaceImage.image" @tap="jumpByOption(cpaceImage)" class="w-710rpx m-auto mt-base"> <view v-if="cpaceImage.image" @tap="jumpByOption(cpaceImage)" class="w-710rpx m-auto mt-base">
<u-image border-radius="25rpx" width="100%" height="180rpx" :src="cpaceImage.image" :lazy-load="true"></u-image> <u-image border-radius="25rpx" width="100%" height="180rpx" :src="cpaceImage.image" :lazy-load="true"></u-image>
</view> </view>
<!-- 有数据 --> <!-- 列表 -->
<block v-if="dataList.length!=0" v-for="(item,index) in dataList" :key="index"> <view @tap="jumpByOption(item)" v-for="(item,index) in dataList" :key="index"
<view @tap="$u.route('/pages/healthy/healthy',{id:item.id})" class="box-show w-710rpx rounded-xs h-340rpx mt-base m-auto " > class="w-710rpx p-base bg-white rounded-xs m-auto mt-base flex items-start justify-between">
<image class="w-full h-full rounded-xs" :src="item.cover" ></image> <block v-if="item.cover">
<u-image border-radius="15rpx" width="250rpx" height="187rpx" :src="item.cover" :lazy-load="true"></u-image>
</block>
<view class="ml-base flex-1">
<view class="text-txBase w-full h-80rpx leading-40rpx text-30rpx two-ellipsis font-bold">{{item.title}}
</view>
<view class="text-txGray text-md mt-10rpx">{{item.created_at}}</view>
<view class="flex items-center justify-between mt-10rpx text-txGray text-md">
<view>积分: {{item.points}}</view>
<view class="flex items-center">
<u-icon :color="item.like_status ? '#378264' : ''" size="48"
:name="item.like_status ? 'thumb-up-fill' : 'thumb-up'"></u-icon>
<view class="ml-10rpx h-30rpx">{{item.likes}}</view>
</view>
</view>
</view> </view>
</block>
<!-- 没有数据 -->
<view v-if="dataList.length==0" class="flex items-center justify-center flex-col mt-80rpx">
<image class="w-300rpx h-254rpx" mode="scaleToFill" src="/static/images/user/empty.png"></image>
<view class="mt-30rpx text-25rpx text-txGray">~ 空空如也 ~</view>
</view> </view>
</mescroll-body>
</view> </view>
</template> </template>
<script> <script>
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
import CartMixin from '@/pages/shop_cart/mixin'; import CartMixin from '@/pages/shop_cart/mixin';
export default { export default {
mixins: [CartMixin], mixins: [MescrollMixin, CartMixin],
data() { data() {
return { return {
isFirstLoading:true, list: [{
article_banner:[],//广 name: '待收货'
}, {
name: '待付款'
}, {
name: '待评价',
}, {
name: '待收货'
}, {
name: '待付款'
}, {
name: '待评价',
}, {
name: '待收货'
}, {
name: '待付款'
}, {
name: '待评价',
}],
isFirstLoading: true,
article_banner: [], //广
searchText: '', searchText: '',
downOption: {
auto: false,
},
upOption: {
page: {
size: 20
},
noMoreSize: 1
},
dataList: [], // dataList: [], //
id: 0
}; };
}, },
computed: { computed: {
cpaceImage(){ height() {
return this.article_banner.length>0?this.article_banner[0]:{} const {
windowHeight,
statusBarHeight
} = this.$u.sys();
return windowHeight - statusBarHeight - 44 + 'px';
},
cpaceImage() {
return this.article_banner.length > 0 ? this.article_banner[0] : {}
} }
}, },
onLoad() { onLoad({
id
}) {
this.id = id
setTimeout(() => {
this.isFirstLoading = false
}, 300)
this.getCpace() this.getCpace()
this.getclassList() uni.$on('isUp', ({
id
}) => {
this.dataList.forEach((item) => {
if (item.id == id) {
item.like_status = true;
item.likes += 1
}
})
})
}, },
methods: { methods: {
change(e) {
this.id = e
},
//广 //广
async getCpace(){ async getCpace() {
try{ try {
let resDate = await this.$api.get('/v1/ads', { let resDate = await this.$api.get('/v1/ads', {
params: { params: {
keys: 'article_banner' keys: 'article_banner'
} }
}) })
this.article_banner=resDate.article_banner this.article_banner = resDate.article_banner
}catch(err){} } catch (err) {} finally {}
}, },
// downCallback() {
async getclassList(){ this.mescroll.resetUpScroll();
try{ this.dataList = []
const res=await this.$api.get(`/v1/articles/health-category`, {params: { key:this.searchText}})
this.dataList=res
}catch(err){}finally{
setTimeout(()=>{
this.isFirstLoading=false
},200)
}
},
Search() {
this.getclassList()
}, },
Change(e) { async upCallback(page) {
if (e == '')this.getclassList() this.loadData(page);
},
loadData({
num,
size
}) {
let obj = {
category: this.id,
key: this.searchText,
page: num,
per_page: size
}
this.$api.get(`/v1/articles/by-category/${ this.id}`, {
params: obj
}).then(res => {
this.mescroll.endSuccess(res.data.length)
if (num == 1) this.dataList = [];
this.dataList = this.dataList.concat(res.data);
}).catch(err => {
this.mescroll.endErr()
})
}, },
//
jumpByOption(e) { jumpByOption(e) {
if (!!e.jump_link) { if (!!e.jump_link) {
if (e.jump_type == 1) { if (e.jump_type == 1) {
this.$u.route(e.jump_link); this.$u.route(e.jump_link);
} else if (e.jump_type == 2) { } else if (e.jump_type == 2) {
this.$u.route(`/pages/web_view/index?url=${e.jump_link}`); this.$u.route(`/pages/web_view/index?url=${e.jump_link}`);
} }
@ -103,7 +167,4 @@
.badge { .badge {
@apply bg-badge; @apply bg-badge;
} }
.box-show {
box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.12);
}
</style> </style>

View File

@ -0,0 +1,109 @@
<template>
<view>
<loading-view v-if="isFirstLoading"></loading-view>
<!-- 导航栏 -->
<u-navbar :border-bottom="false" :is-back="false" :background="{ background: '#ffffff' }">
<view class="pl-base w-full">
<u-search @change="Change" @search="Search" placeholder="请输入内容" v-model="searchText" :show-action="false"></u-search>
</view>
<template #right>
<view class="mx-base relative" @tap="$u.routeAuth('/pages/news/index')">
<u-icon name="chat" size="48"></u-icon>
<block v-if="news_num>0">
<u-badge :is-dot="true" size="16" :offset="[0, 2]" class="badge"></u-badge>
</block>
</view>
</template>
</u-navbar>
<!-- 广告位 -->
<view v-if="cpaceImage.image" @tap="jumpByOption(cpaceImage)" class="w-710rpx m-auto mt-base">
<u-image border-radius="25rpx" width="100%" height="180rpx" :src="cpaceImage.image" :lazy-load="true"></u-image>
</view>
<!-- 有数据 -->
<block v-if="dataList.length!=0" v-for="(item,index) in dataList" :key="index">
<view @tap="$u.route('/pages/healthy/healthy',{id:item.id})" class="box-show w-710rpx rounded-xs h-340rpx mt-base m-auto " >
<image class="w-full h-full rounded-xs" :src="item.cover" ></image>
</view>
</block>
<!-- 没有数据 -->
<view v-if="dataList.length==0" class="flex items-center justify-center flex-col mt-80rpx">
<image class="w-300rpx h-254rpx" mode="scaleToFill" src="/static/images/user/empty.png"></image>
<view class="mt-30rpx text-25rpx text-txGray">~ 空空如也 ~</view>
</view>
</view>
</template>
<script>
import CartMixin from '@/pages/shop_cart/mixin';
export default {
mixins: [CartMixin],
data() {
return {
isFirstLoading:true,
article_banner:[],//广
searchText: '',
dataList: [], //
};
},
computed: {
cpaceImage(){
return this.article_banner.length>0?this.article_banner[0]:{}
}
},
onLoad() {
this.getCpace()
this.getclassList()
},
methods: {
//广
async getCpace(){
try{
let resDate = await this.$api.get('/v1/ads', {
params: {
keys: 'article_banner'
}
})
this.article_banner=resDate.article_banner
}catch(err){}
},
//
async getclassList(){
try{
const res=await this.$api.get(`/v1/articles/health-category`, {params: { key:this.searchText}})
this.dataList=res
}catch(err){}finally{
setTimeout(()=>{
this.isFirstLoading=false
},200)
}
},
Search() {
this.getclassList()
},
Change(e) {
if (e == '')this.getclassList()
},
//
jumpByOption(e) {
if (!!e.jump_link) {
if (e.jump_type == 1) {
this.$u.route(e.jump_link);
} else if (e.jump_type == 2) {
this.$u.route(`/pages/web_view/index?url=${e.jump_link}`);
}
}
},
}
}
</script>
<style lang="scss" scoped>
.badge {
@apply bg-badge;
}
.box-show {
box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.12);
}
</style>

View File

@ -36,7 +36,7 @@
</view> </view>
</view> </view>
<view class="flex items-center justify-between mt-20rpx text-txBase text-lg"> <view class="flex items-center justify-between mt-20rpx text-txBase text-lg">
<view class="flex-1" v-if="walletShow" <view @tap="$u.routeAuth('/pageB/svip/index')" class="flex-1" v-if="walletShow"
>余额: <text class="font-medium">{{ balance.balance }}</text></view >余额: <text class="font-medium">{{ balance.balance }}</text></view
> >
<view class="w-200rpx flex-none"> <view class="w-200rpx flex-none">

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
<template> <template>
<view> <view class="u-wrap">
<!-- 顶部导航栏 -->
<u-navbar :border-bottom="false" :is-back="false" :background="{ background: '#ffffff' }"> <u-navbar :border-bottom="false" :is-back="false" :background="{ background: '#ffffff' }">
<view class="pl-base w-full" @tap="$u.route('/pages/search/search')"> <view class="pl-base w-full" @tap="$u.route('/pages/search/search')">
<u-search disabled placeholder="搜索商品名称" :show-action="false"></u-search> <u-search disabled placeholder="搜索商品名称" :show-action="false"></u-search>
@ -13,242 +14,289 @@
</view> </view>
</template> </template>
</u-navbar> </u-navbar>
<view class="rounded-b-md bg-white fixed top-0 left-0 w-full z-50"> <view class="u-menu-wrap">
<view class="w-full" :style="[{ height: StatusBar + 44 + 'px' }]"></view> <scroll-view scroll-y scroll-with-animation class="u-tab-view menu-scroll-view" :scroll-top="scrollTop"
<u-tabs :scroll-into-view="itemId">
class="cu-tabs w-full" <view v-for="(item,index) in tabbar" :key="index" class="u-tab-item" :class="[current == index ? 'u-tab-item-active' : '']"
active-color="#378264" @tap.stop="swichMenu(index)">
inactive-color="#808080" <text class="u-line-1">{{item.name}}</text>
height="60" </view>
bar-height="8" </scroll-view>
:list="tabsList" <scroll-view :scroll-top="scrollRightTop" scroll-y scroll-with-animation class="right-box" @scroll="rightScroll">
:is-scroll="true" <view class="page-view">
:current="tabsCurrent" <view class="class-item" :id="'item' + index" v-for="(item , index) in tabbar" :key="index">
@change="tabChange" <view class="item-title">
></u-tabs> <text>{{item.name}}</text>
<view class="h-80rpx flex justify-between items-center px-40rpx"> </view>
<view class="text-txGray text-lg" :class="filterSort == '' ? 'text-primary' : ''" @tap="onChangeFilter('')"> </view> <!-- 广告位 -->
<view <view class="my-20rpx">
class="text-txGray text-lg flex items-center" <image class="w-full h-200rpx" src="https://img1.baidu.com/it/u=1597761366,2823600315&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500" mode="aspectFill"></image>
:class="filterSort == 'price' || filterSort == '-price' ? 'text-primary' : ''" </view>
@tap="onPriceSort" <view class="item-container">
> <view class="thumb-box" v-for="(item1, index1) in item.foods" :key="index1">
<text> 价格 </text> <image class="item-menu-image" :src="item1.icon" mode=""></image>
<view> <view class="item-menu-name">{{item1.name}}</view>
<trigonometry :key="'a' + key" direction="up" :color="filterSort == 'price' ? '#378264' : '#808080'"> </trigonometry> </view>
<trigonometry :key="'b' + key" direction="down" :color="filterSort == '-price' ? '#378264' : '#808080'"> </trigonometry> </view>
</view> </view>
</view> </view>
<view </scroll-view>
class="text-txGray text-lg flex items-center" </view>
:class="filterSort == 'sales' || filterSort == '-sales' ? 'text-primary' : ''" </view>
@tap="onSaleSort"
>
<text> 销量 </text>
<view>
<trigonometry :key="'c' + key" direction="up" :color="filterSort == 'sales' ? '#378264' : '#808080'"> </trigonometry>
<trigonometry :key="'d' + key" direction="down" :color="filterSort == '-sales' ? '#378264' : '#808080'"> </trigonometry>
</view>
</view>
<view class="text-txGray text-lg" :class="filterSort == 'release_at' ? 'text-primary' : ''" @tap="onChangeFilter('release_at')"></view>
</view>
</view>
<mescroll-body
:height="height"
:bottombar="false"
ref="mescrollRef"
@init="mescrollInit"
@down="downCallback"
@up="upCallback"
:down="downOption"
:up="upOption"
>
<view class="px-rowSm mt-20rpx pt-base" :style="[{ marginTop: 150 + 'rpx' }]">
<!-- <view class="grid grid-cols-2 gap-x-10rpx px-10rpx gap-y-20rpx">
<goods-item v-for="(item, index) in goods" :goods="item" :key="index"></goods-item>
</view> -->
<goods-list ref="uWaterfall" :list="goods"></goods-list>
</view>
</mescroll-body>
</view>
</template> </template>
<script> <script>
import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; import classifyData from './data.js';
import CartMixin from '@/pages/shop_cart/mixin'; export default {
export default { data() {
mixins: [MescrollMixin, CartMixin], return {
data() { scrollTop: 0, //tab
return { oldScrollTop: 0,
key: 0, current: 0, //
firstLoading: true, menuHeight: 0, //
tabsCurrent: 0, menuItemHeight: 0, // item
tabsList: [], itemId: '', // scroll-viewid
filter: { tabbar: classifyData,
sort: '', //price sales release_at price -price menuItemPos: [],
}, arr: [],
downOption: { scrollRightTop: 0, // scroll-view
// use: false, timer: null, //
},
upOption: { }
auto: false, },
}, onLoad() {
};
}, },
computed: { onReady() {
StatusBar() { this.getMenuItemTop()
const { statusBarHeight } = this.$u.sys(); },
return statusBarHeight; methods: {
}, //
filterSort() { async swichMenu(index) {
return this.filter.sort; if(this.arr.length == 0) {
}, await this.getMenuItemTop();
goods() { }
return this.tabsList[this.tabsCurrent]?.goods ?? []; if (index == this.current) return;
}, this.scrollRightTop = this.oldScrollTop;
height() { this.$nextTick(function(){
const { windowHeight, statusBarHeight } = this.$u.sys(); this.scrollRightTop = this.arr[index];
return windowHeight - statusBarHeight - 44 + 'px'; this.current = index;
}, this.leftMenuStatus(index);
}, })
onShow() { },
const params = uni.getStorageSync('/pages/sort/index') ?? ''; //
uni.removeStorageSync('/pages/sort/index'); getElRect(elClass, dataVal) {
this.id = params.id; new Promise((resolve, reject) => {
if (!!this.id && this.tabsList.length > 0) { const query = uni.createSelectorQuery().in(this);
const index = this.tabsList?.findIndex(({ id }) => id == this.id); query.select('.' + elClass).fields({
if (index != this.tabsCurrent) { size: true
setTimeout(()=>{ }, res => {
this.tabChange(index >= 0 ? index : 0); // resnull
},200) if (!res) {
} setTimeout(() => {
} this.getElRect(elClass);
}, }, 10);
methods: { return;
async downCallback() { }
this.mescroll.resetUpScroll(); this[dataVal] = res.height;
}, resolve();
async upCallback(page) { }).exec();
if (this.firstLoading) { })
await this.getCategories(); },
} //
this.getGoodsList(page); async observer() {
this.firstLoading = false; this.tabbar.map((val, index) => {
}, let observer = uni.createIntersectionObserver(this);
// // scroll-viewiditemxxright-box
onChangeFilter(type) { // .right-box
if (type == this.filter.sort) return; observer.relativeTo('.right-box', {
this.$u.throttle(() => { top: 0
this.$refs.uWaterfall.clear(); }).observe('#item' + index, res => {
this.$nextTick(() => { if (res.intersectionRatio > 0) {
this.filter.sort = type; let id = res.id.substring(4);
this.mescroll.resetUpScroll(); this.leftMenuStatus(id);
}); }
}); })
}, })
// },
onPriceSort() { //
this.Refresh(); async leftMenuStatus(index) {
const type = this.filter.sort == 'price' ? '-price' : 'price'; this.current = index;
this.onChangeFilter(type); // 0
}, if (this.menuHeight == 0 || this.menuItemHeight == 0) {
// await this.getElRect('menu-scroll-view', 'menuHeight');
onSaleSort() { await this.getElRect('u-tab-item', 'menuItemHeight');
this.Refresh(); }
const type = this.filter.sort == 'sales' ? '-sales' : 'sales'; // item
this.onChangeFilter(type); this.scrollTop = index * this.menuItemHeight + this.menuItemHeight / 2 - this.menuHeight / 2;
}, },
// // item
Refresh() { getMenuItemTop() {
this.$nextTick(() => { new Promise(resolve => {
this.key++; let selectorQuery = uni.createSelectorQuery();
}); selectorQuery.selectAll('.class-item').boundingClientRect((rects) => {
}, // rects[](selectAll)
// if(!rects.length) {
tabChange(index) { setTimeout(() => {
this.filter.sort = ''; this.getMenuItemTop();
if (!this.tabsCurrent) this.tabsCurrent = 0; }, 10);
return ;
this.$refs.uWaterfall.clear(); }
rects.forEach((rect) => {
this.$nextTick(() => { // rects[0].top()
console.log("======="); this.arr.push(rect.top - rects[0].top);
console.log(index); resolve();
let preTab = this.tabsList[this.tabsCurrent]; })
preTab.y = this.mescroll.getScrollTop(); }).exec()
this.tabsCurrent = index; })
},
const curTab = this.tabsList[index]; //
if (!curTab.goods) { async rightScroll(e) {
this.mescroll.resetUpScroll(); this.oldScrollTop = e.detail.scrollTop;
} else { if(this.arr.length == 0) {
this.mescroll.setPageNum(curTab.num + 1); await this.getMenuItemTop();
this.mescroll.endSuccess(curTab.curPageLen, curTab.hasNext); }
this.$nextTick(() => { if(this.timer) return ;
this.mescroll.scrollTo(curTab.y, 0); if(!this.menuHeight) {
}); await this.getElRect('menu-scroll-view', 'menuHeight');
} }
}); setTimeout(() => { //
}, this.timer = null;
async getCategories() { // scrollHeight
return new Promise((resolve, reject) => { let scrollHeight = e.detail.scrollTop + this.menuHeight / 2;
this.$api for (let i = 0; i < this.arr.length; i++) {
.get('/v1/product/categories') let height1 = this.arr[i];
.then((resData) => { let height2 = this.arr[i + 1];
resData.unshift({ // height2
icon: "", if (!height2 || scrollHeight >= height1 && scrollHeight < height2) {
id: -999, this.leftMenuStatus(i);
name: "全部" return ;
}) }
this.tabsList = resData.map((e) => { }
return { }, 10)
...e, }
num: 1, }
y: 0, }
curPageLen: 0,
hasNext: true,
goods: null,
};
});
if (!!this.id) {
const index = resData.findIndex(({ id }) => id == this.id);
this.tabChange(index >= 0 ? index : 0);
}
resolve(resData);
})
.catch((err) => {
reject(err);
});
});
},
async getGoodsList({ num, size }) {
let keyword = this.tabsList[this.tabsCurrent].id;
try {
const resData = await this.$api.get('/v1/product/products', {
params: {
sort: this.filter.sort,
per_page: size,
page: num,
category: keyword == -999 ? '' : keyword,
},
});
const { data } = resData;
let curTab = this.tabsList[this.tabsCurrent];
if (num === 1) curTab.goods = [];
curTab.goods = curTab.goods.concat(data);
curTab.num = num;
curTab.curPageLen = data.length;
curTab.hasNext = this.mescroll.optUp.hasNext;
this.mescroll.endSuccess(data.length, size == data.length);
} catch (error) {
this.mescroll.endErr();
}
},
},
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.badge { .u-wrap {
@apply bg-badge; height: calc(100vh);
} /* #ifdef H5 */
height: calc(100vh - var(--window-top));
/* #endif */
display: flex;
flex-direction: column;
}
.u-search-box {
padding: 18rpx 30rpx;
}
.u-menu-wrap {
flex: 1;
display: flex;
overflow: hidden;
}
.u-search-inner {
background-color: rgb(234, 234, 234);
border-radius: 100rpx;
display: flex;
align-items: center;
padding: 10rpx 16rpx;
}
.u-search-text {
font-size: 26rpx;
color: $u-tips-color;
margin-left: 10rpx;
}
.u-tab-view {
width: 200rpx;
height: 100%;
}
.u-tab-item {
height: 110rpx;
background: #f6f6f6;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
font-size: 26rpx;
color: #444;
font-weight: 400;
line-height: 1;
}
.u-tab-item-active {
position: relative;
color: #000;
font-size: 30rpx;
font-weight: 600;
background: #fff;
}
.u-tab-item-active::before {
content: "";
position: absolute;
border-left: 4px solid $u-type-primary;
height: 32rpx;
left: 0;
top: 39rpx;
}
.u-tab-view {
height: 100%;
}
.right-box {
background-color: rgb(250, 250, 250);
}
.page-view {
padding: 16rpx;
}
.class-item {
margin-bottom: 30rpx;
background-color: #fff;
padding: 16rpx;
border-radius: 8rpx;
}
// .class-item:last-child {
// min-height: 100vh;
// }
.item-title {
font-size: 26rpx;
color: $u-main-color;
font-weight: bold;
}
.item-menu-name {
font-weight: normal;
font-size: 24rpx;
color: $u-main-color;
}
.item-container {
display: flex;
flex-wrap: wrap;
}
.thumb-box {
width: 33.333333%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
margin-top: 20rpx;
}
.item-menu-image {
width: 120rpx;
height: 120rpx;
}
</style> </style>

View File

@ -0,0 +1,254 @@
<template>
<view>
<u-navbar :border-bottom="false" :is-back="false" :background="{ background: '#ffffff' }">
<view class="pl-base w-full" @tap="$u.route('/pages/search/search')">
<u-search disabled placeholder="搜索商品名称" :show-action="false"></u-search>
</view>
<template #right>
<view class="mx-base relative" @tap="$u.routeAuth('/pageA/news/index')">
<u-icon name="chat" size="48"></u-icon>
<block v-if="news_num > 0">
<u-badge :is-dot="true" size="16" :offset="[0, 2]" class="badge"></u-badge>
</block>
</view>
</template>
</u-navbar>
<view class="rounded-b-md bg-white fixed top-0 left-0 w-full z-50">
<view class="w-full" :style="[{ height: StatusBar + 44 + 'px' }]"></view>
<u-tabs
class="cu-tabs w-full"
active-color="#378264"
inactive-color="#808080"
height="60"
bar-height="8"
:list="tabsList"
:is-scroll="true"
:current="tabsCurrent"
@change="tabChange"
></u-tabs>
<view class="h-80rpx flex justify-between items-center px-40rpx">
<view class="text-txGray text-lg" :class="filterSort == '' ? 'text-primary' : ''" @tap="onChangeFilter('')"> </view>
<view
class="text-txGray text-lg flex items-center"
:class="filterSort == 'price' || filterSort == '-price' ? 'text-primary' : ''"
@tap="onPriceSort"
>
<text> 价格 </text>
<view>
<trigonometry :key="'a' + key" direction="up" :color="filterSort == 'price' ? '#378264' : '#808080'"> </trigonometry>
<trigonometry :key="'b' + key" direction="down" :color="filterSort == '-price' ? '#378264' : '#808080'"> </trigonometry>
</view>
</view>
<view
class="text-txGray text-lg flex items-center"
:class="filterSort == 'sales' || filterSort == '-sales' ? 'text-primary' : ''"
@tap="onSaleSort"
>
<text> 销量 </text>
<view>
<trigonometry :key="'c' + key" direction="up" :color="filterSort == 'sales' ? '#378264' : '#808080'"> </trigonometry>
<trigonometry :key="'d' + key" direction="down" :color="filterSort == '-sales' ? '#378264' : '#808080'"> </trigonometry>
</view>
</view>
<view class="text-txGray text-lg" :class="filterSort == 'release_at' ? 'text-primary' : ''" @tap="onChangeFilter('release_at')"></view>
</view>
</view>
<mescroll-body
:height="height"
:bottombar="false"
ref="mescrollRef"
@init="mescrollInit"
@down="downCallback"
@up="upCallback"
:down="downOption"
:up="upOption"
>
<view class="px-rowSm mt-20rpx pt-base" :style="[{ marginTop: 150 + 'rpx' }]">
<!-- <view class="grid grid-cols-2 gap-x-10rpx px-10rpx gap-y-20rpx">
<goods-item v-for="(item, index) in goods" :goods="item" :key="index"></goods-item>
</view> -->
<goods-list ref="uWaterfall" :list="goods"></goods-list>
</view>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
import CartMixin from '@/pages/shop_cart/mixin';
export default {
mixins: [MescrollMixin, CartMixin],
data() {
return {
key: 0,
firstLoading: true,
tabsCurrent: 0,
tabsList: [],
filter: {
sort: '', //price sales release_at price -price
},
downOption: {
// use: false,
},
upOption: {
auto: false,
},
};
},
computed: {
StatusBar() {
const { statusBarHeight } = this.$u.sys();
return statusBarHeight;
},
filterSort() {
return this.filter.sort;
},
goods() {
return this.tabsList[this.tabsCurrent]?.goods ?? [];
},
height() {
const { windowHeight, statusBarHeight } = this.$u.sys();
return windowHeight - statusBarHeight - 44 + 'px';
},
},
onShow() {
const params = uni.getStorageSync('/pages/sort/index') ?? '';
uni.removeStorageSync('/pages/sort/index');
this.id = params.id;
if (!!this.id && this.tabsList.length > 0) {
const index = this.tabsList?.findIndex(({ id }) => id == this.id);
if (index != this.tabsCurrent) {
setTimeout(()=>{
this.tabChange(index >= 0 ? index : 0);
},200)
}
}
},
methods: {
async downCallback() {
this.mescroll.resetUpScroll();
},
async upCallback(page) {
if (this.firstLoading) {
await this.getCategories();
}
this.getGoodsList(page);
this.firstLoading = false;
},
//
onChangeFilter(type) {
if (type == this.filter.sort) return;
this.$u.throttle(() => {
this.$refs.uWaterfall.clear();
this.$nextTick(() => {
this.filter.sort = type;
this.mescroll.resetUpScroll();
});
});
},
//
onPriceSort() {
this.Refresh();
const type = this.filter.sort == 'price' ? '-price' : 'price';
this.onChangeFilter(type);
},
//
onSaleSort() {
this.Refresh();
const type = this.filter.sort == 'sales' ? '-sales' : 'sales';
this.onChangeFilter(type);
},
//
Refresh() {
this.$nextTick(() => {
this.key++;
});
},
//
tabChange(index) {
this.filter.sort = '';
if (!this.tabsCurrent) this.tabsCurrent = 0;
this.$refs.uWaterfall.clear();
this.$nextTick(() => {
console.log("=======");
console.log(index);
let preTab = this.tabsList[this.tabsCurrent];
preTab.y = this.mescroll.getScrollTop();
this.tabsCurrent = index;
const curTab = this.tabsList[index];
if (!curTab.goods) {
this.mescroll.resetUpScroll();
} else {
this.mescroll.setPageNum(curTab.num + 1);
this.mescroll.endSuccess(curTab.curPageLen, curTab.hasNext);
this.$nextTick(() => {
this.mescroll.scrollTo(curTab.y, 0);
});
}
});
},
async getCategories() {
return new Promise((resolve, reject) => {
this.$api
.get('/v1/product/categories')
.then((resData) => {
resData.unshift({
icon: "",
id: -999,
name: "全部"
})
this.tabsList = resData.map((e) => {
return {
...e,
num: 1,
y: 0,
curPageLen: 0,
hasNext: true,
goods: null,
};
});
if (!!this.id) {
const index = resData.findIndex(({ id }) => id == this.id);
this.tabChange(index >= 0 ? index : 0);
}
resolve(resData);
})
.catch((err) => {
reject(err);
});
});
},
async getGoodsList({ num, size }) {
let keyword = this.tabsList[this.tabsCurrent].id;
try {
const resData = await this.$api.get('/v1/product/products', {
params: {
sort: this.filter.sort,
per_page: size,
page: num,
category: keyword == -999 ? '' : keyword,
},
});
const { data } = resData;
let curTab = this.tabsList[this.tabsCurrent];
if (num === 1) curTab.goods = [];
curTab.goods = curTab.goods.concat(data);
curTab.num = num;
curTab.curPageLen = data.length;
curTab.hasNext = this.mescroll.optUp.hasNext;
this.mescroll.endSuccess(data.length, size == data.length);
} catch (error) {
this.mescroll.endErr();
}
},
},
};
</script>
<style lang="scss" scoped>
.badge {
@apply bg-badge;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -209,7 +209,8 @@ page {
border-bottom: 1rpx solid #E5E5E5; border-bottom: 1rpx solid #E5E5E5;
} }
.border{ .border{
border: 1px solid !important; border-width: 1px;
border-style: solid;
} }
.inputHeight { .inputHeight {
border: 1rpx solid; border: 1rpx solid;
@ -228,4 +229,10 @@ page {
button::after{ border: none; } button::after{ border: none; }
image{ image{
height: auto; height: auto;
}
.price-text {
&::before {
content: '';
font-size: 60%;
}
} }