<template>
	<view class="content" :class="screenMode">
		<view class="split-layout" v-if="screenMode === 'heng'">
			<!-- 左侧联系人列表 -->
			<view class="left-panel">
				<view class="header">
					<view class="header-left">
						<image class="avatar" :src="studentAvatar"></image>
						<text class="greeting">{{ studentName }}，你好！</text>
					</view>
					<view class="logout-btn" @click="killBackgroundApp">
						<image src="/static/icon/logout.png"></image>
					</view>
				</view>
				<view class="contact-list">
					<view class="contact-card" v-for="contact in contacts" :key="contact.id"
						:class="{ 'active': currentContact?.id === contact.id }">
						<view class="contact-info">
							<image class="contact-avatar" :src="contact.avatar"></image>
							<text class="contact-name">{{ contact.username }}</text>
						</view>
						<view class="action-buttons">
							<view class="action-btn" @click.stop="startAudioCall(contact)">
								<view class="action-btn-icon">
									<image src="/static/icon/audio.png"></image>
								</view>
								<text>音频</text>
							</view>
							<view class="action-btn" @click.stop="startVideoCall(contact)">
								<view class="action-btn-icon">
									<image src="/static/icon/video.png"></image>
								</view>
								<text>视频</text>
							</view>
							<view class="action-btn" :class="{ 'message-point': contact.hasPoints }"
								@click="selectContact(contact)">
								<view class="action-btn-icon">
									<image src="/static/icon/message.png"></image>
								</view>
								<text>留言</text>
							</view>
						</view>
					</view>
				</view>

				<!-- 个人服务状态 -->
				<view class="service-status" v-if="serviceStatus">
					<view class="service-status-header">
						<text class="service-status-title">服务状态</text>
					</view>
					<view class="service-status-content">
						<view class="status-item" v-if="serviceStatus.sfmf === 1">
							<text class="status-label">免费服务</text>
						</view>
						<view class="status-item" v-if="serviceStatus.zdsc > 0">
							<text class="status-label">时长</text>
							<text class="status-value">{{ serviceStatus.ljsc || 0 }}/{{ serviceStatus.zdsc }}分钟</text>
						</view>
						<view class="status-item" v-if="serviceStatus.zdcs > 0">
							<text class="status-label">次数</text>
							<text class="status-value">{{ serviceStatus.ljcs || 0 }}/{{ serviceStatus.zdcs }}次</text>
						</view>
						<view class="status-item" v-if="serviceStatus.zdll > 0">
							<text class="status-label">流量</text>
							<text class="status-value">{{ serviceStatus.ljll || 0 }}/{{ serviceStatus.zdll }}MB</text>
						</view>
					</view>
				</view>
			</view>

			<!-- 右侧消息面板 -->
			<view class="right-panel">
				<message-page v-if="currentContact" :contact-id="currentContact.id" :contact-name="currentContact.username" role="device"></message-page>
				<!-- <view v-else class="empty-message">
					<text>请选择联系人开始聊天</text>
				</view> -->
			</view>
		</view>
		<view class="split-layout" v-else>
			<!-- 头部欢迎语 -->
			<view class="header">
				<view class="header-left">
					<image class="avatar" :src="studentAvatar"></image>
					<text class="greeting">{{ studentName }}，你好！</text>
				</view>
				<view class="logout-btn" @click="killBackgroundApp">
					<image src="/static/icon/logout.png"></image>
				</view>
			</view>

			<!-- 调试信息 -->
			<!-- <view class="debug-info" @click="startCall">
				<text>Options1: {{ JSON.stringify(options) }}</text>
			</view> -->

			<!-- 联系人卡片列表 -->
			<view class="contact-list">
				<view class="contact-card" v-for="contact in contacts" :key="contact.id">
					<view class="contact-info">
						<image class="contact-avatar" :src="contact.avatar"></image>
						<text class="contact-name">{{ contact.username }}</text>
					</view>
					<view class="action-buttons">
						<view class="action-btn" @click="startAudioCall(contact)">
							<view class="action-btn-icon">
								<image src="/static/icon/audio.png"></image>
							</view>
							<text>音频</text>
						</view>
						<view class="action-btn" @click="startVideoCall(contact)">
							<view class="action-btn-icon">
								<image src="/static/icon/video.png"></image>
							</view>
							<text>视频</text>
						</view>
						<view class="action-btn" :class="{ 'message-point': contact.hasPoints }"
							@click="goToMessage(contact)">
							<view class="action-btn-icon">
								<image src="/static/icon/message.png"></image>
							</view>
							<text>留言</text>
						</view>
					</view>
				</view>
			</view>

			<!-- 个人服务状态 -->
			<view class="service-status" v-if="serviceStatus">
				<view class="service-status-header">
					<text class="service-status-title">服务状态</text>
				</view>
				<view class="service-status-content">
					<view class="status-item" v-if="serviceStatus.sfmf === 1">
						<text class="status-label">免费服务</text>
					</view>
					<view class="status-item" v-if="serviceStatus.zdsc > 0">
						<text class="status-label">时长</text>
						<text class="status-value">{{ serviceStatus.ljsc || 0 }}/{{ serviceStatus.zdsc }}分钟</text>
					</view>
					<view class="status-item" v-if="serviceStatus.zdcs > 0">
						<text class="status-label">次数</text>
						<text class="status-value">{{ serviceStatus.ljcs || 0 }}/{{ serviceStatus.zdcs }}次</text>
					</view>
					<view class="status-item" v-if="serviceStatus.zdll > 0">
						<text class="status-label">流量</text>
						<text class="status-value">{{ serviceStatus.ljll || 0 }}/{{ serviceStatus.zdll }}MB</text>
					</view>
				</view>
			</view>
		</view>

		<!-- 自定义Modal -->
		<custom-modal
			:visible="modalVisible"
			:title="modalTitle"
			:content="modalContent"
			:showCancel="modalShowCancel"
			:confirmText="modalConfirmText"
			@confirm="handleModalConfirm"
			@cancel="handleModalCancel"
		/>
	</view>
