fix(diy-card): 操作区独立样式改单绑定 — uni-app 静默丢弃数组绑定(2.18 缺陷)

2026-10-22 线上问题(qrBlockStyle)同根因漏网: 4 个操作区分支
:style="[actsBlockStyle, cornerClearStyle]" 数组绑定被 uni-app 运行时
静默丢弃(style 属性整体为 null) → 操作区独立成块(actsBlockBg/Radius/Pad)
与 corner 让位在 C 端全部失效, 后端配置了也不生效。

- mini.vue: 新增 actsBlockFinalStyle 合并 computed(块样式字符串 +
  cornerClearStyle.marginTop), 4 分支(上/下 x grid/chips)改单绑定
- 契约锁死: style-v2/ab-visual 数组绑定反例 + 单绑定断言
- H5 实测(8080 diy2699, 配置 #F7F8FA/12/12): 修复前 computed
  transparent/0/0 → 修复后 rgb(247,248,250)/12px/12px 与配置一致

验证: 名片 7 套件全绿 + 三回归 79/41/56
This commit is contained in:
2026-10-24 14:03:28 +08:00
parent 4b99bcdd7e
commit 8617bb0395
3 changed files with 24 additions and 7 deletions

View File

@@ -94,7 +94,7 @@
</view>
<!-- 快捷操作·资料区上方档(2.18 actsPosition=above): below 时由下方同构块渲染 -->
<view v-if="actsAbove && showActs && acts.length && actsGrid" class="mini-acts-grid" :style="[actsBlockStyle, cornerClearStyle]">
<view v-if="actsAbove && showActs && acts.length && actsGrid" class="mini-acts-grid" :style="actsBlockFinalStyle">
<view v-for="(act, i) in acts" :key="'ta' + i" class="act-grid-item" :style="{ width: gridItemWidth }" hover-class="btn-press" @tap.stop="onAct(act)">
<view class="act-grid-icon" :style="actGridIconStyle(act)">
<!-- 自定义图标图片(2.18 媒体库, 优先) / SVG 线稿(2.18.1 与 wap detail 同源) / 首字兜底 -->
@@ -106,7 +106,7 @@
<text class="act-grid-label" :style="actGridLabelStyle(act)">{{ act.label }}</text>
</view>
</view>
<view v-if="actsAbove && showActs && acts.length && !actsGrid" class="mini-acts" :style="[actsBlockStyle, cornerClearStyle]">
<view v-if="actsAbove && showActs && acts.length && !actsGrid" class="mini-acts" :style="actsBlockFinalStyle">
<view v-for="(act, i) in acts" :key="'ta' + i" class="act-chip"
:style="i === 0 ? actPrimaryStyle : actGhostStyle" hover-class="btn-press" @tap.stop="onAct(act)">
<text class="act-text" :style="i === 0 ? actPrimaryTextStyle : actGhostTextStyle">{{ act.label }}</text>
@@ -149,7 +149,7 @@
</view>
<!-- 快捷操作·图标宫格档(grid): 彩色浅底图标 + 下方文字 -->
<view v-if="!actsAbove && showActs && acts.length && actsGrid" class="mini-acts-grid" :style="[actsBlockStyle, cornerClearStyle]">
<view v-if="!actsAbove && showActs && acts.length && actsGrid" class="mini-acts-grid" :style="actsBlockFinalStyle">
<view v-for="(act, i) in acts" :key="i" class="act-grid-item" :style="{ width: gridItemWidth }" hover-class="btn-press" @tap.stop="onAct(act)">
<view class="act-grid-icon" :style="actGridIconStyle(act)">
<!-- 自定义图标图片(2.18 媒体库, 优先) / SVG 线稿(2.18.1 与 wap detail 同源) / 首字兜底 -->
@@ -163,7 +163,7 @@
</view>
<!-- 快捷操作·胶囊芯片档(chips, 历史默认; 最小触达 72rpx; 首个为主动作) -->
<view v-if="!actsAbove && showActs && acts.length && !actsGrid" class="mini-acts" :style="[actsBlockStyle, cornerClearStyle]">
<view v-if="!actsAbove && showActs && acts.length && !actsGrid" class="mini-acts" :style="actsBlockFinalStyle">
<view v-for="(act, i) in acts" :key="i" class="act-chip"
:style="actStyle" hover-class="btn-press" @tap.stop="onAct(act)">
<text class="act-text" :style="actTextStyle">{{ act.label }}</text>
@@ -681,6 +681,17 @@ export default {
rowsClearStyle() {
return this.actsAbove ? {} : this.cornerClearStyle;
},
/**
* 操作区最终样式(2.18 独立成块 + corner 让位): 合并输出单字符串。
* uni-app 运行时会静默丢弃 :style="[字符串, 对象]" 数组绑定 ——
* 2026-10-22 线上问题(qrBlockStyle)同根因, 2026-10-24 H5 实测复现于操作区
* (actsBlockBg/Radius/Pad 与 corner 让位同时失效, style 属性整体为 null)
*/
actsBlockFinalStyle() {
const clear = this.cornerClearStyle || {};
const extra = clear.marginTop ? 'margin-top: ' + clear.marginTop + ';' : '';
return ((this.actsBlockStyle || '') + ' ' + extra).trim();
},
detailBtnStyle() {
// 发送名片大按钮: 纯色主题实心(2026-10-22 参考图定稿, 不再用渐变);
// 高度 104rpx(用户反馈: 比触达标准 80rpx 加高一档, 参考图观感)

View File

@@ -141,9 +141,11 @@ test('mini: corner 档 Logo 避让 + 资料行/操作区动态让位', () => {
// 头部水平让位 = cornerHeadStyle 动态反算(审计修复: 静态 180rpx 在自定义大尺寸下不足)
assert.match(miniSrc, /<view class="mini-head" :style="cornerHeadStyle">/);
// 资料行/操作区让位 = cornerClearStyle 动态反算(自定义大尺寸/关 tip 自动跟随, 不用 calc)
// 2.18: 让位经 rowsClearStyle 分流(操作区在上方时资料行不重复位移); 操作区为 独立块样式+让位 合并绑定
// 2.18: 让位经 rowsClearStyle 分流(操作区在上方时资料行不重复位移); 操作区让位并入
// actsBlockFinalStyle 单绑定(2026-10-24: uni-app 静默丢弃数组绑定, 操作区独立样式曾整体失效)
assert.match(miniSrc, /rowsClearStyle\(\)\s*\{[\s\S]*?this\.actsAbove \? \{\} : this\.cornerClearStyle/);
assert.match(miniSrc, /:style="\[actsBlockStyle, cornerClearStyle\]"/);
assert.match(miniSrc, /:style="actsBlockFinalStyle"/);
assert.doesNotMatch(miniSrc, /:style="\[actsBlockStyle/);
// 静态 CSS 让位必须已移除(动态值才是单一事实来源)
assert.ok(!/padding-right: 180rpx;/.test(miniSrc), '静态 180rpx 让位应废弃, 改由 cornerHeadStyle 动态给出');
// 浮层 CSS 只定位于层次; 视觉衬底(白卡等)由 qrBlockStyle 内联决定

View File

@@ -281,7 +281,11 @@ test('2.18: 操作区位置/独立样式/每按钮图标/自定义二维码 全
assert.match(src, /v-if="actsAbove && showActs && acts\.length && actsGrid"/, '上方档宫格分支渲染');
assert.match(src, /v-if="!actsAbove && showActs && acts\.length && actsGrid"/, '下方档宫格分支互斥守卫');
assert.match(src, /rowsClearStyle\(\)\s*\{[\s\S]*?return this\.actsAbove \? \{\} : this\.cornerClearStyle/, '上方档时资料行不再重复让位');
assert.match(src, /:style="\[actsBlockStyle, cornerClearStyle\]"/, '操作区块样式 + corner 让位合并绑定');
// 2026-10-24: uni-app 运行时静默丢弃 :style="[字符串, 对象]" 数组绑定(2026-10-22 qrBlockStyle 线上问题同根因,
// H5 实测 actsBlockBg/Radius/Pad 全失效、style 属性为 null) → 合并为 actsBlockFinalStyle 单绑定, 数组形态禁止回归
assert.match(src, /:style="actsBlockFinalStyle"/, '操作区块走 actsBlockFinalStyle 单绑定');
assert.doesNotMatch(src, /:style="\[actsBlockStyle/, '操作区块禁数组绑定(uni-app 静默丢弃)');
assert.match(src, /actsBlockFinalStyle\(\)\s*\{[\s\S]*?cornerClearStyle/, 'actsBlockFinalStyle 合并 corner 让位');
assert.match(src, /actsBlockStyle\(\)\s*\{[\s\S]*?actsBlockBg/, '独立块样式消费 actsBlockBg/Radius/Pad');
// 每按钮图标: img 优先于字形/CSS 图标; 前景/底色覆盖
assert.match(src, /actImgOf\(act\)\s*\{[\s\S]*?actIconCfgOf\(this\.c\.actIcons,\s*act && act\.type\)/, 'actImgOf 消费 actIconCfgOf');