DeviceEcharts.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. <template>
  2. <div class="charts-container">
  3. <a-select ref="select" v-model:value="chartsType" size="small" style="position: absolute; z-index: 99; top: 2px; left: 2px; width: 98px">
  4. <!-- <a-select-option value="listMonitor">实时监测</a-select-option> -->
  5. <a-select-option value="history">历史记录</a-select-option>
  6. <a-select-option value="detail">详情监测</a-select-option>
  7. </a-select>
  8. <!-- <div class="charts-box" v-if="chartsType === 'listMonitor'" style="position: absolute; top: 20px">
  9. <BarAndLine
  10. :chartsColumnsType="chartsColumnsType"
  11. :xAxisPropType="xAxisPropType"
  12. :dataSource="dataSource"
  13. height="100%"
  14. chartsType="listMonitor"
  15. :option="echartsOption"
  16. :chartsColumns="chartsColumns"
  17. />
  18. </div> -->
  19. <div class="charts-box" v-if="chartsType === 'detail' && deviceListApi">
  20. <Select
  21. :options="options"
  22. :fieldNames="{ label: 'strname', value: 'deviceID' }"
  23. v-model:value="deviceId"
  24. placeholder="请选择查看的设备"
  25. size="small"
  26. style="position: absolute; z-index: 99; left: 102px; width: 150px; top: 2px"
  27. />
  28. <BarAndLine
  29. :chartsColumnsType="chartsColumnsType"
  30. :xAxisPropType="resultXAxisPropType"
  31. :dataSource="detailDataSource"
  32. height="100%"
  33. :option="echartsOption2"
  34. chartsType="detail"
  35. :chartsColumns="chartsColumns"
  36. />
  37. </div>
  38. <div class="charts-box" v-else-if="chartsType === 'history'">
  39. <Select
  40. :options="options"
  41. :fieldNames="{ label: 'strname', value: 'deviceID' }"
  42. v-model:value="deviceId"
  43. placeholder="请选择查看的设备"
  44. size="small"
  45. style="position: absolute; z-index: 99; left: 102px; width: 150px; top: 2px"
  46. />
  47. <template v-if="globalConfig.History_Type == 'vent'">
  48. <a-date-picker
  49. v-model:value="historyParams.ttime_begin"
  50. valueFormat="YYYY-MM-DD HH:mm:ss"
  51. placeholder="请选择开始日期"
  52. size="small"
  53. :showTime="true"
  54. style="position: absolute; z-index: 99; left: 254px; width: 170px; top: 2px"
  55. />
  56. <a-date-picker
  57. v-model:value="historyParams.ttime_end"
  58. valueFormat="YYYY-MM-DD HH:mm:ss"
  59. placeholder="请选择结束日期"
  60. size="small"
  61. :showTime="true"
  62. style="position: absolute; z-index: 99; left: 426px; width: 170px; top: 2px"
  63. />
  64. <a-select
  65. ref="select"
  66. v-model:value="historyParams.skip"
  67. placeholder="请选择间隔时间"
  68. size="small"
  69. style="position: absolute; z-index: 99; top: 2px; left: 598px; width: 150px"
  70. >
  71. <a-select-option value="1">1秒</a-select-option>
  72. <a-select-option value="2">5秒</a-select-option>
  73. <a-select-option value="3">10秒</a-select-option>
  74. <a-select-option value="4">30分钟</a-select-option>
  75. <a-select-option value="5">1分钟</a-select-option>
  76. <a-select-option value="6">10分钟</a-select-option>
  77. <a-select-option value="7">30分钟</a-select-option>
  78. <a-select-option value="8">1小时</a-select-option>
  79. </a-select>
  80. </template>
  81. <template v-else>
  82. <a-date-picker
  83. v-model:value="historyParams.ttime_begin"
  84. valueFormat="YYYY-MM-DD HH:mm:ss"
  85. placeholder="开始时间"
  86. size="small"
  87. :showTime="true"
  88. style="position: absolute; z-index: 99; left: 254px; width: 170px; top: 2px"
  89. />
  90. <a-date-picker
  91. v-model:value="historyParams.ttime_end"
  92. valueFormat="YYYY-MM-DD HH:mm:ss"
  93. placeholder="结束时间"
  94. size="small"
  95. :showTime="true"
  96. style="position: absolute; z-index: 99; left: 426px; width: 170px; top: 2px"
  97. />
  98. <a-select
  99. ref="select"
  100. v-model:value="historyParams.interval"
  101. placeholder="请选择间隔时间"
  102. size="small"
  103. style="position: absolute; z-index: 99; top: 2px; left: 598px; width: 150px"
  104. >
  105. <a-select-option value="1s">1秒</a-select-option>
  106. <a-select-option value="5s">5秒</a-select-option>
  107. <a-select-option value="10s">10秒</a-select-option>
  108. <a-select-option value="30s">30秒</a-select-option>
  109. <a-select-option value="1m">1分钟</a-select-option>
  110. <a-select-option value="10m">5分钟</a-select-option>
  111. <a-select-option value="30m">10分钟</a-select-option>
  112. <a-select-option value="1h">1小时</a-select-option>
  113. </a-select>
  114. </template>
  115. <Pagination
  116. size="small"
  117. v-model:current="currentPage"
  118. v-model:page-size="pageSize"
  119. :total="total"
  120. :show-total="(total) => `共 ${total} 条`"
  121. style="position: absolute; z-index: 99; top: 2px; right: 30px"
  122. />
  123. <BarAndLine
  124. :chartsColumnsType="chartsColumnsType"
  125. :xAxisPropType="resultXAxisPropType"
  126. :dataSource="resultDataSource"
  127. height="100%"
  128. :option="echartsOption1"
  129. chartsType="history"
  130. style="margin-top: 20px"
  131. :chartsColumns="chartsColumns"
  132. />
  133. </div>
  134. </div>
  135. </template>
  136. <script lang="ts">
  137. import { ref, defineComponent, watch, reactive, onMounted, watchEffect, inject } from 'vue';
  138. import BarAndLine from '/@/components/chart/BarAndLine.vue';
  139. import dayjs from 'dayjs';
  140. import { defHttp } from '/@/utils/http/axios';
  141. import { Select, Pagination } from 'ant-design-vue';
  142. export default defineComponent({
  143. name: 'DeviceEcharts',
  144. components: { BarAndLine, Select, Pagination },
  145. props: {
  146. chartsColumns: {
  147. type: Array,
  148. default: () => [],
  149. },
  150. chartsColumnsHistory: {
  151. type: Array,
  152. default: () => [],
  153. },
  154. chartsColumnsType: {
  155. type: String,
  156. required: true,
  157. },
  158. dataSource: {
  159. type: Array,
  160. default: () => [],
  161. },
  162. deviceListApi: {
  163. type: Function,
  164. required: true,
  165. },
  166. deviceType: {
  167. type: String,
  168. required: true,
  169. },
  170. option: {
  171. type: Object,
  172. default: () => ({}),
  173. },
  174. xAxisPropType: {
  175. type: String,
  176. required: true,
  177. },
  178. },
  179. setup(props) {
  180. const globalConfig = inject('globalConfig');
  181. const stationType = ref('plc1');
  182. let historyList;
  183. // if (globalConfig.History_Type == 'vent') {
  184. // historyList = (params) => defHttp.get({ url: '/safety/ventanalyMonitorData/listdays', params });
  185. // } else {
  186. // historyList = (params) => defHttp.post({ url: '/monitor/history/getHistoryData', params });
  187. // }
  188. const chartsType = ref('history');
  189. const deviceId = ref('');
  190. const options = ref([]);
  191. const historyParams = reactive({
  192. ttime_begin: dayjs().startOf('date').format('YYYY-MM-DD HH:mm:ss').toString(),
  193. ttime_end: dayjs().format('YYYY-MM-DD HH:mm:ss').toString(),
  194. skip: '8',
  195. interval: '1h',
  196. });
  197. const resultXAxisPropType = ref('');
  198. const resultDataSource = ref<any[]>([]);
  199. const detailDataSource = ref<any[]>([]);
  200. const currentPage = ref<number>(1);
  201. const pageSize = ref<number>(20);
  202. const total = ref(0);
  203. const echartsOption = {
  204. grid: {
  205. top: '60px',
  206. left: '10px',
  207. right: props.chartsColumns.length * 15 + 'px',
  208. bottom: '5%',
  209. containLabel: true,
  210. },
  211. toolbox: {
  212. feature: {},
  213. },
  214. xAxis: {
  215. axisLabel: {
  216. interval: 0,
  217. },
  218. },
  219. };
  220. const echartsOption1 = {
  221. grid: {
  222. top: '70px',
  223. left: '10px',
  224. right: props.chartsColumns.length * 15 + 'px',
  225. bottom: '45px',
  226. containLabel: true,
  227. },
  228. toolbox: {
  229. feature: {},
  230. },
  231. xAxis: {
  232. interval: 0,
  233. },
  234. };
  235. const echartsOption2 = {
  236. grid: {
  237. top: '70px',
  238. left: '10px',
  239. right: props.chartsColumns.length * 15 + 'px',
  240. bottom: '2%',
  241. containLabel: true,
  242. },
  243. toolbox: {
  244. feature: {},
  245. },
  246. };
  247. const onChange = (pageNumber: number) => {
  248. console.log('Page: ', pageNumber);
  249. };
  250. watch(
  251. [chartsType, deviceId, historyParams, pageSize, currentPage],
  252. async (
  253. [newChartsType, newDeviceId, newHistoryParams, newPageSize, newCurrentPage],
  254. [oldChartsType, oldDeviceId, oldHistoryParams, oldPageSize, oldCurrentPage]
  255. ) => {
  256. console.log('[ historyParams ] >', historyParams.ttime, dayjs(historyParams.ttime).format('HH:mm:ss'));
  257. if (newChartsType === 'listMonitor') {
  258. // 实时监测所有
  259. resultDataSource.value = props.dataSource;
  260. } else if (newChartsType === 'history') {
  261. resultDataSource.value = [];
  262. // 历史
  263. if (newChartsType !== oldChartsType || newDeviceId !== oldDeviceId) {
  264. currentPage.value = 1;
  265. }
  266. const device = options.value.find((device) => device['deviceID'] === newDeviceId);
  267. if (device) {
  268. let res;
  269. if (device['stationtype'] !== 'redis') {
  270. resultXAxisPropType.value = 'ttime';
  271. historyList = (params) => defHttp.get({ url: '/safety/ventanalyMonitorData/listdays', params });
  272. const datas = await historyList({
  273. ttime_begin: newHistoryParams.ttime_begin,
  274. ttime_end: newHistoryParams.ttime_end,
  275. strtype: device.deviceType,
  276. gdeviceid: newDeviceId,
  277. skip: newHistoryParams.skip,
  278. pageSize: pageSize.value,
  279. pageNo: currentPage.value,
  280. column: 'createTime',
  281. });
  282. res = datas['datalist']['records'];
  283. if (res && res.length > 0) {
  284. resultDataSource.value = res.map((item) => Object.assign(item, item.readData));
  285. } else {
  286. resultDataSource.value = [];
  287. }
  288. total.value = datas['datalist'].total;
  289. } else {
  290. historyList = (params) => defHttp.post({ url: '/monitor/history/getHistoryData', params });
  291. resultXAxisPropType.value = 'time';
  292. res = await historyList({
  293. pageSize: pageSize.value,
  294. pageNum: currentPage.value,
  295. startTime: newHistoryParams.ttime_begin,
  296. endTime: newHistoryParams.ttime_end,
  297. deviceId: newDeviceId,
  298. strtype: device.deviceType,
  299. interval: newHistoryParams.interval,
  300. column: 'createTime',
  301. });
  302. if (res && res.records && res.records.length > 0) {
  303. resultDataSource.value = res.records.map((item) => Object.assign(item, item.readData));
  304. } else {
  305. resultDataSource.value = [];
  306. }
  307. total.value = res.total;
  308. }
  309. }
  310. } else if (newChartsType === 'detail') {
  311. // 设备详情
  312. resultXAxisPropType.value = 'readTime';
  313. if (newDeviceId !== oldDeviceId) {
  314. detailDataSource.value = [];
  315. }
  316. }
  317. }
  318. );
  319. watchEffect(() => {
  320. if (chartsType.value === 'detail') {
  321. const currentData = props.dataSource.find((item: any) => item.deviceID === deviceId.value);
  322. if (currentData) {
  323. const isHas = detailDataSource.value.find((item) => item[resultXAxisPropType.value] === currentData[resultXAxisPropType.value]);
  324. if (!isHas) {
  325. if (detailDataSource.value.length < 15) {
  326. detailDataSource.value.push(currentData);
  327. } else {
  328. detailDataSource.value.shift();
  329. detailDataSource.value.push(currentData);
  330. }
  331. }
  332. }
  333. }
  334. });
  335. onMounted(async () => {
  336. const res = await props.deviceListApi();
  337. // debugger;
  338. if (res['msgTxt'] && res['msgTxt'][0] && res['msgTxt'][0]['datalist']) {
  339. options.value = res['msgTxt'][0]['datalist'];
  340. deviceId.value = options.value[0]['deviceID'];
  341. }
  342. });
  343. return {
  344. chartsType,
  345. deviceId,
  346. resultDataSource,
  347. historyParams,
  348. options,
  349. resultXAxisPropType,
  350. detailDataSource,
  351. currentPage,
  352. pageSize,
  353. total,
  354. echartsOption,
  355. echartsOption1,
  356. echartsOption2,
  357. onChange,
  358. globalConfig,
  359. };
  360. },
  361. });
  362. </script>
  363. <style lang="less">
  364. :deep(.vent-select-dropdown) {
  365. color: #000 !important;
  366. .vent-select-item {
  367. color: #000 !important;
  368. }
  369. }
  370. </style>
  371. <style lang="less" scoped>
  372. @import '/@/design/theme.less';
  373. .charts-container {
  374. position: relative;
  375. height: 100%;
  376. .charts-box {
  377. width: 100%;
  378. height: 100%;
  379. position: absolute;
  380. bottom: 0;
  381. top: 0px;
  382. }
  383. .@{ventSpace}-picker,
  384. .@{ventSpace}-select-selector {
  385. background: #00000017 !important;
  386. border: 1px solid @vent-form-item-border !important;
  387. input,
  388. .@{ventSpace}-select-selection-item,
  389. .@{ventSpace}-picker-suffix {
  390. color: #fff !important;
  391. }
  392. .@{ventSpace}-select-selection-placeholder {
  393. color: #b7b7b7 !important;
  394. }
  395. }
  396. .@{ventSpace}-select-arrow,
  397. .@{ventSpace}-picker-separator {
  398. color: #fff !important;
  399. }
  400. }
  401. :deep(.@{ventSpace}-select-dropdown) {
  402. color: #000 !important;
  403. .@{ventSpace}-select-item {
  404. color: #000 !important;
  405. }
  406. }
  407. </style>