</template>

<script>
import messagePage from '../parent/message.vue'
import customModal from '@/components/custom-modal.vue'
import { deviceApi } from '@/api/device'
import { getImageUrl } from '@/utils/util'
import websocketService from '@/utils/websocket'


const wmpfVoip = requirePlugin('wmpf-voip').default

const isWmpf = (typeof wmpf !== 'undefined')
// 指定接听方使用的小程序版本。formal/正式版（默认）；trial/体验版；developer/开发版
const miniprogramState = (() => {
	const accountInfo = wx.getAccountInfoSync();
	if (accountInfo && accountInfo.miniProgram) {
		const platform = { develop: 'developer', trial: 'trial', release: 'formal' }
		return platform[accountInfo.miniProgram.envVersion]
	}
})()
export default {
	components: {
		messagePage,
		customModal
	},
	data() {
		return {
			studentAvatar: 'https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132',
			studentName: '默认学生',
			title: '家庭联系',
			screenMode: 'heng',
			currentContact: null,
			contacts: [],
			serviceStatus: null, // 个人服务状态
			_voipEndPathSet: false, // 记录是否已设置通话结束跳转页面
			studentId: '1',
			sn: 'A1000006B624470',
			inactivityTimer: null,
			inactivityTimeout: 180000, // 3分钟
			options: null,
			// 自定义Modal相关
			modalVisible: false,
			modalTitle: '提示',
			modalContent: '',
			modalShowCancel: false,
			modalConfirmText: '确定',
			modalResolve: null, // 用于Promise
		}
	},
		async onLoad(options) {
			uni.$on('device-message-refresh', this.handleDeviceMessageRefresh)


		// console.log('Device onLoad', options)
		this.options = options

		// 🔧 关闭可能存在的旧Modal
		this.modalVisible = false
		if (this.modalResolve) {
			this.modalResolve(false) // 取消旧的Promise
			this.modalResolve = null
		}

		uni.getSystemInfo({
			success: (res) => {
				this.screenMode = res.windowWidth > res.windowHeight ? 'heng' : 'shu'
			}
		})

		// 🎯 检查是否从通话结束返回
		if (options && options.fromCall === 'true') {
			console.log('📞 检测到通话结束返回，准备记录通话')
			await this.recordCallAndRefresh(options)
			return // 处理完通话记录后直接返回
		}

		// 🎯 检查是否已有登录信息（从通话结束页面返回的情况）
		const userInfo = uni.getStorageSync('userInfo')
		if (userInfo && userInfo.devId && (!options || !options.sn)) {
			// 已登录且没有传递新的 sn，说明是从其他页面返回
			console.log('✅ 检测到已登录，使用缓存数据')

			// 恢复学生信息
			if (userInfo.xm) {
				this.studentName = userInfo.xm
			}
			if (userInfo.yszwj) {
				this.studentAvatar = getImageUrl(userInfo.yszwj)
			}

			// 恢复 sn
			this.sn = userInfo.devId
			await this.ensureDeviceSocketConnected()

			// 获取联系人列表
			await this.getContactList()

			// 检查个人服务状态
			await this.checkServiceStatus(115)

			// 注册通话事件
			this.registerVoipEvent()

			this.setVoipEndPagePath()

			// 初始化无操作检测
			this.resetInactivityTimer()

			

			// 添加全局点击事件监听
			const pages = getCurrentPages();
			const currentPage = pages[pages.length - 1];
			if (currentPage.$getAppWebview) {
				const webview = currentPage.$getAppWebview();
				webview.addEventListener('click', () => {
					this.handleUserActivity();
				});
			}

			return // 直接返回，不需要重新登录
		}

		// 🆕 新登录流程：从 options 获取 sn 和 cardNo
		if (options && options.sn) {
			this.sn = options.sn
		}
		await this.ensureDeviceSocketConnected()
		const cardNo = options && options.cardNo ? options.cardNo : ''

		// 可选的 studentId 参数
		if (options && options.studentId) {
			this.studentId = options.studentId
		}

		// 第一步: 设备登录
		const loginSuccess = await this.deviceLogin(this.sn, cardNo)

		// 登录成功后才继续后续操作
		if (!loginSuccess) {
			return // 登录失败，直接返回
		}

		this.registerVoipEvent()

		// 初始化无操作检测
		this.resetInactivityTimer()

		// 添加全局点击事件监听
		const pages = getCurrentPages();
		const currentPage = pages[pages.length - 1];
		if (currentPage.$getAppWebview) {
			const webview = currentPage.$getAppWebview();
			webview.addEventListener('click', () => {
				this.handleUserActivity();
			});
		}
	},
			onUnload() {
			uni.$off('device-message-refresh', this.handleDeviceMessageRefresh)
			// 清理定时器
			if (this.inactivityTimer) {
				clearTimeout(this.inactivityTimer);
			}
		},
		async onShow() {
			await this.ensureDeviceSocketConnected()
		},
	methods: {
		async ensureDeviceSocketConnected() {
			const ssDevId = String(this.sn || '').trim()
			if (!ssDevId) return
			try {
				await websocketService.ensureConnected({
					role: 'device',
					ssDevId,
					heartbeat: true,
					autoReconnect: true
				})
			} catch (error) {
				console.error('index 建立设备 websocket 失败:', error)
			}
		},
		// 显示自定义Modal
		showCustomModal(options = {}) {
			return new Promise((resolve) => {
				this.modalTitle = options.title || '提示'
				this.modalContent = options.content || ''
				this.modalShowCancel = options.showCancel || false
				this.modalConfirmText = options.confirmText || '确定'
				this.modalResolve = resolve
				this.modalVisible = true
			})
		},
		// 处理Modal确认
		handleModalConfirm() {
			this.modalVisible = false
			if (this.modalResolve) {
				this.modalResolve(true)
				this.modalResolve = null
			}
		},
		// 处理Modal取消
		handleModalCancel() {
			this.modalVisible = false
			if (this.modalResolve) {
				this.modalResolve(false)
				this.modalResolve = null
			}
		},
		// 设备登录
		async deviceLogin(sn, cardNo) {
			try {
				const result = await deviceApi.login(sn, cardNo)

				if (result && result.data) {
					const loginData = result.data

					// 🚫 检查登录失败的情况（废卡/登录过期等）
					if (loginData.msg) {
						// 有 msg 字段说明登录失败

						// 弹出自定义确认框
						const confirmed = await this.showCustomModal({
							title: '登录失败',
							content: '登录失败，卡无登记',
							showCancel: false,
							confirmText: '确定'
						})

						// 用户确认后，调用退出
						if (confirmed) {
							await this.killBackgroundApp()
						}

						return false
					}

					// 🎯 参考 H5 login.html 的 userData 构建方式（304-314行）
					// 后端返回的数据没有 userInfo 层级，需要手动构建
					const userData = {
						devId: loginData.devId,
						sbmc: loginData.sbmc,
						sessId: loginData.sessId,
						xm: loginData.xm,
						yhsbToken: loginData.yhsbToken,
						onlineToken: loginData.onlineToken,
						syList: loginData.sylist || loginData.syList,
						yhid: loginData.yhid,
						yhm: loginData.yhm
					}

					// 可选字段：如果存在则添加
					if (loginData.yszwj) {
						userData.yszwj = loginData.yszwj
					}
					if (loginData.zjzwj) {
						userData.zjzwj = loginData.zjzwj
					}

					// 保存完整的用户信息
					uni.setStorageSync('userInfo', userData)

					// 保存 JSESSIONID
					if (userData.sessId) {
						uni.setStorageSync('JSESSIONID', userData.sessId)
					} else {
						console.warn('⚠️ 登录数据中没有 sessId')
					}

					// 更新页面显示的学生信息
					if (userData.xm) {
						this.studentName = userData.xm
					}
					if (userData.yszwj){
						this.studentAvatar = getImageUrl(userData.yszwj)
					}
					// 如果登录返回了学生ID,更新当前学生ID
					if (loginData.studentId) {
						this.studentId = loginData.studentId
					}

					// ✅ 登录成功，获取联系人列表
					await this.getContactList()

					// 检查个人服务状态
					await this.checkServiceStatus(115)

					console.log('✅ 设备登录成功:', userData.xm)
					return true
				} else {
					throw new Error('登录返回数据格式错误')
				}
			} catch (error) {
				console.error('❌ 设备登录失败:', error)

				// 弹出自定义确认框
				await this.showCustomModal({
					title: '登录失败',
					content: '网络错误或服务异常',
					showCancel: false,
					confirmText: '确定'
				})

				// 用户确认后，调用退出
				await this.killBackgroundApp()

				return false
			}
		},

		// 通用通话方法，供音频和视频通话共用
		async startCall(contact, roomType) {
			const contactOpenid = (contact && (contact.openid || contact.wbid2 || contact.wbid || '') || '').trim()
			if (!contactOpenid) {
				uni.showToast({
					title: '请让家长先关注公众号，登陆小程序后再发起',
					icon: 'none'
				})
				return false
			}

			// 显示loading弹窗
			uni.showLoading({
				title: '呼叫中...',
				mask: true  // 添加遮罩，防止触摸穿透
			});

			// 记录当前联系人
			this.currentContact = contact;

			// 清除可能的上次通话记录，确保本次通话信息独立
			if (uni.getStorageSync('currcall')) {
				uni.removeStorageSync('currcall');
			}
			// 先存储基本联系人信息
			uni.setStorageSync('lastCallInfo', {
				name: contact.username || '未知联系人',
				avatar: contact.avatar || '/static/logo.png',
				duration: 0,
				time: new Date().toLocaleString(),
				type: roomType,
			});

			this.setVoipEndPagePath()
			try {
				const res = await wmpfVoip.initByCaller({
					roomType: roomType,
					caller: {
						id: this.sn,
					},
					listener: {
						id: contactOpenid,
						name: contact.username
					},
					businessType: 1,
					miniprogramState: miniprogramState
				})
				console.log("res:",res)
				if (res.isSuccess) {
					uni.hideLoading();
					uni.redirectTo({
						url: wmpfVoip.CALL_PAGE_PATH
					})
					return true
				} else {
					uni.hideLoading();
					console.error("呼叫失败,res:",res)
					uni.showToast({
						title: '呼叫失败1',
						icon: 'error'
					})
					
					return false
				}
			} catch (error) {
				uni.hideLoading();
				console.error('通话错误：', error)
				uni.showToast({
					title: '发起通话失败',
					icon: 'none'
				})
				return false
			}
		},
		// 设置通话结束跳转地址
		setVoipEndPagePath(forceUpdate) {
			if (this._voipEndPathSet && !forceUpdate) return;
			if (wmpfVoip) {
				const callInfo = uni.getStorageSync('lastCallInfo') || {};

				// 构建参数：如果需要记录通话，传递参数给首页
				let options = '';
				if (callInfo.needRecord && callInfo.duration > 0) {
					options = `fromCall=true&duration=${callInfo.duration}&callType=${callInfo.type || 'voice'}`;
					console.log('🔗 设置通话结束跳转参数:', options);
				}

				wmpfVoip.setVoipEndPagePath({
					url: '/pages/device/index',  // 通话结束直接返回首页
					key: 'Call',                   // 设置业务类型为通话
					options: options,              // 传递通话数据
					routeType: 'redirectTo'        // 使用redirectTo方式跳转
				});
				this._voipEndPathSet = true;  // 记录已设置状态
			}
		},
		registerVoipEvent() {
			wmpfVoip.onVoipEvent((event) => {
				const eventName = event.eventName;

				// 开始通话时清除无操作定时器
				if (eventName === 'startVoip') {
					clearTimeout(this.inactivityTimer);
				}

				// 定义不同类型的结束事件
				const hangupEvent = ['hangUpVoip', 'endVoip']; // 正常挂断
				const cancelEvent = ['cancelVoip']; // 主动取消
				const timeoutEvent = ['timeout']; // 超时未接听
				const rejectEvent = ['rejectVoip']; // 拒绝接听
				const callInfo = uni.getStorageSync('lastCallInfo') || {};

				// 处理正常通话结束
				if (hangupEvent.includes(eventName)) {
						callInfo.duration = event.data?.keepTime || 0;
						callInfo.status = callInfo.duration > 0 ? '通话已结束' : '未接通';

						// 如果有通话时长，标记需要记录到后端
						if (callInfo.duration > 0) {
								callInfo.needRecord = true;
								console.log('✅ 通话结束，时长:', callInfo.duration, '秒，类型:', callInfo.type);
						}
				}

				// 处理取消通话
				else if (cancelEvent.includes(eventName)) {
					callInfo.duration = 0;
					callInfo.status = '已取消';
				}

				// 处理超时未接听
				else if (timeoutEvent.includes(eventName)) {
					callInfo.duration = 0;
					callInfo.status = '未接听';
				}

				// 处理拒绝接听
				else if (rejectEvent.includes(eventName)) {
					callInfo.duration = 0;
					callInfo.status = '已拒绝';
				}

				// 如果是任何一种结束事件，保存信息并更新跳转页面
				if ([...hangupEvent, ...cancelEvent, ...timeoutEvent, ...rejectEvent].includes(eventName)) {
					callInfo.endType = eventName;
					callInfo.endTime = Date.now();
					uni.hideLoading();
					uni.setStorageSync('lastCallInfo', callInfo);
					this.setVoipEndPagePath(true);
					this.resetInactivityTimer();
				}
			})
		},

		async startAudioCall(contact) {
			await this.startCall(contact, 'voice')
		},
		async startVideoCall(contact) {
			await this.startCall(contact, 'video')
		},

			// 杀后台方法 by xu 2025-12-29
			async killBackgroundApp() {
				try {
					try {
						await deviceApi.ssExit()
						console.log('✅ 设备退出服务调用成功')
					} catch (exitError) {
						console.warn('⚠️ 设备退出服务调用失败:', exitError)
					}

					// 🧹 清理登录信息
					uni.removeStorageSync('userInfo')
				uni.removeStorageSync('JSESSIONID')

				// 🧹 清理通话相关缓存
				uni.removeStorageSync('currcall')
				uni.removeStorageSync('lastCallInfo')

				// 提示退出成功 by xu 2025-12-29
				uni.showToast({
					title: '已退出',
					icon: 'success',
					duration: 1500
				});

				// 延迟跳转到通知页 by xu 2025-12-29
				setTimeout(() => {
					uni.redirectTo({
						url: '/pages/device/notice'
					});
				}, 1500);
			} catch (error) {
				console.error('❌ 退出失败：', error);
				uni.showToast({
					title: '退出失败',
					icon: 'error'
				});
			}
		},
		// 重置无操作计时器
		resetInactivityTimer() {
			if (this.inactivityTimer) {
				clearTimeout(this.inactivityTimer);
			}
			this.inactivityTimer = setTimeout(() => {
				this.killBackgroundApp();
			}, this.inactivityTimeout);
		},

		// 监听用户活动的方法
		handleUserActivity() {
			this.resetInactivityTimer();
		},
			selectContact(contact) {
				this.currentContact = contact
				const idx = this.contacts.findIndex((item) => item.id === contact.id)
				if (idx > -1) {
					this.$set(this.contacts[idx], 'hasPoints', false)
				}
			},
			handleDeviceMessageRefresh() {
				if (!this.contacts || !this.contacts.length) return
				this.contacts = this.contacts.map((item) => ({
					...item,
					hasPoints: true
				}))
			},
		async getContactList() {
			try {
				const result = await deviceApi.mp_telHomep_load()
				const data = result && result.data ? result.data : {}
				const chatMbrList = Array.isArray(data.chatMbrList) ? data.chatMbrList : []
				const flatChatMbrList = chatMbrList.flatMap((item) => (Array.isArray(item) ? item : [item])).filter(Boolean)

				if (flatChatMbrList.length) {
					const defaultAvatar = 'https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132'
					this.contacts = flatChatMbrList.map((item) => ({
						id: item.ryid,
						username: item.xm || '未命名联系人',
						avatar: item.yszwj ? getImageUrl(item.yszwj) : defaultAvatar,
						openid: item.wbid2 || item.wbid || '',
						hasPoints: false
					}))
					console.log('✅ 获取留言联系人成功:', flatChatMbrList)
					return
				}

				// 兼容旧返回（后端未切换时）
				if (data && data.ssData) {
					const parent = data.ssData
					const defaultAvatar = 'https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132'
					const avatar = parent.yszwj ? getImageUrl(parent.yszwj) : defaultAvatar
					this.contacts = [{
						id: parent.ryid,
						username: parent.xm,
						avatar,
						openid: parent.wbid,
						hasPoints: false
					}]
					console.log('✅ 获取联系人成功(兼容旧返回):', parent)
				}
			} catch (error) {
				console.error('❌ 获取联系人失败:', error)
			}
		},
		goToMessage(contact) {
			const contactId = contact && contact.id ? contact.id : ''
			const contactName = contact && contact.username ? contact.username : ''
			uni.navigateTo({
				url: '/pages/parent/message?contactId=' + encodeURIComponent(contactId) + "&contactName=" + encodeURIComponent(contactName) + "&role=device&fromIndex=1"
			})
		},

		// 检查个人服务状态
		async checkServiceStatus(grfwxmm = 115) {
			try {
				const result = await deviceApi.grfw_chkGrfw(grfwxmm)
				console.log('检查服务状态返回：', result)

				if (result && result.data) {
					const data = result.data
					if (data.ssCode === 0 && data.ssData) {
						// 成功获取服务状态
						this.serviceStatus = data.ssData
						console.log('✅ 服务状态：', this.serviceStatus)
					} else if (data.ssCode > 0) {
						// 服务异常
						console.warn('⚠️ 服务状态异常：', data.ssMsg)
						this.serviceStatus = null
					}
				}
			} catch (error) {
				console.error('❌ 检查服务状态失败：', error)
				this.serviceStatus = null
			}
		},

		// 记录通话并刷新服务状态
		async recordCallAndRefresh(callOptions) {
			try {
				const duration = parseInt(callOptions.duration) || 0 // 秒
				const callType = callOptions.callType || 'voice'

				if (duration <= 0) {
					console.log('⚠️ 通话时长为0，不记录')
					await this.loadPageAfterCall()
					return
				}

				// 转换为分钟，不满1分钟按1分钟算（向上取整）
				const minutes = Math.ceil(duration / 60)
				console.log(`📊 通话时长: ${duration}秒 → ${minutes}分钟（向上取整）`)

				// 根据通话类型确定服务项目码
				const grfwxmm = callType === 'video' ? 115 : 111 // 115=视频电话, 111=音频电话

				// 调用接口记录通话
				console.log(`📝 记录通话: grfwxmm=${grfwxmm}, 时长=${minutes}分钟`)
				await deviceApi.grfw_endGrfw({
					grfwxmm: grfwxmm,
					sc: minutes,  // 时长（分钟）
					ll: 0,        // 流量
					ms: `通话${duration}秒` // 备注
				})

				console.log('✅ 通话记录成功')

				// 重新加载服务状态
				await this.checkServiceStatus(grfwxmm)

				// 清理通话记录标记
				const callInfo = uni.getStorageSync('lastCallInfo') || {}
				delete callInfo.needRecord
				uni.setStorageSync('lastCallInfo', callInfo)

			} catch (error) {
				console.error('❌ 记录通话失败:', error)
				uni.showToast({
					title: '记录通话失败',
					icon: 'none'
				})
			} finally {
				await this.loadPageAfterCall()
			}
		},

		// 通话结束后加载页面内容
		async loadPageAfterCall() {
			const userInfo = uni.getStorageSync('userInfo')
			if (userInfo) {
				if (userInfo.xm) {
					this.studentName = userInfo.xm
				}
				if (userInfo.yszwj) {
					this.studentAvatar = getImageUrl(userInfo.yszwj)
				}
				this.sn = userInfo.devId
			}

			await this.getContactList()
			this.registerVoipEvent()
			this.setVoipEndPagePath()
			this.resetInactivityTimer()

			const pages = getCurrentPages();
			const currentPage = pages[pages.length - 1];
			if (currentPage.$getAppWebview) {
				const webview = currentPage.$getAppWebview();
				webview.addEventListener('click', () => {
					this.handleUserActivity();
				});
			}
		},
	}
}
</script>

