DeviceEcharts.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  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="detail">详情监测</a-select-option>
  6. <a-select-option value="history">历史记录</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-else-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. let historyList;
  182. if (globalConfig.History_Type == 'vent') {
  183. historyList = (params) => defHttp.get({ url: '/safety/ventanalyMonitorData/listdays', params });
  184. } else {
  185. historyList = (params) => defHttp.post({ url: '/monitor/history/getHistoryData', params });
  186. }
  187. const chartsType = ref('history');
  188. const deviceId = ref('');
  189. const options = ref([]);
  190. const historyParams = reactive({
  191. ttime_begin: dayjs().startOf('date').format('YYYY-MM-DD HH:mm:ss').toString(),
  192. ttime_end: dayjs().format('YYYY-MM-DD HH:mm:ss').toString(),
  193. skip: '8',
  194. interval: '1h',
  195. });
  196. const resultXAxisPropType = ref('');
  197. const resultDataSource = ref<any[]>([]);
  198. const detailDataSource = ref<any[]>([]);
  199. const currentPage = ref<number>(1);
  200. const pageSize = ref<number>(20);
  201. const total = ref(0);
  202. const echartsOption = {
  203. grid: {
  204. top: '60px',
  205. left: '10px',
  206. right: props.chartsColumns.length * 15 + 'px',
  207. bottom: '5%',
  208. containLabel: true,
  209. },
  210. toolbox: {
  211. feature: {},
  212. },
  213. xAxis: {
  214. axisLabel: {
  215. interval: 0,
  216. },
  217. },
  218. };
  219. const echartsOption1 = {
  220. grid: {
  221. top: '70px',
  222. left: '10px',
  223. right: props.chartsColumns.length * 15 + 'px',
  224. bottom: '45px',
  225. containLabel: true,
  226. },
  227. toolbox: {
  228. feature: {},
  229. },
  230. xAxis: {
  231. interval: 0,
  232. },
  233. };
  234. const echartsOption2 = {
  235. grid: {
  236. top: '70px',
  237. left: '10px',
  238. right: props.chartsColumns.length * 15 + 'px',
  239. bottom: '2%',
  240. containLabel: true,
  241. },
  242. toolbox: {
  243. feature: {},
  244. },
  245. };
  246. const onChange = (pageNumber: number) => {
  247. console.log('Page: ', pageNumber);
  248. };
  249. watch(
  250. [chartsType, deviceId, historyParams, pageSize, currentPage],
  251. async (
  252. [newChartsType, newDeviceId, newHistoryParams, newPageSize, newCurrentPage],
  253. [oldChartsType, oldDeviceId, oldHistoryParams, oldPageSize, oldCurrentPage]
  254. ) => {
  255. console.log('[ historyParams ] >', historyParams.ttime, dayjs(historyParams.ttime).format('HH:mm:ss'));
  256. if (newChartsType === 'listMonitor') {
  257. // 实时监测所有
  258. resultDataSource.value = props.dataSource;
  259. } else if (newChartsType === 'history') {
  260. resultDataSource.value = [];
  261. // 历史
  262. if (newChartsType !== oldChartsType || newDeviceId !== oldDeviceId) {
  263. currentPage.value = 1;
  264. }
  265. const device = options.value.find((device) => device['deviceID'] === newDeviceId);
  266. if (device) {
  267. let res;
  268. if (props.dataSource['stationtype'] !== 'redis') {
  269. resultXAxisPropType.value = 'ttime';
  270. const datas = await historyList({
  271. ttime_begin: newHistoryParams.ttime_begin,
  272. ttime_end: newHistoryParams.ttime_end,
  273. strtype: device.deviceType,
  274. gdeviceid: newDeviceId,
  275. skip: newHistoryParams.skip,
  276. pageSize: pageSize.value,
  277. pageNo: currentPage.value,
  278. column: 'createTime',
  279. });
  280. res = datas['datalist']['records'];
  281. if (res && res.length > 0) {
  282. resultDataSource.value = res.map((item) => Object.assign(item, item.readData));
  283. } else {
  284. resultDataSource.value = [];
  285. }
  286. total.value = datas['datalist'].total;
  287. } else {
  288. resultXAxisPropType.value = 'time';
  289. res = await historyList({
  290. pageSize: pageSize.value,
  291. pageNum: currentPage.value,
  292. startTime: newHistoryParams.ttime_begin,
  293. endTime: newHistoryParams.ttime_end,
  294. deviceId: newDeviceId,
  295. strtype: device.deviceType,
  296. interval: newHistoryParams.interval,
  297. column: 'createTime',
  298. });
  299. if (res && res.records && res.records.length > 0) {
  300. resultDataSource.value = res.records.map((item) => Object.assign(item, item.readData));
  301. } else {
  302. resultDataSource.value = [];
  303. }
  304. total.value = res.total;
  305. }
  306. }
  307. } else if (newChartsType === 'detail') {
  308. // 设备详情
  309. resultXAxisPropType.value = 'readTime';
  310. if (newDeviceId !== oldDeviceId) {
  311. detailDataSource.value = [];
  312. }
  313. }
  314. }
  315. );
  316. watchEffect(() => {
  317. if (chartsType.value === 'detail') {
  318. const currentData = props.dataSource.find((item: any) => item.deviceID === deviceId.value);
  319. if (currentData) {
  320. const isHas = detailDataSource.value.find((item) => item[resultXAxisPropType.value] === currentData[resultXAxisPropType.value]);
  321. if (!isHas) {
  322. if (detailDataSource.value.length < 15) {
  323. detailDataSource.value.push(currentData);
  324. } else {
  325. detailDataSource.value.shift();
  326. detailDataSource.value.push(currentData);
  327. }
  328. }
  329. }
  330. }
  331. });
  332. onMounted(async () => {
  333. const res = await props.deviceListApi();
  334. // debugger;
  335. if (res['msgTxt'] && res['msgTxt'][0] && res['msgTxt'][0]['datalist']) {
  336. options.value = res['msgTxt'][0]['datalist'];
  337. deviceId.value = options.value[0]['deviceID'];
  338. }
  339. });
  340. return {
  341. chartsType,
  342. deviceId,
  343. resultDataSource,
  344. historyParams,
  345. options,
  346. resultXAxisPropType,
  347. detailDataSource,
  348. currentPage,
  349. pageSize,
  350. total,
  351. echartsOption,
  352. echartsOption1,
  353. echartsOption2,
  354. onChange,
  355. globalConfig,
  356. };
  357. },
  358. });
  359. </script>
  360. <style lang="less">
  361. :deep(.vent-select-dropdown) {
  362. color: #000 !important;
  363. .vent-select-item {
  364. color: #000 !important;
  365. }
  366. }
  367. </style>
  368. <style lang="less" scoped>
  369. @import '/@/design/vent/color.less';
  370. .charts-container {
  371. position: relative;
  372. height: 100%;
  373. .charts-box {
  374. width: 100%;
  375. height: 100%;
  376. position: absolute;
  377. bottom: 0;
  378. top: 0px;
  379. }
  380. .@{ventSpace}-picker,
  381. .@{ventSpace}-select-selector {
  382. background: #00000017 !important;
  383. border: 1px solid @vent-form-item-boder !important;
  384. input,
  385. .@{ventSpace}-select-selection-item,
  386. .@{ventSpace}-picker-suffix {
  387. color: #fff !important;
  388. }
  389. .@{ventSpace}-select-selection-placeholder {
  390. color: #b7b7b7 !important;
  391. }
  392. }
  393. .@{ventSpace}-select-arrow,
  394. .@{ventSpace}-picker-separator {
  395. color: #fff !important;
  396. }
  397. }
  398. :deep(.@{ventSpace}-select-dropdown) {
  399. color: #000 !important;
  400. .@{ventSpace}-select-item {
  401. color: #000 !important;
  402. }
  403. }
  404. </style>