Files
frontend-app/pages/active/group-detail/group-detail.vue
T

1136 lines
29 KiB
Vue
Raw Normal View History

2026-09-23 10:29:41 +08:00
<template>
<view class="group_detail_page">
<!-- 顶部紫色渐变背景与自定义导航栏 -->
<view class="top_nav_container" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="nav_bar">
<!-- 返回按钮 -->
<view class="nav_back_btn" @click="handleBack">
<up-image src="/static/common/left.png" width="16" height="16" bgColor="transparent" />
</view>
<!-- 导航标题与成功状态标识 -->
<view class="nav_title_wrap">
<view class="nav_status_icon" v-if="isSuccess || (isOngoing && isJoined)">
<up-image src="/pages/mine_package/static/order_status_2.png" width="38rpx" height="38rpx"
bgColor="transparent"></up-image>
</view>
<text class="nav_title_text">{{ navTitle }}</text>
</view>
<!-- 占位,保持标题居中 -->
<view class="nav_right_placeholder"></view>
</view>
</view>
<!-- 页面内容主体 (带有负边距向上融入紫色背景) -->
<view class="page_body" v-if="teamDetail">
<!-- 1. 商品卡片 -->
<view class="product_card" @click="jumpProductDetail">
<!-- 商品图片 -->
<view class="product_img_wrap">
<image class="product_img" :src="teamDetail.mainGraph" mode="aspectFill" />
</view>
<!-- 商品右侧信息 -->
<view class="product_info_wrap">
<view class="product_name">{{ teamDetail.goodsName }}</view>
<view class="group_size_badge" v-if="teamDetail.requiredNum">
<text>{{ teamDetail.requiredNum }}人成团</text>
</view>
<view class="product_price_row">
<view class="group_price_box">
<text class="group_price_label">拼团价</text>
<text class="group_price_symbol">¥</text>
<text class="group_price_val">{{ teamDetail.groupPrice }}</text>
</view>
<view class="original_price_box" v-if="teamDetail.salePrice">
<text class="original_price">¥{{ teamDetail.salePrice }}</text>
</view>
</view>
</view>
</view>
<!-- 2. 拼团状态与操作卡片 -->
<view class="status_card">
<!-- 状态A:拼团中 (还差X人成团 + 倒计时) -->
<template v-if="isOngoing">
<view class="status_header_row">
<text class="status_title_text">还差 </text>
<text class="status_num_highlight">{{ teamDetail.remainingNum != null ? teamDetail.remainingNum
: 1 }}</text>
<text class="status_title_text"> 人成团</text>
</view>
<view class="countdown_row">
<text class="countdown_text">拼团剩余时间 {{ countdownText }}</text>
</view>
</template>
<!-- 状态B:拼团成功 -->
<template v-else-if="isSuccess">
<view class="success_header_row">
<text class="success_title_text">已成功拼团</text>
</view>
</template>
<!-- 状态C:拼团失败/超时/取消 -->
<template v-else>
<view class="success_header_row">
<text class="failed_title_text">{{ failedDescText }}</text>
</view>
</template>
<!-- 成员头像坑位列表 (根据 requiredNum 控制坑位总数) -->
<view class="avatars_slot_row" :class="{ 'slots_compact': (teamDetail.requiredNum || 2) > 4 }">
<!-- 团长坑位 (第一位) -->
<view class="avatar_slot_item">
<image class="member_avatar leader_avatar" :src="leaderMember.avatar || defaultAvatar"
mode="aspectFill" />
<view class="leader_badge">
<text class="leader_badge_text">团长</text>
</view>
</view>
<!-- 其余坑位 (共 requiredNum - 1 个) -->
<view class="avatar_slot_item" v-for="(slot, sIdx) in otherSlots" :key="sIdx">
<!-- 已参团成员 -->
<image v-if="slot.joined" class="member_avatar" :src="slot.avatar || defaultAvatar"
mode="aspectFill" />
<!-- 空坑位 (待邀请),紫色浅底加号 -->
<view v-else class="empty_slot" @click="handleSlotClick">
<text class="plus_icon">+</text>
</view>
</view>
</view>
<!-- 操作按钮区域 (不同角色在不同状态下显示不同按钮) -->
<view class="action_buttons_wrap" v-if="hasActionButtons">
<!-- 场景 1:拼团中且当前用户已参团 (邀请好友参团 + 没人拼单?单独购买) -->
<template v-if="isOngoing && isJoined">
<!-- #ifdef MP-WEIXIN -->
<button class="btn_primary btn_reset" @tap="handleInviteShare" hover-class="none">
邀请好友参团
</button>
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<view class="btn_primary" @click="handleInviteShare">
邀请好友参团
</view>
<!-- #endif -->
<view class="btn_secondary" @click="handleBuyAlone">
单独购买
</view>
</template>
<!-- 场景 2:拼团中且当前用户未参团 (单按钮:参加这个团) -->
<template v-else-if="isOngoing && !isJoined">
<view class="btn_primary" @click="handleJoinGroup">
参加这个团
</view>
</template>
<!-- 场景 3:已参团,处于拼团成功或拼团失败状态 (单按钮:查看订单) -->
<template v-else-if="isJoined && (isSuccess || isFailed)">
<view class="btn_primary" @click="handleViewOrder">
查看订单
</view>
</template>
</view>
</view>
<!-- 3. 拼团玩法说明卡片 -->
<view class="rules_card">
<view class="rules_card_title">拼团玩法</view>
<!-- 3 步骤流程 -->
<view class="rules_steps_row">
<view class="step_item">
<image class="step_icon" src="https://static.tbmall.xin/static/new/group_buying_1.png"
mode="aspectFit" />
<text class="step_label">开团/参加</text>
</view>
<view class="step_item">
<image class="step_icon" src="https://static.tbmall.xin/static/new/group_buying_2.png"
mode="aspectFit" />
<text class="step_label">邀请好友参团</text>
</view>
<view class="step_item">
<image class="step_icon" src="https://static.tbmall.xin/static/new/group_buying_3.png"
mode="aspectFit" />
<text class="step_label">成团发货</text>
</view>
</view>
<!-- 购买须知说明 -->
<view class="rules_notice">
购买须知:付款后等待成团,成团后 1-3 天发货。未成团且不支持自动成团时全额退款。
</view>
</view>
</view>
<!-- 分享海报弹窗 -->
<SharePopup ref="share" v-if="shareOpen" :show="shareShow" @close="onShareClose" @wxShare="onWxShare"
@share="onShare" :isGroupBuy="true" :id="String(teamDetail?.goodsId || goodsId)"
:text="teamDetail?.goodsName ? teamDetail.goodsName : ''"
:tu="teamDetail?.mainGraph ? teamDetail.mainGraph : ''"
:price="teamDetail?.groupPrice ? String(teamDetail.groupPrice) : ''"
:groupPrice="teamDetail?.groupPrice ? String(teamDetail.groupPrice) : ''"
:requiredNum="teamDetail?.requiredNum || 2" :inviterName="inviterName" :inviterAvatar="inviterAvatar"
:sharePath="groupSharePath"></SharePopup>
<!-- 单独购买确认弹窗 -->
<up-modal :show="buyAloneModalShow" title="提示" content="单独购买将创建一笔新的普通订单,原拼团订单仍然保留。需要退出原团时,请在订单详情申请退款。"
:showCancelButton="true" cancelText="继续等团" cancelColor="#333333" confirmText="创建单买订单" confirmColor="#7F3BF5"
:closeOnClickOverlay="true" :borderRadius="16" @confirm="confirmBuyAlone" @cancel="cancelBuyAlone"
@close="cancelBuyAlone"></up-modal>
<qiaobao-assistant page-key="pages/active/group-detail/group-detail" title="拼团详情与邀请" />
</view>
</template>
<script>
import { getTeamDetail } from "@/api/product.js";
import SharePopup from "@/pages/active/components/share-popup.vue";
import { SHARE_URL, MINI_PROGRAM_TYPE } from "@/utils/config.js";
import { getStorageFun, USER_DATA } from "@/utils/auth.js";
export default {
name: "group-detail",
components: {
SharePopup,
},
data() {
return {
statusBarHeight: 20,
teamId: "",
orderId: "",
goodsId: "",
teamDetail: null,
remainingSeconds: 0,
countdownText: "00:00:00",
countdownTimer: null,
defaultAvatar: "https://static.tbmall.xin/static/mine-purse/vcoin_1.png",
shareShow: false,
shareOpen: false,
buyAloneModalShow: false,
};
},
computed: {
// 是否拼团中
isOngoing() {
if (!this.teamDetail) return true;
return this.teamDetail.status === 0 || this.teamDetail.statusCode === "ONGOING";
},
// 是否拼团成功
isSuccess() {
if (!this.teamDetail) return false;
return this.teamDetail.status === 1 || this.teamDetail.statusCode === "SUCCESS";
},
// 是否拼团失败
isFailed() {
if (!this.teamDetail) return false;
return this.teamDetail.status === 2 || this.teamDetail.statusCode === "CANCELLED" || this.teamDetail.statusCode === "TIMEOUT";
},
// 当前用户是否已参团
isJoined() {
return Boolean(this.teamDetail?.joined);
},
// 是否有操作按钮需要显示 (未参团且处于成功/失败状态时不显示任何按钮)
hasActionButtons() {
if (this.isOngoing) return true;
if (this.isJoined && (this.isSuccess || this.isFailed)) return true;
return false;
},
// 导航栏标题
navTitle() {
if (this.isSuccess) {
return "拼团成功!";
}
if (this.isFailed) {
return "拼团失败!";
}
return "邀请好友参与拼团";
},
// 拼团失败状态下的文字说明
failedDescText() {
if (!this.teamDetail) return "拼团已结束";
const code = this.teamDetail.statusCode;
const text = this.teamDetail.statusText || "";
if (code === "CANCELLED" || text.includes("取消")) {
return this.isJoined ? "拼单已取消,款项将原路退回" : "拼单已取消";
}
if (code === "TIMEOUT" || text.includes("超时") || this.teamDetail.status === 2) {
return "未在规定时间内集齐人数";
}
return this.teamDetail.statusText || "拼团已结束";
},
// 团长成员信息
leaderMember() {
const members = this.teamDetail?.members || [];
return members.find((m) => m.leader) || members[0] || {};
},
// 其余坑位列表 (长度为 requiredNum - 1)
otherSlots() {
const requiredNum = Number(this.teamDetail?.requiredNum || 2);
const totalOther = Math.max(0, requiredNum - 1);
const members = this.teamDetail?.members || [];
const otherMembers = members.filter((m) => !m.leader);
const slots = [];
for (let i = 0; i < totalOther; i++) {
if (i < otherMembers.length) {
slots.push({
joined: true,
avatar: otherMembers[i].avatar,
nickname: otherMembers[i].nickname || `团员${i + 1}`,
});
} else {
slots.push({
joined: false,
});
}
}
return slots;
},
groupSharePath() {
const targetGoodsId = this.teamDetail?.goodsId || this.goodsId;
let path = `pages/other_package/productInfo/productInfo?id=${targetGoodsId}&activedType=groupBuy&activityId=1`;
if (this.teamId || this.teamDetail?.id) {
path += `&teamId=${this.teamId || this.teamDetail?.id}`;
}
return path;
},
inviterName() {
const userData = getStorageFun(USER_DATA) || {};
return (
this.teamDetail?.inviterName ||
this.leaderMember?.nickname ||
this.teamDetail?.leaderName ||
userData?.name ||
userData?.nickName ||
"Haonan Mu"
);
},
inviterAvatar() {
const userData = getStorageFun(USER_DATA) || {};
return (
this.teamDetail?.inviterAvatar ||
this.leaderMember?.avatar ||
this.teamDetail?.leaderAvatar ||
userData?.avatar ||
userData?.avatarUrl ||
"https://static.tbmall.xin/static/new/default_avatar.png"
);
},
},
onLoad(options) {
try {
const sys = uni.getSystemInfoSync();
if (sys && sys.statusBarHeight) {
this.statusBarHeight = sys.statusBarHeight;
}
} catch (e) {
console.error("获取系统信息失败:", e);
}
// #ifdef MP-WEIXIN
uni.showShareMenu({
withShareTicket: true,
menus: ["shareAppMessage", "shareTimeline"],
});
if (options && options.q) {
try {
const qrUrl = decodeURIComponent(options.q);
const queryIndex = qrUrl.indexOf("?");
if (queryIndex !== -1) {
const queryString = qrUrl.slice(queryIndex + 1);
const pairs = queryString.split("&");
pairs.forEach((pair) => {
if (!pair) return;
const [k, v] = pair.split("=");
if (k) {
options[decodeURIComponent(k)] = v ? decodeURIComponent(v) : "";
}
});
}
} catch (e) {
console.error("解析二维码参数 options.q 失败:", e);
}
}
// 如果从朋友圈等分享渠道直达此页面且携带商品与拼团参数,重定向至对应拼团商品详情
if (options?.activedType === "groupBuy" && options?.id) {
uni.redirectTo({
url: `/pages/other_package/productInfo/productInfo?id=${options.id}&activedType=${options.activedType}&activityId=${options.activityId || 1}`,
});
return;
}
// #endif
if (options?.teamId) {
this.teamId = options.teamId;
this.fetchTeamDetail();
}
},
onUnload() {
this.stopCountdown();
},
// 微信小程序原生分享给好友
onShareAppMessage() {
const targetGoodsId = this.teamDetail?.goodsId || this.goodsId;
const goodsName = this.teamDetail?.goodsName || "好物";
const remaining = this.teamDetail?.remainingNum != null ? this.teamDetail.remainingNum : 1;
let path = `/pages/other_package/productInfo/productInfo?id=${targetGoodsId}&activedType=groupBuy&activityId=1`;
if (this.teamId || this.teamDetail?.id) {
path += `&teamId=${this.teamId || this.teamDetail?.id}`;
}
return {
title: `【还差${remaining}人】快来和我一起拼团!${goodsName}`,
path: path,
imageUrl: this.teamDetail?.mainGraph,
};
},
// 微信小程序原生分享到朋友圈
onShareTimeline() {
const targetGoodsId = this.teamDetail?.goodsId || this.goodsId;
const remaining = this.teamDetail?.remainingNum != null ? this.teamDetail.remainingNum : 1;
return {
title: `【仅剩${remaining}个名额】¥${this.teamDetail?.groupPrice || ''} 拼团抢购!`,
query: `id=${targetGoodsId}&activedType=groupBuy&activityId=1`,
imageUrl: this.teamDetail?.mainGraph,
};
},
methods: {
// 请求拼团详情
async fetchTeamDetail() {
try {
const res = await getTeamDetail({ teamId: this.teamId, type: 5 });
if (res && res.bizcode === 100 && res.data) {
this.teamDetail = res.data;
if (res.data.goodsId) {
this.goodsId = res.data.goodsId;
}
if (res.data.myOrderId) {
this.orderId = res.data.myOrderId;
}
// 计算倒计时剩余秒数
if (res.data.remainingSeconds != null && res.data.remainingSeconds > 0) {
this.remainingSeconds = Number(res.data.remainingSeconds);
} else if (res.data.expireTime) {
const diff = Math.floor((Number(res.data.expireTime) - Date.now()) / 1000);
this.remainingSeconds = diff > 0 ? diff : 0;
} else {
this.remainingSeconds = 0;
}
if (this.isOngoing && this.remainingSeconds > 0) {
this.startCountdown();
} else {
this.countdownText = "00:00:00";
}
}
} catch (e) {
console.error("获取拼团详情失败:", e);
}
},
// 返回上一页
handleBack() {
const pages = getCurrentPages();
if (pages && pages.length > 1) {
uni.navigateBack();
} else {
uni.switchTab({
url: "/pages/home/home",
});
}
},
// 倒计时处理
startCountdown() {
this.stopCountdown();
this.updateCountdownText();
this.countdownTimer = setInterval(() => {
if (this.remainingSeconds > 0) {
this.remainingSeconds--;
this.updateCountdownText();
} else {
this.countdownText = "00:00:00";
this.stopCountdown();
// 倒计时结束后重新拉取拼团状态
this.fetchTeamDetail();
}
}, 1000);
},
stopCountdown() {
if (this.countdownTimer) {
clearInterval(this.countdownTimer);
this.countdownTimer = null;
}
},
updateCountdownText() {
const total = this.remainingSeconds;
const hh = String(Math.floor(total / 3600)).padStart(2, "0");
const mm = String(Math.floor((total % 3600) / 60)).padStart(2, "0");
const ss = String(total % 60).padStart(2, "0");
this.countdownText = `${hh}:${mm}:${ss}`;
},
// 点击空坑位:提示邀请
handleSlotClick() {
if (this.isJoined) {
this.handleInviteShare();
} else {
this.handleJoinGroup();
}
},
// 跳转商品详情
jumpProductDetail() {
const id = this.teamDetail?.goodsId || this.goodsId;
if (id) {
uni.navigateTo({
url: `/pages/other_package/productInfo/productInfo?id=${id}`,
});
}
},
// 邀请好友参团:打开分享弹窗
handleInviteShare() {
this.shareOpen = true;
this.shareShow = true;
},
// 关闭分享弹窗
onShareClose() {
this.shareShow = false;
setTimeout(() => {
this.shareOpen = false;
}, 300);
},
// 微信小程序分享回调
onWxShare(index) {
console.log("微信小程序分享", index);
if (index === 0) {
// 微信好友:通过 button open-type="share" 触发,延时关闭弹窗确保微信分享面板顺畅弹出
setTimeout(() => {
this.onShareClose();
}, 150);
} else if (index === 1) {
// 分享到朋友圈
// #ifdef MP-WEIXIN
uni.showShareMenu({
withShareTicket: true,
menus: ["shareTimeline"],
success: () => {
uni.showModal({
title: "提示",
content: "已为您开启朋友圈分享功能,请点击右上角 [...] 选择【分享到朋友圈】",
showCancel: false,
});
},
fail: () => {
uni.showModal({
title: "提示",
content: "请点击右上角 [...] 分享到朋友圈",
showCancel: false,
});
},
});
// #endif
this.onShareClose();
}
},
// App / H5 分享回调
onShare(index) {
const targetGoodsId = this.teamDetail?.goodsId || this.goodsId;
let targetPath = `/pages/other_package/productInfo/productInfo?id=${targetGoodsId}&activedType=groupBuy&activityId=1`;
if (this.teamId || this.teamDetail?.id) {
targetPath += `&teamId=${this.teamId || this.teamDetail?.id}`;
}
const targetUrl = `${SHARE_URL}/#${targetPath}`;
const goodsName = this.teamDetail?.goodsName || "";
const price = this.teamDetail?.groupPrice || "";
const remaining = this.teamDetail?.remainingNum != null ? this.teamDetail.remainingNum : 1;
const title = `【还差${remaining}人】快来和我一起拼团!${goodsName}`;
const summary = `【信任桥】邀请好友拼团!${goodsName} 拼团价 ¥${price}`;
if (index === 0) {
// 微信好友
// #ifdef APP-PLUS
uni.share({
provider: "weixin",
scene: "WXSceneSession",
type: 5,
imageUrl: this.teamDetail?.mainGraph,
title: title,
miniProgram: {
id: "gh_c31503d62920",
path: targetPath,
type: MINI_PROGRAM_TYPE,
webUrl: targetUrl,
},
success: () => {
this.onShareClose();
},
fail: (err) => {
console.error("App小程序分享失败,降级为普通网页分享:", err);
uni.share({
provider: "weixin",
scene: "WXSceneSession",
type: 0,
href: targetUrl,
title: title,
summary: summary,
imageUrl: this.teamDetail?.mainGraph,
complete: () => {
this.onShareClose();
},
});
},
});
// #endif
// #ifdef H5
uni.setClipboardData({
data: targetUrl,
success: () => {
uni.showToast({
title: "拼团链接已复制,请发送给微信好友",
icon: "none",
});
},
});
this.onShareClose();
// #endif
} else if (index === 1) {
// 微信朋友圈
// #ifdef APP-PLUS
uni.share({
provider: "weixin",
scene: "WXSceneTimeline",
type: 0,
href: targetUrl,
title: title,
summary: summary,
imageUrl: this.teamDetail?.mainGraph,
});
// #endif
// #ifdef H5
uni.setClipboardData({
data: targetUrl,
success: () => {
uni.showToast({
title: "拼团链接已复制,去分享到朋友圈吧",
icon: "none",
});
},
});
// #endif
this.onShareClose();
} else if (index === 2) {
let tmp = `【信任桥】消费共享数字化权益 ${SHARE_URL}/#/pages/other_package/productInfo/productInfo?id=${targetGoodsId}&activedType=groupBuy&activityId=1`;
// 复制链接
uni.setClipboardData({
data: tmp,
success: () => {
uni.showToast({
title: "拼团链接已复制,去发给好友吧",
icon: "none",
});
},
});
} else if (index === 3) {
// 保存图片
if (this.$refs.share && this.$refs.share.saveGroupCard) {
this.$refs.share.saveGroupCard();
}
} else {
this.onShareClose();
}
},
// 单独购买:弹出确认弹窗
handleBuyAlone() {
this.buyAloneModalShow = true;
},
// 确认创建单买订单
confirmBuyAlone() {
this.buyAloneModalShow = false;
const targetGoodsId = this.teamDetail?.goodsId || this.goodsId;
if (targetGoodsId) {
uni.navigateTo({
url: `/pages/other_package/productInfo/productInfo?id=${targetGoodsId}&activedType=groupBuy&activityId=1&fromBuyAlone=1`,
});
}
},
// 取消单买 (继续等团)
cancelBuyAlone() {
this.buyAloneModalShow = false;
},
// 参加这个团 (被邀请人点击)
handleJoinGroup() {
const id = this.teamDetail?.goodsId || this.goodsId;
if (id) {
uni.navigateTo({
url: `/pages/other_package/productInfo/productInfo?id=${id}&teamId=${this.teamId}&action=joinGroup`,
});
}
},
// 查看订单 (拼团成功后点击)
handleViewOrder() {
const targetOrderId = this.teamDetail?.myOrderId || this.orderId;
if (targetOrderId) {
uni.navigateTo({
url: `/pages/mine_package/mine_order_info/mine_order_info?orderId=${targetOrderId}`,
});
} else {
uni.navigateTo({
url: "/pages/mine_package/mine_order/mine_order?type=0",
});
}
},
},
};
</script>
<style lang="scss" scoped>
.group_detail_page {
min-height: 100vh;
background-color: #f6f7f9;
box-sizing: border-box;
padding-bottom: calc(40rpx + env(safe-area-inset-bottom));
}
// ========== 顶部导航栏与紫色渐变背景 ==========
.top_nav_container {
background: linear-gradient(180deg, #742af5 0%, #8a3bf8 100%);
padding-bottom: 80rpx;
.nav_bar {
height: 88rpx;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 28rpx;
.nav_back_btn {
width: 60rpx;
height: 60rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.2s;
&:active {
background: rgba(255, 255, 255, 0.35);
}
}
.nav_title_wrap {
display: flex;
align-items: center;
justify-content: center;
flex: 1;
height: 100%;
.nav_status_icon {
display: flex;
align-items: center;
justify-content: center;
margin-right: 12rpx;
flex-shrink: 0;
:deep(.u-image),
:deep(.u-transition) {
display: flex !important;
align-items: center !important;
justify-content: center !important;
}
}
.nav_title_text {
color: #ffffff;
font-size: 32rpx;
font-weight: bold;
letter-spacing: 1rpx;
line-height: 1;
display: flex;
align-items: center;
}
}
.nav_right_placeholder {
width: 60rpx;
height: 60rpx;
}
}
}
// ========== 内容主体卡片区 (负边距上移) ==========
.page_body {
margin-top: -50rpx;
padding: 0 24rpx;
display: flex;
flex-direction: column;
gap: 24rpx;
}
// ========== 1. 商品卡片 ==========
.product_card {
background: #ffffff;
border-radius: 24rpx;
padding: 24rpx;
display: flex;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.03);
.product_img_wrap {
width: 190rpx;
height: 190rpx;
border-radius: 16rpx;
position: relative;
overflow: hidden;
flex-shrink: 0;
background-color: #f7f7f7;
.product_img {
width: 100%;
height: 100%;
}
}
.product_info_wrap {
flex: 1;
min-width: 0;
margin-left: 20rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
.product_name {
font-size: 28rpx;
font-weight: bold;
color: #1a1a1a;
line-height: 40rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.group_size_badge {
align-self: flex-start;
background: #f2f3f5;
border-radius: 6rpx;
padding: 4rpx 14rpx;
font-size: 22rpx;
color: #666666;
margin-top: 8rpx;
}
.product_price_row {
display: flex;
align-items: baseline;
margin-top: 10rpx;
.group_price_box {
display: flex;
align-items: baseline;
color: #742af5;
.group_price_label {
font-size: 24rpx;
font-weight: bold;
margin-right: 6rpx;
}
.group_price_symbol {
font-size: 24rpx;
font-weight: bold;
}
.group_price_val {
font-size: 38rpx;
font-weight: bold;
margin-left: 2rpx;
}
}
.original_price_box {
margin-left: 14rpx;
.original_price {
font-size: 24rpx;
color: #999999;
text-decoration: line-through;
}
}
}
}
}
// ========== 2. 拼团状态与操作卡片 ==========
.status_card {
background: #ffffff;
border-radius: 24rpx;
padding: 40rpx 28rpx 36rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.03);
display: flex;
flex-direction: column;
align-items: center;
.status_header_row {
display: flex;
align-items: baseline;
justify-content: center;
.status_title_text {
font-size: 34rpx;
font-weight: bold;
color: #1a1a1a;
}
.status_num_highlight {
font-size: 40rpx;
font-weight: 800;
color: #742af5;
margin: 0 8rpx;
}
}
.countdown_row {
margin-top: 10rpx;
.countdown_text {
font-size: 24rpx;
color: #666666;
}
}
.success_header_row {
padding: 6rpx 0 10rpx;
.success_title_text {
font-size: 36rpx;
font-weight: bold;
color: #1a1a1a;
letter-spacing: 1rpx;
}
.failed_title_text {
font-size: 32rpx;
font-weight: bold;
color: #e61d2b;
}
}
// 成员头像与坑位列表
.avatars_slot_row {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 28rpx;
margin: 36rpx 0 44rpx;
width: 100%;
&.slots_compact {
gap: 18rpx;
}
.avatar_slot_item {
position: relative;
width: 100rpx;
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
.member_avatar {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
background-color: #eeeeee;
display: block;
}
.leader_badge {
position: absolute;
bottom: -8rpx;
left: 50%;
transform: translateX(-50%);
background: #7934f6;
border-radius: 16rpx;
padding: 0 14rpx;
height: 32rpx;
min-width: 68rpx;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
white-space: nowrap;
.leader_badge_text {
color: #ffffff;
font-size: 20rpx;
font-weight: 500;
line-height: 1;
text-align: center;
}
}
// 空坑位加号
.empty_slot {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
background: #f0e8fe;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: transform 0.15s ease;
&:active {
transform: scale(0.95);
}
.plus_icon {
font-size: 42rpx;
color: #7934f6;
font-weight: 300;
line-height: 1;
}
}
}
}
// 按钮区域
.action_buttons_wrap {
width: 100%;
display: flex;
flex-direction: column;
gap: 20rpx;
.btn_primary {
width: 100%;
height: 88rpx;
background: linear-gradient(90deg, #8a3bf8 0%, #742af5 100%);
color: #ffffff;
font-size: 32rpx;
font-weight: bold;
border-radius: 44rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 20rpx rgba(116, 42, 245, 0.25);
border: none;
outline: none;
margin: 0;
padding: 0;
line-height: 88rpx;
transition: opacity 0.2s ease, transform 0.1s ease;
&::after {
border: none;
}
&:active {
opacity: 0.9;
transform: scale(0.99);
}
}
// 清除 button 默认样式(用于微信小程序 button 元素)
.btn_reset {
appearance: none;
-webkit-appearance: none;
background-color: transparent;
border-radius: 44rpx;
&::after {
border: none;
background: transparent;
}
}
.btn_secondary {
width: 100%;
height: 88rpx;
background: #f0e7fe;
color: #742af5;
font-size: 30rpx;
font-weight: bold;
border-radius: 44rpx;
display: flex;
align-items: center;
justify-content: center;
transition: opacity 0.2s ease;
&:active {
opacity: 0.85;
}
}
}
}
// ========== 3. 拼团玩法卡片 ==========
.rules_card {
background: #ffffff;
border-radius: 24rpx;
padding: 28rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.03);
.rules_card_title {
font-size: 28rpx;
font-weight: bold;
color: #1a1a1a;
margin-bottom: 24rpx;
}
.rules_steps_row {
display: flex;
align-items: flex-start;
justify-content: space-around;
padding: 10rpx 0;
.step_item {
display: flex;
flex-direction: column;
align-items: center;
width: 180rpx;
.step_icon {
width: 96rpx;
height: 96rpx;
}
.step_label {
font-size: 24rpx;
color: #333333;
margin-top: 14rpx;
font-weight: 500;
text-align: center;
}
}
}
.rules_notice {
font-size: 22rpx;
color: #999999;
line-height: 36rpx;
margin-top: 20rpx;
padding-top: 16rpx;
border-top: 1rpx solid #f6f6f6;
}
}
</style>