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",
"style": {
"navigationBarTitleText": "健康首页",
"enablePullDownRefresh": false
"navigationBarTitleText": "文章分类",
"enablePullDownRefresh": false,
"navigationStyle": "default"
}
},
{
@ -568,6 +569,14 @@
"navigationBarTitleText": "订单详情",
"enablePullDownRefresh": false
}
},
{
"path": "svip/index",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "default"
}
}
]
}

View File

@ -1,95 +1,159 @@
<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>
<loading-view v-if="isFirstLoading"></loading-view>
<!-- 顶部tabbar -->
<view class="bg-white sticky top-0 z-9999">
<u-tabs :list="list" active-color="#378264" inactive-color="#808080" :current="id" @change="change"></u-tabs>
</view>
<mescroll-body :height="height" ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback"
:down="downOption" :up="upOption">
<!-- 广告位 -->
<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>
</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 @tap="jumpByOption(item)" v-for="(item,index) in dataList" :key="index"
class="w-710rpx p-base bg-white rounded-xs m-auto mt-base flex items-start justify-between">
<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>
</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>
</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: [CartMixin],
mixins: [MescrollMixin, CartMixin],
data() {
return {
isFirstLoading:true,
article_banner:[],//广
list: [{
name: '待收货'
}, {
name: '待付款'
}, {
name: '待评价',
}, {
name: '待收货'
}, {
name: '待付款'
}, {
name: '待评价',
}, {
name: '待收货'
}, {
name: '待付款'
}, {
name: '待评价',
}],
isFirstLoading: true,
article_banner: [], //广
searchText: '',
downOption: {
auto: false,
},
upOption: {
page: {
size: 20
},
noMoreSize: 1
},
dataList: [], //
id: 0
};
},
computed: {
cpaceImage(){
return this.article_banner.length>0?this.article_banner[0]:{}
height() {
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.getclassList()
uni.$on('isUp', ({
id
}) => {
this.dataList.forEach((item) => {
if (item.id == id) {
item.like_status = true;
item.likes += 1
}
})
})
},
methods: {
change(e) {
this.id = e
},
//广
async getCpace(){
try{
async getCpace() {
try {
let resDate = await this.$api.get('/v1/ads', {
params: {
keys: 'article_banner'
}
})
this.article_banner=resDate.article_banner
}catch(err){}
this.article_banner = resDate.article_banner
} catch (err) {} finally {}
},
//
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()
downCallback() {
this.mescroll.resetUpScroll();
this.dataList = []
},
Change(e) {
if (e == '')this.getclassList()
async upCallback(page) {
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) {
if (!!e.jump_link) {
if (e.jump_type == 1) {
this.$u.route(e.jump_link);
this.$u.route(e.jump_link);
} else if (e.jump_type == 2) {
this.$u.route(`/pages/web_view/index?url=${e.jump_link}`);
}
@ -103,7 +167,4 @@
.badge {
@apply bg-badge;
}
.box-show {
box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.12);
}
</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 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
>
<view class="w-200rpx flex-none">

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
<template>
<view>
<view class="u-wrap">
<!-- 顶部导航栏 -->
<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>
@ -13,242 +14,289 @@
</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>
<view class="u-menu-wrap">
<scroll-view scroll-y scroll-with-animation class="u-tab-view menu-scroll-view" :scroll-top="scrollTop"
:scroll-into-view="itemId">
<view v-for="(item,index) in tabbar" :key="index" class="u-tab-item" :class="[current == index ? 'u-tab-item-active' : '']"
@tap.stop="swichMenu(index)">
<text class="u-line-1">{{item.name}}</text>
</view>
</scroll-view>
<scroll-view :scroll-top="scrollRightTop" scroll-y scroll-with-animation class="right-box" @scroll="rightScroll">
<view class="page-view">
<view class="class-item" :id="'item' + index" v-for="(item , index) in tabbar" :key="index">
<view class="item-title">
<text>{{item.name}}</text>
</view>
<!-- 广告位 -->
<view class="my-20rpx">
<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>
</view>
<view class="item-container">
<view class="thumb-box" v-for="(item1, index1) in item.foods" :key="index1">
<image class="item-menu-image" :src="item1.icon" mode=""></image>
<view class="item-menu-name">{{item1.name}}</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</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();
}
},
},
};
import classifyData from './data.js';
export default {
data() {
return {
scrollTop: 0, //tab
oldScrollTop: 0,
current: 0, //
menuHeight: 0, //
menuItemHeight: 0, // item
itemId: '', // scroll-viewid
tabbar: classifyData,
menuItemPos: [],
arr: [],
scrollRightTop: 0, // scroll-view
timer: null, //
}
},
onLoad() {
},
onReady() {
this.getMenuItemTop()
},
methods: {
//
async swichMenu(index) {
if(this.arr.length == 0) {
await this.getMenuItemTop();
}
if (index == this.current) return;
this.scrollRightTop = this.oldScrollTop;
this.$nextTick(function(){
this.scrollRightTop = this.arr[index];
this.current = index;
this.leftMenuStatus(index);
})
},
//
getElRect(elClass, dataVal) {
new Promise((resolve, reject) => {
const query = uni.createSelectorQuery().in(this);
query.select('.' + elClass).fields({
size: true
}, res => {
// resnull
if (!res) {
setTimeout(() => {
this.getElRect(elClass);
}, 10);
return;
}
this[dataVal] = res.height;
resolve();
}).exec();
})
},
//
async observer() {
this.tabbar.map((val, index) => {
let observer = uni.createIntersectionObserver(this);
// scroll-viewiditemxxright-box
// .right-box
observer.relativeTo('.right-box', {
top: 0
}).observe('#item' + index, res => {
if (res.intersectionRatio > 0) {
let id = res.id.substring(4);
this.leftMenuStatus(id);
}
})
})
},
//
async leftMenuStatus(index) {
this.current = index;
// 0
if (this.menuHeight == 0 || this.menuItemHeight == 0) {
await this.getElRect('menu-scroll-view', 'menuHeight');
await this.getElRect('u-tab-item', 'menuItemHeight');
}
// item
this.scrollTop = index * this.menuItemHeight + this.menuItemHeight / 2 - this.menuHeight / 2;
},
// item
getMenuItemTop() {
new Promise(resolve => {
let selectorQuery = uni.createSelectorQuery();
selectorQuery.selectAll('.class-item').boundingClientRect((rects) => {
// rects[](selectAll)
if(!rects.length) {
setTimeout(() => {
this.getMenuItemTop();
}, 10);
return ;
}
rects.forEach((rect) => {
// rects[0].top()
this.arr.push(rect.top - rects[0].top);
resolve();
})
}).exec()
})
},
//
async rightScroll(e) {
this.oldScrollTop = e.detail.scrollTop;
if(this.arr.length == 0) {
await this.getMenuItemTop();
}
if(this.timer) return ;
if(!this.menuHeight) {
await this.getElRect('menu-scroll-view', 'menuHeight');
}
setTimeout(() => { //
this.timer = null;
// scrollHeight
let scrollHeight = e.detail.scrollTop + this.menuHeight / 2;
for (let i = 0; i < this.arr.length; i++) {
let height1 = this.arr[i];
let height2 = this.arr[i + 1];
// height2
if (!height2 || scrollHeight >= height1 && scrollHeight < height2) {
this.leftMenuStatus(i);
return ;
}
}
}, 10)
}
}
}
</script>
<style lang="scss" scoped>
.badge {
@apply bg-badge;
}
.u-wrap {
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>

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{
border: 1px solid !important;
border-width: 1px;
border-style: solid;
}
.inputHeight {
border: 1rpx solid;
@ -228,4 +229,10 @@ page {
button::after{ border: none; }
image{
height: auto;
}
.price-text {
&::before {
content: '';
font-size: 60%;
}
}