DeviceEcharts.vue 13 KB

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