Просмотр исходного кода

APP工分页面增加排名展示

ouyj 4 месяцев назад
Родитель
Сommit
5254948ee1
1 измененных файлов с 362 добавлено и 59 удалено
  1. 362 59
      pages/score/index.uvue

+ 362 - 59
pages/score/index.uvue

@@ -1,7 +1,7 @@
 <template>
-  <uni-navbar-lite :showLeft=false title="工分"></uni-navbar-lite>
+  <uni-navbar-lite :showLeft="false" title="工分" />
   <view class="list-page">
-    <!-- 搜索栏 -->
+    <!-- 搜索栏 --> 
     <view class="search-bar">
       <view class="search-box">
         <image class="search-icon" src="/static/images/workbench/list/1.png" mode="aspectFit"></image>
@@ -63,64 +63,102 @@
         </text> -->
       </view>
     </view>
-
-    <!-- 工分统计 -->
+ 
     <view class="stats-section">
-      <view class="stats-header">
-        <text class="stats-title">{{ monthTitle }}月度工分</text>
-        <view class="month-filters">
-			<view class="month-tab">
-			  <text
-				class="month-filter"
-				:class="{ 'month-filter-sel': selectedMonth === 'prev' }"
-				@click="changeMonth('prev')"
-			  >
-				上月
-			  </text>
-			</view>
-			<view class="month-tab">
-			  <text
-				class="month-filter"
-				:class="{ 'month-filter-sel': selectedMonth === 'current' }"
-				@click="changeMonth('current')"
-			  >
-				本月
-			  </text>
+      <!-- 标签切换 -->
+      <view class="stats-tabs">
+        <text
+          class="tab-item" 
+          :class="{ 'tab-active': activeTab === 'ranking' }"
+          @click="switchTab('ranking')"
+        >
+          个人排名
+        </text>
+        <text
+          class="tab-item" 
+          :class="{ 'tab-active': activeTab === 'score' }"
+          @click="switchTab('score')"
+        >
+          月度工分
+        </text>
+      </view>
+		<!-- 个人排名内容 -->
+		<view v-if="activeTab === 'ranking'" class="ranking-content"> 
+		  <!-- 排名模块 -->
+		  <view v-if="rankingItems.length > 0">
+		    <view class="ranking-item-wrapper" v-for="(item, index) in rankingItems" :key="index">
+		      <view class="ranking-item">
+		        <view class="ranking-circle-wrapper">
+		          <view class="ranking-number" :class="getRankingSizeClass(index)">
+		            <text class="ranking-number-text">{{ item.rank }}/{{ item.total }}</text>
+		          </view>
+		        </view>
+		        <text class="ranking-name">{{ item.name }}</text>
+		        <text class="ranking-label">第{{ item.rank }}名</text>
+		      </view>
+		    </view>
 		  </view>
-		  <view class="month-tab">
-			  <text
-				class="month-filter"
-				:class="{ 'month-filter-sel': selectedMonth === 'custom' }"
-				@click="showCustomDatePicker"
-			  >
-				自定义
-			  </text>
+		  <view v-else class="no-data">
+		    <text class="no-data-text">无排名数据</text>
 		  </view>
-        </view>
-      </view>
-
-      <!-- 统计数据 -->
-      <view class="stats-content">
-        <view class="total-score">
-          <text class="score-value">{{ totalScore }}分</text>
-          <text class="score-label">{{ monthTitle }}总工分</text>
-        </view>
-
-        <view class="score-breakdown">
-          <view class="breakdown-item">
-            <text class="breakdown-label">维保工分</text>
-            <text class="breakdown-value">{{ maintenanceScore }}分</text>
-          </view>
-          <view class="breakdown-item">
-            <text class="breakdown-label">维修工分</text>
-            <text class="breakdown-value">{{ repairScore }}分</text>
-          </view>
-          <!-- <view v-if="rank !== null && totalRankingUsers !== null" class="breakdown-item">
-            <text class="breakdown-label">排名</text>
-            <text class="breakdown-value">{{ rank }}/{{ totalRankingUsers }}</text>
-          </view> -->
-        </view>
-      </view>
+		</view>
+		<!-- 月度工分内容 -->
+		<view v-if="activeTab === 'score'" class="score-content">
+			<view class="stats-header">
+				<text class="stats-title">{{ monthTitle }}月度工分</text>
+				<view class="month-filters">
+					<view class="month-tab">
+					  <text
+						class="month-filter"
+						:class="{ 'month-filter-sel': selectedMonth === 'prev' }"
+						@click="changeMonth('prev')"
+					  >
+						上月
+					  </text>
+					</view>
+					<view class="month-tab">
+					  <text
+						class="month-filter"
+						:class="{ 'month-filter-sel': selectedMonth === 'current' }"
+						@click="changeMonth('current')"
+					  >
+						本月
+					  </text>
+				  </view>
+				  <view class="month-tab">
+					  <text
+						class="month-filter"
+						:class="{ 'month-filter-sel': selectedMonth === 'custom' }"
+						@click="showCustomDatePicker"
+					  >
+						自定义
+					  </text>
+				  </view>
+				</view> 
+			</view>
+			<!-- 统计数据 -->
+			<view class="stats-content"> 
+			  <view class="total-score">
+				<text class="score-value">{{ totalScore }}分</text>
+				<text class="score-label">{{ monthTitle }}总工分</text>
+			  </view>
+			
+			  <view class="score-breakdown">
+				<view class="breakdown-item">
+				  <text class="breakdown-label">维保工分</text>
+				  <text class="breakdown-value">{{ maintenanceScore }}分</text>
+				</view>
+				<view class="breakdown-item">
+				  <text class="breakdown-label">维修工分</text>
+				  <text class="breakdown-value">{{ repairScore }}分</text>
+				</view>
+				<!-- <view v-if="rank !== null && totalRankingUsers !== null" class="breakdown-item">
+				  <text class="breakdown-label">排名</text>
+				  <text class="breakdown-value">{{ rank }}/{{ totalRankingUsers }}</text>
+				</view> -->
+			  </view>
+			</view>
+		</view>
     </view>
 
     <!-- 工单评分列表 -->
