290 lines
7.5 KiB
Vue
290 lines
7.5 KiB
Vue
<template>
|
|
<view data-component-name="diy-card-self" class="diy-card-self">
|
|
<!-- 未登录 + 登录引导兜底 -->
|
|
<view v-if="!hasToken && fallbackMode === 'none'" class="self-login" :style="boxStyle" @tap="goLogin" hover-class="btn-press">
|
|
<text class="login-tip" :style="nameStyle">{{ value.loginTip || '登录后这里展示我的名片' }}</text>
|
|
<view class="login-btn" :style="loginBtnStyle">
|
|
<text class="login-btn-text">{{ value.loginBtnText || '去登录' }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 名片卡(已登录=本人名片 / 未登录=兜底名片); loading 时基件出骨架屏;
|
|
「我的名片」角标已按 2026-10-23 参考图定稿移除 -->
|
|
<diy-card-mini
|
|
v-else-if="loading || card"
|
|
:card="card"
|
|
:config="miniConfig"
|
|
:loading="loading"
|
|
@act="doAct"
|
|
@row-act="doAct"
|
|
@detail="goDetail"
|
|
>
|
|
</diy-card-mini>
|
|
|
|
<!-- 未登录提示条(参考图 2026-10-22): 兜底名片下方灰条, 左文案右链接 -->
|
|
<view v-if="!hasToken && fallbackMode !== 'none' && !loading && card"
|
|
class="self-login-bar" hover-class="btn-press">
|
|
<text class="login-bar-text" :style="subTextStyle" @tap="goLogin">{{ value.loginBarTip || '登录后即可展示我的名片' }}</text>
|
|
<text class="login-bar-link" :style="loginLinkStyle" @tap="goCardList">{{ value.loginBarBtnText || '去看看名片' }}</text>
|
|
</view>
|
|
|
|
<!-- 已登录但没有任何名片可显示 -->
|
|
<view v-else-if="!loading" class="self-empty" :style="boxStyle">
|
|
<text class="empty-icon">🪪</text>
|
|
<text class="empty-tip" :style="subTextStyle">{{ value.noCardTip || '登录后即可展示我的名片' }}</text>
|
|
<view class="empty-btn" :style="loginBtnStyle" hover-class="btn-press" @tap="goCardList">
|
|
<text class="empty-btn-text">{{ value.noCardBtnText || '去看看名片' }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
// 数字名片 · 我的名片(装修组件)
|
|
// 运行时判定: 已登录 → 本人名片(optionalAuth); 未登录 → 配置的兜底名片
|
|
// fallbackMode: enterprise=店铺企业名片 / card=指定 fallbackCardId / none=登录引导
|
|
// 视觉基件 diy-card-mini; 本文件管登录态/兜底/空态 CTA
|
|
export default {
|
|
name: 'diy-card-self',
|
|
props: {
|
|
value: { type: Object }
|
|
},
|
|
data() {
|
|
return {
|
|
card: null,
|
|
isSelf: false,
|
|
loading: false,
|
|
};
|
|
},
|
|
computed: {
|
|
hasToken() {
|
|
try {
|
|
return !!(this.$store && this.$store.state && this.$store.state.token);
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
},
|
|
fallbackMode() {
|
|
const m = String((this.value || {}).fallbackMode || 'enterprise');
|
|
return ['enterprise', 'card', 'none'].includes(m) ? m : 'enterprise';
|
|
},
|
|
miniConfig() {
|
|
const v = this.value || {};
|
|
return {
|
|
bgColor: v.bgColor,
|
|
nameColor: v.nameColor,
|
|
infoColor: v.infoColor,
|
|
labelColor: v.labelColor,
|
|
borderRadius: v.borderRadius,
|
|
padding: v.padding,
|
|
showQuick: v.showQuick,
|
|
showDetailBtn: v.showDetailBtn,
|
|
detailBtnText: v.detailBtnText,
|
|
// 2.0 新增视觉开关
|
|
useCover: v.useCover,
|
|
showGradient: v.showGradient,
|
|
showLogo: v.showLogo,
|
|
showShadow: v.showShadow,
|
|
showRows: v.showRows,
|
|
maxRows: v.maxRows,
|
|
showQr: v.showQr,
|
|
qrTip: v.qrTip,
|
|
// 3.0 A+B 视觉升级
|
|
showRowIcons: v.showRowIcons,
|
|
rowTap: v.rowTap,
|
|
qrPosition: v.qrPosition,
|
|
// 3.1 头像开关 + 二维码样式/微调
|
|
showAvatar: v.showAvatar,
|
|
qrStyle: v.qrStyle,
|
|
qrSize: v.qrSize,
|
|
qrOffsetX: v.qrOffsetX,
|
|
qrOffsetY: v.qrOffsetY,
|
|
qrTipShow: v.qrTipShow,
|
|
};
|
|
},
|
|
boxStyle() {
|
|
const v = this.value || {};
|
|
return this.$util.objToStyle({
|
|
background: v.bgColor || '#FFFFFF',
|
|
borderRadius: this.px2rpx(v.borderRadius || 16) + 'rpx',
|
|
padding: this.px2rpx(v.padding || 16) + 'rpx',
|
|
boxShadow: '0 4rpx 16rpx rgba(15,23,42,0.06)',
|
|
});
|
|
},
|
|
nameStyle() {
|
|
return this.$util.objToStyle({ color: (this.value || {}).nameColor || '#1F2329' });
|
|
},
|
|
subTextStyle() {
|
|
return this.$util.objToStyle({ color: (this.value || {}).infoColor || '#8A8F99' });
|
|
},
|
|
loginLinkStyle() {
|
|
return this.$util.objToStyle({ color: (this.card || {}).theme_color || '#2F6BFF' });
|
|
},
|
|
loginBtnStyle() {
|
|
return this.$util.objToStyle({
|
|
background: (this.card || {}).theme_color || '#2F6BFF',
|
|
height: '80rpx',
|
|
borderRadius: '999rpx',
|
|
padding: '0 48rpx',
|
|
});
|
|
},
|
|
},
|
|
watch: {
|
|
hasToken() {
|
|
this.fetchData();
|
|
},
|
|
'value.fallbackMode'() {
|
|
this.fetchData();
|
|
},
|
|
'value.fallbackCardId'() {
|
|
this.fetchData();
|
|
},
|
|
},
|
|
mounted() {
|
|
this.fetchData();
|
|
},
|
|
methods: {
|
|
px2rpx(v) {
|
|
const n = Number(v);
|
|
return isNaN(n) ? 0 : Math.round(n * 2);
|
|
},
|
|
fetchData() {
|
|
if (!this.hasToken && this.fallbackMode === 'none') {
|
|
this.card = null;
|
|
return;
|
|
}
|
|
this.loading = true;
|
|
this.$api.sendRequest({
|
|
url: '/card/api/diy/mycard',
|
|
data: {
|
|
fallback_mode: this.fallbackMode,
|
|
fallback_card_id: String((this.value || {}).fallbackCardId || '').trim(),
|
|
},
|
|
success: res => {
|
|
this.loading = false;
|
|
if (res.code == 0 && res.data) {
|
|
this.card = res.data.card || null;
|
|
this.isSelf = res.data.is_self == 1;
|
|
} else {
|
|
this.card = null;
|
|
this.isSelf = false;
|
|
}
|
|
},
|
|
fail: () => {
|
|
this.loading = false;
|
|
this.card = null;
|
|
this.isSelf = false;
|
|
},
|
|
});
|
|
},
|
|
goLogin() {
|
|
this.$util.redirectTo('/pages_tool/login/login');
|
|
},
|
|
goCardList() {
|
|
this.$util.redirectTo('/pages_tool/card/list');
|
|
},
|
|
doAct(act) {
|
|
if (!act || !act.value) return;
|
|
if (act.type === 'tel') {
|
|
uni.makePhoneCall({ phoneNumber: act.value, fail: () => {} });
|
|
} else if (act.type === 'wx') {
|
|
uni.setClipboardData({
|
|
data: act.value,
|
|
success: () => uni.showToast({ title: '微信号已复制', icon: 'none' }),
|
|
});
|
|
} else if (act.type === 'mail') {
|
|
// #ifdef H5
|
|
window.location.href = 'mailto:' + act.value;
|
|
// #endif
|
|
// #ifndef H5
|
|
uni.setClipboardData({
|
|
data: act.value,
|
|
success: () => uni.showToast({ title: '邮箱已复制', icon: 'none' }),
|
|
});
|
|
// #endif
|
|
} else {
|
|
uni.setClipboardData({
|
|
data: act.value,
|
|
success: () => uni.showToast({ title: '已复制', icon: 'none' }),
|
|
});
|
|
}
|
|
},
|
|
goDetail(card) {
|
|
if (!card || !card.card_id) return;
|
|
this.$util.redirectTo('/pages_tool/card/detail', { card_id: card.card_id });
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.diy-card-self {
|
|
width: 100%;
|
|
position: relative;
|
|
|
|
/* 未登录提示条(参考图 2026-10-22): 兜底名片下方, 浅灰圆角条 左文案右链接 */
|
|
.self-login-bar {
|
|
margin-top: 20rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
background: #F5F6F8;
|
|
border-radius: 12rpx;
|
|
padding: 20rpx 24rpx;
|
|
|
|
.login-bar-text {
|
|
font-size: 24rpx;
|
|
}
|
|
|
|
.login-bar-link {
|
|
font-size: 24rpx;
|
|
font-weight: 600;
|
|
flex-shrink: 0;
|
|
margin-left: 16rpx;
|
|
}
|
|
}
|
|
|
|
.self-login,
|
|
.self-empty {
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 48rpx 24rpx;
|
|
|
|
.empty-icon {
|
|
font-size: 64rpx;
|
|
}
|
|
|
|
.login-tip,
|
|
.empty-tip {
|
|
font-size: 28rpx;
|
|
font-weight: 600;
|
|
text-align: center;
|
|
}
|
|
|
|
.login-btn,
|
|
.empty-btn {
|
|
margin-top: 28rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.login-btn-text,
|
|
.empty-btn-text {
|
|
font-size: 26rpx;
|
|
font-weight: 600;
|
|
color: #ffffff;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.btn-press {
|
|
opacity: 0.72;
|
|
transform: scale(0.98);
|
|
}
|
|
</style>
|