| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- <template>
- <uni-navbar-lite :showLeft="true" title="排名详情"></uni-navbar-lite>
- <view class="ranking-page">
- <!-- 排名列表 -->
- <common-list
- :dataList="rankingList"
- :loading="loading"
- :refreshing="refreshing"
- :hasMore="false"
- @refresh="handleRefresh"
- class="list-with-padding"
- >
- <template #default="{ item, index }">
- <view class="ranking-item">
- <view class="ranking-info">
- <view class="ranking-position">
- <view class="position-circle" :class="getPositionClass(index as number)">
- <text class="position-text">{{ (item as UTSJSONObject).get('rank').toString() }}</text>
- </view>
- </view>
- <view class="user-info">
- <text class="user-name" :style="{ color: (item as UTSJSONObject).get('nickName') == currentUserNickName ? '#ff0000' : '#333333' }">{{ (item as UTSJSONObject).get('nickName') as string }}</text>
- <text class="user-dept">{{ (item as UTSJSONObject).get('deptName') as string }}</text>
- </view>
- </view>
- <view class="score-info">
- <text class="score-value">{{ formatScore((item as UTSJSONObject).get('finalScore') as number | null) }}</text>
- </view>
- </view>
- </template>
- </common-list>
- </view>
- </template>
- <script setup lang="uts">
- import { ref } from 'vue'
- import { selectHomePageData } from '@/api/index/index'
- // 数据状态
- const loading = ref<boolean>(false)
- const refreshing = ref<boolean>(false)
- // 添加防重复刷新的标志
- const isRefreshing = ref<boolean>(false)
- // 添加刷新时间戳,用于防抖
- const lastRefreshTime = ref<number>(0)
- // 排名类型 (dept, center, company)
- const rankingType = ref<string>('')
- const rankingTypeName = ref<string>('')
- // 排名列表数据
- const rankingList = ref<UTSJSONObject[]>([])
- // 当前用户昵称
- const currentUserNickName = ref<string>('')
- // 获取排名数据
- const loadRankingData = async (): Promise<void> => {
- try {
- loading.value = true
- refreshing.value = true
- const response = await selectHomePageData()
- if (response != null) {
- const respObj = response as UTSJSONObject
- const data = respObj['data'] as UTSJSONObject
-
- // 保存当前用户昵称
- currentUserNickName.value = data.get('nickName') as string
- console.log("当前用户昵称:", currentUserNickName.value)
-
- // 根据类型获取相应的排名数据
- let rawData: UTSJSONObject[] = []
- const type = rankingType.value;
-
- if (type == 'dept' && data.get('scoreDept') != null) {
- const deptData = data.get('scoreDept');
- if (Array.isArray(deptData)) {
- rawData = deptData as UTSJSONObject[];
- }
- } else if (type == 'center' && data.get('scoreCenter') != null) {
- const centerData = data.get('scoreCenter');
- if (Array.isArray(centerData)) {
- rawData = centerData as UTSJSONObject[];
- }
- } else if (type == 'company' && data.get('scoreCompany') != null) {
- const companyData = data.get('scoreCompany');
- if (Array.isArray(companyData)) {
- rawData = companyData as UTSJSONObject[];
- }
- } else {
- console.log("没有匹配到任何分支")
- }
- // 按照分数排序
- rawData.sort((a: UTSJSONObject, b: UTSJSONObject): number => {
- const scoreA = (a['finalScore'] as number | null) ?? 0
- const scoreB = (b['finalScore'] as number | null) ?? 0
- return scoreB - scoreA
- })
- // 处理排名(相同分数排名相同)
- const processedData: UTSJSONObject[] = []
- rawData.forEach((item: UTSJSONObject, index: number) => {
- let rank = index + 1
- // 如果当前项分数与前一项相同,则排名也相同
- if (index > 0) {
- const prevScore = (rawData[index - 1]['finalScore'] as number | null) ?? 0
- const currentScore = (item['finalScore'] as number | null) ?? 0
- if (currentScore === prevScore) {
- // 找到前一个处理后的项的排名
- rank = (processedData[processedData.length - 1]['rank'] as number)
- }
- }
- processedData.push({
- ...item,
- 'rank': rank
- })
- })
- rankingList.value = processedData
- }
- } catch (error) {
- console.error('获取排名数据失败:', error)
- // 出错时也需要重置刷新状态
- if (refreshing.value) {
- refreshing.value = false;
- isRefreshing.value = false;
- }
- } finally {
- loading.value = false
- refreshing.value = false
- // 确保在finally中也重置isRefreshing标志
- isRefreshing.value = false
- }
- }
- const formatScore = (score: number | null): string => {
- if (score === null) return '0.00'
- return score.toFixed(2)
- }
- // 获取排名位置的样式类
- const getPositionClass = (index: number): string => {
- if (index == 0) {
- return 'first'
- } else if (index == 1) {
- return 'second'
- } else if (index == 2) {
- return 'third'
- }
- return 'other'
- }
- // 下拉刷新
- const handleRefresh = (): void => {
- console.log("handleRefresh被触发")
- console.log("loading.value===" + loading.value)
- console.log("isRefreshing.value===" + isRefreshing.value)
- // 防抖处理,避免频繁触发
- const now = Date.now();
- if (now - lastRefreshTime.value < 1000) {
- console.log("刷新操作过于频繁,忽略本次触发");
- refreshing.value = false;
- return;
- }
- lastRefreshTime.value = now;
- // 添加防重复调用检查
- if (loading.value || isRefreshing.value) {
- // 如果已经在加载或正在刷新,直接重置刷新状态
- refreshing.value = false;
- return;
- }
- console.log("loading.value1===" + loading.value)
- console.log("isRefreshing.value1===" + isRefreshing.value)
- // 设置刷新标志
- isRefreshing.value = true;
- loadRankingData(); // 使用默认的下拉刷新行为
- // 确保在一定时间后重置刷新标志,防止意外情况
- setTimeout(() => {
- isRefreshing.value = false
- }, 100) // 延迟重置,确保状态完全更新
- }
- // 页面加载时获取参数
- onLoad((options: UTSJSONObject | null) => {
- if (options != null && options['type'] != null) {
- const typeVal = options['type'] as string
- rankingType.value = typeVal
- /* switch(rankingType.value) {
- case 'dept':
- rankingTypeName.value = '部门'
- break
- case 'center':
- rankingTypeName.value = '中心'
- break
- case 'company':
- rankingTypeName.value = '公司'
- break
- default:
- rankingTypeName.value = '排名'
- } */
- loadRankingData()
- }
- })
- // 组件销毁时清除状态
- onUnload(() => {
- // 如果组件销毁前还有未完成的刷新操作,确保状态被重置
- loading.value = false;
- refreshing.value = false;
- isRefreshing.value = false;
- })
- </script>
- <style lang="scss">
- .ranking-page {
- flex: 1;
- background-color: #e8f0f9;
- }
- .ranking-item {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- align-items: center;
- padding: 30rpx;
- background-color: #ffffff;
- margin: 12rpx 30rpx;
- border-radius: 16rpx;
- }
- .ranking-info {
- display: flex;
- flex-direction: row;
- align-items: center;
- flex: 1;
- }
- .ranking-position {
- margin-right: 24rpx;
- }
- .position-circle {
- width: 60rpx;
- height: 60rpx;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .position-circle.first {
- //background-color: #ffd700; /* 金色 */
- }
- .position-circle.second {
- //background-color: #c0c0c0; /* 银色 */
- }
- .position-circle.third {
- //background-color: #cd7f32; /* 铜色 */
- }
- .position-circle.other {
- //background-color: #e0e0e0;
- }
- .position-text {
- font-size: 30rpx;
- font-weight: bold;
- color: #333333;
- }
- .user-info {
- display: flex;
- flex-direction: row;
- align-items: center;
- }
- .user-name {
- font-size: 30rpx;
- color: #333333;
- font-weight: bold;
- margin-right: 20rpx;
- }
- .user-dept {
- font-size: 30rpx;
- color: #666666;
- }
- .score-info {
- display: flex;
- flex-direction: column;
- align-items: flex-end;
- }
- .score-value {
- font-size: 30rpx;
- font-weight: bold;
- color: #165dff;
- }
- // 添加底部填充的类
- .list-with-padding {
- padding-bottom: 40rpx;
- }
- </style>
|