index.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <template>
  2. <home-container :customStyle="{ background: 'none' }">
  3. <div class="question-statistics-container">
  4. <!-- 选项卡 -->
  5. <div class="tab-container">
  6. <h-tabs class="h-tab" v-model="activeTab" :tabs="tabs" :activeColor="'#2B7BFF'" value-key="value" label-key="label"
  7. @change="handleTabChange" />
  8. </div>
  9. <!-- 组件切换区域 -->
  10. <div class="component-container">
  11. <!-- 实时状态组件 -->
  12. <real-time-status
  13. v-if="activeTab === 'realtime'"
  14. :loading="loading"
  15. @update:loading="loading = $event"
  16. />
  17. <!-- 完成趋势组件 -->
  18. <completion-trend
  19. v-else-if="activeTab === 'trend'"
  20. />
  21. <!-- 错题分析组件 -->
  22. <error-analysis
  23. v-else-if="activeTab === 'analysis'"
  24. />
  25. </div>
  26. </div>
  27. </home-container>
  28. </template>
  29. <script>
  30. import HomeContainer from "@/components/HomeContainer.vue";
  31. import RealTimeStatus from "./components/RealTimeStatus.vue";
  32. import CompletionTrend from "./components/CompletionTrend.vue";
  33. import ErrorAnalysis from "./components/ErrorAnalysis.vue";
  34. import HTabs from "@/components/h-tabs/h-tabs.vue";
  35. import { mapState } from 'vuex'
  36. export default {
  37. name: 'QuestionStatistics',
  38. components: {
  39. HomeContainer,
  40. RealTimeStatus,
  41. CompletionTrend,
  42. ErrorAnalysis,
  43. HTabs
  44. },
  45. data() {
  46. return {
  47. loading: false,
  48. activeTab: 'realtime', // realtime, trend, analysis
  49. allTabs: [
  50. { label: '实时状态', value: 'realtime', style: { 'color': '#666666' }, activeStyle: { 'color': '#2B7BFF' } },
  51. { label: '完成趋势', value: 'trend', style: { 'color': '#666666' }, activeStyle: { 'color': '#2B7BFF' } },
  52. { label: '错题分析', value: 'analysis', style: { 'color': '#666666' }, activeStyle: { 'color': '#2B7BFF' } }
  53. ]
  54. };
  55. },
  56. computed: {
  57. ...mapState({
  58. userRoles: state => state.user.roles
  59. }),
  60. // 根据用户角色过滤tabs
  61. tabs() {
  62. // 如果是班组长,过滤掉完成趋势tab
  63. if (this.isBanZuZhang) {
  64. return this.allTabs.filter(tab => tab.value !== 'trend');
  65. }
  66. return this.allTabs;
  67. },
  68. // 判断是否为班组长
  69. isBanZuZhang() {
  70. let roles = this.userRoles;
  71. console.log('用户角色:', roles);
  72. return roles && (roles.includes('banzuzhang') || roles.includes('teamLeader'));
  73. }
  74. },
  75. methods: {
  76. // 选项卡切换事件
  77. handleTabChange(index) {
  78. this.activeTab = index;
  79. console.log('切换到选项卡:', this.tabs.find(tab => tab.value === index)?.label);
  80. }
  81. }
  82. };
  83. </script>
  84. <style lang="scss" scoped>
  85. .question-statistics-container {
  86. position: relative;
  87. padding-top: 80rpx;
  88. }
  89. .tab-container {
  90. position: fixed;
  91. top: 80rpx;
  92. left: 0;
  93. right: 0;
  94. z-index: 1000;
  95. padding: 15px 15px 0 15px;
  96. background-color: white;
  97. .h-tab{
  98. padding-bottom: 10px !important;
  99. }
  100. }
  101. .capsule-tab-container {
  102. display: inline-flex;
  103. // border: 2rpx solid #2B7BFF;
  104. border-radius: 32rpx;
  105. padding: 2rpx;
  106. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
  107. }
  108. .capsule-tab-item {
  109. position: relative;
  110. padding: 8rpx 24rpx;
  111. cursor: pointer;
  112. transition: all 0.3s ease;
  113. user-select: none;
  114. // 非激活状态 - 蓝字白底蓝边框
  115. &:not(.capsule-tab-active) {
  116. background: #ffffff;
  117. border: 1rpx solid #2B7BFF;
  118. .capsule-tab-text {
  119. color: #2B7BFF;
  120. font-weight: normal;
  121. }
  122. }
  123. // 激活状态 - 白字蓝底
  124. &.capsule-tab-active {
  125. background: #2B7BFF;
  126. border: 1rpx solid #2B7BFF;
  127. box-shadow: 0 2rpx 8rpx rgba(43, 123, 255, 0.3);
  128. .capsule-tab-text {
  129. color: #ffffff;
  130. font-weight: bold;
  131. }
  132. }
  133. }
  134. .capsule-tab-text {
  135. font-size: 24rpx;
  136. line-height: 1;
  137. transition: all 0.3s ease;
  138. }
  139. .component-container {
  140. min-height: 400rpx;
  141. }
  142. .loading-container {
  143. display: flex;
  144. justify-content: center;
  145. align-items: center;
  146. height: 200rpx;
  147. font-size: 32rpx;
  148. color: #999;
  149. background: #f8f8f8;
  150. border-radius: 16rpx;
  151. }
  152. .progress-container {
  153. display: flex;
  154. align-items: center;
  155. gap: 16rpx;
  156. .progress-text {
  157. font-size: 24rpx;
  158. color: #4873E3;
  159. font-weight: 500;
  160. min-width: 60rpx;
  161. }
  162. }
  163. </style>