index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. <template>
  2. <div class="box">
  3. <el-container style="height:100%">
  4. <el-header>
  5. <div class="spaceName">
  6. <b>空间名称:</b>{{spaceDetails.RoomLocalName?spaceDetails.RoomLocalName:"-"}}
  7. </div>
  8. </el-header>
  9. <el-container>
  10. <el-aside width="450px">
  11. <div class="aside-top">
  12. <div class="aside-top-left">
  13. <p><b>空间功能区类型:</b>{{spaceDetails.RoomFuncType?spaceDetails.RoomFuncType:"-"}}</p>
  14. <p style="padding-right: 10px"><b>备注文字:</b>{{spaceDetails.Intro?spaceDetails.Intro:"-"}}</p>
  15. </div>
  16. <div class="aside-top-right">
  17. <p><b>空间二维码:</b><span v-if="!spaceDetails.RoomQRCode">-</span></p>
  18. <img :src="'/image-service/common/file_get/'+ spaceDetails.RoomQRCode +'?systemId=dataPlatform'" alt="二维码图片"
  19. v-if="spaceDetails.RoomQRCode">
  20. </div>
  21. </div>
  22. <div>
  23. <p><b>位置图片:</b></p>
  24. <div v-show="spaceDetails.Outline && spaceDetails.Outline[0] && spaceDetails.Outline[0].length" id="graphy" ref="graphy"
  25. style="width:400px;height:280px;" v-loading="canvasLoading">
  26. <div style="color:#333;font-weight: 700">{{buildingFloor}}</div>
  27. <canvas id="floorCanvas" :width="canvasWidth" :height="canvasHeight" ref="canvas" tabindex="0"></canvas>
  28. </div>
  29. </div>
  30. <div v-show="spaceDetails.Outline && !spaceDetails.Outline[0] || !spaceDetails.Outline"
  31. style="height: 280px;transform: translateY(30%);text-align:center;">
  32. <i class="icon-wushuju iconfont"></i>
  33. 数据暂无
  34. </div>
  35. <div class="space-img" style="height:400px;margin-top:40px;">
  36. <el-scrollbar>
  37. <p><b>空间照片:</b></p>
  38. <div v-if="spaceDetails.Pic">
  39. <div class="img-box" v-for="(item) in spaceDetails.Pic" :key='`${item.Id}+${item.Key}`'>
  40. <img :src="`/image-service/common/image_get?systemId=dataPlatform&key=${item.Key}`" alt="空间图片">
  41. </div>
  42. </div>
  43. <div v-show="!spaceDetails.Pic" style="height:100%;transform: translateY(50%);textAlign:center;">
  44. <i class="icon-wushuju iconfont"></i>
  45. 数据暂无
  46. </div>
  47. </el-scrollbar>
  48. </div>
  49. </el-aside>
  50. <el-main>
  51. <el-tabs v-model="activeTab" type='card'>
  52. <template v-for="(item,index) in tabsList">
  53. <el-tab-pane :name="item.Code" :key="index" :label="item.Name">
  54. <section v-show="activeTab === 'staticData'">
  55. <el-radio-group
  56. v-model="radio"
  57. style=" margin: 0 10px;"
  58. @change="changRadio"
  59. v-for="(item,index) in radioList"
  60. :key="index"
  61. >
  62. <el-radio :label="item.label">{{item.value}}</el-radio>
  63. </el-radio-group>
  64. <exhibitionBaseInformation :exhibitionBaseInformation="exhibitionBaseInformation"/>
  65. </section>
  66. <div v-show="activeTab === 'dynamicData'" style="width:100%;height:100%;">
  67. <div class="content-box">
  68. <div style="text-align: left;margin-bottom: 10px">
  69. <el-checkbox v-model="onlyMessage" @change="handleCheckbox">只看需采集的信息点</el-checkbox>
  70. </div>
  71. <el-table ref="multipleTable" :data="tableData" stripe :header-cell-style="headerStyle">
  72. <el-table-column prop="InfoPointName" label="信息点名称">
  73. <template slot-scope="scope">
  74. <div>
  75. <span>{{ scope.row.InfoPointName}}</span>
  76. <span class="unit">{{scope.row.Unit?`${"("+scope.row.Unit+")"}`:""}}</span>
  77. </div>
  78. </template>
  79. </el-table-column>
  80. <el-table-column prop="functionNo" label="表号功能号"></el-table-column>
  81. <el-table-column prop="functionNoDynamicData" label="动态数据"></el-table-column>
  82. <el-table-column prop="functionNoTime" label="数据采集时间"></el-table-column>
  83. <!-- 后台未提供,暂不显示 -->
  84. <!-- <el-table-column prop="LastUpdate" label="数据采集时间"></el-table-column> -->
  85. <template slot="empty">
  86. <div style="height: 60%;transform: translateY(50%);">
  87. <i class="icon-wushuju iconfont"></i>
  88. 数据暂无
  89. </div>
  90. </template>
  91. </el-table>
  92. </div>
  93. </div>
  94. <div v-if="activeTab === 'objectRelationship'" class="objectRelationship">
  95. <div class="objectRelationship-left">
  96. <h5>空间内设备:</h5>
  97. <eqToSpaceTable :params="params" type="Equipment"></eqToSpaceTable>
  98. </div>
  99. <div class="objectRelationship-center">
  100. <h5>服务于空间的设备:</h5>
  101. <eqToSpaceTable :params="params" type="EquipmentFor"></eqToSpaceTable>
  102. </div>
  103. <div class="objectRelationship-right">
  104. <h5>空间内系统:</h5>
  105. <syInSpaceTable :params="params" type="generalSystem"></syInSpaceTable>
  106. </div>
  107. </div>
  108. </el-tab-pane>
  109. </template>
  110. </el-tabs>
  111. </el-main>
  112. </el-container>
  113. </el-container>
  114. </div>
  115. </template>
  116. <script>
  117. import {BeatchQueryParam, floorQuery, getDataDictionary, zoneQuery, zoneQueryOutline} from '@/api/scan/request'
  118. import eqToSpaceTable from '@/components/business_space/newTables/eqToSpaceTable'
  119. import syInSpaceTable from '@/components/business_space/newTables/syInSpaceTable'
  120. import {DivideFloorScene, FloorView} from "@saga-web/cad-engine/lib";
  121. import tools from "@/utils/scan/tools";
  122. import exhibitionBaseInformation from "@/components/ledger/details/detail/exhibitionBaseInformation";
  123. export default {
  124. data() {
  125. return {
  126. tabsList: [
  127. {Code: 'staticData', Name: '静态数据'},
  128. {Code: 'dynamicData', Name: '动态数据'},
  129. {Code: 'objectRelationship', Name: '对象关系'}
  130. ],
  131. activeTab: 'staticData',
  132. checked: true,
  133. spaceDetails: {},
  134. iframeSrc: '',
  135. proId: '',
  136. params: {},
  137. view: null,
  138. scene: null,
  139. canvasWidth: 410,
  140. canvasHeight: 300,
  141. page: {
  142. pageSize: 50,
  143. pageSizes: [10, 20, 50, 100],
  144. pageNumber: 1,
  145. total: 0
  146. },
  147. tableData: [],
  148. headerStyle: {// 列表样式
  149. backgroundColor: '#e1e4e5',
  150. color: '#2b2b2b',
  151. lineHeight: '30px'
  152. },
  153. secret: '',
  154. canvasLoading: false,
  155. buildingFloor: localStorage.getItem('buildingFloor'),
  156. onlyMessage: false,
  157. exhibitionBaseInformation: {
  158. information: {},
  159. },
  160. pointData: [],
  161. instance: {},
  162. radioList: [
  163. {
  164. value: '显示全部信息点',
  165. label: '1'
  166. },
  167. {
  168. value: '显示有值信息点',
  169. label: '2'
  170. }
  171. ],
  172. radio: '1'
  173. }
  174. },
  175. components: {
  176. eqToSpaceTable,
  177. syInSpaceTable,
  178. exhibitionBaseInformation
  179. },
  180. beforeRouteEnter(to, from, next) {
  181. if (to.query.RoomID && to.query.zone) {
  182. next();
  183. }
  184. },
  185. created() {
  186. if (this.$route.name === "spaceLedger" && this.$route.query.RoomID && this.$route.query.zone) {
  187. this.getData();
  188. }
  189. },
  190. updated() {
  191. },
  192. computed: {},
  193. methods: {
  194. getData() {
  195. //获取表头
  196. let params1 = {
  197. data: {
  198. Orders: "sort asc",
  199. PageNumber: 1,
  200. PageSize: 1000
  201. },
  202. type: this.$route.query.zone
  203. }
  204. // 获取空间数据
  205. let params2 = {
  206. Filters: `RoomID="${this.$route.query.RoomID}"`,
  207. ZoneType: this.$route.query.zone
  208. }
  209. this.params = this.$route.query;
  210. let promise1 = new Promise((resolve, reject) => {
  211. getDataDictionary(params1, res => {
  212. resolve(res)
  213. })
  214. })
  215. let promise2 = new Promise((resolve, reject) => {
  216. zoneQuery(params2, res => {
  217. resolve(res)
  218. })
  219. })
  220. Promise.all([promise1, promise2]).then(values => {
  221. this.pointData = values[0].Content;
  222. this.spaceDetails = values[1].Content[0];
  223. this.getOutline();
  224. // if (this.spaceDetails.Outline && this.spaceDetails.Outline[0] && this.spaceDetails.Outline[0].length) {
  225. // this.getSpaceFloor();
  226. // }
  227. let obj = values[1].Content[0] ? this.deepCopy(values[1].Content[0]) : values[1].Content[0];
  228. obj = tools.flattenKeys(obj);
  229. for(let key in obj) {
  230. if(Array.isArray(obj[key]) && !obj[key].length) {
  231. delete obj[key]
  232. }
  233. }
  234. this.instance = obj;
  235. this.getInFormationPoitnName();
  236. this.handleRadios(this.radio);
  237. })
  238. },
  239. getOutline(){
  240. zoneQueryOutline({
  241. Filters: `RoomID="${this.$route.query.RoomID}"`,
  242. ZoneType: this.$route.query.zone
  243. },res => {
  244. if(res.Content[0]&&res.Content[0].Outline&&res.Content[0].Outline.length){
  245. this.spaceDetails.Outline = res.Content[0].Outline;
  246. this.getSpaceFloor();
  247. }
  248. })
  249. },
  250. deepCopy(obj) {
  251. return JSON.parse(JSON.stringify(obj))
  252. },
  253. getSpaceFloor() {
  254. // 获取业务空间楼层
  255. let params = {
  256. Filters: `FloorID='${this.spaceDetails.FloorId}'`
  257. }
  258. floorQuery(params, res => {
  259. if (res.Content[0] && res.Content[0].StructureInfo && res.Content[0].StructureInfo.FloorMap) {
  260. this.FloorMap = res.Content[0].StructureInfo.FloorMap;
  261. this.getGraphy();
  262. }
  263. })
  264. },
  265. getGraphy() {// 绘制空间位置图片
  266. let that = this;
  267. that.clearGraphy()
  268. that.scene = new DivideFloorScene();
  269. this.canvasLoading = true;
  270. that.scene.loadUrl(`/image-service/common/file_get?systemId=revit&key=${this.FloorMap}`).then(res => {
  271. that.canvasLoading = false;
  272. if (res == 'error') {
  273. this.FloorMap = '';
  274. this.$message.warning('数据解析异常');
  275. return;
  276. }
  277. that.view.scene = that.scene;
  278. that.view.fitSceneToView();
  279. let tempArr = {
  280. RoomLocalName: this.spaceDetails.RoomLocalName,
  281. OutLine: this.spaceDetails.Outline,
  282. RoomID: this.spaceDetails.RoomID,
  283. Color: "#F56C6C",
  284. HighLightFlag: true
  285. }
  286. that.scene.addZoneList([tempArr]);
  287. this.scene.isSpaceSelectable = false;
  288. })
  289. },
  290. clearGraphy() {
  291. if (this.view && this.view.scene) {
  292. this.view.scene = null;
  293. return
  294. }
  295. this.view = new FloorView('floorCanvas')
  296. },
  297. getInFormationPoitnName() {// 获取动态数据
  298. let proId = localStorage.getItem('projectId');
  299. let secret = localStorage.getItem('secret');
  300. let params = {
  301. data: {
  302. Filters: 'InputMode in ["L1","L2","L","M"]',
  303. Orders: "sort asc",
  304. PageNumber: 1,
  305. PageSize: 500
  306. },
  307. type: this.$route.query.zone
  308. }
  309. let param = {
  310. secret: secret,
  311. ProjId: proId,
  312. data: {
  313. criterias: []
  314. }
  315. }
  316. getDataDictionary(params, res => {// 获取表号功能号
  317. // this.tableData = res.Content;
  318. if (this.onlyMessage) {
  319. this.tableData = res.Content.filter(i => i.Visible)
  320. } else {
  321. this.tableData = res.Content
  322. }
  323. this.tableData.map(item => {
  324. let cur = tools.dataForKey(this.spaceDetails, item.Path);
  325. // item.functionNo = cur;
  326. param.data.criterias.push({
  327. id: this.spaceDetails.RoomID,
  328. code: item.InfoPointCode
  329. });
  330. })
  331. BeatchQueryParam(param, res => {// 获取动态数据
  332. res.Content.forEach((item, index) => {
  333. this.$set(this.tableData[index], 'functionNo', item.data)
  334. this.$set(this.tableData[index], 'functionNoTime', item.receivetime)
  335. tools.setDataForKey(
  336. this.spaceDetails,
  337. this.tableData[index].Path,
  338. this.$set(this.tableData[index], "functionNoDynamicData", item.interrupt ? '已断数' : (item.error ? item.value ? "表号功能号不存在" : "未维护" : "暂未采集到实时数据"))
  339. );
  340. })
  341. });
  342. })
  343. },
  344. handleCheckbox(val) {
  345. this.onlyMessage = val
  346. this.getInFormationPoitnName()
  347. },
  348. displayData(arr) {//对数据进行处理传给组件展示
  349. const result = {}
  350. const resultEnergy = {};
  351. arr.forEach(i => {
  352. if (this.instance && this.instance.hasOwnProperty(i.Path) && this.currentRadio != 2) {
  353. i.value = this.instance[i.Path]
  354. }
  355. if (i.InputMode == 'C5') {
  356. if (this.instance && this.instance.hasOwnProperty(i.Path)) {
  357. let time = this.instance[i.Path]
  358. i.value = this.formatDate(time)
  359. }
  360. }
  361. if (i.DataSource && i.DataSource.length) {
  362. let source = JSON.parse(i.DataSource)
  363. //判断输入类型
  364. if (i.InputMode == 'D1L') {
  365. let d1l = tools.formatDataSource(i.DataSource)
  366. d1l.forEach(k => {
  367. if (k.Code == this.instance[i.Path]) {
  368. i.value = k.Name
  369. }
  370. })
  371. } else if (i.InputMode == 'D2' || i.InputMode == 'C6') {
  372. if (this.instance && this.instance.hasOwnProperty(i.Path)) {
  373. if (!Array.isArray(this.instance[i.Path])) {
  374. let transArray = this.instance[i.Path].split(',')
  375. i.value = source.filter(item => transArray.includes(item.Code)).map(item => item.Name).join(',')
  376. }
  377. }
  378. }
  379. source.forEach(j => {
  380. if (this.instance && j.Code == this.instance[i.Path]) {
  381. i.value = j.Name
  382. }
  383. })
  384. }
  385. switch (i.InputMode) {
  386. case "L":
  387. case "L1":
  388. case "L2":
  389. case "M":
  390. break;
  391. default:
  392. if (result[`${i.FirstName}${i.SecondName ? '/' + i.SecondName : ''}`]) {
  393. result[`${i.FirstName}${i.SecondName ? '/' + i.SecondName : ''}`].paths.push({
  394. Path: i.Path,
  395. InfoPointName: i.InfoPointName,
  396. InfoPointCode: i.InfoPointCode,
  397. Value: i.value,
  398. Visible: i.Visible,
  399. KeyWord: i.KeyWord,
  400. InputMode: i.InputMode
  401. })
  402. } else {
  403. result[`${i.FirstName}${i.SecondName ? '/' + i.SecondName : ''}`] = {
  404. paths: [{
  405. Path: i.Path,
  406. InfoPointName: i.InfoPointName,
  407. InfoPointCode: i.InfoPointCode,
  408. Value: i.value,
  409. Visible: i.Visible,
  410. KeyWord: i.KeyWord,
  411. InputMode: i.InputMode
  412. }]
  413. }
  414. }
  415. }
  416. })
  417. this.exhibitionBaseInformation.information = result
  418. },
  419. changRadio(val) {
  420. this.handleRadios(val)
  421. this.radio = val
  422. },
  423. handleRadios(val) {
  424. let arr = []
  425. if (val == 1) {
  426. arr = this.pointData
  427. } else {
  428. let list = this.pointData
  429. list.map(j => {
  430. if (this.instance.hasOwnProperty(j.Path)) {
  431. return {
  432. ...j,
  433. value: this.instance[j.Path]
  434. }
  435. }
  436. })
  437. arr = list.filter(k => k.value)
  438. }
  439. this.displayData(arr)
  440. }
  441. },
  442. watch: {
  443. // 监听路由地址,并判断有RoomID和zone,重新请求空间数据
  444. "$route"(to, from) {
  445. if (this.$route.name === "spaceLedger" && this.$route.query.RoomID && this.$route.query.zone) {
  446. this.getData();
  447. }
  448. }
  449. }
  450. }
  451. </script>
  452. <style lang="less" scoped>
  453. .box.screen-router {
  454. padding: 0;
  455. section {
  456. .el-container {
  457. padding: 0;
  458. }
  459. }
  460. }
  461. .el-header {
  462. padding: 0;
  463. height: 30px !important;
  464. margin-top: -10px;
  465. .boxName {
  466. color: #fff;
  467. font-size: 16px;
  468. line-height: 50px;
  469. height: 50px !important;
  470. padding: 0 10px;
  471. background-color: #3f4f62;
  472. }
  473. .spaceName {
  474. font-size: 14px;
  475. line-height: 30px;
  476. border-bottom: 1px solid #e4e7ed;
  477. box-sizing: border-box;
  478. }
  479. }
  480. .el-aside {
  481. color: #333;
  482. border: 1px solid #e4e7ed;
  483. margin-top: 10px;
  484. padding: 10px;
  485. box-sizing: border-box;
  486. height: calc(100% - 10px);
  487. overflow: hidden;
  488. .aside-top {
  489. overflow: hidden;
  490. display: flex;
  491. .aside-top-left {
  492. flex: 3;
  493. }
  494. .aside-top-right {
  495. float: right;
  496. img {
  497. margin-left: -10px;
  498. width: 140px;
  499. height: 140px;
  500. }
  501. }
  502. }
  503. .space-img {
  504. width: 100%;
  505. .img-box {
  506. float: left;
  507. position: relative;
  508. width: 47%;
  509. height: 180px;
  510. margin: 10px 10px 0 0;
  511. overflow: hidden;
  512. img {
  513. position: absolute;
  514. left: 50%;
  515. top: 50%;
  516. transform: translate(-50%, -50%);
  517. width: 100%;
  518. }
  519. }
  520. }
  521. }
  522. .el-scrollbar {
  523. width: 430px;
  524. height: 100%;
  525. overflow-x: hidden !important;
  526. }
  527. .el-main {
  528. color: #333;
  529. /*text-align: center;*/
  530. overflow: hidden;
  531. width: 100%;
  532. padding: 10px 0 0 10px;
  533. }
  534. .el-tabs.el-tabs--card.el-tabs--top {
  535. height: 100% !important;
  536. width: 100%;
  537. }
  538. .objectRelationship {
  539. height: 100%;
  540. width: 100%;
  541. display: flex;
  542. .objectRelationship-left,
  543. .objectRelationship-center,
  544. .objectRelationship-right {
  545. flex: 1;
  546. margin-right: 10px;
  547. text-align: left;
  548. height: 100% !important;
  549. }
  550. }
  551. #pane-dynamicData {
  552. height: calc(100% - 10px);
  553. }
  554. .el-tab-pane {
  555. height: 100%;
  556. }
  557. #pane-staticData {
  558. div {
  559. height: 100%;
  560. }
  561. }
  562. .unit {
  563. color: rgb(167, 167, 167);
  564. }
  565. #floorCanvas {
  566. position: static;
  567. }
  568. /deep/ .el-scrollbar__wrap {
  569. height: 100%;
  570. overflow-x: hidden !important;
  571. overflow-y: auto !important;
  572. }
  573. .objectRelationship {
  574. height: calc(100% - 46px) !important;
  575. }
  576. /deep/ .el-tabs__content {
  577. height: 100%;
  578. }
  579. </style>