From cf2da3b2a63840888815c6a81cbd7948faf93533 Mon Sep 17 00:00:00 2001
From: doum <doum>
Date: 星期一, 08 六月 2026 17:41:15 +0800
Subject: [PATCH] aaa
---
h5/pages/index_3/index.vue | 513 ++++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 438 insertions(+), 75 deletions(-)
diff --git a/h5/pages/index_3/index.vue b/h5/pages/index_3/index.vue
index c748635..7a01d06 100644
--- a/h5/pages/index_3/index.vue
+++ b/h5/pages/index_3/index.vue
@@ -236,22 +236,41 @@
<text>{{ sub.name }}</text>
</view>
</view>
- <view class="expand_search_wrap">
+ <view class="expand_search_wrap" :style="suggestDropdownTheme">
<view class="expand_search" :style="searchBarStyle">
<image class="search_icon" src="@/static/ic_search@2x.png" mode="aspectFit"></image>
- <input type="text" v-model="row.modelVal" placeholder="鎼滅储鍟嗗搧鍚嶇О/鍨嬪彿" @input="searchModel(row)" />
+ <view class="search_divider"></view>
+ <input type="text" v-model="row.modelVal" placeholder="鎼滅储鍟嗗搧鍚嶇О/鍨嬪彿" placeholder-class="expand_search_placeholder" @input="searchModel(row)" />
</view>
- <view class="model_suggest_list" v-if="hasModelKeyword(row) && modelOptions(row).length">
- <view
- class="model_suggest_item"
- v-for="(g, gi) in modelOptions(row)"
- :key="g.id || gi"
- @click.stop="onClickSound(() => selectGoodsFromSearch(index, g))"
- @mouseenter="playHoverSound">
- {{ g.name }}
+ <view class="model_suggest_panel" v-if="hasModelKeyword(row) && modelOptions(row).length">
+ <view class="model_suggest_list">
+ <view
+ class="model_suggest_item"
+ v-for="(g, gi) in modelOptions(row)"
+ :key="g.id || gi"
+ @click.stop="onClickSound(() => selectGoodsFromSearch(index, g))"
+ @mouseenter="playHoverSound">
+ <view class="model_suggest_thumb">
+ <image v-if="suggestGoodsImg(g)" :src="suggestGoodsImg(g)" mode="aspectFit"></image>
+ <view v-else class="model_suggest_thumb_ph"></view>
+ </view>
+ <view class="model_suggest_body">
+ <text class="model_suggest_name">{{ g.name }}</text>
+ <text class="model_suggest_brand" v-if="g.brandName">{{ g.brandName }}</text>
+ </view>
+ <view class="model_suggest_meta">
+ <text class="model_suggest_price" v-if="g.price != null && g.price !== ''">楼{{ g.price }}</text>
+ <text class="model_suggest_zd" v-if="g.zdPrice != null && g.zdPrice !== ''">鏃楄埌 楼{{ g.zdPrice }}</text>
+ </view>
+ </view>
+ </view>
+ <view class="model_suggest_footer">
+ <text>鍏� {{ modelOptions(row).length }} 浠跺彲閫�</text>
</view>
</view>
- <view class="model_suggest_empty" v-else-if="hasModelKeyword(row)">鏆傛棤鍖归厤鍟嗗搧</view>
+ <view class="model_suggest_empty" v-else-if="hasModelKeyword(row)">
+ <text class="model_suggest_empty_text">鏈壘鍒般�寋{ (row.modelVal || '').trim() }}銆嶇浉鍏冲晢鍝�</text>
+ </view>
</view>
</view>
</view>
@@ -266,12 +285,12 @@
<view class="product_grid">
<view
class="product_card"
- v-for="(item, pi) in displayProducts"
+ v-for="(item, pi) in visibleProducts"
:key="item.id || pi"
@click="onClickSound(() => clickProduct(item))"
@mouseenter="playHoverSound">
<view class="product_card_img">
- <image :src="productImg(item)" mode="aspectFit"></image>
+ <image :src="productImg(item)" mode="aspectFit" lazy-load></image>
</view>
<view class="product_card_info">
<text class="product_brand">{{ item.brandName || '' }}</text>
@@ -279,8 +298,20 @@
<text class="product_price_label">鎸囧浠� 楼 {{ item.price || '' }}</text>
</view>
</view>
- <view class="product_card placeholder" v-if="!displayProducts.length">
+ <view class="product_card placeholder" v-if="!visibleProducts.length && !productLoadingMore">
<text>鏆傛棤鍟嗗搧</text>
+ </view>
+ </view>
+ <view class="product_list_footer" v-if="productTotalCount > 0">
+ <view class="product_load_hint" v-if="productLoadingMore">
+ <view class="product_load_spinner"></view>
+ <text>鍔犺浇涓�...</text>
+ </view>
+ <view class="product_load_hint" v-else-if="hasMoreProducts">
+ <text>宸叉樉绀� {{ visibleProducts.length }} / {{ productTotalCount }}锛岀户缁笂婊戝姞杞芥洿澶�</text>
+ </view>
+ <view class="product_load_hint product_load_hint--done" v-else>
+ <text>宸插姞杞藉叏閮� {{ productTotalCount }} 浠跺晢鍝�</text>
</view>
</view>
</view>
@@ -481,6 +512,7 @@
const DEFAULT_MAIN = '#E8DCC8'
const DEFAULT_HEADER = '#4A3728'
const DEFAULT_ROW = '#FFFFFF'
+const PRODUCT_PAGE_SIZE = 30
export default {
components: { search, bigImg },
@@ -526,6 +558,8 @@
shopPageData: [],
shopPageDataSou: [],
+ productPageNo: 1,
+ productLoadingMore: false,
shopPageBrand: { id: '', name: '' },
brandData: [],
title: '',
@@ -585,7 +619,26 @@
return { background: t.rowBg || DEFAULT_ROW }
},
dropdownStyle() {
- return { background: this.themeStyle.background }
+ const { background, color } = this.themeStyle
+ const accent = this.accentColor || '#FFD88A'
+ return {
+ background,
+ color,
+ '--picker-accent': accent,
+ '--picker-hover-bg': 'rgba(255, 255, 255, 0.14)',
+ '--picker-active-bg': this.hexToRgba(accent, 0.28),
+ '--picker-divider': 'rgba(255, 255, 255, 0.12)'
+ }
+ },
+ suggestDropdownTheme() {
+ const { background } = this.themeStyle
+ const accent = this.accentColor || '#FFD88A'
+ return {
+ '--suggest-theme': background,
+ '--suggest-accent': accent,
+ '--suggest-accent-soft': this.hexToRgba(accent, 0.22),
+ '--suggest-theme-soft': this.hexToRgba(background, 0.08)
+ }
},
searchBarStyle() {
const s = (this.configuration && this.configuration.search) || {}
@@ -659,6 +712,16 @@
displayProducts() {
return Array.isArray(this.shopPageDataSou) ? this.shopPageDataSou : []
},
+ productTotalCount() {
+ return this.displayProducts.length
+ },
+ visibleProducts() {
+ const end = this.productPageNo * PRODUCT_PAGE_SIZE
+ return this.displayProducts.slice(0, end)
+ },
+ hasMoreProducts() {
+ return this.visibleProducts.length < this.productTotalCount
+ },
productListCategoryImg() {
const row = this.activeRowIndex >= 0 ? this.shopList[this.activeRowIndex] : null
return (row && row.categoryImgurl) ? row.categoryImgurl : ''
@@ -708,6 +771,33 @@
this.sessionCreateTime = new Date()
this.loadAllData()
},
+
+ onReachBottom() {
+ this.tryLoadMoreProducts()
+ },
+
+ mounted() {
+ if (typeof window !== 'undefined') {
+ this._onProductScroll = () => {
+ if (this.status !== 1 || !this.hasMoreProducts) return
+ const doc = document.documentElement
+ const scrollTop = doc.scrollTop || document.body.scrollTop || 0
+ const viewHeight = doc.clientHeight || window.innerHeight
+ const scrollHeight = doc.scrollHeight || document.body.scrollHeight
+ if (scrollTop + viewHeight >= scrollHeight - 100) {
+ this.tryLoadMoreProducts()
+ }
+ }
+ window.addEventListener('scroll', this._onProductScroll, { passive: true })
+ }
+ },
+
+ beforeDestroy() {
+ if (typeof window !== 'undefined' && this._onProductScroll) {
+ window.removeEventListener('scroll', this._onProductScroll)
+ }
+ },
+
methods: {
playHoverSound,
playClickSound,
@@ -992,6 +1082,11 @@
return row.modelSearchList || []
},
+ suggestGoodsImg(g) {
+ if (!g || !g.imgurl) return ''
+ return (g.prefixUrl || '') + g.imgurl
+ },
+
selectGoodsFromSearch(index, goods) {
this.applyGoodsToRow(index, goods)
this.hoverRowIndex = -1
@@ -1104,6 +1199,7 @@
if (!row) {
this.shopPageData = []
this.shopPageDataSou = []
+ this.resetProductPagination()
return
}
const list = filterGoods(this.allGoods, {
@@ -1136,9 +1232,24 @@
const kw = (this.title || '').trim()
if (!kw) {
this.shopPageDataSou = source.slice()
- return
+ } else {
+ this.shopPageDataSou = source.filter(item => matchKeyword(item, kw))
}
- this.shopPageDataSou = source.filter(item => matchKeyword(item, kw))
+ this.resetProductPagination()
+ },
+
+ resetProductPagination() {
+ this.productPageNo = 1
+ this.productLoadingMore = false
+ },
+
+ tryLoadMoreProducts() {
+ if (this.status !== 1 || !this.hasMoreProducts || this.productLoadingMore) return
+ this.productLoadingMore = true
+ this.$nextTick(() => {
+ this.productPageNo += 1
+ this.productLoadingMore = false
+ })
},
clickProduct(item) {
@@ -1423,6 +1534,7 @@
this.hoverRowIndex = -1
this.resetPkState()
this.title = ''
+ this.resetProductPagination()
this.shopPageData = []
this.shopPageDataSou = []
this.loadOrderNo()
@@ -1437,6 +1549,7 @@
this.status = 0
this.title = ''
this.showBrandPicker = false
+ this.resetProductPagination()
this.shopPageData = []
this.shopPageDataSou = []
this.activeRowIndex = -1
@@ -1935,41 +2048,76 @@
}
}
-.home_top_section .category_picker {
- position: absolute;
- top: calc(100% + 2px);
- left: -26px;
- min-width: 168px;
- z-index: 20;
- max-height: 240px;
- overflow-y: auto;
- border-radius: 0 0 6px 6px;
- padding: 6px 0;
- box-shadow: 0 8px 20px rgba(0, 0, 0, 0.22);
+.home_top_section .category_picker {
+ position: absolute;
+ top: calc(100% + 6px);
+ left: -26px;
+ min-width: 188px;
+ z-index: 20;
+ max-height: 260px;
+ overflow-x: hidden;
+ overflow-y: auto;
+ border-radius: 12px;
+ padding: 0;
+ box-shadow: 0 12px 32px rgba(61, 46, 34, 0.28);
+ border: 1px solid rgba(255, 255, 255, 0.14);
+ backdrop-filter: blur(8px);
+
+ &::-webkit-scrollbar {
+ width: 4px;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ background: rgba(255, 255, 255, 0.28);
+ border-radius: 999px;
+ }
+
+ &::before {
+ content: '';
+ display: block;
+ height: 3px;
+ background: var(--picker-accent, #FFD88A);
+ border-radius: 12px 12px 0 0;
+ }
.category_picker_item {
display: flex;
align-items: center;
gap: 10px;
- padding: 10px 12px;
- color: #fff;
+ padding: 11px 14px;
+ color: inherit;
cursor: pointer;
- border-radius: 0;
+ border-bottom: 1px solid var(--picker-divider, rgba(255, 255, 255, 0.12));
+ transition: background 0.15s;
+
+ &:last-child {
+ border-bottom: none;
+ }
&:hover {
- background: rgba(255, 255, 255, 0.1);
+ background: var(--picker-hover-bg, rgba(255, 255, 255, 0.14));
}
image {
- width: 28px;
- height: 28px;
+ width: 30px;
+ height: 30px;
+ border-radius: 6px;
+ background: rgba(255, 255, 255, 0.12);
+ padding: 2px;
+ box-sizing: border-box;
+ }
+
+ text {
+ font-size: 13px;
+ font-weight: 500;
+ line-height: 1.3;
}
}
.category_picker_empty {
- padding: 16px;
+ padding: 20px 16px;
text-align: center;
- color: rgba(255, 255, 255, 0.7);
+ color: rgba(255, 255, 255, 0.72);
font-size: 13px;
}
}
@@ -2098,26 +2246,71 @@
.brand_picker {
position: absolute;
- top: calc(100% + 4px);
+ top: calc(100% + 6px);
right: 0;
- min-width: 120px;
- max-height: 220px;
+ min-width: 136px;
+ max-height: 240px;
+ overflow-x: hidden;
overflow-y: auto;
- border-radius: 8px;
- padding: 6px 0;
- box-shadow: 0 8px 20px rgba(0, 0, 0, 0.22);
+ border-radius: 12px;
+ padding: 0;
+ box-shadow: 0 12px 32px rgba(61, 46, 34, 0.28);
+ border: 1px solid rgba(255, 255, 255, 0.14);
z-index: 20;
+ backdrop-filter: blur(8px);
+
+ &::-webkit-scrollbar {
+ width: 4px;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ background: rgba(255, 255, 255, 0.28);
+ border-radius: 999px;
+ }
+
+ &::before {
+ content: '';
+ display: block;
+ height: 3px;
+ background: var(--picker-accent, #FFD88A);
+ border-radius: 12px 12px 0 0;
+ }
.brand_picker_item {
- padding: 10px 14px;
+ padding: 11px 16px;
font-size: 13px;
- color: #fff;
+ font-weight: 500;
+ color: inherit;
cursor: pointer;
white-space: nowrap;
+ border-bottom: 1px solid var(--picker-divider, rgba(255, 255, 255, 0.12));
+ transition: background 0.15s;
- &:hover,
+ &:last-child {
+ border-bottom: none;
+ }
+
+ &:hover {
+ background: var(--picker-hover-bg, rgba(255, 255, 255, 0.14));
+ }
+
&.active {
- background: rgba(255, 255, 255, 0.12);
+ background: var(--picker-active-bg, rgba(255, 216, 138, 0.28));
+ font-weight: 600;
+ position: relative;
+ padding-left: 22px;
+
+ &::before {
+ content: '';
+ position: absolute;
+ left: 10px;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 4px;
+ height: 4px;
+ border-radius: 50%;
+ background: var(--picker-accent, #FFD88A);
+ }
}
}
}
@@ -2431,6 +2624,14 @@
gap: 10px;
border-radius: 24px;
padding: 10px 16px;
+ border: 1px solid rgba(74, 55, 40, 0.1);
+ box-shadow: 0 2px 12px rgba(74, 55, 40, 0.08);
+ transition: box-shadow 0.2s, border-color 0.2s;
+
+ &:focus-within {
+ border-color: var(--suggest-theme, rgba(74, 55, 40, 0.22));
+ box-shadow: 0 4px 16px var(--suggest-theme-soft, rgba(74, 55, 40, 0.1));
+ }
.search_icon {
width: 14px;
@@ -2441,6 +2642,13 @@
filter: $search-icon-filter;
}
+ .search_divider {
+ width: 1px;
+ height: 16px;
+ background: rgba(74, 55, 40, 0.12);
+ flex-shrink: 0;
+ }
+
input {
flex: 1;
font-size: 14px;
@@ -2449,52 +2657,172 @@
}
}
- .model_suggest_empty {
+ .expand_search_placeholder {
+ color: rgba(74, 55, 40, 0.38);
+ font-size: 14px;
+ }
+
+ .model_suggest_panel {
position: absolute;
- top: calc(100% + 4px);
+ top: calc(100% + 6px);
left: 0;
right: 0;
- margin-top: 0;
- padding: 10px 14px;
- font-size: 13px;
- color: #999;
- text-align: center;
+ padding: 8px;
+ border-radius: 16px;
background: #fff;
- border-radius: 8px;
- box-shadow: 0 8px 20px rgba(74, 55, 40, 0.16);
border: 1px solid rgba(74, 55, 40, 0.08);
+ box-shadow:
+ 0 10px 28px rgba(61, 46, 34, 0.14),
+ 0 2px 8px rgba(61, 46, 34, 0.06);
z-index: 20;
}
.model_suggest_list {
- position: absolute;
- top: calc(100% + 4px);
- left: 0;
- right: 0;
- margin-top: 0;
- max-height: 160px;
+ max-height: 204px;
overflow-y: auto;
- border-radius: 8px;
- background: #fff;
- box-shadow: 0 8px 20px rgba(74, 55, 40, 0.16);
- border: 1px solid rgba(74, 55, 40, 0.08);
- z-index: 20;
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+ padding: 2px;
+
+ &::-webkit-scrollbar {
+ width: 4px;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ background: rgba(74, 55, 40, 0.18);
+ border-radius: 999px;
+ }
}
.model_suggest_item {
- padding: 10px 14px;
- font-size: 13px;
- color: $brown;
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 8px 10px;
+ border-radius: 12px;
+ background: $panel-bg;
+ border: 1px solid rgba(74, 55, 40, 0.05);
cursor: pointer;
- border-bottom: 1px solid rgba(74, 55, 40, 0.06);
-
- &:last-child {
- border-bottom: none;
- }
+ transition: background 0.15s, border-color 0.15s, box-shadow 0.15s, transform 0.15s;
&:hover {
- background: rgba(255, 255, 255, 0.6);
+ background: #fff;
+ border-color: var(--suggest-accent, rgba(255, 216, 138, 0.85));
+ box-shadow: 0 3px 10px var(--suggest-accent-soft, rgba(255, 216, 138, 0.28));
+ transform: translateY(-1px);
}
+
+ &:active {
+ transform: translateY(0);
+ }
+ }
+
+ .model_suggest_thumb {
+ width: 38px;
+ height: 38px;
+ flex-shrink: 0;
+ border-radius: 10px;
+ background: #fff;
+ border: 1px solid rgba(74, 55, 40, 0.06);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+
+ image {
+ width: 34px;
+ height: 34px;
+ }
+ }
+
+ .model_suggest_thumb_ph {
+ width: 18px;
+ height: 18px;
+ border-radius: 4px;
+ background: rgba(74, 55, 40, 0.08);
+ }
+
+ .model_suggest_body {
+ flex: 1;
+ min-width: 0;
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+ }
+
+ .model_suggest_name {
+ font-size: 13px;
+ font-weight: 600;
+ color: $brown;
+ line-height: 1.3;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .model_suggest_brand {
+ font-size: 11px;
+ color: rgba(74, 55, 40, 0.42);
+ line-height: 1.2;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .model_suggest_meta {
+ flex-shrink: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ gap: 2px;
+ min-width: 64px;
+ }
+
+ .model_suggest_price {
+ font-size: 13px;
+ font-weight: 700;
+ color: $orange;
+ line-height: 1.2;
+ }
+
+ .model_suggest_zd {
+ font-size: 10px;
+ color: rgba(74, 55, 40, 0.4);
+ line-height: 1.2;
+ white-space: nowrap;
+ }
+
+ .model_suggest_footer {
+ margin-top: 6px;
+ padding-top: 6px;
+ border-top: 1px solid rgba(74, 55, 40, 0.06);
+ text-align: center;
+
+ text {
+ font-size: 11px;
+ color: rgba(74, 55, 40, 0.38);
+ }
+ }
+
+ .model_suggest_empty {
+ position: absolute;
+ top: calc(100% + 6px);
+ left: 0;
+ right: 0;
+ padding: 16px 14px;
+ text-align: center;
+ background: #fff;
+ border-radius: 14px;
+ box-shadow: 0 8px 20px rgba(61, 46, 34, 0.1);
+ border: 1px dashed rgba(74, 55, 40, 0.12);
+ z-index: 20;
+ }
+
+ .model_suggest_empty_text {
+ font-size: 12px;
+ color: rgba(74, 55, 40, 0.45);
+ line-height: 1.5;
}
.col {
@@ -2636,6 +2964,41 @@
justify-content: center;
}
}
+
+ .product_list_footer {
+ padding: 16px 12px 8px;
+ }
+
+ .product_load_hint {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ padding: 10px 12px;
+ border-radius: 10px;
+ background: rgba(255, 255, 255, 0.72);
+ border: 1px solid rgba(74, 55, 40, 0.08);
+
+ text {
+ font-size: 12px;
+ color: rgba(74, 55, 40, 0.55);
+ line-height: 1.4;
+ }
+
+ &--done text {
+ color: rgba(74, 55, 40, 0.42);
+ }
+ }
+
+ .product_load_spinner {
+ width: 14px;
+ height: 14px;
+ border: 2px solid rgba(74, 55, 40, 0.15);
+ border-top-color: $brown;
+ border-radius: 50%;
+ animation: spin 0.8s linear infinite;
+ flex-shrink: 0;
+ }
}
.pk_page {
--
Gitblit v1.9.3