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