| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- <template>
- <view class="points-ring-container">
- <view class="ring-wrapper">
- <svg class="progress-ring" viewBox="0 0 120 120">
- <!-- Background ring -->
- <circle
- class="progress-ring__background"
- cx="60"
- cy="60"
- r="54"
- fill="none"
- stroke="#f0f9ff"
- stroke-width="10"
- />
- <!-- Progress ring -->
- <circle
- class="progress-ring__progress"
- cx="60"
- cy="60"
- r="54"
- fill="none"
- :stroke="progressColor"
- stroke-width="10"
- stroke-linecap="round"
- :stroke-dasharray="circumference"
- :stroke-dashoffset="dashOffset"
- />
- </svg>
- <view class="ring-content">
- <text class="points-value">{{ points }}</text>
- <text class="points-label">积分</text>
- </view>
- </view>
- <view class="milestone-info" v-if="milestone">
- <text class="milestone-text">🎯 距离下一个奖励还差 {{ milestone.remaining }} 分</text>
- </view>
- </view>
- </template>
- <script>
- export default {
- name: 'PointsProgressRing',
- props: {
- points: { type: Number, default: 0 },
- currentMilestone: { type: Number, default: 0 },
- nextMilestone: { type: Number, default: 100 }
- },
- computed: {
- circumference() {
- return 2 * Math.PI * 54
- },
- progress() {
- if (this.nextMilestone <= 0) return 0
- return Math.min(this.currentMilestone / this.nextMilestone, 1)
- },
- dashOffset() {
- return this.circumference * (1 - this.progress)
- },
- progressColor() {
- if (this.progress >= 0.75) return '#10B981' // green
- if (this.progress >= 0.5) return '#F59E0B' // yellow
- return '#0EA5E9' // blue
- },
- milestone() {
- if (this.nextMilestone > this.points) {
- return {
- remaining: this.nextMilestone - this.points,
- target: this.nextMilestone
- }
- }
- return null
- }
- }
- }
- </script>
- <style scoped>
- .points-ring-container {
- display: flex;
- flex-direction: column;
- align-items: center;
- }
- .ring-wrapper {
- position: relative;
- width: 120px;
- height: 120px;
- }
- .progress-ring {
- width: 100%;
- height: 100%;
- transform: rotate(-90deg);
- }
- .progress-ring__progress {
- transition: stroke-dashoffset 0.5s ease;
- }
- .ring-content {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- text-align: center;
- }
- .points-value {
- display: block;
- font-size: 28px;
- font-weight: 800;
- color: #0EA5E9;
- }
- .points-label {
- display: block;
- font-size: 12px;
- color: #94A3B8;
- }
- .milestone-info {
- margin-top: 8px;
- padding: 6px 12px;
- background: linear-gradient(135deg, #FEF3C7, #FDE68A);
- border-radius: 20px;
- }
- .milestone-text {
- font-size: 12px;
- color: #92400E;
- }
- </style>
|