HistoryTable.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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. // 使用方法如下:
  23. // 设有历史数据2条,[{ name, forcFan1Temp, forcFan2Temp }, { name, forcFan1Temp, forcFan2Temp }]。
  24. //
  25. // 1、配置设备字段(参考公司端综合设备管理-设备字段管理)
  26. // 以压风机为例,设压风机设备的历史数据编码为forcFan_history。
  27. // 那么字段code中加$的字段将允许动态展示数据,例子如下:
  28. // 显示字段 字段code
  29. // 温度 $Temp
  30. // 安装位置 name
  31. //
  32. // 2、配置数据字典(参考系统管理-数据字典),为上述设备配置子设备
  33. // 同以压风机为例,设压风机子设备字典编码为forcFan_dict,且已经新增到系统中。
  34. // 则字典配置的例子如下:
  35. // 名称 数据值
  36. // 压风机1 forcFan1
  37. // 压风机2 forcFan2
  38. //
  39. // 3、运维人员应配合前端开发人员,使用指定的编码配置内容。
  40. // 同以压风机为例,需使用device-code(forcFan)、dict-code(forcFan_dict)。
  41. //
  42. // 4、其他内容说明
  43. // 同以压风机为例,当子设备没有数据是,此时展示的数据是:
  44. // 温度 安装位置
  45. // 取Temp 取name
  46. // 同以压风机为例,当子设备选择压风机1时,此时展示的数据是:
  47. // 温度 安装位置
  48. // 取forcFan1Temp 取name
  49. import { onMounted, ref, shallowRef } from 'vue';
  50. import { BasicColumn, PaginationProps, BasicTable } from '/@/components/Table';
  51. import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
  52. import { defaultFormProps, defaultPaginationProps, getDefaultSchemas, defaultTableProps } from './history.data';
  53. import { getDeviceList, list } from './history.api';
  54. import { useListPage } from '/@/hooks/system/useListPage';
  55. import { initDictOptions } from '/@/utils/dict';
  56. const props = withDefaults(
  57. defineProps<{
  58. /** 表格项配置,默认由deviceCode获取且联动dictCode,可以覆写,覆写后将不支持联动,参考BaiscTable */
  59. // columns?: BasicColumn[];
  60. /** 表格操作项配置,默认为空,可以覆写 */
  61. // actionColumns?: BasicColumn;
  62. /** 查询表单项配置,默认联动dictCode,可以覆写,覆写后将不支持联动,提供formProps时此项无效,参考BaiscTable */
  63. // schemas?: FormSchema[];
  64. /** 表格分页配置,可以覆写,参考BaiscTable */
  65. pagination?: PaginationProps;
  66. /** 设备编码,该编码用于请求设备信息,示例:forcFan */
  67. deviceCode: string;
  68. /** 字典编码,该编码用于从字典配置中读出设备项,示例:forcFan_dict */
  69. dictCode: string;
  70. /** 字段编码,该编码用于从设备字段配置中读取默认表头信息,示例:forcFan_history */
  71. columnsCode: string;
  72. /** 表格配置,参考BaiscTable,该值会与默认的配置进行浅合并,这里提供的任何配置都是优先的 */
  73. // tableProps?: BasicTableProps;
  74. /** 查询表单配置,参考BaiscTable */
  75. // formProps?: FormProps;
  76. }>(),
  77. {
  78. deviceCode: '',
  79. dictCode: '',
  80. }
  81. );
  82. // 创建表格,此表格目前不具备常用功能,需要初始化后使用(props指定表格配置时除外)
  83. let originColumns: BasicColumn[] = [];
  84. const { tableContext } = useListPage({ tableProps: defaultTableProps });
  85. const [register, { getForm, setLoading, getPaginationRef, setPagination, setProps, setColumns }] = tableContext;
  86. /**
  87. * 初始化表格,该方法将根据参数设定新的表头、表单,如果提供了自定义的表头、表单配置则不作操作。
  88. *
  89. * 之所以将设备相关的信息作参数传入,是因为这样可以确认依赖关系,即需要有设备信息之后再初始化表格。
  90. *
  91. * @param deviceCodes 获取表头所用的编码,从左到右依次尝试,直到找到第一个有表头信息的为止
  92. * @param deviceOptions 设备下拉框对应的选项
  93. */
  94. function initTable(deviceCodes: string[], deviceOptions: any[], dictOptions: any[]) {
  95. const defaultSchemas = getDefaultSchemas(dictOptions, deviceOptions);
  96. for (const code of deviceCodes) {
  97. const cols = getTableHeaderColumns(code);
  98. if (cols.length) {
  99. originColumns = cols;
  100. setColumns(cols);
  101. break;
  102. }
  103. }
  104. setProps({
  105. formConfig: {
  106. ...defaultFormProps,
  107. schemas: defaultSchemas,
  108. },
  109. pagination: props.pagination || defaultPaginationProps,
  110. });
  111. }
  112. /**
  113. * 更新表头,表头默认情况下需要和子设备联动
  114. * @param prefix 子设备的值,即为表头取数据时字段的前缀
  115. */
  116. function updateColumns(prefix: string) {
  117. const cols = originColumns.map((col) => {
  118. const di = col.dataIndex as string;
  119. if (di && di.includes('$')) {
  120. return {
  121. ...col,
  122. dataIndex: di.replace('$', prefix),
  123. };
  124. }
  125. return col;
  126. });
  127. setColumns(cols);
  128. }
  129. // 表格数据相关的字段
  130. const data = shallowRef([]);
  131. /**
  132. * 获取列表的数据
  133. *
  134. * 这些参数确认了依赖关系,即需要有表单数据、设备信息之后再尝试获取表格数据。
  135. *
  136. * @param formData 表格上方的表单数据
  137. * @param deviceCode 设备编码
  138. * @param deviceInfo 设备信息
  139. */
  140. function fetchData(formData: Record<string, unknown>, deviceCode: string, deviceInfo: any) {
  141. setLoading(true);
  142. const pagination = getPaginationRef() as PaginationProps;
  143. return list(deviceCode, deviceInfo, formData, pagination)
  144. .then(({ records, total, current }) => {
  145. setPagination({
  146. current,
  147. total,
  148. });
  149. records.forEach((item) => {
  150. Object.assign(item, item.readData);
  151. });
  152. data.value = records;
  153. })
  154. .finally(() => {
  155. setLoading(false);
  156. });
  157. }
  158. // 设备信息相关的字段
  159. const deviceInfo = ref<Record<string, unknown>>({});
  160. const deviceOptions = ref<Record<string, unknown>[]>([]);
  161. const dictOptions = ref<Record<string, unknown>[]>([]); // 子设备下拉框选项
  162. /**
  163. * 获取设备信息列表,初始化设备信息及设备可选项
  164. */
  165. async function fetchDevice() {
  166. const results = await getDeviceList({ devicetype: props.deviceCode, pageSize: 10000 });
  167. const dicts = await initDictOptions(props.dictCode);
  168. const options = results.map((item) => {
  169. return {
  170. label: item.strinstallpos,
  171. value: item.id || item.deviceID,
  172. deviceType: item.strtype || item.deviceType,
  173. devicekind: item.devicekind,
  174. stationtype: item.stationtype,
  175. };
  176. });
  177. deviceOptions.value = options;
  178. deviceInfo.value = results[0];
  179. dictOptions.value = dicts;
  180. }
  181. /**
  182. * 搜索,核心方法
  183. *
  184. * 该方法获取表单、处理表单数据后尝试获取数据并设置表头
  185. */
  186. async function search() {
  187. const form = getForm();
  188. await form.validate();
  189. const formData = form.getFieldsValue();
  190. deviceInfo.value = deviceOptions.value.find((opt) => {
  191. return opt.value === formData.gdeviceid;
  192. }) as Record<string, unknown>;
  193. const code = (deviceInfo.value.deviceType || props.deviceCode.concat('*')) as string;
  194. await fetchData(formData, code, deviceInfo.value);
  195. updateColumns(formData.deviceNum || '');
  196. }
  197. onMounted(async () => {
  198. await fetchDevice();
  199. initTable([deviceInfo.value.deviceType as string, props.columnsCode], deviceOptions.value, dictOptions.value);
  200. search();
  201. });
  202. </script>
  203. <style scoped lang="less">
  204. @import '/@/design/vent/color.less';
  205. </style>