@@ -197,13 +235,14 @@
 
     <!-- 底部 TabBar -->
     <custom-tabbar :current="3" :hide0="tabbar[0]" :hide1="tabbar[1]" :hide2="tabbar[2]" :hide3="tabbar[3]"/>
-  </view>
+  </view> 
 </template>
 
 <script setup lang="uts">
     import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
     import { listOrderScores, getOrderScoreStatistics, listMobileOrderScores } from '@/api/score/index'
     import { getDictDataByType } from '@/api/dict/index'
+    import { selectHomePageData } from '@/api/index/index'
     import type { SysDictData } from '@/types/dict'
 
     // 数据状态
@@ -221,6 +260,19 @@
     const rank = ref<number | null>(null)
     const totalRankingUsers = ref<number | null>(null)
     const customDate = ref<string>('')
+    
+    // 新增:标签切换相关
+    const activeTab = ref<string>('ranking') // 默认显示个人排名
+
+    // 用户数据类型定义
+    type RankingItem = {
+      name: string;
+      rank: number;
+      total: number;
+    }
+    
+    // 新增:个人排名相关数据
+    const rankingItems = ref<RankingItem[]>([])
 
     // 防止重复请求的标志位
     const isSearching = ref<boolean>(false)
@@ -261,6 +313,111 @@
       }
     })
 
+
+    
+
+
+    // 根据索引获取排名圆圈的大小类(复制并修改自开屏页)
+    const getRankingSizeClass = (index: number): string => {
+      // size-1 对应最小的圆圈,size-3 对应最大的圆圈
+      const size = Math.min(index + 1, 3);
+      return `size-${size}`;
+    };
+
+    // 获取个人排名数据(复制并修改自开屏页)
+    const fetchRankingData = async (): Promise<void> => {
+      try {
+        // 调用后端API获取用户数据
+        const response = await selectHomePageData();
+        
+        // 根据响应结果更新rankingItems
+        if (response != null) {
+          const respObj = response as UTSJSONObject; 
+          const data = respObj['data'] as UTSJSONObject; 
+          
+          // 初始化默认值
+          let deptName = '未知部门';
+          let center = '未知中心';
+          let companyName = '未知公司';
+          
+          // 从scoreDept中提取部门、中心和公司名称
+          if (data.hasOwnProperty('scoreDept') && Array.isArray(data['scoreDept']) && (data['scoreDept'] as any[]).length > 0) {
+            const scoreDept = data['scoreDept'] as UTSJSONObject[];
+            const firstItem = scoreDept[0];
+            if (firstItem.hasOwnProperty('deptName')) {
+              deptName = firstItem['deptName'] as string;
+            }
+            if (firstItem.hasOwnProperty('center')) {
+              center = firstItem['center'] as string;
+            }
+            if (firstItem.hasOwnProperty('companyName')) {
+              companyName = firstItem['companyName'] as string;
+            }
+          }
+          
+          // 更新排名信息
+          const items : RankingItem[] = [];
+          
+          // 部门排名(东山电场)
+          if (data.hasOwnProperty('deptSort') && data.hasOwnProperty('scoreDept')) {
+            const deptSort = typeof data['deptSort'] === 'number' ? data['deptSort'] as number : 0;
+            const scoreDept = Array.isArray(data['scoreDept']) ? data['scoreDept'] as any[] : [];
+            // 只有当部门排序大于0且scoreDept数组不为空时才添加
+            if (deptSort > 0 && scoreDept.length > 0) {
+              items.push({
+                name: deptName,
+                rank: deptSort,
+                total: scoreDept.length
+              });
+            }
+          }
+          
+          // 中心排名(陆上设备维护中心)
+          if (data.hasOwnProperty('centerSort') && data.hasOwnProperty('scoreCenter')) {
+            const centerSort = typeof data['centerSort'] === 'number' ? data['centerSort'] as number : 0;
+            const scoreCenter = Array.isArray(data['scoreCenter']) ? data['scoreCenter'] as any[] : [];
+            // 只有当中心排序大于0且scoreCenter数组不为空时才添加
+            if (centerSort > 0 && scoreCenter.length > 0) {
+              items.push({
+                name: center,
+                rank: centerSort,
+                total: scoreCenter.length
+              });
+            }
+          }
+          
+          // 公司排名
+          if (data.hasOwnProperty('companySort') && data.hasOwnProperty('scoreCompany')) {
+            const companySort = typeof data['companySort'] === 'number' ? data['companySort'] as number : 0;
+            const scoreCompany = Array.isArray(data['scoreCompany']) ? data['scoreCompany'] as any[] : [];
+            // 只有当公司排序大于0且scoreCompany数组不为空时才添加
+            if (companySort > 0 && scoreCompany.length > 0) {
+              items.push({
+                name: companyName,
+                rank: companySort,
+                total: scoreCompany.length
+              });
+            }
+          }
+          
+          // 更新rankingItems
+          rankingItems.value = items;
+        }
+      } catch (error) {
+        console.error('获取用户排名数据失败:', error);
+      }
+    };
+
+    // 新增:切换标签
+    function switchTab(tab: string) {
+      activeTab.value = tab;
+      
+      // 当切换到个人排名标签时,获取排名数据
+      if (tab === 'ranking') {
+        fetchRankingData();
+      }
+    }
+
     // 打开自定义日期选择弹窗
     function showCustomDatePicker() {
       showDatePickerPopup.value = true
@@ -828,6 +985,9 @@
       loadData(false)
       getStatistics()
       dictLoaded.value = true
+      
+      // 获取初始排名数据
+      fetchRankingData();
     })
 
     // 组件销毁时清除定时器
