222 lines
5.0 KiB
Vue
222 lines
5.0 KiB
Vue
<template>
|
|
<view class="card-detail">
|
|
<!-- 名片头部 -->
|
|
<view class="detail-head" v-if="relation">
|
|
<view class="head-avatar">
|
|
<text>{{ avatarText(relation.name) }}</text>
|
|
</view>
|
|
<view class="head-info">
|
|
<view class="head-name">{{ relation.name || '未命名名片' }}</view>
|
|
<view class="head-sub" v-if="relation.job_title || relation.company">
|
|
{{ [relation.job_title, relation.company].filter(Boolean).join(' · ') }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 字段列表 -->
|
|
<view class="detail-fields" v-if="fieldRows.length > 0">
|
|
<view v-for="(row, index) in fieldRows" :key="index" class="field-row">
|
|
<view class="field-label">{{ row.label }}</view>
|
|
<view class="field-value">{{ row.value }}</view>
|
|
<view class="field-action" v-if="row.action"
|
|
@tap="row.action.type === 'call' ? callPhone(row.value) : copyText2(row.value)">
|
|
{{ row.action.text }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 加载中 -->
|
|
<view class="detail-loading" v-if="isLoading">加载中…</view>
|
|
|
|
<!-- 不存在 / 无权查看 -->
|
|
<ns-empty v-if="!isLoading && !relation" isIndex="false"
|
|
:text="errorMsg || '卡片不存在或已被删除'"></ns-empty>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
data() {
|
|
return {
|
|
cardId: '',
|
|
relation: null,
|
|
source: null,
|
|
shareList: [],
|
|
isLoading: true,
|
|
errorMsg: ''
|
|
};
|
|
},
|
|
computed: {
|
|
fieldRows() {
|
|
const r = this.relation;
|
|
if (!r) return [];
|
|
|
|
const rows = [];
|
|
const push = (label, value, action) => {
|
|
if (value !== undefined && value !== null && String(value).trim() !== '') {
|
|
rows.push({ label, value: String(value), action: action || null });
|
|
}
|
|
};
|
|
|
|
push('手机', r.mobile, { type: 'call', text: '拨打' });
|
|
push('电话', r.phone, { type: 'call', text: '拨打' });
|
|
push('邮箱', r.email, { type: 'copy', text: '复制' });
|
|
push('微信', r.wechat, { type: 'copy', text: '复制' });
|
|
push('网站', r.website);
|
|
push('地址', [r.country, r.province, r.city, r.address].filter(Boolean).join(' '));
|
|
push('邮编', r.postal_code);
|
|
push('Telegram', r.telegram);
|
|
push('Messenger', r.messenger);
|
|
|
|
return rows;
|
|
}
|
|
},
|
|
onLoad(options) {
|
|
this.cardId = decodeURIComponent(options.card_id || '');
|
|
this.loadDetail();
|
|
},
|
|
methods: {
|
|
avatarText(name) {
|
|
return (name || '?').trim().charAt(0).toUpperCase();
|
|
},
|
|
loadDetail() {
|
|
if (!this.cardId) {
|
|
this.isLoading = false;
|
|
this.errorMsg = '缺少名片编号';
|
|
return;
|
|
}
|
|
this.isLoading = true;
|
|
this.$api.sendRequest({
|
|
url: '/card/api/card/detail',
|
|
data: { card_id: this.cardId },
|
|
success: res => {
|
|
this.isLoading = false;
|
|
if (res.code == 0) {
|
|
const data = res.data || {};
|
|
this.relation = data.relation || null;
|
|
this.source = data.source || null;
|
|
this.shareList = data.share_list || [];
|
|
} else {
|
|
// 后端对"不存在"与"非本人名下"同一报错口径,不区分展示
|
|
this.errorMsg = res.message || '卡片不存在或已被删除';
|
|
this.relation = null;
|
|
}
|
|
},
|
|
fail: () => {
|
|
this.isLoading = false;
|
|
this.errorMsg = '网络异常,请稍后重试';
|
|
uni.showToast({ title: '网络异常,请稍后重试', icon: 'none' });
|
|
}
|
|
});
|
|
},
|
|
callPhone(mobile) {
|
|
if (!mobile) return;
|
|
uni.makePhoneCall({ phoneNumber: mobile });
|
|
},
|
|
copyText2(text) {
|
|
uni.setClipboardData({
|
|
data: text,
|
|
success: () => {
|
|
uni.showToast({ title: '已复制', icon: 'success' });
|
|
}
|
|
});
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.card-detail {
|
|
min-height: 100vh;
|
|
background-color: #f6f7f9;
|
|
padding-bottom: 60rpx;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.detail-head {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 48rpx 32rpx;
|
|
background: linear-gradient(135deg, var(--main-color, #0054a5), var(--main-color-shallow, #3a7bc8));
|
|
color: #ffffff;
|
|
|
|
.head-avatar {
|
|
width: 120rpx;
|
|
height: 120rpx;
|
|
border-radius: 50%;
|
|
background-color: rgba(255, 255, 255, 0.25);
|
|
font-size: 52rpx;
|
|
font-weight: 600;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
margin-right: 28rpx;
|
|
}
|
|
|
|
.head-info {
|
|
min-width: 0;
|
|
|
|
.head-name {
|
|
font-size: 40rpx;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.head-sub {
|
|
font-size: 26rpx;
|
|
opacity: 0.85;
|
|
margin-top: 12rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
.detail-fields {
|
|
margin: 24rpx;
|
|
background-color: #ffffff;
|
|
border-radius: 16rpx;
|
|
overflow: hidden;
|
|
|
|
.field-row {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 28rpx 24rpx;
|
|
border-bottom: 1rpx solid #f0f0f0;
|
|
|
|
&:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.field-label {
|
|
width: 140rpx;
|
|
font-size: 28rpx;
|
|
color: #999;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.field-value {
|
|
flex: 1;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.field-action {
|
|
margin-left: 20rpx;
|
|
flex-shrink: 0;
|
|
font-size: 24rpx;
|
|
color: var(--main-color, #0054a5);
|
|
border: 1rpx solid var(--main-color, #0054a5);
|
|
border-radius: 28rpx;
|
|
padding: 6rpx 24rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
.detail-loading {
|
|
text-align: center;
|
|
color: #999;
|
|
font-size: 26rpx;
|
|
padding: 120rpx 0;
|
|
}
|
|
</style>
|