<template> <view class="container" :style="appThemeStyle"> <mescroll-body ref="mescrollRef" :sticky="true" @init="mescrollInit" :down="{ use: false }" :up="upOption" @up="upCallback"> <!-- 拼团海报图 --> <view v-if="curTab == 0 && setting.backdrop" class="banner"> <image class="image" :src="setting.backdrop.src" mode="widthFix"></image> </view> <!-- 拼团活动 --> <view v-if="curTab == 0" class="groupon-hall active-list"> <view class="goods-item--container" v-for="(item, index) in goodsList.data" :key="index"> <view class="goods-item" @click="onTargetGoods(item)"> <!-- 商品图片 --> <view class="goods-item-left"> <view v-if="item.active_type != ActiveTypeEnum.NORMAL.value" class="label"> <text>{{ ActiveTypeEnum[item.active_type].name2 }}</text> </view> <image class="image" :src="item.goods_image"></image> </view> <view class="goods-item-right"> <!-- 商品标题 --> <view class="goods-name"> <text class="twoline-hide">{{ item.goods_name }}</text> </view> <!-- 商品信息 --> <view class="goods-item-desc"> <view class="desc_situation"> <view class="state-tag"> <u-tag :color="appTheme.mainBg" :border-color="appTheme.mainBg" :text="`${item.show_people}人团`" type="error" size="mini" mode="plain" /> </view> <view class="state-tag"> <u-tag v-if="item.active_sales" :color="appTheme.mainBg" :border-color="tagBorderColor" :bg-color="tagBackgroundColor" :text="`已团${item.active_sales}件`" type="error" size="mini" /> </view> </view> <view class="desc-footer"> <view class="item-prices oneline-hide"> <text class="price-x">¥{{ item.groupon_price }}</text> <text class="price-y cl-9">¥{{ item.original_price }}</text> </view> <view class="settlement">去拼团</view> </view> </view> </view> </view> </view> </view> <!-- 我的拼团 --> <view v-if="curTab == 1" class="groupon-hall my-list"> <view class="goods-item--container" v-for="(item, index) in myList.data" :key="index"> <view class="goods-item" @click="onTargetTask(item)"> <!-- 商品图片 --> <view class="goods-item-left"> <view v-if="item.active_type != ActiveTypeEnum.NORMAL.value" class="label"> <text>{{ ActiveTypeEnum[item.active_type].name2 }}</text> </view> <image class="image" :src="item.goods.goods_image"></image> </view> <view class="goods-item-right"> <!-- 商品标题 --> <view class="goods-name"> <text class="twoline-hide">{{ item.goods.goods_name }}</text> </view> <!-- 商品信息 --> <view class="goods-item-desc"> <view class="desc_situation"> <u-tag v-if="item.status == TaskStatusEnum.NORMAL.value" :text="`已拼${item.joined_people}人,还差${item.people - item.joined_people}人`" type="warning" size="mini" /> <u-tag v-else class="people" :text="`${item.people}人团`" type="error" size="mini" mode="plain" /> </view> <view class="desc-footer"> <view class="item-status"> <text>{{ TaskStatusEnum[item.status].name }}</text> </view> <view v-if="item.status == TaskStatusEnum.NORMAL.value" class="settlement">查看拼单</view> </view> </view> </view> </view> </view> </view> <!-- 底部选项卡 --> <view class="footer-fixed"> <view class="footer-container"> <!-- 拼团活动 --> <view class="tabbar-item flex-box" :class="{ active: curTab == 0 }"> <view class="tabbar-item-content dis-flex flex-x-center flex-y-center" @click="onChangeTab(0)"> <view class="tabbar-item-icon"> <text class="iconfont icon-shangcheng"></text> </view> <view class="tabbar-item-name"> <text>拼团活动</text> </view> </view> </view> <!-- 分割线 --> <view class="tabbar-item__divider"> <view class="divider-line"></view> </view> <!-- 我的砍价 --> <view class="tabbar-item flex-box" :class="{ active: curTab == 1 }"> <view class="tabbar-item-content dis-flex flex-x-center flex-y-center" @click="onChangeTab(1)"> <view class="tabbar-item-icon"> <text class="iconfont icon-sy-yh"></text> </view> <view class="tabbar-item-name"> <text>我的拼团</text> </view> </view> </view> </view> </view> </mescroll-body> </view> </template> <script> import WxofficialMixin from '@/core/mixins/wxofficial' import { hex2rgba } from '@/utils/color' import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins' import { getEmptyPaginateObj, getMoreListData } from '@/core/app' import { ActiveStatusEnum, ActiveTypeEnum, TaskStatusEnum } from '@/common/enum/groupon' import * as TaskApi from '@/api/groupon/task' import * as GoodsApi from '@/api/groupon/goods' import SettingModel from '@/common/model/groupon/Setting' const pageSize = 15 export default { mixins: [MescrollMixin, WxofficialMixin], data() { return { // 枚举类 ActiveStatusEnum, ActiveTypeEnum, TaskStatusEnum, // 当前tab索引 curTab: 0, // 上拉加载配置 upOption: { // 首次自动执行 auto: true, // 每页数据的数量; 默认10 page: { size: pageSize }, // 数量要大于3条才显示无更多数据 noMoreSize: 3, }, // 拼团设置 setting: {}, // 拼团商品列表 goodsList: getEmptyPaginateObj(), // 我的拼单列表 myList: getEmptyPaginateObj(), } }, watch: { curTab(val) { // 设置页面标题 uni.setNavigationBarTitle({ title: val == 0 ? '拼团活动' : '我的拼团' }) } }, computed: { // 标签背景色 tagBackgroundColor() { return hex2rgba(this.appTheme.mainBg, 0.1) }, // 标签边框颜色 tagBorderColor() { return hex2rgba(this.appTheme.mainBg, 0.6) } }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { // 设置当前tab索引 if (options.tab) { this.curTab = options.tab } // 获取拼团设置 this.getSetting() // 设置微信公众号链接分享卡片内容 this.setWxofficialShareData() }, methods: { // 获取拼团设置 getSetting() { SettingModel.data().then(setting => this.setting = setting) }, /** * 上拉加载的回调 * 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 * @param {Object} page */ upCallback(page) { const app = this // 设置列表数据 app.getListData(page.num) .then(list => { const curPageLen = list.data.length const totalSize = list.data.total app.mescroll.endBySize(curPageLen, totalSize) }) .catch(() => app.mescroll.endErr()) }, // 获取列表数据(根据当前选项卡判断调用的方法) getListData(pageNo) { const apiFuc = { 0: this.getGoodsList, 1: this.getMyList } return apiFuc[this.curTab](pageNo) }, /** * 获取拼团商品列表 * @param {Number} pageNo 页码 */ getGoodsList(pageNo = 1) { const app = this return new Promise((resolve, reject) => { GoodsApi.list({ page: pageNo }, { load: false }) .then(result => { // 合并新数据 const newList = result.data.list app.goodsList.data = getMoreListData(newList, app.goodsList, pageNo) resolve(newList) }) .catch(reject) }) }, // 获取我的拼团列表 getMyList(pageNo) { const app = this return new Promise((resolve, reject) => { TaskApi.myList({ page: pageNo }, { load: false }) .then(result => { // 合并新数据 const newList = result.data.list app.myList.data = getMoreListData(newList, app.myList, pageNo) resolve(newList) }) .catch(reject) }) }, // 切换当前选项卡 onChangeTab(key = 0) { const app = this // 记录选项卡索引 app.curTab = key // 刷新列表数据 app.goodsList = getEmptyPaginateObj() app.myList = getEmptyPaginateObj() app.mescroll.resetUpScroll() }, // 跳转到拼团商品详情 onTargetGoods(item) { this.$navTo('pages/groupon/goods/index', { grouponGoodsId: item.groupon_goods_id }) }, // 跳转拼单详情页 onTargetTask(item) { this.$navTo('pages/groupon/task/index', { taskId: item.task_id }) }, // 设置微信公众号链接分享卡片内容 setWxofficialShareData() { this.updateShareCardData({ title: '拼团活动' }) }, }, /** * 分享当前页面 */ onShareAppMessage() { // 构建页面参数 const params = this.$getShareUrlParams() return { title: '拼团活动', path: `/pages/groupon/index?${params}` } }, /** * 分享到朋友圈 * 本接口为 Beta 版本,暂只在 Android 平台支持,详见分享到朋友圈 (Beta) * https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/share-timeline.html */ onShareTimeline() { // 构建页面参数 const params = this.$getShareUrlParams() return { title: '拼团活动', path: `/pages/groupon/index?${params}` } }, } </script> <style lang="scss"> page { background: #F5F5F8; } </style> <style lang="scss" scoped> .container { // 设置ios刘海屏底部横线安全区域 // 110 - 18 + 4 padding-bottom: calc(constant(safe-area-inset-bottom) + 96rpx); padding-bottom: calc(env(safe-area-inset-bottom) + 96rpx); } .banner { z-index: 0; .image { display: block; width: 100%; } } .groupon-hall { padding: 0 24rpx; position: relative; z-index: 1; &.active-list { margin-top: -80rpx; } &.my-list { padding-top: 30rpx; } } .goods-item--container { margin-bottom: 20rpx; &:last-child { margin-bottom: 0 !important; } } .goods-item { padding: 28rpx 24rpx; display: flex; background: #fff; box-sizing: border-box; border-radius: 14rpx; box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.07); } .goods-item-left { position: relative; background: #fff; margin-right: 20rpx; .label { position: absolute; top: 0; left: 0; z-index: 1; background: linear-gradient(to right, #ffa600, #f5b914); color: #fff; font-size: 24rpx; padding: 6rpx 8rpx; border-radius: 8rpx; } .image { display: block; width: 220rpx; height: 220rpx; border-radius: 10rpx; } } .goods-item-right { position: relative; flex: 1; .goods-name { display: block; width: 100%; min-height: 68rpx; font-size: 28rpx; line-height: 1.3; color: #333; } } .goods-item-desc { margin-top: 20rpx; .desc_situation { font-size: 26rpx; line-height: 1.3; color: $main-bg; margin-top: 20rpx; } .state-tag { display: inline-block; margin-right: 14rpx; } .desc-footer { width: 100%; display: flex; justify-content: space-between; align-items: center; position: absolute; right: 0rpx; bottom: 0rpx; min-height: 44rpx; .item-status { color: $main-bg; } .item-prices { padding-right: 6rpx; .price-x { margin-right: 14rpx; color: $main-bg; font-size: 28rpx; } .price-y { color: #999; text-decoration: line-through; font-size: 24rpx; } } .settlement { padding: 0 30rpx; line-height: 56rpx; text-align: center; font-size: 28rpx; border-radius: 40rpx; color: #fff; background: linear-gradient(to right, $main-bg, $main-bg2); color: $main-text; } } } // 底部选项卡 .footer-fixed { position: fixed; bottom: var(--window-bottom); left: 0; right: 0; z-index: 11; box-shadow: 0 -4rpx 40rpx 0 rgba(151, 151, 151, 0.24); background: #fff; // 设置ios刘海屏底部横线安全区域 padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); } .footer-container { display: flex; align-items: center; height: 96rpx; } .tabbar-item { font-size: 30rpx; &.active { .tabbar-item-content { color: $main-bg; } } .tabbar-item-icon { margin-right: 15rpx; } } // 分割线 .tabbar-item__divider { padding: 22rpx 0; } .divider-line { width: 1rpx; height: 62rpx; background: #ddd; } </style>