invite-detail.vue 7.22 KB
<template>
	<view class="container">
		<!-- 详情卡片 -->
		<view class="detail-card">
			<view class="card-header">邀约详情</view>
			<view class="detail-content">
				<!-- 加载状态 -->
				<view v-if="loading" class="loading">
					<u-loading-icon mode="circle" color="#43a047"></u-loading-icon>
					<text class="loading-text">正在加载详情...</text>
				</view>
				
				<!-- 错误状态 -->
				<view v-else-if="error" class="error-state">
					<view class="error-text">{{ error }}</view>
					<u-button class="retry-btn" @click="retryLoad" type="primary" size="small">重试</u-button>
				</view>
				
				<!-- 详情内容 -->
				<view v-else-if="inviteData" class="info-sections">
					<!-- 基本信息 -->
					<view class="info-section">
						<view class="section-title">基本信息</view>
						<view class="info-grid">
							<view class="info-item">
								<text class="info-label">客户姓名</text>
								<text class="info-value">{{ inviteData.yykhxm || inviteData.gkxm || '未知客户' }}</text>
							</view>
							<view class="info-item">
								<text class="info-label">联系时间</text>
								<text class="info-value">{{ utils.formatTime(inviteData.lxsj) }}</text>
							</view>
							<view class="info-item">
								<text class="info-label">预约时间</text>
								<text class="info-value">{{ utils.formatTime(inviteData.yysj) }}</text>
							</view>
							<view class="info-item">
								<text class="info-label">电话状态</text>
								<view class="status-badge" :class="inviteData.dhsfyx=='是'?'success':inviteData.dhsfyx=='否'?'failed':'pending'">
									{{ getStatusText(inviteData.dhsfyx) }}
								</view>
							</view>
							<view class="info-item">
								<text class="info-label">邀约人</text>
								<text class="info-value">{{ inviteData.yyrName || inviteData.yyr || '无' }}</text>
							</view>
							<view class="info-item" v-if="inviteData.tkbh">
								<text class="info-label">关联拓客号</text>
								<text class="info-value expansion-link" @click="goToExpansion(inviteData.tkbh)">
									{{ inviteData.tkbh }}
								</text>
							</view>
						</view>
					</view>
					
					<!-- 联系记录 -->
					<view class="info-section">
						<view class="section-title">联系记录</view>
						<view class="info-item full-width">
							<text class="info-label">记录内容</text>
							<text class="info-value contact-record">{{ inviteData.lxjl || '无联系记录' }}</text>
						</view>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	import inviteApi from '@/apis/modules/invite.js'

	export default {
		data() {
			return {
				loading: false,
				error: '',
				inviteId: null,
				inviteData: null
			}
		},

		onLoad(options) {
			this.initializePage(options)
		},

		methods: {
			// 初始化页面
			async initializePage(options) {
				try {
					// 检查登录状态
					await this.checkLoginStatus()
					
					// 获取URL参数中的ID
					this.inviteId = options.id
					
					if (!this.inviteId) {
						this.error = '缺少邀约ID参数'
						return
					}
					
					// 加载邀约详情
					await this.loadInviteDetail()
				} catch (error) {
					console.error('页面初始化失败:', error)
					this.error = '页面初始化失败,请刷新重试'
				}
			},

			// 检查登录状态
			async checkLoginStatus() {
				const userInfo = uni.getStorageSync('userInfo')
				if (!userInfo || Object.keys(userInfo).length === 0) {
					uni.showToast({
						title: '请先登录',
						icon: 'none'
					})
					setTimeout(() => {
						uni.reLaunch({
							url: '/pages/login/login'
						})
					}, 1500)
					return
				}
			},

			// 加载邀约详情
			async loadInviteDetail() {
				try {
					this.loading = true
					this.error = ''
					
					const res = await inviteApi.getInviteDetail(this.inviteId)
					
					if (res.code === 200 && res.data) {
						this.inviteData = res.data
					} else {
						throw new Error(res.message || '获取详情失败')
					}
					
				} catch (error) {
					console.error('加载邀约详情失败:', error)
					this.error = '加载详情失败,请重试'
				} finally {
					this.loading = false
				}
			},

			// 重试加载
			async retryLoad() {
				await this.loadInviteDetail()
			},


			// 获取状态文本
			getStatusText(status) {
				if (status === '是') return '电话有效'
				if (status === '否') return '电话无效'
				return '待确认'
			},

			// 获取状态样式类
			getStatusClass(status) {
				if (status === '是') return 'success'
				if (status === '否') return 'failed'
				return 'pending'
			},

			// 跳转到拓客详情
			goToExpansion(tkbh) {
				if (tkbh) {
					uni.navigateTo({
						url: '/pages/expansion-detail/expansion-detail?id=' + tkbh
					})
				}
			}
		}
	}
