2026-06-23 15:36:34 +08:00

313 lines
7.7 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view v-if="card" class="business-card" @click="handleClick">
<image class="card-bg" :src="cardBg"></image>
<view class="card-header">
<view class="avatar">
<image :src="card.avatar || '/static/card/avatar.png'" mode="aspectFill"></image>
</view>
<view class="info">
<text class="name">{{ card.externalName || card.anotherName || '' }}</text>
<text v-if="card.hospitalInfo" class="hospital">{{ card.hospitalInfo.name || '' }}</text>
<view class="title-tags">
<text class="title-tag department" v-if="card.deptName">{{ card.deptName }}</text>
<text class="title-tag position" v-if="card.title">{{ card.title }}</text>
</view>
</view>
</view>
<view class="contact-section">
<view class="contact-info">
<!-- <view class="contact-item" v-if="card.externalContact">
<image class="contact-icon" src="/static/card/address.png" mode="aspectFit"></image>
<text class="contact-text">{{ accountInfo.address }}</text>
</view> -->
<view v-if="card.externalContact" class="contact-item">
<image class="contact-icon" src="/static/card/phone.png" mode="aspectFit"></image>
<text class="contact-text">{{ card.externalContact || '' }}</text>
</view>
<view v-if="card.externalEmail" class="contact-item">
<image class="contact-icon" src="/static/card/email.png" mode="aspectFit"></image>
<text class="contact-text">{{ card.externalEmail || '' }}</text>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { computed, onMounted, ref } from "vue";
import { onShow } from '@dcloudio/uni-app'
// import { useCardStore } from "@/stores/card";
// import { useAccountStore } from "@/stores/account";
// import { getDeptStaffDepartments } from "@/api/dept";
const props = defineProps({
card: {
type: [Object, null],
default: null
},
// 点击事件处理函数
onClick: {
type: Function,
default: null,
},
// 背景图片路径
cardBg: {
type: String,
default: "/static/card/card-bg2.png",
},
// 显示模式:'doctor' 医生模式(使用 cardStore 的可见性设置),'patient' 患者模式(直接显示)
mode: {
type: String,
default: "doctor",
validator: (value) => ["doctor", "patient"].includes(value),
},
// 自定义账户信息(如果提供,则使用自定义数据而不是 store
customAccountInfo: {
type: Object,
default: null,
},
// 自定义机构信息(如果提供,则使用自定义数据而不是 store
customInstitutionInfo: {
type: Object,
default: null,
},
// 自定义医生名片状态(如果提供,则使用自定义数据而不是 store
customDoctorCardStatus: {
type: Object,
default: null,
},
});
const emit = defineEmits(["click"]);
const cardStore = ref({});
const accountStore = ref({});
// 获取账户信息(优先使用自定义数据)
const accountInfo = computed(() => {
if (props.customAccountInfo) {
return props.customAccountInfo;
}
return accountStore.getAccountInfo || {};
});
// 部门显示名称(优先使用接口 getDeptStaffDepartments 返回的结果)
const deptDisplayName = ref("");
const displayDeptName = computed(() => {
// 优先展示接口返回的部门字符串,否则回退账户里的 deptName
return deptDisplayName.value || accountInfo.value.deptName || "";
});
// 获取机构信息(优先使用自定义数据)
const institutionInfo = computed(() => {
if (props.customInstitutionInfo) {
return props.customInstitutionInfo;
}
return accountStore.getInstitutionInfo || {};
});
// 获取医生名片状态(优先使用自定义数据)
const doctorCardStatus = computed(() => {
if (props.customDoctorCardStatus) {
return props.customDoctorCardStatus;
}
return accountStore.getDoctorCardStatus || { hasDoctorCard: false };
});
// 根据模式决定是否显示部门名称
const shouldShowDeptName = computed(() => {
if (props.mode === "patient") {
return true; // 患者模式直接显示
}
return cardStore.deptNameVisible; // 医生模式使用 cardStore 设置
});
// 根据模式决定是否显示职位
const shouldShowPosition = computed(() => {
if (props.mode === "patient") {
return true; // 患者模式直接显示
}
return cardStore.positionVisible; // 医生模式使用 cardStore 设置
});
// 根据模式决定是否显示电话
const shouldShowPhone = computed(() => {
if (props.mode === "patient") {
return true; // 患者模式直接显示
}
return cardStore.phoneVisible; // 医生模式使用 cardStore 设置
});
// 根据模式决定是否显示邮箱
const shouldShowEmail = computed(() => {
if (props.mode === "patient") {
return true; // 患者模式直接显示
}
return cardStore.emailVisible; // 医生模式使用 cardStore 设置
});
// 根据模式决定是否显示地址
const shouldShowAddress = computed(() => {
if (props.mode === "patient") {
return true; // 患者模式直接显示
}
return cardStore.addressVisible; // 医生模式使用 cardStore 设置
});
// 处理点击事件
const handleClick = () => {
if (props.onClick) {
props.onClick();
}
emit("click");
};
// 组件挂载后,通过工号 staffId 调用 getDeptStaffDepartments 获取部门显示信息
onShow(async () => {
try {
const staffId = accountInfo.value.staffId;
if (!staffId) return;
const res = await getDeptStaffDepartments({ staffId });
if (res && res.success && Array.isArray(res.data) && res.data.length > 0) {
// 后端返回的是部门名称数组,例如 ["人力资源部/人事培训科/人事培训科"]
deptDisplayName.value = res.data.join("、");
}
} catch (error) {
console.error("获取部门显示信息失败:", error);
}
});
</script>
<style scoped lang="scss">
/* 名片展示区域 */
.business-card {
position: relative;
overflow: visible;
border-bottom-left-radius: 16rpx;
border-bottom-right-radius: 16rpx;
font-size: 0;
}
.card-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
display: block;
}
.card-header {
position: relative;
padding: 36rpx 40rpx 10rpx 40rpx;
display: flex;
align-items: center;
margin-bottom: 36rpx;
}
.contact-section {
position: relative;
z-index: 1;
padding: 0 40rpx 56rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.avatar {
width: 120rpx;
height: 120rpx;
display: flex;
border-radius: 50%;
align-items: center;
justify-content: center;
font-size: 60rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
flex-shrink: 0;
margin-right: 30rpx;
align-self: center;
image {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.name {
display: block;
font-size: 36rpx;
font-weight: 500;
margin-bottom: 6rpx;
color: #222;
}
.hospital {
display: block;
font-size: 26rpx;
margin-bottom: 8rpx;
color: #666;
}
.title-tags {
display: flex;
gap: 16rpx;
margin-top: 8rpx;
}
.title-tag {
font-size: 24rpx;
font-weight: 400;
padding: 0 16rpx;
flex-shrink: 0;
border-radius: 28rpx;
display: flex;
align-items: center;
justify-content: center;
}
.title-tag.department {
color: #ff8b00;
border: 1rpx solid #ff8b00;
}
.title-tag.position {
color: #de4f27;
border: 0.5px solid #de4f27;
}
.contact-info {
display: flex;
flex-direction: column;
gap: 10rpx;
align-items: flex-start;
flex: 1;
}
.contact-item {
display: flex;
align-items: center;
gap: 10rpx;
}
.contact-icon {
width: 32rpx;
height: 32rpx;
}
.contact-text {
font-size: 24rpx;
color: #666;
}
</style>