From 6f9ac29aa6502f17ab6d0ac9fc4087199a46e7b4 Mon Sep 17 00:00:00 2001 From: jing <1683105490@qq.com> Date: Wed, 21 Oct 2026 18:16:49 +0800 Subject: [PATCH] =?UTF-8?q?chore=EF=BC=9A=E4=BA=8C=E7=BB=B4=E7=A0=81?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE=E5=92=8C=E5=90=8E=E5=8F=B0=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components-diy/diy-card-show.vue | 86 ++++++++++++++++++++++++++++++-- tests/diy-card-qr-style.test.js | 23 +++++++-- 2 files changed, 102 insertions(+), 7 deletions(-) diff --git a/components-diy/diy-card-show.vue b/components-diy/diy-card-show.vue index ba99689..6f8308d 100644 --- a/components-diy/diy-card-show.vue +++ b/components-diy/diy-card-show.vue @@ -30,7 +30,8 @@ {{ card.name || '未命名名片' }} {{ jobLine }} - + + {{ qrTipText }} @@ -51,6 +52,18 @@ + + + + {{ qrTipText }} + + + + + + {{ qrTipText }} + + + + + + {{ qrTipText }} + + 发名片 @@ -102,7 +121,7 @@ // 图标资料行 + 卡外「发名片」胶囊。面板仅颜色/底色/圆角/阴影/行数继续生效。 import { CardTokens, px2rpx, num, flagOn, initialOf, avatarBg, themeGradient, visibleRows, rowIconFor, rowActOf, - resolveQrSize, + resolveQrSize, normalizeQrPosition, qrTransform, } from './diy-card-common.js'; export default { @@ -147,6 +166,24 @@ export default { showQrBlock() { return flagOn(this.c.showQr, true); }, + /** 二维码位置(四档, 与面板下拉/mini 基件同口径): rows 资料行下方 / head 头部右侧 / + * corner 右上角浮层 / bottom 主按钮上方; 未配置回落 rows(面板默认档) */ + qrPos() { + return normalizeQrPosition(this.c.qrPosition); + }, + /** 位置分档显隐(共用 showQrBlock + qr_url 前置) */ + showQrBase() { + return this.showQrBlock && !!(this.card && this.card.qr_url); + }, + showQrHead() { return this.showQrBase && this.qrPos === 'head'; }, + showQrRows() { return this.showQrBase && this.qrPos === 'rows'; }, + showQrCorner() { return this.showQrBase && this.qrPos === 'corner'; }, + showQrBottom() { return this.showQrBase && this.qrPos === 'bottom'; }, + /** 二维码微调(qrOffsetX/Y, 任一轴非零才输出 transform) */ + qrShiftStyle() { + const t = qrTransform(this.c.qrOffsetX, this.c.qrOffsetY); + return t ? this.$util.objToStyle({ transform: t }) : ''; + }, /** 二维码提示文字: 面板 qrTip, 未配置回落「扫码查看完整名片」 */ qrTipText() { return this.c.qrTip || '扫码查看完整名片'; @@ -195,11 +232,12 @@ export default { const card = this.card || {}; return card.job_title || card.company || card.card_title || ''; }, - /** 二维码边长: 面板 qrSize > 0 用自定义(px), 0/空 = 「按位自动」走头部右侧档(120rpx)。 + /** 二维码边长: 面板 qrSize > 0 用自定义(px), 0/空 = 「按位自动」按位置档位取值 + * (rows/bottom 180rpx, head/corner 120rpx, 见 common.QR_SIZES)。 * 之前用 num(qrSize, 48) 兜底 —— 面板默认 0 是合法数字不触发默认值, * 算出 0rpx 宽高, 二维码图被渲染成 0 尺寸「看不见」 */ qrSide() { - return resolveQrSize('head', this.c.qrSize); + return resolveQrSize(this.qrPos, this.c.qrSize); }, qrImgStyle() { return this.$util.objToStyle({ @@ -574,6 +612,46 @@ export default { } } } + + /* 右上角浮层档: 白底描边小卡浮在名片右上角(z-index 压过头部信息) */ + .card-qr-corner { + position: absolute; + top: 20rpx; + right: 20rpx; + z-index: 2; + display: flex; + flex-direction: column; + align-items: center; + padding: 10rpx; + background-color: #ffffff; + border: 2rpx solid #EEF0F3; + border-radius: 12rpx; + box-shadow: 0 4rpx 16rpx rgba(15, 23, 42, 0.10); + + .qr-tip-corner { + font-size: 20rpx; + margin-top: 4rpx; + white-space: nowrap; + } + } + } + + /* 资料行下方 / 主按钮上方档: 大码居中(边长走 qrImgStyle 内联) */ + .qr-center { + margin-top: 24rpx; + display: flex; + flex-direction: column; + align-items: center; + + .qr-tip-c { + font-size: 22rpx; + margin-top: 8rpx; + } + + /* 卡外(主按钮上方): 与上下元素拉开间距 */ + &.qr-center-bottom { + margin: 32rpx 24rpx 0; + } } /* 发名片: 卡片外下方胶囊(背景色由 sendBtnStyle 内联) */ diff --git a/tests/diy-card-qr-style.test.js b/tests/diy-card-qr-style.test.js index 936adad..08d7dcf 100644 --- a/tests/diy-card-qr-style.test.js +++ b/tests/diy-card-qr-style.test.js @@ -196,12 +196,29 @@ test('show: 快捷操作开关(面板「显示快捷操作」, 默认显示, 关 assert.match(showSrc, /@tap\.stop="doAct\(act\)"/); }); +test('show: 二维码位置四档(与面板下拉/mini 基件同口径, 未配置回落 rows)', () => { + assert.match(showSrc, /qrPos\(\)\s*\{\s*return normalizeQrPosition\(this\.c\.qrPosition\)/); + // 四档各自的条件渲染块 + assert.match(showSrc, /showQrHead\(\)\s*\{\s*return this\.showQrBase && this\.qrPos === 'head';\s*\}/); + assert.match(showSrc, /showQrRows\(\)\s*\{\s*return this\.showQrBase && this\.qrPos === 'rows';\s*\}/); + assert.match(showSrc, /showQrCorner\(\)\s*\{\s*return this\.showQrBase && this\.qrPos === 'corner';\s*\}/); + assert.match(showSrc, /showQrBottom\(\)\s*\{\s*return this\.showQrBase && this\.qrPos === 'bottom';\s*\}/); + // 模板四个位置都有落点(头部/资料行下/浮层/主按钮上方) + assert.match(showSrc, /v-if="showQrHead" class="card-qr"/); + assert.match(showSrc, /v-if="showQrRows" class="qr-center"/); + assert.match(showSrc, /v-if="showQrCorner" class="card-qr-corner"/); + assert.match(showSrc, /v-if="showQrBottom" class="qr-center qr-center-bottom"/); + // 微调位移(qrOffsetX/Y → transform) + assert.match(showSrc, /qrTransform\(this\.c\.qrOffsetX,\s*this\.c\.qrOffsetY\)/); +}); + test('show: 自绘版式自带小二维码(开关可关 + 点击进详情, 尺寸/提示文字面板可调)', () => { assert.match(showSrc, /class="card-qr"/); assert.match(showSrc, /\$util\.img\(card\.qr_url\)/); // 二维码块受面板「显示二维码」开关控制(与头像/资料行/快捷操作同口径: flagOn 默认显示) assert.match(showSrc, /showQrBlock\(\)\s*\{\s*return flagOn\(this\.c\.showQr,\s*true\)/); - assert.match(showSrc, /v-if="showQrBlock && card\.qr_url" class="card-qr"/); + // 开关 + 位置统一收敛在 showQrBase / showQrHead 等分档计算属性里(模板只消费分档结果) + assert.match(showSrc, /showQrBase\(\)\s*\{\s*return this\.showQrBlock && !!\(this\.card && this\.card\.qr_url\)/); // 提示文字消费面板 qrTip, 未配置回落「扫码查看完整名片」(与 mini 基件同口径) assert.match(showSrc, /qrTipText\(\)\s*\{\s*return this\.c\.qrTip \|\| '扫码查看完整名片';/); // 点二维码弹「分享名片」抽屉(复刻 detail.vue: 码 + 链接 + 复制链接/浏览器分享/保存二维码) @@ -211,10 +228,10 @@ test('show: 自绘版式自带小二维码(开关可关 + 点击进详情, 尺 assert.match(showSrc, /分享名片<\/view>/); assert.match(showSrc, /客户打开链接即可查看名片并留言留资/); assert.match(showSrc, /copyCardLink\(\)\s*\{\s*const url = \(this\.card && this\.card\.wap_url\) \|\| '';/); - // 尺寸走 resolveQrSize: 面板 qrSize>0 用自定义, 0/空 = 自动档(head 120rpx)。 + // 尺寸走 resolveQrSize: 面板 qrSize>0 用自定义, 0/空 = 按位置档位自动(rows/bottom 180, head/corner 120)。 // 反例形态: 不允许 num(qrSize, 48) 兜底 —— 面板默认 0 是合法数字, 会算出 0rpx 宽高, // 二维码图渲染成 0 尺寸「看不见」(2026-10-21 线上问题) - assert.match(showSrc, /qrSide\(\)\s*\{\s*return resolveQrSize\('head',\s*this\.c\.qrSize\)/); + assert.match(showSrc, /qrSide\(\)\s*\{\s*return resolveQrSize\(this\.qrPos,\s*this\.c\.qrSize\)/); assert.ok(!showSrc.includes("num(this.c.qrSize")); });