GroupMonitorTable.vue 10.0 KB

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