ranking.uvue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. <template>
  2. <uni-navbar-lite :showLeft="true" title="排名详情"></uni-navbar-lite>
  3. <view class="ranking-page">
  4. <!-- 排名列表 -->
  5. <common-list
  6. :dataList="rankingList"
  7. :loading="loading"
  8. :refreshing="refreshing"
  9. :hasMore="false"
  10. @refresh="handleRefresh"
  11. class="list-with-padding"
  12. >
  13. <template #default="{ item, index }">
  14. <view class="ranking-item">
  15. <view class="ranking-info">
  16. <view class="ranking-position">
  17. <view class="position-circle" :class="getPositionClass(index as number)">
  18. <text class="position-text">{{ (item as UTSJSONObject).get('rank').toString() }}</text>
  19. </view>
  20. </view>
  21. <view class="user-info">
  22. <text class="user-name" :style="{ color: (item as UTSJSONObject).get('nickName') == currentUserNickName ? '#ff0000' : '#333333' }">{{ (item as UTSJSONObject).get('nickName') as string }}</text>
  23. <text class="user-dept">{{ (item as UTSJSONObject).get('deptName') as string }}</text>
  24. </view>
  25. </view>
  26. <view class="score-info">
  27. <text class="score-value">{{ formatScore((item as UTSJSONObject).get('finalScore') as number | null) }}</text>
  28. </view>
  29. </view>
  30. </template>
  31. </common-list>
  32. </view>
  33. </template>
  34. <script setup lang="uts">
  35. import { ref } from 'vue'
  36. import { selectHomePageData } from '@/api/index/index'
  37. // 数据状态
  38. const loading = ref<boolean>(false)
  39. const refreshing = ref<boolean>(false)
  40. // 排名类型 (dept, center, company)
  41. const rankingType = ref<string>('')
  42. const rankingTypeName = ref<string>('')
  43. // 排名列表数据
  44. const rankingList = ref<UTSJSONObject[]>([])
  45. // 当前用户昵称
  46. const currentUserNickName = ref<string>('')
  47. // 获取排名数据
  48. const loadRankingData = async (): Promise<void> => {
  49. try {
  50. loading.value = true
  51. refreshing.value = true
  52. const response = await selectHomePageData()
  53. if (response != null) {
  54. const respObj = response as UTSJSONObject
  55. const data = respObj['data'] as UTSJSONObject
  56. // 保存当前用户昵称
  57. currentUserNickName.value = data.get('nickName') as string
  58. console.log("当前用户昵称:", currentUserNickName.value)
  59. // 根据类型获取相应的排名数据
  60. let rawData: UTSJSONObject[] = []
  61. const type = rankingType.value;
  62. if (type == 'dept' && data.get('scoreDept') != null) {
  63. const deptData = data.get('scoreDept');
  64. if (Array.isArray(deptData)) {
  65. rawData = deptData as UTSJSONObject[];
  66. }
  67. } else if (type == 'center' && data.get('scoreCenter') != null) {
  68. const centerData = data.get('scoreCenter');
  69. if (Array.isArray(centerData)) {
  70. rawData = centerData as UTSJSONObject[];
  71. }
  72. } else if (type == 'company' && data.get('scoreCompany') != null) {
  73. const companyData = data.get('scoreCompany');
  74. if (Array.isArray(companyData)) {
  75. rawData = companyData as UTSJSONObject[];
  76. }
  77. } else {
  78. console.log("没有匹配到任何分支")
  79. }
  80. // 按照分数排序
  81. rawData.sort((a: UTSJSONObject, b: UTSJSONObject): number => {
  82. const scoreA = (a['finalScore'] as number | null) ?? 0
  83. const scoreB = (b['finalScore'] as number | null) ?? 0
  84. return scoreB - scoreA
  85. })
  86. // 处理排名(相同分数排名相同)
  87. const processedData: UTSJSONObject[] = []
  88. rawData.forEach((item: UTSJSONObject, index: number) => {
  89. let rank = index + 1
  90. // 如果当前项分数与前一项相同,则排名也相同
  91. if (index > 0) {
  92. const prevScore = (rawData[index - 1]['finalScore'] as number | null) ?? 0
  93. const currentScore = (item['finalScore'] as number | null) ?? 0
  94. if (currentScore === prevScore) {
  95. // 找到前一个处理后的项的排名
  96. rank = (processedData[processedData.length - 1]['rank'] as number)
  97. }
  98. }
  99. processedData.push({
  100. ...item,
  101. 'rank': rank
  102. })
  103. })
  104. rankingList.value = processedData
  105. }
  106. } catch (error) {
  107. console.error('获取排名数据失败:', error)
  108. } finally {
  109. loading.value = false
  110. refreshing.value = false
  111. }
  112. }
  113. const formatScore = (score: number | null): string => {
  114. if (score === null) return '0.00'
  115. return score.toFixed(2)
  116. }
  117. // 获取排名位置的样式类
  118. const getPositionClass = (index: number): string => {
  119. if (index == 0) {
  120. return 'first'
  121. } else if (index == 1) {
  122. return 'second'
  123. } else if (index == 2) {
  124. return 'third'
  125. }
  126. return 'other'
  127. }
  128. // 下拉刷新
  129. const handleRefresh = (): void => {
  130. loadRankingData()
  131. }
  132. // 页面加载时获取参数
  133. onLoad((options: UTSJSONObject | null) => {
  134. if (options != null && options['type'] != null) {
  135. const typeVal = options['type'] as string
  136. rankingType.value = typeVal
  137. /* switch(rankingType.value) {
  138. case 'dept':
  139. rankingTypeName.value = '部门'
  140. break
  141. case 'center':
  142. rankingTypeName.value = '中心'
  143. break
  144. case 'company':
  145. rankingTypeName.value = '公司'
  146. break
  147. default:
  148. rankingTypeName.value = '排名'
  149. } */
  150. loadRankingData()
  151. }
  152. })
  153. </script>
  154. <style lang="scss">
  155. .ranking-page {
  156. flex: 1;
  157. background-color: #e8f0f9;
  158. }
  159. .ranking-item {
  160. display: flex;
  161. flex-direction: row;
  162. justify-content: space-between;
  163. align-items: center;
  164. padding: 30rpx;
  165. background-color: #ffffff;
  166. margin: 12rpx 30rpx;
  167. border-radius: 16rpx;
  168. }
  169. .ranking-info {
  170. display: flex;
  171. flex-direction: row;
  172. align-items: center;
  173. flex: 1;
  174. }
  175. .ranking-position {
  176. margin-right: 24rpx;
  177. }
  178. .position-circle {
  179. width: 60rpx;
  180. height: 60rpx;
  181. border-radius: 50%;
  182. display: flex;
  183. align-items: center;
  184. justify-content: center;
  185. }
  186. .position-circle.first {
  187. //background-color: #ffd700; /* 金色 */
  188. }
  189. .position-circle.second {
  190. //background-color: #c0c0c0; /* 银色 */
  191. }
  192. .position-circle.third {
  193. //background-color: #cd7f32; /* 铜色 */
  194. }
  195. .position-circle.other {
  196. //background-color: #e0e0e0;
  197. }
  198. .position-text {
  199. font-size: 30rpx;
  200. font-weight: bold;
  201. color: #333333;
  202. }
  203. .user-info {
  204. display: flex;
  205. flex-direction: row;
  206. align-items: center;
  207. }
  208. .user-name {
  209. font-size: 30rpx;
  210. color: #333333;
  211. font-weight: bold;
  212. margin-right: 20rpx;
  213. }
  214. .user-dept {
  215. font-size: 30rpx;
  216. color: #666666;
  217. }
  218. .score-info {
  219. display: flex;
  220. flex-direction: column;
  221. align-items: flex-end;
  222. }
  223. .score-value {
  224. font-size: 30rpx;
  225. font-weight: bold;
  226. color: #165dff;
  227. }
  228. // 添加底部填充的类
  229. .list-with-padding {
  230. padding-bottom: 40rpx;
  231. }
  232. </style>