index.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <template>
  2. <div class="app-container">
  3. <el-card>
  4. <!-- 第一行:标题 -->
  5. <div class="header-section">
  6. <h2 class="section-title">绩效指标</h2>
  7. </div>
  8. <!-- 第二行:多选按钮组 -->
  9. <div class="button-group-section">
  10. <el-checkbox-group v-model="selectedIndicators" class="indicator-checkbox-group" :min="3">
  11. <el-checkbox-button v-for="indicator in indicatorOptions" :key="indicator.value" :label="indicator.value" disabled>
  12. {{ indicator.label }}
  13. </el-checkbox-button>
  14. </el-checkbox-group>
  15. </div>
  16. <!-- 第三行:绩效矩阵标题 -->
  17. <div class="header-section" style="margin-top: 30px;">
  18. <h2 class="section-title">绩效矩阵</h2>
  19. </div>
  20. <!-- 第四行:默认值说明 -->
  21. <!-- <div class="default-value-section">
  22. <p class="default-value-text">
  23. 默认值a=3,b=5,c=2;abc可编辑,编辑后,计算逻辑按照下图取倒数
  24. </p>
  25. </div> -->
  26. <!-- 第五行:绩效矩阵表格 -->
  27. <div class="matrix-section">
  28. <el-table :data="matrixData" border style="width:600px; margin-top: 20px;" class="performance-matrix">
  29. <!-- 表头 -->
  30. <el-table-column label="" prop="rowName" align="center" width="120" fixed />
  31. <el-table-column v-for="header in matrixHeaders" :key="header" :label="header" align="center" min-width="120">
  32. <template #default="scope">
  33. <div v-if="scope.row.rowName === '查获效率' && header === '查获效率'" class="fixed-cell">
  34. 1
  35. </div>
  36. <div v-else-if="scope.row.rowName === '查获效率' && header === '巡检合格率'" class="editable-cell">
  37. <el-input-number v-model="aValue" :min="1" :step="1" controls-position="right" size="small"
  38. style="width: 100%;" />
  39. </div>
  40. <div v-else-if="scope.row.rowName === '查获效率' && header === '抽问抽答正确率'" class="editable-cell">
  41. <el-input-number v-model="bValue" :min="1" :step="1" controls-position="right" size="small"
  42. style="width: 100%;" />
  43. </div>
  44. <div v-else-if="scope.row.rowName === '巡检合格率' && header === '查获效率'" class="calculated-cell">
  45. {{ reciprocalA }}
  46. </div>
  47. <div v-else-if="scope.row.rowName === '巡检合格率' && header === '巡检合格率'" class="fixed-cell">
  48. 1
  49. </div>
  50. <div v-else-if="scope.row.rowName === '巡检合格率' && header === '抽问抽答正确率'" class="editable-cell">
  51. <el-input-number v-model="cValue" :min="1" :step="1" controls-position="right" size="small"
  52. style="width: 100%;" />
  53. </div>
  54. <div v-else-if="scope.row.rowName === '抽问抽答正确率' && header === '查获效率'" class="calculated-cell">
  55. {{ reciprocalB }}
  56. </div>
  57. <div v-else-if="scope.row.rowName === '抽问抽答正确率' && header === '巡检合格率'" class="calculated-cell">
  58. {{ reciprocalC }}
  59. </div>
  60. <div v-else-if="scope.row.rowName === '抽问抽答正确率' && header === '抽问抽答正确率'" class="fixed-cell">
  61. 1
  62. </div>
  63. <div v-else>
  64. -
  65. </div>
  66. </template>
  67. </el-table-column>
  68. </el-table>
  69. <div class="matrix-actions" style="margin-bottom: 20px;">
  70. <el-button type="primary" @click="handleSaveMatrixConfig">保存配置</el-button>
  71. </div>
  72. </div>
  73. </el-card>
  74. </div>
  75. </template>
  76. <script setup>
  77. import { ref, reactive, onMounted, computed } from 'vue'
  78. import { ElMessage } from 'element-plus'
  79. import { getMatrixConfig, saveMatrixConfig } from '@/api/performance/performance.js'
  80. // 绩效指标选项
  81. const indicatorOptions = [
  82. { label: '查获效率', value: 'detectionEfficiency' },
  83. { label: '巡检合格率', value: 'inspectionPassRate' },
  84. { label: '抽问抽答正确率', value: 'trainingScore' }
  85. ]
  86. // 选中的指标(默认全选)
  87. const selectedIndicators = ref(['detectionEfficiency', 'inspectionPassRate', 'trainingScore'])
  88. // 矩阵表头
  89. const matrixHeaders = ['查获效率', '巡检合格率', '抽问抽答正确率']
  90. // 矩阵数据(简化版,主要用于显示行名)
  91. const matrixData = reactive([
  92. { rowName: '查获效率' },
  93. { rowName: '巡检合格率' },
  94. { rowName: '抽问抽答正确率' }
  95. ])
  96. // 可编辑的a、b、c值
  97. const aValue = ref(0)
  98. const bValue = ref(0)
  99. const cValue = ref(0)
  100. // 计算值(使用computed实现自动更新)
  101. const reciprocalA = computed(() => `1/${aValue.value}`)
  102. const reciprocalB = computed(() => `1/${bValue.value}`)
  103. const reciprocalC = computed(() => `1/${cValue.value}`)
  104. // 保存绩效矩阵配置
  105. const handleSaveMatrixConfig = async () => {
  106. try {
  107. const params = {
  108. a: aValue.value,
  109. b: bValue.value,
  110. c: cValue.value
  111. }
  112. const response = await saveMatrixConfig(params)
  113. if (response.code === 200) {
  114. ElMessage.success('保存成功')
  115. } else {
  116. ElMessage.error('保存失败:' + response.msg)
  117. }
  118. } catch (error) {
  119. console.error('保存配置异常:', error)
  120. ElMessage.error('保存失败,请重试')
  121. }
  122. }
  123. // 获取绩效矩阵配置
  124. const fetchMatrixConfig = async () => {
  125. try {
  126. const response = await getMatrixConfig({})
  127. if (response.code === 200 && response.data) {
  128. const { paramA, paramB, paramC } = response.data
  129. // 设置从接口返回的a、b、c值
  130. aValue.value = paramA || 0
  131. bValue.value = paramB || 0
  132. cValue.value = paramC || 0
  133. }
  134. } catch (error) {
  135. console.error('获取配置异常:', error)
  136. // 使用默认值
  137. aValue.value = 3
  138. bValue.value = 5
  139. cValue.value = 2
  140. }
  141. }
  142. onMounted(() => {
  143. // 页面加载时获取配置
  144. fetchMatrixConfig()
  145. })
  146. </script>
  147. <style lang="less" scoped>
  148. .app-container {
  149. padding: 20px;
  150. }
  151. .header-section {
  152. margin-bottom: 20px;
  153. .section-title {
  154. margin: 0;
  155. color: #303133;
  156. font-size: 18px;
  157. font-weight: 600;
  158. }
  159. }
  160. .button-group-section {
  161. margin-bottom: 30px;
  162. .indicator-checkbox-group {
  163. display: flex;
  164. gap: 10px;
  165. :deep(.el-checkbox-button) {
  166. .el-checkbox-button__inner {
  167. padding: 12px 20px;
  168. font-size: 14px;
  169. border-radius: 4px;
  170. &:hover {
  171. color: #409EFF;
  172. border-color: #409EFF;
  173. }
  174. }
  175. &.is-checked {
  176. .el-checkbox-button__inner {
  177. background-color: #409EFF;
  178. border-color: #409EFF;
  179. color: #fff;
  180. &:hover {
  181. background-color: #66b1ff;
  182. border-color: #66b1ff;
  183. }
  184. }
  185. }
  186. }
  187. }
  188. }
  189. .default-value-section {
  190. margin: 20px 0;
  191. padding: 15px;
  192. background-color: #f5f7fa;
  193. border-radius: 4px;
  194. border-left: 4px solid #409EFF;
  195. .default-value-text {
  196. margin: 0;
  197. color: #606266;
  198. font-size: 14px;
  199. line-height: 1.5;
  200. }
  201. }
  202. .matrix-section {
  203. .matrix-actions {
  204. margin-top: 20px;
  205. }
  206. .performance-matrix {
  207. :deep(.el-table__header-wrapper) {
  208. th {
  209. background-color: #f5f7fa;
  210. font-weight: 600;
  211. color: #303133;
  212. }
  213. }
  214. :deep(.el-table__body-wrapper) {
  215. td {
  216. .fixed-cell {
  217. color: #303133;
  218. font-weight: 600;
  219. }
  220. .editable-cell {
  221. padding: 4px;
  222. }
  223. .calculated-cell {
  224. color: #409EFF;
  225. font-weight: 500;
  226. }
  227. &:not(:first-child) {
  228. font-weight: 500;
  229. }
  230. }
  231. }
  232. }
  233. }
  234. </style>