Merge remote-tracking branch 'origin/feat/camcard' into feat/camcard
# Conflicts: # components-diy/diy-card-mini.vue # components-diy/diy-card-show.vue # tests/diy-card-ab-visual.test.js # tests/diy-card-qr-style.test.js
This commit is contained in:
@@ -41,6 +41,20 @@ const hasPanels = fs.existsSync(path.join(PANEL_DIR, 'diy-card-self/design.html'
|
||||
const showPanel = hasPanels ? strip(fs.readFileSync(path.join(PANEL_DIR, 'diy-card-show/design.html'), 'utf8')) : '';
|
||||
const selfPanel = hasPanels ? strip(fs.readFileSync(path.join(PANEL_DIR, 'diy-card-self/design.html'), 'utf8')) : '';
|
||||
|
||||
/**
|
||||
* 面板控件的字段绑定有三种形态(2026-10-21 面板改版: 下拉框 → 可视化选项组,
|
||||
* 数字框 → 滑块):
|
||||
* ① v-model="nc.X" 输入框 / 开关
|
||||
* ② nc.X = 'v' 可视化选项组(芯片)的赋值绑定
|
||||
* ③ field: 'X' 滑块控件 :data="{field:'X'}"
|
||||
* 断言的是「这个字段确实被某个控件绑定了」, 不限定控件形态 —— 契约是字段名, 不是控件类型。
|
||||
*/
|
||||
const bound = (src, field) => new RegExp(
|
||||
'v-model(\\.[a-z]+)?="nc\\.' + field + '"'
|
||||
+ '|\\bnc\\.' + field + "\\s*=\\s*['\"]"
|
||||
+ '|field\\s*:\\s*[\'"]' + field + '[\'"]'
|
||||
).test(src);
|
||||
|
||||
// =============================================================
|
||||
// 1. common.js 纯函数(真值断言)
|
||||
// =============================================================
|
||||
@@ -200,7 +214,7 @@ test('mini: qrBlockStyle 四档外观分支(多彩只装饰外围, 码黑白保
|
||||
// 2026-10-23 用户定稿: 外观衬底只包二维码图(qrImgStyle), 「扫码查看完整名片」tip 在衬底外无蓝底
|
||||
assert.match(miniSrc, /class="qr-img" :style="qrImgStyle"/);
|
||||
const tipBinds = miniSrc.match(/class="qr-tip" :style="labelStyle"/g) || [];
|
||||
assert.equal(tipBinds.length, 4, '四档 tip 仍独立(不进衬底), 实际 ' + tipBinds.length);
|
||||
assert.equal(tipBinds.length, 5, '五档 tip 仍独立(不进衬底; 含 theme 头部块), 实际 ' + tipBinds.length);
|
||||
});
|
||||
|
||||
test('mini: 二维码尺寸取 resolveQrSize(自定义>0 优先, 否则档位自动)', () => {
|
||||
@@ -218,15 +232,15 @@ test('mini: 微调位移 transform(不用 calc, WXSS 兼容)', () => {
|
||||
|
||||
test('mini: 扫码提示开关 + 四个挂点统一消费', () => {
|
||||
assert.match(miniSrc, /showQrTip\(\)\s*\{\s*return flagOn\(this\.c\.qrTipShow,\s*true\)/);
|
||||
// 四个二维码块(corner/head/rows/bottom)各有一个 tip, 都受开关控制
|
||||
// 二维码 tip 挂点: corner/rows/bottom 各 1 + head 档 2(head 双形态分支互斥渲染, 2.17)
|
||||
const tips = miniSrc.match(/<text v-if="showQrTip" class="qr-tip"/g) || [];
|
||||
assert.equal(tips.length, 4, '四档二维码 tip 挂点, 实际 ' + tips.length);
|
||||
assert.equal(tips.length, 5, 'tip 挂点(4 档 + head 双分支各一), 实际 ' + tips.length);
|
||||
});
|
||||
|
||||
test('mini: cornerClearStyle 按实际尺寸反算让位(防遮挡, 纯数值不用 calc)', () => {
|
||||
assert.match(miniSrc, /cornerClearStyle\(\)\s*\{[\s\S]*?if \(this\.qrPos !== 'corner' \|\| !this\.showQrBase\) return \{\};/);
|
||||
// 让位量 = 浮层 top 20 + 块高[尺寸+衬底+tip] - 头部 104 + 间隙 10; 下限 24
|
||||
assert.match(miniSrc, /Math\.max\(24, total - 104 \+ 10\)/);
|
||||
assert.match(miniSrc, /Math\.max\(24, total - headHeight \+ 10\)/);
|
||||
// 衬底与 tip 参与计算(关 tip 时让位自动收窄)
|
||||
assert.match(miniSrc, /const tip = this\.showQrTip \? 42 : 0;/);
|
||||
});
|
||||
@@ -242,7 +256,7 @@ test('mini: cornerHeadStyle 头部水平让位按浮层实际宽度动态反算'
|
||||
|
||||
test('mini: 四个二维码块统一绑 qrBlockStyle(尺寸/位移/外观单一事实来源)', () => {
|
||||
const binds = miniSrc.match(/:style="qrBlockStyle"/g) || [];
|
||||
assert.equal(binds.length, 4, 'corner/head/rows/bottom 四块, 实际 ' + binds.length);
|
||||
assert.equal(binds.length, 5, 'qrBlockStyle 绑定(corner/rows/bottom 各 1 + head 双分支各一), 实际 ' + binds.length);
|
||||
});
|
||||
|
||||
// =============================================================
|
||||
@@ -400,8 +414,12 @@ for (const [name, panel] of hasPanels ? [['show', showPanel], ['self', selfPanel
|
||||
assert.match(panel, /v-model\.number="nc\.qrOffsetY"/);
|
||||
assert.match(panel, /v-model="nc\.qrTipShow"/);
|
||||
// 二维码外观四选项(plain/card/theme/gradient)
|
||||
|
||||
for (const v of ['plain', 'card', 'theme', 'gradient']) {
|
||||
assert.ok(panel.includes('<option value="' + v + '">'), '缺选项 ' + v);
|
||||
assert.ok(
|
||||
panel.includes("nc.qrStyle = '" + v + "'") || panel.includes('<option value="' + v + '">'),
|
||||
'缺选项 ' + v
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -410,10 +428,9 @@ for (const [name, panel] of hasPanels ? [['show', showPanel], ['self', selfPanel
|
||||
assert.ok(panel.includes('nc.showAvatar !== false'), '预览不消费 showAvatar');
|
||||
// 二维码外观四档
|
||||
assert.ok(panel.includes("nc.qrStyle === 'plain'"), '预览不消费 qrStyle');
|
||||
// 自定义尺寸(0=自动: 三处默认 48/44/56 按档位)
|
||||
assert.ok(panel.includes('nc.qrSize > 0 ? nc.qrSize : 48'), '预览不消费 qrSize(corner)');
|
||||
assert.ok(panel.includes('nc.qrSize > 0 ? nc.qrSize : 44'), '预览不消费 qrSize(head)');
|
||||
assert.ok(panel.includes('nc.qrSize > 0 ? nc.qrSize : 56'), '预览不消费 qrSize(rows/bottom)');
|
||||
// 自定义尺寸: 只锁「自定义值优先于档位自动」这层语义, 不锁死具体像素值
|
||||
// (档位默认值是可调的设计参数, 锁死会让改一次尺寸就得改一次测试)
|
||||
assert.ok(panel.includes('nc.qrSize > 0 ? nc.qrSize'), '预览不消费 qrSize');
|
||||
// 微调位移
|
||||
assert.ok(panel.includes('nc.qrOffsetX || 0'), '预览不消费 qrOffsetX');
|
||||
assert.ok(panel.includes('nc.qrOffsetY || 0'), '预览不消费 qrOffsetY');
|
||||
|
||||
Reference in New Issue
Block a user