This commit is contained in:
1173117610@qq.com 2026-05-11 16:39:24 +08:00
parent 45f6556ff0
commit 42e810ac21
1 changed files with 559 additions and 18 deletions

View File

@ -4,8 +4,8 @@
<view class="search-header"> <view class="search-header">
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view> <view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
<view class="header-main"> <view class="header-main">
<view class="back-btn" @click="goBack"> <view class="back-btn" @click="goBack" hover-class="back-btn-hover">
<text class="iconfont icon-back"></text> <text class="back-arrow"></text>
</view> </view>
<view class="search-input-wrap"> <view class="search-input-wrap">
<text class="search-icon">🔍</text> <text class="search-icon">🔍</text>
@ -24,9 +24,80 @@
</view> </view>
</view> </view>
<scroll-view scroll-y class="search-body" :style="{ paddingTop: (statusBarHeight + 96) + 'px' }"> <scroll-view scroll-y class="search-body" :style="{ paddingTop: (statusBarHeight + 96) + 'px' }"
@scrolltolower="onScrollBottom">
<!-- 搜索结果列表 -->
<block v-if="isSearching">
<!-- 排序栏 -->
<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 searchResults" :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">
<text class="shop-type-tag" :class="goods.shopType === '天猫' ? 'tag-tmall' : 'tag-taobao'">{{ goods.shopType }}</text>
<text class="g-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-status">
<view v-if="loading" class="loading-text">加载中...</view>
<view v-else-if="searchResults.length === 0" class="empty-text">暂无相关商品</view>
<view v-else-if="finished" class="finished-text">-- 已经到底啦 --</view>
</view>
<view class="footer-placeholder"></view>
</block>
<block v-else>
<!-- 历史搜索 --> <!-- 历史搜索 -->
<view class="section history-section" v-if="historyList.length > 0"> <view class="section history-section" v-if="historyList.length > 0">
<view class="section-title">
<text>历史搜索</text>
<text class="clear-history" @click="clearHistory">清空</text>
</view>
<view class="tag-list"> <view class="tag-list">
<view class="tag-item" v-for="(word, index) in historyList" :key="index" @click="onSearch(word)"> <view class="tag-item" v-for="(word, index) in historyList" :key="index" @click="onSearch(word)">
{{ word }} {{ word }}
@ -34,6 +105,18 @@
</view> </view>
</view> </view>
<!-- 轻松省钱三部曲 -->
<view class="steps-tip">
<text class="steps-title">轻松省钱三部曲</text>
<view class="steps-row">
<text class="step-item"><text class="step-num">1.</text>输入关键词或商品标题</text>
<text class="step-arrow"></text>
<text class="step-item"><text class="step-num">2.</text>点击搜索查询</text>
<text class="step-arrow"></text>
<text class="step-item"><text class="step-num">3.</text>领券省钱购物</text>
</view>
</view>
<!-- 热门搜索 (固定的词条文字) --> <!-- 热门搜索 (固定的词条文字) -->
<view class="section hot-tags-section"> <view class="section hot-tags-section">
<view class="section-title">热门搜索</view> <view class="section-title">热门搜索</view>
@ -85,6 +168,7 @@
<text>© 粉丝福利购专属优惠商城</text> <text>© 粉丝福利购专属优惠商城</text>
</view> </view>
<view class="footer-placeholder"></view> <view class="footer-placeholder"></view>
</block>
</scroll-view> </scroll-view>
</view> </view>
</template> </template>
@ -99,7 +183,40 @@
historyList: [], historyList: [],
hotTags: ['风扇', '牙膏', '面膜', '洗发水', '保温杯', '蚊香液', '洗脸巾', '四件套'], hotTags: ['风扇', '牙膏', '面膜', '洗发水', '保温杯', '蚊香液', '洗脸巾', '四件套'],
rankingList: [], rankingList: [],
hotThemes: [] hotThemes: [],
//
isSearching: false,
searchResults: [],
page: 1,
pageSize: 20,
numPage: 0,
finished: false,
loading: false,
currentKeyword: '',
//
sortType: 1, // 1: 2: 3:
priceOrder: 'desc',
//
filterHasCoupon: false,
filterIsFlagship: false,
filterIsTmall: false,
filterIsBrand: false
}
},
watch: {
keyword(val) {
//
if (!val) {
this.isSearching = false;
this.searchResults = [];
this.currentKeyword = '';
}
},
activePlatform() {
//
if (this.isSearching && this.currentKeyword) {
this.doSearch(this.currentKeyword, true);
}
} }
}, },
computed: { computed: {
@ -161,14 +278,134 @@
}); });
}, },
onSearch(word) { onSearch(word) {
if (!word.trim()) { if (!word || !word.trim()) {
uni.showToast({ title: '请输入搜索内容', icon: 'none' }); uni.showToast({ title: '请输入搜索内容', icon: 'none' });
return; return;
} }
this.saveHistory(word); const trimmed = word.trim();
const name = encodeURIComponent(word.trim()); this.keyword = trimmed;
this.saveHistory(trimmed);
this.doSearch(trimmed, true);
},
doSearch(word, reset) {
if (this.loading) return;
if (reset) {
this.page = 1;
this.numPage = 0;
this.finished = false;
this.searchResults = [];
this.currentKeyword = word;
this.isSearching = true;
} else if (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;
//
const data = {
page: this.page,
page_size: this.pageSize,
keyword: encodeURIComponent(word), // data encode
sort: sortParam,
cid: 'qOstW90'
};
if (this.filterHasCoupon) data.filtrate_type = 16;
if (this.filterIsBrand) data.is_brand = 1;
const shopTypes = [];
if (this.filterIsFlagship) shopTypes.push(1);
if (this.filterIsTmall) shopTypes.push(2);
if (shopTypes.length > 0) data.shoptype = shopTypes.join(',');
uni.request({
url: 'https://api.cmspro.haodanku.com/find/allItemList',
data,
success: (res) => {
const body = res.data || {};
if (body.code === 200 && body.data) {
if (body.data.num_page) this.numPage = body.data.num_page;
const rawList = body.data.item_info || [];
const list = rawList.map(item => ({
id: item.id,
itemid: item.itemid,
image: item.itempic,
title: item.itemshorttitle && item.itemshorttitle.length > 18
? item.itemshorttitle.substring(0, 18) + '...'
: (item.itemshorttitle || item.itemtitle),
finalPrice: item.itemendprice,
couponValue: item.couponmoney || 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.searchResults = this.searchResults.concat(list);
this.page += 1;
// num_page
if (this.numPage > 0 && this.page > this.numPage) {
this.finished = true;
} else if (list.length < this.pageSize) {
this.finished = true;
}
}
} else {
this.finished = true;
if (body.code !== 200) {
uni.showToast({ title: body.msg || '搜索失败', icon: 'none' });
}
}
},
fail: () => {
uni.showToast({ title: '网络错误', icon: 'none' });
},
complete: () => {
this.loading = false;
}
});
},
onScrollBottom() {
if (this.isSearching && !this.finished && !this.loading && this.currentKeyword) {
this.doSearch(this.currentKeyword, 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';
}
if (this.currentKeyword) this.doSearch(this.currentKeyword, true);
},
toggleFilter(type) {
if (type === 'coupon') this.filterHasCoupon = !this.filterHasCoupon;
else if (type === 'flagship') this.filterIsFlagship = !this.filterIsFlagship;
else if (type === 'tmall') this.filterIsTmall = !this.filterIsTmall;
else if (type === 'brand') this.filterIsBrand = !this.filterIsBrand;
if (this.currentKeyword) this.doSearch(this.currentKeyword, true);
},
goToDetail(id) {
uni.navigateTo({ uni.navigateTo({
url: `/pages/category/category_detail?cate_name=${name}&is_search=1` url: `/pages/detail/detail?id=${id}`
});
},
clearHistory() {
uni.showModal({
title: '提示',
content: '确定清空搜索历史?',
success: (r) => {
if (r.confirm) {
this.historyList = [];
uni.removeStorageSync('search_history');
}
}
}); });
} }
} }
@ -201,9 +438,28 @@
} }
.back-btn { .back-btn {
width: 50rpx; width: 64rpx;
font-size: 36rpx; height: 64rpx;
border-radius: 50%;
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: background-color 0.2s;
}
.back-btn-hover {
background-color: #e8e8e8;
}
.back-arrow {
font-size: 44rpx;
color: #333; color: #333;
line-height: 1;
font-weight: 500;
margin-top: -4rpx;
margin-left: -2rpx;
} }
.search-input-wrap { .search-input-wrap {
@ -324,28 +580,34 @@
.column-card { .column-card {
width: 48.5%; width: 48.5%;
background-color: #ffffff; background: linear-gradient(180deg, #fff4eb 0%, #ffffff 40%);
border: 2rpx solid #ffe1cc;
border-radius: 16rpx; border-radius: 16rpx;
padding: 20rpx; padding: 20rpx;
box-sizing: border-box; box-sizing: border-box;
} }
.topic-card {
background: linear-gradient(180deg, #fff1ee 0%, #ffffff 40%);
border-color: #ffd8d0;
}
.card-header { .card-header {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 30rpx; margin-bottom: 24rpx;
flex-wrap: wrap;
} }
.card-icon { .card-icon {
font-size: 32rpx; font-size: 30rpx;
margin-right: 10rpx; margin-right: 8rpx;
} }
.card-title { .card-title {
font-size: 28rpx; font-size: 28rpx;
font-weight: bold; font-weight: bold;
color: #d16d3f; color: #d16d3f;
white-space: nowrap;
} }
.topic-card .card-title { .topic-card .card-title {
@ -355,9 +617,50 @@
.card-sub { .card-sub {
font-size: 20rpx; font-size: 20rpx;
color: #d1a38f; color: #d1a38f;
margin-left: 10rpx; margin-left: 8rpx;
width: 100%; white-space: nowrap;
margin-top: 4rpx; overflow: hidden;
text-overflow: ellipsis;
}
/* 轻松省钱三部曲 */
.steps-tip {
margin: 16rpx 20rpx 0;
padding: 16rpx 20rpx;
background: linear-gradient(135deg, #fff7f0, #fff0f3);
border-radius: 12rpx;
border: 2rpx solid #ffe1d6;
}
.steps-title {
display: block;
font-size: 24rpx;
font-weight: bold;
color: #ff6b3d;
margin-bottom: 10rpx;
}
.steps-row {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.step-item {
font-size: 22rpx;
color: #888;
}
.step-num {
color: #ff6b3d;
font-weight: bold;
margin-right: 4rpx;
}
.step-arrow {
font-size: 18rpx;
color: #ffb199;
margin: 0 8rpx;
} }
/* 全网热搜列表 */ /* 全网热搜列表 */
@ -448,4 +751,242 @@
.footer-placeholder { .footer-placeholder {
height: 60rpx; height: 60rpx;
} }
/* 历史搜索标题行 */
.history-section .section-title {
display: flex;
justify-content: space-between;
align-items: center;
}
.clear-history {
font-size: 24rpx;
color: #bbb;
padding: 6rpx 12rpx;
}
/* 排序栏 */
.filter-bar {
display: flex;
background: #ffffff;
height: 80rpx;
align-items: center;
border-bottom: 1rpx solid #f1f1f1;
}
.filter-bar .filter-item {
flex: 1;
text-align: center;
font-size: 26rpx;
color: #666;
display: flex;
align-items: center;
justify-content: center;
}
.filter-bar .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;
}
/* 高级筛选 */
.sub-filter-row {
display: flex;
background: #ffffff;
padding: 10rpx 20rpx 20rpx;
align-items: center;
}
.sub-filter-item {
padding: 6rpx 20rpx;
background: #f5f6f8;
color: #333;
font-size: 24rpx;
border-radius: 8rpx;
margin-right: 16rpx;
transition: all 0.2s;
}
.sub-filter-item.active {
background: linear-gradient(to right, #ff758c, #ff416c);
color: #ffffff;
font-weight: 500;
}
/* 商品列表 */
.goods-list {
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;
min-width: 0;
}
.goods-title-row {
display: flex;
align-items: center;
line-height: 1.4;
}
.shop-type-tag {
font-size: 18rpx;
padding: 0 8rpx;
border-radius: 4rpx;
margin-right: 8rpx;
color: #fff;
flex-shrink: 0;
line-height: 28rpx;
}
.tag-tmall {
background: #ff0036;
}
.tag-taobao {
background: #ff7800;
}
.g-title-text {
font-size: 26rpx;
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: 22rpx;
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;
}
.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;
}
</style> </style>