baimacms/pages/special-sale/details.vue

693 lines
16 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="brand-detail-container">
<!-- 自定义沉浸式头部导航 -->
<view class="custom-header" :class="{ 'header-scrolled': scrollY > 50 }">
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
<view class="nav-bar">
<view class="nav-left" @click="goBack">
<text class="back-arrow">&lt;</text>
</view>
<view class="nav-title" v-if="scrollY > 50">{{ brandInfo.fq_brand_name || '品牌详情' }}</view>
<view class="nav-title" v-else></view>
<view class="nav-right"></view>
</view>
</view>
<!-- 页面滚动主视图区 -->
<scroll-view scroll-y class="main-scroll-view" :show-scrollbar="false" @scroll="onScroll" @scrolltolower="loadMoreItems">
<!-- 顶部品牌英雄传记大幕区 -->
<view class="hero-biography-section">
<!-- 底层唯美梦幻光影背景 -->
<image class="biography-bg" :src="heroBgImage" mode="aspectFill"></image>
<view class="biography-overlay"></view>
<!-- 品牌身份核心图腾层 -->
<view class="biography-core" :style="{ paddingTop: (statusBarHeight + 44) + 'px' }">
<view class="logo-wrapper">
<image class="brand-logo-img" :src="brandInfo.brand_logo || brandInfo.inside_logo" mode="aspectFit"></image>
</view>
<view class="brand-title-box">
<text class="b-name">{{ brandInfo.fq_brand_name || brandInfo.tb_brand_name }}</text>
<view class="b-fans-capsule" v-if="brandInfo.fans">
<text class="heart-icon">❤</text>
<text>{{ formattedFans }} 粉丝关注</text>
</view>
</view>
<!-- 品牌背书长简介展示 -->
<view class="brand-intro-text" v-if="brandInfo.introduce">{{ brandInfo.introduce }}</view>
</view>
</view>
<!-- 浮动式品牌卖点与话题推荐墙 (高级拟态玻璃卡片) -->
<view class="compile-card-wrapper" v-if="compileLines.length > 0 || recommendTags.length > 0">
<view class="glass-compile-card">
<view class="card-tag-title" v-if="compileLines.length > 0">✨ 品牌深度精编卖点</view>
<view class="compile-line-item" v-for="(line, lIdx) in compileLines" :key="lIdx">
<text class="line-dot">▪</text>
<text class="line-text">{{ line }}</text>
</view>
<!-- 推荐话题列表 -->
<view class="recommend-tags-box" v-if="recommendTags.length > 0">
<text class="r-tag" v-for="(tag, tIdx) in recommendTags" :key="tIdx">{{ tag }}</text>
</view>
</view>
</view>
<!-- 栏目分隔条下辖爆款单品集市 -->
<view class="matrix-header-bar">
<view class="m-line"></view>
<view class="m-title">
<text class="m-icon">🛍</text>
<text>品牌在售货盘 · 官方授权正品直发</text>
</view>
<view class="m-line"></view>
</view>
<!-- 下半部双列瀑布流单品矩阵 -->
<view class="items-grid-section">
<view class="grid-card-item" v-for="(goods, gIdx) in itemList" :key="gIdx" @click="goToDetail(goods.id)">
<!-- 商品正方形预览图 -->
<view class="img-preview-box">
<view class="badge-label" v-if="goods.label && goods.label.length > 0">{{ goods.label[0] }}</view>
<view class="badge-label" v-else-if="goods.discount">省{{ goods.discount }}元</view>
<image class="goods-pic" :src="goods.itempic" mode="aspectFill"></image>
<view class="sold-count-bar" v-if="goods.itemsale">热抢 {{ formatSale(goods.itemsale) }} 件</view>
</view>
<!-- 下层交易信息枢纽 -->
<view class="goods-meta-info">
<view class="g-title">{{ goods.itemshorttitle || goods.itemtitle }}</view>
<view class="price-hub">
<view class="current-price">
<text class="rmb">¥</text>
<text class="num">{{ goods.itemendprice }}</text>
</view>
<text class="old-price">¥{{ goods.itemprice }}</text>
</view>
<!-- 抵扣券胶囊组件 -->
<view class="coupon-capsule" v-if="goods.couponmoney > 0">
<text class="cap-tag">券</text>
<text class="cap-val">{{ goods.couponmoney }}元</text>
</view>
</view>
</view>
</view>
<!-- 触底无限加载状态条 -->
<view class="loading-status-bar">
<text v-if="loading">火速为您加载后续精选货品中...</text>
<text v-else-if="finished">-- 品牌旗下所有特惠好货已全数呈献 --</text>
<text v-else>上拉或滑动浏览更多单品</text>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
statusBarHeight: 44,
scrollY: 0,
brandId: 0,
brandInfo: {},
itemList: [],
page: 1,
loading: false,
finished: false,
// 预设高定静态莫兰迪光影壁纸库,用于海报衬底自愈
defaultBanners: [
'https://images.unsplash.com/photo-1556228720-195a672e8a03?w=800&q=80',
'https://images.unsplash.com/photo-1590080875515-8a3a8dc5735e?w=800&q=80',
'https://images.unsplash.com/photo-1585771724684-38269d6639fd?w=800&q=80',
'https://images.unsplash.com/photo-1607082348824-0a96f2a4b9da?w=800&q=80'
]
}
},
computed: {
heroBgImage() {
// 优先采用配置中的合成图或随机自愈壁纸
if (this.brandInfo.composeimage) {
return this.brandInfo.composeimage.replace('http://', 'https://');
}
const idx = Number(this.brandId) || 1;
return this.defaultBanners[idx % this.defaultBanners.length];
},
formattedFans() {
const f = this.brandInfo.fans;
if (!f) return '10万+';
if (f >= 10000) {
return (f / 10000).toFixed(1) + '万';
}
return f;
},
compileLines() {
const comp = this.brandInfo.brand_compile || '';
if (!comp) return [];
// 根据 \n 拆分,过滤掉空行,并去掉首位可能带有的星号及箭头
return comp.split('\n')
.map(s => s.trim())
.filter(s => s.length > 0)
.map(s => s.replace(/^[★☆▪•]/, '').trim());
},
recommendTags() {
const rec = this.brandInfo.brand_recommend;
if (Array.isArray(rec)) return rec;
if (typeof rec === 'string' && rec.length > 0) {
try {
return JSON.parse(rec);
} catch (e) {
return rec.split(' ').filter(s => s.length > 0);
}
}
return [];
}
},
onLoad(options) {
const sysInfo = uni.getSystemInfoSync();
this.statusBarHeight = sysInfo.statusBarHeight || 44;
this.brandId = options.id || options.brand_id || 1292;
console.log('品牌详情专页加载传入目标ID:', this.brandId);
this.fetchBrandDetailData();
},
methods: {
goBack() {
const pages = getCurrentPages();
if (pages && pages.length > 1) {
uni.navigateBack({ delta: 1 });
} else {
uni.reLaunch({ url: '/pages/special-sale/choicen' });
}
},
goToDetail(id) {
uni.navigateTo({
url: `/pages/detail/detail?id=${id}`
});
},
onScroll(e) {
this.scrollY = e.detail.scrollTop;
},
formatSale(val) {
if (val >= 10000) {
return (val / 10000).toFixed(1) + '万';
}
return val;
},
loadMoreItems() {
if (this.loading || this.finished) return;
this.page += 1;
console.log('品牌单品列表触发触底翻页,发起页码:', this.page);
this.fetchBrandDetailData(true);
},
fetchBrandDetailData(isLoadMore = false) {
if (this.loading) return;
this.loading = true;
if (!isLoadMore) {
uni.showLoading({ title: '构建专场中...', mask: true });
}
uni.request({
url: `https://api.cmspro.haodanku.com/brandItem/detail?page=${this.page}&page_size=20&sort=0&brand_id=${this.brandId}&cid=YsWZ21tx`,
success: (res) => {
if (res.data && res.data.code === 200 && res.data.data) {
// 挂载核心品牌自画像
if (res.data.data.brand_info) {
const info = res.data.data.brand_info;
if (info.brand_logo) info.brand_logo = info.brand_logo.replace('http://', 'https://');
if (info.inside_logo) info.inside_logo = info.inside_logo.replace('http://', 'https://');
this.brandInfo = info;
}
// 挂载分页商品方阵
if (res.data.data.items && Array.isArray(res.data.data.items.list)) {
const list = res.data.data.items.list.map(goods => {
let pic = goods.itempic ? goods.itempic.replace('http://', 'https://') : '';
return {
id: goods.id,
itemtitle: goods.itemtitle,
itemshorttitle: goods.itemshorttitle,
itempic: pic,
itemprice: goods.itemprice,
itemendprice: goods.itemendprice,
itemsale: goods.itemsale,
discount: goods.discount,
couponmoney: parseFloat(goods.couponmoney || 0),
label: Array.isArray(goods.label) ? goods.label : []
};
});
if (isLoadMore) {
this.itemList = [...this.itemList, ...list];
} else {
this.itemList = list;
}
const pagination = res.data.data.items.pagination;
if (pagination && this.page >= pagination.page_count) {
this.finished = true;
} else if (list.length < 20) {
this.finished = true;
}
} else {
if (isLoadMore) this.finished = true;
}
} else {
uni.showToast({ title: '加载专区数据失败', icon: 'none' });
}
},
fail: (err) => {
console.log('拉取品牌专页接口错误', err);
if (isLoadMore && this.page > 1) this.page -= 1;
},
complete: () => {
this.loading = false;
if (!isLoadMore) uni.hideLoading();
}
});
}
}
}
</script>
<style scoped>
.brand-detail-container {
width: 100%;
height: 100vh;
background-color: #f5f6f8;
display: flex;
flex-direction: column;
}
/* 顶部回退沉浸式导航栏 */
.custom-header {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
background: transparent;
}
.header-scrolled {
background: rgba(255, 255, 255, 0.98);
backdrop-filter: blur(20rpx);
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.nav-bar {
height: 44px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 30rpx;
}
.nav-left {
width: 80rpx;
height: 100%;
display: flex;
align-items: center;
}
.back-arrow {
font-size: 38rpx;
color: #ffffff;
font-weight: 300;
text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.4);
}
.header-scrolled .back-arrow {
color: #333333;
text-shadow: none;
}
.nav-title {
font-size: 32rpx;
font-weight: bold;
color: #333333;
opacity: 0;
transition: opacity 0.2s;
}
.header-scrolled .nav-title {
opacity: 1;
}
.nav-right {
width: 80rpx;
}
/* 滚动主体区 */
.main-scroll-view {
flex: 1;
width: 100%;
overflow-y: auto;
}
/* 品牌英雄大幕传记层 */
.hero-biography-section {
position: relative;
width: 100%;
min-height: 480rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
padding-bottom: 40rpx;
}
.biography-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
.biography-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(to bottom, rgba(0,0,0,0.15) 0%, rgba(138,43,226,0.35) 50%, rgba(20,20,20,0.85) 100%);
}
.biography-core {
position: relative;
z-index: 2;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
padding: 0 40rpx;
box-sizing: border-box;
}
.logo-wrapper {
width: 140rpx;
height: 140rpx;
background: #ffffff;
border-radius: 50%;
padding: 12rpx;
box-shadow: 0 6rpx 20rpx rgba(0,0,0,0.25);
border: 4rpx solid rgba(255,255,255,0.8);
margin-bottom: 16rpx;
}
.brand-logo-img {
width: 100%;
height: 100%;
border-radius: 50%;
}
.brand-title-box {
display: flex;
flex-direction: column;
align-items: center;
}
.b-name {
font-size: 40rpx;
font-weight: 800;
color: #ffffff;
letter-spacing: 2rpx;
text-shadow: 0 4rpx 8rpx rgba(0,0,0,0.4);
}
.b-fans-capsule {
margin-top: 10rpx;
background: linear-gradient(to right, rgba(255,65,108,0.85), rgba(255,75,43,0.85));
padding: 4rpx 20rpx;
border-radius: 20rpx;
display: flex;
align-items: center;
backdrop-filter: blur(8rpx);
}
.heart-icon {
color: #ffffff;
font-size: 22rpx;
margin-right: 8rpx;
}
.b-fans-capsule text {
color: #ffffff;
font-size: 22rpx;
font-weight: bold;
}
.brand-intro-text {
margin-top: 20rpx;
font-size: 24rpx;
color: rgba(255,255,255,0.85);
line-height: 1.5;
text-align: center;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.5);
}
/* 拟态玻璃精编卖点卡片层 */
.compile-card-wrapper {
padding: 0 30rpx;
margin-top: -24rpx;
position: relative;
z-index: 5;
}
.glass-compile-card {
background: rgba(255, 255, 255, 0.95);
border-radius: 24rpx;
padding: 30rpx;
box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.06);
border: 1rpx solid rgba(255,255,255,0.8);
display: flex;
flex-direction: column;
}
.card-tag-title {
font-size: 26rpx;
font-weight: bold;
color: #8a2be2;
margin-bottom: 16rpx;
}
.compile-line-item {
display: flex;
align-items: baseline;
margin-bottom: 10rpx;
}
.line-dot {
color: #ff416c;
font-size: 24rpx;
margin-right: 12rpx;
}
.line-text {
font-size: 26rpx;
color: #444444;
line-height: 1.45;
font-weight: 500;
}
.recommend-tags-box {
display: flex;
flex-wrap: wrap;
margin-top: 16rpx;
padding-top: 16rpx;
border-top: 1rpx dashed #eeeeee;
}
.r-tag {
font-size: 20rpx;
color: #8a2be2;
background-color: #f3e5f5;
padding: 4rpx 14rpx;
border-radius: 10rpx;
margin-right: 12rpx;
margin-bottom: 10rpx;
font-weight: 600;
}
/* 下方单品方阵分隔区 */
.matrix-header-bar {
display: flex;
align-items: center;
justify-content: center;
padding: 40rpx 30rpx 24rpx;
}
.m-line {
width: 60rpx;
height: 2rpx;
background: linear-gradient(to right, transparent, #cccccc);
}
.m-line:last-child {
background: linear-gradient(to left, transparent, #cccccc);
}
.m-title {
font-size: 28rpx;
font-weight: bold;
color: #333333;
padding: 0 20rpx;
display: flex;
align-items: center;
}
.m-icon {
margin-right: 10rpx;
font-size: 32rpx;
}
/* 双列商品瀑布网格 */
.items-grid-section {
display: flex;
flex-wrap: wrap;
padding: 0 30rpx;
justify-content: space-between;
}
.grid-card-item {
width: 48.5%;
background: #ffffff;
border-radius: 20rpx;
overflow: hidden;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.03);
display: flex;
flex-direction: column;
}
.img-preview-box {
width: 100%;
aspect-ratio: 1 / 1;
position: relative;
background: #f9f9f9;
}
.goods-pic {
width: 100%;
height: 100%;
}
.badge-label {
position: absolute;
top: 0;
left: 0;
background: linear-gradient(135deg, #8a2be2 0%, #ff416c 100%);
color: #ffffff;
font-size: 18rpx;
padding: 4rpx 12rpx;
border-bottom-right-radius: 16rpx;
font-weight: bold;
z-index: 2;
}
.sold-count-bar {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: rgba(0,0,0,0.5);
color: #ffffff;
font-size: 20rpx;
text-align: center;
padding: 4rpx 0;
backdrop-filter: blur(4rpx);
}
.goods-meta-info {
padding: 16rpx;
display: flex;
flex-direction: column;
flex: 1;
}
.g-title {
font-size: 26rpx;
font-weight: bold;
color: #333333;
line-height: 1.35;
height: 70rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
margin-bottom: 12rpx;
}
.price-hub {
display: flex;
align-items: baseline;
margin-top: auto;
}
.current-price {
color: #ff416c;
font-weight: bold;
}
.rmb {
font-size: 20rpx;
}
.num {
font-size: 34rpx;
}
.old-price {
font-size: 20rpx;
color: #bbbbbb;
text-decoration: line-through;
margin-left: 8rpx;
}
.coupon-capsule {
display: flex;
align-items: center;
border: 1rpx solid #ff416c;
border-radius: 8rpx;
overflow: hidden;
width: fit-content;
margin-top: 10rpx;
}
.cap-tag {
background: #ff416c;
color: #ffffff;
font-size: 18rpx;
padding: 0 8rpx;
font-weight: bold;
}
.cap-val {
color: #ff416c;
font-size: 18rpx;
padding: 0 10rpx;
font-weight: bold;
}
.loading-status-bar {
text-align: center;
font-size: 22rpx;
color: #aaaaaa;
padding: 30rpx 0 60rpx;
}
</style>