<style scoped>

.heng .split-layout {
	display: flex;
	height: 100vh;
}

.heng .left-panel {
	width: 50%;
	border-right: 2rpx solid #dcdcdc;
	background: #f5f5f5;
	overflow-y: auto;
}

.heng .right-panel {
	flex: 1;
	background: #fff;
	height: 100%;
	overflow-y: auto;
}

.heng .empty-message {
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	color: #999;
	font-size: 32rpx;
}



.heng .header {
	display: flex;
	align-items: center;
	padding: 16rpx 20rpx 10rpx;
	/* height: 200rpx; */
	border-bottom: 1rpx solid #d2d2d2;
	background: #f5f5f5;
	box-sizing: border-box;
	justify-content: space-between;
}

.heng .avatar {
	width: 42rpx;
	height: 42rpx;
	border-radius: 50%;
	margin-right: 8rpx;
}

.heng .header-left {
	display: flex;
	align-items: center;
}

.heng .logout-btn image {
	width: 20rpx;
	height: 20rpx;
}
.heng .greeting {
	font-size: 14rpx;
	color: #333;
}

.heng .contact-list {
	margin-top: 20rpx;
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 15rpx;
	padding: 0 12rpx;
}

.heng .contact-card {
	width: calc(100% - 20rpx);
	/* margin: 16rpx 20rpx; */
	padding: 8rpx;
	background-color: #fff;
	border-radius: 3rpx;
	display: flex;
	align-items: center;
	background: #f5f5f5;
	border: 1px solid #dddfe6;
	justify-content: space-between;
	position: relative;
	/* 添加相对定位 */

}

