HistoryTable.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <template>
  2. <BasicTable ref="historyTable" @register="register" :data-source="data">
  3. <template #bodyCell="{ column, record }">
  4. <a-tag v-if="column.dataIndex === 'warnFlag'" :color="record.warnFlag == '0' ? 'green' : 'red'">
  5. {{ record.warnFlag == '0' ? '正常' : '报警' }}
  6. </a-tag>
  7. <a-tag v-if="column.dataIndex === 'netStatus'" :color="record.netStatus == '0' ? '#f00' : 'green'">
  8. {{ record.netStatus == '0' ? '断开' : '连接' }}
  9. </a-tag>
  10. </template>
  11. <template #form-submitBefore>
  12. <a-button type="primary" preIcon="ant-design:search-outlined" @click="search">查询</a-button>
  13. </template>
  14. </BasicTable>
  15. </template>
  16. <script lang="ts" setup>
  17. // 场景类历史数据公共组件!
  18. // 用于服务场景类历史数据业务,这类数据通常由一条数据返回多个子设备的信息,例如:{ forcFan1Temp, forcFan2Temp };
  19. // 而此组件可以将这些数据分类,例如:表格只有 温度 一列,但可以根据所选的子设备展示不同的数据;
  20. // 综上所述,此组件在基础的历史数据组件上添加了子设备下拉框(由字典驱动),用户选择子设备后表头将动态调整以适配数据展示;
  21. // 使用方法如下:
  22. // 设有历史数据2条,[{ name, forcFan1Temp, forcFan2Temp }, { name, forcFan1Temp, forcFan2Temp }]。
  23. // 1、配置设备字段(通常是综合管理-设备字段管理),加$的字段将允许动态展示数据。如 name-名称,$Temp-温度。
  24. // 2、配置数据字典(通常是设置-数据字典),为上述设备的子设备添加编码。如 压风机1-forcFan1,压风机2-forcFan2。
  25. // 3、配合前端开发人员开发,调用该组件并使用上面定好的device-code(设备字段)、dict-code(数据字典)。
  26. // 4、测试结果,子设备选择 压风机1 时,表格会读取 name、forcFan1Temp 作展示。
  27. import { onMounted, ref, shallowRef } from 'vue';
  28. import { BasicColumn, PaginationProps, BasicTable } from '/@/components/Table';
  29. import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
  30. import { defaultFormProps, defaultPaginationProps, getDefaultSchemas, defaultTableProps } from './history.data';
  31. import { getDeviceList, list } from './history.api';
  32. import { useListPage } from '/@/hooks/system/useListPage';
  33. import { initDictOptions } from '/@/utils/dict';
  34. const props = withDefaults(
  35. defineProps<{
  36. /** 表格项配置,默认由deviceCode获取且联动dictCode,可以覆写,覆写后将不支持联动,参考BaiscTable */
  37. // columns?: BasicColumn[];
  38. /** 表格操作项配置,默认为空,可以覆写 */
  39. // actionColumns?: BasicColumn;
  40. /** 查询表单项配置,默认联动dictCode,可以覆写,覆写后将不支持联动,提供formProps时此项无效,参考BaiscTable */
  41. // schemas?: FormSchema[];
  42. /** 表格分页配置,可以覆写,参考BaiscTable */
  43. pagination?: PaginationProps;
  44. /** 设备编码,该编码用于从字段/点表配置中读出默认表头,示例:forcFan */
  45. deviceCode: string;
  46. /** 字典编码,该编码用于从字典配置中读出设备项,示例:forcFan_dict */
  47. dictCode: string;
  48. /** 表格配置,参考BaiscTable,该值会与默认的配置进行浅合并,这里提供的任何配置都是优先的 */
  49. // tableProps?: BasicTableProps;
  50. /** 查询表单配置,参考BaiscTable */
  51. // formProps?: FormProps;
  52. }>(),
  53. {
  54. deviceCode: '',
  55. dictCode: '',
  56. }
  57. );
  58. // 创建表格,此表格目前不具备常用功能,需要初始化后使用(props指定表格配置时除外)
  59. let originColumns: BasicColumn[] = [];
  60. const { tableContext } = useListPage({ tableProps: defaultTableProps });
  61. const [register, { getForm, setLoading, getPaginationRef, setPagination, setProps, setColumns }] = tableContext;
  62. /**
  63. * 初始化表格,该方法将根据参数设定新的表头、表单,如果提供了自定义的表头、表单配置则不作操作。
  64. *
  65. * 之所以将设备相关的信息作参数传入,是因为这样可以确认依赖关系,即需要有设备信息之后再初始化表格。
  66. *
  67. * @param deviceCodes 获取表头所用的编码,从左到右依次尝试,直到找到第一个有表头信息的为止
  68. * @param deviceOptions 设备下拉框对应的选项
  69. */
  70. function initTable(deviceCodes: string[], deviceOptions: any[], dictOptions: any[]) {
  71. const defaultSchemas = getDefaultSchemas(dictOptions, deviceOptions);
  72. for (const code of deviceCodes) {
  73. const cols = getTableHeaderColumns(code);
  74. if (cols.length) {
  75. originColumns = cols;
  76. setColumns(cols);
  77. break;
  78. }
  79. }
  80. setProps({
  81. formConfig: {
  82. ...defaultFormProps,
  83. schemas: defaultSchemas,
  84. },
  85. pagination: props.pagination || defaultPaginationProps,
  86. });
  87. }
  88. /**
  89. * 更新表头,表头默认情况下需要和子设备联动
  90. * @param prefix 子设备的值,即为表头取数据时字段的前缀
  91. */
  92. function updateColumns(prefix: string) {
  93. const cols = originColumns.map((col) => {
  94. const di = col.dataIndex as string;
  95. if (di && di.includes('$')) {
  96. return {
  97. ...col,
  98. dataIndex: di.replace('$', prefix),
  99. };
  100. }
  101. return col;
  102. });
  103. setColumns(cols);
  104. }
  105. // 表格数据相关的字段
  106. const data = shallowRef([]);
  107. /**
  108. * 获取列表的数据
  109. *
  110. * 这些参数确认了依赖关系,即需要有表单数据、设备信息之后再尝试获取表格数据。
  111. *
  112. * @param formData 表格上方的表单数据
  113. * @param deviceCode 设备编码
  114. * @param deviceInfo 设备信息
  115. */
  116. function fetchData(formData: Record<string, unknown>, deviceCode: string, deviceInfo: any) {
  117. setLoading(true);
  118. const pagination = getPaginationRef() as PaginationProps;
  119. return list(deviceCode, deviceInfo, formData, pagination)
  120. .then(({ records, total, current }) => {
  121. setPagination({
  122. current,
  123. total,
  124. });
  125. records.forEach((item) => {
  126. Object.assign(item, item.readData);
  127. });
  128. data.value = records;
  129. })
  130. .finally(() => {
  131. setLoading(false);
  132. });
  133. }
  134. // 设备信息相关的字段
  135. const deviceInfo = ref<Record<string, unknown>>({});
  136. const deviceOptions = ref<Record<string, unknown>[]>([]);
  137. const dictOptions = ref<Record<string, unknown>[]>([]); // 子设备下拉框选项
  138. /**
  139. * 获取设备信息列表,初始化设备信息及设备可选项
  140. */
  141. async function fetchDevice() {
  142. const results = await getDeviceList({ devicetype: props.deviceCode, pageSize: 10000 });
  143. const dicts = await initDictOptions(props.dictCode);
  144. const options = results.map((item) => {
  145. return {
  146. label: item.strinstallpos,
  147. value: item.id || item.deviceID,
  148. deviceType: item.strtype || item.deviceType,
  149. devicekind: item.devicekind,
  150. stationtype: item.stationtype,
  151. };
  152. });
  153. deviceOptions.value = options;
  154. deviceInfo.value = results[0];
  155. dictOptions.value = dicts;
  156. }
  157. /**
  158. * 搜索,核心方法
  159. *
  160. * 该方法获取表单、处理表单数据后尝试获取数据并设置表头
  161. */
  162. async function search() {
  163. const form = getForm();
  164. await form.validate();
  165. const formData = form.getFieldsValue();
  166. deviceInfo.value = deviceOptions.value.find((opt) => {
  167. return opt.value === formData.gdeviceid;
  168. }) as Record<string, unknown>;
  169. const code = (deviceInfo.value.deviceType || props.deviceCode.concat('*')) as string;
  170. await fetchData(formData, code, deviceInfo.value);
  171. updateColumns(formData.deviceNum || '');
  172. }
  173. onMounted(async () => {
  174. await fetchDevice();
  175. initTable([deviceInfo.value.deviceType as string, props.deviceCode.concat('_history')], deviceOptions.value, dictOptions.value);
  176. search();
  177. });
  178. </script>
  179. <style scoped lang="less">
  180. @import '/@/design/vent/color.less';
  181. </style>