index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. <!--
  2. revit业务空间
  3. -->
  4. <template>
  5. <div id="businessSpace">
  6. <!-- 空间属于多个建筑楼层 -->
  7. <roomInFloorDialog ref="roomInFloorDialog" @relaSuc="relaSuc"></roomInFloorDialog>
  8. <!--------- 页面头部 -------------->
  9. <div class="saga-title" v-show="!needCalculate">
  10. <div class="saga-build-mess">
  11. <div style="margin-left: 10px;float: left;">
  12. <span style="color: #999999;font-size: 14px;margin-right: 12px;">建筑楼层</span>
  13. <el-cascader :options="options" @change="changeCascader" placeholder="请选择建筑楼层" ref="cascaderAddr" v-model="buildFloorSelectd">
  14. <template slot-scope="{ node, data }">
  15. <span>{{ data.label }}</span>
  16. <i class="el-icon-warning-outline" v-if="data.count" style="color:red;margin-right:10px;"></i>
  17. </template>
  18. </el-cascader>
  19. </div>
  20. <input type="hidden" v-model="zoneItemID">
  21. </div>
  22. <div class="saga-build-tab">
  23. <el-radio-group v-model="isMyTab" @change="changeRadio" style="width: 136px;">
  24. <el-radio-button label="1">平面图</el-radio-button>
  25. <el-radio-button label="2" class="space-own-radio" style="width: 68px;">列表</el-radio-button>
  26. </el-radio-group>
  27. </div>
  28. <div class="saga-build-tips" v-if="mutiCount>0" @click="getTips">有{{ mutiCount }}个空间同时属于多个建筑楼层,点击处理</div>
  29. </div>
  30. <div class="saga-business-sapce-main" v-show="!needCalculate">
  31. <el-row class="spaceTypes">
  32. <div class="types">
  33. <el-tabs v-model="activeName" type='card' @tab-click="tabClick">
  34. <template v-for="(item,index) in tabsList">
  35. <el-tab-pane :name="item.code" :key="index">
  36. <span slot="label"><i class="el-icon-warning-outline" v-if="item.count>0"
  37. style="color:red;margin-right:10px;"></i>{{ item.name }}</span>
  38. </el-tab-pane>
  39. </template>
  40. </el-tabs>
  41. </div>
  42. </el-row>
  43. <div v-show="isMyTab == 1" style="width:100%;height:100%">
  44. <graphy @getSp="checkSpace" @dimension="checkSpace" @businessDetails="getBuinessDetails" ref="graphy" @copyID="copyID"
  45. @updateState="updateStateSuc"></graphy>
  46. </div>
  47. <div v-show="isMyTab == 2">
  48. <handsontable-main @lookEqu="lookEqu" ref="handsontable" :zoneCode="activeName" :otherType="otherType" :id="`handsontable${activeName}`">
  49. </handsontable-main>
  50. </div>
  51. <div class="infectedTips" v-show="isMyTab==1">
  52. <p v-if="repeatFloor.length" class="repeatTips">{{repeatTextTips}}</p>
  53. <p v-if="infectedTotal>0">因底图变化而受影响的业务空间{{ infectedTotal.toString() }}个<span v-show="buildFloorSelectd.length>1">,本层受影响的业务空间{{ infectedCurfloor.toString() }}个</span>
  54. </p>
  55. </div>
  56. </div>
  57. <div v-show="needCalculate" style="display:flex;align-items:center;justify-content:center;height:100%;background-color:#fff;">
  58. <div class="center" style="flex:1">
  59. <i class="iconfont icon-jianzhu" style="font-size:50px;"></i>
  60. <p style="margin:10px 0;">空间关系已发生变化,请更新关系后再使用业务空间台账</p>
  61. <p style="margin:10px 0;">前往【全部关系总览】中重新计算“建筑下的空间”“楼层下的空间”关系</p>
  62. <el-button @click="jumpToAllRelation">立即跳转</el-button>
  63. </div>
  64. </div>
  65. </div>
  66. </template>
  67. <script>
  68. import graphy from "@/components/old-adm/business_space/newGraphy/graphy";
  69. import roomInFloorDialog from "@/components/old-adm/business_space/newAddDialogs/roomInFloorDialog";
  70. import handsontableMain from "@/components/old-adm/business_space/business/handsontable";
  71. import {businessSpaceController} from '@/controller/old-adm/businessSpaceController';
  72. import floorCascader from "@/components/old-adm/ledger/components/lib/floorCascader";
  73. import { mapGetters } from "vuex";
  74. export default {
  75. components: {
  76. graphy,
  77. handsontableMain,
  78. roomInFloorDialog,
  79. floorCascader,
  80. },
  81. computed: {
  82. ...mapGetters('layout', ['projectId', 'userId', 'secret']),
  83. repeatTextTips() {
  84. let str = `当前楼层与${this.repeatFloor.join('、')}关联同一个平面图`
  85. if (!this.handled) {
  86. str += `,请通过「建筑楼层管理」页面处理`
  87. }
  88. return str
  89. }
  90. },
  91. data() {
  92. return {
  93. floor: {
  94. influence: false, //受影响的业务空间弹窗
  95. details: false, //详情弹窗
  96. notRelated: false,
  97. facility: false
  98. },
  99. param: {
  100. ProjId: this.projectId, //项目id
  101. UserId: this.userId, //用户id
  102. secret: this.secret
  103. },
  104. buildMess: {
  105. name: "--",
  106. code: "",
  107. selectd: [],
  108. map: "",
  109. isChild: true,
  110. buildName: "--",
  111. buildCode: ""
  112. },
  113. isMyTab: 1,
  114. activeName: "0",
  115. tabsList: [],
  116. activeTabType: {
  117. "code": "GeneralZone",
  118. "name": "默认分区",
  119. "rel_type": "99"
  120. },
  121. options: [], //建筑楼层级联下拉
  122. floorToMap: {}, //楼层及其对应的模型图
  123. FloorMap: "", //当前选中的楼层对象
  124. zoneItemID: '',
  125. buildFloorSelectd: [''], //当前所选的建筑楼层
  126. childBackParam: {},
  127. needCalculate: false, // 关系是否需要计算
  128. mutiCount: 0,
  129. infectedTotal: 0,
  130. infectedCurfloor: 0,
  131. otherType: '',
  132. tabsListLoadOver: false,
  133. isGetType: true, // 防止请求图时 分区类型还没有请求回来
  134. repeatFloor: [], // 与当前楼层重复的其他楼层
  135. handled: false, // 是否已处理重复,需求未明确指出
  136. modelIdToFloor: {}, // 楼层 modelid 到楼层对象的映射
  137. };
  138. },
  139. created() {
  140. this.getRelations()
  141. this.childBackParam = this.$route.params;
  142. },
  143. mounted() {
  144. },
  145. methods: {
  146. // 初始化
  147. init() {
  148. this.getTypes()
  149. this.getBuilding()
  150. this.getMutiCount()
  151. this.getInfected();
  152. },
  153. // 获取项目下建筑
  154. getBuilding() {
  155. businessSpaceController.queryBFloorWithState({}, res => {
  156. this.modelIdToFloor = {};
  157. this.options = res.content.map(t => {
  158. t.value = t.id;
  159. t.label = t.localName || t.localId;
  160. t.count = 0;
  161. if (t.floor) {
  162. t.children = t.floor.map(item => {
  163. item.value = item.id;
  164. item.label = item.localName || item.name;
  165. item.buildName = t.localName || t.name;
  166. this.floorToMap[item.id] = item;
  167. if (item.count > 0) {
  168. t.count++;
  169. }
  170. if (item.modelId) {
  171. if (this.modelIdToFloor[item.modelId]) {
  172. this.modelIdToFloor[item.modelId].push(item);
  173. } else {
  174. this.modelIdToFloor[item.modelId] = [item]
  175. }
  176. }
  177. return item;
  178. })
  179. t.children.unshift({ value: "all", label: "全部" }, { value: 'noKnow', label: "未明确楼层" })
  180. } else {
  181. t.children = []
  182. }
  183. return t;
  184. })
  185. this.options.unshift({ value: "all", label: "全部" }, { value: "noKnow", label: "未明确建筑" })
  186. if (this.childBackParam.buildFloorSelectd) {
  187. this.buildFloorSelectd = this.childBackParam.buildFloorSelectd;
  188. }
  189. if (this.childBackParam.zone) {
  190. this.changeCascader(this.buildFloorSelectd);
  191. }
  192. })
  193. },
  194. // 获取受影响统计
  195. getInfected(floor) {
  196. let pa = {
  197. filters: `state=1`
  198. }
  199. if (floor) {
  200. pa.filters += `;floorId="${floor}"`
  201. }
  202. businessSpaceController.zoneCount(pa, res => {
  203. if (floor) {
  204. this.infectedCurfloor = res.count
  205. } else {
  206. this.infectedTotal = res.count
  207. }
  208. })
  209. },
  210. // 切换平面图和列表
  211. changeRadio(val) {
  212. this.changeGraphyOrTable(val)
  213. },
  214. // 获取tabs的列表
  215. getTypes(floorid) {
  216. let pa = {
  217. // Cascade: [{ Name: 'zoneType' }]
  218. }
  219. if (floorid) {
  220. pa.floorId = floorid
  221. }
  222. businessSpaceController.queryAllZoneType(pa, res => {
  223. this.tabsList = res.content.map(t => {
  224. if (t.name == "元空间") {
  225. return undefined;
  226. }
  227. return t;
  228. }).filter(item => item);
  229. this.tabsListLoadOver = true;
  230. if (this.childBackParam.zone) {
  231. this.activeName = this.childBackParam.zone;
  232. this.buildFloorSelectd = this.childBackParam.buildFloorSelectd;
  233. this.isMyTab = this.childBackParam.isMyTab;
  234. this.otherType = this.childBackParam.otherType;
  235. } else if (this.activeName == '0') {
  236. this.activeName = 'GeneralZone';
  237. }
  238. })
  239. },
  240. // 获取多建筑楼层统计
  241. getMutiCount() {
  242. businessSpaceController.getSpaceBdFlCount({}, res => {
  243. this.mutiCount = res.count;
  244. if (this.mutiCount > 0) {
  245. this.getTips();
  246. }
  247. })
  248. },
  249. // 获取关系是否需要计算
  250. getRelations() {
  251. let pa = {
  252. filters: `relationType in ["bd2sp","fl2sp"];computationalState>1`
  253. }
  254. // 后台暂无接口提供 todo
  255. businessSpaceController.getrelationTypeProject(pa, res => {
  256. if (res.content.length) {
  257. this.needCalculate = true;
  258. } else {
  259. this.needCalculate = false;
  260. this.init()
  261. }
  262. })
  263. },
  264. // 通过选中的tab-Code 获取选中的tab的所有数据
  265. getItemForType() {
  266. let data = {}
  267. this.tabsList.map(item => {
  268. if (item.code == this.activeName) {
  269. data.code = item.code;
  270. data.name = item.name;
  271. }
  272. })
  273. return data
  274. },
  275. // 点击tab
  276. tabClick(val) {
  277. this.changeGraphyOrTable(this.isMyTab)
  278. },
  279. //修改所选建筑楼层
  280. changeCascader(val) {
  281. this.buildFloorSelectd = val;
  282. this.$nextTick(() => {
  283. let node = this.$refs['cascaderAddr'].getCheckedNodes()
  284. let name = node[0].pathLabels
  285. name = name.join(' ')
  286. localStorage.setItem('buildingFloor', name)
  287. })
  288. // 如果选择的是全部或者未明确
  289. if (val.indexOf('noKnow') > -1 || val.indexOf('all') > -1) {
  290. this.getTypes()
  291. this.isMyTab = 2;
  292. this.FloorMap = {}
  293. } else {
  294. // 选择的是具体某个楼层
  295. if (!this.floorToMap[val[1]].infos || !this.floorToMap[val[1]].infos.floorMap) {
  296. this.isMyTab = 2;
  297. }
  298. this.getTypes(val[1]);
  299. this.FloorMap = this.floorToMap[val[1]];
  300. }
  301. this.changeGraphyOrTable(this.isMyTab);
  302. this.setRepeatText()
  303. },
  304. // 判断切换至图还是表
  305. changeGraphyOrTable(num) {
  306. this.activeTabType = this.getItemForType()
  307. if (!this.buildFloorSelectd[0]) {
  308. this.$message.warning('请选择建筑楼层')
  309. return
  310. }
  311. if (!this.activeTabType.code) {
  312. this.isGetType = false;
  313. return
  314. }
  315. if (num == 2) {
  316. this.initMessage();
  317. } else {
  318. this.getInfected(this.buildFloorSelectd[1]);
  319. ///
  320. console.log(this.FloorMap, '========================');
  321. this.isGetType = true;
  322. this.$refs.graphy.getData(this.buildFloorSelectd, this.FloorMap, this.activeTabType);
  323. this.childBackParam = {}
  324. }
  325. },
  326. // 设置平面图重复显示文本
  327. setRepeatText() {
  328. if (this.buildFloorSelectd.indexOf('noKnow') > -1 || this.buildFloorSelectd.indexOf('all') > -1) {
  329. this.repeatFloor = []
  330. } else {
  331. const fId = this.buildFloorSelectd[1]
  332. const mId = this.floorToMap[fId].modelId;
  333. if (mId) {
  334. const fList = this.modelIdToFloor[mId];
  335. if (fList.length < 2) {
  336. this.repeatFloor = []
  337. } else {
  338. this.repeatFloor = fList.map(t => {
  339. if (t.id != fId) {
  340. return `${t.buildName}-${t.localName}`
  341. }
  342. }).filter(item => item);
  343. }
  344. }
  345. }
  346. },
  347. // 触发获取表头-获取初始化信息点
  348. initMessage() {
  349. this.$refs.handsontable.getHeader(this.activeName, this.buildFloorSelectd);
  350. },
  351. checkSpace(list, build, graphyId) {
  352. this.floor.notRelated = true;
  353. this.$refs.notRelated.getIdList(list, build, graphyId, this.activeTabType);
  354. this.$refs["graphy"].getHasSpace();
  355. },
  356. changeShow() {
  357. this.floor.dialogVisible = true;
  358. console.log(this.buildMess, 'buildMess')
  359. },
  360. //成功关联平面图
  361. createSuccess() {
  362. this.$refs["graphy"].getHasSpace();
  363. this.$refs["graphy"].clearDimension();
  364. this.floor.notRelated = false;
  365. },
  366. //成功删除业务空间
  367. delSuccess() {
  368. this.floor.details = false;
  369. this.$refs["graphy"].getHasSpace();
  370. this.$refs["graphy"].clearDimension();
  371. },
  372. //查看业务空间详情
  373. getBuinessDetails(list) {
  374. this.floor.details = true;
  375. this.$refs.details.getData(list, this.buildMess);
  376. },
  377. lookEqu(infos) {
  378. infos.id = infos.id
  379. infos.name = infos.localName
  380. this.floor.facility = true
  381. this.$refs.facility.getData(infos, this.buildMess)
  382. },
  383. copyID(val) {
  384. this.$refs.handsontable.keyWord = val;
  385. },
  386. // 空间属于多个建筑楼层
  387. getTips() {
  388. this.$refs.roomInFloorDialog.showDialog();
  389. },
  390. // 跳转至关系总览
  391. jumpToAllRelation() {
  392. this.$router.push({path: '/relation/overview', name: 'overView' })
  393. },
  394. relaSuc() {
  395. this.init();
  396. if (this.buildFloorSelectd.length > 1) {
  397. this.changeCascader(this.buildFloorSelectd)
  398. }
  399. },
  400. // 受影响业务空间确认成功回调
  401. updateStateSuc() {
  402. this.getBuilding()
  403. this.getTypes(this.buildFloorSelectd[1]);
  404. this.infectedTotal--;
  405. this.infectedCurfloor--;
  406. }
  407. },
  408. watch: {
  409. floor: {
  410. deep: true,
  411. handler: function () {
  412. if (this.floor.notRelated) {
  413. this.$refs["graphy"].clearDimension();
  414. }
  415. }
  416. },
  417. projectId() {
  418. this.getRelations();
  419. },
  420. tabsListLoadOver: {
  421. handler: function (n) {
  422. if (n) {
  423. if (!this.isGetType) {
  424. console.log(n, '0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0');
  425. this.changeGraphyOrTable(this.isMyTab)
  426. }
  427. }
  428. }
  429. }
  430. }
  431. };
  432. </script>
  433. <style lang="less">
  434. #businessSpace {
  435. position: relative;
  436. display: flex;
  437. flex-direction: column;
  438. .space-own-radio {
  439. .el-radio-button__inner {
  440. padding: 9px 21px;
  441. }
  442. }
  443. .el-dialog__body {
  444. max-height: 600px;
  445. overflow-y: auto;
  446. }
  447. .saga-title {
  448. height: 54px;
  449. background-color: #fff;
  450. font-size: 14px;
  451. position: relative;
  452. line-height: 54px;
  453. margin-bottom: 10px;
  454. border: 1px solid #dfe6ec;
  455. .saga-build-mess {
  456. // position: absolute;
  457. // left: 10px;
  458. width: 500px;
  459. margin-left: 10px;
  460. i {
  461. padding-right: 5px;
  462. }
  463. p {
  464. float: left;
  465. }
  466. .saga-btn {
  467. float: left;
  468. height: 40px;
  469. line-height: 40px;
  470. padding: 0 10px;
  471. }
  472. }
  473. .saga-build-tab {
  474. position: absolute;
  475. left: 50%;
  476. transform: translateX(-50%);
  477. .tab-main {
  478. float: left;
  479. width: 120px;
  480. padding: 0 5px;
  481. margin: 5px 0;
  482. border: 1px solid #ccc;
  483. background-color: #fff;
  484. height: 30px;
  485. box-sizing: border-box;
  486. text-align: center;
  487. cursor: pointer;
  488. overflow: hidden;
  489. i {
  490. font-size: 18px;
  491. padding-right: 10px;
  492. float: left;
  493. line-height: 30px;
  494. margin-left: 10px;
  495. }
  496. span {
  497. line-height: 30px;
  498. float: left;
  499. }
  500. }
  501. .tab-active {
  502. background-color: #409eff;
  503. color: #fff;
  504. }
  505. }
  506. .saga-build-tips {
  507. float: right;
  508. margin-right: 10px;
  509. font-size: 12px;
  510. color: #409eff;
  511. cursor: pointer;
  512. }
  513. }
  514. .saga-business-sapce-main {
  515. overflow: hidden;
  516. height: 100%;
  517. background: #fff;
  518. // padding: 10px;
  519. /deep/ .el-tabs__item.is-top {
  520. border-top: 2px solid transparent;
  521. &.is-active {
  522. border-top: 2px solid #409eff;
  523. }
  524. }
  525. .infectedTips {
  526. position: absolute;
  527. bottom: 0px;
  528. box-sizing: border-box;
  529. width: 100%;
  530. padding: 0 20px;
  531. line-height: 40px;
  532. background: #ec808d;
  533. color: #fff;
  534. z-index: 9;
  535. .repeatTips{
  536. overflow: hidden;
  537. white-space: nowrap;
  538. text-overflow: ellipsis;
  539. }
  540. }
  541. }
  542. .spaceTypes {
  543. padding: 10px 10px 0;
  544. .types {
  545. float: left;
  546. width: 100%;
  547. // width: calc(100% - 200px);
  548. }
  549. .groupAdd {
  550. float: left;
  551. width: 200px;
  552. text-align: right;
  553. height: 40px;
  554. border-bottom: 1px solid #e4e7ed;
  555. }
  556. }
  557. }
  558. </style>