.heng .contact-card.active::after {
	content: '';
	position: absolute;
	right: -13rpx;
	top: 50%;
	transform: translateY(-50%);
	width: 0;
	height: 0;
	border-top: 8rpx solid transparent;
	border-bottom: 8rpx solid transparent;
	border-left: 8rpx solid #d2d2d2;
}

.heng .contact-info {
	display: flex;
	align-items: center;
}

.heng .contact-avatar {
	width: 52rpx;
	height: 52rpx;
	border: 1px solid #fff;
	margin-right: 8rpx;
	border-radius: 0rpx;
}

.heng .contact-name {
	font-size: 16rpx;
	color: #333;
}

.heng .action-buttons {
	display: flex;
	justify-content: space-around;
	gap: 12rpx;
	margin-right: 8rpx;
}

.heng .action-btn {
	display: flex;
	flex-direction: column;
	align-items: center;

}

.heng .action-btn-icon {
	width: 32rpx;
	height: 32rpx;
	margin-bottom: 2rpx;
	display: flex;
	align-items: center;

	justify-content: center;
	background: #ffffff;
	border: 1px solid #dddfe6;
	box-sizing: border-box;
	border-radius: 3rpx;
}

.heng .action-btn image {
	width: 60%;
	height: 60%;
}

.heng .action-btn text {
	font-size: 10rpx;
	color: #000000;
}

