fix(diy-article): 修复无图文章样式异常,新增字号样式配置
1. 为无图文章项添加no-image类适配样式,统一与有图项的视觉高度 2. 新增标签、摘要、阅读区的字号CSS变量支持,替换硬编码字号 3. 调整列表项间距默认值和swiper行间距,优化布局紧凑度 4. 补充默认字号配置项,兼容老数据缺失字段的情况
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
:display-multiple-items="safeDisplayMultipleItems">
|
:display-multiple-items="safeDisplayMultipleItems">
|
||||||
<swiper-item v-for="(item, index) in list" :key="index" @tap.stop="toDetail(item)">
|
<swiper-item v-for="(item, index) in list" :key="index" @tap.stop="toDetail(item)">
|
||||||
<view class="swiper-item-content">
|
<view class="swiper-item-content">
|
||||||
<view :class="['item', value.ornament && value.ornament.type]" :style="itemStyle">
|
<view :class="['item', value.ornament && value.ornament.type, !item.cover_img && value.style !== 'style-4' ? 'no-image' : '']" :style="itemStyle">
|
||||||
<!-- 封面图:无图时隐藏图位;style-4 纯文字始终不显示 -->
|
<!-- 封面图:无图时隐藏图位;style-4 纯文字始终不显示 -->
|
||||||
<view class="article-img" v-if="item.cover_img && value.style !== 'style-4'">
|
<view class="article-img" v-if="item.cover_img && value.style !== 'style-4'">
|
||||||
<image class="cover-img" :src="$util.img(item.cover_img)" mode="aspectFill"
|
<image class="cover-img" :src="$util.img(item.cover_img)" mode="aspectFill"
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
</swiper>
|
</swiper>
|
||||||
<!-- 非滚动模式(scrollMode==='none')时的普通列表 -->
|
<!-- 非滚动模式(scrollMode==='none')时的普通列表 -->
|
||||||
<template v-if="!useScroll">
|
<template v-if="!useScroll">
|
||||||
<view v-for="(item, index) in list" :key="index" :class="['item', value.ornament && value.ornament.type]" :style="itemStyle"
|
<view v-for="(item, index) in list" :key="index" :class="['item', value.ornament && value.ornament.type, !item.cover_img && value.style !== 'style-4' ? 'no-image' : '']" :style="itemStyle"
|
||||||
@tap.stop="toDetail(item)">
|
@tap.stop="toDetail(item)">
|
||||||
<view class="article-img" v-if="item.cover_img && value.style !== 'style-4'">
|
<view class="article-img" v-if="item.cover_img && value.style !== 'style-4'">
|
||||||
<image class="cover-img" :src="$util.img(item.cover_img)" mode="aspectFill"
|
<image class="cover-img" :src="$util.img(item.cover_img)" mode="aspectFill"
|
||||||
@@ -141,16 +141,21 @@ export default {
|
|||||||
// 注: 用 objToStyle 自动过滤 undefined/空值,避免输出 background-color:; 这类脏 CSS
|
// 注: 用 objToStyle 自动过滤 undefined/空值,避免输出 background-color:; 这类脏 CSS
|
||||||
warpWrapStyle() {
|
warpWrapStyle() {
|
||||||
const v = this.value || {};
|
const v = this.value || {};
|
||||||
|
// ========== 单位约定 ==========
|
||||||
|
// 数据里所有「字号/图标/间距/圆角」类数字字段统一存为 rpx(uni-app 响应式像素);
|
||||||
|
// 老数据若是字符串("24rpx")或缺字段,经 r() 归一化为数字,再拼 'rpx' 后缀;
|
||||||
|
// 老数据若用 px 存(早期 DIY 圆角),需在设计面板里手动改为 rpx 量级再保存(否则会被 r() 截断)。
|
||||||
|
// 后端预览(PC 浏览器)做 /2 折算,把 rpx 转 px。
|
||||||
const r = (val, fb) => this._num(val, fb);
|
const r = (val, fb) => this._num(val, fb);
|
||||||
const isRootRound = v.componentAngle === 'round';
|
const isRootRound = v.componentAngle === 'round';
|
||||||
const isItemRound = v.elementAngle === 'round';
|
const isItemRound = v.elementAngle === 'round';
|
||||||
// 标签胶囊 3 色(默认值与后端 design.js nestedDefaults 对齐)
|
// 标签胶囊 3 色 + 字号(默认值与后端 design.js nestedDefaults 对齐)
|
||||||
const tag = v.tagStyle || {};
|
const tag = v.tagStyle || {};
|
||||||
// 摘要文字色(默认值与后端 design.js nestedDefaults 对齐)
|
// 摘要文字色 + 字号
|
||||||
const abs = v.abstractStyle || {};
|
const abs = v.abstractStyle || {};
|
||||||
// 查看更多(字号 + 图标大小)
|
// 查看更多(字号 + 图标大小)
|
||||||
const vm = v.viewMore || {};
|
const vm = v.viewMore || {};
|
||||||
// 阅读区(文字色 + 图标大小)
|
// 阅读区(文字色 + 图标大小 + 文字大小)
|
||||||
const rw = v.readWrapStyle || {};
|
const rw = v.readWrapStyle || {};
|
||||||
// 标题字号(每风格独立 1/2/3/4)
|
// 标题字号(每风格独立 1/2/3/4)
|
||||||
const tfs1 = r(v.titleFontSize1, 30);
|
const tfs1 = r(v.titleFontSize1, 30);
|
||||||
@@ -166,25 +171,26 @@ export default {
|
|||||||
'--article-bottom-around-radius': isRootRound ? `${r(v.bottomAroundRadius, 0) * 2}rpx` : '0rpx',
|
'--article-bottom-around-radius': isRootRound ? `${r(v.bottomAroundRadius, 0) * 2}rpx` : '0rpx',
|
||||||
'--article-top-element-around-radius': isItemRound ? `${r(v.topElementAroundRadius, 0) * 2}rpx` : '0rpx',
|
'--article-top-element-around-radius': isItemRound ? `${r(v.topElementAroundRadius, 0) * 2}rpx` : '0rpx',
|
||||||
'--article-bottom-element-around-radius': isItemRound ? `${r(v.bottomElementAroundRadius, 0) * 2}rpx` : '0rpx',
|
'--article-bottom-element-around-radius': isItemRound ? `${r(v.bottomElementAroundRadius, 0) * 2}rpx` : '0rpx',
|
||||||
// 标签胶囊 3 色
|
// 标签胶囊 3 色 + 字号(rpx)
|
||||||
'--article-tag-bg-color': tag.bgColor || '#f0f9ff',
|
'--article-tag-bg-color': tag.bgColor || '#f0f9ff',
|
||||||
'--article-tag-text-color': tag.textColor || '#1e6bb8',
|
'--article-tag-text-color': tag.textColor || '#1e6bb8',
|
||||||
'--article-tag-border-color': tag.borderColor || '#b3d8ff',
|
'--article-tag-border-color': tag.borderColor || '#b3d8ff',
|
||||||
// 摘要文字色
|
'--article-tag-font-size': r(tag.fontSize, 22) + 'rpx',
|
||||||
|
// 摘要文字色 + 字号(rpx)
|
||||||
'--article-abstract-color': abs.textColor || '#888888',
|
'--article-abstract-color': abs.textColor || '#888888',
|
||||||
// 阅读区文字色
|
'--article-abstract-font-size': r(abs.fontSize, 24) + 'rpx',
|
||||||
|
// 阅读区文字色 + 图标大小 + 文字大小(rpx)
|
||||||
'--article-meta-color': rw.color || '#999ca7',
|
'--article-meta-color': rw.color || '#999ca7',
|
||||||
// 阅读区图标大小(rpx)
|
|
||||||
'--article-meta-icon-size': r(rw.iconSize, 24) + 'rpx',
|
'--article-meta-icon-size': r(rw.iconSize, 24) + 'rpx',
|
||||||
// 查看更多字号(rpx)
|
'--article-meta-font-size': r(rw.fontSize, 24) + 'rpx',
|
||||||
'--article-view-more-font-size': (typeof vm.fontSize === 'number' ? vm.fontSize : r(vm.fontSize, 26)) + 'rpx',
|
// 查看更多字号 + 图标大小(rpx,统一走 r() 兜底,不再 typeof 区分)
|
||||||
// 查看更多图标大小(rpx)
|
'--article-view-more-font-size': r(vm.fontSize, 26) + 'rpx',
|
||||||
'--article-view-more-icon-size': r(vm.iconSize, 24) + 'rpx',
|
'--article-view-more-icon-size': r(vm.iconSize, 24) + 'rpx',
|
||||||
// 列表项间距(rpx)
|
// 列表项间距(rpx)
|
||||||
'--article-item-gap': r(v.itemGap, 24) + 'rpx',
|
'--article-item-gap': r(v.itemGap, 16) + 'rpx',
|
||||||
// 分割线颜色(主要用于 style-4)
|
// 分割线颜色(主要用于 style-4)
|
||||||
'--article-divider-color': v.dividerColor || '#eeeeee',
|
'--article-divider-color': v.dividerColor || '#eeeeee',
|
||||||
// 标题字号 4 风格独立
|
// 标题字号 4 风格独立(rpx)
|
||||||
'--article-title-fs-1': tfs1 + 'rpx',
|
'--article-title-fs-1': tfs1 + 'rpx',
|
||||||
'--article-title-fs-2': tfs2 + 'rpx',
|
'--article-title-fs-2': tfs2 + 'rpx',
|
||||||
'--article-title-fs-3': tfs3 + 'rpx',
|
'--article-title-fs-3': tfs3 + 'rpx',
|
||||||
@@ -221,7 +227,7 @@ export default {
|
|||||||
},
|
},
|
||||||
// ========== 字段显示配置(带默认值,避免老数据缺字段时报错) ==========
|
// ========== 字段显示配置(带默认值,避免老数据缺字段时报错) ==========
|
||||||
abstractStyle() {
|
abstractStyle() {
|
||||||
return Object.assign({ support: true, control: true }, this.value.abstractStyle || {});
|
return Object.assign({ support: true, control: true, fontSize: 24 }, this.value.abstractStyle || {});
|
||||||
},
|
},
|
||||||
readNumStyle() {
|
readNumStyle() {
|
||||||
return Object.assign({ support: true, control: true }, this.value.readNumStyle || {});
|
return Object.assign({ support: true, control: true }, this.value.readNumStyle || {});
|
||||||
@@ -230,15 +236,15 @@ export default {
|
|||||||
return Object.assign({ support: true, control: false }, this.value.dianzanStyle || {});
|
return Object.assign({ support: true, control: false }, this.value.dianzanStyle || {});
|
||||||
},
|
},
|
||||||
tagStyle() {
|
tagStyle() {
|
||||||
return Object.assign({ support: true, control: true }, this.value.tagStyle || {});
|
return Object.assign({ support: true, control: true, fontSize: 22 }, this.value.tagStyle || {});
|
||||||
},
|
},
|
||||||
viewMore() {
|
viewMore() {
|
||||||
return Object.assign({ support: true, control: false, text: '查看更多', color: '#999999', iconSize: 24 },
|
return Object.assign({ support: true, control: false, text: '查看更多', color: '#999999', iconSize: 24 },
|
||||||
this.value.viewMore || {});
|
this.value.viewMore || {});
|
||||||
},
|
},
|
||||||
// 阅读区样式(文字色 + 图标大小)
|
// 阅读区样式(文字色 + 图标大小 + 文字大小)
|
||||||
readWrapStyle() {
|
readWrapStyle() {
|
||||||
return Object.assign({ color: '#999ca7', iconSize: 24 },
|
return Object.assign({ color: '#999ca7', iconSize: 24, fontSize: 24 },
|
||||||
this.value.readWrapStyle || {});
|
this.value.readWrapStyle || {});
|
||||||
},
|
},
|
||||||
// ========== 滚动配置(同时兼容老数据 swiperConfig 和新字段 scrollMode) ==========
|
// ========== 滚动配置(同时兼容老数据 swiperConfig 和新字段 scrollMode) ==========
|
||||||
@@ -261,8 +267,12 @@ export default {
|
|||||||
return actualCount > 0 ? Math.min(displayCount, actualCount) : 1;
|
return actualCount > 0 ? Math.min(displayCount, actualCount) : 1;
|
||||||
},
|
},
|
||||||
// swiper 高度(rpx)优先级:
|
// swiper 高度(rpx)优先级:
|
||||||
// 1. 老/新数据显式设置了 swiperConfig.swiperHeight(>0) → 用配置值
|
// 1. 老/新数据显式设置了 swiperConfig.swiperHeight(>0) → 配置值
|
||||||
// 2. 否则按 style 算单行高度 × 实际显示行数 + 行间距
|
// 2. 否则按 style 算单行高度 × 显示行数 + 行间距
|
||||||
|
// 注:风格1 perRow=210,正好容纳:
|
||||||
|
// 有图 item 200(图160+info 160 被 stretch+padding40)
|
||||||
|
// 无图 item ~200(标题/摘要单行截断+space-between 上下分布+padding40)
|
||||||
|
// swiper 整体 = 210*3+10 = 640rpx,行间紧凑,有图无图视觉高度统一。
|
||||||
swiperHeight() {
|
swiperHeight() {
|
||||||
// 1. 显式设置了 swiperHeight (>0)
|
// 1. 显式设置了 swiperHeight (>0)
|
||||||
var configHeight = parseInt(this.swiperConfig.swiperHeight) || 0;
|
var configHeight = parseInt(this.swiperConfig.swiperHeight) || 0;
|
||||||
@@ -271,13 +281,13 @@ export default {
|
|||||||
// 注:swiper 内 item 已去掉 margin-bottom,swiper-item 高度 = perRow
|
// 注:swiper 内 item 已去掉 margin-bottom,swiper-item 高度 = perRow
|
||||||
var perRow;
|
var perRow;
|
||||||
switch (this.value.style) {
|
switch (this.value.style) {
|
||||||
case 'style-1': perRow = 200; break; // 图160 + padding 上下20*2 = 200
|
case 'style-1': perRow = 210; break; // 容纳有图200/无图200+10rpx 缓冲
|
||||||
case 'style-2': perRow = 540; break; // 图320 + info 220
|
case 'style-2': perRow = 540; break; // 图320 + info 220
|
||||||
case 'style-3': perRow = 300; break; // 图200 + info 100
|
case 'style-3': perRow = 300; break; // 图200 + info 100
|
||||||
case 'style-4': perRow = 120; break; // 纯文字
|
case 'style-4': perRow = 120; break; // 纯文字
|
||||||
default: perRow = 200; break;
|
default: perRow = 200; break;
|
||||||
}
|
}
|
||||||
return perRow * this.safeDisplayMultipleItems + 30; // N 行 + 30rpx 行间距总空间
|
return perRow * this.safeDisplayMultipleItems + 10; // N 行 + 10rpx 行间距总空间(更紧凑)
|
||||||
}
|
}
|
||||||
// 注: :class 一律在模板里用 :class="['static', dynamic]" 内联数组写法
|
// 注: :class 一律在模板里用 :class="['static', dynamic]" 内联数组写法
|
||||||
// 不再用 listClass/itemClass computed (computed 返回 array 时,uni-app WXML 编译
|
// 不再用 listClass/itemClass computed (computed 返回 array 时,uni-app WXML 编译
|
||||||
@@ -365,12 +375,15 @@ export default {
|
|||||||
--article-tag-bg-color: #f0f9ff;
|
--article-tag-bg-color: #f0f9ff;
|
||||||
--article-tag-text-color: #1e6bb8;
|
--article-tag-text-color: #1e6bb8;
|
||||||
--article-tag-border-color: #b3d8ff;
|
--article-tag-border-color: #b3d8ff;
|
||||||
|
--article-tag-font-size: 22rpx;
|
||||||
--article-abstract-color: #888888;
|
--article-abstract-color: #888888;
|
||||||
|
--article-abstract-font-size: 24rpx;
|
||||||
--article-meta-color: #999ca7;
|
--article-meta-color: #999ca7;
|
||||||
--article-meta-icon-size: 24rpx;
|
--article-meta-icon-size: 24rpx;
|
||||||
|
--article-meta-font-size: 24rpx;
|
||||||
--article-view-more-font-size: 26rpx;
|
--article-view-more-font-size: 26rpx;
|
||||||
--article-view-more-icon-size: 24rpx;
|
--article-view-more-icon-size: 24rpx;
|
||||||
--article-item-gap: 24rpx;
|
--article-item-gap: 16rpx;
|
||||||
--article-divider-color: #eeeeee;
|
--article-divider-color: #eeeeee;
|
||||||
--article-title-fs-1: 30rpx;
|
--article-title-fs-1: 30rpx;
|
||||||
--article-title-fs-2: 30rpx;
|
--article-title-fs-2: 30rpx;
|
||||||
@@ -402,7 +415,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
margin-bottom: var(--article-item-gap, 24rpx);
|
margin-bottom: var(--article-item-gap, 16rpx);
|
||||||
/* 背景 / 圆角通过 CSS 变量从 .article-wrap 继承(由 warpWrapStyle 注入) */
|
/* 背景 / 圆角通过 CSS 变量从 .article-wrap 继承(由 warpWrapStyle 注入) */
|
||||||
background-color: var(--article-element-bg-color, transparent);
|
background-color: var(--article-element-bg-color, transparent);
|
||||||
border-top-left-radius: var(--article-top-element-around-radius, 0);
|
border-top-left-radius: var(--article-top-element-around-radius, 0);
|
||||||
@@ -432,7 +445,8 @@ export default {
|
|||||||
border-radius: 20rpx;
|
border-radius: 20rpx;
|
||||||
padding: 2rpx 14rpx;
|
padding: 2rpx 14rpx;
|
||||||
margin: 0 8rpx 8rpx 0;
|
margin: 0 8rpx 8rpx 0;
|
||||||
font-size: 22rpx;
|
/* 标签字号由 CSS 变量驱动 */
|
||||||
|
font-size: var(--article-tag-font-size, 22rpx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,7 +458,8 @@ export default {
|
|||||||
margin-top: 10rpx;
|
margin-top: 10rpx;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
font-size: $font-size-tag;
|
/* 阅读区文字大小由 CSS 变量驱动(覆盖原 SCSS 变量 $font-size-tag) */
|
||||||
|
font-size: var(--article-meta-font-size, 24rpx);
|
||||||
|
|
||||||
.category-icon {
|
.category-icon {
|
||||||
width: 8rpx;
|
width: 8rpx;
|
||||||
@@ -534,7 +549,8 @@ export default {
|
|||||||
.desc {
|
.desc {
|
||||||
/* 颜色由 CSS 变量驱动(来自 warpWrapStyle 注入;老数据走默认值) */
|
/* 颜色由 CSS 变量驱动(来自 warpWrapStyle 注入;老数据走默认值) */
|
||||||
color: var(--article-abstract-color, #888888);
|
color: var(--article-abstract-color, #888888);
|
||||||
font-size: 24rpx;
|
/* 摘要字号由 CSS 变量驱动 */
|
||||||
|
font-size: var(--article-abstract-font-size, 24rpx);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
@@ -543,6 +559,31 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== 无图紧凑样式:让 item 高度跟有图一致 (~200rpx) ==========
|
||||||
|
// 背景:无图时 info-wrap 无 image 撑高,内容自然展开 ~232rpx + padding 40 = 272rpx,
|
||||||
|
// 远超有图时的 200rpx,导致 swiper-item 内行间空白巨大或被裁。
|
||||||
|
// 解决:无图时 info-wrap 显式 min-height: 160rpx(与有图时 image 撑高一致),
|
||||||
|
// 标题/摘要单行截断 + 去掉多余 margin,内容 ~124rpx 在 160rpx 容器内用
|
||||||
|
// space-between 上下分布(标题顶/摘要中/阅读底),与有图场景视觉高度统一。
|
||||||
|
.item.no-image {
|
||||||
|
.info-wrap {
|
||||||
|
min-height: 160rpx;
|
||||||
|
.title {
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.desc {
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
|
}
|
||||||
|
.tag-list {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
.read-wrap {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== style-2: 大图卡片(上图下文) ==========
|
// ========== style-2: 大图卡片(上图下文) ==========
|
||||||
@@ -581,7 +622,8 @@ export default {
|
|||||||
.desc {
|
.desc {
|
||||||
/* 颜色由 CSS 变量驱动(来自 warpWrapStyle 注入;老数据走默认值) */
|
/* 颜色由 CSS 变量驱动(来自 warpWrapStyle 注入;老数据走默认值) */
|
||||||
color: var(--article-abstract-color, #888888);
|
color: var(--article-abstract-color, #888888);
|
||||||
font-size: 24rpx;
|
/* 摘要字号由 CSS 变量驱动 */
|
||||||
|
font-size: var(--article-abstract-font-size, 24rpx);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
@@ -642,8 +684,7 @@ export default {
|
|||||||
.category-name {
|
.category-name {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
// style-3 不再硬覆写字号,跟随 --article-meta-font-size(用户配多小就多小)
|
||||||
font-size: 20rpx;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user