zbb 3 週間 前
コミット
200e3c5f75
5 ファイル変更1677 行追加681 行削除
  1. 883 0
      pages/index/index - 副本.vue
  2. 656 656
      pages/index/index.vue
  3. 119 14
      pages/mine/card.vue
  4. 5 5
      pages/mine/userCard.vue
  5. 14 6
      utils/poster.js

+ 883 - 0
pages/index/index - 副本.vue

@@ -0,0 +1,883 @@
+<template>
+	<view class="index-container">
+		<!-- 顶部背景 -->
+		<image class="top-bg" src="/static/image/home/top-bg.png" />
+		<NavBar title="" color="#020202" :fixed="true" :bg="'transparent'">
+			<template #left>
+				<view class="left-title">{{appName}}</view>
+			</template>
+		</NavBar>
+		<view class="page-warp">
+			<view class="page-top">
+				<view class="user-card">
+					<!-- 背景图 -->
+					<image class="user-card-bg" src="/static/image/home/usecard-bg.png" />
+
+					<!-- 左上:姓名 + 职位 -->
+					<view class="user-header">
+						<view class="name-row">
+							<text class="user-name">{{ cardInfo.nickName || '用户' }}</text>
+							<text class="user-role">{{ cardInfo.postName || '职位' }}</text>
+						</view>
+						<text class="company-name">{{ cardInfo.companyName || '公司名称' }}</text>
+					</view>
+
+					<!-- 右上:头像 -->
+					<view class="avatar-wrapper">
+						<UserAvatar :src="cardInfo.avatar" :name="cardInfo.nickName" :size="140" :badge-src="'/static/image/public/badge-icon.png'" :badge-size="64" />
+					</view>
+
+					<!-- 左下:联系方式 -->
+					<view class="user-contact">
+						<view class="contact-row" @click="makeCall">
+							<uni-icons style="margin-top: 4rpx;" type="phone" :size="18" color="#666666"></uni-icons>
+							<text class="contact-text">{{ cardInfo.phonenumber || '暂无电话' }}</text>
+						</view>
+						<view class="contact-row">
+							<uni-icons style="margin-top: 4rpx;" type="email" :size="18" color="#666666"></uni-icons>
+							<text class="contact-text">{{ cardInfo.email || '暂无邮箱' }}</text>
+						</view>
+						<view class="contact-row">
+							<uni-icons style="margin-top: 4rpx;" type="location" :size="18" color="#666666"></uni-icons>
+							<text class="contact-text">{{ cardInfo.companyAddress || '暂无地址' }}</text>
+						</view>
+					</view>
+
+					<!-- 右下:分享名片按钮 -->
+				<!-- 	<view class="share-btn-wrapper">
+						<view class="share-btn" @click="shareCard">
+							<text class="share-text">分享名片</text>
+						</view>
+					</view> -->
+				</view>
+			</view>
+
+			<!-- 最近访客模块 -->
+			<view class="recent-visitors" v-if="false">
+				<view class="section-header">
+					<text class="section-title">最近访客</text>
+					<view class="visitor-count">
+						<view class="avatar-group">
+							<image class="group-avatar" src="/static/avatar-1.png" mode="aspectFill" />
+							<image class="group-avatar" src="/static/avatar-2.png" mode="aspectFill" />
+							<image class="group-avatar" src="/static/avatar-3.png" mode="aspectFill" />
+						</view>
+						<text class="visitor-number">255 人</text>
+					</view>
+				</view>
+				<view class="visitor-list">
+					<view class="visitor-item">
+						<view class="visitor-left">
+							<view class="visitor-top">
+								<view class="visitor-avatar">
+									<image src="/static/image/public/avatar-default2.png" mode="aspectFill" />
+								</view>
+								<view class="visitor-name-row">
+									<text class="visitor-name">匿名用户</text>
+									<text class="visitor-tag pending">待跟进</text>
+								</view>
+								<view class="view-more-btn" @click="viewAllVisitors">查看更多</view>
+							</view>
+							<view class="visitor-meta">
+								<text class="meta-item">
+									<text class="meta-label">来源:</text>
+									<text class="meta-value">微信小程序</text>
+								</text>
+								<text class="meta-item">
+									<text class="meta-label">手机:</text>
+									<text class="meta-value">13822255555</text>
+								</text>
+							</view>
+						</view>
+						<view class="visitor-product">
+							<image class="product-image" src="/static/product-printer.png" mode="aspectFit" />
+							<view class="product-info">
+								<text class="product-name">惠普黑白激光打印机 选配小白盒巴</text>
+								<view>
+									<text class="product-tag">打印机</text>
+									<text class="product-brand">惠普</text>
+								</view>
+							</view>
+						</view>
+					</view>
+				</view>
+				<!-- 底部拖动条 -->
+				<view class="drag-handle"></view>
+			</view>
+
+			<!-- 功能菜单网格 -->
+			<view class="function-grid"  v-if="false">
+				<view class="grid-item" @click="navigateTo('clue')">
+					<view class="grid-icon clue-icon">
+						<text class="icon-text">📋</text>
+					</view>
+					<text class="grid-label">线索管理</text>
+				</view>
+				<view class="grid-item" @click="navigateTo('customer')">
+					<view class="grid-icon customer-icon">
+						<text class="icon-text">🏢</text>
+					</view>
+					<text class="grid-label">客户管理</text>
+				</view>
+				<view class="grid-item" @click="navigateTo('contact')">
+					<view class="grid-icon contact-icon">
+						<text class="icon-text">👥</text>
+					</view>
+					<text class="grid-label">联系人管理</text>
+				</view>
+				<view class="grid-item" @click="navigateTo('public-pool')">
+					<view class="grid-icon pool-icon">
+						<text class="icon-text">🌊</text>
+					</view>
+					<text class="grid-label">客户公海</text>
+				</view>
+				<view class="grid-item" @click="navigateTo('opportunity')">
+					<view class="grid-icon opportunity-icon">
+						<text class="icon-text">💼</text>
+					</view>
+					<text class="grid-label">商机管理</text>
+				</view>
+				<view class="grid-item" @click="navigateTo('payment')">
+					<view class="grid-icon payment-icon">
+						<text class="icon-text">💰</text>
+					</view>
+					<text class="grid-label">回款管理</text>
+				</view>
+				<view class="grid-item" @click="navigateTo('product')">
+					<view class="grid-icon product-icon">
+						<text class="icon-text">📦</text>
+					</view>
+					<text class="grid-label">产品管理</text>
+				</view>
+				<view class="grid-item" @click="navigateTo('all')">
+					<view class="grid-icon all-icon">
+						<text class="icon-text">📊</text>
+					</view>
+					<text class="grid-label">全部</text>
+				</view>
+			</view>
+
+			<!-- 业务日历模块 -->
+			<view class="business-calendar"  v-if="false">
+				<view class="section-header">
+					<text class="section-title">业务日历</text>
+					<text class="view-more" @click="viewAllCalendar">查看更多</text>
+				</view>
+
+				<!-- 日历头部 -->
+				<view class="calendar-header">
+					<text class="calendar-month">2026 年 4 月</text>
+				</view>
+
+				<!-- 星期 -->
+				<view class="calendar-weekdays">
+					<text class="weekday">日</text>
+					<text class="weekday">一</text>
+					<text class="weekday">二</text>
+					<text class="weekday">三</text>
+					<text class="weekday">四</text>
+					<text class="weekday">五</text>
+					<text class="weekday">六</text>
+				</view>
+
+				<!-- 日期网格 -->
+				<view class="calendar-dates">
+					<view class="date-cell">
+						<text class="date-num">15</text>
+					</view>
+					<view class="date-cell">
+						<text class="date-num">16</text>
+					</view>
+					<view class="date-cell">
+						<text class="date-num">17</text>
+					</view>
+					<view class="date-cell today">
+						<text class="date-num current">18</text>
+					</view>
+					<view class="date-cell has-event">
+						<text class="date-num">19</text>
+						<view class="event-dot"></view>
+					</view>
+					<view class="date-cell">
+						<text class="date-num">20</text>
+					</view>
+					<view class="date-cell">
+						<text class="date-num">21</text>
+					</view>
+				</view>
+
+				<!-- 今日日程 -->
+				<view class="today-schedule">
+					<view class="schedule-item">
+						<view class="schedule-time">
+							<text class="time-period">下午</text>
+							<text class="time-value">3:00</text>
+						</view>
+						<view class="schedule-content">
+							<text class="schedule-title">与李总沟通合同细节</text>
+						</view>
+					</view>
+					<view class="schedule-item tomorrow">
+						<view class="schedule-time">
+							<text class="time-period">明天</text>
+							<text class="time-value">10:00</text>
+						</view>
+						<view class="schedule-content">
+							<text class="schedule-title">拜访新客户 - 科技公司</text>
+						</view>
+					</view>
+				</view>
+			</view>
+
+		</view>
+
+		<!-- 底部留白,避免被 TabBar 遮挡 -->
+		<view class="bottom-spacer"></view>
+
+		<!-- 名片预览弹窗 -->
+		<CardPreview :visible="showPreview" @close="closePreview" @share="handleShareCard" @save="handleSaveCard" />
+	</view>
+</template>
+
+<script setup>
+	import NavBar from '@/components/nav-bar/index.vue'
+	import UserAvatar from '@/components/user-avatar/index.vue'
+	import CardPreview from './components/card-preview.vue'
+	import {
+		ref,
+		onMounted,
+		computed
+	} from 'vue'
+	import {
+		useUserStore
+	} from '@/store/modules/user.js'
+	import {
+		storeToRefs
+	} from 'pinia'
+	import {
+		getCurrentConfig
+	} from '@/config/index.js'
+	// 使用 Pinia 管理用户状态
+	const userStore = useUserStore()
+	const {
+		cardInfo,
+		companyInfo
+	} = storeToRefs(userStore)
+
+	let appName = ref('')
+
+	onMounted(async () => {
+		const config = await getCurrentConfig()
+		appName.value = config.appName
+		// 从 store 中获取用户名片和公司信息
+		console.log('用户名片信息:', cardInfo.value)
+		console.log('公司信息:', companyInfo.value)
+
+		// 如果没有数据,重新获取
+		if (!cardInfo.value.nickName) {
+			await userStore.queryCardInfo()
+		}
+		if (!companyInfo.value.name) {
+			await userStore.queryCompanyInfo()
+		}
+
+		console.log('更新后的用户名片信息:', cardInfo.value)
+		console.log('更新后的公司信息:', companyInfo.value)
+	})
+
+	const makeCall = () => {
+		if (cardInfo.value.phonenumber) {
+			uni.makePhoneCall({
+				phoneNumber: cardInfo.value.phonenumber
+			})
+		} else {
+			uni.showToast({
+				title: '暂无电话号码',
+				icon: 'none'
+			})
+		}
+	}
+
+	// 控制名片预览弹窗
+	const showPreview = ref(false)
+
+	const shareCard = () => {
+		showPreview.value = true
+	}
+
+	// 关闭预览弹窗
+	const closePreview = () => {
+		showPreview.value = false
+	}
+
+	// 分享名片
+	const handleShareCard = () => {
+		uni.showShareMenu({
+			withShareTicket: true
+		})
+	}
+
+	// 保存名片
+	const handleSaveCard = () => {
+		uni.showToast({
+			title: '已保存到手机相册',
+			icon: 'success'
+		})
+	}
+
+	const viewAllVisitors = () => {
+		uni.navigateTo({
+			url: '/pages/visitors/list'
+		})
+	}
+
+	const navigateTo = (page) => {
+		uni.showToast({
+			title: `功能开发中:${page}`,
+			icon: 'none'
+		})
+	}
+
+	const viewAllCalendar = () => {
+		uni.navigateTo({
+			url: '/pages/calendar/list'
+		})
+	}
+</script>
+
+<style lang="scss" scoped>
+	.index-container {
+		background-color: #f5f6f8;
+		padding-bottom: 120rpx;
+	}
+
+	.left-title {
+		font-size: 44rpx;
+		font-weight: bold;
+		color: #ffffff;
+		text-shadow: 2px 2px 0 black;
+	}
+
+	.top-bg {
+		width: 750rpx;
+		height: 634rpx;
+		position: fixed;
+		top: 0;
+		left: 0;
+		z-index: 1;
+	}
+
+	.page-warp {
+		position: relative;
+		z-index: 2;
+		padding: 20px;
+	}
+
+	/* 用户信息卡片 */
+	.page-top {
+		margin-bottom: 20rpx;
+
+		.user-card {
+			width: 100%;
+			height: 414rpx;
+			padding: 80rpx 40rpx 32rpx;
+			position: relative;
+
+			.user-card-bg {
+				position: absolute;
+				top: 0;
+				left: 0;
+				width: 100%;
+				height: 100%;
+				z-index: 0;
+			}
+
+			view,
+			text {
+				position: relative;
+				z-index: 1;
+			}
+
+			.user-header {
+				.name-row {
+					display: flex;
+					align-items: center;
+					margin-bottom: 16rpx;
+
+					.user-name {
+						font-size: 44rpx;
+						font-weight: 700;
+						color: #202020;
+						line-height: 1.2;
+					}
+
+					.user-role {
+						margin-left: 16rpx;
+						padding: 6rpx 16rpx;
+						background: rgba(68, 110, 255, 0.10);
+						border-radius: 8rpx;
+						font-size: 24rpx;
+						font-weight: 500;
+						color: #446eff;
+					}
+				}
+
+				.company-name {
+					font-size: 28rpx;
+					font-weight: 500;
+					color: #666666;
+					line-height: 1.4;
+				}
+			}
+
+			.avatar-wrapper {
+				position: absolute;
+				top: 32rpx;
+				right: 36rpx;
+				z-index: 2;
+			}
+
+			.user-contact {
+				margin-top: 32rpx;
+
+				.contact-row {
+					display: flex;
+					align-items: flex-start;
+					margin-bottom: 16rpx;
+
+					uni-icons {
+						margin-right: 12rpx;
+						flex-shrink: 0;
+					}
+
+					.contact-text {
+						font-size: 26rpx;
+						color: #666666;
+					}
+				}
+			}
+
+			.share-btn-wrapper {
+				position: absolute;
+				bottom: 90rpx;
+				right: 40rpx;
+
+				.share-btn {
+					padding: 14rpx 36rpx;
+					background: linear-gradient(90deg, #446dff 0%, #6b85ff 100%);
+					border-radius: 32rpx;
+					box-shadow: 0 4rpx 12rpx rgba(68, 110, 255, 0.35);
+
+					.share-text {
+						font-size: 26rpx;
+						font-weight: 500;
+						color: #ffffff;
+					}
+				}
+			}
+		}
+	}
+
+	/* 最近访客模块 */
+	.recent-visitors {
+		padding: 20rpx;
+		background: #f2f6ff;
+		border: 2rpx solid rgba(255, 255, 255, 0.80);
+		border-radius: 28rpx;
+
+		.section-header {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			margin-bottom: 24rpx;
+
+			.section-title {
+				font-size: 32rpx;
+				font-weight: 600;
+				color: #333333;
+			}
+
+			.visitor-count {
+				display: flex;
+				align-items: center;
+				margin-left: 20rpx;
+
+				.avatar-group {
+					display: flex;
+					margin-right: 12rpx;
+
+					.group-avatar {
+						width: 32rpx;
+						height: 32rpx;
+						border-radius: 50%;
+						border: 4rpx solid #ffffff;
+						margin-left: -16rpx;
+
+						&:first-child {
+							margin-left: 0;
+						}
+					}
+				}
+
+				.visitor-number {
+					font-size: 24rpx;
+					color: #999999;
+				}
+			}
+
+			.view-more {
+				font-size: 24rpx;
+				color: #667eea;
+				margin-left: auto;
+			}
+		}
+
+		.visitor-list {
+			background: #ffffff;
+			border: 2rpx solid #ffffff;
+			border-radius: 28rpx;
+
+			.visitor-item {
+				padding: 20rpx;
+
+				.visitor-left {
+					display: grid;
+
+					.visitor-top {
+						display: grid;
+						grid-template-columns: auto 1fr auto;
+						gap: 6rpx;
+					}
+
+					.visitor-name-row {
+						display: flex;
+						align-items: center;
+
+						.visitor-name {
+							font-size: 24rpx;
+							font-weight: 500;
+							color: #8390b1;
+							margin: 0 10rpx;
+						}
+
+						.visitor-tag {
+							width: 92rpx;
+							height: 40rpx;
+							text-align: center;
+							line-height: 40rpx;
+							border: 1.2rpx solid #ff9230;
+							border-radius: 12rpx;
+							font-size: 24rpx;
+							font-weight: 500;
+							color: #ff9230;
+						}
+					}
+
+					.view-more-btn {
+						font-size: 24rpx;
+						color: #999999;
+					}
+
+					.visitor-avatar {
+						width: 40rpx;
+						height: 40rpx;
+						border-radius: 50%;
+						background: #ffffff;
+						padding: 4rpx;
+						box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
+
+						image {
+							width: 100%;
+							height: 100%;
+							border-radius: 50%;
+						}
+					}
+				}
+
+
+
+				.visitor-meta {
+					display: flex;
+					align-items: flex-start;
+					margin-bottom: 16rpx;
+					gap: 32rpx;
+
+					.meta-item {
+						display: flex;
+						align-items: flex-start;
+
+						.meta-label {
+							font-size: 22rpx;
+							color: #999999;
+						}
+
+						.meta-value {
+							font-size: 22rpx;
+							color: #666666;
+						}
+					}
+				}
+
+				.visitor-product {
+					display: flex;
+					align-items: flex-start;
+					background: #ffffff;
+					border-radius: 16rpx;
+					padding: 16rpx;
+					box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
+
+					.product-image {
+						width: 72rpx;
+						height: 72rpx;
+						border-radius: 12rpx;
+						background-color: #30cfd0;
+						margin-right: 16rpx;
+					}
+
+					.product-info {
+						flex: 1;
+						display: flex;
+						flex-direction: column;
+						justify-content: center;
+
+						.product-name {
+							font-size: 24rpx;
+							font-weight: 500;
+							color: #08105c;
+						}
+
+						.product-tag,
+						.product-brand {
+							font-size: 20rpx;
+							color: #999999;
+							margin-right: 12rpx;
+						}
+					}
+				}
+
+			}
+		}
+
+		.drag-handle {
+			width: 80rpx;
+			height: 8rpx;
+			background: rgba(0, 0, 0, 0.2);
+			border-radius: 4rpx;
+			margin: 24rpx auto 0;
+		}
+	}
+
+	/* 功能菜单网格 */
+	.function-grid {
+		display: grid;
+		grid-template-columns: repeat(4, 1fr);
+		gap: 24rpx;
+		margin-top: 20rpx;
+		padding: 32rpx 24rpx;
+		height: 322rpx;
+		background: linear-gradient(180deg, #eff6ff, #ffffff 42%);
+		border: 2rpx solid #ffffff;
+		border-radius: 28rpx;
+		box-shadow: 0rpx 8rpx 8rpx 0rpx rgba(178, 194, 208, 0.10);
+
+		.grid-item {
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+
+			.grid-icon {
+				width: 54rpx;
+				height: 54rpx;
+				border-radius: 28rpx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				margin-bottom: 12rpx;
+
+				.icon-text {
+					font-size: 48rpx;
+				}
+			}
+
+			.clue-icon {
+				background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+			}
+
+			.customer-icon {
+				background: linear-gradient(135deg, #30cfd0 0%, #330867 100%);
+			}
+
+			.contact-icon {
+				background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
+			}
+
+			.pool-icon {
+				background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+			}
+
+			.opportunity-icon {
+				background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
+			}
+
+			.payment-icon {
+				background: linear-gradient(135deg, #ffd89b 0%, #19547b 100%);
+			}
+
+			.product-icon {
+				background: linear-gradient(135deg, #89f7fe 0%, #66a6ff 100%);
+			}
+
+			.all-icon {
+				background: linear-gradient(135deg, #cd9cf2 0%, #f6f3ff 100%);
+			}
+
+			.grid-label {
+				font-size: 24rpx;
+				color: #333333;
+			}
+		}
+	}
+
+	/* 业务日历模块 */
+	.business-calendar {
+		background: #ffffff;
+		margin: 20rpx 0;
+		padding: 32rpx;
+		border-radius: 24rpx;
+		box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
+
+		.section-header {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			margin-bottom: 24rpx;
+
+			.section-title {
+				font-size: 32rpx;
+				font-weight: 600;
+				color: #333333;
+			}
+
+			.view-more {
+				font-size: 24rpx;
+				color: #667eea;
+			}
+		}
+
+		.calendar-header {
+			text-align: center;
+			margin-bottom: 20rpx;
+
+			.calendar-month {
+				font-size: 30rpx;
+				font-weight: 600;
+				color: #333333;
+			}
+		}
+
+		.calendar-weekdays {
+			display: grid;
+			grid-template-columns: repeat(7, 1fr);
+			text-align: center;
+			margin-bottom: 16rpx;
+
+			.weekday {
+				font-size: 24rpx;
+				color: #999999;
+				padding: 12rpx 0;
+			}
+		}
+
+		.calendar-dates {
+			display: grid;
+			grid-template-columns: repeat(7, 1fr);
+			gap: 8rpx;
+			margin-bottom: 32rpx;
+
+			.date-cell {
+				aspect-ratio: 1;
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				justify-content: center;
+				border-radius: 50%;
+				position: relative;
+
+				.date-num {
+					font-size: 26rpx;
+					color: #333333;
+				}
+
+				&.today {
+					background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+
+					.date-num {
+						color: #ffffff;
+						font-weight: 600;
+					}
+				}
+
+				&.has-event {
+					.event-dot {
+						width: 12rpx;
+						height: 12rpx;
+						background: #ff6b6b;
+						border-radius: 50%;
+						position: absolute;
+						bottom: 8rpx;
+					}
+				}
+			}
+		}
+
+		.today-schedule {
+			.schedule-item {
+				display: flex;
+				align-items: flex-start;
+				padding: 24rpx;
+				background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
+				border-radius: 16rpx;
+				margin-bottom: 16rpx;
+				border-left: 6rpx solid #667eea;
+
+				&.tomorrow {
+					border-left-color: #30cfd0;
+				}
+
+				.schedule-time {
+					display: flex;
+					flex-direction: column;
+					align-items: center;
+					margin-right: 20rpx;
+					min-width: 100rpx;
+
+					.time-period {
+						font-size: 22rpx;
+						color: #999999;
+						margin-bottom: 4rpx;
+					}
+
+					.time-value {
+						font-size: 28rpx;
+						font-weight: 600;
+						color: #333333;
+					}
+				}
+
+				.schedule-content {
+					flex: 1;
+
+					.schedule-title {
+						font-size: 28rpx;
+						color: #333333;
+						line-height: 1.5;
+					}
+				}
+			}
+		}
+	}
+
+	.bottom-spacer {
+		height: 40rpx;
+	}
+</style>

+ 656 - 656
pages/index/index.vue

@@ -1,5 +1,6 @@
 <template>
-	<view class="index-container">
+	<view class="card-container">
+
 		<!-- 顶部背景 -->
 		<image class="top-bg" src="/static/image/home/top-bg.png" />
 		<NavBar title="" color="#020202" :fixed="true" :bg="'transparent'">
@@ -7,247 +8,224 @@
 				<view class="left-title">{{appName}}</view>
 			</template>
 		</NavBar>
-		<view class="page-warp">
-			<view class="page-top">
-				<view class="user-card">
-					<!-- 背景图 -->
-					<image class="user-card-bg" src="/static/image/home/usecard-bg.png" />
-
-					<!-- 左上:姓名 + 职位 -->
-					<view class="user-header">
-						<view class="name-row">
-							<text class="user-name">{{ cardInfo.nickName || '用户' }}</text>
-							<text class="user-role">{{ cardInfo.postName || '职位' }}</text>
-						</view>
-						<text class="company-name">{{ cardInfo.companyName || '公司名称' }}</text>
-					</view>
-
-					<!-- 右上:头像 -->
-					<view class="avatar-wrapper">
-						<UserAvatar :src="cardInfo.avatar" :name="cardInfo.nickName" :size="140" :badge-src="'/static/image/public/badge-icon.png'" :badge-size="64" />
-					</view>
-
-					<!-- 左下:联系方式 -->
-					<view class="user-contact">
-						<view class="contact-row" @click="makeCall">
-							<uni-icons style="margin-top: 4rpx;" type="phone" :size="18" color="#666666"></uni-icons>
-							<text class="contact-text">{{ cardInfo.phonenumber || '暂无电话' }}</text>
-						</view>
-						<view class="contact-row">
-							<uni-icons style="margin-top: 4rpx;" type="email" :size="18" color="#666666"></uni-icons>
-							<text class="contact-text">{{ cardInfo.email || '暂无邮箱' }}</text>
-						</view>
-						<view class="contact-row">
-							<uni-icons style="margin-top: 4rpx;" type="location" :size="18" color="#666666"></uni-icons>
-							<text class="contact-text">{{ cardInfo.companyAddress || '暂无地址' }}</text>
-						</view>
+		<!-- 名片卡片 -->
+		<view class="page-top">
+			<view class="user-card" id="user-card">
+				<!-- 背景图 -->
+				<image class="user-card-bg" src="/static/image/home/usecard-bg.png" />
+
+				<!-- 左上:姓名 + 职位 -->
+				<view class="user-header">
+					<view class="name-row">
+						<text class="user-name">{{ cardInfo.nickName || '用户' }}</text>
+						<text class="user-role">{{ cardInfo.postName || '职位' }}</text>
 					</view>
+					<text class="company-name">{{ cardInfo.companyName || '公司名称' }}</text>
+				</view>
 
-					<!-- 右下:分享名片按钮 -->
-				<!-- 	<view class="share-btn-wrapper">
-						<view class="share-btn" @click="shareCard">
-							<text class="share-text">分享名片</text>
-						</view>
-					</view> -->
+				<!-- 右上:头像 -->
+				<view class="avatar-wrapper">
+					<UserAvatar :src="cardInfo.avatar" :name="cardInfo.nickName" :size="130"
+						:badge-src="'/static/image/public/badge-icon.png'" :badge-size="56" />
 				</view>
-			</view>
 
-			<!-- 最近访客模块 -->
-			<view class="recent-visitors" v-if="false">
-				<view class="section-header">
-					<text class="section-title">最近访客</text>
-					<view class="visitor-count">
-						<view class="avatar-group">
-							<image class="group-avatar" src="/static/avatar-1.png" mode="aspectFill" />
-							<image class="group-avatar" src="/static/avatar-2.png" mode="aspectFill" />
-							<image class="group-avatar" src="/static/avatar-3.png" mode="aspectFill" />
-						</view>
-						<text class="visitor-number">255 人</text>
+				<!-- 左下:联系方式 -->
+				<view class="user-contact">
+					<view class="contact-row" @click="makeCall">
+						<uni-icons type="phone" :size="18" color="#666666"></uni-icons>
+						<text class="contact-text">{{ cardInfo.phonenumber || '暂无电话' }}</text>
 					</view>
-				</view>
-				<view class="visitor-list">
-					<view class="visitor-item">
-						<view class="visitor-left">
-							<view class="visitor-top">
-								<view class="visitor-avatar">
-									<image src="/static/image/public/avatar-default2.png" mode="aspectFill" />
-								</view>
-								<view class="visitor-name-row">
-									<text class="visitor-name">匿名用户</text>
-									<text class="visitor-tag pending">待跟进</text>
-								</view>
-								<view class="view-more-btn" @click="viewAllVisitors">查看更多</view>
-							</view>
-							<view class="visitor-meta">
-								<text class="meta-item">
-									<text class="meta-label">来源:</text>
-									<text class="meta-value">微信小程序</text>
-								</text>
-								<text class="meta-item">
-									<text class="meta-label">手机:</text>
-									<text class="meta-value">13822255555</text>
-								</text>
-							</view>
-						</view>
-						<view class="visitor-product">
-							<image class="product-image" src="/static/product-printer.png" mode="aspectFit" />
-							<view class="product-info">
-								<text class="product-name">惠普黑白激光打印机 选配小白盒巴</text>
-								<view>
-									<text class="product-tag">打印机</text>
-									<text class="product-brand">惠普</text>
-								</view>
-							</view>
-						</view>
+					<view class="contact-row">
+						<uni-icons type="email" :size="18" color="#666666"></uni-icons>
+						<text class="contact-text">{{ cardInfo.email || '暂无邮箱' }}</text>
+					</view>
+					<view class="contact-row">
+						<uni-icons type="location" :size="18" color="#666666"></uni-icons>
+						<text class="contact-text">{{ cardInfo.companyAddress || '暂无地址' }}</text>
 					</view>
 				</view>
-				<!-- 底部拖动条 -->
-				<view class="drag-handle"></view>
 			</view>
 
-			<!-- 功能菜单网格 -->
-			<view class="function-grid"  v-if="false">
-				<view class="grid-item" @click="navigateTo('clue')">
-					<view class="grid-icon clue-icon">
-						<text class="icon-text">📋</text>
-					</view>
-					<text class="grid-label">线索管理</text>
+
+			<view class="control-card">
+				<view class="item" @click="shareUserCard">
+					<image src="/static/image/public/card-sharing.png"></image>
+					<text class="text">分享名片</text>
 				</view>
-				<view class="grid-item" @click="navigateTo('customer')">
-					<view class="grid-icon customer-icon">
-						<text class="icon-text">🏢</text>
-					</view>
-					<text class="grid-label">客户管理</text>
+				<view class="item" @click="saveCard">
+					<image src="/static/image/public/card-save.png"></image>
+					<text class="text">保存名片</text>
 				</view>
-				<view class="grid-item" @click="navigateTo('contact')">
-					<view class="grid-icon contact-icon">
-						<text class="icon-text">👥</text>
-					</view>
-					<text class="grid-label">联系人管理</text>
-				</view>
-				<view class="grid-item" @click="navigateTo('public-pool')">
-					<view class="grid-icon pool-icon">
-						<text class="icon-text">🌊</text>
-					</view>
-					<text class="grid-label">客户公海</text>
+				<view class="item" @click="showQRCode">
+					<image src="/static/image/public/card-qr.png"></image>
+					<text class="text">名片码</text>
 				</view>
-				<view class="grid-item" @click="navigateTo('opportunity')">
-					<view class="grid-icon opportunity-icon">
-						<text class="icon-text">💼</text>
-					</view>
-					<text class="grid-label">商机管理</text>
-				</view>
-				<view class="grid-item" @click="navigateTo('payment')">
-					<view class="grid-icon payment-icon">
-						<text class="icon-text">💰</text>
+			</view>
+		</view>
+		<view class="card-content">
+			<!-- Tab 切换 -->
+			<view class="tab-section">
+				<view class="tab-wrapper">
+					<!-- 	<view class="tab-item" :class="{ active: currentTab === 'products' }"
+						@click="switchTab('products')">
+						<text class="tab-text">产品列表</text>
+						<view class="tab-indicator" v-if="currentTab === 'products'"></view>
+					</view> -->
+					<view class="tab-item" :class="{ active: currentTab === 'company' }" @click="switchTab('company')">
+						<text class="tab-text">企业简介</text>
+						<view class="tab-indicator" v-if="currentTab === 'company'"></view>
 					</view>
-					<text class="grid-label">回款管理</text>
 				</view>
-				<view class="grid-item" @click="navigateTo('product')">
-					<view class="grid-icon product-icon">
-						<text class="icon-text">📦</text>
+			</view>
+			<!-- 产品列表 -->
+			<view class="product-list" v-if="currentTab === 'products'">
+				<EmptyState v-if="productList.length === 0" text="暂无产品" sub-text="还没有添加产品信息" icon="gift" />
+				<view class="product-item" v-for="(item, index) in productList" :key="index">
+					<image class="product-image" :src="item.image" mode="aspectFill" />
+					<view class="product-info">
+						<text class="product-title">{{ item.title }}</text>
+						<text class="product-desc">{{ item.description }}</text>
 					</view>
-					<text class="grid-label">产品管理</text>
 				</view>
-				<view class="grid-item" @click="navigateTo('all')">
-					<view class="grid-icon all-icon">
-						<text class="icon-text">📊</text>
-					</view>
-					<text class="grid-label">全部</text>
+			</view>
+			<!-- 企业简介 -->
+			<view class="company-section" v-if="currentTab === 'company'">
+				<view class="company-content">
+					<rich-text class="company-text" :nodes="companyInfo.introduce"></rich-text>
 				</view>
 			</view>
+		</view>
 
-			<!-- 业务日历模块 -->
-			<view class="business-calendar"  v-if="false">
-				<view class="section-header">
-					<text class="section-title">业务日历</text>
-					<text class="view-more" @click="viewAllCalendar">查看更多</text>
-				</view>
+		<!-- 隐藏的 Canvas 用于生成名片快照 -->
+		<canvas id="posterCanvas" type="2d"
+			style="position: fixed; left: -9999px; top: -9999px; width: 750px; height: 780px;"></canvas>
+
+		<!-- 隐藏的 Canvas 用于生成二维码海报 -->
+		<view class="hidden-canvas-box">
+			<canvas id="qrPosterCanvas" type="2d" style="width: 600px; height: 700px;"></canvas>
+		</view>
 
-				<!-- 日历头部 -->
-				<view class="calendar-header">
-					<text class="calendar-month">2026 年 4 月</text>
+		<!-- 名片分享弹窗 -->
+		<uni-popup ref="cardPopup" type="center">
+			<view class="card-popup">
+				<!-- 顶部装饰条 -->
+				<view class="popup-decor">
+					<view class="decor-line"></view>
 				</view>
 
-				<!-- 星期 -->
-				<view class="calendar-weekdays">
-					<text class="weekday">日</text>
-					<text class="weekday">一</text>
-					<text class="weekday">二</text>
-					<text class="weekday">三</text>
-					<text class="weekday">四</text>
-					<text class="weekday">五</text>
-					<text class="weekday">六</text>
+				<!-- 标题 -->
+				<view class="popup-title-box">
+					<text class="popup-title">我的名片</text>
+					<text class="popup-desc">分享给朋友或保存到相册</text>
 				</view>
 
-				<!-- 日期网格 -->
-				<view class="calendar-dates">
-					<view class="date-cell">
-						<text class="date-num">15</text>
-					</view>
-					<view class="date-cell">
-						<text class="date-num">16</text>
-					</view>
-					<view class="date-cell">
-						<text class="date-num">17</text>
+				<!-- 名片卡片 -->
+				<view class="card-box">
+					<view class="user-card">
+						<!-- 背景图 -->
+						<image class="user-card-bg" src="/static/image/home/usecard-bg.png" mode="aspectFill" />
+
+						<!-- 左上:姓名 + 职位 -->
+						<view class="user-header">
+							<view class="name-row">
+								<text class="user-name">{{ cardInfo.nickName || '用户' }}</text>
+								<text class="user-role">{{ cardInfo.postName || '职位' }}</text>
+							</view>
+							<text class="company-name">{{ cardInfo.companyName || '公司名称' }}</text>
+						</view>
+
+						<!-- 右上:头像 -->
+						<view class="user-avatar-box">
+							<UserAvatar :src="cardInfo.avatar" :name="cardInfo.nickName" :size="120"
+								:badge-src="'/static/image/public/badge-icon.png'" :badge-size="50" />
+						</view>
+
+						<!-- 左下:联系方式 -->
+						<view class="user-contact">
+							<view class="contact-row" @click="makeCall">
+								<view class="contact-icon">
+									<uni-icons type="phone" :size="16" color="#4080FF"></uni-icons>
+								</view>
+								<text class="contact-text">{{ cardInfo.phonenumber || '暂无电话' }}</text>
+							</view>
+							<view class="contact-row">
+								<view class="contact-icon">
+									<uni-icons type="email" :size="16" color="#4080FF"></uni-icons>
+								</view>
+								<text class="contact-text">{{ cardInfo.email || '暂无邮箱' }}</text>
+							</view>
+							<view class="contact-row">
+								<view class="contact-icon">
+									<uni-icons type="location" :size="16" color="#4080FF"></uni-icons>
+								</view>
+								<text class="contact-text">{{ cardInfo.companyAddress || '暂无地址' }}</text>
+							</view>
+						</view>
 					</view>
-					<view class="date-cell today">
-						<text class="date-num current">18</text>
+				</view>
+
+				<!-- 操作按钮 -->
+				<view class="popup-btns">
+					<view class="btn btn-cancel" @click="closeCardPopup">
+						<text class="btn-text">取消</text>
 					</view>
-					<view class="date-cell has-event">
-						<text class="date-num">19</text>
-						<view class="event-dot"></view>
+					<view class="btn btn-confirm" @click="shareCardConfirm">
+						<text class="btn-text">分享名片</text>
 					</view>
-					<view class="date-cell">
-						<text class="date-num">20</text>
+				</view>
+
+				<!-- 底部全宽按钮 -->
+				<view class="popup-footer">
+					<view class="btn btn-full" @click="shareCardConfirm">
+						<uni-icons type="paperplane" size="22" color="#ffffff"></uni-icons>
+						<text class="btn-text">立即分享名片给朋友</text>
 					</view>
-					<view class="date-cell">
-						<text class="date-num">21</text>
+				</view>
+			</view>
+		</uni-popup>
+
+		<!-- 二维码弹窗 -->
+		<uni-popup ref="qrPopup" type="center">
+			<view class="qr-popup">
+				<view class="qr-header">
+					<text class="qr-title">名片二维码</text>
+					<text class="qr-subtitle">扫一扫查看我的名片信息</text>
+				</view>
+				<view class="qr-content">
+					<image v-if="qrInfo && qrInfo.image"
+						:src="qrInfo.image.startsWith('data:') ? qrInfo.image : 'data:image/png;base64,' + qrInfo.image"
+						class="qr-image" mode="aspectFit" />
+					<view v-else class="qr-loading">
+						<text>加载中...</text>
 					</view>
 				</view>
-
-				<!-- 今日日程 -->
-				<view class="today-schedule">
-					<view class="schedule-item">
-						<view class="schedule-time">
-							<text class="time-period">下午</text>
-							<text class="time-value">3:00</text>
-						</view>
-						<view class="schedule-content">
-							<text class="schedule-title">与李总沟通合同细节</text>
-						</view>
+				<view class="qr-actions">
+					<view class="action-btn" @click="saveQRCode">
+						<uni-icons type="download" size="24" color="#4080FF"></uni-icons>
+						<text class="action-text">保存到相册</text>
 					</view>
-					<view class="schedule-item tomorrow">
-						<view class="schedule-time">
-							<text class="time-period">明天</text>
-							<text class="time-value">10:00</text>
-						</view>
-						<view class="schedule-content">
-							<text class="schedule-title">拜访新客户 - 科技公司</text>
-						</view>
+					<view class="action-btn" @click="handleShare">
+						<uni-icons type="paperplane" size="24" color="#4080FF"></uni-icons>
+						<!-- <button open-type="share" class="action-text">分享给好友</button> -->
+						<text class="action-text">分享给好友</text>
 					</view>
 				</view>
 			</view>
-
-		</view>
-
-		<!-- 底部留白,避免被 TabBar 遮挡 -->
-		<view class="bottom-spacer"></view>
-
-		<!-- 名片预览弹窗 -->
-		<CardPreview :visible="showPreview" @close="closePreview" @share="handleShareCard" @save="handleSaveCard" />
+		</uni-popup>
 	</view>
 </template>
 
 <script setup>
-	import NavBar from '@/components/nav-bar/index.vue'
-	import UserAvatar from '@/components/user-avatar/index.vue'
-	import CardPreview from './components/card-preview.vue'
 	import {
 		ref,
-		onMounted,
-		computed
+		onMounted
 	} from 'vue'
+	import {
+		onShareAppMessage
+	} from '@dcloudio/uni-app';
+	import NavBar from '@/components/nav-bar/index.vue'
+	import UserAvatar from '@/components/user-avatar/index.vue'
+	import EmptyState from '@/components/empty-state/index.vue'
 	import {
 		useUserStore
 	} from '@/store/modules/user.js'
@@ -255,34 +233,47 @@
 		storeToRefs
 	} from 'pinia'
 	import {
+		generateCardPoster,
+		savePosterToAlbum,
+	} from '@/utils/poster.js'
+import {
 		getCurrentConfig
 	} from '@/config/index.js'
 	// 使用 Pinia 管理用户状态
 	const userStore = useUserStore()
 	const {
 		cardInfo,
-		companyInfo
+		companyInfo,
+		qrInfo,
 	} = storeToRefs(userStore)
 
-	let appName = ref('')
-
+	const currentTab = ref('company')
+	// 名片快照图片路径
+	const cardSnapshot = ref('')
+	// 二维码海报图片路径
+	const qrCodePoster = ref('')
+	// 二维码弹窗引用
+	const qrPopup = ref(null)
+	const cardPopup = ref(null)
+
+	const productList = ref([])
+	onShareAppMessage(() => {
+		return {
+			userName: '小程序',
+			path: 'pages/splash/splash?userId=' + cardInfo.value.userId,
+		};
+	});
+		let appName = ref('')
 	onMounted(async () => {
-		const config = await getCurrentConfig()
-		appName.value = config.appName
-		// 从 store 中获取用户名片和公司信息
-		console.log('用户名片信息:', cardInfo.value)
-		console.log('公司信息:', companyInfo.value)
-
-		// 如果没有数据,重新获取
+			const config = await getCurrentConfig()
+			appName.value = config.appName
+		// 如果没有数据,重新获取
 		if (!cardInfo.value.nickName) {
 			await userStore.queryCardInfo()
 		}
 		if (!companyInfo.value.name) {
 			await userStore.queryCompanyInfo()
 		}
-
-		console.log('更新后的用户名片信息:', cardInfo.value)
-		console.log('更新后的公司信息:', companyInfo.value)
 	})
 
 	const makeCall = () => {
@@ -298,57 +289,174 @@
 		}
 	}
 
-	// 控制名片预览弹窗
-	const showPreview = ref(false)
+	// 生成名片快照并保存
+	const saveCard = async () => {
+		uni.showLoading({
+			title: '生成快照中...',
+			mask: true
+		})
+
+		try {
+
+			// 生成名片快照
+			const snapshotPath = await generateCardPoster(cardInfo.value, qrInfo.value)
+			console.log(snapshotPath, "snapshotPathsnapshotPathsnapshotPath");
+			// 用属性接收快照路径
+			cardSnapshot.value = snapshotPath
 
-	const shareCard = () => {
-		showPreview.value = true
+			console.log('名片快照路径:', cardSnapshot.value)
+
+			// 保存到相册
+			await savePosterToAlbum(snapshotPath)
+
+			uni.hideLoading()
+			uni.showToast({
+				title: '已保存到相册',
+				icon: 'success'
+			})
+		} catch (error) {
+			console.error('保存失败:', error)
+			uni.hideLoading()
+			uni.showToast({
+				title: '保存失败,请重试',
+				icon: 'none'
+			})
+		}
 	}
 
-	// 关闭预览弹窗
-	const closePreview = () => {
-		showPreview.value = false
+	// 显示二维码
+	const showQRCode = async () => {
+		// 打开弹窗
+		qrPopup.value.open()
 	}
 
-	// 分享名片
-	const handleShareCard = () => {
-		uni.showShareMenu({
-			withShareTicket: true
-		})
+	const close = async () => {
+		cardPopup.value.close()
 	}
 
-	// 保存名片
-	const handleSaveCard = () => {
-		uni.showToast({
-			title: '已保存到手机相册',
-			icon: 'success'
-		})
+	const shareUserCard = async () => {
+		const snapshotPath = await generateCardPoster(cardInfo.value, qrInfo.value)
+		wx.showShareImageMenu({
+			path: snapshotPath,
+			entrancePath: 'pages/splash/splash?userId=' + cardInfo.value.userId,
+			success: () => {
+				console.log('分享菜单已调起');
+			},
+			fail: (err) => {
+				console.error('调起分享菜单失败', err);
+			}
+		});
+
 	}
 
-	const viewAllVisitors = () => {
-		uni.navigateTo({
-			url: '/pages/visitors/list'
+
+	const base64ToImage = async (base64Data) => {
+		return new Promise((resolve, reject) => {
+			try {
+				const filePath = `${wx.env.USER_DATA_PATH}/temp_image.png`;
+				let pureBase64Data = base64Data
+				if (pureBase64Data.startsWith('data:image')) {
+					pureBase64Data = pureBase64Data.replace(/^data:image\/\w+;base64,/, '');
+				}
+				const fs = wx.getFileSystemManager();
+				fs.writeFile({
+					filePath: filePath,
+					data: pureBase64Data,
+					encoding: 'base64',
+					success: (res) => {
+						console.log("resresweresresresres", res);
+						resolve(filePath)
+					},
+					fail: (err) => {
+						console.error('写入临时文件失败', err);
+					}
+				});
+			} catch (error) {
+				console.error('base64 转换异常:', error)
+				reject(error)
+			}
 		})
 	}
+	const handleShare = async () => {
+		const qrFilePath = await base64ToTempFile(qrInfo.value.image)
+		wx.showShareImageMenu({
+			path: qrFilePath,
+			entrancePath: 'pages/splash/splash?userId=' + cardInfo.value.userId,
+			success: () => {
+				console.log('分享菜单已调起');
+			},
+			fail: (err) => {
+				console.error('调起分享菜单失败', err);
+			}
+		});
+	}
+	// 保存二维码到相册
+	const saveQRCode = async () => {
+		if (!qrInfo.value.image) {
+			uni.showToast({
+				title: '二维码图片不存在',
+				icon: 'none'
+			})
+			return
+		}
 
-	const navigateTo = (page) => {
-		uni.showToast({
-			title: `功能开发中:${page}`,
-			icon: 'none'
-		})
+		try {
+			// 将 base64 转换为临时文件
+			const qrFilePath = await base64ToTempFile(qrInfo.value.image)
+			// 保存到相册
+			await savePosterToAlbum(qrFilePath)
+			uni.showToast({
+				title: '已保存到相册',
+				icon: 'success'
+			})
+		} catch (error) {
+			console.error('保存失败:', error)
+			uni.showToast({
+				title: '保存失败,请重试',
+				icon: 'none'
+			})
+		}
 	}
 
-	const viewAllCalendar = () => {
-		uni.navigateTo({
-			url: '/pages/calendar/list'
+
+
+	const switchTab = (tab) => {
+		currentTab.value = tab
+	}
+	// 将 base64 转换为临时文件路径
+	const base64ToTempFile = async (base64Data) => {
+		return new Promise((resolve, reject) => {
+			try {
+				// 移除 data:image/png;base64, 前缀(如果有)
+				const pureBase64 = base64Data.replace(/^data:image\/\w+;base64,/, '')
+
+				const fileName = `${Date.now()}_qrcode.png`
+				const filePath = `${wx.env.USER_DATA_PATH}/${fileName}`
+				const fs = uni.getFileSystemManager()
+				fs.writeFile({
+					filePath: filePath,
+					data: pureBase64,
+					encoding: 'base64',
+					success: () => {
+						console.log('base64 转文件成功:', filePath)
+						resolve(filePath)
+					},
+					fail: (err) => {
+						console.error('base64 转文件失败:', err)
+						reject(err)
+					}
+				})
+			} catch (error) {
+				console.error('base64 转换异常:', error)
+				reject(error)
+			}
 		})
 	}
 </script>
 
 <style lang="scss" scoped>
-	.index-container {
-		background-color: #f5f6f8;
-		padding-bottom: 120rpx;
+	.card-container {
+		background: #f5f6f8;
 	}
 
 	.left-title {
@@ -357,7 +465,6 @@
 		color: #ffffff;
 		text-shadow: 2px 2px 0 black;
 	}
-
 	.top-bg {
 		width: 750rpx;
 		height: 634rpx;
@@ -367,517 +474,410 @@
 		z-index: 1;
 	}
 
-	.page-warp {
+	// 顶部背景区域
+	.header-bg {
+		background: linear-gradient(135deg, #4A90E2 0%, #6FB3F2 50%, #87CEEB 100%);
+		padding: 0 40rpx;
+		padding-top: calc(var(--status-bar-height) + 20rpx);
+		padding-bottom: 60rpx;
 		position: relative;
-		z-index: 2;
-		padding: 20px;
-	}
-
-	/* 用户信息卡片 */
-	.page-top {
-		margin-bottom: 20rpx;
+		overflow: hidden;
+
+		// 背景光效
+		&::before {
+			content: '';
+			position: absolute;
+			top: -100rpx;
+			right: -100rpx;
+			width: 500rpx;
+			height: 500rpx;
+			background: radial-gradient(circle, rgba(255, 255, 255, 0.2) 0%, transparent 70%);
+			border-radius: 50%;
+		}
 
-		.user-card {
-			width: 100%;
-			height: 414rpx;
-			padding: 80rpx 40rpx 32rpx;
+		// 导航栏
+		.nav-bar {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			height: 88rpx;
 			position: relative;
+			z-index: 10;
 
-			.user-card-bg {
-				position: absolute;
-				top: 0;
-				left: 0;
-				width: 100%;
-				height: 100%;
-				z-index: 0;
+			.nav-back {
+				width: 60rpx;
+				height: 60rpx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
 			}
 
-			view,
-			text {
-				position: relative;
-				z-index: 1;
+			.nav-title {
+				font-size: 32rpx;
+				font-weight: 600;
+				color: #ffffff;
+				text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
 			}
 
-			.user-header {
-				.name-row {
+			.nav-right {
+				display: flex;
+				align-items: center;
+
+				.more-btn,
+				.refresh-btn {
+					width: 64rpx;
+					height: 64rpx;
+					border-radius: 50%;
+					background: rgba(255, 255, 255, 0.15);
 					display: flex;
 					align-items: center;
-					margin-bottom: 16rpx;
+					justify-content: center;
+					margin-left: 16rpx;
+				}
+			}
+		}
+	}
 
-					.user-name {
-						font-size: 44rpx;
-						font-weight: 700;
-						color: #202020;
-						line-height: 1.2;
-					}
 
-					.user-role {
-						margin-left: 16rpx;
-						padding: 6rpx 16rpx;
-						background: rgba(68, 110, 255, 0.10);
-						border-radius: 8rpx;
-						font-size: 24rpx;
-						font-weight: 500;
-						color: #446eff;
-					}
+	.user-card {
+		position: relative;
+		z-index: 2;
+		width: 100%;
+		height: 400rpx;
+		box-sizing: border-box;
+		padding: 80rpx 40rpx 32rpx;
+		position: relative;
+
+		.user-card-bg {
+			position: absolute;
+			top: 0;
+			left: 0;
+			width: 100%;
+			height: 100%;
+			z-index: 0;
+		}
+
+		view,
+		text {
+			position: relative;
+			z-index: 1;
+		}
+
+		.user-header {
+			.name-row {
+				display: flex;
+				align-items: center;
+				margin-bottom: 16rpx;
+
+				.user-name {
+					font-size: 44rpx;
+					font-weight: 700;
+					color: #202020;
+					line-height: 1.2;
 				}
 
-				.company-name {
-					font-size: 28rpx;
+				.user-role {
+					margin-left: 16rpx;
+					padding: 6rpx 16rpx;
+					background: rgba(68, 110, 255, 0.10);
+					border-radius: 8rpx;
+					font-size: 24rpx;
 					font-weight: 500;
-					color: #666666;
-					line-height: 1.4;
+					color: #446eff;
 				}
 			}
 
-			.avatar-wrapper {
-				position: absolute;
-				top: 32rpx;
-				right: 36rpx;
-				z-index: 2;
+			.company-name {
+				font-size: 28rpx;
+				font-weight: 500;
+				color: #666666;
+				line-height: 1.4;
 			}
+		}
 
-			.user-contact {
-				margin-top: 32rpx;
+		.avatar-wrapper {
+			position: absolute;
+			top: 32rpx;
+			right: 36rpx;
+			z-index: 2;
+		}
 
-				.contact-row {
-					display: flex;
-					align-items: flex-start;
-					margin-bottom: 16rpx;
+		.user-contact {
+			margin-top: 32rpx;
 
-					uni-icons {
-						margin-right: 12rpx;
-						flex-shrink: 0;
-					}
+			.contact-row {
+				display: flex;
+				align-items: center;
+				margin-bottom: 16rpx;
 
-					.contact-text {
-						font-size: 26rpx;
-						color: #666666;
-					}
+				uni-icons {
+					margin-right: 12rpx;
+					flex-shrink: 0;
 				}
-			}
 
-			.share-btn-wrapper {
-				position: absolute;
-				bottom: 90rpx;
-				right: 40rpx;
-
-				.share-btn {
-					padding: 14rpx 36rpx;
-					background: linear-gradient(90deg, #446dff 0%, #6b85ff 100%);
-					border-radius: 32rpx;
-					box-shadow: 0 4rpx 12rpx rgba(68, 110, 255, 0.35);
-
-					.share-text {
-						font-size: 26rpx;
-						font-weight: 500;
-						color: #ffffff;
-					}
+				.contact-text {
+					font-size: 26rpx;
+					color: #666666;
 				}
 			}
 		}
+
 	}
 
-	/* 最近访客模块 */
-	.recent-visitors {
-		padding: 20rpx;
-		background: #f2f6ff;
-		border: 2rpx solid rgba(255, 255, 255, 0.80);
-		border-radius: 28rpx;
+	/* 用户信息卡片 */
+	.page-top {
+		margin: 0 24rpx 24rpx;
+
 
-		.section-header {
+		.control-card {
+			background-color: #fff;
+			border-radius: 0 0 24rpx 24rpx;
+			position: relative;
+			z-index: 1;
+			bottom: 24rpx;
 			display: flex;
 			align-items: center;
-			justify-content: space-between;
-			margin-bottom: 24rpx;
-
-			.section-title {
-				font-size: 32rpx;
-				font-weight: 600;
-				color: #333333;
-			}
+			justify-content: space-around;
+			padding-top: 48rpx;
+			padding-bottom: 24rpx;
 
-			.visitor-count {
+			.item {
 				display: flex;
+				flex-direction: column;
 				align-items: center;
-				margin-left: 20rpx;
-
-				.avatar-group {
-					display: flex;
-					margin-right: 12rpx;
-
-					.group-avatar {
-						width: 32rpx;
-						height: 32rpx;
-						border-radius: 50%;
-						border: 4rpx solid #ffffff;
-						margin-left: -16rpx;
+				justify-content: center;
+				gap: 4rpx;
 
-						&:first-child {
-							margin-left: 0;
-						}
-					}
+				image {
+					width: 64rpx;
+					height: 64rpx;
 				}
 
-				.visitor-number {
-					font-size: 24rpx;
-					color: #999999;
+				.text {
+					font-size: 26rpx !important;
+					color: #202020;
 				}
 			}
-
-			.view-more {
-				font-size: 24rpx;
-				color: #667eea;
-				margin-left: auto;
-			}
 		}
 
-		.visitor-list {
-			background: #ffffff;
-			border: 2rpx solid #ffffff;
-			border-radius: 28rpx;
 
-			.visitor-item {
-				padding: 20rpx;
+	}
 
-				.visitor-left {
-					display: grid;
+	// 名片内容区域
+	.card-content {
+		margin: 0 24rpx;
+		padding: 0 24rpx;
+		border-radius: 24rpx;
+		background: #ffffff;
+		box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.04);
+		position: relative;
+		bottom: 24rpx;
+		z-index: 2;
+	}
 
-					.visitor-top {
-						display: grid;
-						grid-template-columns: auto 1fr auto;
-						gap: 6rpx;
-					}
+	// Tab 切换区域
+	.tab-section {
+		border-radius: 24rpx 24rpx 0 0;
+		padding: 0 40rpx;
 
-					.visitor-name-row {
-						display: flex;
-						align-items: center;
-
-						.visitor-name {
-							font-size: 24rpx;
-							font-weight: 500;
-							color: #8390b1;
-							margin: 0 10rpx;
-						}
-
-						.visitor-tag {
-							width: 92rpx;
-							height: 40rpx;
-							text-align: center;
-							line-height: 40rpx;
-							border: 1.2rpx solid #ff9230;
-							border-radius: 12rpx;
-							font-size: 24rpx;
-							font-weight: 500;
-							color: #ff9230;
-						}
-					}
+		.tab-wrapper {
+			display: flex;
+			border-bottom: 1rpx solid #f0f0f0;
 
-					.view-more-btn {
-						font-size: 24rpx;
-						color: #999999;
-					}
+			.tab-item {
+				flex: 1;
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				padding: 32rpx 0;
+				position: relative;
 
-					.visitor-avatar {
-						width: 40rpx;
-						height: 40rpx;
-						border-radius: 50%;
-						background: #ffffff;
-						padding: 4rpx;
-						box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
-
-						image {
-							width: 100%;
-							height: 100%;
-							border-radius: 50%;
-						}
-					}
+				.tab-text {
+					font-size: 28rpx;
+					color: #999999;
+					font-weight: 500;
 				}
 
-
-
-				.visitor-meta {
-					display: flex;
-					align-items: flex-start;
-					margin-bottom: 16rpx;
-					gap: 32rpx;
-
-					.meta-item {
-						display: flex;
-						align-items: flex-start;
-
-						.meta-label {
-							font-size: 22rpx;
-							color: #999999;
-						}
-
-						.meta-value {
-							font-size: 22rpx;
-							color: #666666;
-						}
-					}
+				&.active .tab-text {
+					color: #333333;
+					font-weight: 600;
 				}
 
-				.visitor-product {
-					display: flex;
-					align-items: flex-start;
-					background: #ffffff;
-					border-radius: 16rpx;
-					padding: 16rpx;
-					box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
-
-					.product-image {
-						width: 72rpx;
-						height: 72rpx;
-						border-radius: 12rpx;
-						background-color: #30cfd0;
-						margin-right: 16rpx;
-					}
-
-					.product-info {
-						flex: 1;
-						display: flex;
-						flex-direction: column;
-						justify-content: center;
-
-						.product-name {
-							font-size: 24rpx;
-							font-weight: 500;
-							color: #08105c;
-						}
-
-						.product-tag,
-						.product-brand {
-							font-size: 20rpx;
-							color: #999999;
-							margin-right: 12rpx;
-						}
-					}
+				.tab-indicator {
+					position: absolute;
+					bottom: 0;
+					width: 60rpx;
+					height: 4rpx;
+					background: linear-gradient(90deg, #4A90E2 0%, #6FB3F2 100%);
+					border-radius: 2rpx;
 				}
-
 			}
 		}
-
-		.drag-handle {
-			width: 80rpx;
-			height: 8rpx;
-			background: rgba(0, 0, 0, 0.2);
-			border-radius: 4rpx;
-			margin: 24rpx auto 0;
-		}
 	}
 
-	/* 功能菜单网格 */
-	.function-grid {
-		display: grid;
-		grid-template-columns: repeat(4, 1fr);
-		gap: 24rpx;
-		margin-top: 20rpx;
-		padding: 32rpx 24rpx;
-		height: 322rpx;
-		background: linear-gradient(180deg, #eff6ff, #ffffff 42%);
-		border: 2rpx solid #ffffff;
-		border-radius: 28rpx;
-		box-shadow: 0rpx 8rpx 8rpx 0rpx rgba(178, 194, 208, 0.10);
-
-		.grid-item {
-			display: flex;
-			flex-direction: column;
-			align-items: center;
+	// 产品列表
+	.product-list {
+		padding: 24rpx 40rpx;
 
-			.grid-icon {
-				width: 54rpx;
-				height: 54rpx;
-				border-radius: 28rpx;
-				display: flex;
-				align-items: center;
-				justify-content: center;
-				margin-bottom: 12rpx;
-
-				.icon-text {
-					font-size: 48rpx;
-				}
-			}
-
-			.clue-icon {
-				background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-			}
-
-			.customer-icon {
-				background: linear-gradient(135deg, #30cfd0 0%, #330867 100%);
-			}
+		.product-item {
+			display: flex;
+			padding: 24rpx 0;
+			border-bottom: 1rpx solid #f0f0f0;
 
-			.contact-icon {
-				background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
+			&:last-child {
+				border-bottom: none;
 			}
 
-			.pool-icon {
-				background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+			.product-image {
+				width: 160rpx;
+				height: 160rpx;
+				border-radius: 12rpx;
+				background: #f5f5f5;
+				flex-shrink: 0;
+				margin-right: 24rpx;
 			}
 
-			.opportunity-icon {
-				background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
-			}
+			.product-info {
+				flex: 1;
+				display: flex;
+				flex-direction: column;
+				justify-content: center;
 
-			.payment-icon {
-				background: linear-gradient(135deg, #ffd89b 0%, #19547b 100%);
-			}
+				.product-title {
+					font-size: 28rpx;
+					color: #333333;
+					margin-bottom: 12rpx;
+					line-height: 1.5;
+				}
 
-			.product-icon {
-				background: linear-gradient(135deg, #89f7fe 0%, #66a6ff 100%);
+				.product-desc {
+					font-size: 24rpx;
+					color: #999999;
+				}
 			}
+		}
+	}
 
-			.all-icon {
-				background: linear-gradient(135deg, #cd9cf2 0%, #f6f3ff 100%);
-			}
+	// 企业简介
+	.company-section {
+		background: #ffffff;
+		padding: 40rpx;
+
+		.company-content {
+			.company-text {
+				display: block;
+				font-size: 28rpx;
+				color: #666666;
+				line-height: 1.8;
+				margin-bottom: 24rpx;
+
+				::v-deep img {
+					max-width: 100% !important;
+				}
 
-			.grid-label {
-				font-size: 24rpx;
-				color: #333333;
+				&:last-child {
+					margin-bottom: 0;
+				}
 			}
 		}
 	}
 
-	/* 业务日历模块 */
-	.business-calendar {
+	// 隐藏的 canvas 容器
+	.hidden-canvas-box {
+		position: fixed;
+		left: -9999px;
+		top: -9999px;
+		width: 1px;
+		height: 1px;
+		overflow: hidden;
+	}
+
+	// 二维码弹窗样式
+	.qr-popup {
+		margin: 100rpx auto;
+
+		width: 600rpx;
 		background: #ffffff;
-		margin: 20rpx 0;
-		padding: 32rpx;
 		border-radius: 24rpx;
-		box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
+		padding: 40rpx;
+		box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
 
-		.section-header {
-			display: flex;
-			align-items: center;
-			justify-content: space-between;
-			margin-bottom: 24rpx;
+		.qr-header {
+			text-align: center;
+			margin-bottom: 40rpx;
 
-			.section-title {
-				font-size: 32rpx;
+			.qr-title {
+				display: block;
+				font-size: 36rpx;
 				font-weight: 600;
-				color: #333333;
+				color: #202020;
+				margin-bottom: 12rpx;
 			}
 
-			.view-more {
-				font-size: 24rpx;
-				color: #667eea;
+			.qr-subtitle {
+				display: block;
+				font-size: 26rpx;
+				color: #999999;
 			}
 		}
 
-		.calendar-header {
-			text-align: center;
-			margin-bottom: 20rpx;
+		.qr-content {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			min-height: 400rpx;
+			margin-bottom: 40rpx;
 
-			.calendar-month {
-				font-size: 30rpx;
-				font-weight: 600;
-				color: #333333;
+			.qr-image {
+				width: 400rpx;
+				height: 400rpx;
+				border-radius: 16rpx;
+				box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
 			}
-		}
 
-		.calendar-weekdays {
-			display: grid;
-			grid-template-columns: repeat(7, 1fr);
-			text-align: center;
-			margin-bottom: 16rpx;
-
-			.weekday {
-				font-size: 24rpx;
-				color: #999999;
-				padding: 12rpx 0;
+			.qr-loading {
+				display: flex;
+				justify-content: center;
+				align-items: center;
 			}
 		}
 
-		.calendar-dates {
-			display: grid;
-			grid-template-columns: repeat(7, 1fr);
-			gap: 8rpx;
-			margin-bottom: 32rpx;
+		.qr-actions {
+			display: flex;
+			justify-content: space-around;
 
-			.date-cell {
-				aspect-ratio: 1;
+			.action-btn {
 				display: flex;
 				flex-direction: column;
 				align-items: center;
-				justify-content: center;
-				border-radius: 50%;
-				position: relative;
-
-				.date-num {
-					font-size: 26rpx;
-					color: #333333;
-				}
-
-				&.today {
-					background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+				gap: 12rpx;
+				padding: 20rpx 40rpx;
+				border-radius: 16rpx;
+				background: rgba(64, 128, 255, 0.08);
 
-					.date-num {
-						color: #ffffff;
-						font-weight: 600;
+				.action-text {
+					&::after {
+						border: none;
 					}
-				}
 
-				&.has-event {
-					.event-dot {
-						width: 12rpx;
-						height: 12rpx;
-						background: #ff6b6b;
-						border-radius: 50%;
-						position: absolute;
-						bottom: 8rpx;
-					}
+					line-height: 1;
+					background-color: transparent;
+					font-size: 26rpx;
+					color: #4080FF;
+					font-weight: 500;
 				}
 			}
 		}
+	}
 
-		.today-schedule {
-			.schedule-item {
-				display: flex;
-				align-items: flex-start;
-				padding: 24rpx;
-				background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
-				border-radius: 16rpx;
-				margin-bottom: 16rpx;
-				border-left: 6rpx solid #667eea;
-
-				&.tomorrow {
-					border-left-color: #30cfd0;
-				}
-
-				.schedule-time {
-					display: flex;
-					flex-direction: column;
-					align-items: center;
-					margin-right: 20rpx;
-					min-width: 100rpx;
-
-					.time-period {
-						font-size: 22rpx;
-						color: #999999;
-						margin-bottom: 4rpx;
-					}
-
-					.time-value {
-						font-size: 28rpx;
-						font-weight: 600;
-						color: #333333;
-					}
-				}
-
-				.schedule-content {
-					flex: 1;
+	.resetButton {
+		background-color: transparent !important;
+		border: none !important;
+		display: inline !important;
 
-					.schedule-title {
-						font-size: 28rpx;
-						color: #333333;
-						line-height: 1.5;
-					}
-				}
-			}
+		&::after {
+			border: none !important;
 		}
-	}
 
-	.bottom-spacer {
-		height: 40rpx;
 	}
 </style>

+ 119 - 14
pages/mine/card.vue

@@ -61,11 +61,11 @@
 			<!-- Tab 切换 -->
 			<view class="tab-section">
 				<view class="tab-wrapper">
-					<view class="tab-item" :class="{ active: currentTab === 'products' }"
+				<!-- 	<view class="tab-item" :class="{ active: currentTab === 'products' }"
 						@click="switchTab('products')">
 						<text class="tab-text">产品列表</text>
 						<view class="tab-indicator" v-if="currentTab === 'products'"></view>
-					</view>
+					</view> -->
 					<view class="tab-item" :class="{ active: currentTab === 'company' }" @click="switchTab('company')">
 						<text class="tab-text">企业简介</text>
 						<view class="tab-indicator" v-if="currentTab === 'company'"></view>
@@ -98,7 +98,7 @@
 
 		<!-- 隐藏的 Canvas 用于生成名片快照 -->
 		<canvas id="posterCanvas" type="2d"
-			style="position: fixed; left: -9999px; top: -9999px; width: 750px; height: 780px;"></canvas>
+			style="position: fixed; left: -9999px; top: -9999px; width: 750px; height: 900px;"></canvas>
 
 		<!-- 隐藏的 Canvas 用于生成二维码海报 -->
 		<view class="hidden-canvas-box">
@@ -160,6 +160,25 @@
 								<text class="contact-text">{{ cardInfo.companyAddress || '暂无地址' }}</text>
 							</view>
 						</view>
+
+						<!-- 名片底部二维码 -->
+						<view class="card-qr-section">
+							<view class="qr-divider"></view>
+							<view class="qr-wrapper">
+								<view class="qr-icon-area">
+									<image
+										v-if="qrInfo && qrInfo.image"
+										:src="(qrInfo.image || '').startsWith('data:') ? qrInfo.image : 'data:image/png;base64,' + qrInfo.image"
+										class="qr-code-img"
+										mode="aspectFit"
+									/>
+									<view v-else class="qr-placeholder">
+										<text class="qr-placeholder-text">名片码</text>
+									</view>
+								</view>
+								<text class="qr-hint">扫一扫查看我的名片</text>
+							</view>
+						</view>
 					</view>
 				</view>
 				
@@ -244,7 +263,7 @@
 		qrInfo,
 	} = storeToRefs(userStore)
 
-	const currentTab = ref('products')
+	const currentTab = ref('company')
 	// 名片快照图片路径
 	const cardSnapshot = ref('')
 	// 二维码海报图片路径
@@ -268,6 +287,10 @@
 		if (!companyInfo.value.name) {
 			await userStore.queryCompanyInfo()
 		}
+		// 预加载名片二维码,确保分享弹窗底部显示名片码
+		if (!qrInfo.value || !qrInfo.value.image) {
+			await userStore.queryCardQrcode()
+		}
 	})
 
 	const makeCall = () => {
@@ -291,6 +314,10 @@
 		})
 
 		try {
+			// 确保二维码已加载
+			if (!qrInfo.value || !qrInfo.value.image) {
+				await userStore.queryCardQrcode()
+			}
 
 			// 生成名片快照
 			const snapshotPath = await generateCardPoster(cardInfo.value, qrInfo.value)
@@ -329,17 +356,35 @@
 	}
 
 	const shareUserCard = async () => {
-		const snapshotPath = await generateCardPoster(cardInfo.value, qrInfo.value)
-		wx.showShareImageMenu({
-			path: snapshotPath,
-			entrancePath:'pages/splash/splash?userId=' + cardInfo.value.userId,
-			success: () => {
-				console.log('分享菜单已调起');
-			},
-			fail: (err) => {
-				console.error('调起分享菜单失败', err);
+		uni.showLoading({
+			title: '生成分享图片...',
+			mask: true
+		})
+		try {
+			// 确保二维码已加载
+			if (!qrInfo.value || !qrInfo.value.image) {
+				await userStore.queryCardQrcode()
 			}
-		});
+			const snapshotPath = await generateCardPoster(cardInfo.value, qrInfo.value)
+			uni.hideLoading()
+			wx.showShareImageMenu({
+				path: snapshotPath,
+				entrancePath:'pages/splash/splash?userId=' + cardInfo.value.userId,
+				success: () => {
+					console.log('分享菜单已调起');
+				},
+				fail: (err) => {
+					console.error('调起分享菜单失败', err);
+				}
+			});
+		} catch (error) {
+			console.error('分享失败:', error)
+			uni.hideLoading()
+			uni.showToast({
+				title: '分享失败,请重试',
+				icon: 'none'
+			})
+		}
 
 	}
 
@@ -858,6 +903,66 @@
 		}
 	}
 
+	// 分享弹窗卡片底部二维码
+	.card-qr-section {
+		position: relative;
+		z-index: 1;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		padding: 8rpx 0 4rpx;
+
+		.qr-divider {
+			width: 80%;
+			height: 1rpx;
+			background: #e8e8e8;
+			margin-bottom: 12rpx;
+		}
+
+		.qr-wrapper {
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+			gap: 6rpx;
+
+			.qr-icon-area {
+				width: 96rpx;
+				height: 96rpx;
+				border-radius: 12rpx;
+				overflow: hidden;
+				border: 2rpx solid #e8e8e8;
+				background: #ffffff;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+
+				.qr-code-img {
+					width: 100%;
+					height: 100%;
+				}
+
+				.qr-placeholder {
+					width: 100%;
+					height: 100%;
+					display: flex;
+					align-items: center;
+					justify-content: center;
+					background: #f5f5f5;
+
+					.qr-placeholder-text {
+						font-size: 18rpx;
+						color: #cccccc;
+					}
+				}
+			}
+
+			.qr-hint {
+				font-size: 18rpx;
+				color: #b0b0b0;
+			}
+		}
+	}
+
 	.resetButton {
 		background-color: transparent !important;
 		border: none !important;

+ 5 - 5
pages/mine/userCard.vue

@@ -60,11 +60,11 @@
 			<!-- Tab 切换 -->
 			<view class="tab-section">
 				<view class="tab-wrapper">
-					<view class="tab-item" :class="{ active: currentTab === 'products' }"
+				<!-- 	<view class="tab-item" :class="{ active: currentTab === 'products' }"
 						@click="switchTab('products')">
 						<text class="tab-text">产品列表</text>
 						<view class="tab-indicator" v-if="currentTab === 'products'"></view>
-					</view>
+					</view> -->
 					<view class="tab-item" :class="{ active: currentTab === 'company' }" @click="switchTab('company')">
 						<text class="tab-text">企业简介</text>
 						<view class="tab-indicator" v-if="currentTab === 'company'"></view>
@@ -72,7 +72,7 @@
 				</view>
 			</view>
 			<!-- 产品列表 -->
-			<view class="product-list" v-if="currentTab === 'products'">
+<!-- 			<view class="product-list" v-if="currentTab === 'products'">
 				<EmptyState v-if="productList.length === 0" text="暂无产品" sub-text="还没有添加产品信息" icon="gift" />
 				<view class="product-item" v-for="(item, index) in productList" :key="index">
 					<image class="product-image" :src="item.image" mode="aspectFill" />
@@ -81,7 +81,7 @@
 						<text class="product-desc">{{ item.description }}</text>
 					</view>
 				</view>
-			</view>
+			</view> -->
 			<!-- 企业简介 -->
 			<view class="company-section" v-if="currentTab === 'company'">
 				<view class="company-content">
@@ -117,7 +117,7 @@
 		companyInfo
 	} = storeToRefs(userStore)
 
-	const currentTab = ref('products')
+	const currentTab = ref('company')
 
 	const productList = ref([])
 

+ 14 - 6
utils/poster.js

@@ -81,19 +81,27 @@ const drawContactRow = (ctx, emoji, text, x, y) => {
 	ctx.textAlign = 'center'
 	ctx.textBaseline = 'middle'
 	ctx.fillText(emoji, x + 20, y + 20)
-	// 文字
+	// 文字 - 超长时自动换行
 	ctx.font = '26px sans-serif'
 	ctx.textAlign = 'left'
 	ctx.textBaseline = 'middle'
 	ctx.fillStyle = '#555555'
-	let display = text
-	if (text.length > 24) display = text.substring(0, 22) + '...'
-	ctx.fillText(display, x + 52, y + 20)
+	// 计算可用宽度(图标到右边界)
+	const textMaxWidth = 480  // 联系方式文本最大宽度
+	const textX = x + 52
+	if (ctx.measureText(text).width > textMaxWidth) {
+		// 超长时换行显示(从垂直居中位置开始)
+		ctx.textBaseline = 'top'
+		const lineY = y + 10 // 和图标居中对齐的偏移
+		fillTextWrap(ctx, text, textX, lineY, textMaxWidth, 40, 'left')
+	} else {
+		ctx.fillText(text, textX, y + 20)
+	}
 }
 
-const fillTextWrap = (ctx, text, x, y, maxWidth, lineHeight) => {
+const fillTextWrap = (ctx, text, x, y, maxWidth, lineHeight, align = 'left') => {
 	if (!text) return y
-	ctx.textAlign = 'center'
+	ctx.textAlign = align
 	ctx.textBaseline = 'top'
 	const chars = text.split('')
 	let line = '', cy = y