DeviceEcharts.vue 12 KB

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