</script>

<style lang="scss" scoped>
	.container {
		min-height: 100vh;
		background: linear-gradient(135deg, #e8f5e9 0%, #b2dfdb 100%);
		padding: 40rpx;
		box-sizing: border-box;
	}

	.detail-card {
		background: #fff;
		border-radius: 32rpx;
		box-shadow: 0 8rpx 32rpx rgba(76, 175, 80, 0.1);
		overflow: hidden;
	}

	.card-header {
		background: linear-gradient(120deg, #43e97b 0%, #38f9d7 100%);
		padding: 32rpx 40rpx;
		color: #fff;
		font-weight: 600;
		letter-spacing: 2rpx;
		font-size: 32rpx;
	}

	.detail-content {
		padding: 40rpx;
	}

	.loading {
		text-align: center;
		padding: 80rpx 40rpx;
		color: #6a9c6a;
		font-size: 28rpx;
		display: flex;
		flex-direction: column;
		align-items: center;
		gap: 20rpx;
	}

	.loading-text {
		font-size: 28rpx;
	}

	.error-state {
		text-align: center;
		padding: 80rpx 40rpx;
		color: #c62828;
	}

	.error-text {
		font-size: 28rpx;
		margin-bottom: 24rpx;
	}

	.retry-btn {
		margin-top: 24rpx;
		background: #43a047;
		color: #fff;
		border-radius: 16rpx;
		padding: 16rpx 32rpx;
		font-size: 28rpx;
	}

	.info-sections {
		display: block;
	}

	.info-section {
		margin-bottom: 48rpx;
	}

	.info-section:last-child {
		margin-bottom: 0;
	}

	.section-title {
		font-size: 32rpx;
		font-weight: 600;
		color: #2e7d32;
		margin-bottom: 32rpx;
		padding-bottom: 16rpx;
		border-bottom: 4rpx solid #e8f5e9;
	}

	.info-grid {
		display: grid;
		grid-template-columns: 1fr 1fr;
		gap: 32rpx;
	}

	.info-item {
		display: flex;
		flex-direction: column;
	}

	.info-item.full-width {
		grid-column: 1 / -1;
	}

	.info-label {
		font-size: 24rpx;
		color: #6a9c6a;
		margin-bottom: 8rpx;
		font-weight: 500;
	}

	.info-value {
		font-size: 28rpx;
		color: #2e7d32;
		font-weight: 500;
		padding: 16rpx 24rpx;
		background: #f8fff8;
		border-radius: 16rpx;
		border: 2rpx solid #e8f5e9;
		word-break: break-all;
	}

	.expansion-link {
		color: #43a047 !important;
		text-decoration: underline;
		cursor: pointer;
	}

	.contact-record {
		min-height: 120rpx;
		white-space: pre-wrap;
		line-height: 1.6;
	}

	.status-badge {
		display: inline-block;
		padding: 8rpx 24rpx;
		border-radius: 40rpx;
		font-size: 24rpx;
		font-weight: 500;
		text-align: center;
		margin-top: 8rpx;
	}

	.status-badge.success {
		background: #e8f5e9;
		color: #2e7d32;
		border: 2rpx solid #c8e6c9;
	}

	.status-badge.failed {
		background: #ffebee;
		color: #c62828;
		border: 2rpx solid #ffcdd2;
	}

	.status-badge.pending {
		background: #fff3e0;
		color: #ef6c00;
		border: 2rpx solid #ffe0b2;
	}
</style>