fix: 融合完成

This commit is contained in:
whitechiina 2026-06-03 15:40:51 +08:00
parent 50f01140c4
commit 93b91f12db
215 changed files with 15111 additions and 275 deletions

View File

@ -30,7 +30,7 @@ var tools = {
uni.setStorageSync('promotionUnlocked', true) uni.setStorageSync('promotionUnlocked', true)
return true return true
} }
uni.removeStorageSync('promotionUnlocked') uni.setStorageSync('promotionUnlocked', false)
return false return false
}, },
setPromotionBridgeSkip: function(path) { setPromotionBridgeSkip: function(path) {
@ -57,11 +57,7 @@ var tools = {
return false return false
}, },
clearLoginStorage: function() { clearLoginStorage: function() {
const promotionUnlocked = this.getPromotionUnlocked()
uni.clearStorageSync() uni.clearStorageSync()
if (promotionUnlocked) {
this.setPromotionUnlocked(true)
}
}, },
//图片地址拼接 //图片地址拼接
oss: function(url) { oss: function(url) {

View File

@ -0,0 +1,21 @@
<template>
<view class="bottom-nav-stub"></view>
</template>
<script>
export default {
name: 'BottomNav',
props: {
activeTab: {
type: Number,
default: 0
}
}
}
</script>
<style scoped>
.bottom-nav-stub {
display: none;
}
</style>

View File

@ -0,0 +1,313 @@
<template>
<view class="classify-container">
<view class="classify-header">
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
<view class="header-content">
<view class="search-bar" @click="goToSearch">
<text class="search-icon">🔍</text>
<text class="search-placeholder">输入关键词或粘贴商品标题</text>
</view>
</view>
</view>
<view class="main-body" :style="{ paddingTop: navBarHeight + 'px' }">
<!-- 左侧一级菜单 -->
<scroll-view scroll-y class="side-bar" :show-scrollbar="false">
<view class="side-item" :class="{ 'active': activeIndex === index }"
v-for="(item, index) in categoryData" :key="index" @click="switchMainCategory(index)">
<text class="side-txt">{{ item.name }}</text>
</view>
</scroll-view>
<!-- 右侧内容区 -->
<scroll-view scroll-y class="content-panel" :show-scrollbar="false">
<view class="category-group" v-for="(second, sIdx) in currentSubCategories" :key="sIdx">
<view class="group-title">
<text class="title-line"></text>
<text class="title-txt">{{ second.cate_name }}</text>
<text class="title-line"></text>
</view>
<view class="sub-grid">
<view class="sub-item" v-for="(three, tIdx) in second.three" :key="tIdx" @click="goToDetail(three)">
<view class="sub-img-wrap">
<image class="sub-img" :src="three.img_url" mode="aspectFit"></image>
</view>
<text class="sub-name">{{ three.cate_name }}</text>
</view>
</view>
</view>
<view class="footer-placeholder"></view>
</scroll-view>
</view>
<!-- 底部导航 -->
<bottom-nav :activeTab="navActiveIndex"></bottom-nav>
</view>
</template>
<script>
import BottomNav from '@/components/bottom-nav/bottom-nav.vue';
import http from '@/request/request.js';
export default {
components: {
BottomNav
},
data() {
return {
statusBarHeight: 44,
activeIndex: 0,
categoryData: [],
navActiveIndex: -1 // -1Tab
}
},
computed: {
navBarHeight() {
return this.statusBarHeight + 44;
},
currentSubCategories() {
if (this.categoryData.length > 0 && this.categoryData[this.activeIndex]) {
return this.categoryData[this.activeIndex].second || [];
}
return [];
}
},
onLoad() {
this.initializePage();
},
mounted() {
if (this.__taokeInitialized) return;
this.__taokeInitialized = true;
this.initializePage();
},
methods: {
initializePage() {
if (this.__pageInitialized) return;
this.__pageInitialized = true;
const sysInfo = uni.getSystemInfoSync();
this.statusBarHeight = sysInfo.statusBarHeight || 44;
this.getSuperCategory();
},
getSuperCategory() {
http.get('https://api.cmspro.haodanku.com/index/superCategory?cid=YsWZ21tx', undefined, {
header: {
'accept': 'application/json, text/plain, */*',
'accept-language': 'zh-CN,zh;q=0.9'
}
}).then(res => {
this.categoryData = res.data;
//
this.matchNavActive();
});
},
matchNavActive() {
//
http.get('https://api.cmspro.haodanku.com/bottomBar/lists?cid=YsWZ21tx').then(res => {
if (res.data && res.data.bottom_bar) {
const allowedTitles = ['首页', '榜单', '分类'];
const list = res.data.bottom_bar
.filter(item => allowedTitles.includes(item.title))
.sort((a, b) => b.sort - a.sort);
const idx = list.findIndex(item => item.title === '分类');
if (idx !== -1) {
this.navActiveIndex = idx;
}
}
});
},
switchMainCategory(index) {
this.activeIndex = index;
},
goToSearch() {
uni.navigateTo({
url: '/pages/search/search'
});
},
goToDetail(three) {
const name = encodeURIComponent(three.cate_name.trim());
const catId = this.categoryData[this.activeIndex].cat_id;
const secondCat = three.second_category;
uni.navigateTo({
url: `/pages/category/category_detail?cate_name=${name}&id=${catId}&second_category=${secondCat}`
});
}
}
}
</script>
<style scoped>
.classify-container {
width: 100%;
height: 100vh;
background-color: #ffffff;
display: flex;
flex-direction: column;
}
/* 头部 */
.classify-header {
position: fixed;
top: 0;
left: 0;
right: 0;
background: #ffffff;
z-index: 100;
border-bottom: 1rpx solid #f8f8f8;
}
.status-bar {
width: 100%;
}
.header-content {
height: 88rpx;
display: flex;
align-items: center;
padding: 0 30rpx;
}
.search-bar {
flex: 1;
height: 72rpx;
background-color: #f5f5f5;
border-radius: 36rpx;
display: flex;
align-items: center;
padding: 0 30rpx;
}
.search-icon {
font-size: 28rpx;
color: #999;
margin-right: 12rpx;
}
.search-placeholder {
font-size: 26rpx;
color: #999;
}
/* 主体布局 */
.main-body {
flex: 1;
display: flex;
overflow: hidden;
}
/* 左侧菜单 */
.side-bar {
width: 180rpx;
height: 100%;
background-color: #f7f8fa;
flex-shrink: 0;
}
.side-item {
width: 100%;
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.side-txt {
font-size: 28rpx;
color: #666;
}
.side-item.active {
background-color: #ffffff;
}
.side-item.active .side-txt {
color: #333;
font-weight: bold;
}
.side-item.active::before {
content: "";
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 32rpx;
background: linear-gradient(180deg, #ff715a, #ff416c);
border-radius: 0 4rpx 4rpx 0;
}
/* 右侧内容 */
.content-panel {
flex: 1;
height: 100%;
padding: 0 20rpx;
background-color: #ffffff;
}
.category-group {
padding-top: 30rpx;
}
.group-title {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 30rpx;
}
.title-line {
width: 30rpx;
height: 2rpx;
background-color: #eee;
}
.title-txt {
font-size: 26rpx;
color: #333;
font-weight: bold;
margin: 0 20rpx;
}
.sub-grid {
display: flex;
flex-wrap: wrap;
}
.sub-item {
width: 33.33%;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 40rpx;
}
.sub-img-wrap {
width: 120rpx;
height: 120rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 12rpx;
}
.sub-img {
width: 100%;
height: 100%;
}
.sub-name {
font-size: 24rpx;
color: #666;
text-align: center;
width: 90%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.footer-placeholder {
height: 120rpx; /* 为底部导航预留空间 */
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,753 @@
<template>
<view class="rank-container">
<!-- 沉浸式渐变头部 -->
<view class="rank-header">
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
<!-- 榜单类型切换 -->
<view class="rank-main-tabs">
<view class="main-tab" :class="{ 'active': rankType === 1 }" @click="switchRankType(1)">
<view class="tab-content-wrap">
<image class="wheat-icon wheat-left" src="/static/wheat_icon.png" v-if="rankType === 1"></image>
<text class="tab-main-txt">实时热销榜</text>
<image class="wheat-icon wheat-right" src="/static/wheat_icon.png" v-if="rankType === 1"></image>
</view>
</view>
<view class="main-tab" :class="{ 'active': rankType === 2 }" @click="switchRankType(2)">
<view class="tab-content-wrap">
<text class="tab-main-txt">全天热销榜</text>
</view>
</view>
</view>
<!-- 分类滑动导航 -->
<scroll-view scroll-x class="cate-nav" :show-scrollbar="false">
<view class="cate-item" :class="{ 'active': currentCateId === item.id }"
v-for="(item, index) in categoryList" :key="index" @click="switchCategory(item.id)">
<text class="cate-txt">{{ item.name }}</text>
</view>
</scroll-view>
</view>
<scroll-view scroll-y class="rank-content" @scrolltolower="loadMore">
<!-- 顶部背景延伸区 (仅作为背景块不包裹卡片) -->
<view class="rank-bg-header" :style="{ height: rankHeaderHeight + 'px' }"></view>
<!-- Top 1-3 领奖台布局 (参考 shop-sy2 样式) -->
<view class="top-three-wrap" v-if="goodsList.length >= 3">
<!-- Top 2 (左侧) -->
<view class="top-card top-card-side" @click="goToDetail(goodsList[1].id)">
<view class="top-badge-wrap badge-2">
<text class="top-badge-num">TOP 2</text>
</view>
<view class="top-img-box">
<image class="top-img" :src="goodsList[1].image" mode="aspectFill"></image>
<view class="top-sales-bar">已抢{{ goodsList[1].sales }}</view>
</view>
<view class="top-info-box">
<text class="top-name">{{ goodsList[1].title }}</text>
<view class="top-price-box">
<text class="price-label">券后</text>
<text class="price-val">{{ goodsList[1].finalPrice }}</text>
</view>
<view class="coupon-wrap" v-if="goodsList[1].couponValue">
<text class="coupon-label"></text>
<text class="coupon-value">{{ goodsList[1].couponValue }}</text>
</view>
</view>
</view>
<!-- Top 1 (中间) -->
<view class="top-card top-card-center" @click="goToDetail(goodsList[0].id)">
<image class="crown-icon" src="https://img.bc.haodanku.com/cms_web/1698115530" mode="widthFix"></image>
<view class="top-badge-wrap badge-1">
<text class="top-badge-num">TOP 1</text>
</view>
<view class="top-img-box">
<image class="top-img" :src="goodsList[0].image" mode="aspectFill"></image>
<view class="top-sales-bar">已抢{{ goodsList[0].sales }}</view>
</view>
<view class="top-info-box">
<text class="top-name">{{ goodsList[0].title }}</text>
<view class="top-price-box">
<text class="price-label">券后</text>
<text class="price-val">{{ goodsList[0].finalPrice }}</text>
</view>
<view class="coupon-wrap" v-if="goodsList[0].couponValue">
<text class="coupon-label"></text>
<text class="coupon-value">{{ goodsList[0].couponValue }}</text>
</view>
</view>
</view>
<!-- Top 3 (右侧) -->
<view class="top-card top-card-side" @click="goToDetail(goodsList[2].id)">
<view class="top-badge-wrap badge-3">
<text class="top-badge-num">TOP 3</text>
</view>
<view class="top-img-box">
<image class="top-img" :src="goodsList[2].image" mode="aspectFill"></image>
<view class="top-sales-bar">已抢{{ goodsList[2].sales }}</view>
</view>
<view class="top-info-box">
<text class="top-name">{{ goodsList[2].title }}</text>
<view class="top-price-box">
<text class="price-label">券后</text>
<text class="price-val">{{ goodsList[2].finalPrice }}</text>
</view>
<view class="coupon-wrap" v-if="goodsList[2].couponValue">
<text class="coupon-label"></text>
<text class="coupon-value">{{ goodsList[2].couponValue }}</text>
</view>
</view>
</view>
</view>
<!-- Top 4+ 横向列表 -->
<view class="rest-list">
<view class="rest-item" v-for="(goods, idx) in goodsList.slice(3)" :key="idx" @click="goToDetail(goods.id)">
<view class="rest-left">
<view class="rest-badge-wrap">
<image class="rest-badge-img" src="/static/rank_badge.png" mode="widthFix"></image>
<text class="rest-badge-num">{{ idx + 4 }}</text>
</view>
<image class="rest-img" :src="goods.image" mode="aspectFill"></image>
</view>
<view class="rest-right">
<view class="rest-title-row">
<image src="https://img-haodanku-com.cdn.fudaiapp.com/FlyOSTvjC3LjrkUoJ0NPxx1qnGz4" class="p-icon"></image>
<text class="rest-name">{{ goods.title }}</text>
</view>
<view class="rest-price-row">
<text class="rest-price-tip">券后¥</text>
<text class="rest-price-val">{{ goods.finalPrice }}</text>
<text class="rest-price-old">¥{{ goods.originalPrice }}</text>
</view>
<view class="coupon-wrap" v-if="goods.couponValue">
<text class="coupon-label"></text>
<text class="coupon-value">{{ goods.couponValue }}</text>
</view>
<view class="rest-buy-bar">
<view class="btn-prev">
<text class="rest-buy-txt">近2小时已抢 <text class="rest-buy-num">{{ goods.itemsale2 }}</text> </text>
</view>
<view class="btn-next">马上抢</view>
</view>
</view>
</view>
</view>
<view class="loading-status" v-if="loading">火速加载中...</view>
<view class="footer-placeholder"></view>
</scroll-view>
<!-- 底部导航 -->
<bottom-nav :activeTab="1"></bottom-nav>
</view>
</template>
<script>
import BottomNav from '@/components/bottom-nav/bottom-nav.vue';
import http from '@/request/request.js';
export default {
components: {
BottomNav
},
data() {
return {
statusBarHeight: 44,
rankType: 1,
currentCateId: 0,
categoryList: [
{ id: 0, name: '全部' },
{ id: 10, name: '居家' },
{ id: 11, name: '美食' },
{ id: 8, name: '儿童' },
{ id: 3, name: '女装' },
{ id: 4, name: '美妆' }
],
goodsList: [],
loading: false,
page: 1
}
},
computed: {
rankHeaderHeight() {
return this.statusBarHeight + 90;
}
},
onLoad() {
this.initializePage();
},
mounted() {
if (this.__taokeInitialized) return;
this.__taokeInitialized = true;
this.initializePage();
},
methods: {
initializePage() {
if (this.__pageInitialized) return;
this.__pageInitialized = true;
const sysInfo = uni.getSystemInfoSync();
this.statusBarHeight = sysInfo.statusBarHeight || 44;
this.getRankList(true);
},
switchRankType(type) {
if (this.rankType === type) return;
this.rankType = type;
this.getRankList(true);
},
switchCategory(id) {
if (this.currentCateId === id) return;
this.currentCateId = id;
this.getRankList(true);
},
getRankList(refresh = false) {
if (refresh) {
this.page = 1;
this.goodsList = [];
}
if (this.loading) return;
this.loading = true;
http.get('https://api.cmspro.haodanku.com/ranking/lists', {
type: this.rankType,
category_id: this.currentCateId,
page: this.page,
page_size: 60,
cid: 'YsWZ21tx'
})
.then(res => {
if (res.data && res.data.list_item && res.data.list_item.list) {
const list = res.data.list_item.list.map(item => {
//
let title = item.itemshorttitle || item.itemtitle;
if (title.length > 18) {
title = title.substring(0, 18) + '...';
}
// (/)
let salesCount = this.rankType === 1 ? (item.todaysale || item.itemsale2 || 0) : item.itemsale;
let salesStr = salesCount >= 10000 ? (salesCount / 10000).toFixed(1) + '万' : salesCount;
// 2 (itemsale2)
let itemSale2 = item.itemsale2 || 0;
let itemSale2Str = itemSale2 >= 10000 ? (itemSale2 / 10000).toFixed(1) + '万' : itemSale2;
return {
id: item.id,
image: item.itempic,
title: title,
finalPrice: item.itemendprice,
originalPrice: item.itemprice,
couponValue: item.couponmoney || 0,
sales: salesStr,
itemsale2: itemSale2Str,
shopName: item.shopname,
labels: item.label || []
};
});
this.goodsList = [...this.goodsList, ...list];
}
})
.finally(() => {
this.loading = false;
});
},
loadMore() {
// 60
},
goToDetail(id) {
uni.navigateTo({
url: `/pages/detail/detail?id=${id}`
});
}
}
}
</script>
<style scoped>
.rank-container {
width: 100%;
height: 100vh;
background-color: #f5f6f8;
display: flex;
flex-direction: column;
}
/* ========== 头部区域 ========== */
.rank-header {
position: fixed;
top: 0;
left: 0;
right: 0;
background-image: linear-gradient(90deg, rgba(255, 154, 12, 0.9), rgba(253, 36, 39, 0.9)), url("https://img.alicdn.com/bao/uploaded/O1CN015WwOJy1qPYhqS1DwG_!!6000000005488-0-yinhe.jpg_310x310");
background-size: cover;
background-position: center;
z-index: 200; /* 提升层级至最高,确保滑动时文字不被卡片遮挡 */
padding-bottom: 0;
}
.status-bar {
width: 100%;
}
.rank-main-tabs {
display: flex;
align-items: center;
justify-content: center;
height: 88rpx;
gap: 60rpx;
}
.main-tab {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
}
.tab-content-wrap {
display: flex;
align-items: center;
gap: 8rpx;
}
.tab-main-txt {
font-size: 30rpx;
color: rgba(255, 255, 255, 0.7);
transition: all 0.3s;
padding-bottom: 8rpx;
}
.main-tab.active .tab-main-txt {
color: #ffffff;
font-size: 34rpx;
font-weight: bold;
}
.main-tab.active::after {
content: "";
width: 40rpx;
height: 4rpx;
background: #ffffff;
border-radius: 2rpx;
margin-top: 4rpx; /* 紧贴文字下方 */
}
.wheat-icon {
width: 32rpx;
height: 44rpx;
}
.wheat-right {
transform: scaleX(-1);
}
/* 分类导航 */
.cate-nav {
white-space: nowrap;
padding: 10rpx 0 20rpx;
background: transparent;
}
.cate-item {
display: inline-block;
padding: 8rpx 32rpx;
position: relative;
}
.cate-txt {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.8);
}
.cate-item.active .cate-txt {
color: #ffffff;
font-weight: bold;
font-size: 30rpx;
}
.cate-item.active::after {
content: "";
position: absolute;
bottom: 4rpx;
left: 50%;
transform: translateX(-50%);
width: 48rpx;
height: 6rpx;
background: #ffffff;
border-radius: 3rpx;
}
/* ========== 滚动内容 ========== */
.rank-content {
flex: 1;
height: 100%;
background-color: #f5f6f8;
overflow: visible;
}
.rank-bg-header {
width: 100%;
background-image: linear-gradient(90deg, rgba(255, 154, 12, 0.9), rgba(253, 36, 39, 0.9)), url("https://img.alicdn.com/bao/uploaded/O1CN015WwOJy1qPYhqS1DwG_!!6000000005488-0-yinhe.jpg_310x310");
background-size: cover;
background-position: bottom;
}
/* ========== Top 1-3 领奖台 ========== */
.top-three-wrap {
display: flex;
align-items: flex-end;
justify-content: space-between;
padding: 60rpx 20rpx 20rpx;
margin-top: -60rpx; /* 调小负边距,防止遮挡导航文字 */
position: relative;
z-index: 110;
box-sizing: border-box;
width: 100%;
}
.top-card {
display: flex;
flex-direction: column;
align-items: center;
background: #ffffff;
border-radius: 20rpx;
overflow: visible;
position: relative;
box-shadow: 0 16rpx 40rpx rgba(0,0,0,0.15);
}
.top-card-side {
width: 31%;
height: 410rpx; /* 侧边基准高度 */
z-index: 10;
}
.top-card-center {
width: 34%;
height: 470rpx; /* 中间拔高 */
z-index: 15;
border: 2rpx solid #ffd700;
}
.crown-icon {
position: absolute;
top: -50rpx;
left: 50%;
transform: translateX(-50%);
width: 76rpx;
z-index: 100;
}
/* 荣誉徽章体系 (参考 shop-sy2) */
.top-badge-wrap {
position: absolute;
top: 0;
left: 0;
padding: 4rpx 16rpx;
border-radius: 20rpx 0 20rpx 0;
z-index: 99;
display: flex;
align-items: center;
justify-content: center;
}
.badge-1 {
background: linear-gradient(135deg, #ff4b2b, #ff416c);
}
.badge-2 {
background: linear-gradient(135deg, #4facfe, #00f2fe);
}
.badge-3 {
background: linear-gradient(135deg, #f093fb, #f5576c);
}
.top-badge-num {
font-size: 20rpx;
font-weight: 900;
color: #ffffff;
font-style: italic;
}
.top-img-box {
width: 100%;
height: 210rpx;
overflow: visible;
position: relative;
background: #f5f5f5;
}
.top-card-center .top-img-box {
height: 270rpx;
}
.top-img {
width: 100%;
height: 100%;
border-radius: 16rpx 16rpx 0 0;
}
/* 胶囊式销量标签 */
.top-sales-bar {
position: absolute;
bottom: 0;
left: 50%;
transform: translate(-50%, 50%);
background: rgba(255, 75, 43, 0.9);
color: #ffffff;
font-size: 18rpx;
white-space: nowrap;
padding: 4rpx 16rpx;
border-radius: 40rpx;
font-weight: bold;
z-index: 100;
box-shadow: 0 4rpx 12rpx rgba(255, 75, 43, 0.3);
}
.top-info-box {
padding: 24rpx 16rpx 16rpx; /* 增加左右内边距 */
width: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
background: #ffffff;
border-radius: 0 0 20rpx 20rpx;
text-align: left; /* 切换为左对齐 */
}
.top-name {
font-size: 24rpx;
color: #333;
font-weight: bold;
margin-bottom: 8rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.top-price-box {
display: flex;
align-items: baseline;
justify-content: flex-start; /* 切换为左对齐 */
color: #ff4b2b;
}
.price-label {
font-size: 18rpx;
font-weight: bold;
}
.price-val {
font-size: 34rpx;
font-weight: 900;
}
.coupon-wrap {
display: inline-flex;
align-items: center;
justify-content: center;
margin: 8rpx 0 0; /* 移除 auto改为左对齐 */
border: 1rpx solid #ff4b2b;
border-radius: 4rpx;
overflow: hidden;
background: #ffffff;
align-self: flex-start; /* 确保在 flex 容器中左对齐 */
}
.rest-right .coupon-wrap {
margin: 8rpx 0;
align-self: flex-start;
}
.coupon-label {
background: #ff4b2b;
color: #ffffff;
font-size: 18rpx;
padding: 0 8rpx;
height: 30rpx;
line-height: 30rpx;
font-weight: bold;
}
.coupon-value {
color: #ff4b2b;
font-size: 18rpx;
padding: 0 10rpx;
height: 30rpx;
line-height: 30rpx;
font-weight: bold;
}
/* ========== Top 4+ 列表 ========== */
.rest-list {
background: #ffffff;
margin: 0 16rpx;
border-radius: 16rpx;
overflow: hidden;
}
.rest-item {
display: flex;
padding: 24rpx;
border-bottom: 1rpx solid #f5f5f5;
}
.rest-left {
flex-shrink: 0;
width: 200rpx;
height: 200rpx;
border-radius: 12rpx;
overflow: visible;
position: relative;
background: #f5f5f5;
}
.rest-badge-wrap {
position: absolute;
top: -12rpx;
left: -4rpx;
width: 50rpx;
height: 50rpx;
z-index: 99;
display: flex;
align-items: center;
justify-content: center;
}
.rest-badge-img {
width: 50rpx;
position: absolute;
}
.rest-badge-num {
position: relative;
z-index: 11;
font-size: 22rpx;
font-weight: bold;
color: #ffffff;
margin-top: -4rpx;
}
.rest-img {
width: 100%;
height: 100%;
}
.rest-right {
flex: 1;
margin-left: 20rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
min-width: 0; /* 关键:防止 Flex 子项被内容撑开导致超伸 */
}
.rest-title-row {
display: flex;
align-items: center;
}
.p-icon {
width: 26rpx;
height: 26rpx;
margin-right: 8rpx;
flex-shrink: 0;
}
.rest-name {
font-size: 26rpx;
color: #333;
font-weight: bold;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
}
.rest-price-row {
display: flex;
align-items: baseline;
margin-top: 10rpx;
}
.rest-price-tip {
font-size: 22rpx;
color: #ff4b2b;
}
.rest-price-val {
font-size: 40rpx;
color: #ff4b2b;
font-weight: bold;
margin-right: 10rpx;
}
.rest-price-old {
font-size: 22rpx;
color: #bbb;
text-decoration: line-through;
}
.rest-buy-bar {
display: flex;
align-items: center;
background: url("https://web.cms.hykefu.cn/static/img/todayBg.png") no-repeat center;
background-size: 100% 100%;
border-radius: 40rpx;
margin-top: 10rpx;
overflow: hidden;
width: 100%;
height: 56rpx;
box-sizing: border-box; /* 确保 padding 不会增加总宽度 */
}
.btn-prev {
flex: 1;
display: flex;
align-items: center;
padding-left: 20rpx;
height: 100%;
}
.rest-buy-txt {
padding-left: 15rpx;
font-size: 20rpx;
color: #ff6534;
white-space: nowrap;
}
.rest-buy-num {
font-weight: bold;
color: #ff4b2b;
margin: 0 4rpx;
}
.btn-next {
width: 150rpx; /* 调整宽度以对齐图片中的按钮区域 */
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: transparent; /* 背景透明,直接使用底图效果 */
color: #ffffff !important;
font-size: 24rpx;
font-weight: bold;
flex-shrink: 0;
}
/* ========== 其他 ========== */
.loading-status {
text-align: center;
padding: 40rpx 0;
font-size: 24rpx;
color: #999;
}
.footer-placeholder {
height: 140rpx;
}
</style>

View File

@ -0,0 +1,13 @@
<template>
<classify-source></classify-source>
</template>
<script>
import ClassifySource from './source/classify-source.vue'
export default {
components: {
ClassifySource
}
}
</script>

View File

@ -0,0 +1,13 @@
<template>
<home-source></home-source>
</template>
<script>
import HomeSource from './source/home-source.vue'
export default {
components: {
HomeSource
}
}
</script>

View File

@ -0,0 +1,13 @@
<template>
<rank-source></rank-source>
</template>
<script>
import RankSource from './source/rank-source.vue'
export default {
components: {
RankSource
}
}
</script>

View File

@ -30,22 +30,19 @@ const promotionList = [
pagePath: '/pages/tabbar/index', pagePath: '/pages/tabbar/index',
iconPath: '/static/images/icon_sy.png', iconPath: '/static/images/icon_sy.png',
selectedIconPath: '/static/images/icon_syf.png', selectedIconPath: '/static/images/icon_syf.png',
text: '首页', text: '首页'
h5Url: 'https://point.agrimedia.cn/affiliate-activity/pages/index/index'
}, },
{ {
pagePath: '/pages/tabbar/shop', pagePath: '/pages/tabbar/shop',
iconPath: '/static/images/icon_gwc.png', iconPath: '/static/images/icon_gwc.png',
selectedIconPath: '/static/images/icon_gwcf.png', selectedIconPath: '/static/images/icon_gwcf.png',
text: '榜单', text: '榜单'
h5Url: 'https://point.agrimedia.cn/affiliate-activity/pages/rank/rank'
}, },
{ {
pagePath: '/pages/tabbar/sort', pagePath: '/pages/tabbar/sort',
iconPath: '/static/images/icon_fl.png', iconPath: '/static/images/icon_fl.png',
selectedIconPath: '/static/images/icon_flf.png', selectedIconPath: '/static/images/icon_flf.png',
text: '分类', text: '分类'
h5Url: 'https://point.agrimedia.cn/affiliate-activity/pages/classify/classify'
}, },
{ {
pagePath: '/pages/tabbar/me', pagePath: '/pages/tabbar/me',
@ -227,15 +224,6 @@ Component({
if (!item) { if (!item) {
return return
} }
if (!isPromotionUnlocked && item.h5Url) {
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
const from = currentPage && currentPage.route ? `/${currentPage.route}` : ''
wx.navigateTo({
url: `/pages/h5/bridge?url=${encodeURIComponent(item.h5Url)}&from=${encodeURIComponent(from)}`
})
return
}
setTabbarSelectedPath(item.pagePath) setTabbarSelectedPath(item.pagePath)
this.setData({ this.setData({
selected: selectedPath, selected: selectedPath,

31
main.js
View File

@ -9,14 +9,29 @@ const inter = require('common/interceptor.js')
import interceptor from '@/common/interceptor.js' import interceptor from '@/common/interceptor.js'
import common from '@/common/common.js' import common from '@/common/common.js'
Vue.prototype.$tools = tools ;//工具类 Vue.prototype.$tools = tools ;//工具类
Vue.prototype.$amapwx = amapwx;//高德地图类 Vue.prototype.$amapwx = amapwx;//高德地图类
// 混入代码 Vue.prototype.$estimateCoupon = function(tkmoney = 0, percentage = 0.3) {
Vue.mixin(mixin) const amount = Number(tkmoney || 0) * Number(percentage || 0)
Vue.mixin(inter) return amount.toFixed(2)
Vue.use(uView) }
Vue.prototype.$store = Vue.prototype.$store || {
state: {
isThirdParty: false
},
getters: {
currentUid: '',
relationId: '',
pid: '',
isThirdParty: false
}
}
// 混入代码
Vue.mixin(mixin)
Vue.mixin(inter)
Vue.use(uView)
// 工具类 // 工具类

106
pageOne/mes/member.vue Normal file
View File

@ -0,0 +1,106 @@
<template>
<view class="member-page">
<image class="member-bg" src="https://imgs.agrimedia.cn/jiuye-haibao.png" mode="aspectFit"></image>
<view class="page-overlay">
<view class="back-btn" :style="{ top: statusBarHeight + 12 + 'px' }" @click="$tools.goBack(1)">
<text class="back-arrow"></text>
</view>
<view class="action-wrap" :style="{ paddingBottom: safeBottom + 16 + 'px' }">
<view class="open-btn" @click="handleOpenMember">开通会员</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
statusBarHeight: 20,
safeBottom: 0
}
},
onLoad() {
const systemInfo = uni.getSystemInfoSync()
this.statusBarHeight = systemInfo.statusBarHeight || 20
const safeAreaInsets = systemInfo.safeAreaInsets || {}
this.safeBottom = safeAreaInsets.bottom || 0
},
methods: {
handleOpenMember() {
uni.showToast({
title: '支付正在对接中…',
icon: 'none'
})
}
}
}
</script>
<style scoped>
page {
background: #1c0d0d;
}
.member-page {
position: relative;
width: 100%;
min-height: 100vh;
overflow: hidden;
background: #f23f3e;
}
.member-bg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.page-overlay {
position: relative;
min-height: 100vh;
}
.back-btn {
position: fixed;
left: 24rpx;
width: 72rpx;
height: 72rpx;
border-radius: 36rpx;
background: #f23f3e;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
}
.back-arrow {
color: #ffffff;
font-size: 52rpx;
line-height: 1;
margin-top: -4rpx;
}
.action-wrap {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding-left: 32rpx;
padding-right: 32rpx;
}
.open-btn {
height: 96rpx;
border-radius: 48rpx;
background: linear-gradient(135deg, #f8e2b7 0%, #d8b06b 100%);
color: #6b2b10;
font-size: 32rpx;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 16rpx 32rpx rgba(0, 0, 0, 0.18);
}
</style>

View File

@ -40,6 +40,55 @@
"navigationBarTitleText": "", "navigationBarTitleText": "",
"navigationStyle": "default" "navigationStyle": "default"
} }
},
{
"path": "pages/detail/detail",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "商品详情"
}
},
{
"path": "pages/category/category",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "商品分类"
}
},
{
"path": "pages/category/category_detail",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "商品分类详情"
}
},
{
"path": "pages/search/search",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "搜索"
}
},
{
"path": "pages/special-sale/choicen",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "精选品牌"
}
},
{
"path": "pages/special-sale/details",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "品牌详情"
}
},
{
"path": "pages/save-money/save-money",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "省钱攻略"
}
} }
], ],
"subPackages": [{ "subPackages": [{
@ -157,18 +206,25 @@
"navigationBarBackgroundColor": "#fff" "navigationBarBackgroundColor": "#fff"
} }
}, },
{ {
"path": "mes/collection", "path": "mes/collection",
"style": { "style": {
"navigationBarTitleText": "我的收藏", "navigationBarTitleText": "我的收藏",
"navigationBarBackgroundColor": "#fff" "navigationBarBackgroundColor": "#fff"
} }
}, },
{ {
"path": "mes/service", "path": "mes/member",
"style": { "style": {
"navigationBarTitleText": "联系客服", "navigationBarTitleText": "",
"navigationBarBackgroundColor": "#F3C0C3" "navigationStyle": "custom"
}
},
{
"path": "mes/service",
"style": {
"navigationBarTitleText": "联系客服",
"navigationBarBackgroundColor": "#F3C0C3"
} }
}, },
{ {
@ -276,24 +332,24 @@
"color": "#666", "color": "#666",
"selectedColor": "#ee4237", "selectedColor": "#ee4237",
"backgroundColor": "#FFFFFF", "backgroundColor": "#FFFFFF",
"list": [{ "list": [{
"pagePath": "pages/tabbar/index", "pagePath": "pages/tabbar/index",
"iconPath": "/static/images/icon_sy.png", "iconPath": "/static/images/icon_sy.png",
"selectedIconPath": "/static/images/icon_syf.png", "selectedIconPath": "/static/images/icon_syf.png",
"text": "首页" "text": "首页"
}, { }, {
"pagePath": "pages/tabbar/sort", "pagePath": "pages/tabbar/shop",
"iconPath": "/static/images/icon_fl.png", "iconPath": "/static/images/icon_gwc.png",
"selectedIconPath": "/static/images/icon_flf.png", "selectedIconPath": "/static/images/icon_gwcf.png",
"text": "分类" "text": "榜单"
}, { }, {
"pagePath": "pages/tabbar/shop", "pagePath": "pages/tabbar/sort",
"iconPath": "/static/images/icon_gwc.png", "iconPath": "/static/images/icon_fl.png",
"selectedIconPath": "/static/images/icon_gwcf.png", "selectedIconPath": "/static/images/icon_flf.png",
"text": "购物车" "text": "分类"
}, { }, {
"pagePath": "pages/tabbar/me", "pagePath": "pages/tabbar/me",
"iconPath": "/static/images/icon_wd.png", "iconPath": "/static/images/icon_wd.png",
"selectedIconPath": "/static/images/icon_wdf.png", "selectedIconPath": "/static/images/icon_wdf.png",
"text": "我的" "text": "我的"
}] }]

671
pages/category/category.vue Normal file
View File

@ -0,0 +1,671 @@
<template>
<view class="category-container">
<!-- 头部搜索与导航 (1:1 还原首页样式) -->
<view class="header">
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
<view class="search-section">
<view class="search-bar-wrap" @click="goSearch">
<text class="search-icon"></text>
<text class="search-input" style="color: #999;">输入关键词或粘贴商品标题</text>
<view class="search-btn-red">搜索</view>
</view>
<image class="search-right-ad" src="https://img.bc.haodanku.com/cms_web/1651735687" mode="aspectFit" @click="goHome"></image>
</view>
<scroll-view scroll-x class="nav-scroll" :show-scrollbar="false">
<view class="nav-item" :class="{ 'active': currentCatId == item.cat_id }" v-for="(item, index) in navList" :key="index" @click="switchCategory(item)">
<text class="nav-text">{{ item.name }}</text>
<view class="nav-line" v-if="currentCatId == item.cat_id"></view>
</view>
</scroll-view>
</view>
<scroll-view scroll-y class="main-content" @scrolltolower="loadMore">
<!-- 占位符适配固定头部 -->
<view class="header-placeholder" :style="{ height: categoryHeaderHeight + 'px' }"></view>
<!-- 子分类金刚区 (支持翻页) -->
<view class="sub-grid-wrap" v-if="subCategories.length > 0">
<swiper class="sub-swiper" :duration="300" @change="onSubSwiperChange">
<swiper-item v-for="(group, gIdx) in groupedSubCategories" :key="gIdx">
<view class="sub-grid">
<view class="sub-item" v-for="(sub, idx) in group" :key="idx" @click="selectSub(sub)">
<image class="sub-icon" :src="sub.img_url" mode="aspectFit"></image>
<text class="sub-text">{{ sub.cate_name.trim() }}</text>
</view>
</view>
</swiper-item>
</swiper>
<!-- 进度条指示器 (仅在多页时显示) -->
<view class="swiper-dot-wrap" v-if="groupedSubCategories.length > 1">
<view class="swiper-dot-bar">
<view class="swiper-dot-active" :style="{ left: dotLeft + '%' }"></view>
</view>
</view>
</view>
<!-- 排序筛选栏 -->
<view class="filter-bar">
<view class="filter-item" :class="{ 'active': sortType === 1 }" @click="changeSort(1)">综合</view>
<view class="filter-item" :class="{ 'active': sortType === 2 }" @click="changeSort(2)">销量</view>
<view class="filter-item" :class="{ 'active': sortType === 3 }" @click="changeSort(3)">
券后价
<view class="price-arrows">
<text class="up" :class="{ 'hl': sortType === 3 && priceOrder === 'asc' }"></text>
<text class="down" :class="{ 'hl': sortType === 3 && priceOrder === 'desc' }"></text>
</view>
</view>
</view>
<!-- 商品列表 (同步 category_detail 的横向高保真风格) -->
<view class="goods-list">
<view class="goods-item" v-for="(goods, idx) in goodsList" :key="idx" @click="goToDetail(goods.id)">
<view class="g-img-left">
<image class="goods-img" :src="goods.image" mode="aspectFill"></image>
</view>
<view class="goods-info">
<view class="goods-title-row">
<image src="https://img-haodanku-com.cdn.fudaiapp.com/FlyOSTvjC3LjrkUoJ0NPxx1qnGz4" class="platform-icon"></image>
<text class="title-text">{{ goods.title }}</text>
</view>
<!-- 标签组 -->
<view class="labels-row" v-if="goods.labels && goods.labels.length > 0">
<text class="label-tag" v-for="(label, lIdx) in goods.labels.slice(0, 2)" :key="lIdx">{{ label }}</text>
</view>
<view class="goods-price-section">
<view class="price-main">
<text class="price-tip">{{ goods.couponValue > 0 ? '券后' : '抢购价' }}</text>
<text class="price-symbol"></text>
<text class="price-integer">{{ goods.finalPrice }}</text>
<view class="coupon-box" v-if="goods.couponValue > 0">
<text class="coupon-icon"></text>
<text class="coupon-txt">{{ goods.couponValue }}</text>
</view>
</view>
</view>
<view class="goods-bottom-info">
<text class="sales">已售{{ goods.sales }}</text>
<text class="split-line">|</text>
<text class="shop-name">店铺{{ goods.shopName }}</text>
</view>
</view>
</view>
</view>
<view class="loading-more" v-if="loading">加载中...</view>
<view class="loading-more" v-else-if="goodsList.length === 0">该分类暂无商品</view>
<view class="loading-more" v-else>-- 到底啦 --</view>
<view class="footer-placeholder"></view>
</scroll-view>
</view>
</template>
<script>
import http from '@/request/request.js';
export default {
data() {
return {
statusBarHeight: 44,
currentCatId: 0,
currentSonId: 0,
navList: [],
subCategories: [],
goodsList: [],
page: 1,
sortType: 1,
priceOrder: 'desc',
loading: false,
finished: false,
subCurrentIndex: 0
}
},
computed: {
categoryHeaderHeight() {
return this.statusBarHeight + 70;
},
groupedSubCategories() {
const groups = [];
for (let i = 0; i < this.subCategories.length; i += 10) {
groups.push(this.subCategories.slice(i, i + 10));
}
return groups;
},
dotLeft() {
if (this.groupedSubCategories.length <= 1) return 0;
const maxIndex = this.groupedSubCategories.length - 1;
return (this.subCurrentIndex / maxIndex) * 50; // 50%
}
},
onLoad(options) {
this.currentCatId = options.cat_id || 1;
const sysInfo = uni.getSystemInfoSync();
this.statusBarHeight = sysInfo.statusBarHeight || 44;
this.getCategoryTabs();
this.getProducts(true);
},
methods: {
goHome() {
uni.reLaunch({
url: '/pages/index/index'
});
},
goSearch() {
uni.navigateTo({
url: '/pages/search/search'
});
},
getCategoryTabs() {
http.get('https://api.cmspro.haodanku.com/index/superCategory?is_get_second=1&cid=YsWZ21tx').then(res => {
if (res.data) {
// navList
const categories = res.data.map(item => ({
name: item.name,
cat_id: item.cat_id,
second: item.second || []
}));
this.navList = [{ name: '首页', cat_id: 0 }, { name: '推荐', cat_id: -1 }, ...categories];
const currentCat = this.navList.find(c => c.cat_id == this.currentCatId);
if (currentCat && currentCat.second) {
this.subCategories = currentCat.second;
}
}
});
},
getProducts(refresh = false) {
if (refresh) {
this.page = 1;
this.finished = false;
this.goodsList = [];
}
if (this.loading || this.finished) return;
this.loading = true;
// allItemList (0:, 3:, 8:, 9:)
let sortParam = 0;
if (this.sortType === 2) {
sortParam = 3;
} else if (this.sortType === 3) {
sortParam = this.priceOrder === 'asc' ? 8 : 9;
}
http.get(`https://api.cmspro.haodanku.com/find/allItemList?category_id=${this.currentCatId}&page=${this.page}&sort=${sortParam}&page_size=20&cid=YsWZ21tx`).then(res => {
if (res.data && res.data.item_info) {
const list = res.data.item_info.map(item => ({
id: item.id,
image: item.itempic,
title: item.itemshorttitle && item.itemshorttitle.length > 17 ? item.itemshorttitle.substring(0, 17) + '...' : item.itemshorttitle,
finalPrice: item.itemendprice,
couponValue: item.couponmoney || 0,
tkmoney: item.tkmoney || 0,
sales: item.itemsale >= 10000 ? (item.itemsale / 10000).toFixed(1) + '万' : item.itemsale,
shopType: item.shoptype === 'B' ? '天猫' : '淘宝',
shopName: item.shopname,
labels: item.label || []
}));
if (list.length === 0) {
this.finished = true;
} else {
//
this.goodsList = [...this.goodsList, ...list];
this.page++;
//
if (list.length < 20) {
this.finished = true;
}
}
} else {
this.finished = true;
}
}).finally(() => {
this.loading = false;
});
},
switchCategory(item) {
if (item.cat_id <= 0) {
this.goHome();
return;
}
if (this.currentCatId == item.cat_id) return;
this.currentCatId = item.cat_id;
this.currentSonId = 0;
this.subCategories = item.second || [];
this.getProducts(true);
},
onSubSwiperChange(e) {
this.subCurrentIndex = e.detail.current;
},
selectSub(sub) {
const name = encodeURIComponent(sub.cate_name.trim());
const catId = this.currentCatId;
const secondCat = sub.second_category;
uni.navigateTo({
url: `/pages/category/category_detail?cate_name=${name}&id=${catId}&second_category=${secondCat}`
});
},
changeSort(type) {
if (type === 3 && this.sortType === 3) {
this.priceOrder = this.priceOrder === 'asc' ? 'desc' : 'asc';
} else {
this.sortType = type;
if (type === 3) this.priceOrder = 'desc';
}
this.getProducts(true);
},
loadMore() {
this.getProducts();
},
goToDetail(id) {
uni.navigateTo({
url: `/pages/detail/detail?id=${id}`
});
}
}
}
</script>
<style scoped>
.category-container {
width: 100%;
height: 100vh;
background-color: #f5f6f8;
display: flex;
flex-direction: column;
}
/* 头部区域 (与首页 1:1) */
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
background: #ffffff;
z-index: 100;
padding-bottom: 10rpx;
}
.status-bar {
width: 100%;
}
.search-section {
display: flex;
align-items: center;
padding: 20rpx 30rpx;
justify-content: space-between;
}
.search-bar-wrap {
flex: 1;
height: 72rpx;
background: #ffffff;
border: 2rpx solid #ff416c;
border-radius: 36rpx;
display: flex;
align-items: center;
padding-left: 30rpx;
padding-right: 4rpx;
position: relative;
}
.search-icon {
font-size: 30rpx;
color: #ff416c;
margin-right: 16rpx;
}
.search-input {
flex: 1;
font-size: 26rpx;
color: #333;
}
.search-btn-red {
width: 130rpx;
height: 64rpx;
background: linear-gradient(to right, #ff715a, #ff416c);
color: #ffffff;
font-size: 28rpx;
font-weight: bold;
border-radius: 32rpx;
display: flex;
align-items: center;
justify-content: center;
}
.search-right-ad {
width: 100rpx;
height: 80rpx;
margin-left: 20rpx;
}
.nav-scroll {
white-space: nowrap;
padding: 0 20rpx;
}
.nav-item {
display: inline-block;
padding: 10rpx 30rpx;
position: relative;
}
.nav-text {
font-size: 30rpx;
color: #333;
transition: all 0.3s;
}
.nav-item.active .nav-text {
color: #ff416c;
font-size: 34rpx;
font-weight: bold;
}
.nav-line {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 6rpx;
background-color: #ff416c;
border-radius: 6rpx;
}
.main-content {
flex: 1;
height: 100%;
}
.header-placeholder {
width: 100%;
}
/* 子分类金刚区 */
.sub-grid-wrap {
background: #ffffff;
margin: 20rpx;
border-radius: 16rpx;
padding: 20rpx 0;
}
.sub-swiper {
height: 300rpx; /* 适应两行 2x5 布局 */
}
.sub-grid {
display: flex;
flex-wrap: wrap;
padding: 0 10rpx;
}
.sub-item {
width: 20%;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 20rpx;
}
.sub-icon {
width: 80rpx;
height: 80rpx;
margin-bottom: 10rpx;
}
.sub-text {
font-size: 22rpx;
color: #333;
}
.swiper-dot-wrap {
display: flex;
justify-content: center;
margin-top: 10rpx;
}
.swiper-dot-bar {
width: 60rpx;
height: 4rpx;
background: #eeeeee;
border-radius: 2rpx;
position: relative;
overflow: hidden;
}
.swiper-dot-active {
position: absolute;
top: 0;
width: 30rpx;
height: 4rpx;
background: #ff416c;
border-radius: 2rpx;
transition: left 0.3s;
}
/* 筛选栏 */
.filter-bar {
display: flex;
background: #ffffff;
height: 88rpx;
align-items: center;
border-bottom: 1rpx solid #f1f1f1;
position: sticky;
top: 0;
z-index: 90;
}
.filter-item {
flex: 1;
text-align: center;
font-size: 28rpx;
color: #666;
display: flex;
align-items: center;
justify-content: center;
}
.filter-item.active {
color: #ff416c;
font-weight: bold;
}
.price-arrows {
display: flex;
flex-direction: column;
margin-left: 6rpx;
line-height: 1;
}
.price-arrows text {
font-size: 16rpx;
color: #ccc;
}
.price-arrows text.hl {
color: #ff416c;
}
/* 商品列表 */
.goods-list {
padding: 0;
background: #ffffff;
}
.goods-item {
display: flex;
padding: 24rpx;
border-bottom: 1rpx solid #f8f8f8;
background: #ffffff;
}
.g-img-left {
flex-shrink: 0;
width: 240rpx;
height: 240rpx;
border-radius: 12rpx;
overflow: hidden;
background: #f0f0f0;
}
.goods-img {
width: 100%;
height: 100%;
}
.goods-info {
flex: 1;
margin-left: 20rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 4rpx 0;
}
.goods-title-row {
display: flex;
align-items: center;
line-height: 1.4;
}
.platform-icon {
width: 26rpx;
height: 26rpx;
margin-right: 8rpx;
flex-shrink: 0;
}
.title-text {
color: #333333;
font-size: 24rpx;
font-weight: bold;
width: 100%;
box-sizing: border-box;
padding-left: 6rpx;
display: inline-block;
line-height: 29rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.labels-row {
display: flex;
flex-wrap: wrap;
margin-top: 12rpx;
}
.label-tag {
font-size: 20rpx;
color: #ff416c;
background: #fff5f7;
border: 1rpx solid #ffd6de;
padding: 2rpx 12rpx;
border-radius: 20rpx;
margin-right: 12rpx;
margin-bottom: 8rpx;
}
.goods-price-section {
margin-top: auto;
padding-bottom: 8rpx;
}
.price-main {
display: flex;
align-items: baseline;
}
.price-tip {
font-size: 24rpx;
color: #ff416c;
margin-right: 4rpx;
}
.price-symbol {
font-size: 24rpx;
color: #ff416c;
font-weight: bold;
}
.price-integer {
font-size: 40rpx;
color: #ff416c;
font-weight: bold;
margin-right: 12rpx;
}
.coupon-box {
display: flex;
align-items: center;
background: #ff416c;
border-radius: 4rpx;
overflow: hidden;
height: 32rpx;
}
.coupon-icon {
font-size: 20rpx;
color: #ffffff;
background: rgba(255,255,255,0.2);
padding: 0 6rpx;
height: 100%;
display: flex;
align-items: center;
}
.coupon-txt {
font-size: 20rpx;
color: #ffffff;
padding: 0 8rpx;
}
.price-coupon {
display: flex;
align-items: baseline;
margin-top: 4rpx;
}
.coupon-tip {
font-size: 22rpx;
color: #ff8a00;
}
.coupon-val {
font-size: 28rpx;
color: #ff8a00;
font-weight: bold;
}
.goods-bottom-info {
display: flex;
align-items: center;
font-size: 22rpx;
color: #999;
margin-top: 8rpx;
}
.split-line {
margin: 0 10rpx;
color: #eee;
}
.loading-more {
text-align: center;
padding: 40rpx 0;
font-size: 24rpx;
color: #999;
}
.footer-placeholder {
height: 40rpx;
}
</style>

View File

@ -0,0 +1,660 @@
<template>
<view class="detail-page-container">
<!-- 沉浸式顶部标题栏 -->
<view class="nav-header">
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
<view class="header-content">
<view class="back-area" @click="goBack">
<text class="back-icon"></text>
</view>
<view class="title-area">
<text class="title-text">{{ cateName }}</text>
</view>
<view class="placeholder-area"></view>
</view>
</view>
<scroll-view scroll-y class="scroll-content" @scrolltolower="loadMore">
<!-- 占位适配固定头部 -->
<view class="header-placeholder" :style="{ height: navBarHeight + 'px' }"></view>
<!-- 排序筛选栏 -->
<view class="filter-bar">
<view class="filter-item" :class="{ 'active': sortType === 1 }" @click="changeSort(1)">综合</view>
<view class="filter-item" :class="{ 'active': sortType === 2 }" @click="changeSort(2)">销量</view>
<view class="filter-item" :class="{ 'active': sortType === 3 }" @click="changeSort(3)">
券后价
<view class="price-arrows">
<text class="up" :class="{ 'hl': sortType === 3 && priceOrder === 'asc' }"></text>
<text class="down" :class="{ 'hl': sortType === 3 && priceOrder === 'desc' }"></text>
</view>
</view>
</view>
<!-- 高级筛选标签栏 -->
<view class="sub-filter-row">
<view class="sub-filter-item" :class="{ 'active': filterHasCoupon }" @click="toggleFilter('coupon')">有券
</view>
<view class="sub-filter-item" :class="{ 'active': filterIsFlagship }" @click="toggleFilter('flagship')">
旗舰店</view>
<view class="sub-filter-item" :class="{ 'active': filterIsTmall }" @click="toggleFilter('tmall')">天猫
</view>
<view class="sub-filter-item" :class="{ 'active': filterIsBrand }" @click="toggleFilter('brand')">品牌
</view>
</view>
<!-- 商品列表 (横向单列风格) -->
<view class="goods-list">
<view class="goods-item" v-for="(goods, idx) in goodsList" :key="idx"
@click="goToDetail('id', goods.id)">
<view class="g-img-left">
<image class="goods-img" :src="goods.image" mode="aspectFill"></image>
</view>
<view class="goods-info">
<view class="goods-title-row">
<image src="https://img-haodanku-com.cdn.fudaiapp.com/FlyOSTvjC3LjrkUoJ0NPxx1qnGz4"
class="platform-icon"></image>
<text class="title-text">{{ goods.title }}</text>
</view>
<!-- 标签组 -->
<view class="labels-row" v-if="goods.labels && goods.labels.length > 0">
<text class="label-tag" v-for="(label, lIdx) in goods.labels.slice(0, 2)"
:key="lIdx">{{ label }}</text>
</view>
<view class="goods-price-section">
<view class="price-main">
<text class="price-tip">{{ goods.couponValue > 0 ? '券后' : '抢购价' }}</text>
<text class="price-symbol"></text>
<text class="price-integer">{{ goods.finalPrice }}</text>
<view class="coupon-box" v-if="goods.couponValue > 0">
<text class="coupon-icon"></text>
<text class="coupon-txt">{{ goods.couponValue }}</text>
</view>
</view>
</view>
<view class="goods-bottom-info">
<text class="sales">已售{{ goods.sales }}</text>
<text class="split-line">|</text>
<text class="shop-name">店铺{{ goods.shopName }}</text>
</view>
</view>
</view>
</view>
<!-- 更多推荐分割线 -->
<view class="recommend-divider" v-if="recommendList.length > 0">
<view class="line"></view>
<text class="dot">更多推荐</text>
<view class="line"></view>
</view>
<!-- 推荐商品列表 -->
<view class="goods-list recommend-list" v-if="recommendList.length > 0">
<view class="goods-item" v-for="(goods, idx) in recommendList" :key="idx"
@click="goToDetail('keywordid', goods.id)">
<view class="g-img-left">
<image class="goods-img" :src="goods.image" mode="aspectFill"></image>
</view>
<view class="goods-info">
<view class="goods-title-row">
<image src="https://img-haodanku-com.cdn.fudaiapp.com/FlyOSTvjC3LjrkUoJ0NPxx1qnGz4"
class="platform-icon"></image>
<text class="title-text">{{ goods.title }}</text>
</view>
<view class="labels-row" v-if="goods.labels && goods.labels.length > 0">
<text class="label-tag" v-for="(label, lIdx) in goods.labels.slice(0, 2)"
:key="lIdx">{{ label }}</text>
</view>
<view class="goods-price-section">
<view class="price-main">
<text class="price-tip">{{ goods.couponValue > 0 ? '券后' : '抢购价' }}</text>
<text class="price-symbol"></text>
<text class="price-integer">{{ goods.finalPrice }}</text>
<view class="coupon-box" v-if="goods.couponValue > 0">
<text class="coupon-icon"></text>
<text class="coupon-txt">{{ goods.couponValue }}</text>
</view>
</view>
<view class="price-coupon" v-if="!$store.state.isThirdParty">
<view class="coupon-left">
<text class="coupon-tip"></text>
<text class="coupon-val">{{ $estimateCoupon(goods.tkmoney) }}</text>
</view>
</view>
</view>
<view class="goods-bottom-info">
<text class="sales">已售{{ goods.sales }}</text>
<text class="split-line">|</text>
<text class="shop-name">店铺{{ goods.shopName }}</text>
</view>
</view>
</view>
</view>
<view class="loading-status">
<view v-if="loading" class="loading-text">加载中...</view>
<view v-else-if="goodsList.length === 0" class="empty-text">暂无相关商品</view>
<view v-else-if="finished" class="finished-text">-- 已经到底啦 --</view>
</view>
<view class="footer-placeholder"></view>
</scroll-view>
</view>
</template>
<script>
import http from '@/request/request.js';
export default {
data() {
return {
statusBarHeight: 44,
cateName: '分类详情',
mainCatId: '',
secondCategory: '', // ID
goodsList: [],
page: 1,
sortType: 1, // 1:, 2:, 3:
priceOrder: 'desc',
loading: false,
finished: false,
//
filterHasCoupon: false,
filterIsFlagship: false,
filterIsTmall: false,
filterIsBrand: false,
recommendList: [], //
loadingRecommend: false
}
},
computed: {
navBarHeight() {
return this.statusBarHeight + 44;
}
},
onLoad(options) {
const sysInfo = uni.getSystemInfoSync();
this.statusBarHeight = sysInfo.statusBarHeight || 44;
if (options.cate_name) this.cateName = decodeURIComponent(options.cate_name);
if (options.id) this.mainCatId = options.id;
if (options.second_category) this.secondCategory = options.second_category;
this.getProducts(true);
},
methods: {
goBack() {
uni.navigateBack();
},
getProducts(refresh = false) {
if (refresh) {
this.page = 1;
this.finished = false;
this.goodsList = [];
}
if (this.loading || this.finished) return;
this.loading = true;
// (0:, 3:, 8:, 9:)
let sortParam = 0;
if (this.sortType === 2) {
sortParam = 3;
} else if (this.sortType === 3) {
sortParam = this.priceOrder === 'asc' ? 8 : 9;
}
//
let filterParams = '';
if (this.filterHasCoupon) filterParams += '&filtrate_type=16';
if (this.filterIsBrand) filterParams += '&is_brand=1';
// shoptype: 121,2
let shopTypes = [];
if (this.filterIsFlagship) shopTypes.push(1);
if (this.filterIsTmall) shopTypes.push(2);
if (shopTypes.length > 0) {
filterParams += `&shoptype=${shopTypes.join(',')}`;
}
http.get(
`https://api.cmspro.haodanku.com/find/allItemList?category_id=${this.mainCatId}&son_category=${encodeURIComponent(this.secondCategory)}&page=${this.page}&sort=${sortParam}&page_size=20&cid=YsWZ21tx${filterParams}`
).then(res => {
if (res.data && res.data.item_info) {
const list = res.data.item_info.map(item => ({
id: item.id,
image: item.itempic,
title: item.itemshorttitle && item.itemshorttitle.length > 18 ? item
.itemshorttitle.substring(0, 18) + '...' : item.itemshorttitle,
finalPrice: item.itemendprice,
couponValue: item.couponmoney || 0,
tkmoney: item.tkmoney || 0,
sales: item.itemsale >= 10000 ? (item.itemsale / 10000).toFixed(1) + '万' :
item.itemsale,
shopType: item.shoptype === 'B' ? '天猫' : '淘宝',
shopName: item.shopname,
labels: item.label || []
}));
if (list.length === 0) {
this.finished = true;
} else {
this.goodsList = [...this.goodsList, ...list];
this.page++;
if (list.length < 20) {
this.finished = true;
}
}
// 10
if (refresh && this.goodsList.length < 10) {
this.getRecommendList();
}
} else {
this.finished = true;
if (refresh) this.getRecommendList();
}
}).finally(() => {
this.loading = false;
});
},
getRecommendList() {
if (this.loadingRecommend) return;
this.loadingRecommend = true;
//
let recommendParams = '';
if (this.filterHasCoupon) recommendParams += '&is_coupon=1';
if (this.filterIsFlagship) recommendParams += '&is_tmall=1';
if (this.filterIsTmall) recommendParams += '&min_id=1';
http.get(
`https://api.cmspro.haodanku.com/superSearch/getList?sort=0&page_size=20&category_id=${this.mainCatId}&son_category=${encodeURIComponent(this.secondCategory)}&cid=YsWZ21tx${recommendParams}`
).then(res => {
console.log('res', res)
if (res.data) {
const list = res.data.map(item => {
console.log('推荐商品:', item.id || item.itemid)
return {
id: item.id || item.itemid,
image: item.itempic,
title: item.itemshorttitle && item.itemshorttitle.length > 18 ? item
.itemshorttitle.substring(0, 18) + '...' : item.itemshorttitle,
finalPrice: item.itemendprice,
couponValue: item.couponmoney || 0,
tkmoney: item.tkmoney || 0,
sales: item.itemsale >= 10000 ? (item.itemsale / 10000).toFixed(1) + '万' :
item.itemsale,
shopType: item.shoptype === 'B' ? '天猫' : '淘宝',
shopName: item.shopname,
labels: item.label || (item.couponmoney > 0 ? [`${item.couponmoney}元券`] :
[])
}
});
this.recommendList = list;
}
}).finally(() => {
this.loadingRecommend = false;
});
},
changeSort(type) {
if (type === 3 && this.sortType === 3) {
this.priceOrder = this.priceOrder === 'asc' ? 'desc' : 'asc';
} else {
this.sortType = type;
if (type === 3) this.priceOrder = 'desc';
}
this.getProducts(true);
},
toggleFilter(type) {
if (type === 'coupon') this.filterHasCoupon = !this.filterHasCoupon;
if (type === 'flagship') this.filterIsFlagship = !this.filterIsFlagship;
if (type === 'tmall') this.filterIsTmall = !this.filterIsTmall;
if (type === 'brand') this.filterIsBrand = !this.filterIsBrand;
this.getProducts(true);
},
loadMore() {
this.getProducts();
},
goToDetail(key, id) {
// console.log(`/pages/detail/detail?${key}=${id}`)
uni.navigateTo({
url: `/pages/detail/detail?${key}=${id}`
});
}
}
}
</script>
<style scoped>
.detail-page-container {
width: 100%;
height: 100vh;
background-color: #f5f6f8;
display: flex;
flex-direction: column;
}
/* 顶部导航 */
.nav-header {
position: fixed;
top: 0;
left: 0;
/* 去掉阴影让头部更轻 */
right: 0;
background-color: #ffffff;
z-index: 100;
}
.status-bar {
width: 100%;
}
.header-content {
height: 44px;
display: flex;
align-items: center;
padding: 0 30rpx;
}
.back-area {
width: 60rpx;
display: flex;
align-items: center;
}
.back-icon {
font-size: 36rpx;
color: #333;
font-weight: bold;
}
.title-area {
flex: 1;
text-align: center;
}
.nav-header .title-text {
font-size: 36rpx;
color: #333;
font-weight: bold;
}
.placeholder-area {
width: 60rpx;
}
.scroll-content {
flex: 1;
height: 100%;
}
.header-placeholder {
width: 100%;
}
/* 筛选栏 */
.filter-bar {
display: flex;
background: #ffffff;
height: 76rpx;
align-items: center;
position: sticky;
top: 0;
z-index: 90;
}
.filter-item {
flex: 1;
text-align: center;
font-size: 28rpx;
color: #666;
display: flex;
align-items: center;
justify-content: center;
}
.filter-item.active {
color: #ff416c;
font-weight: bold;
}
/* 高级筛选标签栏 */
.sub-filter-row {
display: flex;
background: #ffffff;
padding: 0 20rpx 16rpx;
align-items: center;
border-bottom: 1rpx solid #f1f1f1;
}
.sub-filter-item {
padding: 8rpx 26rpx;
background: #f5f6f8;
color: #333;
font-size: 24rpx;
border-radius: 28rpx;
margin-right: 16rpx;
transition: all 0.2s;
}
.sub-filter-item.active {
background: linear-gradient(to right, #ff758c, #ff416c);
color: #ffffff;
font-weight: 500;
}
.price-arrows {
display: flex;
flex-direction: column;
margin-left: 6rpx;
line-height: 1;
}
.price-arrows text {
font-size: 16rpx;
color: #ccc;
}
.price-arrows text.hl {
color: #ff416c;
}
/* 商品列表 */
.goods-list {
padding: 0;
background: #ffffff;
}
.goods-item {
display: flex;
padding: 24rpx;
border-bottom: 1rpx solid #f8f8f8;
background: #ffffff;
}
.g-img-left {
flex-shrink: 0;
width: 240rpx;
height: 240rpx;
border-radius: 12rpx;
overflow: hidden;
background: #f0f0f0;
}
.goods-img {
width: 100%;
height: 100%;
}
.goods-info {
flex: 1;
margin-left: 20rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 4rpx 0;
}
.goods-title-row {
display: flex;
align-items: center;
line-height: 1.4;
}
.platform-icon {
width: 26rpx;
height: 26rpx;
margin-right: 8rpx;
flex-shrink: 0;
}
.title-text {
font-size: 22rpx;
color: #333;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
}
.labels-row {
display: flex;
flex-wrap: wrap;
margin-top: 12rpx;
}
.label-tag {
font-size: 20rpx;
color: #ff416c;
background: #fff5f7;
border: 1rpx solid #ffd6de;
padding: 2rpx 12rpx;
border-radius: 20rpx;
margin-right: 12rpx;
margin-bottom: 8rpx;
}
.goods-price-section {
margin-top: auto;
padding-bottom: 8rpx;
}
.price-main {
display: flex;
align-items: baseline;
}
.price-tip {
font-size: 24rpx;
color: #ff416c;
margin-right: 4rpx;
}
.price-symbol {
font-size: 24rpx;
color: #ff416c;
font-weight: bold;
}
.price-integer {
font-size: 40rpx;
color: #ff416c;
font-weight: bold;
margin-right: 12rpx;
}
.coupon-box {
display: flex;
align-items: center;
background: #ff416c;
border-radius: 4rpx;
overflow: hidden;
height: 32rpx;
}
.coupon-icon {
font-size: 20rpx;
color: #ffffff;
background: rgba(255, 255, 255, 0.2);
padding: 0 6rpx;
height: 100%;
display: flex;
align-items: center;
}
.coupon-txt {
font-size: 20rpx;
color: #ffffff;
padding: 0 8rpx;
}
.price-coupon {
display: flex;
align-items: baseline;
margin-top: 4rpx;
}
.coupon-tip {
font-size: 22rpx;
color: #ff8a00;
}
.coupon-val {
font-size: 28rpx;
color: #ff8a00;
font-weight: bold;
}
.goods-bottom-info {
display: flex;
align-items: center;
font-size: 22rpx;
color: #999;
margin-top: 8rpx;
}
.split-line {
margin: 0 10rpx;
color: #eee;
}
.loading-status {
text-align: center;
padding: 40rpx 0;
font-size: 24rpx;
color: #999;
}
/* 更多推荐分割线 */
.recommend-divider {
display: flex;
align-items: center;
justify-content: center;
padding: 30rpx 0;
background-color: #f8f8f8;
}
.recommend-divider .line {
width: 100rpx;
height: 1rpx;
background-color: #ddd;
}
.recommend-divider .dot {
margin: 0 30rpx;
font-size: 28rpx;
color: #999;
}
.recommend-list {
background: #ffffff;
}
.footer-placeholder {
height: 40rpx;
}
</style>

1703
pages/detail/detail.vue Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
<template> <template>
<view class="page"> <view class="page">
<web-view :src="src"></web-view> <view class="bridge-tip">正在返回小程序页面...</view>
</view> </view>
</template> </template>
@ -8,49 +8,37 @@
export default { export default {
data() { data() {
return { return {
activityHomeUrl: 'http://point.agrimedia.cn/affiliate-activity/pages/index/index',
src: '',
from: '' from: ''
} }
}, },
onLoad(options) { onLoad(options) {
this.initBridgeEntryUrl()
if (options && options.from) { if (options && options.from) {
this.from = decodeURIComponent(options.from) this.from = decodeURIComponent(options.from)
} }
}, const target = this.from || '/pages/tabbar/index'
onUnload() { uni.switchTab({
if (this.from) { url: target,
this.$tools.setPromotionBridgeSkip(this.from) fail: () => {
} uni.reLaunch({
}, url: target
methods: { })
// bridge
// 1. exuiduid 7
// 2. exuid
initBridgeEntryUrl() {
const localUid = String(uni.getStorageSync('uid') || '')
if (!localUid) {
this.src = this.activityHomeUrl
return
} }
const promotionUid = this.buildPromotionUidValue(localUid) })
this.src = `${this.activityHomeUrl}?exuid=${promotionUid}` },
console.log(this.src) methods: {}
},
// 广 uid 7 0
buildPromotionUidValue(localUid) {
const uidValue = String(localUid || '')
const padCount = Math.max(7 - uidValue.length, 0)
return `${uidValue}${'0'.repeat(padCount)}`
}
}
} }
</script> </script>
<style> <style>
.page { .page {
width: 100%; width: 100%;
height: 100%; height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.bridge-tip {
font-size: 28rpx;
color: #666;
} }
</style> </style>

View File

@ -7,7 +7,8 @@
</view> </view>
</view> </view>
<view class="w100 rows rowsc"> <view class="w100 rows rowsc">
<image class="w-188 h-188 br-100" :src="$tools.oss(logo)" mode="aspectFill"></image> <!-- <image class="w-188 h-188 br-100" :src="$tools.oss(logo)" mode="aspectFill"></image> 后台配置头像 -->
<image class="w-188 h-188 br-100" src="https://imgs.agrimedia.cn/user.png" mode="aspectFill"></image>
</view> </view>
<view class="w100 rows rowsl rowsm mt-300"> <view class="w100 rows rowsl rowsm mt-300">
<button class="w-546 h-90 bg br-100 colfff fs-30 rows rowsm rowsc" open-type="getPhoneNumber" <button class="w-546 h-90 bg br-100 colfff fs-30 rows rowsm rowsc" open-type="getPhoneNumber"

View File

@ -0,0 +1,138 @@
<template>
<view class="save-money-container">
<!-- 沉浸式状态栏与高定自定义顶部导航条 -->
<view class="custom-nav-bar">
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
<view class="nav-header">
<view class="nav-back" @click="goBack">
<text class="back-arrow"></text>
</view>
<text class="nav-title">省钱攻略</text>
<view class="nav-right-placeholder"></view>
</view>
</view>
<!-- 占位符防止图片被顶部悬浮遮挡 -->
<view class="nav-placeholder" :style="{ height: navBarHeight + 'px' }"></view>
<!-- 核心内容区无缝连接的两张全景自适应介绍照片 -->
<view class="photo-flow">
<image class="flow-img" src="https://img.bc.haodanku.com/cms_web/cms-save-money-1" mode="widthFix"></image>
<image class="flow-img" src="https://img.bc.haodanku.com/cms_web/cms-save-money-2" mode="widthFix"></image>
</view>
<!-- 底部专属版权说明 -->
<view class="custom-copyright">
<text class="copyright-txt">©粉丝福利购专属优惠商城</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
statusBarHeight: 20
};
},
computed: {
navBarHeight() {
return this.statusBarHeight + 44;
}
},
onLoad() {
const systemInfo = uni.getSystemInfoSync();
if (systemInfo.statusBarHeight) {
this.statusBarHeight = systemInfo.statusBarHeight;
}
},
methods: {
goBack() {
uni.navigateBack({
delta: 1
});
}
}
}
</script>
<style scoped>
.save-money-container {
min-height: 100vh;
background-color: #ffffff;
display: flex;
flex-direction: column;
}
/* 顶部沉浸式导航条 */
.custom-nav-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: #ffffff;
z-index: 999;
box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.02);
}
.status-bar {
width: 100%;
}
.nav-header {
height: 44px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 30rpx;
}
.nav-back {
width: 60rpx;
height: 100%;
display: flex;
align-items: center;
}
.back-arrow {
font-size: 38rpx;
font-weight: bold;
color: #333333;
}
.nav-title {
font-size: 34rpx;
font-weight: bold;
color: #333333;
}
.nav-right-placeholder {
width: 60rpx;
}
/* 照片瀑布流底板 */
.photo-flow {
width: 100%;
display: flex;
flex-direction: column;
font-size: 0; /* 彻底清除图片间的空白缝隙 */
}
.flow-img {
width: 100%;
display: block;
}
/* 底部版权说明 */
.custom-copyright {
padding: 40rpx 0 60rpx;
text-align: center;
background-color: #ffffff;
}
.copyright-txt {
font-size: 24rpx;
color: rgb(150, 151, 153);
letter-spacing: 2rpx;
}
</style>

1019
pages/search/search.vue Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,850 @@
<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 back-area" @click="goBack">
<text class="back-icon"></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: navBarHeight + '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="capsules-row">
<view class="b-fans-capsule" v-if="brandInfo.fans">
<text class="heart-icon"></text>
<text>{{ formattedFans }} 粉丝关注</text>
</view>
<!-- 月销量动态胶囊0值全隐 -->
<view class="b-sale-capsule" v-if="brandInfo.todaysale && Number(brandInfo.todaysale) > 0">
<text class="fire-icon">🔥</text>
<text>月销 {{ formatSale(brandInfo.todaysale) }} </text>
</view>
</view>
</view>
<!-- 顶层海报极度纯净减负旧版简介彻底下沉至卡片内展示 -->
</view>
</view>
<!-- 浮动式品牌卖点话题与下沉简介展示墙 (高级拟态玻璃卡片) -->
<view class="compile-card-wrapper" v-if="compileLines.length > 0 || recommendTags.length > 0 || brandInfo.introduce">
<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> -->
<!-- 推荐话题列表 (横向丝滑拖动轴) -->
<scroll-view scroll-x class="recommend-tags-scroll" :show-scrollbar="false" v-if="recommendTags.length > 0">
<view class="tags-scroll-inner">
<text class="r-tag" v-for="(tag, tIdx) in recommendTags" :key="tIdx">{{ tag }}</text>
</view>
</scroll-view>
<!-- 下沉式高定深色简介与行末跟随红字按钮 -->
<view class="card-intro-section" v-if="brandInfo.introduce">
<text class="c-intro-txt">{{ isExpanded ? brandInfo.introduce : (brandInfo.introduce.length > 95 ? brandInfo.introduce.slice(0, 95) + '...' : brandInfo.introduce) }}</text>
<text class="inline-toggle-btn" v-if="brandInfo.introduce.length > 95" @click="isExpanded = !isExpanded">{{ isExpanded ? ' 收起' : ' 展开'}}</text>
</view>
</view>
</view>
<!-- 纯白容器大盘装配货盘引擎 -->
<view class="items-container-box">
<!-- 排序选项卡栏 (极细线分割) -->
<view class="filter-bar">
<view class="filter-item" :class="{ 'active': sortType === 1 }" @click="changeSort(1)">综合</view>
<view class="filter-divider"></view>
<view class="filter-item" :class="{ 'active': sortType === 2 }" @click="changeSort(2)">销量</view>
<view class="filter-divider"></view>
<view class="filter-item" :class="{ 'active': sortType === 3 }" @click="changeSort(3)">
券后价
<view class="price-arrows">
<text class="up" :class="{ 'hl': sortType === 3 && priceOrder === 'asc' }"></text>
<text class="down" :class="{ 'hl': sortType === 3 && priceOrder === 'desc' }"></text>
</view>
</view>
</view>
<!-- 横向单列左图右文精装流 -->
<view class="goods-list-single">
<view class="single-goods-item" v-for="(goods, gIdx) in itemList" :key="gIdx" @click="goToDetail(goods.id)">
<!-- 左侧圆角方图预览 -->
<view class="g-img-left">
<image class="goods-pic" :src="goods.itempic" mode="aspectFill"></image>
</view>
<!-- 右侧高阶信息核心带 -->
<view class="g-info-right">
<!-- 平台红标与加粗题词 -->
<view class="g-title-row">
<image src="https://img-haodanku-com.cdn.fudaiapp.com/FlyOSTvjC3LjrkUoJ0NPxx1qnGz4" class="platform-icon"></image>
<text class="title-text">{{ goods.itemshorttitle || goods.itemtitle }}</text>
</view>
<!-- 精装浅粉底色圆角标签阵列 -->
<view class="g-labels-row" v-if="goods.label && goods.label.length > 0">
<text class="g-label-tag" v-for="(tag, tIdx) in goods.label.slice(0, 2)" :key="tIdx">{{ tag }}</text>
</view>
<view class="g-labels-row" v-else-if="goods.discount">
<text class="g-label-tag">{{ goods.discount }}</text>
</view>
<view class="g-labels-row" v-else>
<text class="g-label-tag">精选特卖</text>
</view>
<!-- 超大字粉红券后价与实心红底连体券标 -->
<view class="g-price-row">
<view class="price-left">
<text class="p-tip">券后</text>
<text class="p-symbol"></text>
<text class="p-integer">{{ goods.itemendprice }}</text>
</view>
<!-- 连体实心红胶囊 -->
<view class="coupon-solid-box" v-if="goods.couponmoney > 0">
<text class="c-left"></text>
<text class="c-right">{{ goods.couponmoney }}</text>
</view>
</view>
<!-- 底部已售与店铺背书墙 -->
<view class="g-bottom-row">
<text class="sales">已售{{ formatSale(goods.itemsale) }}</text>
<text class="divider">|</text>
<text class="shop">店铺{{ goods.shopname || brandInfo.tb_brand_name || brandInfo.fq_brand_name || '官方旗舰店' }}</text>
</view>
</view>
</view>
</view>
<!-- 底部极致干脆的高端提示语留白区 -->
<view class="pure-loading-footer">
<text v-if="loading">加载中...</text>
<text v-else-if="finished">已为您加载完毕</text>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import http from '@/request/request.js';
export default {
data() {
return {
statusBarHeight: 44,
scrollY: 0,
brandId: 0,
brandInfo: {},
itemList: [],
page: 1,
sortType: 1, // 1:, 2:, 3:
priceOrder: 'desc',
isExpanded: false,
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: {
navBarHeight() {
return this.statusBarHeight + 44;
},
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) return '1.0万';
if (val >= 10000) {
return (val / 10000).toFixed(1) + '万';
}
return val;
},
changeSort(type) {
if (type === 3 && this.sortType === 3) {
this.priceOrder = this.priceOrder === 'asc' ? 'desc' : 'asc';
} else {
this.sortType = type;
if (type === 3) this.priceOrder = 'desc';
}
this.page = 1;
this.finished = false;
this.itemList = [];
this.fetchBrandDetailData();
},
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 });
}
// 0389
let sortParam = 0;
if (this.sortType === 2) {
sortParam = 3;
} else if (this.sortType === 3) {
sortParam = this.priceOrder === 'asc' ? 8 : 9;
}
http.get(`https://api.cmspro.haodanku.com/brandItem/detail?page=${this.page}&page_size=20&sort=${sortParam}&brand_id=${this.brandId}&cid=YsWZ21tx`)
.then((res) => {
if (res.data) {
//
if (res.data.brand_info) {
const info = res.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.items && Array.isArray(res.data.items.list)) {
const list = res.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),
shopname: goods.shopname || (goods.shoptype === 'B' ? '天猫超市' : ''),
label: Array.isArray(goods.label) ? goods.label : []
};
});
if (isLoadMore) {
this.itemList = [...this.itemList, ...list];
} else {
this.itemList = list;
}
const pagination = res.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' });
}
})
.catch((err) => {
console.log('拉取品牌专页接口错误', err);
if (isLoadMore && this.page > 1) this.page -= 1;
})
.finally(() => {
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;
}
.status-bar {
width: 100%;
}
.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-icon {
font-size: 38rpx;
color: #ffffff;
font-weight: bold;
text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.4);
}
.header-scrolled .back-icon {
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);
}
.capsules-row {
display: flex;
align-items: center;
justify-content: center;
gap: 16rpx;
margin-top: 10rpx;
}
.b-fans-capsule {
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);
}
.b-sale-capsule {
background: linear-gradient(to right, rgba(255,140,0,0.85), rgba(255,69,0,0.85));
padding: 4rpx 20rpx;
border-radius: 20rpx;
display: flex;
align-items: center;
backdrop-filter: blur(8rpx);
}
.heart-icon, .fire-icon {
color: #ffffff;
font-size: 22rpx;
margin-right: 8rpx;
}
.b-fans-capsule text, .b-sale-capsule text {
color: #ffffff;
font-size: 22rpx;
font-weight: bold;
}
/* 拟态玻璃精编卖点与下沉简介卡片层 */
.card-intro-section {
margin-top: 16rpx;
border-top: 1rpx dashed rgba(0,0,0,0.06);
padding-top: 16rpx;
width: 100%;
}
.c-intro-txt {
font-size: 26rpx;
color: #333333;
line-height: 1.6;
text-align: justify;
}
.inline-toggle-btn {
color: #ff416c;
font-size: 26rpx;
font-weight: bold;
padding-left: 6rpx;
display: inline;
}
/* 拟态玻璃精编卖点卡片层 */
.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-scroll {
width: 100%;
white-space: nowrap;
box-sizing: border-box;
}
.tags-scroll-inner {
display: inline-flex;
align-items: center;
padding: 4rpx 0;
}
.r-tag {
font-size: 24rpx;
color: #555555;
background-color: #f4f5f9;
padding: 10rpx 24rpx;
border-radius: 26rpx;
margin-right: 16rpx;
font-weight: 500;
display: inline-block;
white-space: nowrap;
word-break: keep-all;
flex-shrink: 0;
}
/* 纯白装配大底盘与过滤排序引擎 */
.items-container-box {
background: #ffffff;
border-top-left-radius: 24rpx;
border-top-right-radius: 24rpx;
margin: 0 24rpx;
padding-bottom: 40rpx;
overflow: hidden;
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.02);
}
.filter-bar {
display: flex;
align-items: center;
height: 88rpx;
border-bottom: 1rpx solid #f6f6f6;
background: #ffffff;
}
.filter-item {
flex: 1;
text-align: center;
font-size: 28rpx;
color: #666666;
display: flex;
align-items: center;
justify-content: center;
}
.filter-item.active {
color: #ff416c;
font-weight: bold;
}
.filter-divider {
width: 2rpx;
height: 24rpx;
background-color: #eeeeee;
}
.price-arrows {
display: flex;
flex-direction: column;
margin-left: 8rpx;
line-height: 1;
}
.price-arrows text {
font-size: 16rpx;
color: #cccccc;
}
.price-arrows text.hl {
color: #ff416c;
}
/* 单列横排货盘流 */
.goods-list-single {
background: #ffffff;
}
.single-goods-item {
display: flex;
padding: 24rpx;
border-bottom: 1rpx solid #f9f9f9;
}
.g-img-left {
width: 220rpx;
height: 220rpx;
border-radius: 12rpx;
overflow: hidden;
flex-shrink: 0;
background-color: #f5f5f5;
}
.goods-pic {
width: 100%;
height: 100%;
}
.g-info-right {
flex: 1;
margin-left: 24rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 4rpx 0;
overflow: hidden;
}
.g-title-row {
display: flex;
align-items: flex-start;
line-height: 1.4;
}
.platform-icon {
width: 26rpx;
height: 26rpx;
margin-right: 8rpx;
margin-top: 4rpx;
flex-shrink: 0;
}
.title-text {
font-size: 26rpx;
color: #333333;
font-weight: bold;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.g-labels-row {
display: flex;
flex-wrap: wrap;
margin-top: 10rpx;
}
.g-label-tag {
font-size: 20rpx;
color: #ff416c;
background: #fff5f7;
border: 1rpx solid #ffd6de;
padding: 2rpx 12rpx;
border-radius: 20rpx;
margin-right: 12rpx;
margin-bottom: 6rpx;
}
.g-price-row {
display: flex;
align-items: baseline;
margin-top: auto;
padding-top: 12rpx;
}
.price-left {
display: flex;
align-items: baseline;
}
.p-tip {
font-size: 22rpx;
color: #ff416c;
margin-right: 4rpx;
}
.p-symbol {
font-size: 24rpx;
color: #ff416c;
font-weight: bold;
}
.p-integer {
font-size: 38rpx;
color: #ff416c;
font-weight: bold;
}
/* 连体实心红胶囊 */
.coupon-solid-box {
display: flex;
align-items: center;
background: #ff416c;
border-radius: 6rpx;
overflow: hidden;
height: 32rpx;
margin-left: 16rpx;
}
.c-left {
font-size: 18rpx;
color: #ffffff;
background: rgba(255, 255, 255, 0.2);
padding: 0 8rpx;
height: 100%;
display: flex;
align-items: center;
font-weight: bold;
}
.c-right {
font-size: 18rpx;
color: #ffffff;
padding: 0 10rpx;
font-weight: bold;
}
.g-bottom-row {
display: flex;
align-items: center;
font-size: 22rpx;
color: #999999;
margin-top: 10rpx;
}
.divider {
margin: 0 12rpx;
color: #e0e0e0;
}
.shop {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
}
.pure-loading-footer {
text-align: center;
font-size: 24rpx;
color: #999999;
padding: 40rpx 0 20rpx;
}
</style>

View File

@ -1,6 +1,7 @@
<template> <template>
<view class="tabbar-page tabbar-page-padding"> <view class="tabbar-page tabbar-page-padding">
<block v-if="promotionUnlocked"> <taoke-home v-if="!promotionUnlocked"></taoke-home>
<block v-else>
<view class="w100 h-186" style="background-image: linear-gradient(to bottom,#F2BCBF,#F7F6FA);"> <view class="w100 h-186" style="background-image: linear-gradient(to bottom,#F2BCBF,#F7F6FA);">
<uni-nav-bar title="首页" :border="false" backgroundColor="transparent" class="fw-b"></uni-nav-bar> <uni-nav-bar title="首页" :border="false" backgroundColor="transparent" class="fw-b"></uni-nav-bar>
</view> </view>
@ -65,15 +66,18 @@
</template> </template>
<script> <script>
import TaokeHome from '@/components/taoke/tab-home.vue'
export default { export default {
components: {
TaokeHome
},
data() { data() {
return { return {
images: [], images: [],
nots: [], nots: [],
types: [], types: [],
list: [], list: [],
promotionUnlocked: true, promotionUnlocked: false
promotionH5Url: 'https://point.agrimedia.cn/affiliate-activity/pages/index/index'
} }
}, },
onLoad() { onLoad() {
@ -86,7 +90,7 @@
onShow() { onShow() {
this.syncPromotionStatus() this.syncPromotionStatus()
this.syncCustomTabBar() this.syncCustomTabBar()
if (this.openPromotionPageIfNeeded()) { if (!this.promotionUnlocked) {
return return
} }
if (this.list.length === 0) { if (this.list.length === 0) {
@ -108,16 +112,6 @@
} }
} }
}, },
openPromotionPageIfNeeded() {
if (this.promotionUnlocked) {
return false
}
if (this.$tools.consumePromotionBridgeSkip('/pages/tabbar/index')) {
return false
}
this.$tools.goNext(`/pages/h5/bridge?url=${encodeURIComponent(this.promotionH5Url)}&from=${encodeURIComponent('/pages/tabbar/index')}`)
return true
},
loadPageData() { loadPageData() {
this.banner() this.banner()
this.notice() this.notice()

View File

@ -13,12 +13,12 @@
<view class="h-164 rows rowsl rowsb"> <view class="h-164 rows rowsl rowsb">
<view class="rows rowsm"> <view class="rows rowsm">
<view class="fs-36 fw-b colfff mr-20 one_overflow" style="max-width: 250rpx;">{{infor.nickname}}</view> <view class="fs-36 fw-b colfff mr-20 one_overflow" style="max-width: 250rpx;">{{infor.nickname}}</view>
<view class="pl-10 pr-10 bgff rows rowsc rowsm h-38 col fs-24 fw-b br-100" v-if="infor.level==1">酒鬼</view> <!-- <view class="pl-10 pr-10 bgff rows rowsc rowsm h-38 col fs-24 fw-b br-100" v-if="infor.level==1">酒鬼</view>
<view class="pl-10 pr-10 bgff rows rowsc rowsm h-38 col fs-24 fw-b br-100" v-if="infor.level==2">酒圣</view> <view class="pl-10 pr-10 bgff rows rowsc rowsm h-38 col fs-24 fw-b br-100" v-if="infor.level==2">酒圣</view>
<view class="pl-10 pr-10 bgff rows rowsc rowsm h-38 col fs-24 fw-b br-100" v-if="infor.level==3">酒王</view> <view class="pl-10 pr-10 bgff rows rowsc rowsm h-38 col fs-24 fw-b br-100" v-if="infor.level==3">酒王</view>
<view class="pl-10 pr-10 bgff rows rowsc rowsm h-38 col fs-24 fw-b br-100" v-if="infor.level==4">酒仙</view> <view class="pl-10 pr-10 bgff rows rowsc rowsm h-38 col fs-24 fw-b br-100" v-if="infor.level==4">酒仙</view>
<view class="pl-10 pr-10 bgff rows rowsc rowsm h-38 col fs-24 fw-b br-100" v-if="infor.level==5">酒神</view> <view class="pl-10 pr-10 bgff rows rowsc rowsm h-38 col fs-24 fw-b br-100" v-if="infor.level==5">酒神</view>
<view class="pl-10 pr-10 bgff rows rowsc rowsm h-38 col fs-24 fw-b br-100" v-if="infor.level==6">酒佛</view> <view class="pl-10 pr-10 bgff rows rowsc rowsm h-38 col fs-24 fw-b br-100" v-if="infor.level==6">酒佛</view> -->
</view> </view>
<view class="rows rowsc rowsm w-160 br-10 h-40 colfff fs-26 fw-b" style="border: 2rpx solid #fff;">ID{{infor.invitation||''}}</view> <view class="rows rowsc rowsm w-160 br-10 h-40 colfff fs-26 fw-b" style="border: 2rpx solid #fff;">ID{{infor.invitation||''}}</view>
<text class="fs-28 colfff fw-b">{{infor.mobile||''}}</text> <text class="fs-28 colfff fw-b">{{infor.mobile||''}}</text>
@ -111,6 +111,7 @@
baseMenu:[ baseMenu:[
{id:1,name:'收货地址',icon:'/static/images/04_erfg.png',url:`/pageOne/mes/address`}, {id:1,name:'收货地址',icon:'/static/images/04_erfg.png',url:`/pageOne/mes/address`},
{id:2,name:'我的收藏',icon:'/static/images/04_we.png',url:`/pageOne/mes/collection`}, {id:2,name:'我的收藏',icon:'/static/images/04_we.png',url:`/pageOne/mes/collection`},
{id:4,name:'开通会员',icon:'/static/images/04_we.png',url:`/pageOne/mes/member`},
{id:3,name:'联系客服',icon:'/static/images/04_ghi.png',url:``}/* /pageOne/mes/service */ {id:3,name:'联系客服',icon:'/static/images/04_ghi.png',url:``}/* /pageOne/mes/service */
], ],
menu:[], menu:[],

View File

@ -1,5 +1,7 @@
<template> <template>
<view class="tabbar-page"> <view class="tabbar-page">
<taoke-rank v-if="!promotionUnlocked"></taoke-rank>
<block v-else>
<view class="w100 h-186" style="background-image: linear-gradient(to bottom,#F2BCBF,#F7F6FA);"> <view class="w100 h-186" style="background-image: linear-gradient(to bottom,#F2BCBF,#F7F6FA);">
<uni-nav-bar title="购物车" :border="false" backgroundColor="transparent" class="fw-b"></uni-nav-bar> <uni-nav-bar title="购物车" :border="false" backgroundColor="transparent" class="fw-b"></uni-nav-bar>
</view> </view>
@ -48,19 +50,23 @@
结算 结算
</view> </view>
</view> </view>
</block>
</view> </view>
</template> </template>
<script> <script>
import TaokeRank from '@/components/taoke/tab-rank.vue'
export default { export default {
components: {
TaokeRank
},
data() { data() {
return { return {
min: 1, min: 1,
nums: 1, nums: 1,
list: [], list: [],
checkAllList: false, checkAllList: false,
promotionUnlocked: true, promotionUnlocked: false
promotionH5Url: 'https://point.agrimedia.cn/affiliate-activity/pages/rank/rank'
} }
}, },
onLoad() { onLoad() {
@ -69,7 +75,7 @@
onShow() { onShow() {
this.syncPromotionStatus() this.syncPromotionStatus()
this.syncCustomTabBar() this.syncCustomTabBar()
if (this.openPromotionPageIfNeeded()) { if (!this.promotionUnlocked) {
return return
} }
if (this.list.length === 0) { if (this.list.length === 0) {
@ -102,16 +108,6 @@
} }
} }
}, },
openPromotionPageIfNeeded() {
if (this.promotionUnlocked) {
return false
}
if (this.$tools.consumePromotionBridgeSkip('/pages/tabbar/shop')) {
return false
}
this.$tools.goNext(`/pages/h5/bridge?url=${encodeURIComponent(this.promotionH5Url)}&from=${encodeURIComponent('/pages/tabbar/shop')}`)
return true
},
shopCar() { shopCar() {
this.$tools.axiosFromToken('POST', 'shop/shopCar').then(res => { this.$tools.axiosFromToken('POST', 'shop/shopCar').then(res => {
res.data.forEach(item => { res.data.forEach(item => {

View File

@ -1,5 +1,7 @@
<template> <template>
<view class="tabbar-page tabbar-page-padding"> <view class="tabbar-page tabbar-page-padding">
<taoke-classify v-if="!promotionUnlocked"></taoke-classify>
<block v-else>
<view class="w100 h-186" style="background-image: linear-gradient(to bottom,#F2BCBF,#F7F6FA);"> <view class="w100 h-186" style="background-image: linear-gradient(to bottom,#F2BCBF,#F7F6FA);">
<uni-nav-bar title="分类" :border="false" backgroundColor="transparent" class="fw-b"></uni-nav-bar> <uni-nav-bar title="分类" :border="false" backgroundColor="transparent" class="fw-b"></uni-nav-bar>
</view> </view>
@ -31,19 +33,23 @@
</scroll-view> </scroll-view>
</view> </view>
</view> </view>
</block>
</view> </view>
</template> </template>
<script> <script>
import TaokeClassify from '@/components/taoke/tab-classify.vue'
export default { export default {
components: {
TaokeClassify
},
data() { data() {
return { return {
select: 0, select: 0,
types: [], types: [],
list: [], list: [],
ids: '', ids: '',
promotionUnlocked: true, promotionUnlocked: false
promotionH5Url: 'https://point.agrimedia.cn/affiliate-activity/pages/classify/classify'
} }
}, },
onLoad(e) { onLoad(e) {
@ -57,7 +63,7 @@
onShow() { onShow() {
this.syncPromotionStatus() this.syncPromotionStatus()
this.syncCustomTabBar() this.syncCustomTabBar()
if (this.openPromotionPageIfNeeded()) { if (!this.promotionUnlocked) {
return return
} }
if (this.types.length === 0) { if (this.types.length === 0) {
@ -79,16 +85,6 @@
} }
} }
}, },
openPromotionPageIfNeeded() {
if (this.promotionUnlocked) {
return false
}
if (this.$tools.consumePromotionBridgeSkip('/pages/tabbar/sort')) {
return false
}
this.$tools.goNext(`/pages/h5/bridge?url=${encodeURIComponent(this.promotionH5Url)}&from=${encodeURIComponent('/pages/tabbar/sort')}`)
return true
},
onSel(index, item) { onSel(index, item) {
this.ids = item.id this.ids = item.id
this.select = index this.select = index

257
request/request.js Normal file
View File

@ -0,0 +1,257 @@
/**
* uni.request 统一封装
*
* 设计目标
* 1. 自动兼容项目中所有 API 的成功状态判断code === 200 / code === 1 / status === 200
* 2. 支持自定义 header超时baseURL
* 3. Promise 调用简单
* 4. 支持请求/响应拦截器便于后续统一注入 token处理错误等
* 5. 数据提取自动降级优先取 res.data.data不存在则取 res.data
*/
class Request {
/**
* @param {Object} config - 全局默认配置
* @param {string} config.baseURL - 基础 URL
* @param {number} config.timeout - 超时时间ms默认 30000
* @param {Object} config.header - 默认请求头
*/
constructor(config = {}) {
this.config = {
baseURL: '',
timeout: 30000,
header: {
'Content-Type': 'application/json'
},
...config
};
this.interceptors = {
request: [],
response: []
};
}
/**
* 添加请求拦截器
* @param {Function} fn - (config) => config
*/
addRequestInterceptor(fn) {
if (typeof fn === 'function') {
this.interceptors.request.push(fn);
}
}
/**
* 添加响应拦截器
* @param {Function} fn - (response) => response
*/
addResponseInterceptor(fn) {
if (typeof fn === 'function') {
this.interceptors.response.push(fn);
}
}
/**
* 判断响应是否成功
*
* 兼容项目中实际存在的 4 种响应格式
* 1. CMS API: res.data.code === 200
* 2. Auth API: res.statusCode === 200 && (res.data.status === 200 || res.data.code === 1)
* 3. Hdk v2 API: res.data.code === 1
* 4. 兜底: res.statusCode === 200无业务状态码时
*
* @param {Object} res - uni.request success 回调参数
* @returns {boolean}
*/
isSuccess(res) {
// HTTP 层已失败(如 404/500
if (res.statusCode >= 400) {
return false;
}
const data = res.data;
if (!data || typeof data !== 'object') {
// 无响应体时,以 HTTP 状态码为准
return res.statusCode === 200;
}
// 提取业务状态码(兼容 code / status 两种字段名)
const code = data.code !== undefined ? Number(data.code)
: data.status !== undefined ? Number(data.status)
: null;
if (code !== null && !isNaN(code)) {
return code === 200 || code === 1;
}
// 无业务状态码时,以 HTTP 状态码为准
return res.statusCode === 200;
}
/**
* 从响应中提取业务数据
*
* 降级策略
* - 优先取 res.data.dataCMS 标准格式
* - 不存在则取 res.data 本身直接返回格式
* - 空响应返回 null
*
* @param {Object} res - uni.request success 回调参数
* @returns {any}
*/
extractData(res) {
const data = res.data;
if (!data || typeof data !== 'object') {
return data;
}
return data.data !== undefined ? data.data : data;
}
/**
* 从响应中提取错误信息
* @param {Object} res - uni.request success 回调参数
* @returns {string}
*/
extractError(res) {
const data = res.data;
if (!data || typeof data !== 'object') {
return `请求失败 (HTTP ${res.statusCode})`;
}
return data.msg || data.message || data.error || `请求失败 (code: ${data.code || data.status})`;
}
/**
* 核心请求方法
*
* @param {Object} options - 请求配置
* @param {string} options.url - 请求地址可相对 baseURL
* @param {string} options.method - 请求方法GET/POST/PUT/DELETE默认 GET
* @param {Object} options.data - 请求数据
* @param {Object} options.header - 自定义请求头会合并覆盖默认 header大小写不敏感
* @param {number} options.timeout - 本次请求单独设置的超时时间
* @returns {Promise<{success: true, data: any, body: any, raw: Object}>}
*/
request(options = {}) {
return new Promise((resolve, reject) => {
// 1. 合并配置:默认 → 实例配置 → 单次请求配置
// header 合并需大小写不敏感去重(如 Content-Type 与 content-type 是同一头)
const mergedHeader = {};
for (const [k, v] of Object.entries(this.config.header)) {
mergedHeader[k.toLowerCase()] = v;
}
for (const [k, v] of Object.entries(options.header || {})) {
mergedHeader[k.toLowerCase()] = v;
}
let config = {
...this.config,
...options,
header: mergedHeader
};
// 2. 拼接 baseURL如果 url 不是完整 HTTP 地址)
if (config.baseURL && config.url && !config.url.startsWith('http')) {
config.url = config.baseURL.replace(/\/$/, '') + '/' + config.url.replace(/^\//, '');
}
// 3. 执行请求拦截器
try {
for (const fn of this.interceptors.request) {
config = fn(config) || config;
}
} catch (err) {
reject({ success: false, message: err.message || '请求拦截器异常', code: -2 });
return;
}
// 4. 发起请求
uni.request({
url: config.url,
method: (config.method || 'GET').toUpperCase(),
data: config.data,
header: config.header,
timeout: config.timeout,
success: (res) => {
// 5. 执行响应拦截器
try {
for (const fn of this.interceptors.response) {
res = fn(res) || res;
}
} catch (err) {
reject({ success: false, message: err.message || '响应拦截器异常', code: -3, raw: res });
return;
}
// 6. 判断成功/失败
if (this.isSuccess(res)) {
resolve({
success: true,
data: this.extractData(res),
body: res.data,
raw: res
});
} else {
reject({
success: false,
message: this.extractError(res),
code: res.data?.code ?? res.data?.status ?? res.statusCode,
raw: res
});
}
},
fail: (err) => {
reject({
success: false,
message: err.errMsg || '网络请求失败,请检查网络',
code: -1,
raw: err
});
}
});
});
}
/**
* GET 请求快捷方法
* @param {string} url
* @param {Object} data
* @param {Object} options
*/
get(url, data, options = {}) {
return this.request({ url, data, method: 'GET', ...options });
}
/**
* POST 请求快捷方法
* @param {string} url
* @param {Object} data
* @param {Object} options
*/
post(url, data, options = {}) {
return this.request({ url, data, method: 'POST', ...options });
}
/**
* PUT 请求快捷方法
*/
put(url, data, options = {}) {
return this.request({ url, data, method: 'PUT', ...options });
}
/**
* DELETE 请求快捷方法
*/
delete(url, data, options = {}) {
return this.request({ url, data, method: 'DELETE', ...options });
}
}
// ============================================================
// 创建全局默认实例
// ============================================================
const http = new Request();
// ============================================================
// 导出
// ============================================================
export default http;
export { Request };

BIN
static/img/fuli.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
static/rank_badge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
static/wheat_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,14 @@
"pages/tabbar/me", "pages/tabbar/me",
"pages/tabbar/sort", "pages/tabbar/sort",
"pages/tabbar/shop", "pages/tabbar/shop",
"pages/h5/bridge" "pages/h5/bridge",
"pages/detail/detail",
"pages/category/category",
"pages/category/category_detail",
"pages/search/search",
"pages/special-sale/choicen",
"pages/special-sale/details",
"pages/save-money/save-money"
], ],
"subPackages": [ "subPackages": [
{ {
@ -28,6 +35,7 @@
"mes/addNew", "mes/addNew",
"mes/addEdit", "mes/addEdit",
"mes/collection", "mes/collection",
"mes/member",
"mes/service", "mes/service",
"mes/promotion", "mes/promotion",
"mes/withdraw", "mes/withdraw",
@ -63,18 +71,18 @@
"selectedIconPath": "/static/images/icon_syf.png", "selectedIconPath": "/static/images/icon_syf.png",
"text": "首页" "text": "首页"
}, },
{
"pagePath": "pages/tabbar/shop",
"iconPath": "/static/images/icon_gwc.png",
"selectedIconPath": "/static/images/icon_gwcf.png",
"text": "榜单"
},
{ {
"pagePath": "pages/tabbar/sort", "pagePath": "pages/tabbar/sort",
"iconPath": "/static/images/icon_fl.png", "iconPath": "/static/images/icon_fl.png",
"selectedIconPath": "/static/images/icon_flf.png", "selectedIconPath": "/static/images/icon_flf.png",
"text": "分类" "text": "分类"
}, },
{
"pagePath": "pages/tabbar/shop",
"iconPath": "/static/images/icon_gwc.png",
"selectedIconPath": "/static/images/icon_gwcf.png",
"text": "购物车"
},
{ {
"pagePath": "pages/tabbar/me", "pagePath": "pages/tabbar/me",
"iconPath": "/static/images/icon_wd.png", "iconPath": "/static/images/icon_wd.png",

View File

@ -1,2 +1,2 @@
(global["webpackJsonp"]=global["webpackJsonp"]||[]).push([["common/main"],{0:function(e,t,o){"use strict";(function(e,t){var n=o(4),r=n(o(11));o(26);var a=n(o(25)),s=n(o(27)),i=o(33),c=n(o(34)),u=n(o(35)),l=n(o(36));n(o(65)),n(o(66));function f(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,n)}return o}function d(e){for(var t=1;t<arguments.length;t++){var o=null!=arguments[t]?arguments[t]:{};t%2?f(Object(o),!0).forEach((function(t){(0,r.default)(e,t,o[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(o)):f(Object(o)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(o,t))}))}return e}e.__webpack_require_UNI_MP_PLUGIN__=o;var p=o(65);a.default.prototype.$tools=c.default,a.default.prototype.$amapwx=u.default,a.default.mixin(i.mixin),a.default.mixin(p),a.default.use(l.default),s.default.mpType="app";var g=new a.default(d({},s.default));t(g).$mount()}).call(this,o(1)["default"],o(2)["createApp"])},27:function(e,t,o){"use strict";o.r(t);var n=o(28);for(var r in n)["default"].indexOf(r)<0&&function(e){o.d(t,e,(function(){return n[e]}))}(r);o(30);var a,s,i,c,u=o(32),l=Object(u["default"])(n["default"],a,s,!1,null,null,null,!1,i,c);l.options.__file="App.vue",t["default"]=l.exports},28:function(e,t,o){"use strict";o.r(t);var n=o(29),r=o.n(n);for(var a in n)["default"].indexOf(a)<0&&function(e){o.d(t,e,(function(){return n[e]}))}(a);t["default"]=r.a},29:function(e,t,o){"use strict";(function(e,n){var r=o(4);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=r(o(11));function s(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,n)}return o}function i(e){for(var t=1;t<arguments.length;t++){var o=null!=arguments[t]?arguments[t]:{};t%2?s(Object(o),!0).forEach((function(t){(0,a.default)(e,t,o[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(o)):s(Object(o)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(o,t))}))}return e}var c={globalData:{address:"",openId:null,token:null,location:{},system:{},userInfo:{},onAddress:{},onGoodCart:[],onCoupon:{},addressDetail:{},shoppings:[]},onLaunch:function(){},onShow:function(){console.log("App Show")},onHide:function(){console.log("App Hide")},methods:{overShare:function(){e.onAppRoute((function(t){var o=getCurrentPages(),n=o[o.length-1];n&&e.showShareMenu({withShareTicket:!0,menus:["shareAppMessage","shareTimeline"]})}))},getSystem:function(){var e=this;this.axiosFromToken("POST","common/service",{},"加载中").then((function(t){e.globalData.system=t.data,n.setStorageSync("system",t.data),console.log(t.constructor().constructor(),"系统配置")}))},getUserInfo:function(){var e=this;this.axiosFromToken("POST","user/userinfo",{token:this.globalData.token}).then((function(t){1==t.code?(console.log("用户信息",t.data),e.globalData.userInfo=t.data,n.setStorageSync("userInfo",t.data)):e.$tools.showtt(t.msg)}))},getAddress:function(){var e=this;return new Promise((function(t,o){if(e.globalData.location&&e.globalData.location.Address&&e.globalData.location.latitude&&e.globalData.location.longitude)t();else{var r=new e.$vm.$amapwx.AMapWX({key:"32744ba7c2805fac5edc9f7bafc1e1ae"});n.showLoading({title:"加载中"}),r.getRegeo({success:function(o){n.hideLoading(),e.globalData.location=o[0];var r=o[0].regeocodeData.addressComponent;"string"==typeof r.city?o[0].Address=r.city:o[0].Address=r.province,o[0].Address=o[0].Address.substring(0,o[0].Address.length-1),e.globalData.onAddress=o[0].Address,t(o[0].Address)},fail:function(t){n.hideLoading(),"getLocation:fail auth deny"==t.errMsg&&e.showtt("请同意授权位置信息"),console.log(t)}})}}))},payFn:function(e,t){return console.log(t,"支付参数"),new Promise((function(o,r){n.requestPayment(i(i({provider:e},t),{},{success:function(e){n.showToast({icon:"success",title:"支付成功"}),o(e)},fail:function(e){n.showToast({icon:"error",title:"支付失败"}),r(e)}}))}))}}};t.default=c}).call(this,o(1)["default"],o(2)["default"])},30:function(e,t,o){"use strict";o.r(t);var n=o(31),r=o.n(n);for(var a in n)["default"].indexOf(a)<0&&function(e){o.d(t,e,(function(){return n[e]}))}(a);t["default"]=r.a},31:function(e,t,o){}},[[0,"common/runtime","common/vendor"]]]); (global["webpackJsonp"]=global["webpackJsonp"]||[]).push([["common/main"],{0:function(e,t,o){"use strict";(function(e,t){var n=o(4),r=n(o(11));o(26);var a=n(o(25)),i=n(o(27)),s=o(33),c=n(o(34)),u=n(o(35)),l=n(o(36));n(o(65)),n(o(66));function f(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,n)}return o}function d(e){for(var t=1;t<arguments.length;t++){var o=null!=arguments[t]?arguments[t]:{};t%2?f(Object(o),!0).forEach((function(t){(0,r.default)(e,t,o[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(o)):f(Object(o)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(o,t))}))}return e}e.__webpack_require_UNI_MP_PLUGIN__=o;var p=o(65);a.default.prototype.$tools=c.default,a.default.prototype.$amapwx=u.default,a.default.prototype.$estimateCoupon=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:.3,o=Number(e||0)*Number(t||0);return o.toFixed(2)},a.default.prototype.$store=a.default.prototype.$store||{state:{isThirdParty:!1},getters:{currentUid:"",relationId:"",pid:"",isThirdParty:!1}},a.default.mixin(s.mixin),a.default.mixin(p),a.default.use(l.default),i.default.mpType="app";var g=new a.default(d({},i.default));t(g).$mount()}).call(this,o(1)["default"],o(2)["createApp"])},27:function(e,t,o){"use strict";o.r(t);var n=o(28);for(var r in n)["default"].indexOf(r)<0&&function(e){o.d(t,e,(function(){return n[e]}))}(r);o(30);var a,i,s,c,u=o(32),l=Object(u["default"])(n["default"],a,i,!1,null,null,null,!1,s,c);l.options.__file="App.vue",t["default"]=l.exports},28:function(e,t,o){"use strict";o.r(t);var n=o(29),r=o.n(n);for(var a in n)["default"].indexOf(a)<0&&function(e){o.d(t,e,(function(){return n[e]}))}(a);t["default"]=r.a},29:function(e,t,o){"use strict";(function(e,n){var r=o(4);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=r(o(11));function i(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,n)}return o}function s(e){for(var t=1;t<arguments.length;t++){var o=null!=arguments[t]?arguments[t]:{};t%2?i(Object(o),!0).forEach((function(t){(0,a.default)(e,t,o[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(o)):i(Object(o)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(o,t))}))}return e}var c={globalData:{address:"",openId:null,token:null,location:{},system:{},userInfo:{},onAddress:{},onGoodCart:[],onCoupon:{},addressDetail:{},shoppings:[]},onLaunch:function(){},onShow:function(){console.log("App Show")},onHide:function(){console.log("App Hide")},methods:{overShare:function(){e.onAppRoute((function(t){var o=getCurrentPages(),n=o[o.length-1];n&&e.showShareMenu({withShareTicket:!0,menus:["shareAppMessage","shareTimeline"]})}))},getSystem:function(){var e=this;this.axiosFromToken("POST","common/service",{},"加载中").then((function(t){e.globalData.system=t.data,n.setStorageSync("system",t.data),console.log(t.constructor().constructor(),"系统配置")}))},getUserInfo:function(){var e=this;this.axiosFromToken("POST","user/userinfo",{token:this.globalData.token}).then((function(t){1==t.code?(console.log("用户信息",t.data),e.globalData.userInfo=t.data,n.setStorageSync("userInfo",t.data)):e.$tools.showtt(t.msg)}))},getAddress:function(){var e=this;return new Promise((function(t,o){if(e.globalData.location&&e.globalData.location.Address&&e.globalData.location.latitude&&e.globalData.location.longitude)t();else{var r=new e.$vm.$amapwx.AMapWX({key:"32744ba7c2805fac5edc9f7bafc1e1ae"});n.showLoading({title:"加载中"}),r.getRegeo({success:function(o){n.hideLoading(),e.globalData.location=o[0];var r=o[0].regeocodeData.addressComponent;"string"==typeof r.city?o[0].Address=r.city:o[0].Address=r.province,o[0].Address=o[0].Address.substring(0,o[0].Address.length-1),e.globalData.onAddress=o[0].Address,t(o[0].Address)},fail:function(t){n.hideLoading(),"getLocation:fail auth deny"==t.errMsg&&e.showtt("请同意授权位置信息"),console.log(t)}})}}))},payFn:function(e,t){return console.log(t,"支付参数"),new Promise((function(o,r){n.requestPayment(s(s({provider:e},t),{},{success:function(e){n.showToast({icon:"success",title:"支付成功"}),o(e)},fail:function(e){n.showToast({icon:"error",title:"支付失败"}),r(e)}}))}))}}};t.default=c}).call(this,o(1)["default"],o(2)["default"])},30:function(e,t,o){"use strict";o.r(t);var n=o(31),r=o.n(n);for(var a in n)["default"].indexOf(a)<0&&function(e){o.d(t,e,(function(){return n[e]}))}(a);t["default"]=r.a},31:function(e,t,o){}},[[0,"common/runtime","common/vendor"]]]);
//# sourceMappingURL=../../.sourcemap/mp-weixin/common/main.js.map //# sourceMappingURL=../../.sourcemap/mp-weixin/common/main.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,10 @@
(global["webpackJsonp"]=global["webpackJsonp"]||[]).push([["components/address-picker/address-picker"],{395:function(e,t,n){"use strict";n.r(t);var r=n(396),a=n(398);for(var u in a)["default"].indexOf(u)<0&&function(e){n.d(t,e,(function(){return a[e]}))}(u);var i,c=n(32),d=Object(c["default"])(a["default"],r["render"],r["staticRenderFns"],!1,null,null,null,!1,r["components"],i);d.options.__file="components/address-picker/address-picker.vue",t["default"]=d.exports},396:function(e,t,n){"use strict";n.r(t);var r=n(397);n.d(t,"render",(function(){return r["render"]})),n.d(t,"staticRenderFns",(function(){return r["staticRenderFns"]})),n.d(t,"recyclableRender",(function(){return r["recyclableRender"]})),n.d(t,"components",(function(){return r["components"]}))},397:function(e,t,n){"use strict";var r;n.r(t),n.d(t,"render",(function(){return a})),n.d(t,"staticRenderFns",(function(){return i})),n.d(t,"recyclableRender",(function(){return u})),n.d(t,"components",(function(){return r}));var a=function(){var e=this,t=e.$createElement;e._self._c},u=!1,i=[];a._withStripped=!0},398:function(e,t,n){"use strict";n.r(t);var r=n(399),a=n.n(r);for(var u in r)["default"].indexOf(u)<0&&function(e){n.d(t,e,(function(){return r[e]}))}(u);t["default"]=a.a},399:function(e,t,n){"use strict";var r=n(4);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=r(n(400)),u=["","",""],i={data:function(){return{value:[0,0,0],array:[],index:0}},created:function(){this.initSelect()},methods:{initSelect:function(){this.updateSourceDate().updateAddressDate().$forceUpdate()},columnchange:function(e){this.updateSelectIndex(e.detail.column,e.detail.value).updateSourceDate().updateAddressDate().$forceUpdate()},updateSourceDate:function(){return this.array=[],this.array[0]=a.default.map((function(e){return{name:e.name}})),this.array[1]=a.default[this.value[0]].city.map((function(e){return{name:e.name}})),this.array[2]=a.default[this.value[0]].city[this.value[1]].area.map((function(e){return{name:e}})),this},updateSelectIndex:function(e,t){var n=JSON.parse(JSON.stringify(this.value));return n[e]=t,0===e&&(n[1]=0,n[2]=0),1===e&&(n[2]=0),this.value=n,this},updateAddressDate:function(){return u[0]=this.array[0][this.value[0]].name,u[1]=this.array[1][this.value[1]].name,u[2]=this.array[2][this.value[2]].name,this},bindPickerChange:function(e){return this.$emit("change",{index:this.value,data:u,name:u.join("")}),this}}};t.default=i}}]); (global["webpackJsonp"]=global["webpackJsonp"]||[]).push([["components/address-picker/address-picker"],{475:function(e,t,n){"use strict";n.r(t);var r=n(476),a=n(478);for(var u in a)["default"].indexOf(u)<0&&function(e){n.d(t,e,(function(){return a[e]}))}(u);var i,c=n(32),d=Object(c["default"])(a["default"],r["render"],r["staticRenderFns"],!1,null,null,null,!1,r["components"],i);d.options.__file="components/address-picker/address-picker.vue",t["default"]=d.exports},476:function(e,t,n){"use strict";n.r(t);var r=n(477);n.d(t,"render",(function(){return r["render"]})),n.d(t,"staticRenderFns",(function(){return r["staticRenderFns"]})),n.d(t,"recyclableRender",(function(){return r["recyclableRender"]})),n.d(t,"components",(function(){return r["components"]}))},477:function(e,t,n){"use strict";var r;n.r(t),n.d(t,"render",(function(){return a})),n.d(t,"staticRenderFns",(function(){return i})),n.d(t,"recyclableRender",(function(){return u})),n.d(t,"components",(function(){return r}));var a=function(){var e=this,t=e.$createElement;e._self._c},u=!1,i=[];a._withStripped=!0},478:function(e,t,n){"use strict";n.r(t);var r=n(479),a=n.n(r);for(var u in r)["default"].indexOf(u)<0&&function(e){n.d(t,e,(function(){return r[e]}))}(u);t["default"]=a.a},479:function(e,t,n){"use strict";var r=n(4);Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=r(n(480)),u=["","",""],i={data:function(){return{value:[0,0,0],array:[],index:0}},created:function(){this.initSelect()},methods:{initSelect:function(){this.updateSourceDate().updateAddressDate().$forceUpdate()},columnchange:function(e){this.updateSelectIndex(e.detail.column,e.detail.value).updateSourceDate().updateAddressDate().$forceUpdate()},updateSourceDate:function(){return this.array=[],this.array[0]=a.default.map((function(e){return{name:e.name}})),this.array[1]=a.default[this.value[0]].city.map((function(e){return{name:e.name}})),this.array[2]=a.default[this.value[0]].city[this.value[1]].area.map((function(e){return{name:e}})),this},updateSelectIndex:function(e,t){var n=JSON.parse(JSON.stringify(this.value));return n[e]=t,0===e&&(n[1]=0,n[2]=0),1===e&&(n[2]=0),this.value=n,this},updateAddressDate:function(){return u[0]=this.array[0][this.value[0]].name,u[1]=this.array[1][this.value[1]].name,u[2]=this.array[2][this.value[2]].name,this},bindPickerChange:function(e){return this.$emit("change",{index:this.value,data:u,name:u.join("")}),this}}};t.default=i}}]);
//# sourceMappingURL=../../../.sourcemap/mp-weixin/components/address-picker/address-picker.js.map //# sourceMappingURL=../../../.sourcemap/mp-weixin/components/address-picker/address-picker.js.map
;(global["webpackJsonp"] = global["webpackJsonp"] || []).push([ ;(global["webpackJsonp"] = global["webpackJsonp"] || []).push([
'components/address-picker/address-picker-create-component', 'components/address-picker/address-picker-create-component',
{ {
'components/address-picker/address-picker-create-component':(function(module, exports, __webpack_require__){ 'components/address-picker/address-picker-create-component':(function(module, exports, __webpack_require__){
__webpack_require__('2')['createComponent'](__webpack_require__(395)) __webpack_require__('2')['createComponent'](__webpack_require__(475))
}) })
}, },
[['components/address-picker/address-picker-create-component']] [['components/address-picker/address-picker-create-component']]

View File

@ -0,0 +1,11 @@
(global["webpackJsonp"]=global["webpackJsonp"]||[]).push([["components/bottom-nav/bottom-nav"],{532:function(n,t,e){"use strict";e.r(t);var r=e(533),o=e(535);for(var u in o)["default"].indexOf(u)<0&&function(n){e.d(t,n,(function(){return o[n]}))}(u);e(537);var c,a=e(32),i=Object(a["default"])(o["default"],r["render"],r["staticRenderFns"],!1,null,"02f25924",null,!1,r["components"],c);i.options.__file="components/bottom-nav/bottom-nav.vue",t["default"]=i.exports},533:function(n,t,e){"use strict";e.r(t);var r=e(534);e.d(t,"render",(function(){return r["render"]})),e.d(t,"staticRenderFns",(function(){return r["staticRenderFns"]})),e.d(t,"recyclableRender",(function(){return r["recyclableRender"]})),e.d(t,"components",(function(){return r["components"]}))},534:function(n,t,e){"use strict";var r;e.r(t),e.d(t,"render",(function(){return o})),e.d(t,"staticRenderFns",(function(){return c})),e.d(t,"recyclableRender",(function(){return u})),e.d(t,"components",(function(){return r}));var o=function(){var n=this,t=n.$createElement;n._self._c},u=!1,c=[];o._withStripped=!0},535:function(n,t,e){"use strict";e.r(t);var r=e(536),o=e.n(r);for(var u in r)["default"].indexOf(u)<0&&function(n){e.d(t,n,(function(){return r[n]}))}(u);t["default"]=o.a},536:function(n,t,e){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r={name:"BottomNav",props:{activeTab:{type:Number,default:0}}};t.default=r},537:function(n,t,e){"use strict";e.r(t);var r=e(538),o=e.n(r);for(var u in r)["default"].indexOf(u)<0&&function(n){e.d(t,n,(function(){return r[n]}))}(u);t["default"]=o.a},538:function(n,t,e){}}]);
//# sourceMappingURL=../../../.sourcemap/mp-weixin/components/bottom-nav/bottom-nav.js.map
;(global["webpackJsonp"] = global["webpackJsonp"] || []).push([
'components/bottom-nav/bottom-nav-create-component',
{
'components/bottom-nav/bottom-nav-create-component':(function(module, exports, __webpack_require__){
__webpack_require__('2')['createComponent'](__webpack_require__(532))
})
},
[['components/bottom-nav/bottom-nav-create-component']]
]);

View File

@ -0,0 +1,4 @@
{
"usingComponents": {},
"component": true
}

View File

@ -0,0 +1 @@
<view class="bottom-nav-stub data-v-02f25924"></view>

Some files were not shown because too many files have changed in this diff Show More