<template>
	<view class="swim-timer-container">
		<!-- 固定在顶部的计时栏 -->
		<view class="total-time-section">
			<view class="" style="position: relative;">
				<view class="total-time">{{ formatTime(currentTime) }}</view>
				<view class="" @click="Service.GoPage('/pages/userFunc/setCourse?type=1'+'&id='+planId)"
					style="position: absolute; top: 0; right: 20rpx; ">
					<up-icon name="setting" size="22"></up-icon>
				</view>
			</view>
			<!-- 计划信息 -->
			<view class="plan-info" v-if="planId">
				<text class="plan-title">{{ planName }} · {{ stopwatchMode=='interval'?'间隔触发':'一起出发' }} ·
					共{{ groupedAthletes.length }}组{{ athletes.length }}位选手</text>
			</view>
		</view>

		<!-- 选手列表 -->
		<view class="athletes-section">
			<view class="athletes-list">
				<view v-for="group in groupedAthletes" :key="group.groupNumber" class="group-wrapper">
					<view class="group-header">
						<view class="group-title">
							<u-icon name="grid" size="18" color="#1890ff"></u-icon>
							<text class="group-label">第{{ group.groupNumber }}组</text>
						</view>
						<text class="group-count">{{ group.athletes.length }}人</text>
					</view>

					<view class="group-athletes">
						<view v-for="(athlete, indexInGroup) in group.athletes" :key="athlete.id"
							@click="handleAthleteFirstButton(athlete, athletes.indexOf(athlete))" class="athlete-item"
							:class="{ finished: athlete.finished }">
							<view class="athlete-number">{{ athletes.indexOf(athlete) + 1 }}</view>
							<view class="athlete-info">
								<text class="athlete-name">{{ athlete.name }}</text>
							</view>
							<view class="time-wrapper">
								<text
									class="athlete-time">{{ !athlete.time? ' 00′00″00 ':formatTime(athlete.time) }}</text>
								<text class="best-time">PB:
									{{ athlete.studentQuicklyTime !== null ? athlete.studentQuicklyTime: '无' }}</text>
							</view>
							<view class="" style="display: flex;align-items: center; gap: 10rpx;">

								<view @click.stop="resetAthleteTime(athlete)">
									<u-icon name="reload" :bold="true" size="24" color="#1890ff"></u-icon>
								</view>
							</view>
						</view>
					</view>
				</view>
			</view>
		</view>
		<view class="" style="width: 100%; height: 100rpx;"></view>

		<!-- 右下角悬浮提交按钮 -->
		<!-- 	<view class="fab-submit" @click="submitData">
			<text class="fab-text">提交</text>
		</view> -->

		<!-- 记录提示弹窗 -->
		<u-popup :show="showRecord" mode="center" :round="20" :closeable="true" :safeAreaInsetBottom='false'
			@close="showRecord=false" closeOnClickOverlay>
			<view class="record-notice-modal">
				<view class="notice-header">
					<text class="notice-title">恭喜以下学生打破记录</text>
				</view>
				<view class="notice-table">
					<view class="table-header">
						<text class="header-cell index-cell">序号</text>
						<text class="header-cell name-cell">学生姓名</text>
						<text class="header-cell time-cell">记录时间</text>
					</view>
					<scroll-view scroll-y class="table-body">
						<view v-for="(item,index) in record" class="table-row">
							<text class="row-cell index-cell">{{ index+1 }}</text>
							<text class="row-cell name-cell">{{ item.name }}</text>
							<text class="row-cell time-cell">{{ item.studentQuicklyTime }}</text>
						</view>
					</scroll-view>
				</view>
			</view>
		</u-popup>

		<!-- 可拖动悬浮球 -->
		<view class="float-ball"  @click="ballClick(isRunning)" :style="ballStyle" @touchstart="touchStart" @touchmove="touchMove"
			@touchend="touchEnd">
			<view class="ball-shine"></view>
			<!-- @click="startTimer" @click="recordNextAthlete" -->
			<view v-if="!isRunning"  class="ball-text">开始</view>
			<view v-if="isRunning"  class="ball-text">记录</view>
		</view>

		<!-- 底部控制按钮 -->
		<view class="control-buttons">
			<button class="ctrl-btn btn-submit" @click="submitData">
				<u-icon name="checkmark-circle" size="24" color="#fff"></u-icon>
				<text class="btn-text">提交</text>
			</button>
			<button class="ctrl-btn btn-data" @click="Service.GoPage('/pages/dataAnalyze/timingAnalze')">
				<u-icon name="list-dot" size="24" color="#fff"></u-icon>
				<text class="btn-text">数据</text>
			</button>
			<button v-if="!isRunning" class="ctrl-btn btn-reset" @click="resetAll">
				<u-icon name="reload" size="24" color="#fff"></u-icon>
				<text class="btn-text">重置</text>
			</button>
			<button v-if="isRunning" class="ctrl-btn btn-pause" @click="stopTimer">
				<text class="btn-text">暂停</text>
			</button>
		</view>


	</view>
