GroupMonitorTable.vue 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. <template>
  2. <div class="vent-table">
  3. <a-radio-group v-model:value="selectRowIndex" @change="setSelectedRowKeys" style="width: 100%">
  4. <a-table
  5. :columns="columns"
  6. :pagination="false"
  7. :data-source="dataTableSource"
  8. ref="tableRef"
  9. bordered
  10. style="margin-top: 5px"
  11. :scroll="tableScroll"
  12. :selectType="'radio'"
  13. :customRow="rowClick"
  14. >
  15. <template #bodyCell="{ column, record }">
  16. <template v-if="column.dataIndex === 'isCheck'">
  17. <a-radio :value="record.deviceID" />
  18. </template>
  19. <a-tag v-if="column.dataIndex === 'warnFlag'" :color="record.warnFlag == 0 ? 'green' : 'red'">{{
  20. record.warnFlag == 0 ? '正常' : '报警'
  21. }}</a-tag>
  22. <a-tag v-if="column.dataIndex === 'netStatus'" :color="record.netStatus == '0' ? '#f00' : 'green'">{{
  23. record.netStatus == '0' ? '断开' : '连接'
  24. }}</a-tag>
  25. </template>
  26. <template #operation="{ column, record }">
  27. <slot name="action" v-bind="{ column, record }"></slot>
  28. </template>
  29. </a-table>
  30. </a-radio-group>
  31. </div>
  32. </template>
  33. <script lang="ts" setup>
  34. //ts语法
  35. import { toRaw, watch, ref, onMounted, onUnmounted, nextTick } from 'vue';
  36. import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
  37. const props = defineProps({
  38. columnsType: {
  39. type: String,
  40. required: true,
  41. },
  42. dataSource: {
  43. type: Array,
  44. required: true,
  45. },
  46. deviceType: {
  47. type: String,
  48. },
  49. designScope: {
  50. type: String,
  51. },
  52. title: {
  53. type: String,
  54. },
  55. scroll: {
  56. type: Object,
  57. default: () => null,
  58. },
  59. isAction: {
  60. type: Boolean,
  61. default: false,
  62. },
  63. isShowSelect: {
  64. type: Boolean,
  65. default: true,
  66. },
  67. });
  68. const tableRef = ref();
  69. const emits = defineEmits(['selectRow']);
  70. const dataTableSource = ref<any[]>([]);
  71. const loading = ref(true);
  72. const tableScroll = props.scroll.y ? ref({ y: props.scroll.y, x: 'max-content' }) : ref({});
  73. let scrollY = 0;
  74. const columns = ref<any[]>([]);
  75. // 默认初始是第一行
  76. const selectRowIndex = ref(-1);
  77. const headElHeight = ref(0);
  78. const rowClick = (record) => {
  79. return {
  80. onClick: () => {
  81. setSelectedRowKeys(record['deviceID']);
  82. },
  83. };
  84. };
  85. const setSelectedRowKeys = (target) => {
  86. if (Object.prototype.toString.call(target) === '[object String]') {
  87. selectRowIndex.value = target;
  88. emits('selectRow', target);
  89. } else if (Object.prototype.toString.call(target) === '[object Object]') {
  90. const data = target.target.value;
  91. selectRowIndex.value = data;
  92. emits('selectRow', data);
  93. }
  94. };
  95. /** 定义table Columns */
  96. function setColumns(columnsType) {
  97. const isCheckColumn = {
  98. title: '',
  99. dataIndex: 'isCheck',
  100. width: 40,
  101. align: 'center',
  102. customCell: (_, index) => {
  103. if (index % 2 == 0) {
  104. return { rowSpan: 2 };
  105. } else {
  106. return { rowSpan: 0 };
  107. }
  108. },
  109. };
  110. const indexColumn = {
  111. title: '序号',
  112. dataIndex: 'key',
  113. width: 120,
  114. align: 'center',
  115. customCell: (_, index) => {
  116. if (index % 2 == 0) {
  117. return { rowSpan: 2 };
  118. } else {
  119. return { rowSpan: 0 };
  120. }
  121. },
  122. customRender: function ({ index }) {
  123. return index / 2 + 1;
  124. },
  125. };
  126. const runDevice = {
  127. title: '运行风机',
  128. dataIndex: 'runDevice',
  129. width: 80,
  130. align: 'center',
  131. };
  132. columns.value = getTableHeaderColumns(columnsType);
  133. console.log('风机columns------------------>', columnsType);
  134. if (columns.value && columns.value.length < 1) {
  135. columns.value = getTableHeaderColumns(columnsType.split('_')[0] + '_monitor');
  136. }
  137. const strinstallpos = columns.value.find((item) => {
  138. return item.dataIndex === 'strinstallpos' || item.dataIndex === 'strname';
  139. });
  140. if (strinstallpos) {
  141. strinstallpos.customCell = (_, index) => {
  142. if (index % 2 == 0) {
  143. return { rowSpan: 2 };
  144. } else {
  145. return { rowSpan: 0 };
  146. }
  147. };
  148. }
  149. columns.value.forEach((item) => {
  150. if (item.dataIndex === 'strinstallpos' || item.dataIndex === 'strname' || item.dataIndex.endsWith('_merge')) {
  151. item.customCell = (_, index) => {
  152. if (index % 2 == 0) {
  153. return { rowSpan: 2 };
  154. } else {
  155. return { rowSpan: 0 };
  156. }
  157. };
  158. }
  159. });
  160. columns.value.splice(1, 0, runDevice);
  161. if (props.isShowSelect) {
  162. columns.value = [isCheckColumn, ...columns.value];
  163. } else {
  164. columns.value = [indexColumn, ...columns.value];
  165. }
  166. if (props.isAction) {
  167. columns.value = [
  168. ...columns.value,
  169. {
  170. title: '操作',
  171. dataIndex: 'operation',
  172. width: 120,
  173. align: 'center',
  174. slots: { customRender: 'operation' },
  175. customCell: (_, index) => {
  176. if (index % 2 == 0) {
  177. return { rowSpan: 2 };
  178. } else {
  179. return { rowSpan: 0 };
  180. }
  181. },
  182. },
  183. ];
  184. }
  185. // columns.value = [...columns.value, ...columns.value]
  186. return columns;
  187. }
  188. watch(
  189. () => {
  190. return props.columnsType;
  191. },
  192. (newVal, oldVal) => {
  193. if (!newVal) return;
  194. setColumns(newVal);
  195. nextTick(() => {
  196. const headEl = document.querySelector(`.zxm-table-thead`);
  197. if (headEl) {
  198. headElHeight.value = headEl.clientHeight;
  199. tableScroll.value = { y: (scrollY || props.scroll.y) - (headElHeight.value - 56), x: 'max-content' };
  200. }
  201. });
  202. },
  203. {
  204. immediate: true,
  205. }
  206. );
  207. watch(
  208. () => {
  209. return props.dataSource;
  210. },
  211. (newVal, oldVal) => {
  212. const list: unknown[] = [];
  213. newVal.forEach((item) => {
  214. const data: any = toRaw(item);
  215. const resultData1 = {};
  216. const resultData2 = {};
  217. // 将主风机、备风机的数据进行拆分
  218. columns.value.forEach((column) => {
  219. const columnKey = column.dataIndex;
  220. if (columnKey) {
  221. if (columnKey.startsWith('Fan')) {
  222. const key1 = columnKey.replace('Fan', 'Fan1');
  223. const key2 = columnKey.replace('Fan', 'Fan2');
  224. if (columnKey.endsWith('_merge')) {
  225. resultData1[columnKey] = data[key1] == 0 || data[key1] == null || data[key1] == undefined ? data[key2] : data[key1];
  226. } else {
  227. resultData1[columnKey] = data[key1];
  228. resultData2[columnKey] = data[key2];
  229. if (resultData1[columnKey] == undefined && resultData2[columnKey] == undefined) {
  230. resultData1[columnKey] = data[columnKey];
  231. resultData2[columnKey] = data[columnKey];
  232. }
  233. }
  234. } else if (columnKey.startsWith('fan')) {
  235. const key1 = columnKey.replace('fan', 'fan1');
  236. const key2 = columnKey.replace('fan', 'fan2');
  237. if (columnKey.endsWith('_merge')) {
  238. resultData1[columnKey] = !data[key1] || data[key1] == 0 || data[key1] == null || data[key1] == undefined ? data[key2] : data[key1];
  239. } else {
  240. resultData1[columnKey] = data[key1];
  241. resultData2[columnKey] = data[key2];
  242. if (resultData1[columnKey] == undefined && resultData2[columnKey] == undefined) {
  243. resultData1[columnKey] = data[columnKey];
  244. resultData2[columnKey] = data[columnKey];
  245. }
  246. }
  247. } else if (columnKey.endsWith('_merge')) {
  248. resultData1[columnKey] = data[columnKey];
  249. } else {
  250. resultData1[columnKey] = resultData2[columnKey] = data[columnKey];
  251. }
  252. }
  253. });
  254. resultData1['deviceID'] = resultData2['deviceID'] = data['deviceID'];
  255. if (props.columnsType.startsWith('fanlocal')) {
  256. resultData1['runDevice'] = '主机';
  257. resultData2['runDevice'] = '备机';
  258. } else {
  259. resultData1['runDevice'] = '1#风机';
  260. resultData2['runDevice'] = '2#风机';
  261. }
  262. list.push(resultData1, resultData2);
  263. });
  264. // if (oldVal.length < 1 && selectRowIndex.value == -1) {
  265. // // 第一次
  266. // setSelectedRowKeys(list[0]['deviceID']);
  267. // }
  268. dataTableSource.value = list;
  269. loading.value = false;
  270. }
  271. );
  272. watch(
  273. () => props.scroll.y,
  274. (newVal) => {
  275. if (newVal) {
  276. scrollY = newVal;
  277. tableScroll.value = { y: newVal - (headElHeight.value - 56), x: 'max-content' };
  278. } else {
  279. tableScroll.value = {};
  280. }
  281. }
  282. );
  283. onMounted(() => {
  284. // 如果是https
  285. // 反之是websocket
  286. });
  287. onUnmounted(() => {});
  288. defineExpose({
  289. setSelectedRowKeys,
  290. });
  291. </script>
  292. <style scoped lang="less">
  293. @ventSpace: zxm;
  294. :deep(.@{ventSpace}-table-body) {
  295. height: auto !important;
  296. &::-webkit-scrollbar {
  297. height: 5px !important;
  298. }
  299. }
  300. :deep(.jeecg-basic-table .@{ventSpace}-table-wrapper .@{ventSpace}-table-title) {
  301. min-height: 0;
  302. }
  303. </style>