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

@@ -4,12 +4,13 @@
slide=滑动时显示(默认) / always=始终显示 / never=永不显示
小程序端: show-scrollbar 仅在 enhanced=true 时生效, 所以两者同步绑定 -->
<scroll-view :class="['image-nav', value.showStyle == 'fixed' ? 'fixed-layout' : value.showStyle, scrollBarClass]"
:style="imageSpacingStyle"
:scroll-x="value.showStyle == 'singleSlide'"
:show-scrollbar="scrollBarMode != 'never'"
:enhanced="scrollBarMode != 'never'">
<view class="uni-scroll-view-content">
<view v-for="(item, index) in value.list" :key="index" :class="['image-nav-item', value.mode]"
style="margin-right: 28rpx;">
:style="imageItemStyle">
<!-- 图片部分 -->
<view v-if="value.mode != 'text'" class="image-img" :style="{
'font-size': (value.imageSize * 2 + 'rpx') + ';',
@@ -199,6 +200,112 @@ export default {
const cls = ['scrollbar-' + this.scrollBarMode];
if (this.scrollBarMode == 'slide' && this.slideScrolling) cls.push('is-scrolling');
return cls;
},
// ========== PR-FRONTEND-DIY-IMAGE-NAV-SPACING (2026-09-18): 图片自定义间距 ==========
// 后台"滑动图片"组件新增 3 项间距配置:
// 1) 图片横向间距: 相邻图片项之间的横向间隔
// 2) 图片上间距 : 图片区域内侧的上内边距
// 3) 图片下间距 : 图片区域内侧的下内边距
// 单位: 按项目惯例(与商品 goodsMarginNum 一致)换算 rpx = 后台数值 × 2
// 字段名兼容: 后台各端命名未统一, 这里对常见命名做归一化匹配(忽略大小写/下划线/中划线),
// 并向下探测 value.imageSpacing / value.margin / value.padding 等嵌套容器,
// 保证后端用哪种命名都能生效。
// 兜底: 字段缺失/非法时返回 null, 由 imageSpacingStyle / imageItemStyle 回退历史视觉
// (横向 28rpx, 上/下沿用 CSS 的 16rpx), 老装修数据不受影响。
imageSpacingConfig() {
const v = this.value || {};
const RATIO = 2; // 后台数值 → rpx 换算比例
const norm = k => String(k).toLowerCase().replace(/[\s_-]/g, '');
// 非数字(如 'diy'/枚举)或空值 → null, 交给兜底
const toRpx = val => {
if (val === undefined || val === null || val === '') return null;
const n = Number(val);
if (isNaN(n)) return null;
return Math.max(0, n) * RATIO;
};
// 查找源: value 自身 + 常见嵌套容器(顶层优先)
const sources = [v];
['imageSpacing', 'imageSpace', 'spacing', 'space', 'margin', 'padding', 'style', 'config', 'setting']
.forEach(k => {
if (v[k] && typeof v[k] === 'object') sources.push(v[k]);
});
// 三级查找: ① 全源精确名 → ② 全源模糊包含名 → ③ 嵌套容器内的裸键
// (如 imageSpacing: { horizontal: 3, top: 0, bottom: 0 })
const pick = (exact, fuzzy, nested) => {
for (let s = 0; s < sources.length; s++) {
const src = sources[s];
for (const key in src) {
if (exact.indexOf(norm(key)) != -1) {
const rpx = toRpx(src[key]);
if (rpx !== null) return rpx;
}
}
}
for (let s = 0; s < sources.length; s++) {
const src = sources[s];
for (const key in src) {
const k = norm(key);
if (fuzzy.some(f => k.indexOf(f) != -1)) {
const rpx = toRpx(src[key]);
if (rpx !== null) return rpx;
}
}
}
// 裸键(top/bottom/both...)只在嵌套容器内解释, 避免误取顶层同名字段
for (let s = 1; s < sources.length; s++) {
const src = sources[s];
for (const key in src) {
if (nested.indexOf(norm(key)) != -1) {
const rpx = toRpx(src[key]);
if (rpx !== null) return rpx;
}
}
}
return null;
};
return {
// 图片横向间距
horizontal: pick(
['imagemargin', 'imagemarginnum', 'imagespace', 'imagespacenum', 'imagehorizontalspace',
'horizontalspace', 'horizontalspacenum', 'imagegap', 'space', 'spacenum', 'marginnum', 'gap'],
['horizontalspace', 'imagespace', 'imagemargin', 'spacenum', 'marginnum', 'imagegap', 'gap'],
['horizontal', 'horizontalnum', 'lr', 'leftright', 'both', 'bothnum', 'num', 'margin', 'space', 'gap']
),
// 图片上间距
paddingTop: pick(
['imagepaddingtop', 'imagespacingtop', 'imagespacetop', 'imagetopspace', 'paddingtop',
'spacingtop', 'topspace', 'margintop'],
['paddingtop', 'spacingtop', 'topspace', 'margintop'],
['top', 'topnum', 'paddingtop', 'margintop', 'spacetop']
),
// 图片下间距
paddingBottom: pick(
['imagepaddingbottom', 'imagespacingbottom', 'imagespacebottom', 'imagebottomspace', 'paddingbottom',
'spacingbottom', 'bottomspace', 'marginbottom'],
['paddingbottom', 'spacingbottom', 'bottomspace', 'marginbottom'],
['bottom', 'bottomnum', 'paddingbottom', 'marginbottom', 'spacebottom']
)
};
},
// 图片区域上/下内边距(作用在滚动容器上); 未配置时不输出内联样式, 沿用 CSS padding
imageSpacingStyle() {
const cfg = this.imageSpacingConfig;
let style = '';
if (cfg.paddingTop !== null) style += 'padding-top:' + cfg.paddingTop + 'rpx;';
if (cfg.paddingBottom !== null) style += 'padding-bottom:' + cfg.paddingBottom + 'rpx;';
return style;
},
// 图片项之间的横向间距; 未配置时回退原写死的 28rpx
imageItemStyle() {
const horizontal = this.imageSpacingConfig.horizontal;
return 'margin-right:' + (horizontal === null ? 28 : horizontal) + 'rpx;';
}
},
methods: {