index.vue 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109
  1. <template>
  2. <div class="scene-box">
  3. <div class="select-node" :class="{ 'node-select-show': !treeShow, 'node-select-hide': treeShow, }"
  4. @click="showTree('treeShow', true)">
  5. <SvgIcon class="is-expansion-icon put-away-icon" size="38" name="expansion" />
  6. <span class="title">{{ treeNodeTitle }}</span>
  7. </div>
  8. <div class="device-select" :class="{ 'device-select-show': treeShow, 'device-select-hide': !treeShow, }">
  9. <SvgIcon class="is-expansion-icon expansion-icon" size="28" name="put-away" @click="showTree('treeShow', false)" />
  10. <div class="device-select-box">
  11. <a-tree :show-line="true" :tree-data="treeData" v-model:selectedKeys="selectedKeys"
  12. :autoExpandParent ="true"
  13. v-model:expandedKeys = "expandedKeys" @select="onSelect">
  14. </a-tree>
  15. </div>
  16. </div>
  17. <div class="location-icon"
  18. :class="{ 'location-btn-show': !locationSettingShow, 'location-btn-hide': locationSettingShow, }"
  19. @click="showTree('location', true)">
  20. <SvgIcon size="18" name="put-away" />
  21. <span class="location-text">定位图标显示</span>
  22. </div>
  23. <div class="location-select"
  24. :class="{ 'location-select-show': locationSettingShow, 'location-select-hide': !locationSettingShow, }">
  25. <div class="location-select-box">
  26. <div class="location-top-title" @click="showTree('location', false)">
  27. <SvgIcon class="is-expansion-icon location-expansion-icon" size="28" name="expansion" />
  28. <div class="title">定位图标显示</div>
  29. </div>
  30. <div class="location-container">
  31. <template v-for="location in locationList" :key="location.deviceType">
  32. <div class="location-item">
  33. <div class="item-title">{{ location.title }}&nbsp;:</div>
  34. <div>
  35. <a-radio-group v-model:value="location.Visible" :name="location.deviceType">
  36. <a-radio :value="1">是</a-radio>
  37. <a-radio :value="0">否</a-radio>
  38. </a-radio-group>
  39. </div>
  40. </div>
  41. </template>
  42. <div class="location-bottom-btn">
  43. <span @click="setLocation">提交</span>
  44. </div>
  45. </div>
  46. </div>
  47. </div>
  48. <div>
  49. <div class="bottom-tabs-box" @mousedown="setDivHeight($event, 250, scroll)" id="monitorBox">
  50. <div class="to-small" @click="toHome"></div>
  51. <div class="device-button-group" v-if="deviceList.length > 0">
  52. <div class="device-button" :class="{ 'device-active': deviceActive == device.deviceType }"
  53. v-for="(device, index) in deviceList" :key="index" @click="monitorChange(index)">{{ device.deviceName }}</div>
  54. <div class="enter-detail" @click="goDetail()">
  55. <send-outlined />
  56. {{ treeNodeTitle }}详情
  57. </div>
  58. </div>
  59. <a-tabs class="tabs-box" v-model:activeKey="activeKey" @change="tabChange">
  60. <a-tab-pane key="1" tab="实时监测">
  61. <template v-if="deviceType == 'fan' && activeKey == '1' && isRefresh">
  62. <GroupMonitorTable :dataSource="dataSource" :columnsType="`${deviceType}_monitor`" />
  63. </template>
  64. <template v-else-if="activeKey == '1' && isRefresh">
  65. <MonitorTable ref="monitorTable" :columnsType="`${deviceType}_monitor`" :dataSource="dataSource"
  66. design-scope="device_monitor" :isShowPagination="false" :isShowActionColumn="true" title="设备监测"
  67. :scroll="scroll">
  68. <template #action="{ record }">
  69. <TableAction :actions="[
  70. {
  71. label: '详情',
  72. onClick: goDetail.bind(null, record),
  73. },
  74. {
  75. label: '定位',
  76. onClick: goLocation.bind(null, record),
  77. },
  78. ]" />
  79. </template>
  80. <template #filterCell="{ column, record }">
  81. <template v-if="deviceType.startsWith('gate')">
  82. <template v-if="record.frontGateOpenCtrl">
  83. <a-tag
  84. v-if="column.dataIndex === 'frontGateOpen' && record.frontGateOpen == 0 && record.frontGateClose == 0"
  85. color="red">正在打开</a-tag>
  86. <a-tag v-else-if="column.dataIndex === 'frontGateOpen'" color="processing">打开</a-tag>
  87. </template>
  88. <template v-else>
  89. <a-tag
  90. v-if="column.dataIndex === 'frontGateOpen' && record.frontGateOpen == 0 && record.frontGateClose == 0"
  91. color="red">正在关闭</a-tag>
  92. <a-tag
  93. v-else-if="column.dataIndex === 'frontGateOpen' && record.frontGateOpen == 0 && record.frontGateClose == 1"
  94. color="default">关闭</a-tag>
  95. <a-tag
  96. v-else-if="column.dataIndex === 'frontGateOpen' && record.frontGateOpen == 1 && record.frontGateClose == 0"
  97. color="default">打开</a-tag>
  98. </template>
  99. <template v-if="record.rearGateOpenCtrl">
  100. <a-tag
  101. v-if="column.dataIndex === 'rearGateOpen' && record.rearGateOpen == 0 && record.rearGateClose == 0"
  102. color="red">正在打开</a-tag>
  103. <a-tag v-else-if="column.dataIndex === 'rearGateOpen'" color="processing">打开</a-tag>
  104. </template>
  105. <template v-else>
  106. <a-tag
  107. v-if="column.dataIndex === 'rearGateOpen' && record.rearGateOpen == 0 && record.rearGateClose == 0"
  108. color="red">正在关闭</a-tag>
  109. <a-tag
  110. v-else-if="column.dataIndex === 'rearGateOpen' && record.rearGateOpen == 0 && record.rearGateClose == 1"
  111. color="default">关闭</a-tag>
  112. <a-tag
  113. v-else-if="column.dataIndex === 'rearGateOpen' && record.rearGateOpen == 1 && record.rearGateClose == 0"
  114. color="default">打开</a-tag>
  115. </template>
  116. </template>
  117. <template v-if="deviceType.startsWith('windrect')">
  118. <a-tag v-if="column.dataIndex === 'sign'"
  119. :color="record.sign == 0 ? '#95CF65' : record.sign == 1 ? '#4590EA' : '#9876AA'"> {{
  120. record.sign == 0 ? '高位' : record.sign == 1 ? '中位' : '低位'
  121. }}</a-tag>
  122. <template v-if="record && column && column.dataIndex === 'isRun' && record.isRun">
  123. <a-tag v-if="record.isRun == -2 || record.isRun == -1"
  124. :color="record.isRun == -2 ? '#95CF65' : '#ED5700'">{{
  125. record.isRun == -2 ? '空闲' : '等待'
  126. }}</a-tag>
  127. <a-tag v-else-if="record.isRun == 100" color="#4693FF">完成</a-tag>
  128. <Progress v-else :percent="Number(record.isRun)" size="small" status="active" />
  129. </template>
  130. </template>
  131. <a-tag v-if="column.dataIndex === 'warnFlag'"
  132. :color="record.warnFlag == 0 ? 'green' : record.warnFlag == 1 ? '#FF5812' : 'gray'"> {{
  133. record.warnFlag == 0 ? '正常' : record.warnFlag == 1 ? '报警' : record.warnFlag == 2 ? '断开' : '未监测'
  134. }}</a-tag>
  135. <a-tag v-if="column.dataIndex === 'netStatus'" :color="record.netStatus == 0 ? 'default' : 'green'">{{
  136. record.netStatus == 0 ? '断开' : '连接'
  137. }}</a-tag>
  138. </template>
  139. </MonitorTable>
  140. </template>
  141. </a-tab-pane>
  142. <a-tab-pane key="2" tab="历史数据">
  143. <div class="tab-item">
  144. <HistoryTable ref="historyTable" v-if="activeKey == '2' && isRefresh" :sysId="systemID"
  145. :columns-type="`${deviceType}`" :device-type="deviceType"
  146. :device-list-api="getDeviceList.bind(null, { strtype: deviceType, sysId: systemID })"
  147. designScope="device-history" :scroll="scroll" />
  148. </div>
  149. </a-tab-pane>
  150. <a-tab-pane key="3" tab="报警历史">
  151. <div class="tab-item">
  152. <AlarmHistoryTable ref="alarmHistoryTable" v-if="activeKey == '3' && isRefresh" :sysId="systemID"
  153. columns-type="alarm" :device-type="deviceType"
  154. :device-list-api="getDeviceList.bind(null, { strtype: deviceType, sysId: systemID })" :scroll="scroll"
  155. designScope="alarm-history" />
  156. </div>
  157. </a-tab-pane>
  158. <a-tab-pane key="4" tab="操作历史">
  159. <div class="tab-item">
  160. <HandlerHistoryTable ref="handlerHistoryTable" v-if="activeKey == '4' && isRefresh" :sysId="systemID"
  161. columns-type="operatorhistory" :device-type="deviceType"
  162. :device-list-api="getDeviceList.bind(null, { strtype: deviceType, sysId: systemID })" :scroll="scroll"
  163. designScope="operator-history" />
  164. </div>
  165. </a-tab-pane>
  166. </a-tabs>
  167. </div>
  168. </div>
  169. <component v-if="modalVisible" :is="currentModal" v-model:visible="modalVisible" :dataSource="dataSource"
  170. :activeID="activeID" />
  171. </div>
  172. </template>
  173. <script setup lang="ts">
  174. import { ref, onMounted, onUnmounted, ComponentOptions, shallowRef, nextTick, watch, reactive, defineProps } from 'vue'
  175. import { SendOutlined } from '@ant-design/icons-vue';
  176. import { list, getDeviceList, getDeviceTypeList } from './device.api'
  177. import AlarmHistoryTable from '../../../comment/AlarmHistoryTable.vue';
  178. import HistoryTable from '../../../comment/HistoryTable.vue';
  179. import HandlerHistoryTable from '../../../comment/HandlerHistoryTable.vue';
  180. import MonitorTable from '../../../comment/MonitorTable.vue';
  181. import GroupMonitorTable from '../../../comment/GroupMonitorTable.vue';
  182. import { TreeProps, message, Progress } from 'ant-design-vue';
  183. import { TableAction } from '/@/components/Table';
  184. import FiberModal from './modal/fiber.modal.vue';
  185. import BundleModal from './modal/bundle.modal.vue'
  186. import DustModal from './modal/dust.modal.vue'
  187. import { SvgIcon } from '/@/components/Icon';
  188. import { getActions } from '/@/qiankun/state';
  189. import { useRouter } from 'vue-router';
  190. import { setDivHeight } from '/@/utils/event';
  191. type DeviceType = { deviceType: string, deviceName: string, datalist: any[] };
  192. const props = defineProps({
  193. pageData: {
  194. type: Object,
  195. default: () => {}
  196. }
  197. })
  198. const router = useRouter()
  199. const actions = getActions();
  200. // actions.setGlobalState({ pageObj: { pageType: 'home' } });
  201. const monitorTable = ref()
  202. const historyTable = ref()
  203. const alarmHistoryTable = ref()
  204. const handlerHistoryTable = ref()
  205. // const routerParam = ref('home') // 默认进来时首页
  206. // 模态框
  207. const currentModal = shallowRef<Nullable<ComponentOptions>>(null); //模态框
  208. const modalVisible = ref<Boolean>(false); // 模态框是否可见
  209. // const drawerHeight = ref(240) // 监测框最小高度
  210. const treeShow = ref(true) //是否显示树形菜单
  211. const locationSettingShow = ref(false) //是否显示树形菜单
  212. const treeNodeTitle = ref('') // 选中的树形标题
  213. const locationList = ref([]) //巷道定位图标显示列表
  214. const deviceList = ref<DeviceType[]>([]) //关联设备列表
  215. const deviceActive = ref('')
  216. const activeKey = ref('1'); // tab key
  217. const dataSource = shallowRef([]) // 实时监测数据
  218. const activeID = ref('') // 打开详情modal时监测的设备id
  219. const deviceType = ref('') // 监测设备类型
  220. const systemType = ref('')
  221. const systemID = ref('') // 系统监测时,系统id
  222. const selectedKeys = ref<string[]>([]);
  223. const expandedKeys = ref<string[]>(['0-0-0-1']);
  224. const isRefresh = ref(true)
  225. const scroll = reactive({
  226. y: 240
  227. })
  228. const treeData = ref<TreeProps['treeData']>([]);
  229. //树形菜单选择事件
  230. const onSelect: TreeProps['onSelect'] = (keys, e) => {
  231. deviceType.value = ''
  232. systemID.value = ''
  233. deviceList.value = []
  234. if (e.node.parent && (e.node.parent.node.type.toString()).startsWith('sys')) {
  235. systemType.value = e.node.parent.node.type
  236. deviceType.value = e.node.parent.node.type
  237. systemID.value = e.node.type
  238. // 传递工作面id信息,用于定位
  239. actions.setGlobalState({ locationObj: { pageType: deviceType.value, deviceid: systemID.value }, pageObj: null });
  240. } else {
  241. systemType.value = e.node.type
  242. deviceType.value = e.node.type
  243. }
  244. selectedKeys.values = keys
  245. treeNodeTitle.value = e.node.title
  246. if (timer) clearTimeout(timer)
  247. timer = undefined
  248. if (monitorTable.value) monitorTable.value.setLoading(true)
  249. nextTick(() => {
  250. setTimeout(() => {
  251. timer = null
  252. getMonitor()
  253. }, 0)
  254. })
  255. };
  256. function tabChange(activeKeyVal) {
  257. activeKey.value = activeKeyVal;
  258. };
  259. function showTree(flag, value) {
  260. if (flag == 'treeShow') treeShow.value = value
  261. if (flag == 'location') locationSettingShow.value = value
  262. }
  263. async function getDeviceType() {
  264. if(treeData.value?.length > 0) return
  265. const result = await getDeviceTypeList({})
  266. if (result.length > 0) {
  267. const dataSource = <TreeProps['treeData']>[]
  268. let key = '0'
  269. const getData = (resultList, dataSourceList, keyVal) => {
  270. resultList.forEach((item, index) => {
  271. if (item.children && item.children.length > 0) {
  272. const children = getData(item.children, [], `${keyVal}-${index}`)
  273. dataSourceList.push({
  274. children: children,
  275. title: item.itemText,
  276. key: `${keyVal}-${index}`,
  277. type: item.itemValue,
  278. parentKey: `${keyVal}`
  279. });
  280. } else {
  281. dataSourceList.push({
  282. children: [],
  283. title: item.itemText,
  284. key: `${keyVal}-${index}`,
  285. type: item.itemValue,
  286. parentKey: `${keyVal}`
  287. });
  288. }
  289. });
  290. return dataSourceList
  291. }
  292. treeData.value = getData(result, dataSource, key)
  293. }
  294. }
  295. // https获取监测数据
  296. let timer: null | NodeJS.Timeout = undefined;
  297. function getMonitor() {
  298. if (deviceType.value) {
  299. if (timer) timer = null
  300. if (Object.prototype.toString.call(timer) === '[object Null]') {
  301. timer = setTimeout(async () => {
  302. await getDataSource()
  303. if (timer) {
  304. getMonitor();
  305. }
  306. }, 1000);
  307. }
  308. }
  309. };
  310. async function getDataSource() {
  311. if (deviceType.value && deviceType.value.startsWith('sys') && systemID.value) {
  312. const res = await list({ devicetype: 'sys', systemID: systemID.value });
  313. const result = res.msgTxt;
  314. const deviceArr = <DeviceType[]>[]
  315. result.forEach(item => {
  316. const data = item['datalist'].filter((data: any) => {
  317. const readData = data.readData;
  318. return Object.assign(data, readData);
  319. })
  320. if (item.type != 'sys') {
  321. deviceArr.unshift({ deviceType: item.type, deviceName: item['typeName'] ? item['typeName'] : item['datalist'][0]['typeName'], datalist: data })
  322. }
  323. })
  324. deviceList.value = deviceArr
  325. if (deviceArr.length > 0) {
  326. if (deviceArr[1]) {
  327. deviceActive.value = deviceArr[1].deviceType
  328. monitorChange(1)
  329. } else {
  330. deviceActive.value = deviceArr[0].deviceType
  331. monitorChange(0)
  332. }
  333. }
  334. } else {
  335. const res = await list({ devicetype: deviceType.value, pagetype: 'normal' })
  336. if (res.msgTxt[0]) {
  337. dataSource.value = res.msgTxt[0].datalist || [];
  338. dataSource.value.filter((data: any) => {
  339. const readData = data.readData;
  340. return Object.assign(data, readData);
  341. });
  342. }
  343. }
  344. }
  345. function goLocation(record) {
  346. actions.setGlobalState({ locationId: record.deviceID, locationObj: null, pageObj: null });
  347. }
  348. function goDetail(record?) {
  349. if (record) {
  350. if (deviceType.value.startsWith('fiber')) {
  351. activeID.value = record.deviceID
  352. currentModal.value = FiberModal
  353. modalVisible.value = true;
  354. } else if (deviceType.value.startsWith('dusting')) { //bundletube
  355. activeID.value = record.deviceID
  356. currentModal.value = DustModal
  357. modalVisible.value = true;
  358. } else if (deviceType.value.startsWith('bundletube')) {
  359. activeID.value = record.deviceID
  360. currentModal.value = BundleModal
  361. modalVisible.value = true;
  362. } else if (deviceType.value.indexOf("gate") != -1) {
  363. const newPage = router.resolve({ path: '/monitorChannel/monitor-gate' })
  364. window.open(newPage.href, '_blank')
  365. } else if (deviceType.value.indexOf("window") != -1) {
  366. const newPage = router.resolve({ path: '/monitorChannel/monitor-window' })
  367. window.open(newPage.href, '_blank')
  368. } else if (deviceType.value.indexOf("windrect") != -1) {
  369. const newPage = router.resolve({ path: '/monitorChannel/monitor-windrect' })
  370. window.open(newPage.href, '_blank')
  371. } else if (deviceType.value.indexOf("fanmain") != -1) {
  372. const newPage = router.resolve({ path: '/monitorChannel/monitor-fan-main' })
  373. window.open(newPage.href, '_blank')
  374. } else if (deviceType.value.indexOf("fanlocal") != -1) {
  375. const newPage = router.resolve({ path: '/monitorChannel/monitor-fan-local' })
  376. window.open(newPage.href, '_blank')
  377. } else if (deviceType.value.indexOf("nitrogen") != -1) {
  378. const newPage = router.resolve({ path: '/compressor-home' })
  379. window.open(newPage.href, '_blank')
  380. } else if (deviceType.value.indexOf("pulping") != -1) {
  381. const newPage = router.resolve({ path: '/grout-home' })
  382. window.open(newPage.href, '_blank')
  383. } else if (deviceType.value.indexOf("pressurefan") != -1) {
  384. const newPage = router.resolve({ path: '/nitrogen/home' })
  385. window.open(newPage.href, '_blank')
  386. } else if (deviceType.value.indexOf("chamber") != -1) {
  387. const newPage = router.resolve({ path: '/chamber-home' })
  388. window.open(newPage.href, '_blank')
  389. } else {
  390. message.info('待开发。。。')
  391. }
  392. } else {
  393. if (systemType.value.indexOf("sys_dongshi") != -1) {
  394. const newPage = router.resolve({ path: '/chamber-home', query: { id: systemID.value } })
  395. window.open(newPage.href, '_blank')
  396. } else {
  397. message.info('待开发。。。')
  398. }
  399. }
  400. }
  401. function toHome() {
  402. deviceList.value = []
  403. if (timer) clearTimeout(timer)
  404. timer = undefined
  405. deviceType.value = ''
  406. actions.setGlobalState({ pageObj: { pageType: 'home' } });
  407. }
  408. async function findTreeDataValue(obj) {
  409. const findDeviceType = (data: [], obj) => {
  410. let type = ''
  411. if (obj.deviceid) {
  412. type = obj.deviceid
  413. } else {
  414. type = obj.deviceType
  415. }
  416. data.find((item: any) => {
  417. if (item.children.length > 0) {
  418. findDeviceType(item.children, obj)
  419. }
  420. if (item.type == type) {
  421. deviceType.value = obj.deviceid ? 'sys' : item.type
  422. if (obj.deviceid) systemID.value = obj.deviceid
  423. selectedKeys.value = [item.key]
  424. expandedKeys.value = [item.key]
  425. treeNodeTitle.value = item.title
  426. return true
  427. }
  428. return false
  429. })
  430. }
  431. findDeviceType(treeData.value, obj)
  432. if (timer === undefined) {
  433. timer = null
  434. await getDataSource()
  435. getMonitor()
  436. }
  437. }
  438. function monitorChange(index) {
  439. dataSource.value = []
  440. deviceActive.value = deviceType.value = deviceList.value[index].deviceType
  441. if (activeKey.value == '1' && monitorTable.value) {
  442. monitorTable.value.setLoading(true)
  443. dataSource.value = deviceList.value[index].datalist
  444. }
  445. if (activeKey.value == '2' && historyTable.value) {
  446. historyTable.value.setLoading(true)
  447. }
  448. if (activeKey.value == '3' && alarmHistoryTable.value) {
  449. alarmHistoryTable.value.setLoading(true)
  450. }
  451. if (activeKey.value == '4' && handlerHistoryTable.value) {
  452. handlerHistoryTable.value.setLoading(true)
  453. }
  454. }
  455. /**
  456. * 设置巷道设备定位图标的显示与隐藏
  457. */
  458. function setLocation() {
  459. let locationStr = ''
  460. locationList.value.forEach((item: any) => {
  461. if (item.Visible) {
  462. locationStr = locationStr ? locationStr + ',' + item.value : item.value
  463. }
  464. })
  465. actions.setGlobalState({ locationId: null, locationObj: null, pageObj: null, locationPlane: locationStr });
  466. setTimeout(() => {
  467. message.success('设置成功')
  468. }, 600)
  469. }
  470. watch(() => scroll.y, () => {
  471. isRefresh.value = false
  472. nextTick(() => {
  473. isRefresh.value = true
  474. })
  475. })
  476. onMounted(async () => {
  477. await getDeviceType()
  478. const pageObj = props.pageData
  479. if (pageObj.deviceid) {
  480. findTreeDataValue({ deviceid: pageObj.deviceid })
  481. } else {
  482. findTreeDataValue({ deviceType: pageObj.pageType })
  483. }
  484. // 定位
  485. const posShowData = pageObj.locationPlane
  486. if (posShowData) {
  487. locationList.value = posShowData
  488. }
  489. })
  490. onUnmounted(() => {
  491. if (timer) {
  492. clearTimeout(timer);
  493. }
  494. timer = undefined;
  495. })
  496. </script>
  497. <style lang="less" scoped >
  498. @import '/@/design/vent/modal.less';
  499. @ventSpace: zxm;
  500. .device-header {
  501. position: fixed;
  502. width: 100%;
  503. height: 56px;
  504. background: url('/@/assets/images/vent/home/modal-top.png');
  505. text-align: center;
  506. line-height: 56px;
  507. font-size: 28px;
  508. color: #ffffffdd;
  509. font-weight: 600;
  510. z-index: -1;
  511. }
  512. .select-node {
  513. position: fixed;
  514. top: 60px;
  515. left: 10px;
  516. color: #fff;
  517. display: flex;
  518. justify-content: center;
  519. font-size: 22px;
  520. .title {
  521. margin-left: 10px;
  522. }
  523. }
  524. .expansion-icon {
  525. background: url('/@/assets/images/vent/home/tree-icon-bg.png') no-repeat;
  526. background-size: contain;
  527. position: absolute;
  528. left: 190px;
  529. top: 25px;
  530. &:hover {
  531. background: url('/@/assets/images/vent/home/tree-icon-hover-bg.png') no-repeat;
  532. background-size: contain;
  533. }
  534. }
  535. .device-select {
  536. width: 250px;
  537. height: 500px;
  538. background: url('/@/assets/images/vent/home/tree-bg.png') no-repeat;
  539. position: fixed;
  540. top: 60px;
  541. left: 10px;
  542. background-size: contain;
  543. pointer-events: auto;
  544. padding: 20px 10px 30px 10px;
  545. }
  546. .is-expansion-icon {
  547. padding: 5px;
  548. pointer-events: auto;
  549. z-index: 999;
  550. }
  551. .device-select-show {
  552. left: 10px;
  553. animation-name: treeShow;
  554. /* 持续时间 */
  555. animation-duration: 1s;
  556. transition: all 1s cubic-bezier(0.165, 0.84, 0.44, 1) .5s;
  557. }
  558. .device-select-hide {
  559. left: -250px;
  560. animation-name: treeHide;
  561. /* 持续时间 */
  562. animation-duration: 1s;
  563. transition: all 1s cubic-bezier(0.165, 0.84, 0.44, 1) .5s;
  564. }
  565. .node-select-show {
  566. width: 276px;
  567. height: 44px;
  568. background: url('/@/assets/images/vent/home/tree-expansion-bg.png') no-repeat;
  569. left: 10px;
  570. animation-name: treeShow;
  571. /* 持续时间 */
  572. animation-duration: 1s;
  573. transition: all 1s cubic-bezier(0.165, 0.84, 0.44, 1) .5s;
  574. display: flex;
  575. align-items: center;
  576. margin-left: 0;
  577. justify-content: flex-start;
  578. pointer-events: auto;
  579. &:hover {
  580. background: url('/@/assets/images/vent/home/tree-expansion-hover-bg.png') no-repeat;
  581. }
  582. .put-away-icon {
  583. position: relative;
  584. display: inline-block;
  585. left: 4px;
  586. }
  587. }
  588. .node-select-hide {
  589. left: -400px;
  590. animation-name: treeHide;
  591. /* 持续时间 */
  592. animation-duration: 1s;
  593. transition: all 1s cubic-bezier(0.165, 0.84, 0.44, 1) .5s;
  594. }
  595. .device-select-box {
  596. width: 208px;
  597. height: 450px;
  598. overflow-y: auto;
  599. color: #fff;
  600. :deep(.zxm-tree) {
  601. background: transparent !important;
  602. color: #fff !important;
  603. .zxm-tree-switcher {
  604. background: transparent !important;
  605. }
  606. .zxm-tree-node-content-wrapper.zxm-tree-node-selected {
  607. background-color: #00b1c8;
  608. }
  609. .zxm-tree-node-content-wrapper:hover {
  610. background-color: #00b1c855;
  611. }
  612. input {
  613. height: 0px !important;
  614. }
  615. }
  616. &::-webkit-scrollbar-track {
  617. -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
  618. border-radius: 10px;
  619. background: #ededed22;
  620. height: 100px;
  621. }
  622. &::-webkit-scrollbar-thumb {
  623. -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
  624. background: #4288A444;
  625. }
  626. }
  627. .location-icon {
  628. width: 46px;
  629. height: 178px;
  630. position: absolute;
  631. top: 60px;
  632. // right: 0;
  633. background: url('/@/assets/images/vent/home/location-bg.png') no-repeat;
  634. background-size: contain;
  635. writing-mode: vertical-lr;
  636. line-height: 46px;
  637. color: #fff;
  638. padding-top: 10px;
  639. pointer-events: auto;
  640. cursor: pointer;
  641. &:hover {
  642. background: url('/@/assets/images/vent/home/location-hover-bg.png') no-repeat;
  643. }
  644. .location-text {
  645. padding-top: 20px;
  646. letter-spacing: 3px;
  647. font-size: 16px;
  648. }
  649. }
  650. .location-select {
  651. position: fixed;
  652. top: 60px;
  653. // right: 240px;
  654. pointer-events: auto;
  655. .location-select-box {
  656. width: 100%;
  657. height: 100%;
  658. position: relative;
  659. &::before {
  660. content: "";
  661. position: absolute;
  662. width: 230px;
  663. height: 500px;
  664. top: 0;
  665. left: 0;
  666. background: url('/@/assets/images/vent/home/tree-bg.png') no-repeat;
  667. background-size: contain;
  668. transform: rotateY(180deg);
  669. z-index: -1;
  670. // &:hover {
  671. // background: url('/@/assets/images/vent/home/tree-icon-hover-bg.png') no-repeat;
  672. // background-size: contain;
  673. // }
  674. }
  675. .location-top-title {
  676. color: #fff;
  677. position: absolute;
  678. width: 225px;
  679. height: 68px;
  680. background: url('/@/assets/images/vent/home/turn-location-top-bg.png') no-repeat;
  681. background-size: contain;
  682. top: 5px;
  683. left: 5px;
  684. display: flex;
  685. flex-direction: row;
  686. justify-content: space-between;
  687. align-items: flex-end;
  688. .title {
  689. font-size: 18px;
  690. position: relative;
  691. top: -14px;
  692. right: 15px;
  693. }
  694. }
  695. .location-expansion-icon {
  696. background: url('/@/assets/images/vent/home/tree-icon-cover-bg.png') no-repeat;
  697. background-size: contain;
  698. position: relative;
  699. left: 10px;
  700. top: -15px;
  701. padding: 5px;
  702. &:hover {
  703. background: url('/@/assets/images/vent/home/tree-icon-cover-hover-bg.png') no-repeat;
  704. background-size: contain;
  705. }
  706. }
  707. }
  708. .location-container {
  709. width: 200px;
  710. height: 390px;
  711. position: absolute;
  712. display: flex;
  713. flex-direction: column;
  714. top: 80px;
  715. left: 18px;
  716. overflow-y: auto;
  717. .location-item {
  718. color: #fff;
  719. line-height: 30px;
  720. display: flex;
  721. justify-content: space-between;
  722. background-image: linear-gradient(to left, #39f5ff05, #39f5ff10);
  723. margin: 3px 0;
  724. .item-title {
  725. width: 80px;
  726. text-align: right;
  727. color: #87f1ff;
  728. }
  729. }
  730. .location-bottom-btn {
  731. width: 100%;
  732. color: #fff;
  733. display: flex;
  734. justify-content: flex-end;
  735. margin-top: 20px;
  736. span {
  737. display: inline-block;
  738. width: 100%;
  739. background: #00709955;
  740. border-radius: 3px;
  741. border: 1px solid rgba(174, 243, 255, 0.3);
  742. text-align: center;
  743. padding: 2px 0;
  744. cursor: pointer;
  745. &:hover {
  746. background: #00557422;
  747. }
  748. }
  749. }
  750. }
  751. }
  752. .location-select-show {
  753. right: 240px;
  754. animation-name: locationShow;
  755. /* 持续时间 */
  756. animation-duration: 1s;
  757. transition: all 1s cubic-bezier(0.165, 0.84, 0.44, 1) .5s;
  758. }
  759. .location-select-hide {
  760. right: -2px;
  761. animation-name: locationHide;
  762. /* 持续时间 */
  763. animation-duration: 1s;
  764. transition: all 1s cubic-bezier(0.165, 0.84, 0.44, 1) .5s;
  765. }
  766. .location-btn-show {
  767. right: -0px;
  768. animation-name: locationBtnShow;
  769. /* 持续时间 */
  770. animation-duration: 1s;
  771. transition: all 1s cubic-bezier(0.165, 0.84, 0.44, 1) .5s;
  772. }
  773. .location-btn-hide {
  774. right: -240px;
  775. animation-name: locationBtnHide;
  776. /* 持续时间 */
  777. animation-duration: 1s;
  778. transition: all 1s cubic-bezier(0.165, 0.84, 0.44, 1) .5s;
  779. }
  780. .bottom-tabs-box {
  781. position: relative;
  782. .to-small {
  783. width: 60px;
  784. height: 60px;
  785. background: url('/@/assets/images/vent/home/tosmall.png') no-repeat center;
  786. background-size: auto;
  787. position: absolute;
  788. top: -62px;
  789. right: 36px;
  790. border-radius: 10px;
  791. padding: 8px;
  792. backdrop-filter: blur(10px);
  793. background-color: rgba(45, 86, 137, 0.418);
  794. &:hover {
  795. background-color: rgba(79, 104, 134, 0.418);
  796. }
  797. }
  798. .device-button-group {
  799. position: absolute;
  800. top: -27px;
  801. left: 30px;
  802. display: flex;
  803. width: 100%;
  804. .device-button {
  805. height: 26px;
  806. padding: 0 20px;
  807. background: linear-gradient(45deg, #04e6fb55, #0c5cab55);
  808. clip-path: polygon(10px 0,
  809. 0 50%,
  810. 10px 100%,
  811. 100% 100%,
  812. calc(100% - 10px) 50%,
  813. 100% 0);
  814. display: flex;
  815. justify-content: center;
  816. align-items: center;
  817. color: #FFF;
  818. position: relative;
  819. cursor: pointer;
  820. &:nth-child(1) {
  821. left: calc(-6px * 1);
  822. }
  823. &:nth-child(2) {
  824. left: calc(-6px * 2);
  825. }
  826. &:nth-child(3) {
  827. left: calc(-6px * 3);
  828. }
  829. &:nth-child(4) {
  830. left: calc(-6px * 4);
  831. }
  832. &:nth-child(5) {
  833. left: calc(-6px * 5);
  834. }
  835. &:nth-child(6) {
  836. left: calc(-6px * 6);
  837. }
  838. &:nth-child(7) {
  839. left: calc(-6px * 7);
  840. }
  841. &:nth-child(8) {
  842. left: calc(-6px * 8);
  843. }
  844. &:nth-child(9) {
  845. left: calc(-6px * 9);
  846. }
  847. &:nth-child(10) {
  848. left: calc(-6px * 10);
  849. }
  850. &:nth-child(11) {
  851. left: calc(-6px * 11);
  852. }
  853. &:nth-child(12) {
  854. left: calc(-6px * 12);
  855. }
  856. &:nth-child(13) {
  857. left: calc(-6px * 13);
  858. }
  859. &:nth-child(14) {
  860. left: calc(-6px * 14);
  861. }
  862. &:nth-child(15) {
  863. left: calc(-6px * 15);
  864. }
  865. &:first-child {
  866. clip-path: polygon(0 0,
  867. 10px 50%,
  868. 0 100%,
  869. 100% 100%,
  870. calc(100% - 10px) 50%,
  871. 100% 0);
  872. }
  873. }
  874. .device-active {
  875. background: linear-gradient(45deg, #04e6fb, #0c5cab);
  876. &::before {
  877. border-color: #0efcff;
  878. box-shadow: 1px 1px 3px 1px #0efcff inset;
  879. }
  880. }
  881. }
  882. .enter-detail {
  883. color: #fff;
  884. cursor: pointer;
  885. position: absolute;
  886. right: 120px;
  887. top: -6px;
  888. padding: 5px;
  889. border-radius: 5px;
  890. margin-left: 8px;
  891. margin-right: 8px;
  892. width: auto;
  893. height: 33px !important;
  894. display: flex;
  895. align-items: center;
  896. justify-content: center;
  897. color: #fff;
  898. padding: 5px 15px 5px 15px;
  899. cursor: pointer;
  900. &:hover {
  901. background: linear-gradient(#2cd1ff55, #1eb0ff55);
  902. }
  903. &::before {
  904. width: calc(100% - 6px);
  905. height: 27px;
  906. content: '';
  907. position: absolute;
  908. top: 3px;
  909. right: 0;
  910. left: 3px;
  911. bottom: 0;
  912. z-index: -1;
  913. border-radius: inherit;
  914. /*important*/
  915. background: linear-gradient(#1fa6cb, #127cb5);
  916. }
  917. }
  918. }
  919. @keyframes treeShow {
  920. 0% {
  921. left: -400px;
  922. opacity: 0;
  923. }
  924. 100% {
  925. left: 10px;
  926. opacity: 1;
  927. }
  928. }
  929. @keyframes treeHide {
  930. 0% {
  931. left: 10px;
  932. opacity: 1;
  933. }
  934. 100% {
  935. left: -400px;
  936. opacity: 0;
  937. }
  938. }
  939. @keyframes locationShow {
  940. 0% {
  941. right: 0px;
  942. opacity: 0;
  943. }
  944. 100% {
  945. right: 240px;
  946. opacity: 1;
  947. }
  948. }
  949. @keyframes locationHide {
  950. 0% {
  951. right: 240px;
  952. opacity: 1;
  953. }
  954. 100% {
  955. right: 0;
  956. opacity: 0;
  957. }
  958. }
  959. @keyframes locationBtnShow {
  960. 0% {
  961. right: -240px;
  962. opacity: 0;
  963. }
  964. 100% {
  965. right: -2px;
  966. opacity: 1;
  967. }
  968. }
  969. @keyframes locationBtnHide {
  970. 0% {
  971. right: -2px;
  972. opacity: 1;
  973. }
  974. 100% {
  975. right: -240px;
  976. opacity: 0;
  977. }
  978. }
  979. :deep(.@{ventSpace}-tabs-tabpane-active) {
  980. // overflow: auto;
  981. height: 100%;
  982. }
  983. :deep(.zxm-select-dropdown) {
  984. left: 0 !important;
  985. }</style>