<template>
	<view class="circle-progress" :style="{
      width: '5vw',
      height: '5vw',
    }">
		<view class="circle-bg" :style="{ borderColor: bgColor }"></view>
		<view class="circle-bar-wrapper">
			<view class="circle-bar" :style="{
          background: `conic-gradient(${color} ${animateProgress}%, transparent ${animateProgress}%)`,
          '--thickness': `${thickness}px`,
          '--half-thickness': `${thickness / 2}px`,
        }"></view>
		</view>

		<!-- 中间文字 -->
		<view class="circle-content" v-if="showText">
			<view class="progress-number">{{ Math.round(animateProgress) }}%</view>
			<view class="progress-label">进度</view>
		</view>
	</view>
</template>

<script setup lang="ts">
	import { computed, ref, onMounted, watch } from 'vue';
	interface ProgressProps {
		progress ?: number;
		color ?: string;
		bgColor ?: string;
		thickness ?: number;
		showText ?: boolean;
		duration ?: number;
	}

	const props = withDefaults(defineProps<ProgressProps>(), {
		progress: 0,
		color: '#409EFF',
		bgColor: '#E5E5E5',
		thickness: 1,
		showText: true,
		duration: 1.5,
	});
	const realProgress = computed(() => {
		const p = Number(props.progress);
		return isNaN(p) ? 0 : Math.max(0, Math.min(100, p));
	});
	const animateProgress = ref(0);
	const startProgressAnimation = () => {
		const target = realProgress.value;
		const duration = props.duration * 1000;
		const frameRate = 60;
		const totalFrames = duration / (1000 / frameRate);
		const increment = target / totalFrames;

		let currentFrame = 0;
		const timer = setInterval(() => {
			currentFrame++;
			animateProgress.value += increment;

			if (currentFrame >= totalFrames || animateProgress.value >= target) {
				animateProgress.value = target;
				clearInterval(timer);
			}
		}, 1000 / frameRate);
	};

	watch(realProgress, () => {
		animateProgress.value = 0;
		startProgressAnimation();
	}, { immediate: false });

	onMounted(() => {
		startProgressAnimation();
	});
</script>

<style scoped>
	.circle-progress {
		position: relative;
		flex-shrink: 0;
		aspect-ratio: 1/1;
		box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
		border-radius: 50%;
		background: #fff;
	}

	.circle-bg {
		width: 100%;
		height: 100%;
		border-radius: 50%;
		border: 3px solid #E8E9EA;
		box-sizing: border-box;
		opacity: 1;
		z-index: 2;
		position: relative;
	}

	.circle-bar-wrapper {
		position: absolute;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		border-radius: 50%;
		z-index: 3;
		overflow: hidden;
	}

	.circle-bar {
		position: absolute;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		border-radius: 50%;
		-webkit-mask: radial-gradient(transparent calc(50% - 3px),
				black calc(50% - 3px));
		mask: radial-gradient(transparent calc(50% - 3px),
				black calc(50% - 3px));

		&::after {
			content: '';
			position: absolute;
			top: 3px;
			left: 3px;
			right: 3px;
			bottom: 3px;
			border-radius: 50%;
			box-shadow: inset 0 0 0 13px rgba(255, 255, 255, 1);
		}

		clip-path: circle(50% at center);
	}

	.circle-content {
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		width: 80%;
		text-align: center;
		display: flex;
		flex-direction: column;
		justify-content: center;
		align-items: center;
		z-index: 3;
	}

	.progress-number {
		font-size: 1.2vw;
		font-weight: 600;
		color: #333;
		line-height: 1;
		margin-bottom: 0.2vw;
	}

	.progress-label {
		font-size: 1.1vw;
		color: #666;
		line-height: 1;
	}
</style>