.heng .message-point {
	position: relative;
}

.heng .message-point::after {
	content: '';
	position: absolute;
	width: 8rpx;
	height: 8rpx;
	background-color: #eb6100;
	border-radius: 50%;

	top: -4rpx;
	right: -4rpx;
}



.shu .header {
	display: flex;
	align-items: center;
	padding: 40rpx 50rpx 25rpx;
	height: 200rpx;
	border-bottom: 2rpx solid #d2d2d2;
	background: #f5f5f5;
	box-sizing: border-box;
	justify-content: space-between;
}

.shu .avatar {
	width: 108rpx;
	height: 108rpx;
	border-radius: 50%;
	margin-right: 20rpx;
}

.shu .header-left {
	display: flex;
	align-items: center;
}

.shu .logout-btn image {
	width: 40rpx;
	height: 40rpx;
}

.shu .greeting {
	font-size: 38rpx;
	color: #333;
}

.shu .contact-list {
	margin-top: 30rpx;
}

.shu .contact-card {
	margin: 40rpx 50rpx;
	padding: 20rpx;
	background-color: #fff;
	border-radius: 8rpx;
	display: flex;
	align-items: center;
	background: #f5f5f5;
	border: 1px solid #dddfe6;
	justify-content: space-between;
}

.shu .contact-info {
	display: flex;
	align-items: center;
}

