GroupMonitorTable.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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. <slot name="bodyCell" v-bind="{ column, record }"></slot>
  26. </template>
  27. <template #operation="{ column, record }">
  28. <slot name="action" v-bind="{ column, record }"></slot>
  29. </template>
  30. </a-table>
  31. </a-radio-group>
  32. </div>
  33. </template>
  34. <script lang="ts" setup>
  35. //ts语法
  36. import { toRaw, watch, ref, onMounted, onUnmounted, nextTick, inject } from 'vue';
  37. import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
  38. import { useGlobSetting } from '/@/hooks/setting';
  39. const { sysOrgCode } = useGlobSetting();
  40. const globalConfig = inject('globalConfig');
  41. const props = defineProps({
  42. columnsType: {
  43. type: String,
  44. required: true,
  45. },
  46. dataSource: {
  47. type: Array,
  48. required: true,
  49. },
  50. deviceType: {
  51. type: String,
  52. },
  53. designScope: {
  54. type: String,
  55. },
  56. title: {
  57. type: String,
  58. },
  59. scroll: {
  60. type: Object,
  61. default: () => null,
  62. },
  63. isAction: {
  64. type: Boolean,
  65. default: false,
  66. },
  67. isShowSelect: {
  68. type: Boolean,
  69. default: true,
  70. },
  71. });
  72. const tableRef = ref();
  73. const emits = defineEmits(['selectRow']);
  74. const dataTableSource = ref<any[]>([]);
  75. const loading = ref(true);
  76. const tableScroll = props.scroll.y ? ref({ y: props.scroll.y, x: 'max-content' }) : ref({});
  77. let scrollY = 0;
  78. const columns = ref<any[]>([]);
  79. // 默认初始是第一行
  80. const selectRowIndex = ref(-1);
  81. const headElHeight = ref(0);
  82. const rowClick = (record) => {
  83. return {
  84. onClick: () => {
  85. setSelectedRowKeys(record['deviceID']);
  86. },
  87. };
  88. };
  89. const setSelectedRowKeys = (target) => {
  90. if (Object.prototype.toString.call(target) === '[object String]') {
  91. selectRowIndex.value = target;
  92. emits('selectRow', target);
  93. } else if (Object.prototype.toString.call(target) === '[object Object]') {
  94. const data = target.target.value;
  95. selectRowIndex.value = data;
  96. emits('selectRow', data);
  97. }
  98. };
  99. /** 定义table Columns */
  100. // function setColumns(columnsType) {
  101. // const isCheckColumn = {
  102. // title: '',
  103. // dataIndex: 'isCheck',
  104. // width: 40,
  105. // align: 'center',
  106. // customCell: (_, index) => {
  107. // if (index % 3 == 0) {
  108. // return { rowSpan: 3 };
  109. // } else {
  110. // return { rowSpan: 0 };
  111. // }
  112. // },
  113. // };
  114. // const indexColumn = {
  115. // title: '序号',
  116. // dataIndex: 'key',
  117. // width: 80,
  118. // align: 'center',
  119. // customCell: (_, index) => {
  120. // if (index % 3 == 0) {
  121. // return { rowSpan: 3 };
  122. // } else {
  123. // return { rowSpan: 0 };
  124. // }
  125. // },
  126. // customRender: function ({ index }) {
  127. // return index / 3 + 1;
  128. // },
  129. // };
  130. // const runDevice = {
  131. // title: '风机',
  132. // dataIndex: 'runDevice',
  133. // width: 80,
  134. // align: 'center',
  135. // };
  136. // columns.value = getTableHeaderColumns(columnsType);
  137. // console.log('风机columns------------------>', columnsType);
  138. // if (columns.value && columns.value.length < 1) {
  139. // columns.value = getTableHeaderColumns(columnsType.split('_')[0] + '_monitor');
  140. // }
  141. // const strinstallpos = columns.value.find((item) => {
  142. // return item.dataIndex === 'strinstallpos' || item.dataIndex === 'strname';
  143. // });
  144. // if (strinstallpos) {
  145. // strinstallpos.customCell = (_, index) => {
  146. // if (index % 3 == 0) {
  147. // return { rowSpan: 3 };
  148. // } else {
  149. // return { rowSpan: 0 };
  150. // }
  151. // };
  152. // }
  153. // columns.value.forEach((item) => {
  154. // if (item.dataIndex === 'strinstallpos' || item.dataIndex === 'strname' || item.dataIndex.endsWith('_merge')) {
  155. // item.customCell = (_, index) => {
  156. // if (index % 3 == 0) {
  157. // return { rowSpan: 3 };
  158. // } else {
  159. // return { rowSpan: 0 };
  160. // }
  161. // };
  162. // }
  163. // });
  164. // columns.value.splice(1, 0, runDevice);
  165. // if (props.isShowSelect) {
  166. // columns.value = [isCheckColumn, indexColumn, ...columns.value];
  167. // } else {
  168. // columns.value = [indexColumn, ...columns.value];
  169. // }
  170. // if (props.isAction) {
  171. // columns.value = [
  172. // ...columns.value,
  173. // {
  174. // title: '操作',
  175. // dataIndex: 'operation',
  176. // width: 120,
  177. // align: 'center',
  178. // slots: { customRender: 'operation' },
  179. // customCell: (_, index) => {
  180. // if (index % 3 == 0) {
  181. // return { rowSpan: 3 };
  182. // } else {
  183. // return { rowSpan: 0 };
  184. // }
  185. // },
  186. // },
  187. // ];
  188. // }
  189. // // columns.value = [...columns.value, ...columns.value]
  190. // return columns;
  191. // }
  192. function setColumns(columnsType) {
  193. const isCheckColumn = {
  194. title: '',
  195. dataIndex: 'isCheck',
  196. width: 40,
  197. align: 'center',
  198. customCell: (_, index) => {
  199. const columnNum = _.modalTyoe === 'lijing_3' ? 3 : 2;
  200. if (_.rowIndex % columnNum == 0) {
  201. return { rowSpan: columnNum };
  202. } else {
  203. return { rowSpan: 0 };
  204. }
  205. },
  206. };
  207. const indexColumn = {
  208. title: '序号',
  209. dataIndex: 'key',
  210. width: 80,
  211. align: 'center',
  212. customCell: (_, index) => {
  213. debugger;
  214. const columnNum = _.modalTyoe === 'lijing_3' ? 3 : 2;
  215. if (_.rowIndex % columnNum == 0) {
  216. return { rowSpan: columnNum };
  217. } else {
  218. return { rowSpan: 0 };
  219. }
  220. },
  221. customRender: ({ text, record, index }) => {
  222. const columnNum = record.modalTyoe === 'lijing_3' ? 3 : 2;
  223. return record.index + 1;
  224. },
  225. };
  226. const runDevice = {
  227. title: '风机',
  228. dataIndex: 'runDevice',
  229. width: 80,
  230. align: 'center',
  231. };
  232. columns.value = getTableHeaderColumns(columnsType);
  233. console.log('风机columns------------------>', columnsType);
  234. if (columns.value && columns.value.length < 1) {
  235. columns.value = getTableHeaderColumns(columnsType.split('_')[0] + '_monitor');
  236. }
  237. const strinstallpos = columns.value.find((item) => {
  238. return item.dataIndex === 'strinstallpos' || item.dataIndex === 'strname';
  239. });
  240. if (strinstallpos) {
  241. strinstallpos.customCell = (_, index) => {
  242. const columnNum = _.modalTyoe === 'lijing_3' ? 3 : 2;
  243. if (_.rowIndex % columnNum == 0) {
  244. return { rowSpan: columnNum };
  245. } else {
  246. return { rowSpan: 0 };
  247. }
  248. };
  249. }
  250. columns.value.forEach((item) => {
  251. if (item.dataIndex === 'strinstallpos' || item.dataIndex === 'strname' || item.dataIndex.endsWith('_merge')) {
  252. item.customCell = (_, index) => {
  253. const columnNum = _.modalTyoe === 'lijing_3' ? 3 : 2;
  254. if (_.rowIndex % columnNum == 0) {
  255. return { rowSpan: columnNum };
  256. } else {
  257. return { rowSpan: 0 };
  258. }
  259. };
  260. }
  261. });
  262. columns.value.splice(1, 0, runDevice);
  263. if (props.isShowSelect) {
  264. columns.value = [isCheckColumn, indexColumn, ...columns.value];
  265. } else {
  266. columns.value = [indexColumn, ...columns.value];
  267. }
  268. if (props.isAction) {
  269. columns.value = [
  270. ...columns.value,
  271. {
  272. title: '操作',
  273. dataIndex: 'operation',
  274. width: 120,
  275. align: 'center',
  276. slots: { customRender: 'operation' },
  277. customCell: (_, index) => {
  278. const columnNum = _.modalTyoe === 'lijing_3' ? 3 : 2;
  279. if (_.rowIndex % columnNum == 0) {
  280. return { rowSpan: columnNum };
  281. } else {
  282. return { rowSpan: 0 };
  283. }
  284. },
  285. },
  286. ];
  287. }
  288. // columns.value = [...columns.value, ...columns.value]
  289. return columns;
  290. }
  291. watch(
  292. () => {
  293. return props.columnsType;
  294. },
  295. (newVal, oldVal) => {
  296. if (!newVal) return;
  297. setColumns(newVal);
  298. nextTick(() => {
  299. const headEl = document.querySelector(`.zxm-table-thead`);
  300. if (headEl) {
  301. headElHeight.value = headEl.clientHeight;
  302. tableScroll.value = { y: (scrollY || props.scroll.y) - (headElHeight.value - 56), x: 'max-content' };
  303. }
  304. });
  305. },
  306. {
  307. immediate: true,
  308. }
  309. );
  310. watch(
  311. () => {
  312. return props.dataSource;
  313. },
  314. (newVal, oldVal) => {
  315. const list: unknown[] = [];
  316. newVal.forEach((item, index) => {
  317. const data: any = toRaw(item);
  318. const modalTyoe = data.modalTyoe; ///
  319. const resultData1 = {};
  320. const resultData2 = {};
  321. const resultData3 = {};
  322. // 将主风机、备风机的数据进行拆分
  323. columns.value.forEach((column) => {
  324. const columnKey = column.dataIndex;
  325. if (columnKey) {
  326. if (columnKey.startsWith('Fan')) {
  327. const key1 = columnKey.replace('Fan', 'Fan1');
  328. const key2 = columnKey.replace('Fan', 'Fan2');
  329. const key3 = columnKey.replace('Fan', 'Fan3');
  330. if (columnKey.endsWith('_merge')) {
  331. resultData1[columnKey] = data[key1] == 0 || data[key1] == null || data[key1] == undefined ? data[key2] : data[key1] || data[key3];
  332. } else {
  333. if (columnKey.startsWith('FanStartStatus')) {
  334. resultData1[columnKey] = data[key1];
  335. resultData2[columnKey] = data[key2];
  336. resultData3[columnKey] = data[key3];
  337. } else {
  338. resultData1[columnKey] = data['Fan1StartStatus'] == '0' && globalConfig?.simulatedPassword ? '-' : data[key1];
  339. resultData2[columnKey] = data['Fan2StartStatus'] == '0' && globalConfig?.simulatedPassword ? '-' : data[key2];
  340. resultData3[columnKey] = data['Fan3StartStatus'] == '0' && globalConfig?.simulatedPassword ? '-' : data[key3];
  341. }
  342. if (resultData1[columnKey] == undefined && resultData2[columnKey] == undefined) {
  343. resultData1[columnKey] = data[columnKey];
  344. resultData2[columnKey] = data[columnKey];
  345. resultData3[columnKey] = data[columnKey];
  346. }
  347. }
  348. } else if (columnKey.startsWith('fan')) {
  349. const key1 = columnKey.replace('fan', 'fan1');
  350. const key2 = columnKey.replace('fan', 'fan2');
  351. const key3 = columnKey.replace('fan', 'fan3');
  352. if (columnKey.endsWith('_merge')) {
  353. resultData1[columnKey] =
  354. !data[key1] || data[key1] == 0 || data[key1] == null || data[key1] == undefined ? data[key2] : data[key1] || data[key3];
  355. } else {
  356. if (columnKey.startsWith('fanStartStatus')) {
  357. resultData1[columnKey] = data[key1];
  358. resultData2[columnKey] = data[key2];
  359. resultData3[columnKey] = data[key3];
  360. } else {
  361. resultData1[columnKey] = data['fan1StartStatus'] == '0' && globalConfig?.simulatedPassword ? '-' : data[key1];
  362. resultData2[columnKey] = data['fan2StartStatus'] == '0' && globalConfig?.simulatedPassword ? '-' : data[key2];
  363. resultData3[columnKey] = data['fan3StartStatus'] == '0' && globalConfig?.simulatedPassword ? '-' : data[key3];
  364. }
  365. if (resultData1[columnKey] == undefined && resultData2[columnKey] == undefined) {
  366. resultData1[columnKey] = data[columnKey];
  367. resultData2[columnKey] = data[columnKey];
  368. resultData3[columnKey] = data[columnKey];
  369. }
  370. }
  371. } else if (columnKey.endsWith('_merge')) {
  372. resultData1[columnKey] = data[columnKey];
  373. } else {
  374. resultData1[columnKey] = resultData2[columnKey] = resultData3[columnKey] = data[columnKey];
  375. }
  376. }
  377. });
  378. resultData1['deviceID'] = resultData2['deviceID'] = data['deviceID'];
  379. if (props.columnsType.startsWith('fanlocal') && sysOrgCode !== 'zmhjhzmy') {
  380. resultData1['runDevice'] = '主机';
  381. resultData2['runDevice'] = '备机';
  382. resultData1['rowIndex'] = 0;
  383. resultData2['rowIndex'] = 1;
  384. resultData1['index'] = index;
  385. resultData2['index'] = index;
  386. } else {
  387. resultData1['runDevice'] = '1#风机';
  388. resultData2['runDevice'] = '2#风机';
  389. resultData3['runDevice'] = '3#风机';
  390. resultData1['modalTyoe'] = modalTyoe;
  391. resultData2['modalTyoe'] = modalTyoe;
  392. resultData3['modalTyoe'] = modalTyoe;
  393. resultData1['rowIndex'] = 0;
  394. resultData2['rowIndex'] = 1;
  395. resultData3['rowIndex'] = 2;
  396. resultData1['index'] = index;
  397. resultData2['index'] = index;
  398. resultData3['index'] = index;
  399. }
  400. if (modalTyoe === 'lijing_3') {
  401. list.push(resultData1, resultData2, resultData3);
  402. } else {
  403. list.push(resultData1, resultData2);
  404. }
  405. });
  406. dataTableSource.value = list;
  407. loading.value = false;
  408. }
  409. );
  410. watch(
  411. () => props.scroll.y,
  412. (newVal) => {
  413. if (newVal) {
  414. scrollY = newVal;
  415. tableScroll.value = { y: newVal - (headElHeight.value - 56), x: 'max-content' };
  416. } else {
  417. tableScroll.value = {};
  418. }
  419. }
  420. );
  421. onMounted(() => {
  422. // 如果是https
  423. // 反之是websocket
  424. });
  425. onUnmounted(() => {});
  426. defineExpose({
  427. setSelectedRowKeys,
  428. });
  429. </script>
  430. <style scoped lang="less">
  431. @ventSpace: zxm;
  432. :deep(.@{ventSpace}-table-body) {
  433. height: auto !important;
  434. &::-webkit-scrollbar {
  435. height: 10px !important;
  436. }
  437. }
  438. :deep(.jeecg-basic-table .@{ventSpace}-table-wrapper .@{ventSpace}-table-title) {
  439. min-height: 0;
  440. }
  441. </style>