Files
frontend-app/pages/active/group-detail/group-detail.vue
T
2026-09-23 10:29:41 +08:00

1136 lines
29 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>