.shu .contact-avatar {
	width: 128rpx;
	height: 128rpx;
	border: 1px solid #fff;
	margin-right: 20rpx;
	border-radius: 0rpx;
}

.shu .contact-name {
	font-size: 32rpx;
	color: #333;
}

.shu .action-buttons {
	display: flex;
	justify-content: space-around;
	gap: 30rpx;
	/* margin-right: 20rpx; */
}

.shu .action-btn {
	display: flex;
	flex-direction: column;
	align-items: center;

}

.shu .action-btn-icon {
	width: 80rpx;
	height: 80rpx;
	margin-bottom: 5rpx;
	display: flex;
	align-items: center;

	justify-content: center;
	background: #ffffff;
	border: 1px solid #dddfe6;
	box-sizing: border-box;
	border-radius: 10rpx;
}

.shu .action-btn image {
	width: 60%;
	height: 60%;
}

.shu .action-btn text {
	font-size: 24rpx;
	color: #000000;
}

.shu .message-point {
	position: relative;
}

.shu .message-point::after {
	content: '';
	position: absolute;
	width: 18rpx;
	height: 18rpx;
	background-color: #eb6100;
	border-radius: 50%;

	top: -9rpx;
	right: -9rpx;
}

.debug-info {
	padding: 20rpx;
	background: #fff3cd;
	margin: 20rpx;
	border-radius: 8rpx;
	word-break: break-all;
}

