CockpitHealthTable.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. <template>
  2. <div class="cockpit-health-table">
  3. <h3 class="cockpit-section-title">健康数据信息</h3>
  4. <div
  5. class="cockpit-scroll-table cockpit-table-block cockpit-unified-table cockpit-unified-table--health"
  6. >
  7. <p
  8. class="titleYC cockpit-unified-table-head cockpit-unified-table-head--health"
  9. >
  10. <span>风场名称</span>
  11. <span
  12. v-for="col in sortableCols"
  13. :key="col.prop"
  14. class="cockpit-sortable-th"
  15. :class="{ 'is-active': sortConfig.prop === col.prop }"
  16. @click="toggleSort(col.prop)"
  17. >
  18. {{ col.label }}
  19. <i
  20. class="cockpit-sort-icon"
  21. :class="getSortIconClass(col.prop)"
  22. />
  23. </span>
  24. </p>
  25. <Tabroll
  26. :table-data="displayTableData"
  27. :shujuloading="loading"
  28. :columns="columns"
  29. :column-widths="columnWidths"
  30. :max-height="bodyHeight"
  31. link-column="fieldName"
  32. @link-click="handleFieldNavigate"
  33. />
  34. </div>
  35. </div>
  36. </template>
  37. <script>
  38. import { healthTableColumns } from "./cockpitHealthData";
  39. import { COCKPIT_TABLE_BODY_HEIGHT } from "./cockpitTableMetrics";
  40. import Tabroll from "./tabroll.vue";
  41. import { navigateToHealthDashboard } from "./cockpitFieldNavigate";
  42. export default {
  43. name: "CockpitHealthTable",
  44. components: { Tabroll },
  45. props: {
  46. tableData: { type: Array, default: () => [] },
  47. loading: { type: Boolean, default: false },
  48. bodyHeight: { type: Number, default: COCKPIT_TABLE_BODY_HEIGHT },
  49. datatime: { type: String, default: "" },
  50. sortConfig: {
  51. type: Object,
  52. default: () => ({ prop: "", order: "descending" }),
  53. },
  54. },
  55. data() {
  56. return {
  57. columns: healthTableColumns.map(({ prop }) => ({ prop })),
  58. columnWidths: {
  59. fieldName: "38%",
  60. excellent: "15%",
  61. good: "15%",
  62. medium: "16%",
  63. poor: "16%",
  64. },
  65. countFields: ["excellent", "good", "medium", "poor"],
  66. sortableCols: [
  67. { prop: "excellent", label: "优" },
  68. { prop: "good", label: "良" },
  69. { prop: "medium", label: "中" },
  70. { prop: "poor", label: "差" },
  71. ],
  72. };
  73. },
  74. computed: {
  75. displayTableData() {
  76. return (this.tableData || []).map((row) => {
  77. const next = { ...row };
  78. this.countFields.forEach((key) => {
  79. const value = next[key];
  80. if (value !== null && value !== undefined && value !== "") {
  81. next[key] = `${value}台`;
  82. }
  83. });
  84. return next;
  85. });
  86. },
  87. },
  88. methods: {
  89. toggleSort(prop) {
  90. const current = this.sortConfig || {};
  91. let order = "descending";
  92. if (current.prop === prop) {
  93. order = current.order === "descending" ? "ascending" : "descending";
  94. }
  95. this.$emit("sort-change", { prop, order });
  96. },
  97. getSortIconClass(prop) {
  98. if (this.sortConfig.prop !== prop) return "el-icon-d-caret";
  99. return this.sortConfig.order === "ascending"
  100. ? "el-icon-caret-top"
  101. : "el-icon-caret-bottom";
  102. },
  103. handleFieldNavigate(row) {
  104. navigateToHealthDashboard(this.$router, this.$store, {
  105. fieldCode: row?.fieldCode,
  106. datatime: this.datatime,
  107. });
  108. },
  109. },
  110. };
  111. </script>
  112. <style lang="scss" scoped>
  113. .cockpit-health-table {
  114. width: 100%;
  115. }
  116. .cockpit-health-table .cockpit-section-title {
  117. margin: 0 0 8px;
  118. padding: 0;
  119. border-bottom: none;
  120. font-size: 14px;
  121. font-weight: 600;
  122. }
  123. .cockpit-sortable-th {
  124. cursor: pointer;
  125. user-select: none;
  126. display: inline-flex;
  127. align-items: center;
  128. gap: 2px;
  129. &:hover {
  130. color: var(--cockpit-accent, #409eff);
  131. }
  132. &.is-active {
  133. color: var(--cockpit-accent, #409eff);
  134. }
  135. }
  136. .cockpit-sort-icon {
  137. font-size: 12px;
  138. opacity: 0.6;
  139. .is-active & {
  140. opacity: 1;
  141. }
  142. }
  143. </style>