ykt-team-wxapp/pages/team/business-card.vue
2026-06-25 09:58:57 +08:00

2063 lines
47 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>
<full-page v-if="businessCard">
<view class="card-page">
<view class="card-service-container">
<BusinessCard :card="businessCard" />
<view class="service-section">
<view class="service-grid">
<view class="service-item service-item-1" @click="showTeams()">
<image class="service-item-bg" src="/static/card/jzfwBack.png" mode="aspectFit"></image>
<image class="service-icon" src="/static/card/jzfwIcon.png" mode="aspectFit"></image>
<text class="service-text">全周期管理</text>
</view>
<view class="service-item service-item-3" @click="displayPhone()">
<image class="service-item-bg" src="/static/card/gzhBack.png" mode="aspectFit"></image>
<image class="service-icon" src="/static/card/telephone.svg" mode="aspectFit"></image>
<text class="service-text">联系电话</text>
</view>
<view class="service-item service-item-4" @click="openEmailModal">
<image class="service-item-bg" src="/static/card/sphBack.png" mode="aspectFit"></image>
<image class="service-icon" src="/static/card/email.svg" mode="aspectFit"></image>
<text class="service-text">邮箱</text>
</view>
<view class="service-item service-item-2" @click="openAddressModal">
<image class="service-item-bg" src="/static/card/gwBack.png" mode="aspectFit"></image>
<image class="service-icon" src="/static/card/gwIcon.png" mode="aspectFit"></image>
<text class="service-text">地址</text>
</view>
</view>
</view>
</view>
<view class="info-container">
<!-- Tab 切换栏 -->
<view class="tab-header">
<view v-if="hospitalInfo" class="tab-item" :class="{ active: activeTab === 'hospital' }"
@click="switchTab('hospital')">
<text class="tab-text">医院信息</text>
</view>
<view class="tab-item" :class="{ active: activeTab === 'intro' }" @click="switchTab('intro')">
<text class="tab-text">个人简介</text>
</view>
</view>
<!-- 医院信息内容 -->
<view v-if="hospitalInfo" class="tab-content" :class="{ 'tab-content-left': activeTab === 'hospital' }"
v-show="activeTab === 'hospital'">
<view class="hospital-info">
<view class="hospital-header">
<view class="hospital-logo">
<image :src="hospitalInfo.logo || '/static/card/hospital-icon.png'" mode="aspectFit">
</image>
</view>
<view class="hospital-details">
<text class="hospital-name">
{{ hospitalInfo.name || '未获取到医院名称' }}
</text>
<view class="hospital-tags">
<text class="hospital-tag" :class="getTagClass(index)"
v-for="(tag, index) in (hospitalInfo.tags || [])" :key="tag">{{ tag }}
</text>
</view>
</view>
</view>
<view class="hospital-intro">
<view class="hospital-text-wrapper">
<view v-if="hospitalInfo.introduction" class="hospital-text">
<div v-html="hospitalInfo.introduction"></div>
</view>
<text class="hospital-text" v-else>暂无医院介绍信息</text>
<!-- <view class="more-link" @click="openMoreInfoModal">更多>></view> -->
</view>
</view>
</view>
</view>
<!-- 个人简介内容 -->
<view class="tab-content" :class="{ 'tab-content-right': activeTab === 'intro' }"
v-show="activeTab === 'intro'">
<view class="intro-content">
<view class="intro-header">
<view class="intro-title-bar"></view>
<text class="intro-title">个人简介</text>
</view>
<text class="intro-text" v-if="businessCard && businessCard.memberTroduce">
{{ businessCard.memberTroduce }}
</text>
<text class="intro-text no-data" v-else>暂无个人简介</text>
</view>
</view>
</view>
</view>
<template #footer>
<view class="bottom-actions">
<button class="edit-btn" @click="addFriend()">
<image class="edit-icon" src="/static/card/edit-card.png" mode="aspectFit"></image>
<text class="edit-text">加好友</text>
</button>
<button class="share-btn" open-type="share">
<text class="share-text">转发名片</text>
</button>
</view>
</template>
</full-page>
<!-- 便民服务弹窗 -->
<view v-if="showServiceModal" class="modal-mask" @click="closeServiceModal">
<view class="service-modal-content" @click.stop>
<view class="service-modal-header">
<text class="service-modal-close" @click="closeServiceModal">×</text>
<text class="service-modal-title">便民服务</text>
</view>
<view class="service-modal-body">
<view class="service-list">
<view class="service-list-item" v-for="(service, index) in services" :key="index"
@click="openServiceLink(service)">
<text class="service-list-text">{{ service.label }}</text>
<view class="service-list-icon">🔗</view>
</view>
<view v-if="services.length === 0" class="no-service">
<text class="no-service-text">暂无便民服务</text>
</view>
</view>
</view>
</view>
</view>
<!-- 电话弹窗 -->
<view v-if="showPhoneModal" class="modal-mask" @click="closePhoneModal">
<view class="service-modal-content" @click.stop>
<view class="service-modal-header">
<text class="service-modal-close" @click="closePhoneModal">×</text>
<text class="service-modal-title">电话</text>
</view>
<view class="service-modal-body">
<view class="service-list">
<view class="service-list-item" v-if="businessCard && businessCard.externalContact">
<view class="service-list-text">{{ businessCard.externalContact }}</view>
<view class="flex">
<view class="text-base text-primary mr-10" @click="setClipboardData(businessCard.externalContact)">
复制
</view>
<view class="text-base text-primary" @click="makePhoneCall(businessCard.externalContact)">拨打</view>
</view>
</view>
<view class="service-list-item" v-else>
<text class="service-list-text no-data">暂无电话信息</text>
<view class="service-list-icon">📞</view>
</view>
</view>
</view>
</view>
</view>
<!-- 邮箱弹窗 -->
<view v-if="showEmailModal" class="modal-mask" @click="closeEmailModal">
<view class="service-modal-content" @click.stop>
<view class="service-modal-header">
<text class="service-modal-close" @click="closeEmailModal">×</text>
<text class="service-modal-title">邮箱</text>
</view>
<view class="service-modal-body">
<view class="service-list">
<view class="service-list-item" v-if="businessCard.externalEmail"
@click="copyEmail(businessCard.externalEmail)">
<text class="service-list-text">{{ businessCard.externalEmail }}</text>
<view class="text-base text-primary mr-10" @click="setClipboardData(businessCard.externalEmail)">
复制
</view>
</view>
<view class="service-list-item" v-else>
<text class="service-list-text no-data">暂无邮箱信息</text>
<view class="service-list-icon"></view>
</view>
</view>
</view>
</view>
</view>
<!-- 地址弹窗 -->
<view v-if="showAddressModal" class="modal-mask" @click="closeAddressModal">
<view class="service-modal-content" @click.stop>
<view class="service-modal-header">
<text class="service-modal-close" @click="closeAddressModal">×</text>
<text class="service-modal-title">地址</text>
</view>
<view class="service-modal-body">
<view class="service-list">
<view class="service-list-item" v-if="businessCard.externalAddress"
@click="setClipboardData(businessCard.externalAddress)">
<text class="service-list-text">{{ businessCard.externalAddress }}</text>
<view class="text-base text-primary" @click="setClipboardData(businessCard.externalAddress)">
复制
</view>
</view>
<view class="service-list-item" v-else>
<text class="service-list-text no-data">暂无地址信息</text>
<view class="service-list-icon">📍</view>
</view>
</view>
</view>
</view>
</view>
<!-- 医院介绍弹窗 -->
<view v-if="showMoreInfoModal" class="modal-mask" @click="closeMoreInfoModal">
<view class="more-info-modal-content" @click.stop @touchmove.stop.prevent>
<view class="more-info-modal-header">
<text class="more-info-modal-title">医院介绍</text>
<text class="more-info-modal-close" @click="closeMoreInfoModal">×</text>
</view>
<scroll-view class="more-info-modal-body" scroll-y="true" show-scrollbar="true">
<view class="more-info-content" v-if="institutionInfo?.introduction">
<rich-text :nodes="institutionInfo.introduction"></rich-text>
</view>
<view class="more-info-text" v-else>
<text class="no-data-text">暂无医院介绍信息</text>
</view>
</scroll-view>
</view>
</view>
<!-- 公众号弹窗 -->
<view v-if="showOfficialAccountModal" class="modal-mask" @click="closeOfficialAccountModal">
<view class="link-modal-content" @click.stop>
<view class="link-modal-header">
<text class="link-modal-title">广医一院公众号</text>
<text class="link-modal-close" @click="closeOfficialAccountModal">×</text>
</view>
<view class="link-modal-body">
<view class="qr-code-placeholder">
<view class="qr-code-image">
<image src="/static/card/服务号.jpg" mode="aspectFit"></image>
</view>
</view>
<text class="link-modal-desc">扫描或长按二维码进入</text>
</view>
</view>
</view>
<teams-popup :visible="showTeamPopup" :teams="teams" @close="showTeamPopup = false" />
</template>
<script setup>
import { ref, computed } from 'vue';
import { storeToRefs } from "pinia";
import { onShareAppMessage } from "@dcloudio/uni-app";
import api from '@/utils/api';
import useGuard from '@/hooks/useGuard';
import { toast } from '@/utils/widget.js';
import useAccount from '@/store/account';
import BusinessCard from './components/BusinessCard.vue'
import fullPage from '@/components/full-page.vue'
import TeamsPopup from './components/teams-popup.vue'
const { useShow, useLoad } = useGuard();
const wxAccountStore = useAccount();
const { account } = storeToRefs(useAccount());
const env = __VITE_ENV__;
const shareAppVersion = env.MP_SHARE_WX_APP_VERSION;
const corpId = ref('');
const userid = ref('')
const businessCard = ref(null);
const teams = ref([])
const showTeamPopup = ref(false)
const hospitalInfo = computed(() => businessCard.value?.hospitalInfo || null);
function makePhoneCall(phone) {
closePhoneModal()
uni.makePhoneCall({
phoneNumber: phone,
success: () => {
toast('拨打电话成功')
}
})
}
function setClipboardData(data) {
uni.setClipboardData({
data: data,
success: () => {
toast('复制成功')
}
})
}
async function getCard() {
const res = await api('getBusinessCard', { userid: userid.value, corpId: corpId.value })
businessCard.value = res && res.data ? res.data : null;
if (businessCard.value) {
recordBusinessCardVisit()
}
}
async function displayPhone() {
if (businessCard.value.externalContact) {
showPhoneModal.value = true
}
}
async function showTeams() {
const res = await api('getJoinedTeams', { mateId: userid.value, corpId: corpId.value })
teams.value = res && Array.isArray(res.data) ? res.data : [];
if (teams.value.length === 0) {
toast('暂无加入的团队')
} else {
showTeamPopup.value = true
}
}
async function recordBusinessCardVisit() {
try {
const account = await getVisitorAccount();
let visitorExternalUserId = wxAccountStore.externalUserId || "";
if (!visitorExternalUserId && account && account.unionid && account.openid && corpId.value) {
visitorExternalUserId = await wxAccountStore.getExternalUserId(corpId.value) || "";
}
const response = await api('recordBusinessCardBehavior', {
action: "visit",
corpId: corpId.value,
cardUserid: userid.value,
cardDeptName: businessCard.value?.deptName || "",
source: "team-wxapp",
visitorOpenid: account?.openid || wxAccountStore.openid || uni.getStorageSync('openid') || "",
visitorUnionid: account?.unionid || "",
visitorMobile: account?.mobile || "",
visitorExternalUserId,
}, false);
if (!response?.success) {
console.warn("record business card visit failed", response?.message || response);
}
} catch (error) {
console.warn("record business card visit failed", error);
}
}
async function getVisitorAccount() {
let account = wxAccountStore.account || uni.getStorageSync('account') || null;
if (!account) {
account = await wxAccountStore.login('', { silent: true });
}
return account || wxAccountStore.account || uni.getStorageSync('account') || null;
}
useLoad((opt) => {
corpId.value = opt.corpId
userid.value = opt.userid
})
useShow(() => {
getCard()
})
onShareAppMessage((res) => {
if (businessCard.value) {
return {
title: `${businessCard.value.externalName || card.anotherName || ''}】电子名片`,
type: shareAppVersion || 0, // 0 正式版本 | 1 开发版本 | 2 体验版本
path: `/pages/team/business-card?corpId=${corpId.value}&userid=${userid.value}&shareOpenId=${account.value?.openid || ''}`
}
}
})
const cardStore = ref({})
const accountStore = ref({})
// 获取账户信息
const accountInfo = computed(() => accountStore.getAccountInfo || {})
const institutionInfo = computed(() => accountStore.getInstitutionInfo || {})
// 获取医生名片状态
const doctorCardStatus = computed(() => accountStore.getDoctorCardStatus)
// 判断是否有联系方式
const hasContactInfo = computed(() => {
return cardStore.phoneVisible || cardStore.emailVisible || cardStore.addressVisible
})
// 弹窗显示状态
const showServiceModal = ref(false)
const showPhoneModal = ref(false)
const showEmailModal = ref(false)
const showAddressModal = ref(false)
const showMoreInfoModal = ref(false)
const showOfficialAccountModal = ref(false)
const showVideoAccountModal = ref(false)
const showShareModal = ref(false)
// 便民服务列表
const services = ref([])
// Tab 切换状态
const activeTab = ref('hospital') // 'hospital' 或 'intro'
// 切换 tab
const switchTab = (tab) => {
activeTab.value = tab
}
// 初始化 tab 状态
const initTab = () => {
// 如果只有个人简介,默认显示个人简介
if (!institutionInfo.value?.showHomepage) {
activeTab.value = 'intro'
}
// 如果只有医院信息,默认显示医院信息
else if (!accountInfo.value.introduction) {
activeTab.value = 'hospital'
}
// 如果两者都有,默认显示医院信息
else {
activeTab.value = 'hospital'
}
}
// 防止在同一次拉取过程中重复创建名片
let isAutoCreatingCard = false
const goToCard = () => {
uni.navigateTo({
url: '/pages/card/card'
})
}
// 获取标签样式类名
const getTagClass = (index) => {
const styles = ['grade', 'center', 'specialty']
return styles[index % 3]
}
const goToQRCode = () => {
uni.navigateTo({
url: '/pages/card/code'
})
}
// 跳转到保存名片页
const goToSave = () => {
uni.navigateTo({
url: '/pages/business-card/card-qrcode/card-qrcode'
})
}
// 处理Banner图片点击
const handleBannerClick = (item) => {
if (!item || !item.link) {
return
}
const link = item.link
// 判断是否为外部链接
if (link.startsWith('http://') || link.startsWith('https://')) {
// #ifdef H5
window.open(link, '_blank')
// #endif
// #ifdef APP-PLUS
plus.runtime.openURL(link)
// #endif
// #ifdef MP-WEIXIN
// 微信小程序中,需要先复制链接,然后提示用户
uni.setClipboardData({
data: link,
success: () => {
uni.showToast({
title: '链接已复制',
icon: 'success'
})
}
})
// #endif
} else {
// 内部链接,使用导航
uni.navigateTo({
url: link
})
}
}
// 打开便民服务弹窗
const openServiceModal = () => {
showServiceModal.value = true
}
// 关闭便民服务弹窗
const closeServiceModal = () => {
showServiceModal.value = false
}
// 打开便民服务链接
const openServiceLink = (service) => {
if (service.url) {
// 关闭弹窗
closeServiceModal()
// 显示确认对话框
uni.showModal({
title: '提示',
content: `即将跳转到:${service.label}`,
success: (res) => {
if (res.confirm) {
uni.showToast({
title: '正在跳转中...',
icon: 'none'
})
// #ifdef H5
// H5环境下使用window.open打开外部链接
window.open(service.url, '_blank')
// #endif
// #ifdef MP-WEIXIN
// 微信小程序环境下使用uni.navigateToMiniProgram或提示用户
uni.showToast({
title: '请在浏览器中打开链接',
icon: 'none',
duration: 2000
})
// #endif
// #ifdef APP-PLUS
// App环境下使用plus.runtime.openURL
plus.runtime.openURL(service.url)
// #endif
}
}
})
} else {
uni.showToast({
title: '该服务暂无链接',
icon: 'none'
})
}
}
// 打开电话弹窗
const openPhoneModal = () => {
showPhoneModal.value = true
}
// 关闭电话弹窗
const closePhoneModal = () => {
showPhoneModal.value = false
}
// 打开邮箱弹窗
const openEmailModal = () => {
showEmailModal.value = true
}
// 关闭邮箱弹窗
const closeEmailModal = () => {
showEmailModal.value = false
}
// 打开地址弹窗
const openAddressModal = () => {
showAddressModal.value = true
}
// 关闭地址弹窗
const closeAddressModal = () => {
showAddressModal.value = false
}
// 打开医院介绍弹窗
const openMoreInfoModal = () => {
showMoreInfoModal.value = true
}
// 关闭医院介绍弹窗
const closeMoreInfoModal = () => {
showMoreInfoModal.value = false
}
// 打开公众号弹窗
const openOfficialAccountModal = () => {
showOfficialAccountModal.value = true
}
// 关闭公众号弹窗
const closeOfficialAccountModal = () => {
showOfficialAccountModal.value = false
}
// 打开视频号弹窗
const openVideoAccountModal = () => {
showVideoAccountModal.value = true
}
// 关闭视频号弹窗
const closeVideoAccountModal = () => {
showVideoAccountModal.value = false
}
// 处理人才招聘点击
const handleRecruitClick = () => {
const recruitUrl = 'https://www.gyfyyy.cn/cn/wap/news/xwsd/'
openExternalLink(recruitUrl)
}
// 处理官网点击
const handleWebsiteClick = () => {
const websiteUrl = 'https://www.gyfyyy.cn/'
openExternalLink(websiteUrl)
}
// 打开外部链接的通用方法
const openExternalLink = (url) => {
if (!url) {
uni.showToast({
title: '链接地址无效',
icon: 'none'
})
return
}
// 判断是否为外部链接
if (url.startsWith('http://') || url.startsWith('https://')) {
// #ifdef H5
window.open(url, '_blank')
// #endif
// #ifdef APP-PLUS
plus.runtime.openURL(url)
// #endif
// #ifdef MP-WEIXIN
// 微信小程序中,需要先复制链接,然后提示用户
uni.setClipboardData({
data: url,
success: () => {
uni.showModal({
title: '提示',
content: '链接已复制到剪贴板,请在浏览器中打开',
showCancel: false
})
}
})
// #endif
} else {
// 内部链接,使用导航
uni.navigateTo({
url: url
})
}
}
// 处理来院导航点击
const handleNavigationClick = () => {
// 跳转到导航页面
uni.navigateTo({
url: '/pages/navigation/index'
})
}
// 打开官网
const openWebsite = () => {
// 在微信小程序中打开外部网址
uni.showModal({
title: '提示',
content: '即将打开医院官网,是否继续?',
success: (res) => {
if (res.confirm) {
uni.showToast({
title: '正在跳转中...',
icon: 'none',
duration: 1500
})
}
}
})
}
// 打开互联网医院
const openInternetHospital = () => {
// 在微信小程序中打开外部网址
uni.showModal({
title: '提示',
content: '即将打开互联网医院平台,是否继续?',
success: (res) => {
if (res.confirm) {
uni.showToast({
title: '正在跳转中...',
icon: 'none',
duration: 3000
})
}
}
})
}
// 打开分享弹窗
const openShareModal = () => {
showShareModal.value = true
}
// 关闭分享弹窗
const closeShareModal = () => {
showShareModal.value = false
}
// 分享到企业微信
const shareToWechatWork = () => {
uni.showToast({
title: '分享到企业微信...',
icon: 'none'
})
closeShareModal()
}
// 分享到微信
const shareToWechat = () => {
uni.showToast({
title: '分享到微信...',
icon: 'none'
})
closeShareModal()
}
// 跳转到编辑名片页
const addFriend = () => {
uni.navigateTo({
url: `/pages/team/friend?corpId=${corpId.value}&userid=${userid.value}`
})
}
// 复制邮箱地址
const copyEmail = (email) => {
closeEmailModal()
// #ifdef H5
// H5环境下使用navigator.clipboard API
if (navigator.clipboard) {
navigator.clipboard.writeText(email).then(() => {
uni.showToast({
title: '邮箱已复制',
icon: 'none'
})
}).catch(() => {
// 降级方案:使用传统方法
const textArea = document.createElement('textarea')
textArea.value = email
document.body.appendChild(textArea)
textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
uni.showToast({
title: '邮箱已复制',
icon: 'none'
})
})
} else {
// 降级方案
const textArea = document.createElement('textarea')
textArea.value = email
document.body.appendChild(textArea)
textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
uni.showToast({
title: '邮箱已复制',
icon: 'none'
})
}
// #endif
// #ifdef MP-WEIXIN || APP-PLUS
// 微信小程序和App环境下使用uni.setClipboardData
uni.setClipboardData({
data: email,
success: () => {
uni.showToast({
title: '邮箱已复制',
icon: 'none'
})
},
fail: () => {
uni.showToast({
title: '复制失败',
icon: 'none'
})
}
})
// #endif
}
// 打开地图
const openMap = (address) => {
// 关闭地址弹窗
closeAddressModal()
// #ifdef H5
// H5环境下使用百度地图或高德地图网页版
uni.showModal({
title: '提示',
content: '即将在浏览器中打开地图,是否继续?',
success: (res) => {
if (res.confirm) {
// 使用百度地图网页版
const mapUrl = `https://api.map.baidu.com/geocoder?address=${encodeURIComponent(address)}&output=html&src=webapp.baidu.openAPIdemo`
window.open(mapUrl, '_blank')
}
}
})
// #endif
// #ifdef MP-WEIXIN || APP-PLUS
// 微信小程序和App环境下使用uni.openLocation
uni.openLocation({
latitude: 23.1291, // 广州的纬度
longitude: 113.2644, // 广州的经度
name: '广州医科大学附属第一医院',
address: address,
scale: 18,
success: () => {
console.log('地图打开成功')
},
fail: (err) => {
console.error('地图打开失败:', err)
// 如果打开地图失败,提供备选方案
uni.showModal({
title: '提示',
content: '无法打开地图,是否复制地址到剪贴板?',
success: (res) => {
if (res.confirm) {
uni.setClipboardData({
data: address,
success: () => {
uni.showToast({
title: '地址已复制',
icon: 'none'
})
}
})
}
}
})
}
})
// #endif
}
const getDoctorCardListData = async () => {
try {
const res = await getDoctorCardList({
staffId: accountStore.getAccountInfo.staffId
})
// 更新医生名片状态和基本信息
if (res.success && res.data) {
// 提取基本信息如果API返回了医生信息
const basicInfo = res.data.staffInfo ? {
staffId: res.data.staffInfo.staffId || accountStore.getAccountInfo.staffId,
staffName: res.data.staffInfo.staffName || accountStore.getAccountInfo.staffName,
hospitalId: res.data.staffInfo.hospitalId || accountStore.getAccountInfo.hospitalId,
hospitalName: res.data.staffInfo.hospitalName || accountStore.getAccountInfo.hospitalName,
position: res.data.staffInfo.position || accountStore.getAccountInfo.position,
jobTitle: res.data.staffInfo.jobTitle || accountStore.getAccountInfo.jobTitle,
professionalTitle: res.data.staffInfo.professionalTitle || accountStore.getAccountInfo.professionalTitle,
phone: res.data.staffInfo.phone || accountStore.getAccountInfo.phone,
enterpriseWechatId: res.data.staffInfo.enterpriseWechatId || accountStore.getAccountInfo.enterpriseWechatId,
email: res.data.staffInfo.email || accountStore.getAccountInfo.email,
address: res.data.staffInfo.address || accountStore.getAccountInfo.address,
photo: res.data.staffInfo.photo || accountStore.getAccountInfo.photo,
introduction: res.data.staffInfo.introduction || accountStore.getAccountInfo.introduction,
departments: res.data.staffInfo.departments || accountStore.getAccountInfo.departments
} : null;
accountStore.updateDoctorCardStatus(
res.data.hasCards || false,
res.data.message || '',
basicInfo
)
// 当接口返回明确没有名片时:自动创建名片,然后重新拉取列表
if (res.data.hasCards === false) {
if (!isAutoCreatingCard) {
isAutoCreatingCard = true
try {
const account = accountStore.getAccountInfo
const departments = accountStore.getDepartments || []
const primaryDept =
departments.find((d) => d.isPrimary) || departments[0]
const externalDisplay = {
phone: cardStore.phoneVisible,
email: cardStore.emailVisible,
address: cardStore.addressVisible,
deptName: cardStore.deptNameVisible,
position: cardStore.positionVisible
}
const convenienceServices = (cardStore.services || []).map((service) => ({
serviceName: service.label || service.serviceName || '',
serviceUrl: service.url || service.serviceUrl || ''
}))
const requestData = {
staffId: account.staffId,
shareMessage: cardStore.shareMessage,
phone: account.phone,
email: account.email,
address: account.address,
position: account.position,
photo: account.photo,
introduction: account.introduction,
externalDisplay,
convenienceServices
}
// 设置主部门(保持与 edit-card.vue 一致)
if (primaryDept?.deptId) {
requestData.deptId = primaryDept.deptId
await setDeptStaffPrimary({
staffId: account.staffId,
primaryDeptId: primaryDept.deptId
})
accountStore.updatePrimaryDepartment(primaryDept.deptId)
}
uni.showLoading({ title: '正在创建名片...' })
const createRes = await createDoctorCard(requestData)
uni.hideLoading()
if (!createRes?.success) {
throw new Error(createRes?.message || '创建名片失败')
}
// 创建成功后重新拉取列表
await getDoctorCardListData()
return
} catch (error) {
uni.hideLoading()
uni.showToast({
title: '名片创建失败,请稍后重试',
icon: 'none',
duration: 2000
})
console.error('自动创建名片失败:', error)
} finally {
isAutoCreatingCard = false
}
}
}
// 更新名片列表数据
if (res.data.hasCards && res.data.cards) {
// 使用接口返回的名片数据
const newCardList = res.data.cards.map(card => ({
name: accountStore.getAccountInfo.staffName || '未知',
hospital: accountStore.getAccountInfo.hospitalName || '',
title: `${accountStore.getAccountInfo.deptName || ''} ${accountStore.getAccountInfo.position || ''}`,
version: card.version || '',
cardId: card.cardId
}))
// 更新cardStore中的名片列表
cardStore.setCardList(newCardList)
console.log('cardList:', newCardList)
// 如果当前没有选中的名片,或者当前选中的名片不在新列表中,则选择第一张
if (!cardStore.currentCardId || !newCardList.some(card => card.cardId === cardStore.currentCardId)) {
const firstCardId = newCardList[0].cardId || ''
cardStore.setCurrentCardId(firstCardId)
console.log('设置第一张名片为当前选中:', firstCardId)
// 更新名片缓存数据
await updateCardCache(firstCardId)
} else {
// 更新当前选中名片的缓存数据
await updateCardCache(cardStore.currentCardId)
}
} else {
// 如果没有名片,使用默认数据
const account = accountStore.getAccountInfo
const defaultCardList = [{
name: account.staffName || '',
hospital: account.hospitalName || '',
title: `${account.deptName || ''} ${account.position || ''}`,
version: '全员通用版',
cardId: 'default'
}]
cardStore.setCardList(defaultCardList)
cardStore.setCurrentCardId('default')
}
}
} catch (error) {
console.error('获取名片列表失败:', error)
// 如果获取失败,默认设置为没有名片
accountStore.updateDoctorCardStatus(false, '获取名片信息失败')
cardId.value = ''
// 使用默认名片数据
const account = accountStore.getAccountInfo
const defaultCardList = [{
name: account.staffName || '',
hospital: account.hospitalName || '',
title: `${account.deptName || ''} ${account.position || ''}`,
version: '全员通用版',
cardId: 'default'
}]
cardStore.setCardList(defaultCardList)
cardStore.setCurrentCardId('default')
}
}
// 更新名片缓存数据
const updateCardCache = async (cardId) => {
if (!cardId) return
try {
console.log('开始获取名片详情并更新缓存cardId:', cardId)
const detailRes = await getDoctorCardDetail({ cardId })
if (detailRes.success && detailRes.data) {
const cardData = detailRes.data
console.log('名片详情数据:', cardData)
// 更新名片分享语
if (cardData.shareMessage) {
cardStore.shareMessage = cardData.shareMessage
}
// 更新对外信息展示配置
if (cardData.externalDisplay) {
cardStore.updateContactVisibility(
cardData.externalDisplay.phone || false,
cardData.externalDisplay.email || false,
cardData.externalDisplay.address || false,
cardData.externalDisplay.deptName || false,
cardData.externalDisplay.position || false
)
}
// 更新便民服务
if (cardData.convenienceServices && cardData.convenienceServices.length > 0) {
cardStore.services = cardData.convenienceServices.map(service => ({
label: service.serviceName,
url: service.serviceUrl
}))
}
// 更新审核状态到缓存
if (cardData.auditStatus) {
cardStore.setAuditStatus(cardData.auditStatus)
console.log('名片审核状态已缓存:', cardData.auditStatus)
}
// 保存到本地存储
cardStore.saveToStorage()
console.log('名片缓存数据已更新')
}
} catch (error) {
console.error('更新名片缓存失败:', error)
}
}
</script>
<style scoped lang="scss">
/* 模态框遮罩层 */
.modal-mask {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: flex-end;
justify-content: center;
z-index: 1000;
touch-action: none;
overflow: hidden;
}
.card-page {
background-color: #F8EEE3;
min-height: 100vh;
padding-bottom: 120rpx;
/* 为底部固定按钮栏留出空间 */
}
.card-page::before {
content: '';
position: absolute;
top: -20rpx;
left: 0;
right: 0;
height: 320rpx;
background: linear-gradient(180deg, #EB6625 0%, #F8EEE3 100%);
z-index: 0;
}
/* 名片和服务容器 */
.card-service-container {
border-radius: 20rpx;
overflow: hidden;
position: relative;
}
/* 服务图标区域 */
.service-section {
margin: -10rpx 20rpx 0rpx;
}
.service-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
}
.service-item {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
padding: 36rpx 40rpx;
background-position: center;
background-repeat: no-repeat;
border-radius: 20rpx;
position: relative;
overflow: hidden;
background-size: 114% 150%;
}
.service-item-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
}
// .service-item-1 {
// background-image: url('/static/card/jzfwBack.png');
// }
// .service-item-2 {
// background-image: url('/static/card/gwBack.png');
// }
// .service-item-3 {
// background-image: url('/static/card/gzhBack.png');
// }
// .service-item-4 {
// background-image: url('/static/card/sphBack.png');
// }
.service-icon {
width: 72rpx;
height: 72rpx;
display: flex;
align-items: center;
justify-content: center;
position: relative;
z-index: 1;
margin-right: 48rpx;
}
.service-text {
font-size: 28rpx;
color: #fff;
text-align: center;
font-weight: 500;
position: relative;
z-index: 1;
}
/* 禁用状态的样式 */
.service-item.disabled {
opacity: 0.5;
pointer-events: none;
filter: grayscale(50%);
}
.service-icon.disabled {
filter: grayscale(100%);
opacity: 0.6;
}
.service-text.disabled {
color: rgba(255, 255, 255, 0.6);
}
/* 信息容器通用样式 */
.info-container {
overflow: hidden;
margin: 24rpx 20rpx;
position: relative;
padding: 0;
}
/* 人才招聘和导航按钮 */
.action-buttons {
display: flex;
gap: 20rpx;
margin: 20rpx;
}
.action-btn {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 12rpx;
padding: 24rpx 20rpx;
border-radius: 10px;
border: 1px solid #ffbf6533;
background: linear-gradient(95deg, #FFF5DB 16.63%, #FFECDE 92.44%);
box-shadow: 0 9px 15.6px 0 #FFF inset;
transition: all 0.3s ease;
}
.action-btn:active {
transform: scale(0.98);
opacity: 0.9;
}
.action-icon {
width: 48rpx;
height: 48rpx;
flex-shrink: 0;
}
.action-text {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
/* Tab 切换栏样式 */
.tab-header {
display: flex;
background-color: #F8EEE3;
border-radius: 20rpx 20rpx 0 0;
padding: 0;
overflow: visible;
position: relative;
}
.tab-item {
flex: 1;
padding: 24rpx 0;
text-align: center;
background: linear-gradient(83deg, #eb662566 15.22%, #faae5766 77.02%);
transition: background 0.3s ease, clip-path 0.3s ease, transform 0.3s ease;
cursor: pointer;
position: relative;
z-index: 1;
}
.tab-item:last-child {
margin-right: 0;
}
/* 未选中的 tab - 左侧 */
.tab-item:first-child:not(.active) {
border-radius: 20rpx 0 0 0;
/* 左边垂直,右边倾斜(上宽下窄),延伸到右侧区域 */
clip-path: polygon(0 0, 100% 0, 92% 100%, 0 100%);
/* 缩小未选中的 tab */
transform: scale(0.95);
}
/* 未选中的 tab - 右侧 */
.tab-item:last-child:not(.active) {
border-radius: 0 20rpx 0 0;
/* 右边垂直,左边倾斜(上宽下窄),延伸到左侧区域 */
clip-path: polygon(0% 0, 100% 0, 100% 100%, 4% 100%);
/* 缩小未选中的 tab */
transform: scale(0.95);
}
/* 选中的 tab - 背景变为白色渐变,上窄下宽,占据另一个 tab 的下底 */
.tab-item.active {
background: linear-gradient(178deg, #FEF4E8 10.53%, #fff 100%);
transition: background 0.3s ease, clip-path 0.3s ease, transform 0.3s ease;
z-index: 2;
/* 选中状态保持正常大小 */
transform: scale(1);
}
/* 选中左侧 tab医院信息左边直角边右边斜边上窄下宽下底宽 */
.tab-item.active:first-child {
border-radius: 20rpx 0 0 0;
/* 左边垂直(直角边),右边倾斜(斜边,上窄下宽),延伸到右侧 tab 区域 */
clip-path: polygon(0 0, 92% 0, 100% 100%, 0 100%);
/* 使用负边距让两个 tab 重叠,消除中间空隙 */
margin-right: -8%;
}
/* 选中右侧 tab个人简介右边直角边左边斜边上窄下宽下底宽 */
.tab-item.active:last-child {
border-radius: 0rpx 20rpx 0 0;
/* 右边垂直(直角边),左边倾斜(斜边,上窄下宽),延伸到左侧 tab 区域 */
clip-path: polygon(8% 0, 100% 0, 100% 100%, 0 100%);
/* 使用负边距让两个 tab 重叠,消除中间空隙 */
margin-left: -8%;
}
.tab-item.active:only-child {
border-radius: 20rpx 20rpx 0 0;
/* 只有一个 tab 时,保持矩形,不需要梯形 */
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}
.tab-text {
font-size: 32rpx;
color: #333;
font-weight: 500;
position: relative;
display: inline-block;
transition: all 0.3s ease;
}
.tab-item.active .tab-text {
font-weight: bold;
color: #333;
}
/* 选中 tab 文字下方的橙红色下划线 */
.tab-item.active .tab-text::after {
content: '';
position: absolute;
bottom: -4rpx;
left: 0;
width: 100%;
height: 16rpx;
/* 颜色渐变:从深橙红色到浅色 */
background: linear-gradient(90deg, #EF8839 0%, rgba(239, 136, 57, 0.4) 70%, rgba(239, 136, 57, 0.1) 100%);
border-radius: 20rpx;
/* 使用 transform scaleX 实现从粗到细的效果,从左侧开始 */
transform: scaleX(1);
transform-origin: left center;
/* 添加过渡动画 */
transition: transform 0.3s ease;
/* 通过 mask 或 clip-path 实现从粗到细的视觉效果,粗的部分占据更大比例 */
clip-path: polygon(0 0, 100% 0, 97% 100%, 3% 100%);
}
/* Tab 内容区域 */
.tab-content {
padding: 20rpx 40rpx 30rpx;
background-color: #fff;
}
/* 选中左侧 tab医院信息时的内容区域 - 左上角有圆角,底部圆角 */
.tab-content-left {
border-radius: 0 20rpx 20rpx 20rpx;
}
/* 选中右侧 tab个人简介时的内容区域 - 右上角有圆角,底部圆角 */
.tab-content-right {
border-radius: 20rpx 0 20rpx 20rpx;
}
.section-header {
margin-bottom: 30rpx;
}
.section-title-wrapper {
position: relative;
display: inline-block;
margin-bottom: 20rpx;
width: fit-content;
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
position: relative;
z-index: 2;
}
.title-decoration {
position: absolute;
bottom: -8rpx;
left: 0;
width: 144rpx;
height: 28rpx;
flex-shrink: 0;
border-radius: 4rpx;
background: linear-gradient(90deg, #FAAE57 0%, rgba(255, 255, 255, 0.64) 100%);
z-index: 1;
}
.hospital-info {
margin-top: 0;
}
.hospital-header {
display: flex;
align-items: flex-start;
gap: 20rpx;
margin-bottom: 20rpx;
}
.hospital-logo {
font-size: 48rpx;
flex-shrink: 0;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.hospital-logo image {
width: 100%;
height: 100%;
}
.hospital-details {
flex: 1;
}
.hospital-name {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 16rpx;
display: block;
}
.hospital-tags {
display: flex;
gap: 12rpx;
flex-wrap: wrap;
}
.hospital-tag {
font-size: 20rpx;
font-weight: 400;
padding: 0 16rpx;
line-height: 36rpx;
flex-shrink: 0;
border-radius: 4rpx;
}
.hospital-tag.grade {
border: 1rpx solid #2f8af580;
background: #2f8af51a;
color: #037AFF;
}
.hospital-tag.center {
border: 1rpx solid #fb791e80;
background: #ef88391a;
color: #fb791e;
}
.hospital-tag.specialty {
border: 1rpx solid #12b2b380;
background: #12b2b31a;
color: #12b2b3;
}
/* Banner轮播样式 */
.banner-section {
margin: 30rpx 0;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
.banner-swiper {
width: 100%;
aspect-ratio: 3 / 1;
border-radius: 16rpx;
/* 兼容不支持 aspect-ratio 的浏览器,使用 calc 计算 3:1 比例 */
height: calc(100vw / 3);
}
.banner-item {
width: 100%;
height: 100%;
position: relative;
}
.banner-image {
width: 100%;
height: 100%;
border-radius: 16rpx;
}
.hospital-intro {
display: flex;
/* 解决伪元素height:100%失效的问题 */
margin-bottom: 30rpx;
}
.hospital-text-wrapper {
overflow: hidden;
line-height: 1.6;
position: relative;
/* 使用webkit-line-clamp实现多行文本省略 */
display: -webkit-box;
-webkit-line-clamp: 3;
line-clamp: 3;
/* 标准属性,提升兼容性 */
-webkit-box-orient: vertical;
}
.hospital-text {
font-size: 28rpx;
color: #666;
line-height: 1.6;
display: block;
letter-spacing: 0.4rpx;
}
.more-link {
color: #ffb366;
position: absolute;
/* 改为绝对定位 */
right: 0;
bottom: 0;
font-size: 24rpx;
font-weight: 500;
background: #fff;
padding-left: 8rpx;
z-index: 1;
/* 确保按钮在最上层 */
}
.more-link::before {
content: '...';
color: #999;
font-size: 14px;
margin-right: 8rpx;
}
.hospital-links {
display: flex;
justify-content: space-between;
}
.link-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 12rpx;
flex: 1;
}
.link-icon {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.link-text {
font-size: 22rpx;
color: #666;
text-align: center;
}
/* 个人擅长内容 */
.expertise-content {
margin-top: 20rpx;
min-height: 120rpx;
}
.expertise-text {
font-size: 26rpx;
color: #666;
line-height: 1.6;
}
.expertise-text.no-data {
color: #999;
}
.intro-content {
margin-top: 0;
min-height: 120rpx;
}
.intro-header {
display: flex;
align-items: center;
margin-bottom: 20rpx;
gap: 12rpx;
}
.intro-title-bar {
width: 6rpx;
height: 32rpx;
background: #EF8839;
border-radius: 3rpx;
}
.intro-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.intro-text {
font-size: 28rpx;
color: #666;
line-height: 1.6;
display: block;
letter-spacing: 0.4rpx;
}
.intro-text.no-data {
color: #999;
}
/* 底部操作按钮 */
.bottom-actions {
padding: 20rpx 40rpx;
display: flex;
gap: 20rpx;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1);
}
.edit-btn {
flex: 1;
height: 80rpx;
background: #f8f9fa;
border: 2rpx solid #e0e0e0;
border-radius: 100rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 8rpx;
}
.edit-icon {
width: 32rpx;
height: 32rpx;
}
.edit-text {
font-size: 26rpx;
color: #666;
}
.share-btn {
flex: 2;
height: 80rpx;
background: #E86B3E;
border: none;
border-radius: 100rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
.share-text {
font-size: 28rpx;
color: #fff;
font-weight: bold;
}
/* 便民服务弹窗样式 */
.service-modal-content {
background: white;
border-radius: 20rpx 20rpx 0 0;
width: 100%;
overflow: hidden;
}
.service-modal-header {
position: relative;
padding: 40rpx 40rpx 20rpx;
text-align: center;
border-bottom: 1rpx solid #f0f0f0;
}
.service-modal-close {
position: absolute;
left: 40rpx;
top: 40rpx;
font-size: 40rpx;
color: #999;
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
transition: all 0.3s ease;
}
.service-modal-close:active {
background: #f0f0f0;
}
.service-modal-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
}
.service-modal-body {
padding: 30rpx 40rpx;
}
.service-list {
display: flex;
flex-direction: column;
gap: 20rpx;
}
.service-list-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 25rpx;
}
.service-list-text {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
.service-list-text.no-data {
color: #999;
font-weight: normal;
}
.service-list-icon {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
color: #666;
}
/* 医院介绍弹窗样式 */
.more-info-modal-content {
background: white;
border-radius: 20rpx 20rpx 0 0;
width: 100%;
overflow: hidden;
}
.more-info-modal-header {
position: relative;
padding: 40rpx 40rpx 20rpx;
text-align: center;
border-bottom: 1rpx solid #f0f0f0;
}
.more-info-modal-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
}
.more-info-modal-close {
position: absolute;
right: 40rpx;
top: 40rpx;
font-size: 40rpx;
color: #999;
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
transition: all 0.3s ease;
}
.more-info-modal-close:active {
background: #f0f0f0;
}
.more-info-modal-body {
padding: 20rpx 0;
margin-bottom: 20rpx;
max-height: 60vh;
box-sizing: border-box;
width: 100%;
}
.more-info-text {
padding: 0 40rpx;
margin-bottom: 20rpx;
}
.more-info-content {
padding: 0 40rpx;
margin-bottom: 20rpx;
font-size: 26rpx;
color: #666;
line-height: 1.6;
}
.more-info-content :deep(p) {
margin-bottom: 20rpx;
}
.more-info-content :deep(img) {
max-width: 100%;
height: auto;
margin: 20rpx 0;
border-radius: 8rpx;
}
.more-info-content :deep(strong) {
font-weight: bold;
color: #333;
}
.no-data-text {
font-size: 28rpx;
color: #999;
text-align: center;
padding: 60rpx 0;
display: block;
}
.more-info-image {
padding: 0 40rpx;
margin: 30rpx 0;
display: flex;
justify-content: center;
align-items: center;
}
.more-info-text {
font-size: 26rpx;
color: #666;
line-height: 1.6;
margin-bottom: 20rpx;
}
.more-info-text:last-child {
margin-bottom: 40rpx;
}
.more-info-image-placeholder {
width: 100%;
height: 200rpx;
border: 2rpx solid #e0e0e0;
border-radius: 12rpx;
margin: 30rpx 0;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.placeholder-lines {
position: relative;
width: 100%;
height: 100%;
}
.line {
position: absolute;
background: #e0e0e0;
width: 2rpx;
height: 100%;
top: 0;
left: 50%;
transform: translateX(-50%);
}
.line-1 {
transform: translateX(-50%) rotate(45deg);
}
.line-2 {
transform: translateX(-50%) rotate(-45deg);
}
/* 链接弹窗样式 */
.link-modal-content {
background: white;
border-radius: 20rpx 20rpx 0 0;
width: 100%;
overflow: hidden;
}
.link-modal-header {
position: relative;
padding: 40rpx 40rpx 20rpx;
text-align: center;
border-bottom: 1rpx solid #f0f0f0;
}
.link-modal-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
}
.link-modal-close {
position: absolute;
right: 40rpx;
top: 40rpx;
font-size: 40rpx;
color: #999;
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
transition: all 0.3s ease;
}
.link-modal-close:active {
background: #f0f0f0;
}
.link-modal-body {
padding: 30rpx 40rpx;
text-align: center;
}
.link-modal-desc {
font-size: 26rpx;
color: #666;
line-height: 1.6;
margin-bottom: 30rpx;
display: block;
}
.link-modal-btn {
width: 100%;
height: 80rpx;
background: #ffb366;
color: #fff;
border: none;
border-radius: 16rpx;
font-size: 28rpx;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.link-modal-btn:active {
background: #ffa356;
transform: scale(0.98);
}
.qr-code-placeholder {
margin-bottom: 20rpx;
display: flex;
justify-content: center;
}
.qr-code-image {
width: 360rpx;
height: 360rpx;
border: 2rpx solid #e0e0e0;
border-radius: 12rpx;
overflow: hidden;
}
.qr-code-image image {
width: 100%;
height: 100%;
}
/* 分享弹窗样式 */
.share-modal-content {
background: white;
border-radius: 20rpx 20rpx 0 0;
width: 100%;
overflow: hidden;
}
.share-modal-header {
position: relative;
padding: 40rpx 40rpx 20rpx;
text-align: center;
border-bottom: 1rpx solid #f0f0f0;
}
.share-modal-close {
position: absolute;
left: 40rpx;
top: 40rpx;
font-size: 40rpx;
color: #999;
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
transition: all 0.3s ease;
}
.share-modal-close:active {
background: #f0f0f0;
}
.share-modal-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
}
.share-modal-body {
padding: 30rpx 40rpx;
}
.share-options {
display: flex;
justify-content: space-around;
gap: 40rpx;
}
.share-option {
display: flex;
flex-direction: column;
align-items: center;
gap: 20rpx;
flex: 1;
}
.share-icon {
width: 80rpx;
height: 80rpx;
border-radius: 12rpx;
}
.share-option-text {
font-size: 26rpx;
color: #333;
text-align: center;
}
/* 无服务时的样式 */
.no-service {
text-align: center;
padding: 40rpx 0;
}
.no-service-text {
font-size: 28rpx;
color: #999;
}
</style>