GroupMonitorTable.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  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 ? (_.modalTyoe.endsWith('_3') ? 3 : _.modalTyoe.endsWith('_1') ? 1 : 2) : 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. const columnNum = _.modalTyoe ? (_.modalTyoe.endsWith('_3') ? 3 : _.modalTyoe.endsWith('_1') ? 1 : 2) : 2;
  214. if (_.rowIndex % columnNum == 0) {
  215. return { rowSpan: columnNum };
  216. } else {
  217. return { rowSpan: 0 };
  218. }
  219. },
  220. customRender: ({ text, record, index }) => {
  221. return record.index + 1;
  222. },
  223. };
  224. const runDevice = {
  225. title: '风机',
  226. dataIndex: 'runDevice',
  227. width: 80,
  228. align: 'center',
  229. };
  230. columns.value = getTableHeaderColumns(columnsType);
  231. console.log('风机columns------------------>', columnsType);
  232. if (columns.value && columns.value.length < 1) {
  233. columns.value = getTableHeaderColumns(columnsType.split('_')[0] + '_monitor');
  234. }
  235. const strinstallpos = columns.value.find((item) => {
  236. return item.dataIndex === 'strinstallpos' || item.dataIndex === 'strname';
  237. });
  238. if (strinstallpos) {
  239. strinstallpos.customCell = (_, index) => {
  240. debugger;
  241. const columnNum = _.modalTyoe ? (_.modalTyoe.endsWith('_3') ? 3 : _.modalTyoe.endsWith('_1') ? 1 : 2) : 2;
  242. if (_.rowIndex % columnNum == 0) {
  243. return { rowSpan: columnNum };
  244. } else {
  245. return { rowSpan: 0 };
  246. }
  247. };
  248. }
  249. columns.value.forEach((item) => {
  250. if (item.dataIndex === 'strinstallpos' || item.dataIndex === 'strname' || item.dataIndex.endsWith('_merge')) {
  251. item.customCell = (_, index) => {
  252. const columnNum = _.modalTyoe ? (_.modalTyoe.endsWith('_3') ? 3 : _.modalTyoe.endsWith('_1') ? 1 : 2) : 2;
  253. if (_.rowIndex % columnNum == 0) {
  254. return { rowSpan: columnNum };
  255. } else {
  256. return { rowSpan: 0 };
  257. }
  258. };
  259. }
  260. });
  261. columns.value.splice(1, 0, runDevice);
  262. if (props.isShowSelect) {
  263. columns.value = [isCheckColumn, indexColumn, ...columns.value];
  264. } else {
  265. columns.value = [indexColumn, ...columns.value];
  266. }
  267. if (props.isAction) {
  268. columns.value = [
  269. ...columns.value,
  270. {
  271. title: '操作',
  272. dataIndex: 'operation',
  273. width: 120,
  274. align: 'center',
  275. slots: { customRender: 'operation' },
  276. customCell: (_, index) => {
  277. const columnNum = _.modalTyoe ? (_.modalTyoe.endsWith('_3') ? 3 : _.modalTyoe.endsWith('_1') ? 1 : 2) : 2;
  278. if (_.rowIndex % columnNum == 0) {
  279. return { rowSpan: columnNum };
  280. } else {
  281. return { rowSpan: 0 };
  282. }
  283. },
  284. },
  285. ];
  286. }
  287. // columns.value = [...columns.value, ...columns.value]
  288. return columns;
  289. }
  290. watch(
  291. () => {
  292. return props.columnsType;
  293. },
  294. (newVal, oldVal) => {
  295. if (!newVal) return;
  296. setColumns(newVal);
  297. nextTick(() => {
  298. const headEl = document.querySelector(`.zxm-table-thead`);
  299. if (headEl) {
  300. headElHeight.value = headEl.clientHeight;
  301. tableScroll.value = { y: (scrollY || props.scroll.y) - (headElHeight.value - 56), x: 'max-content' };
  302. }
  303. });
  304. },
  305. {
  306. immediate: true,
  307. }
  308. );
  309. watch(
  310. () => {
  311. return props.dataSource;
  312. },
  313. (newVal, oldVal) => {
  314. const list: unknown[] = [];
  315. newVal.forEach((item, index) => {
  316. const data: any = toRaw(item);
  317. const modalTyoe = data.modalTyoe; ///
  318. const resultData1 = {};
  319. const resultData2 = {};
  320. const resultData3 = {};
  321. // 将主风机、备风机的数据进行拆分
  322. columns.value.forEach((column) => {
  323. const columnKey = column.dataIndex;
  324. if (columnKey) {
  325. if (columnKey.startsWith('Fan')) {
  326. const key1 = columnKey.replace('Fan', 'Fan1');
  327. const key2 = columnKey.replace('Fan', 'Fan2');
  328. const key3 = columnKey.replace('Fan', 'Fan3');
  329. if (columnKey.endsWith('_merge')) {
  330. resultData1[columnKey] = data[key1] == 0 || data[key1] == null || data[key1] == undefined ? data[key2] : data[key1] || data[key3];
  331. } else {
  332. if (columnKey.startsWith('FanStartStatus')) {
  333. resultData1[columnKey] = data[key1];
  334. resultData2[columnKey] = data[key2];
  335. resultData3[columnKey] = data[key3];
  336. } else {
  337. resultData1[columnKey] = data['Fan1StartStatus'] == '0' && globalConfig?.simulatedPassword ? '-' : data[key1];
  338. resultData2[columnKey] = data['Fan2StartStatus'] == '0' && globalConfig?.simulatedPassword ? '-' : data[key2];
  339. resultData3[columnKey] = data['Fan3StartStatus'] == '0' && globalConfig?.simulatedPassword ? '-' : data[key3];
  340. }
  341. if (resultData1[columnKey] == undefined && resultData2[columnKey] == undefined) {
  342. resultData1[columnKey] = data[columnKey];
  343. resultData2[columnKey] = data[columnKey];
  344. resultData3[columnKey] = data[columnKey];
  345. }
  346. }
  347. } else if (columnKey.startsWith('fan')) {
  348. const key1 = columnKey.replace('fan', 'fan1');
  349. const key2 = columnKey.replace('fan', 'fan2');
  350. const key3 = columnKey.replace('fan', 'fan3');
  351. if (columnKey.endsWith('_merge')) {
  352. resultData1[columnKey] =
  353. !data[key1] || data[key1] == 0 || data[key1] == null || data[key1] == undefined ? data[key2] : data[key1] || data[key3];
  354. } else {
  355. if (columnKey.startsWith('fanStartStatus')) {
  356. resultData1[columnKey] = data[key1];
  357. resultData2[columnKey] = data[key2];
  358. resultData3[columnKey] = data[key3];
  359. } else {
  360. resultData1[columnKey] = data['fan1StartStatus'] == '0' && globalConfig?.simulatedPassword ? '-' : data[key1];
  361. resultData2[columnKey] = data['fan2StartStatus'] == '0' && globalConfig?.simulatedPassword ? '-' : data[key2];
  362. resultData3[columnKey] = data['fan3StartStatus'] == '0' && globalConfig?.simulatedPassword ? '-' : data[key3];
  363. }
  364. if (resultData1[columnKey] == undefined && resultData2[columnKey] == undefined) {
  365. resultData1[columnKey] = data[columnKey];
  366. resultData2[columnKey] = data[columnKey];
  367. resultData3[columnKey] = data[columnKey];
  368. }
  369. }
  370. } else if (columnKey.endsWith('_merge')) {
  371. resultData1[columnKey] = data[columnKey];
  372. } else {
  373. resultData1[columnKey] = resultData2[columnKey] = resultData3[columnKey] = data[columnKey];
  374. }
  375. }
  376. });
  377. resultData1['deviceID'] = resultData2['deviceID'] = data['deviceID'];
  378. debugger;
  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 && modalTyoe.endsWith('_3')) {
  401. list.push(resultData1, resultData2, resultData3);
  402. } else if (modalTyoe && modalTyoe.endsWith('_1')) {
  403. list.push(resultData1);
  404. } else {
  405. list.push(resultData1, resultData2);
  406. }
  407. });
  408. dataTableSource.value = list;
  409. loading.value = false;
  410. }
  411. );
  412. watch(
  413. () => props.scroll.y,
  414. (newVal) => {
  415. if (newVal) {
  416. scrollY = newVal;
  417. tableScroll.value = { y: newVal - (headElHeight.value - 56), x: 'max-content' };
  418. } else {
  419. tableScroll.value = {};
  420. }
  421. }
  422. );
  423. onMounted(() => {
  424. // 如果是https
  425. // 反之是websocket
  426. });
  427. onUnmounted(() => {});
  428. defineExpose({
  429. setSelectedRowKeys,
  430. });
  431. </script>
  432. <style scoped lang="less">
  433. @ventSpace: zxm;
  434. :deep(.@{ventSpace}-table-body) {
  435. height: auto !important;
  436. &::-webkit-scrollbar {
  437. height: 10px !important;
  438. }
  439. }
  440. :deep(.jeecg-basic-table .@{ventSpace}-table-wrapper .@{ventSpace}-table-title) {
  441. min-height: 0;
  442. }
  443. </style>