</template>

<script setup lang="ts">
	import { ref, onUnmounted, computed, onMounted } from 'vue'
	import { Service } from '@/Service/Service'
	import { PlanService } from '@/Service/swimming/PlanService'
	import { onLoad, onShow } from '@dcloudio/uni-app'

	// 定义选手类型
	interface Athlete {
		id : string
		number : string
		name : string
		gender : string
		age : string
		birthday : string
		time : number
		bestTime : number | null
		finished : boolean
		startOffset ?: number
	}

	// 定义分组类型
	interface Group {
		groupNumber : number
		athletes : Athlete[]
	}

	// 计划ID
	const planId = ref('')
	// 项目名称
	let planName = ref('')

	// 选手列表
	const athletes = ref<Array<any>>([])

	// 分组设置
	const groupSize = ref('0')


	// 创建播放器
	const video = uni.createInnerAudioContext()

	// 计时器状态
	const isRunning = ref(false)
	const currentTime = ref(0)
	let timerInterval : number | null = null
	let startTime : number = 0

	// 当前要记录的选手索引
	const currentAthleteIndex = ref(0)

	// 秒表模式
	const stopwatchMode = ref<'interval' | 'together'>('interval')
	// 间隔时间（秒）
	const intervalTime = ref('0')
	let record = ref<Array<any>>([])
	let showRecord = ref(false)

	// 已提示过出发的组号集合（间隔模式用）
	const notifiedGroupNumbers = ref<Set<number>>(new Set())

	// 可拖动悬浮球
	const FLOAT_BALL_KEY = 'swiming_float_ball_position'
	const ballPosition = ref({ x: 20, y: 300 })
	const startPosition = ref({ x: 0, y: 0 })
	const touchStartPoint = ref({ x: 0, y: 0 })
	const ballSize = ref({ w: 50, h: 50 })

	const ballStyle = computed(() => {
		return `left:${ballPosition.value.x}px;top:${ballPosition.value.y}px;`
	})

	onLoad((data : any) => {
		planId.value = data.id

		const sys = uni.getSystemInfoSync()
		ballSize.value.w = sys.windowWidth * 50 / 375
		ballSize.value.h = ballSize.value.w
		ballPosition.value = {
			x: 20,
			y: sys.windowHeight - ballSize.value.h - 200
		}

		const saved = uni.getStorageSync(FLOAT_BALL_KEY)
		if (saved) {
			try {
				const pos = JSON.parse(saved)
				if (typeof pos.x === 'number' && typeof pos.y === 'number') {
					ballPosition.value = {
						x: Math.max(0, Math.min(pos.x, sys.windowWidth - ballSize.value.w)),
						y: Math.max(0, Math.min(pos.y, sys.windowHeight - ballSize.value.h))
					}
				}
			} catch (e) { }
		}
	})

	onShow(() => {
		getPlanInfo()
	})

	// 获取计划详情
	const getPlanInfo = () => {
		PlanService.GetPlanInfo(planId.value).then(res => {
			if (res.code == 0) {
				planName.value = res.data.plan.name
				// 将计划数据转换为选手数据
				athletes.value = res.data.plan.users
				groupSize.value = res.data.plan.groupInt
				stopwatchMode.value = res.data.plan.departType == '间隔出发' ? 'interval' : 'together'
				intervalTime.value = res.data.plan.interval
			} else {
				Service.Msg(res.msg)
			}
		})
	}
	
	// 悬浮球事件
	const ballClick=( data:any)=>{
		if(data){
			recordNextAthlete()
		}else{
			startTimer()
		}
	}
	
	// 播报
	const speak=()=>{
		video.src='/static/icon/video.mp3'
		video.play()
	}
	
	// 计算分组
	const groupedAthletes = computed<Group[]>(() => {
		const size = parseInt(groupSize.value) || 2
		const groups : Group[] = []
		let currentGroup : Group | null = null

		athletes.value.forEach((athlete, index) => {
			if (index % size === 0) {
				currentGroup = {
					groupNumber: groups.length + 1,
					athletes: []
				}
				groups.push(currentGroup)
			}
			if (currentGroup) {
				currentGroup.athletes.push(athlete)
			}
		})

		return groups
	})

	// 计算选手的时间偏移量
	const getAthleteOffset = (athlete : any) : number => {
		if (stopwatchMode.value !== 'interval') {
			return 0
		}

		const index = athletes.value.findIndex(a => a.studentId === athlete.studentId)
		const interval = parseFloat(intervalTime.value) || 10
		const size = parseInt(groupSize.value) || 2

		// 根据分组计算偏移：第n组偏移 (n-1) * interval
		const groupNumber = Math.floor(index / size)
		return groupNumber * interval
	}

	// 计算已完成的选手
	const finishedAthletes = computed(() => {
		return athletes.value.filter(a => a.finished)
	})

	// 格式化时间显示
	const formatTime = (seconds : number) : string => {
		const mins = Math.floor(seconds / 60)
		const secs = Math.floor(seconds % 60)
		const ms = Math.floor((seconds % 1) * 100)
		return `${mins.toString().padStart(2, '0')}′${secs.toString().padStart(2, '0')}″${ms.toString().padStart(2, '0')}`
	}

	// 开始计时
	const startTimer = () => {
		if (isRunning.value) return

		isRunning.value = true
		notifiedGroupNumbers.value.clear()
		startTime = Date.now() - currentTime.value * 1000

		timerInterval = setInterval(() => {
			const elapsed = (Date.now() - startTime) / 1000
			currentTime.value = elapsed

			// 间隔模式下，检查是否有新组到达出发时间
			if (stopwatchMode.value === 'interval') {
				const interval = parseFloat(intervalTime.value) || 10
				groupedAthletes.value.forEach(group => {
					const groupOffset = (group.groupNumber - 1) * interval
					if (elapsed >= groupOffset && !notifiedGroupNumbers.value.has(group.groupNumber)) {
						notifiedGroupNumbers.value.add(group.groupNumber)
						// Service.Msg(`第${group.groupNumber}组出发了`)
						speak()
					}
				})
			}

			// 更新未完成选手的时间（考虑偏移量）
			athletes.value.forEach(athlete => {
				if (!athlete.finished) {
					const offset = getAthleteOffset(athlete)
					athlete.time = Math.max(0, elapsed - offset)
				}
			})
		}, 30)
	}

	// 停止计时
	const stopTimer = () => {
		if (!isRunning.value) return

		isRunning.value = false
		if (timerInterval) {
			clearInterval(timerInterval)
			timerInterval = null
		}
	}

	// 记录下一个选手
	const recordNextAthlete = () => {
		// 查找下一个未完成的选手
		while (currentAthleteIndex.value < athletes.value.length) {
			const athlete = athletes.value[currentAthleteIndex.value]
			if (athlete.finished) {
				// 已手动计时的学生，跳过
				currentAthleteIndex.value++
			} else {
				break
			}
		}

		if (currentAthleteIndex.value >= athletes.value.length) {
			stopTimer()
			Service.Msg('所有选手已完成')
			return
		}

		const athlete = athletes.value[currentAthleteIndex.value]
		const offset = getAthleteOffset(athlete)
		athlete.finished = true
		athlete.time = Math.max(0, currentTime.value - offset)
		athlete.startOffset = offset

		currentAthleteIndex.value++

		// 如果所有选手都完成了，停止计时
		if (currentAthleteIndex.value >= athletes.value.length) {
			stopTimer()
			Service.Msg('所有选手已完成！')
		}
	}

	// 重置选手时间
	const resetAthleteTime = (athlete : Athlete) => {
		athlete.time = 0
		athlete.finished = false
		athlete.startOffset = undefined

		// 重新排序索引
		reorderAthletes()
	}

	// 处理选手第一个按钮点击
	const handleAthleteFirstButton = (athlete : Athlete, index : number) => {
		// 如果是一起出发模式，记录该选手时间
		if (athlete.finished) {
			Service.Msg('该选手已记录')
			return
		}

		const offset = getAthleteOffset(athlete)
		athlete.finished = true
		athlete.time = Math.max(0, currentTime.value - offset)
		athlete.startOffset = offset

		// 检查是否所有选手都完成了
		const allFinished = athletes.value.every(a => a.finished)
		if (allFinished) {
			stopTimer()
			Service.Msg('所有选手已完成！')
		} else {
			Service.Msg(`${athlete.name} 已记录`)
		}
	}

	// 重新排序选手索引
	const reorderAthletes = () => {
		const unfinished = athletes.value.filter(a => !a.finished)
		currentAthleteIndex.value = athletes.value.length - unfinished.length
	}

	// 记录所有未完成选手
	const recordAll = () => {
		let recordedCount = 0
		athletes.value.forEach(athlete => {
			if (!athlete.finished) {
				athlete.finished = true
				athlete.time = currentTime.value
				recordedCount++
			}
		})

		if (recordedCount > 0) {
			Service.Msg(`已记录${recordedCount}位选手`, 'success')
		} else {
			Service.Msg('没有需要记录的选手')
		}
	}

	// 重置所有
	const resetAll = () => {
		Service.Confirm('确定要重置所有计时吗？', () => {
			stopTimer()
			currentTime.value = 0
			currentAthleteIndex.value = 0
			notifiedGroupNumbers.value.clear()

			athletes.value.forEach(athlete => {
				athlete.time = 0
				athlete.finished = false
				athlete.startOffset = undefined
			})
		})
	}
	// 处理数据
	const formatMinuteTime = (seconds : number) : string => {
		const mins = Math.floor(seconds / 60)
		const secs = Math.floor(seconds % 60)
		const ms = Math.floor((seconds % 1) * 1000)
		return `${mins.toString().padStart(2, '0')}′${secs.toString().padStart(2, '0')}″${ms.toString().padStart(3, '0')}`
	}

	// 提交数据
	const submitData = () => {

		const hasData = athletes.value.some(a => a.time > 0)
		const allFinished = athletes.value.every(a => a.finished)
		if (!hasData) {
			Service.Msg('暂无数据可提交')
			return
		}
		stopTimer()
		let data = [{
			planName: "",
			studentId: "",
			studentName: "",
			time: ""
		}]
		data = []
		athletes.value.map((item : any) => {
			data.push({
				planName: planName.value,
				studentId: item.studentId,
				studentName: item.name,
				time: item.time
			})
		})
		uni.showModal({
			title: '提示', // 对话框标题
			content: '请确定提交数据!', // 显示的内容
			showCancel: true, // 是否显示取消按钮
			cancelText: '取消', // 取消按钮的文字
			confirmText: '确定', // 确认按钮的文字
			success: function (res) {
				if (res.confirm) {
					PlanService.AddPlanLog(planId.value, '计时项目', JSON.stringify(data), '', '', '').then(res => {
						if (res.code == 0) {
							Service.Msg('提交成功!')
							stopTimer()
							currentTime.value = 0
							currentAthleteIndex.value = 0

							athletes.value.forEach(athlete => {
								athlete.time = 0
								athlete.finished = false
								athlete.startOffset = undefined
							})

							if (res.data.record.length > 0) {
								record.value = res.data.record
								showRecord.value = true
							}
						} else {
							Service.Msg(res.msg)
						}
					})
				} else if (res.cancel) {
					console.log('用户点击取消');
				}
			}
		});


	}


	// 悬浮球拖动事件
	const touchStart = (e : any) => {
		const touch = e.touches[0]
		touchStartPoint.value = { x: touch.clientX, y: touch.clientY }
		startPosition.value = { ...ballPosition.value }
	}

	const touchMove = (e : any) => {
		const touch = e.touches[0]
		const deltaX = touch.clientX - touchStartPoint.value.x
		const deltaY = touch.clientY - touchStartPoint.value.y
		ballPosition.value = {
			x: startPosition.value.x + deltaX,
			y: startPosition.value.y + deltaY
		}
	}

	const touchEnd = () => {
		const sys = uni.getSystemInfoSync()
		ballPosition.value = {
			x: Math.max(0, Math.min(ballPosition.value.x, sys.windowWidth - ballSize.value.w)),
			y: Math.max(0, Math.min(ballPosition.value.y, sys.windowHeight - ballSize.value.h))
		}
		uni.setStorageSync(FLOAT_BALL_KEY, JSON.stringify(ballPosition.value))
	}

	// 页面卸载时清理计时器
	onUnmounted(() => {
		if (timerInterval) {
			clearInterval(timerInterval)
		}
	})
