You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

549 lines
14 KiB

<template>
<view v-if="!isLoading && detail && goods" class="container" :style="appThemeStyle">
<!-- 背景区块 -->
<view class="bg-layer"></view>
<!-- 商品信息 -->
<view class="goods-info" @click="onTargetGoods()">
<view class="goods-image">
<view v-if="detail.active_type != ActiveTypeEnum.NORMAL.value" class="label">
<text>{{ ActiveTypeEnum[detail.active_type].name2 }}</text>
</view>
<image class="image" :src="goods.goods_image"></image>
</view>
<view class="goods-detail">
<view class="goods-name">
<text class="twoline-hide">{{ goods.goods_name }}</text>
</view>
<view class="goods-price">
<text class="f-26 col-m">¥</text>
<text class="m-price">{{ goods.groupon_price }}</text>
<text class="line-price">¥{{ goods.original_price }}</text>
</view>
<view class="goods-tag">
<text class="tag-item">{{ detail.people }}人团</text>
<text v-if="goods.diff_price != '0.00'" class="tag-item">拼团省{{ goods.diff_price }}元</text>
</view>
</view>
</view>
<!-- 拼团成员 -->
<view class="main">
<!-- 拼团状态 (成功、失败) -->
<view v-if="detail.status == TaskStatusEnum.FAIL.value" class="main_status main_status__fail">
<text class="status-icon iconfont icon-shibai"></text>
<text>超过有效时间,拼团失败</text>
</view>
<view v-if="detail.status == TaskStatusEnum.SUCCESS.value" class="main_status main_status__success">
<text class="status-icon iconfont icon-success"></text>
<text>拼团已成功</text>
</view>
<!-- 参团用户 -->
<view class="main-user">
<view v-for="(item, index) in detail.users" :key="item.id" class="user-item">
<avatar-image :url="item.userInfo.avatar_url" :width="100" />
<view v-if="item.is_leader" class="user-role"><text class="role-name">团长</text></view>
</view>
<!-- 虚位以待 -->
<view v-for="(val, idx) in detail.people - detail.joined_people" :key="idx" class="user-item user-item__wait">
<text class="iconfont icon-wenhao"></text>
</view>
</view>
<!-- 拼单状态:拼团中 -->
<view v-if="detail.status == TaskStatusEnum.NORMAL.value" class="main_tiem">
<text>还差</text>
<text class="main_timer_color">{{ detail.people - detail.joined_people }}</text>
<text>个名额,</text>
<!-- 倒计时 -->
<count-down :date="detail.end_time" separator="colon" theme="custom" customBgColor="#FE5246" />
<text>后结束</text>
</view>
<!-- 操作按钮 -->
<block v-if="detail.status == TaskStatusEnum.NORMAL.value">
<view v-if="!detail.is_join" class="button" @click="onShowSkuPopup()">立即参团</view>
<!-- 分享给朋友 -->
<button v-else open-type="share" class="button btn-normal" @click="handleShareBtn()">
<view class="btn-item btn-item__main"><text>立即分享</text></view>
</button>
</block>
<view v-else class="button" @click="onTargetGoods()">去开团</view>
</view>
<!-- 拼团须知 -->
<view class="notice" @click="handleShowRules()">
<text class="f-30">拼团须知</text>
<text class="t-brief">{{ setting.ruleBrief }}</text>
<text class="icon-arrow"></text>
</view>
<!-- 商品SKU弹窗 -->
<SkuPopup v-model="showSkuPopup" :skuMode="skuMode" :goods="goods" :buyMode="1" :taskId="detail.task_id" :stepPeople="detail.people" />
<!-- 拼团规则弹窗 -->
<u-modal v-model="showRules" title="拼团规则">
<scroll-view style="height: 610rpx; touch-action: none;" :scroll-y="true">
<view class="pops-content">
<text>{{ setting.ruleDetail }}</text>
</view>
</scroll-view>
</u-modal>
<!-- 商品推荐 -->
<recommended />
<addShuiyin />
</view>
</template>
<script>
import WxofficialMixin from '@/core/mixins/wxofficial'
import { getCurrentPage, buildUrL } from '@/core/app'
import AvatarImage from '@/components/avatar-image'
import CountDown from '@/components/countdown'
import Recommended from '@/components/recommended'
import SkuPopup from '../goods/components/SkuPopup'
import { ActiveTypeEnum, ActiveStatusEnum, TaskStatusEnum } from '@/common/enum/groupon'
import * as TaskApi from '@/api/groupon/task'
import StoreModel from '@/common/model/Store'
import GrouponSettingModel from '@/common/model/groupon/Setting'
export default {
components: {
AvatarImage,
SkuPopup,
CountDown,
Recommended
},
mixins: [WxofficialMixin],
data() {
return {
// 正在加载
isLoading: true,
// 枚举类
ActiveTypeEnum,
ActiveStatusEnum,
TaskStatusEnum,
// 显示拼团规则
showRules: false,
// 显示/隐藏SKU弹窗
showSkuPopup: false,
// 按钮模式 1:都显示 2:只显示购物车 3:只显示立即购买
skuMode: 3,
// 当前拼单ID
taskId: null,
// 拼单详情
detail: null,
// 拼团商品
goods: null,
// 拼团设置
setting: {}
}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad({ taskId }) {
// 记录拼单ID
this.taskId = taskId
// 获取拼团设置
this.getSetting()
// 获取拼单详情
this.getTaskDetail()
},
methods: {
// 获取拼团设置
getSetting() {
GrouponSettingModel.data().then(setting => (this.setting = setting))
},
// 获取拼单详情
getTaskDetail() {
const { taskId } = this
this.isLoading = true
TaskApi.detail(taskId)
.then(result => {
this.detail = result.data.detail
this.goods = result.data.goods
// 设置微信公众号链接分享卡片内容
this.setWxofficialShareData()
})
.finally(() => (this.isLoading = false))
},
// 跳转到拼团商品详情
onTargetGoods() {
const { goods } = this
this.$navTo('pages/groupon/goods/index', { grouponGoodsId: goods.groupon_goods_id })
},
// 点击分享按钮
handleShareBtn() {
// #ifndef MP
this.handleCopyLink()
// #endif
},
// 复制当前页面链接
handleCopyLink() {
const app = this
app.getShareUrl().then(shareUrl => {
// 复制到剪贴板
uni.setClipboardData({
data: shareUrl,
success: () => app.$toast('复制链接成功,快去发送给朋友吧'),
fail: ({ errMsg }) => app.$toast('复制失败 ' + errMsg)
})
})
},
// 获取分享链接 (H5外链)
getShareUrl() {
const { path, query } = getCurrentPage()
return new Promise((resolve, reject) => {
// 获取h5站点地址
StoreModel.h5Url().then(baseUrl => {
// 生成完整的分享链接
const shareUrl = buildUrL(baseUrl, path, query)
resolve(shareUrl)
})
})
},
// 显示拼团规则
handleShowRules() {
this.showRules = true
},
// 显示/隐藏SKU弹窗
onShowSkuPopup() {
this.showSkuPopup = !this.showSkuPopup
},
// 设置微信公众号链接分享卡片内容
setWxofficialShareData() {
const { detail, goods } = this
this.updateShareCardData({
title: goods.goods_name,
desc: goods.selling_point,
imgUrl: goods.goods_image
})
},
},
/**
* 分享当前页面
*/
onShareAppMessage() {
// 构建页面参数
const app = this
const params = app.$getShareUrlParams({ taskId: app.taskId })
return {
title: app.goods.goods_name,
path: `/pages/groupon/task/index?${params}`
}
},
/**
* 分享到朋友圈
*/
onShareTimeline() {
// 构建页面参数
const app = this
const params = app.$getShareUrlParams({ taskId: app.taskId })
return {
title: app.goods.goods_name,
path: `/pages/groupon/task/index?${params}`
}
},
}
</script>
<style lang="scss" scoped>
.container {
position: relative;
overflow: hidden;
}
// 箭头图标
.icon-arrow {
display: inline-block;
width: 0;
height: 0;
border-width: 10rpx;
border-style: solid;
border-color: transparent transparent transparent #ccc;
}
// 背景区块
.bg-layer {
position: absolute;
top: 0;
width: 100%;
z-index: 0;
height: 250rpx;
text-align: center;
line-height: 100rpx;
&::after {
width: 140%;
height: 250rpx;
position: absolute;
left: -20%;
top: 0;
z-index: -1;
content: '';
border-radius: 0 0 50% 50%;
background-image: linear-gradient(180deg, #ff5644, #fd7524);
}
}
// 商品信息
.goods-info {
position: relative;
margin: auto;
margin-top: 30rpx;
padding: 28rpx;
padding-bottom: 22rpx;
width: 92%;
background: #fff;
border-radius: 10rpx;
box-sizing: border-box;
box-shadow: 0px 5px 12px rgba(226, 226, 226, 0.62);
display: flex;
.goods-image {
position: relative;
margin-right: 30rpx;
.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: 240rpx;
height: 240rpx;
border-radius: 10rpx;
}
}
.goods-detail {
background: #fff;
.goods-name {
display: block;
font-size: 28rpx;
line-height: 1.5;
}
.goods-price {
margin: 20rpx 0;
color: #eb5841;
.m-price {
display: inline-block;
font-size: 40rpx;
}
.line-price {
display: inline-block;
margin: 10rpx;
font-size: 24rpx;
color: #8e8e8e;
text-decoration: line-through;
}
}
.goods-tag {
margin-bottom: -10rpx;
.tag-item {
display: inline-block;
padding: 4rpx 12rpx;
font-size: 24rpx;
line-height: 36rpx;
border-radius: 5rpx;
color: #fa3534;
background: #fef0f0;
margin-right: 10rpx;
margin-bottom: 10rpx;
box-sizing: border-box;
}
}
}
&:after {
display: block;
clear: both;
content: '';
visibility: hidden;
height: 0;
}
}
// 拼团成员
.main {
position: relative;
margin: auto;
margin-top: 30rpx;
padding: 50rpx 20rpx;
background: #fff;
box-sizing: border-box;
.main-user {
display: flex;
flex-wrap: wrap;
justify-content: center;
margin: 0 auto;
width: 600rpx;
margin-bottom: 30rpx;
.user-item {
width: 100rpx;
height: 100rpx;
margin: 0 25rpx 25rpx 0;
position: relative;
box-sizing: border-box;
&:nth-child(5n + 0) {
margin-right: 0;
}
.user-role {
width: 100%;
text-align: center;
height: 40rpx;
position: absolute;
left: 0;
bottom: -1rpx;
.role-name {
background: #eb5841;
border-radius: 15rpx;
display: inline-block;
line-height: 1.4;
font-size: 24rpx;
color: #fff;
width: 78rpx;
}
}
&.user-item__wait {
border-radius: 50%;
background: #f8f8f8;
border: 1rpx dashed #dbdbdb;
display: flex;
justify-content: center;
align-items: center;
text {
color: #dbdbdb;
font-size: 38rpx;
}
}
}
}
.button {
display: block;
margin-top: 40rpx;
width: 550rpx;
line-height: 84rpx;
font-size: 28rpx;
background-image: linear-gradient(90deg, #fe5246, #fb265a);
border: none;
box-shadow: 0px 3px 8px rgba(255, 8, 15, 0.25);
text-align: center;
margin: 0 auto;
color: #fff;
border-radius: 40rpx;
animation: btn_anim 0.9s linear infinite;
transform-origin: center;
}
}
// 按钮动画
@keyframes btn_anim {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
40% {
-webkit-transform: scale(1.05);
transform: scale(1.05);
}
}
/* 拼团状态 */
.main_status {
margin-bottom: 40rpx;
font-size: 35rpx;
text-align: center;
.status-icon {
margin-right: 15rpx;
}
}
.main_status__fail {
color: $main-bg;
}
.main_status__success {
color: #08b625;
}
/* 倒计时 */
.main_tiem {
margin-bottom: 50rpx;
font-size: 30rpx;
text-align: center;
display: flex;
justify-content: center;
.main_timer_color {
color: #fc8434;
margin: 0 6rpx;
}
}
// 拼团须知
.notice {
display: flex;
margin: auto;
margin-top: 30rpx;
padding: 35rpx 20rpx;
background: #fff;
border-radius: 10rpx;
box-sizing: border-box;
justify-content: space-between;
align-items: center;
.t-brief {
font-size: 26rpx;
color: #a6a6a6;
}
}
// 拼团规则 (弹窗)
.pops-content {
padding: 30rpx 48rpx;
font-size: 28rpx;
line-height: 44rpx;
text-align: left;
color: #606266;
min-height: 320rpx;
max-height: 640rpx;
box-sizing: border-box;
}
</style>