chore:商品分类页面符合template==1

This commit is contained in:
2026-07-17 09:58:25 +08:00
parent 94e852032b
commit e3bbb7c77a
3 changed files with 244 additions and 37 deletions

View File

@@ -139,11 +139,15 @@ const localDevConfig = ({
uniacid: 48,
domain: 'https://test.aigc-quickapp.com',
},
'72': { // 测试平台
uniacid: 72,
domain: 'https://test.aigc-quickapp.com',
},
// })['5g-237']; // 商品分类,没有立即咨询文字
// })['5g-97']; // 大宗商品贸易,支持自定义字体大小、颜色
// })['5g-50']; // 燃气安全产品机器人,购物车无反应
// })['2821']; // 离型纸硅油纸
})['48']; // 离型纸硅油纸
})['72']; // 离型纸硅油纸
// })['2485']; // 验证电子表单前后端数据一致性
// })['5g-11']; // 数码
// })['5g-213']; // 选择要使用的环境配置

View File

@@ -45,27 +45,27 @@
</view>
</block>
<block v-else-if="value.level == 2">
<view class="category-title">{{ category.category_name }}</view>
<block v-else-if="categoryLevel == 2">
<view :class="['category-title', value.template == 1 ? 'category-title-with-lines' : '']">{{ category.category_name }}</view>
<view class="category-list">
<view class="category-item" v-for="(one, oneIndex) in category.child_list" :key="oneIndex"
@tap.stop="$util.redirectTo('/pages_goods/list', { category_id: one.category_id })">
<view class="img-box">
<image :src="$util.img(one.image)" mode="widthFix" show-menu-by-longpress />
<image :src="categoryImg(one.image)" mode="aspectFit" @error="categoryImgError(2, oneIndex, -1)" show-menu-by-longpress />
</view>
<view class="name">{{ one.category_name }}</view>
</view>
</view>
</block>
<block v-else-if="value.level == 3">
<block v-else-if="categoryLevel == 3">
<block v-for="(one, oneIndex) in category.child_list" :key="oneIndex">
<view class="category-title">{{ one.category_name }}</view>
<view :class="['category-title', value.template == 1 ? 'category-title-with-lines' : '']">{{ one.category_name }}</view>
<view class="category-list">
<view class="category-item" v-for="(two, twoIndex) in one.child_list" :key="twoIndex"
@tap.stop="$util.redirectTo('/pages_goods/list', { category_id: two.category_id })">
<view class="img-box">
<image :src="$util.img(two.image)" mode="widthFix" :lazy-load="true" show-menu-by-longpress />
<image :src="categoryImg(two.image)" mode="aspectFit" @error="categoryImgError(3, oneIndex, twoIndex)" show-menu-by-longpress />
</view>
<view class="name">{{ two.category_name }}</view>
</view>
@@ -369,6 +369,32 @@ export default {
secondCategoryGoodsList: []
};
},
computed: {
/**
* 当前分类层级 (参考 template 2 的 goodsLevel 模式)
* 优先级: 数据层级 > 后台配置 > 兜底
* 1. 先检测数据实际支持几级 (二级分类下是否还有 child_list)
* 2. 后台配置的 level 不能超过数据支持的层级
* (数据只有 2 级时,就算后台配 3 也强制用 2,避免出现空标题列表)
* 3. 都没配置就按数据层级来
*/
categoryLevel() {
// 先检测数据层级
let dataLevel = 2; // 兜底
if (this.category && this.category.child_list && this.category.child_list.length > 0) {
const hasThirdLevel = this.category.child_list.some(item =>
item.child_list && item.child_list.length > 0
);
dataLevel = hasThirdLevel ? 3 : 2;
}
// 后台配置: 不能超过数据支持的层级
if (this.value.level && this.value.level <= dataLevel) {
return this.value.level;
}
// 否则按数据层级
return dataLevel;
}
},
created() {
this.type = this.value.template == 1 || this.value.template == 99 ? 'category' : 'goods';
if (this.index == this.select && this.pageIndex == 0) this.getGoodsList();
@@ -559,6 +585,23 @@ export default {
}) :
this.$util.getDefaultImage().goods;
},
/**
* 分类图片处理
* @param {Object} imgStr
*/
categoryImg(imgStr) {
if (!imgStr) return this.$util.getDefaultImage().goods;
return this.$util.img(imgStr);
},
categoryImgError(level, oneIndex, twoIndex) {
// 分类图片加载失败处理
if (level == 2 && this.category.child_list && this.category.child_list[oneIndex]) {
this.category.child_list[oneIndex].image = '';
} else if (level == 3 && this.category.child_list && this.category.child_list[oneIndex]
&& this.category.child_list[oneIndex].child_list && this.category.child_list[oneIndex].child_list[twoIndex]) {
this.category.child_list[oneIndex].child_list[twoIndex].image = '';
}
},
imgError(index) {
this.goodsList[index].goods_image = this.$util.getDefaultImage().goods;
},
@@ -963,6 +1006,29 @@ export default {
}
}
// 模板1 专用: 标题居中 + 两侧横线
.category-title-with-lines {
display: flex !important;
align-items: center;
justify-content: center;
text-align: center;
padding: 30rpx 0 20rpx !important;
padding-left: 0 !important;
color: #333;
font-size: 30rpx;
font-weight: 500;
letter-spacing: 2rpx;
&::before,
&::after {
content: '';
flex: 0 0 60rpx;
height: 0;
border-top: 1rpx solid #d9d9d9;
margin: 0 24rpx;
}
}
.category-adv {
width: 100%;
overflow: hidden;
@@ -976,36 +1042,41 @@ export default {
}
.category-list {
display: flex;
flex-wrap: wrap;
background: #fff;
display: grid !important;
grid-template-columns: repeat(3, 1fr) !important;
background: transparent;
margin: 0 20rpx;
border-radius: 10rpx;
padding: 10rpx 0;
border-radius: 0;
padding: 0;
gap: 20rpx 0;
.category-item {
width: 33.33%;
width: 100% !important;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 16rpx;
padding: 0;
box-sizing: border-box;
.img-box {
width: 80%;
padding-top: 80%;
width: 70% !important;
height: 0;
padding-bottom: 70%;
margin: 0 auto;
overflow: hidden;
margin-bottom: 20rpx;
margin-bottom: 16rpx;
position: relative;
background: transparent !important;
border-radius: 0 !important;
image {
position: absolute;
width: 100%;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 100% !important;
height: 100% !important;
left: 0 !important;
top: 0 !important;
transform: none !important;
}
}

View File

@@ -102,23 +102,36 @@
:lastSecondCategoryName="lastSecondCategoryName"
@tologin="toLogin" @selectsku="selectSku($event, 0)" @addCart="addCartPoint"
@saveSecondCategory="saveSecondCategoryName"></diy-category-item>
</scroll-view>
</scroll-view>
<scroll-view scroll-y="true" class="content-wrap" v-else-if="value.template == 1 || 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"
@refresherrestore="onRestore">
<view class="child-category" v-for="(item, index) in categoryTree" :key="index"
:id="'category-' + index" :style="{ display: value.template == 99 && select != index ? 'none' : 'block' }">
<diy-category-item :category="item" :value="value" ref="categoryItem" :index="index"
:select="select" :oneCategorySelect="oneCategorySelect" :isList="isList"
:lastSecondCategoryName="value.template == 99 ? lastSecondCategoryName : ''"
@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>
<!-- 模板1: 仿京东/淘宝商品分类 - 按 template 2 的 part-load 逻辑, 切换一级分类时只渲染选中分类的子分类网格 -->
<scroll-view scroll-y="true" class="content-wrap" v-else-if="value.template == 1"
:refresher-enabled="true" refresher-default-style="none"
:refresher-triggered="triggered" @refresherrefresh="onRefresh" @refresherrestore="onRestore">
<view class="child-category-wrap" v-for="(item, index) in categoryTree" :key="index"
:id="'category-' + index" :style="{ display: select == index ? 'block' : 'none' }">
<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>
</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"
@refresherrestore="onRestore">
<view class="child-category" v-for="(item, index) in categoryTree" :key="index"
:id="'category-' + index" :style="{ display: value.template == 99 && select != index ? 'none' : 'block' }">
<diy-category-item :category="item" :value="value" ref="categoryItem" :index="index"
:select="select" :oneCategorySelect="oneCategorySelect" :isList="isList"
:lastSecondCategoryName="value.template == 99 ? lastSecondCategoryName : ''"
@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>
<view class="content-wrap"
v-if="(value.template == 2 || value.template == 3 || value.template == 4) && loadType == 'part'">
@@ -1135,6 +1148,125 @@ export default {
}
}
// ===================== 模板1 仿京东/淘宝商品分类样式 =====================
.category-template-1 {
.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 {
background: #fff;
.tree-wrap {
width: 170rpx;
background-color: #fff;
}
.right-flex-wrap {
background: #fff;
.content-wrap {
background: #fff;
}
}
}
// 穿透到子组件 diy-category-item: 调整 banner 横向内边距 + 分类网格容器为透明
::v-deep .category-adv {
padding: 0 20rpx;
margin-top: 0;
}
::v-deep .category-list {
margin: 0 20rpx;
border-radius: 0;
background: transparent;
padding: 0;
}
::v-deep .category-title-with-lines {
padding: 30rpx 0 20rpx;
}
// 穿透修复: 图片不需要灰色背景框,与目标图保持一致
::v-deep .img-box {
background: transparent !important;
border-radius: 0 !important;
width: 70% !important;
padding-bottom: 70% !important;
margin-bottom: 16rpx !important;
}
::v-deep .img-box image {
width: 100% !important;
height: 100% !important;
left: 0 !important;
top: 0 !important;
transform: none !important;
}
// 左侧分类栏样式
.tree-wrap .category-item {
padding: 28rpx 16rpx;
background-color: #fff;
border-radius: 0;
view {
color: #666;
font-size: 26rpx;
line-height: 1.3;
}
&.border-top,
&.border-bottom {
border-radius: 0;
}
&.select {
background: #fff;
view {
color: var(--base-color, #FF6B35);
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 {