</script>

<style lang="scss" scoped>
	.swim-timer-container {
		min-height: 100vh;
		background-color: #f6f6f6;
		padding: 20rpx 20rpx;
		padding-top: 180rpx;
	}

	/* 总用时区域 - 固定在顶部 */
	.total-time-section {
		position: fixed;
		top: 0rpx;
		left: 0;
		right: 0;
		text-align: center;
		padding: 40rpx 20rpx;
		background-color: #f6f6f6;

		z-index: 100;
		box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);

		.total-time {
			font-size: 80rpx;
			font-weight: bold;
			color: #ff0000;
			font-family: 'DIN Alternate', monospace;
			min-width: 400rpx;
			display: inline-block;
			text-align: center;
		}

		.plan-info {
			margin-top: 20rpx;
			padding: 0 20rpx;

			.plan-title {
				font-size: 24rpx;
				color: #666;
				background-color: rgba(255, 255, 255, 0.8);
				padding: 8rpx 16rpx;
				border-radius: 16rpx;
				display: inline-block;
			}
		}
	}

	/* 选手列表区域 */
	.athletes-section {
		margin-top: 80rpx;
		margin-bottom: 120rpx;

		.section-header {
			display: flex;
			justify-content: space-between;
			align-items: center;
			margin-bottom: 20rpx;

			.section-title {
				font-size: 32rpx;
				font-weight: 600;
				color: #333333;
			}

			.athlete-count {
				font-size: 24rpx;
				color: #999999;
				background-color: #f5f5f5;
				padding: 6rpx 16rpx;
				border-radius: 16rpx;
			}
		}

		.athletes-list {
			.group-wrapper {
				margin-bottom: 24rpx;
				background-color: #ffffff;
				border-radius: 20rpx;
				box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
				overflow: hidden;

				.group-header {
					display: flex;
					justify-content: space-between;
					align-items: center;
					padding: 10rpx 28rpx;
					background: linear-gradient(135deg, #e6f7ff 0%, #f0f9ff 100%);
					border-left: 6rpx solid #1890ff;

					.group-title {
						display: flex;
						align-items: center;
						gap: 12rpx;

						.group-label {
							font-size: 30rpx;
							font-weight: 600;
							color: #1890ff;
						}
					}

					.group-count {
						font-size: 24rpx;
						color: #666;
						background-color: rgba(255, 255, 255, 0.8);
						padding: 6rpx 16rpx;
						border-radius: 16rpx;
					}
				}

				.group-athletes {
					padding: 8rpx 16rpx 16rpx 16rpx;
				}
			}

			.athlete-item {
				display: flex;
				align-items: center;
				padding: 14rpx 24rpx;
				background-color: #ffffff;
				border-radius: 16rpx;
				box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.03);
				transition: background-color 0.3s, border-color 0.3s;
				border: 2rpx solid transparent;

				&.finished {
					background-color: #f6ffed;
					border: 2rpx solid #b7eb8f;
				}

				&.fastest {
					background-color: #fff7e6;
					border: 2rpx solid #ffd591;
				}

				.athlete-number {
					width: 56rpx;
					height: 56rpx;
					background-color: #e6f7ff;
					color: #1890ff;
					font-size: 28rpx;
					font-weight: 600;
					border-radius: 8rpx;
					display: flex;
					align-items: center;
					justify-content: center;
					margin-right: 20rpx;
				}

				.athlete-info {
					flex: 1;
					margin-right: 30rpx;
					position: relative;

					.athlete-name {
						font-size: 30rpx;
						font-weight: 500;
						color: #333333;
						margin-bottom: 6rpx;
						display: block;
					}

					.athlete-meta {
						display: flex;
						flex-direction: column;
						gap: 4rpx;
					}

					.athlete-lane {
						font-size: 24rpx;
						color: #999999;
					}

					.start-offset {
						font-size: 20rpx;
						color: #fa8c16;
						background-color: #fff7e6;
						padding: 2rpx 10rpx;
						border-radius: 8rpx;
						display: inline-flex;
						align-items: center;
						gap: 4rpx;
						width: fit-content;
					}

					.fastest-tag {
						position: absolute;
						top: 0;
						right: 0;
						font-size: 20rpx;
						color: #fa8c16;
						background-color: #fff7e6;
						padding: 2rpx 10rpx;
						border-radius: 8rpx;
					}
				}

				.time-wrapper {
					display: flex;
					flex-direction: column;
					align-items: flex-end;
					margin-right: 20rpx;
					min-width: 160rpx;

					.athlete-time {
						font-size: 32rpx;
						font-weight: bold;
						color: #ff0000;
						font-family: 'DIN Alternate', monospace;
					}

					.best-time {
						font-size: 20rpx;
						color: #999;
						margin-top: 4rpx;
					}
				}

				.reset-btn {
					width: 48rpx;
					height: 48rpx;
					background-color: #f5f5f5;
					border-radius: 50%;
					display: flex;
					align-items: center;
					justify-content: center;
				}
			}
		}
	}

	/* 右下角悬浮提交按钮 */
	.fab-submit {
		position: fixed;
		right: 30rpx;
		bottom: 180rpx;
		width: 120rpx;
		height: 120rpx;
		border-radius: 50%;
		background: linear-gradient(135deg, #fa8c16 0%, #ffa940 100%);
		display: flex;
		align-items: center;
		justify-content: center;
		box-shadow:
			0 8rpx 24rpx rgba(250, 140, 22, 0.5),
			0 16rpx 40rpx rgba(0, 0, 0, 0.2);
		z-index: 200;

		&:active {
			transform: scale(0.92);
		}

		.fab-text {
			font-size: 28rpx;
			color: #ffffff;
			font-weight: 600;
		}
	}

	/* 底部控制按钮 */
	.control-buttons {
		display: flex;
		gap: 20rpx;
		justify-content: space-between;
		position: fixed;
		bottom: 0;
		left: 0;
		right: 0;
		background: linear-gradient(180deg, rgba(255, 255, 255, 0.98) 0%, #ffffff 100%);
		padding: 24rpx 32rpx;
		padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
		border-top: 1rpx solid rgba(0, 0, 0, 0.06);
		box-shadow: 0 -8rpx 32rpx rgba(0, 0, 0, 0.08);

		.ctrl-btn {
			flex: 1;
			height: 92rpx;
			border-radius: 24rpx;
			border: none;
			font-size: 30rpx;
			font-weight: 600;
			display: flex;
			align-items: center;
			justify-content: center;
			gap: 10rpx;
			transition: all 0.25s ease;
			box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.12);

			&:active {
				transform: scale(0.96);
			}
		}

		.btn-submit {
			background: linear-gradient(135deg, #faad14 0%, #ffc53d 100%);
			color: #fff;
			box-shadow: 0 6rpx 18rpx rgba(250, 173, 20, 0.35);
		}

		.btn-data {
			background: linear-gradient(135deg, #1890ff 0%, #40a9ff 100%);
			color: #fff;
			box-shadow: 0 6rpx 18rpx rgba(24, 144, 255, 0.35);
		}

		.btn-reset {
			background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%);
			color: #fff;
			box-shadow: 0 6rpx 18rpx rgba(82, 196, 26, 0.35);
		}

		.btn-pause {
			background: linear-gradient(135deg, #fa541c 0%, #ff7a45 100%);
			color: #fff;
			box-shadow: 0 6rpx 18rpx rgba(250, 84, 28, 0.35);
		}

		.btn-text {
			font-size: 30rpx;
			color: #ffffff;
			font-weight: 600;
			letter-spacing: 2rpx;
		}
	}

	/* 可拖动悬浮球 */
	.float-ball {
		position: fixed;
		width: 170rpx;
		height: 170rpx;
		border-radius: 50%;
		background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%);
		display: flex;
		align-items: center;
		justify-content: center;
		box-shadow:
			0 8rpx 24rpx rgba(82, 196, 26, 0.45),
			0 16rpx 40rpx rgba(0, 0, 0, 0.15),
			inset 0 4rpx 10rpx rgba(255, 255, 255, 0.35);
		z-index: 999;
		touch-action: none;
		transition: transform 0.2s ease;

		&:active {
			transform: scale(0.92);
		}

		.ball-shine {
			position: absolute;
			top: 20rpx;
			left: 24rpx;
			width: 36rpx;
			height: 18rpx;
			background: rgba(255, 255, 255, 0.4);
			border-radius: 50%;
			filter: blur(2rpx);
			pointer-events: none;
		}

		.ball-text {
			color: #fff;
			font-size: 40rpx;
			font-weight: 700;
			letter-spacing: 2rpx;
			text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.15);
			position: relative;
			z-index: 1;
		}
	}

	/* 记录提示弹窗 */
	.record-notice-modal {
		width: 560rpx;
		padding: 30rpx 40rpx 48rpx;
		background-color: #ffffff;
		border-radius: 20rpx;
		text-align: center;

		.notice-header {
			display: flex;
			flex-direction: column;
			align-items: center;
			margin-bottom: 40rpx;

			.notice-title {
				font-size: 36rpx;
				font-weight: 600;
				color: #333333;
				margin-top: 16rpx;
			}
		}

		.notice-table {
			width: 100%;

			.table-header {
				display: flex;
				background-color: #f5f5f5;
				border-radius: 12rpx;
				padding: 20rpx 0;
				margin-bottom: 16rpx;

				.header-cell {
					font-size: 26rpx;
					font-weight: 600;
					color: #666666;
					text-align: center;
				}
			}

			.table-body {
				max-height: 360rpx;

				.table-row {
					display: flex;
					padding: 20rpx 0;
					border-bottom: 1rpx solid #f0f0f0;

					&:last-child {
						border-bottom: none;
					}

					.row-cell {
						font-size: 28rpx;
						color: #333333;
						text-align: center;
					}

					.time-cell {
						color: #ff0000;
						font-family: 'DIN Alternate', monospace;
						font-weight: 600;
					}
				}
			}

			.index-cell {
				width: 80rpx;
			}

			.name-cell {
				flex: 1;
			}

			.time-cell {
				width: 160rpx;
			}
		}
	}
</style>