WealthEnergyRing.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <template>
  2. <view class="wealth-ring">
  3. <view class="ring-wrap">
  4. <!-- SVG 环形进度 -->
  5. <svg class="ring-svg" viewBox="0 0 200 200">
  6. <!-- 背景轨道 -->
  7. <circle cx="100" cy="100" r="88" fill="none" stroke="#FEF3C7" stroke-width="14" />
  8. <!-- 进度弧线 -->
  9. <circle
  10. class="ring-progress"
  11. cx="100" cy="100" r="88" fill="none"
  12. stroke="url(#ringGradient)" stroke-width="14" stroke-linecap="round"
  13. :stroke-dasharray="circumference" :stroke-dashoffset="progressOffset" />
  14. <defs>
  15. <linearGradient id="ringGradient" x1="0%" y1="0%" x2="100%" y2="0%">
  16. <stop offset="0%" stop-color="#F59E0B" />
  17. <stop offset="100%" stop-color="#FBBF24" />
  18. </linearGradient>
  19. </defs>
  20. </svg>
  21. <!-- 中心文字 -->
  22. <view class="ring-center">
  23. <text class="ring-score">{{ score }}</text>
  24. <text class="ring-total">/ 100</text>
  25. <text class="ring-level">{{ levelText }}</text>
  26. </view>
  27. <!-- 水波纹 -->
  28. <view class="ripple-1"></view>
  29. <view class="ripple-2"></view>
  30. </view>
  31. <view class="ring-slogan">
  32. <text class="ring-slogan-text">富足源于利他与坚持</text>
  33. <text class="ring-delta" v-if="delta > 0">较上月 ↑ {{ delta }}%</text>
  34. </view>
  35. </view>
  36. </template>
  37. <script>
  38. export default {
  39. name: 'WealthEnergyRing',
  40. props: {
  41. score: {
  42. type: Number,
  43. default: 0
  44. },
  45. delta: {
  46. type: Number,
  47. default: 0
  48. }
  49. },
  50. computed: {
  51. circumference() {
  52. // 2 * Math.PI * 88 ≈ 552.92
  53. return 552.92
  54. },
  55. progressOffset() {
  56. var pct = Math.max(0, Math.min(100, this.score)) / 100
  57. return Math.round(552.92 * (1 - pct))
  58. },
  59. levelText() {
  60. var s = this.score
  61. if (s >= 70) return '富足'
  62. if (s >= 30) return '成长'
  63. return '播种'
  64. }
  65. }
  66. }
  67. </script>
  68. <style scoped>
  69. .wealth-ring {
  70. margin: 20rpx 30rpx;
  71. background: linear-gradient(135deg, #FFF7ED 0%, #FEF3C7 100%);
  72. border-radius: 24rpx;
  73. padding: 40rpx 30rpx 30rpx;
  74. display: flex;
  75. flex-direction: column;
  76. align-items: center;
  77. box-shadow: 0 4rpx 16rpx rgba(245, 158, 11, 0.12);
  78. }
  79. .ring-wrap {
  80. position: relative;
  81. width: 360rpx;
  82. height: 360rpx;
  83. }
  84. .ring-svg {
  85. width: 360rpx;
  86. height: 360rpx;
  87. transform: rotate(-90deg);
  88. position: relative;
  89. z-index: 2;
  90. }
  91. .ring-progress {
  92. transition: stroke-dashoffset 0.8s ease;
  93. filter: drop-shadow(0 2rpx 4rpx rgba(245, 158, 11, 0.3));
  94. }
  95. .ring-center {
  96. position: absolute;
  97. top: 0;
  98. left: 0;
  99. right: 0;
  100. bottom: 0;
  101. display: flex;
  102. flex-direction: column;
  103. align-items: center;
  104. justify-content: center;
  105. z-index: 3;
  106. }
  107. .ring-score {
  108. font-size: 72rpx;
  109. font-weight: bold;
  110. color: #92400E;
  111. line-height: 1.1;
  112. }
  113. .ring-total {
  114. font-size: 24rpx;
  115. color: #B45309;
  116. opacity: 0.7;
  117. }
  118. .ring-level {
  119. margin-top: 8rpx;
  120. font-size: 28rpx;
  121. color: #F59E0B;
  122. font-weight: 600;
  123. letter-spacing: 2rpx;
  124. }
  125. .ripple-1,
  126. .ripple-2 {
  127. position: absolute;
  128. top: 0;
  129. left: 0;
  130. width: 360rpx;
  131. height: 360rpx;
  132. border-radius: 50%;
  133. border: 3rpx solid rgba(245, 158, 11, 0.25);
  134. animation: ripple 3s ease-out infinite;
  135. pointer-events: none;
  136. }
  137. .ripple-2 {
  138. animation-delay: 1.5s;
  139. }
  140. @keyframes ripple {
  141. 0% {
  142. opacity: 0.6;
  143. transform: scale(0.9);
  144. }
  145. 100% {
  146. opacity: 0;
  147. transform: scale(1.2);
  148. }
  149. }
  150. .ring-slogan {
  151. margin-top: 24rpx;
  152. display: flex;
  153. flex-direction: column;
  154. align-items: center;
  155. }
  156. .ring-slogan-text {
  157. font-size: 26rpx;
  158. color: #92400E;
  159. letter-spacing: 2rpx;
  160. }
  161. .ring-delta {
  162. margin-top: 8rpx;
  163. font-size: 24rpx;
  164. color: #F59E0B;
  165. font-weight: 500;
  166. }
  167. </style>