chore:新增商品分类模板5

This commit is contained in:
2026-09-18 13:53:47 +08:00
parent 1b1704f7c6
commit a3d2ee562e
4 changed files with 322 additions and 31 deletions

View File

@@ -122,7 +122,7 @@
{ select: select == index },
{ 'border-bottom': value.template == 4 && select + 1 === index },
{ 'border-top': value.template == 4 && select - 1 === index },
{ 'first-category-item': index == 0 && (value.template == 99 || value.template == 1) }
{ 'first-category-item': index == 0 && (value.template == 99 || value.template == 1 || value.template == 5) }
]" @tap.stop="switchOneCategory(index)">
<view class="">{{ item.category_name }}</view>
</view>
@@ -152,11 +152,30 @@
<diy-category-item :category="item" :value="value" ref="categoryItem" :index="index"
:select="select" :oneCategorySelect="oneCategorySelect" :isList="isList"
@tologin="toLogin" @selectsku="selectSku($event, index)" @addCart="addCartPoint"
@saveSecondCategory="saveSecondCategoryName"></diy-category-item>
@saveSecondCategory="saveSecondCategoryName"> </diy-category-item>
</view>
</scroll-view>
</scroll-view>
<scroll-view scroll-y="true" class="content-wrap" v-else-if="value.template == 99 || loadType == 'all'"
<!-- 模板5: 左侧分类树 + 右侧纵向平铺"全部分类"(每个一级分类: 标题 + 商品网格)
与模板1 的核心区别: 模板1 一次只渲染选中的那个分类(display 切换),
模板5 把全部分类按顺序纵向平铺; 左侧点击分类用 scroll-into-view 定位,
滚动时由 listenScroll 反推并高亮左侧分类 -->
<scroll-view scroll-y="true" class="content-wrap" v-else-if="value.template == 5"
ref="contentWrap" :scroll-into-view="categoryId" :scroll-with-animation="true"
:refresher-enabled="true" refresher-default-style="none"
:refresher-triggered="triggered" @refresherrefresh="onRefresh" @refresherrestore="onRestore"
@scroll="listenScroll" @touchstart="touchStart">
<view class="child-category" v-for="(item, index) in categoryTree" :key="index"
:id="'category-' + index">
<diy-category-item :category="item" :value="value" ref="categoryItem" :index="index"
:select="select" :oneCategorySelect="oneCategorySelect" :isList="isList"
@tologin="toLogin" @selectsku="selectSku($event, index)" @addCart="addCartPoint"
@loadfinish="getHeightArea" @saveSecondCategory="saveSecondCategoryName"></diy-category-item>
</view>
<view class="end-tips" ref="endTips" :style="{ opacity: endTips }">{{ $lang('components-diy.diy-category.reachedBottom') }}</view>
</scroll-view>
<scroll-view scroll-y="true" class="content-wrap" v-else-if="value.template == 99 || loadType == 'all'"
ref="contentWrap" :scroll-into-view="categoryId" :scroll-with-animation="true"
@scroll="listenScroll" @touchstart="touchStart" :refresher-enabled="true"
refresher-default-style="none" :refresher-triggered="triggered" @refresherrefresh="onRefresh"
@@ -308,6 +327,7 @@ export default {
})
.exec();
if (this.value.template == 1) this.getHeightArea(-1);
if (this.value.template == 5) this.getHeightArea(-1);
}, 500);
},
watch: {
@@ -317,6 +337,9 @@ export default {
if (nval === false && oval === true) {
this.$nextTick(() => {
if (!this.heightArea.length) this.getHeightArea(-1);
// 分类渲染完成后重新对齐到当前选中的一级分类顶部,
// 避免首屏第一个分类的标题被顶出可视区
if (this.categoryTree && this.categoryTree.length) this.alignToCategory(this.select);
});
}
}
@@ -536,8 +559,30 @@ export default {
switchOneCategory(index) {
if (index >= this.categoryTree.length) return;
this.select = index;
this.categoryId = 'category-' + index;
this.scrollLock = true;
this.alignToCategory(index);
},
/**
* 把右侧滚动区定位到指定一级分类的顶部
*
* uni-app 只在 scroll-into-view 的值"发生变化"时才重新滚动,
* 而 categoryId 的初值就是 'category-0', 且只有点击左侧分类才会被改写;
* 用户在右侧手动滚动后 categoryId 仍是 'category-0', 此时再点第一个分类(index 0)
* 值时没有变化, 右侧不会回滚到该分类, 该分类的标题就被顶出可视区
* (看起来像"标题丢了 / 卡片被切了一半"), 而点其它分类因为值变了所以都正常。
* 这里先置空、下一帧再设置目标 id, 保证每次点击都能重新定位到分类顶部。
* @param {Number} index 一级分类下标
*/
alignToCategory(index) {
const target = 'category-' + index;
if (this.categoryId === target) {
this.categoryId = '';
this.$nextTick(() => {
this.categoryId = target;
});
} else {
this.categoryId = target;
}
},
saveSecondCategoryName(name) {
this.lastSecondCategoryName = name;
@@ -559,7 +604,10 @@ export default {
break;
}
}
if (this.value.template != 1 && this.value.loadType == 'all' && this.heightArea[this.select][1] -
// 模板5 渲染的是分类网格(静态), 不需要懒加载商品; 这里只保留 loadType=all 的懒加载,
// 并补上 heightArea[this.select] 越界保护
if (this.value.template != 1 && this.value.loadType == 'all' &&
this.heightArea[this.select] && this.heightArea[this.select][1] -
scrollTop - contentWrapHeight < 300) {
if (Array.isArray(this.$refs.categoryItem) && this.$refs.categoryItem[this.select]) this.$refs.categoryItem[this.select].getGoodsList();
}
@@ -1674,6 +1722,134 @@ export default {
}
}
// ===================== 模板5 商品分类样式(新增: 基于模板1双栏布局) =====================
.category-template-5 {
.search-box {
padding: 20rpx 24rpx;
background: #fff;
.search-content {
background-color: #f5f5f5;
border-radius: 40rpx;
input {
background: #f5f5f5;
border-radius: 40rpx;
padding: 0 30rpx;
font-size: 26rpx;
color: #333;
}
.iconfont {
right: 16rpx;
color: #89899a;
font-size: 32rpx;
}
}
}
.content-box {
// 模板5 + 三级分类: 标题行所在整片右半边去掉白色, 与模板1一致
background: transparent;
.tree-wrap {
width: 170rpx;
background-color: #fff;
}
.right-flex-wrap {
background: #f5f5f5;
.content-wrap {
background: transparent;
}
// 模板5 纵向平铺: 每个一级分类独占一行(与模板99"全部分类"结构一致)
.child-category {
width: 100%;
box-sizing: border-box;
}
}
}
// 穿透到子组件 diy-category-item: 调整 banner 横向内边距 + 分类网格容器为透明
::v-deep .category-adv {
padding: 0 20rpx;
margin-top: 0;
}
// 模板5: .category-list 直接沿用子组件的 legacy 白底卡片样式(不再覆盖为透明)
// 穿透到子组件 diy-category-item: 模板5标题行定高, 与左侧第一个一级分类等高对齐
::v-deep .category-title-with-lines {
height: 100rpx;
box-sizing: border-box;
padding: 30rpx 0 20rpx;
}
// 模板5: 左侧第一个一级分类定高, 与右侧标题行垂直对齐
.tree-wrap .category-item.first-category-item {
height: 100rpx;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
white-space: nowrap;
overflow: hidden;
view {
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
// 模板5: 分类网格的 .img-box / .name 直接沿用子组件 legacy 尺寸(80% + 名称),
// 不再做 70%/透明 覆盖, 以与 Branch_5cfee417 的商品分类保持一致
// 左侧分类栏样式
.tree-wrap .category-item {
padding: 28rpx 16rpx;
background-color: var(--diy-category-tree-normal-bg-color, #f5f5f5);
border-radius: 0;
view {
color: var(--diy-category-tree-normal-text-color, #222222);
font-size: 26rpx;
line-height: 1.3;
}
&.border-top,
&.border-bottom {
border-radius: 0;
}
&.select {
background: var(--diy-category-tree-select-bg-color, #fff);
view {
color: var(--diy-category-tree-select-text-color, #333);
font-weight: bold;
font-size: 28rpx;
}
&::before {
content: ' ';
width: 6rpx;
height: 32rpx;
background: var(--base-color, #FF6B35);
display: block;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
border-radius: 0 6rpx 6rpx 0;
}
}
}
}
// ===================== 模板99 商品分类样式 =====================
.category-template-99 {
.search-box {