.debug-info text {
	font-size: 24rpx;
	color: #856404;
}

/* 横屏服务状态样式 */
.heng .service-status {
	margin: 12rpx;
	padding: 10rpx 12rpx;
	background: #fff;
	border-radius: 6rpx;
	border: 1px solid #dddfe6;
}

.heng .service-status-header {
	margin-bottom: 8rpx;
}

.heng .service-status-title {
	font-size: 12rpx;
	color: #666;
	font-weight: bold;
}

.heng .service-status-content {
	display: flex;
	flex-wrap: wrap;
	gap: 8rpx;
}

.heng .status-item {
	display: flex;
	align-items: center;
	gap: 4rpx;
	padding: 4rpx 8rpx;
	background: #f0f9ff;
	border-radius: 4rpx;
}

.heng .status-label {
	font-size: 10rpx;
	color: #666;
}

.heng .status-value {
	font-size: 10rpx;
	color: #07c160;
	font-weight: bold;
}

/* 竖屏服务状态样式 */
.shu .service-status {
	margin: 30rpx 50rpx;
	padding: 24rpx;
	background: #fff;
	border-radius: 12rpx;
	border: 1px solid #dddfe6;
}

.shu .service-status-header {
	margin-bottom: 16rpx;
}

.shu .service-status-title {
	font-size: 28rpx;
	color: #666;
	font-weight: bold;
}

.shu .service-status-content {
	display: flex;
	flex-wrap: wrap;
	gap: 20rpx;
}

.shu .status-item {
	display: flex;
	align-items: center;
	gap: 10rpx;
	padding: 12rpx 20rpx;
	background: #f0f9ff;
	border-radius: 8rpx;
}

.shu .status-label {
	font-size: 26rpx;
	color: #666;
}

.shu .status-value {
	font-size: 26rpx;
	color: #07c160;
	font-weight: bold;
}
</style>
