chore:我的名片组件发送名片正常

This commit is contained in:
2026-10-23 10:44:03 +08:00
parent 8348cbb179
commit ecc81b9b31
2 changed files with 217 additions and 9 deletions

View File

@@ -108,11 +108,37 @@
</view>
</view>
<!-- 发送名片(2026-10-23 参考图定稿: 白色名片外面下方, 与精选名片「发名片」同款布局;
放 wrap 外 → 顶带拉伸终点始终相对白卡底, 不受按钮高度影响) -->
<view v-if="showDetailBtn" class="mini-detail" :style="detailBtnStyle" hover-class="btn-press" @tap.stop="onDetail">
<!-- 发送名片(白色名片外面下方, 与精选名片「发名片」同款布局; 点击弹分享抽屉) -->
<view v-if="showDetailBtn" class="mini-detail" :style="detailBtnStyle" hover-class="btn-press" @tap.stop="openCardShare">
<text class="detail-text">{{ detailBtnText || '发送名片' }}</text>
</view>
<!-- 分享名片抽屉(2026-10-23 参考图定稿: 与精选名片 show 同款版式/文案,
复刻 pages_tool/card/detail.vue 的 share-sheet; 类名 cs- 前缀, scoped 隔离) -->
<view class="cs-mask" v-if="showShare" @tap="closeShare"></view>
<view class="cs-sheet" :class="{ 'cs-sheet-show': showShare }">
<view class="ss-bar"></view>
<view class="ss-title">分享名片</view>
<view class="ss-sub">客户打开链接即可查看名片并留言留资</view>
<view class="ss-qr-box">
<image v-if="card && card.qr_url" :src="$util.img(card.qr_url)" class="ss-qr" mode="widthFix" show-menu-by-longpress="true" />
</view>
<view class="ss-link">{{ (card && card.wap_url) || '' }}</view>
<view class="ss-btns">
<view class="ss-btn ss-btn-main" :style="shareBtnStyle" @tap="copyCardLink">复制链接</view>
<!-- #ifdef H5 -->
<view class="ss-btn" @tap="h5CardShare">浏览器分享</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN || MP-HARMONY -->
<view class="ss-btn" @tap="saveCardQr">保存二维码</view>
<!-- #endif -->
</view>
<view class="ss-tip">
<!-- #ifdef MP-WEIXIN -->长按二维码也可保存到相册<!-- #endif -->
<!-- #ifdef H5 -->长按二维码可保存到相册<!-- #endif -->
<!-- #ifdef MP-HARMONY -->点击「保存二维码」存入相册<!-- #endif -->
</view>
</view>
</view>
</template>
@@ -134,7 +160,7 @@ export default {
emptyActionText: { type: String, default: '' },
},
data() {
return { expanded: false };
return { expanded: false, showShare: false };
},
computed: {
c() {
@@ -297,6 +323,14 @@ export default {
// 蓝色顶带底色: 名片主题渐变(精选名片 show 同款)
return this.$util.objToStyle({ background: themeGradient(this.card) });
},
shareBtnStyle() {
// 分享抽屉主按钮(复制链接): 主题色
const theme = (this.card && this.card.theme_color) || CardTokens.color.primary;
return this.$util.objToStyle({
background: theme,
border: '2rpx solid ' + theme,
});
},
avatarStyle() {
return this.$util.objToStyle({ background: avatarBg(this.card) });
},
@@ -368,8 +402,58 @@ export default {
onAct(act) {
this.$emit('act', act);
},
onDetail() {
this.$emit('detail', this.card);
/* ---------- 分享名片抽屉(「发送名片」弹出; 版式/逻辑与精选名片 show 完全同款) ---------- */
openCardShare() {
this.showShare = true;
},
closeShare() {
this.showShare = false;
},
copyCardLink() {
const url = (this.card && this.card.wap_url) || '';
if (!url) {
uni.showToast({ title: '名片链接未返回,请稍后重试', icon: 'none' });
return;
}
uni.setClipboardData({
data: url,
success: () => uni.showToast({ title: '链接已复制', icon: 'success' }),
});
},
// H5: 优先 navigator.share(移动浏览器), 不支持则复制链接兜底
h5CardShare() {
// #ifdef H5
const url = (this.card && this.card.wap_url) || '';
if (navigator && typeof navigator.share === 'function' && url) {
navigator.share({
title: ((this.card && this.card.name) || '我的名片') + '的名片',
url: url
}).catch(() => {});
return;
}
// #endif
this.copyCardLink();
},
// 小程序/鸿蒙: 下载二维码后存相册(长按图片也可存, 抽屉底部有提示)
saveCardQr() {
const qrUrl = (this.card && this.card.qr_url) || '';
if (!qrUrl) return;
uni.downloadFile({
url: this.$util.img(qrUrl),
success: res => {
if (res.statusCode !== 200 || !res.tempFilePath) {
uni.showToast({ title: '二维码下载失败', icon: 'none' });
return;
}
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => uni.showToast({ title: '已保存到相册', icon: 'success' }),
fail: () => uni.showToast({ title: '保存失败,请授权相册权限', icon: 'none' }),
});
},
fail: () => uni.showToast({ title: '二维码下载失败', icon: 'none' }),
});
},
/** 二维码点击 → 预览名片(进详情页; qrTapPreview 开关控制, 默认开) */
onQrTap() {
@@ -809,4 +893,119 @@ export default {
transform: none;
}
}
/* 分享名片抽屉(「发送名片」弹出; 与精选名片 show 同款, 复刻 detail.vue share-sheet) */
.cs-mask {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 100;
}
.cs-sheet {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background-color: #ffffff;
border-radius: 24rpx 24rpx 0 0;
padding: 20rpx 32rpx 40rpx;
z-index: 101;
transform: translateY(100%);
transition: transform 0.25s;
&.cs-sheet-show {
transform: translateY(0);
}
.ss-bar {
width: 36rpx;
height: 4rpx;
border-radius: 2rpx;
background-color: #e3e7ee;
margin: 0 auto 20rpx;
}
.ss-title {
font-size: 32rpx;
font-weight: 600;
color: #1a1f36;
text-align: center;
}
.ss-sub {
font-size: 24rpx;
color: #9aa4b8;
text-align: center;
margin: 8rpx 0 24rpx;
}
.ss-qr-box {
display: flex;
justify-content: center;
margin-bottom: 20rpx;
.ss-qr {
width: 320rpx;
height: 320rpx;
}
}
.ss-link {
font-size: 22rpx;
color: #9aa4b8;
background-color: #f6f7f9;
border-radius: 8rpx;
padding: 14rpx 20rpx;
margin-bottom: 24rpx;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.ss-btns {
display: flex;
justify-content: space-between;
.ss-btn {
flex: 1;
height: 80rpx;
line-height: 80rpx;
text-align: center;
font-size: 28rpx;
color: #333;
border: 1rpx solid #dcdfe6;
border-radius: 12rpx;
margin: 0;
padding: 0;
background-color: transparent;
overflow: visible;
&::after {
border: none;
}
& + .ss-btn {
margin-left: 20rpx;
}
}
/* 主按钮颜色走 shareBtnStyle 内联(主题色), 此处只兜底默认蓝 */
.ss-btn-main {
background-color: #119dff;
border-color: #119dff;
color: #ffffff;
}
}
.ss-tip {
text-align: center;
font-size: 22rpx;
color: #b8c0cc;
margin-top: 20rpx;
}
}
</style>

View File

@@ -94,10 +94,19 @@ test('mini: showDetailBtn 默认开(历史配置无此字段时也显示, 开箱
assert.match(miniSrc, /flagOn\(this\.c\.showDetailBtn,\s*true\)/);
});
test('mini: 存在全宽主按钮节点并 emit detail', () => {
test('mini: 存在全宽主按钮节点并弹分享抽屉(2026-10-23 参考图定稿, 与精选 show 同款)', () => {
assert.match(miniSrc, /class="mini-detail"/);
assert.match(miniSrc, /@tap\.stop="onDetail"/);
assert.match(miniSrc, /this\.\$emit\('detail',\s*this\.card\)/);
// 主按钮点击 → 弹「分享名片」抽屉(不再 emit detail 跳详情)
assert.match(miniSrc, /@tap\.stop="openCardShare"/);
assert.match(miniSrc, /openCardShare\(\)\s*\{\s*this\.showShare = true;/);
// 抽屉版式与 show 同款: 标题/副文案/二维码/复制链接
assert.match(miniSrc, /<view class="ss-title">分享名片<\/view>/);
assert.match(miniSrc, /客户打开链接即可查看名片并留言留资/);
assert.match(miniSrc, /class="ss-btn ss-btn-main" :style="shareBtnStyle" @tap="copyCardLink"/);
// 遮罩关闭 + H5 分享/小程序存码方法齐备
assert.match(miniSrc, /class="cs-mask" v-if="showShare" @tap="closeShare"/);
assert.match(miniSrc, /h5CardShare\(\)/);
assert.match(miniSrc, /saveCardQr\(\)/);
});
test('mini: 主按钮文案可配(detailBtnText, 面板改字即生效)', () => {