@@ -921,6 +1081,37 @@
   padding: 20rpx;
 }
 
+/* 标签切换样式 */
+.stats-tabs {
+  display: flex;
+  flex-direction: row;
+  border-bottom: 2rpx solid #f0f0f0;
+  margin-bottom: 20rpx;
+}
+
+.tab-item {
+  padding: 15rpx 30rpx;
+  font-size: 30rpx;
+  color: #666;
+  position: relative;
+}
+
+.tab-active {
+  color: #165dff;
+  font-weight: bold;
+}
+
+.tab-active::after {
+  content: '';
+  position: absolute;
+  bottom: -2rpx;
+  left: 0;
+  right: 0;
+  height: 6rpx;
+  background-color: #165dff;
+  border-radius: 3rpx;
+}
+
 .stats-header {
   flex-direction: row;
   justify-content: space-between;
@@ -1209,4 +1400,116 @@
   color: #ff0000;
   border-color: #ff7446;
 }
-</style>
+
+/* 个人排名模块样式 */ 
+.ranking-item-wrapper {
+  padding: 5rpx 30rpx;
+  margin-bottom: 5rpx;
+  background: transparent;
+}
+
+.ranking-item {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  width: 100%;
+  padding: 10rpx 0;
+}
+
+.module-title {
+  color: #ffffff;
+  font-size: 36rpx;
+  font-weight: bold;
+  margin-bottom: 0;
+  text-align: center;
+}
+
+.ranking-item {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  width: 100%;
+  padding-left: 0;
+  margin-left: 0;
+}
+
+
+
+.ranking-name {
+  color: #000000;
+  font-size: 32rpx;
+  font-weight: normal;
+  flex: 1;
+  margin-left: 20rpx;
+}
+
+.ranking-number {
+  background: #38bdf8;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.ranking-circle-wrapper {
+  width: 100rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.ranking-number.size-1 {
+  width: 60rpx;
+  height: 60rpx;
+  border-radius: 30rpx;
+}
+
+.ranking-number.size-2 {
+  width: 70rpx;
+  height: 70rpx;
+  border-radius: 35rpx;
+}
+
+.ranking-number.size-3 {
+  width: 80rpx;
+  height: 80rpx;
+  border-radius: 40rpx;
+}
+
+.ranking-number-text {
+  color: #ffffff;
+  font-weight: normal;
+  text-align: center;
+  font-size: 28rpx;
+}
+
+.ranking-number.size-1 .ranking-number-text {
+  font-size: 18rpx;
+}
+
+.ranking-number.size-2 .ranking-number-text {
+  font-size: 20rpx;
+}
+
+.ranking-number.size-3 .ranking-number-text {
+  font-size: 22rpx;
+}
+
+.ranking-label {
+  color: #ff0000;
+  font-size: 32rpx;
+  white-space: nowrap;
+  margin-left: 20rpx;
+}
+
+.no-data {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 200rpx;
+}
+
+.no-data-text {
+  font-size: 28rpx;
+  color: #999;
+}
+</style>