business.vue 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380
  1. <template>
  2. <div ref="graphyMain" class="canvasGraphy" style="width:100%;" v-loading="loading.show" :element-loading-text="loading.num + '/' + loading.total">
  3. <div v-show="hasMap" class="header-search">
  4. <!-- 初始两个按钮 -->
  5. <div v-show="type == 1">
  6. <el-button @click=" type = 2" icon="el-icon-search">查找业务空间</el-button>
  7. <el-button @click="myDialogVisible = true">创建业务空间</el-button>
  8. <span style="font-size:13px;color:#606266;margin-left:40px;display:inline-block;">
  9. 提示:
  10. <i style="color:red;">红色字体</i>的业务空间为不相邻元空间组成,请检查是否要修改
  11. </span>
  12. </div>
  13. <!-- 搜索下拉列表定位 -->
  14. <div v-show="type == 2">
  15. <el-autocomplete popper-class="my-autocomplete" v-model="search" :fetch-suggestions="querySearch" placeholder="输入平面图中已有的业务空间名称进行查找" width="180px" @select="handleSelect">
  16. <i class="el-icon-search el-input__icon" slot="suffix" @click="handleIconClick"></i>
  17. <template slot-scope="{ item }">
  18. <div class="name" style="position: relative;">
  19. {{ item.infos.RoomLocalName |cutString(8) }}
  20. <span
  21. class="addr"
  22. style="position: absolute;right:10px;color:#409EFF;"
  23. >定位</span>
  24. </div>
  25. </template>
  26. </el-autocomplete>
  27. <el-button style="margin-left:10px;" type="text" @click="clearDimension">收起</el-button>
  28. </div>
  29. <!-- 点击元空间显示 -->
  30. <div v-show="type == 3">
  31. <div class="div50">
  32. <el-button
  33. class="float-right"
  34. @click="SpaceDialog"
  35. type="primary"
  36. plain
  37. >从未关联元空间的业务空间中选择</el-button>
  38. </div>
  39. <div class="div50">
  40. <el-button @click="clearDimension" plain>取 消</el-button>
  41. <el-button @click="createSP" type="primary">创建新的业务空间</el-button>
  42. </div>
  43. </div>
  44. <!-- 点击业务空间显示 -->
  45. <div v-show="type == 4">
  46. <div class="div50">
  47. <el-button class="float-right" @click="divide" type="primary" plain>重新划分业务空间</el-button>
  48. </div>
  49. <div class="div50">
  50. <el-button @click="clearDimension" plain>取 消</el-button>
  51. <el-button @click="bussinDea" type="primary">查看详情</el-button>
  52. </div>
  53. </div>
  54. <!-- 点击业务空间后点击元空间 -->
  55. <div v-show="type == 5">
  56. <div class="div50">
  57. <el-button @click="clearDimension" class="float-right" plain>取 消</el-button>
  58. </div>
  59. <div class="div50">
  60. <el-button @click="saveChange" type="primary">保存修改</el-button>
  61. </div>
  62. </div>
  63. <el-button
  64. v-show="type == 1"
  65. @click="getPiss"
  66. style="position: absolute;top: 10px;right: 10px;"
  67. type="text"
  68. >未关联元空间的业务空间 {{num}} 条</el-button>
  69. </div>
  70. <div
  71. v-show="hasMap"
  72. ref="canvasWidth"
  73. class="canvasWidth"
  74. v-loading="myLoading"
  75. style="width:100%;"
  76. >
  77. <canvas :id="canvasId + 'canvas' " :width="canvasW" :height="canvasH"></canvas>
  78. <div
  79. style="height: 35px;overflow: hidden;z-index:99;transform: translateX(-50%);position: absolute;bottom: 10%;left: 50%;"
  80. >
  81. <el-button @click="smallSize" type="primary">- 缩小</el-button>
  82. <el-button @click="suitableSize" type="primary">合适比例</el-button>
  83. <el-button @click="bigSize" type="primary">+ 放大</el-button>
  84. <el-button @click="exportJson" type="primary" icon="el-icon-download">
  85. 导出json文件
  86. </el-button>
  87. </div>
  88. </div>
  89. <div
  90. v-show="!hasMap"
  91. class="center"
  92. style="height: 400px;padding-top:200px;box-sizing:border-box;"
  93. >
  94. <i class="icon-wushuju iconfont"></i>
  95. {{!!buildMess ? '请初始化平面图' : '请选择楼层'}}
  96. </div>
  97. <el-dialog title="提示" :visible.sync="dialogVisible" :before-close="clearDimension" width="30%">
  98. <p style="color:red;line-height:24px;margin-bottom: 10px;" v-show="isAbutMsg">注意:您选择的元空间并未相邻!</p>
  99. <p style="line-height:24px;margin-bottom: 10px;">请输入创建的业务空间名:</p>
  100. <!-- <p>
  101. <el-input
  102. placeholder="请输入业务空间名"
  103. v-model="name"
  104. clearable>
  105. </el-input>
  106. </p>-->
  107. <el-form
  108. :model="ruleForm"
  109. :rules="rules"
  110. ref="ruleForm"
  111. label-width="100px"
  112. class="demo-ruleForm"
  113. >
  114. <el-form-item label label-width="0" prop="name">
  115. <el-input v-model="ruleForm.name"></el-input>
  116. </el-form-item>
  117. </el-form>
  118. <span slot="footer" class="dialog-footer">
  119. <el-button @click="clearDimension">取 消</el-button>
  120. <el-button type="primary" @click="isTrue">确 定</el-button>
  121. </span>
  122. </el-dialog>
  123. <el-dialog title="提示" :visible.sync="myDialogVisible" width="30%">
  124. <p style="line-height:26px;">方法1:直接在平面图中点击单个或多个带⬇️标记的元空间创建业务空间</p>
  125. <p style="line-height:26px;">方法2:根据未关联业务空间的元空间批量创建业务空间</p>
  126. <span slot="footer" class="dialog-footer">
  127. <el-button @click="createBatchSq">批量创建业务空间</el-button>
  128. <el-button type="primary" @click="myDialogVisible = false">返回平面图手动选择</el-button>
  129. </span>
  130. </el-dialog>
  131. </div>
  132. </template>
  133. <script>
  134. import axios from "axios";
  135. //引擎的引用
  136. import {
  137. // SGraphyView,
  138. SGraphyScene,
  139. SGraphyRectItem,
  140. SGraphyLineItem,
  141. SGraphyPolygonItem,
  142. SGraphyVirtualItem,
  143. SGraphyImageItem,
  144. SGraphyPillarItems,
  145. mainScene
  146. } from "@/assets/graphy";
  147. import pako from '@/assets/pako/pako'
  148. import { SGraphyView } from "@sybotan-web/graphy";
  149. import { SPen, SPainter, SColor } from "@sybotan-web/draw";
  150. //ele动画组件
  151. import tools from "@/utils/scan/tools";
  152. let data = "";
  153. let scale = 120; //缩放比例
  154. let myData = [{
  155. Id: "1221512",
  156. PointList: {
  157. X: -35146.875,
  158. Y: 40680
  159. }
  160. }];
  161. // let colorArr = [
  162. // "rgba(0,245,255,.2)",
  163. // "rgba(255,218,185,.2)",
  164. // "rgba(132,112,255,.2)",
  165. // "rgba(127,255,0,.2)",
  166. // "rgba(238,92,66,.2)",
  167. // "rgba(255,255,224,.2)",
  168. // "rgba(238,233,233,.2)",
  169. // "rgba(156,156,156,.2)",
  170. // "rgba(144,238,144,.2)",
  171. // "rgba(180,205,205,.2)"
  172. // ];
  173. let colorArr = [
  174. "#F9C3C3",
  175. "#FFD1BF",
  176. "#FFF3BF",
  177. "#D8F7C6",
  178. "#C6F2F6",
  179. "#DCE3C0",
  180. "#FAE6C9",
  181. "#E3D7F7",
  182. "#C4CBF8",
  183. "#DEC3F6"
  184. ];
  185. // function hexify(color) {
  186. // var values = color
  187. // .replace(/rgba?\(/, '')
  188. // .replace(/\)/, '')
  189. // .replace(/[\s+]/g, '')
  190. // .split(',');
  191. // var a = parseFloat(values[3] || 1),
  192. // r = Math.floor(a * parseInt(values[0]) + (1 - a) * 255),
  193. // g = Math.floor(a * parseInt(values[1]) + (1 - a) * 255),
  194. // b = Math.floor(a * parseInt(values[2]) + (1 - a) * 255);
  195. // return "#" +
  196. // ("0" + r.toString(16)).slice(-2) +
  197. // ("0" + g.toString(16)).slice(-2) +
  198. // ("0" + b.toString(16)).slice(-2);
  199. // }
  200. // colorArr = colorArr.map(item => {
  201. // return hexify(item)
  202. // })
  203. // class MainScene extends SGraphyScene {
  204. // constructor() {
  205. // super();
  206. // //资产id
  207. // } // Function constructor()
  208. // /**
  209. // * 绘制背景
  210. // *
  211. // * @param canvas 画布
  212. // * @param rect 更新绘制区域
  213. // */
  214. // // drawBackground(canvas, rect) {}
  215. // }
  216. import {
  217. formBIMToPri, // 将bimId转换成物理世界id
  218. createBusiness, //添加业务空间
  219. createRelation, //添加关系
  220. getGraphyId, //获取图类型
  221. getBussines2, //获取业务空间
  222. getRelation, //获取业务空间下的元空间id
  223. deleteRelation, //删除关系
  224. isAbut
  225. } from "@/api/scan/request";
  226. import {mapGetters, mapActions} from "vuex";
  227. export default {
  228. name: "HelloWorld",
  229. props: {
  230. canvasId: {
  231. type: String
  232. }
  233. },
  234. computed: {
  235. ...mapGetters("layout", [
  236. "projectId",
  237. "secret",
  238. "userId"
  239. ])
  240. },
  241. data() {
  242. return {
  243. view: "",
  244. num: "",
  245. mainScene: null,
  246. dataMax: "", //最大值最小值数据
  247. scene: {
  248. x: 0,
  249. y: 0
  250. },
  251. dialogVisible: false, //浮层
  252. id: null,
  253. canvasH: 600,
  254. canvasW: 800,
  255. param: {
  256. ProjId: "", //项目id
  257. UserId: "", //用户id
  258. secret: ""
  259. },
  260. myDialogVisible: false,
  261. wallList: [], //处理后的墙的线条
  262. type: 1, //1 默认显示初始按钮, 2搜索下拉, 3点击元空间, 4点击业务空间
  263. restaurants: [],
  264. search: "",
  265. idList: [],
  266. buildMess: null,
  267. loading: {
  268. show: false,
  269. num: 0,
  270. total: 0,
  271. errorNum: 0
  272. },
  273. graphyId: "",
  274. relationList: [],
  275. myLoading: false,
  276. hasMap: false,
  277. ruleForm: {
  278. name: ""
  279. },
  280. rules: {
  281. name: [{
  282. required: true,
  283. message: "请输入需要创建的业务空间名称",
  284. trigger: "blur"
  285. }]
  286. },
  287. isAbutMsg: false, //是否相邻提示
  288. businessData: "", //新建业务空间数据
  289. spaceType: {}, //space类型code
  290. };
  291. },
  292. created() {
  293. this.param.ProjId = this.projectId
  294. this.param.secret = this.secret
  295. this.param.UserId = this.userId
  296. // this.getJson("Fl110108000327d8f006c39f49feb40e24a7ef22323220181119025802bim.jsonz")
  297. // this.getJson("bim.jsonz")
  298. },
  299. mounted() {
  300. console.log(this.canvasId)
  301. // this.resetSize();
  302. // window.addEventListener("click",this.typeTo1)
  303. },
  304. methods: {
  305. //获取数据
  306. getData(floorMap, buildMess, data) {
  307. this.spaceType = data
  308. this.loading.show = false;
  309. this.type = 1;
  310. this.idList = [];
  311. this.buildMess = buildMess;
  312. if (!floorMap) {
  313. this.hasMap = false;
  314. } else {
  315. this.getJson(floorMap);
  316. this.hasMap = true;
  317. }
  318. },
  319. clearList() {
  320. this.idList = []
  321. },
  322. //未关联元空间的业务空间
  323. getPiss() {
  324. this.$emit("getSp", [{}], this.buildMess, this.graphyId);
  325. },
  326. //查询绑定了元空间的业务空间
  327. getHasSpace() {
  328. console.log(this.spaceType, "spaceType")
  329. let param = {
  330. data: {
  331. criteria: {
  332. id: this.buildMess.code,
  333. // graphId: this.graphyId,
  334. // relType: this.spaceType.rel_type,
  335. // exclude: false,
  336. // side: 1,
  337. type: [this.spaceType.code],
  338. "include": [ // 可选, 只查询指定图/关系中的对象
  339. {
  340. "graphId": this.graphyId,
  341. "graphType": this.spaceType.code,
  342. "relType": this.spaceType.rel_type,
  343. "side": "toId",
  344. // "fromId": "", // 选填
  345. // "toId": "" // 选填
  346. }
  347. ]
  348. },
  349. },
  350. ProjId: this.param.ProjId,
  351. secret: this.param.secret
  352. }
  353. getBussines2(param)
  354. .then(res => {
  355. if (res.data.Result == "success") {
  356. this.restaurants = res.data.Content;
  357. let nameList = [];
  358. if (res.data.Content && res.data.Content.length) {
  359. this.relationList = res.data.Content.map(item => {
  360. nameList.push(item.infos.RoomLocalName);
  361. return item.id;
  362. });
  363. this.locationPath(this.relationList, nameList);
  364. }
  365. } else {
  366. this.$message.error(res.data.ResultMsg);
  367. }
  368. this.myLoading = false;
  369. })
  370. .catch(() => {
  371. // console.log("请求出错");
  372. });
  373. },
  374. //确定新建
  375. isTrue() {
  376. this.$refs.ruleForm.validate(valid => {
  377. if (valid) {
  378. this.loading.show = true;
  379. this.loading.num = 0;
  380. this.loading.total = 1 * 2;
  381. this.businessData.infos.RoomLocalName[0].value = this.ruleForm.name;
  382. this.createSpace(this.businessData, this.idList, true);
  383. this.dialogVisible = false;
  384. } else {
  385. // console.log("error submit!!");
  386. return false;
  387. }
  388. });
  389. },
  390. //查询未绑定元空间的业务空间
  391. getNoSpace() {
  392. getBussines2({
  393. data: {
  394. criteria: {
  395. id: this.buildMess.code,
  396. // graphId: this.graphyId,
  397. // relType: this.spaceType.rel_type,
  398. // exclude: false,
  399. // side: 1,
  400. type: [this.spaceType.code],
  401. "exclude": [ // 可选, 只查询指定图/关系中的对象
  402. {
  403. "graphId": this.graphyId,
  404. "graphType": this.spaceType.code,
  405. "relType": this.spaceType.rel_type,
  406. "side": "toId",
  407. // "fromId": "", // 选填
  408. // "toId": "" // 选填
  409. }
  410. ]
  411. },
  412. },
  413. ProjId: this.projectId,
  414. secret: this.secret
  415. })
  416. .then(res => {
  417. if (res.data.Result == "success") {
  418. this.num = res.data.Content.length;
  419. } else {
  420. this.$message.error(res.data.ResultMsg);
  421. }
  422. })
  423. .catch(() => {
  424. // console.log("请求出错");
  425. });
  426. },
  427. //当type=2时点击变成1
  428. typeTo1() {
  429. if (this.type == 2) {
  430. this.type = 1;
  431. }
  432. },
  433. getJson(jsonId) {
  434. axios({
  435. method: 'get',
  436. url: "/image-service/common/file_get/" + jsonId + "?systemId=revit",
  437. data: {},
  438. responseType: 'blob',
  439. // contentType: "charset=utf-8"
  440. })
  441. .then(res => {
  442. // console.log(res.data, "res.data")
  443. let data = null
  444. var blob = res.data;
  445. var reader = new FileReader();
  446. reader.readAsBinaryString(blob)
  447. // console.log("获取到了数据")
  448. let _this = this
  449. reader.onload = function(readerEvt) {
  450. // console.log("reader获取完毕")
  451. var binaryString = readerEvt.target.result;
  452. // let base64Data = btoa(binaryString)
  453. //解压数据
  454. let base64Data = btoa(binaryString)
  455. let unGzipData = pako.unzip(base64Data)
  456. // console.log(unGzipData)
  457. // console.log(unGzipData, "atob")
  458. data = unGzipData
  459. //导出json文件
  460. _this.exportJsonData = JSON.stringify(data);
  461. _this.jsonId = jsonId.split('.')[0];
  462. _this.dataMax = tools.getPoint(data);
  463. if (data.WallList && data.WallList.length) {
  464. tools.changeMap(data.WallList, -1, "PointList");
  465. }
  466. if (data.SpaceList && data.SpaceList.length) {
  467. tools.changeMap(data.SpaceList, -1, "Paths");
  468. }
  469. if (data.ColumnList && data.ColumnList.length) {
  470. tools.changeMap(data.ColumnList, -1, "Path");
  471. }
  472. if (data.VirtualWallList && data.VirtualWallList.length) {
  473. tools.changeMap(data.VirtualWallList, -1, "PointList");
  474. }
  475. if (data.EquipmentList && data.EquipmentList.length) {
  476. tools.changeMap(data.EquipmentList, -1, "PointList");
  477. }
  478. let ids = [];
  479. if (data.SpaceList && data.SpaceList.length) {
  480. data.SpaceList.map(items => {
  481. items.BimId = _this.buildMess.code + ":" + items.BimId;
  482. ids.push(items.BimId);
  483. });
  484. } else {
  485. _this.$message("没有元空间数据")
  486. }
  487. if(!!ids && ids.length){
  488. _this.bimIdToId(ids, data);
  489. }else{
  490. //没有id没有map
  491. _this.hasMap = false
  492. }
  493. _this.myLoading = true;
  494. };
  495. // console.log(reader)
  496. });
  497. },
  498. //获取图实例关系
  499. getGraphy() {
  500. getGraphyId({
  501. type: "ElementSptoSpace",
  502. ProjId: this.projectId,
  503. secret: this.secret
  504. })
  505. .then(res => {
  506. if (res.data.Result == "success") {
  507. this.graphyId = res.data.graph_id;
  508. this.getHasSpace();
  509. this.getNoSpace();
  510. } else {
  511. this.$message.error(res.data.ResultMsg);
  512. }
  513. })
  514. .catch(() => {
  515. this.$message.error("请求错误");
  516. });
  517. },
  518. bimIdToId(ids, data) {
  519. formBIMToPri({
  520. type: ["Si"],
  521. ids: ids,
  522. ProjId: this.param.ProjId,
  523. secret: this.param.secret
  524. })
  525. .then(res => {
  526. if (res.data.Result == "success") {
  527. data.SpaceList.map((item, index) => {
  528. res.data.Content.map((i, li) => {
  529. //判断bimId是否相同
  530. if (item.BimId == i.infos.BIMID) {
  531. item.id = i.id;
  532. }
  533. });
  534. });
  535. this.createCanvas();
  536. this.initGraphy(data);
  537. console.log("请求完毕")
  538. } else {
  539. this.$message.error(res.data.ResultMsg);
  540. }
  541. })
  542. .catch(() => {
  543. this.$message.error("请求出错");
  544. });
  545. },
  546. //创建实例
  547. createCanvas() {
  548. //初始化
  549. if (this.view.scene) {
  550. this.view.scene.root.children = [];
  551. this.view = null;
  552. }
  553. this.view = new SGraphyView(this.canvasId + "canvas", this.mainScene);
  554. // this.view.onDraw();
  555. // this.view.canvasView.addEventListener("mouseup", this.dataChange);
  556. // this.view.canvasView.addEventListener("mousemove", this.canvasMove);
  557. },
  558. //初始化canvas大小
  559. resetSize() {
  560. this.canvasW =
  561. document.getElementById("businessSpace").offsetWidth - 2;
  562. this.canvasH = document.getElementById("app").offsetHeight - 240;
  563. let classs = document.getElementsByClassName("canvasWidth");
  564. // for(let i = 0; i < classs.length;i++){
  565. // classs[i].style.height = this.canvasH + 'px'
  566. // }
  567. this.$refs.canvasWidth.style.height = this.canvasH + "px";
  568. },
  569. //实例化视图
  570. initGraphy(data) {
  571. this.resetSize();
  572. this.$nextTick(()=>{
  573. this.mainScene = new mainScene(data);
  574. this.view.scene = this.mainScene;
  575. this.view.fitSceneToView();
  576. this.mainScene.click(this,this.checkSpace)
  577. })
  578. // this.view.pos.x = this.view.pos.y = -50;
  579. // let equip = data.EquipmentList,
  580. // wall = data.WallList,
  581. // virtual = data.VirtualWallList,
  582. // space = data.SpaceList,
  583. // column = data.ColumnList,
  584. // spaceStr;
  585. // //空间
  586. // if (space && space.length) {
  587. // for (let i = 0; i < space.length; i++) {
  588. // if (space[i].Paths[1] && space[i].Paths[1].length >= 2) {
  589. // spaceStr = new SGraphyPolygonItem(
  590. // space[i].Paths[0],
  591. // 1,
  592. // "rgba(111,111,111,0.5)",
  593. // "#fff",
  594. // space[i].id, {
  595. // x: space[i].LocationPoint.X,
  596. // y: space[i].LocationPoint.Y * -1
  597. // },
  598. // space[i].Name,
  599. // space[i].Paths
  600. // );
  601. // this.mainScene.addItem(spaceStr);
  602. // }
  603. // }
  604. // for (let i = 0; i < space.length; i++) {
  605. // if (space[i].Paths[0] && space[i].Paths[0].length >= 2 && !!!space[i].Paths[1]) {
  606. // spaceStr = new SGraphyPolygonItem(
  607. // space[i].Paths[0],
  608. // 1,
  609. // "rgba(111,111,111,0.5)",
  610. // "#fff",
  611. // space[i].id, {
  612. // x: space[i].LocationPoint.X,
  613. // y: space[i].LocationPoint.Y * -1
  614. // },
  615. // space[i].Name
  616. // );
  617. // this.mainScene.addItem(spaceStr);
  618. // }
  619. // }
  620. // }
  621. // //获取中心点
  622. // let rect = this.view.scene.worldRect();
  623. // //初始化画布缩放比例
  624. // this.view.scale = 1;
  625. // //计算缩放比例
  626. // this.view.scale = Math.min(
  627. // this.view.width / (rect.width * 1.2),
  628. // this.view.height / (rect.height * 1.2)
  629. // );
  630. // this.view.minScale = this.view.scale / 10
  631. // this.view.maxScale = this.view.scale * 10
  632. // // 移动画布
  633. // this.view.pos.x =
  634. // (-(rect.right + rect.left) / 2) * this.view.scale + this.view.width / 2;
  635. // this.view.pos.y =
  636. // (-(rect.bottom + rect.top) / 2) * this.view.scale +
  637. // this.view.height / 2;
  638. // //点击事件
  639. // this.view.canvasView.addEventListener("click", this.checkSpace);
  640. //这里说是点击事件`
  641. this.getGraphy();
  642. },
  643. /** canvas事件------------------------------------------------------------------------------------*/
  644. //点击元空间
  645. checkSpace(e) {
  646. // let item = tools.mouseInElement(this.view, e);
  647. let item = e ;
  648. let items = this.mainScene.root.children;
  649. //点击业务空间
  650. if (
  651. item.businessId &&
  652. (item.isBusiness == 2 || item.isBusiness == 7)
  653. ) {
  654. // console.log("点击不可点击的业务空间", item);
  655. if (this.type == 2) {
  656. this.idList = [];
  657. items.map(i => {
  658. if (i.isBusiness == 3) {
  659. i.isBusiness = 2;
  660. }
  661. });
  662. }
  663. items.map(i => {
  664. if (i.isBusiness == 6) {
  665. i.isBusiness = 2;
  666. } else if (i.isBusiness == 3) {
  667. i.isBusiness = 1;
  668. }
  669. });
  670. this.type = 4;
  671. items.map(i => {
  672. if (i.isBusiness == 6) {
  673. i.isBusiness = 2;
  674. }
  675. if (i.businessId == item.businessId) {
  676. i.isBusiness = 6;
  677. }
  678. });
  679. this.idList.push({
  680. id: item.businessId,
  681. name: item.businessName || item.name
  682. });
  683. }
  684. //点击没有业务空间的元空间
  685. if (
  686. !item.businessId &&
  687. (item.isBusiness == 4 || item.isBusiness == 1) &&
  688. this.type != 5
  689. ) {
  690. console.log("点击的是没有业务空间的元空间",this.type, item);
  691. if (this.type == 4) {
  692. this.idList = [];
  693. items.map(i => {
  694. if (i.isBusiness == 6) {
  695. i.isBusiness = 2;
  696. } else if (i.isBusiness == 3) {
  697. i.isBusiness = 1;
  698. console.log(i)
  699. }
  700. });
  701. // console.log("清空", this.idList);
  702. }
  703. this.type = 3;
  704. item.isBusiness = 3;
  705. this.idList.push({
  706. id: item.id,
  707. name: item.businessName || item.name
  708. });
  709. }
  710. //在重新编辑业务空间状态
  711. if (
  712. this.type == 5 &&
  713. !item.businessId &&
  714. (item.isBusiness == 4 || item.isBusiness == 1)
  715. ) {
  716. item.isBusiness = 3;
  717. this.idList.push({
  718. id: item.id,
  719. name: item.businessName || item.name
  720. });
  721. }
  722. //在重新编辑时的提示
  723. if (
  724. item.businessId &&
  725. (item.isBusiness == 4 || item.isBusiness == 1)
  726. ) {
  727. // console.log("44444");
  728. item.isBusiness = 3;
  729. this.idList.push({
  730. id: item.id,
  731. name: item.businessName || item.name,
  732. parentId: item.businessId
  733. });
  734. }
  735. if (item.isBusiness == 5) {
  736. this.$message("该空间为业务空间,请勿点击");
  737. };
  738. // 点击之后对所有色块重新着色
  739. items.forEach((a)=>{
  740. this.isBusinessToColor(a)
  741. });
  742. },
  743. //isbusiness转换相应的颜色
  744. /**
  745. * @param item item类
  746. */
  747. isBusinessToColor(item){
  748. if (item.isBusiness == 1) {
  749. item.color = item.cacheColor || new SColor('#000');
  750. item.fillColor = new SColor('#000');
  751. item.width = item.cacheWidth;
  752. } else if (item.isBusiness == 2) {
  753. //已有id 的业务空间
  754. item.color = item.cacheColor || new SColor('#000');
  755. item.fillColor =item.cacheFillColor || new SColor('#F2F6FC');
  756. item.width = item.cacheWidth;
  757. } else if (item.isBusiness == 3) {
  758. //被选择的元空间
  759. item.color = item.cacheColor|| new SColor('#000');
  760. // item.width = 800;
  761. item.fillColor =new SColor('#1abc9c')
  762. } else if (item.isBusiness == 4) {
  763. item.color = new SColor(251,226,1,.8) || new SColor('#000');
  764. item.fillColor = item.cacheFillColor || new SColor('#F2F6FC');
  765. item.width = item.cacheWidth;
  766. } else if (item.isBusiness == 5) {
  767. item.width = item.cacheWidth;
  768. item.fillColor = new SColor(11,12,12,.2) || new SColor('#F2F6FC')
  769. } else if (item.isBusiness == 6) {
  770. item.color = new SColor(68,161,140,.4) || new SColor('#000');
  771. // item.width = 800;
  772. item.fillColor =new SColor('#1abc9c');
  773. } else if (item.isBusiness == 7) {
  774. item.width = item.cacheWidth;
  775. item.color = item.cacheColor || new SColor('#000');
  776. item.fillColor = item.cacheFillColor || new SColor('#F2F6FC');
  777. }
  778. },
  779. /** 搜索 ------------------------------------------------------------------------------ */
  780. querySearch(queryString, cb) {
  781. var restaurants = this.restaurants;
  782. var results = queryString ?
  783. restaurants.filter(this.createFilter(queryString)) :
  784. restaurants;
  785. // 调用 callback 返回建议列表的数据
  786. cb(results);
  787. },
  788. createFilter(queryString) {
  789. return restaurant => {
  790. return restaurant.infos.RoomLocalName.indexOf(queryString) > -1;
  791. };
  792. },
  793. handleSelect(item) {
  794. this.locationPath(item.id);
  795. },
  796. handleIconClick(ev) {
  797. this.locationPath(ev.id);
  798. },
  799. //定位
  800. locationPath(id, name) {
  801. let param = {
  802. criterias: {},
  803. ProjId: this.projectId,
  804. secret: this.secret
  805. },
  806. falg = false;
  807. //查询多个关系
  808. if (id instanceof Array) {
  809. falg = true;
  810. param.criterias.criterias = [];
  811. id.map(item => {
  812. param.criterias.criterias.push({
  813. to_id: item,
  814. graph_id: this.graphyId,
  815. rel_type: this.spaceType.rel_type
  816. });
  817. });
  818. } else {
  819. //查询单个关系
  820. param.criterias.criteria = {
  821. to_id: id,
  822. graph_id: this.graphyId,
  823. rel_type: this.spaceType.rel_type
  824. };
  825. }
  826. getRelation(param)
  827. .then(res => {
  828. if (res.data.Result == "success") {
  829. if (falg) {
  830. //多个关系渲染颜色
  831. this.relationList = [];
  832. id.map((item, index) => {
  833. let children = res.data.Content[index].Content.map(i => {
  834. if (!!i) {
  835. return i.from_id;
  836. } else {
  837. return undefined;
  838. }
  839. });
  840. this.relationList.push({
  841. id: item,
  842. name: name[index],
  843. children: children,
  844. isAdjacent: true
  845. });
  846. });
  847. this.relationList.reverse();
  848. // this.getColor(this.relationList);
  849. //判断相邻代码
  850. this.spaceIsAbut(this.relationList);
  851. } else {
  852. //单个是定位
  853. this.getPathToCanvas(res.data.Content[0].from_id);
  854. }
  855. } else {
  856. this.$message.error(res.data.ResultMsg);
  857. }
  858. })
  859. .catch(() => {
  860. this.$message.error("请求错误");
  861. });
  862. },
  863. //给canvas的items渲染色彩
  864. getColor(list) {
  865. // let items = this.mainScene.root.children;
  866. // list.map(item => {
  867. // if (item.children && item.children.length) {
  868. // item.children.map(space => {
  869. // items.map(canvas => {
  870. // if (canvas.id == space) {
  871. // canvas.businessId = item.id;
  872. // canvas.businessName = item.name;
  873. // }
  874. // });
  875. // });
  876. // }
  877. // });
  878. this.applyColor(list);
  879. },
  880. //渲染业务空间色彩
  881. applyColor(list) {
  882. let items = this.mainScene.root.children;
  883. items.map(item => {
  884. item.businessId = null;
  885. item.businessName = null;
  886. item.fillColor = new SColor('#F2F6FC');
  887. item.isBusiness = 1;
  888. });
  889. list.map((item, index) => {
  890. if (item.children && item.children.length) {
  891. item.children.map(space => {
  892. items.map(canvas => {
  893. if (canvas.id == space) {
  894. canvas.businessId = item.id;
  895. canvas.businessName = item.name;
  896. canvas.fillColor = new SColor(colorArr[index % 10]);
  897. canvas.cacheFillColor = canvas.fillColor;
  898. canvas.cacheColor = canvas.color;
  899. canvas.isBusiness = 2;
  900. //判断相邻代码
  901. if (!item.isAbut) {
  902. canvas.isBusiness = 7;
  903. }
  904. }
  905. });
  906. });
  907. }
  908. });
  909. },
  910. spaceIsAbut(list) {
  911. let data = list.map(item => {
  912. return {
  913. ids: item.children
  914. };
  915. });
  916. let param = {
  917. data: {
  918. floor: this.buildMess.code,
  919. criterias: data
  920. },
  921. ProjId: this.projectId,
  922. secret: this.secret
  923. };
  924. // console.log(param);
  925. isAbut(param)
  926. .then(res => {
  927. if (res.data.Result == "success") {
  928. res.data.Content.map((item, index) => {
  929. this.relationList[index].isAbut = item.abut;
  930. });
  931. this.getColor(this.relationList);
  932. } else {
  933. this.$message.error(res.data.ResultMsg);
  934. }
  935. })
  936. .catch(() => {
  937. this.$message.error("请求出错");
  938. });
  939. },
  940. getPathToCanvas(id) {
  941. let items = this.mainScene.root.children;
  942. items.map(item => {
  943. if (item.id == id) {
  944. //定位算法
  945. this.view.pos.x = -item.centerOfGravityPoint.x * this.view.scale +
  946. this.view.width / 2;
  947. this.view.pos.y = -item.centerOfGravityPoint.y * this.view.scale +
  948. this.view.height / 2;
  949. this.view.scale = this.view.scale;
  950. item.isBusiness = 3;
  951. this.idList = [];
  952. console.log(item)
  953. this.idList.push({
  954. id: item.businessId,
  955. name: item.businessName || '--'
  956. });
  957. } else if (item.businessId) {
  958. item.isBusiness = 2;
  959. } else {
  960. item.isBusiness = 1;
  961. }
  962. });
  963. },
  964. /** 按钮事件 ---------------------------------------------------------------------- */
  965. SpaceDialog() {
  966. this.$emit("dimension", this.idList, this.buildMess, this.graphyId);
  967. },
  968. bussinDea() {
  969. this.$emit("businessDetails", this.idList[this.idList.length - 1]);
  970. },
  971. //保存修改
  972. saveChange() {
  973. let id = ""
  974. this.idList.map(item => {
  975. if (!!item.parentId) {
  976. id = item.parentId
  977. }
  978. })
  979. this.deleteRela(id);
  980. },
  981. //调整到合适比例
  982. suitableSize() {
  983. //获取中心点
  984. let rect = this.view.scene.worldRect();
  985. //计算缩放比例
  986. this.view.scale = Math.min(
  987. this.view.width / (rect.width * 1.2),
  988. this.view.height / (rect.height * 1.2)
  989. );
  990. // 移动画布
  991. this.view.pos.x =
  992. (-(rect.right + rect.left) / 2) * this.view.scale + this.view.width / 2;
  993. this.view.pos.y =
  994. (-(rect.bottom + rect.top) / 2) * this.view.scale +
  995. this.view.height / 2;
  996. },
  997. //调整到小比例
  998. smallSize() {
  999. //获取中心点
  1000. let rect = this.view.scene.worldRect();
  1001. //计算缩放比例
  1002. this.view.scale = this.view.scale * 0.9;
  1003. // 移动画布
  1004. this.view.pos.x =
  1005. (-(rect.right + rect.left) / 2) * this.view.scale + this.view.width / 2;
  1006. this.view.pos.y =
  1007. (-(rect.bottom + rect.top) / 2) * this.view.scale +
  1008. this.view.height / 2;
  1009. },
  1010. bigSize() {
  1011. //获取中心点
  1012. let rect = this.view.scene.worldRect();
  1013. //计算缩放比例
  1014. this.view.scale = this.view.scale * 1.1;
  1015. // 移动画布
  1016. this.view.pos.x =
  1017. (-(rect.right + rect.left) / 2) * this.view.scale + this.view.width / 2;
  1018. this.view.pos.y =
  1019. (-(rect.bottom + rect.top) / 2) * this.view.scale +
  1020. this.view.height / 2;
  1021. },
  1022. //删除关系
  1023. deleteRela(id) {
  1024. let param = {
  1025. data: {
  1026. criterias: [{
  1027. to_id: id, //选填
  1028. graph_id: this.graphyId, //选填
  1029. rel_type: this.spaceType.rel_type //选填
  1030. }]
  1031. },
  1032. ProjId: this.projectId,
  1033. secret: this.secret
  1034. };
  1035. if (id) {
  1036. deleteRelation(param)
  1037. .then(res => {
  1038. if (res.data.Result == "success") {
  1039. this.loading.show = true;
  1040. this.loading.num = 0;
  1041. this.loading.total = 1;
  1042. this.addRelation(id, this.idList);
  1043. } else {
  1044. this.$message.error(res.data.ResultMsg);
  1045. }
  1046. })
  1047. .catch(() => {
  1048. this.$message.error("请求失败");
  1049. });
  1050. } else {
  1051. this.$message.error("请选择包含原业务空间的区域块")
  1052. }
  1053. },
  1054. //点击元空间后点击取消
  1055. clearDimension() {
  1056. this.myLoading = true;
  1057. let indexs = tools.clear(
  1058. this.mainScene.root.children,
  1059. 3,
  1060. this.idList,
  1061. "id"
  1062. );
  1063. this.myDialogVisible = false;
  1064. this.dialogVisible = false;
  1065. for (let i = 0; i < indexs.length; i++) {
  1066. this.mainScene.root.children[indexs[i]].isBusiness = 1;
  1067. }
  1068. this.idList = [];
  1069. this.type = 1;
  1070. this.getHasSpace();
  1071. },
  1072. //创建新的业务空间
  1073. createSP() {
  1074. let businessData = {
  1075. building_id: this.buildMess.buildCode,
  1076. floor_id: this.buildMess.code,
  1077. business_type: this.spaceType.code,
  1078. infos: {
  1079. RoomLocalName: [{
  1080. value: tools.getText(this.idList, "name")
  1081. }]
  1082. }
  1083. };
  1084. let data = [];
  1085. this.idList.map(i => {
  1086. data.push(i.id);
  1087. });
  1088. let param = {
  1089. data: {
  1090. floor: this.buildMess.code,
  1091. criterias: [{
  1092. ids: data
  1093. }]
  1094. },
  1095. ProjId: this.projectId,
  1096. secret: this.secret
  1097. };
  1098. // this.createSpace(businessData, this.idList, true);
  1099. //判断相邻代码
  1100. isAbut(param)
  1101. .then(res => {
  1102. if (res.data.Result == "success") {
  1103. this.dialogVisible = true;
  1104. this.ruleForm.name = businessData.infos.RoomLocalName[0].value;
  1105. this.businessData = businessData;
  1106. if (res.data.Content[0].abut) {
  1107. this.isAbutMsg = false;
  1108. // this.createSpace(businessData, this.idList, true);
  1109. } else {
  1110. this.isAbutMsg = true;
  1111. // this.$confirm(
  1112. // "您选择的元空间并未相邻,确定继续创建业务空间?",
  1113. // "提示",
  1114. // {
  1115. // confirmButtonText: "确定",
  1116. // cancelButtonText: "取消",
  1117. // type: "warning"
  1118. // }
  1119. // )
  1120. // .then(() => {
  1121. // this.loading.show = true;
  1122. // this.loading.num = 0;
  1123. // this.loading.total = 1 * 2;
  1124. // this.createSpace(businessData, this.idList, true);
  1125. // })
  1126. // .catch(() => {
  1127. // this.$message({
  1128. // type: "info",
  1129. // message: "已取消"
  1130. // });
  1131. // this.clearDimension();
  1132. // this.loading.show = false;
  1133. // });
  1134. }
  1135. } else {
  1136. this.$message.error(res.data.ResultMsg);
  1137. }
  1138. })
  1139. .catch(() => {
  1140. this.$message.error("请求失败");
  1141. });
  1142. },
  1143. //比较两个元空间是否相邻
  1144. compareSpace(ids) {
  1145. // console.log(ids);
  1146. },
  1147. //重新划分业务空间
  1148. divide() {
  1149. this.type = 5;
  1150. let id = this.idList[this.idList.length - 1],
  1151. items = this.mainScene.root.children;
  1152. items.map(item => {
  1153. if (item.businessId == id.id) {
  1154. item.isBusiness = 4;
  1155. } else if (item.businessId) {
  1156. item.isBusiness = 5;
  1157. }
  1158. });
  1159. this.idList = [];
  1160. },
  1161. //批量生成业务空间
  1162. createBatchSq() {
  1163. let items = this.mainScene.root.children;
  1164. let map = [];
  1165. items.map(item => {
  1166. if (!item.businessId) {
  1167. map.push({
  1168. id: item.id,
  1169. name: item.name
  1170. });
  1171. }
  1172. });
  1173. let text = tools.getText(map, "name");
  1174. this.$confirm(
  1175. // "您确定批量创建业务空间:" +
  1176. // tools.cutString(text, 10, "等业务空间") +
  1177. // ", 是否继续?",
  1178. "<p>确定根据未关联业务空间的元空间批量创建业务空间</p>" +
  1179. "<p>涉及的元空间:</p>" +
  1180. "<p style='line-height:20px;max-height:60px;overflow-y:auto;'>" +
  1181. text +
  1182. "</p>",
  1183. // tools.cutString(text, 60, "等业务空间")
  1184. "提示", {
  1185. dangerouslyUseHTMLString: true,
  1186. confirmButtonText: "确定",
  1187. cancelButtonText: "取消",
  1188. type: "warning"
  1189. }
  1190. )
  1191. .then(() => {
  1192. this.loading.show = true;
  1193. this.loading.num = 0;
  1194. this.loading.total = map.length * 2;
  1195. this.myDialogVisible = false;
  1196. map.map(item => {
  1197. this.createSpace({
  1198. building_id: this.buildMess.buildCode,
  1199. floor_id: this.buildMess.code,
  1200. business_type: this.spaceType.code,
  1201. infos: {
  1202. RoomLocalName: [{
  1203. value: item.name
  1204. }]
  1205. }
  1206. },
  1207. item.id,
  1208. true
  1209. );
  1210. });
  1211. })
  1212. .catch(() => {
  1213. this.$message({
  1214. type: "info",
  1215. message: "已取消批量创建"
  1216. });
  1217. });
  1218. },
  1219. //创建空间
  1220. createSpace(data, id, falg) {
  1221. let param = {
  1222. ProjId: this.projectId,
  1223. secret: this.secret,
  1224. data: data
  1225. };
  1226. createBusiness(param).then(res => {
  1227. if (res.data.Result == "success") {
  1228. if (falg) {
  1229. this.loading.num++;
  1230. this.addRelation(res.data.id, id);
  1231. } else {}
  1232. } else {
  1233. this.loading.num++;
  1234. this.$message.error("修改发生错误:" + res.data.ResultMsg);
  1235. }
  1236. });
  1237. },
  1238. //添加关系
  1239. addRelation(SpId, SiId) {
  1240. let data = {};
  1241. if (SiId instanceof Array) {
  1242. data.criterias = [];
  1243. SiId.map(item => {
  1244. data.criterias.push({
  1245. from_id: item.id,
  1246. to_id: SpId,
  1247. graph_id: this.graphyId,
  1248. rel_type: this.spaceType.rel_type
  1249. });
  1250. });
  1251. } else {
  1252. data = {
  1253. from_id: SiId,
  1254. to_id: SpId,
  1255. graph_id: this.graphyId,
  1256. rel_type: this.spaceType.rel_type
  1257. };
  1258. }
  1259. createRelation({
  1260. data: data,
  1261. ProjId: this.projectId,
  1262. secret: this.secret
  1263. })
  1264. .then(res => {
  1265. if (res.data.Result == "success") {
  1266. this.loading.num++;
  1267. if (this.loading.num == this.loading.total) {
  1268. this.loading.show = false;
  1269. this.getHasSpace();
  1270. this.idList = [];
  1271. this.$message.success("添加成功");
  1272. this.type = 1;
  1273. }
  1274. } else {
  1275. this.$message.error(res.data.ResultMsg);
  1276. this.loading.errorNum++;
  1277. }
  1278. })
  1279. .catch(() => {
  1280. this.$message.error("请求出错");
  1281. this.loading.errorNum++;
  1282. });
  1283. },
  1284. //导出json文件
  1285. exportJson(){
  1286. //下载为json文件
  1287. var Link = document.createElement('a');
  1288. Link.download = `${this.jsonId}.json`;
  1289. Link.style.display = 'none';
  1290. // 字符内容转变成blob地址
  1291. var blob = new Blob([this.exportJsonData]);
  1292. Link.href = URL.createObjectURL(blob);
  1293. // 触发点击
  1294. document.body.appendChild(Link);
  1295. Link.click();
  1296. // 然后移除
  1297. document.body.removeChild(Link);
  1298. }
  1299. },
  1300. filters: {
  1301. cutString: function(str, len) {
  1302. //length属性读出来的汉字长度为1
  1303. if (!!str && typeof str == "string" && str.length > len) {
  1304. return str.substring(0, len) + "...";
  1305. } else {
  1306. return str || "--";
  1307. }
  1308. }
  1309. },
  1310. watch: {
  1311. projectId(){
  1312. this.buildMess = null
  1313. this.param.ProjId = this.projectId
  1314. this.param.secret = this.secret
  1315. this.param.UserId = this.userId
  1316. this.hasMap = false
  1317. }
  1318. }
  1319. };
  1320. </script>
  1321. <!-- Add "scoped" attribute to limit CSS to this component only -->
  1322. <style lang="less">
  1323. .canvasGraphy {
  1324. position: relative;
  1325. // canvas {
  1326. // border: 1px solid #ccc;
  1327. // }
  1328. .header-search {
  1329. position: absolute;
  1330. top: 0;
  1331. height: 50px;
  1332. line-height: 50px;
  1333. padding-left: 20px;
  1334. background-color: rgba(205, 197, 191, 0.4);
  1335. left: 0;
  1336. right: 0;
  1337. top: 0;
  1338. z-index: 99;
  1339. >div {
  1340. height: 50px;
  1341. }
  1342. .div50 {
  1343. float: left;
  1344. width: 50%;
  1345. height: 100%;
  1346. .float-right {
  1347. float: right;
  1348. margin-top: 11px;
  1349. margin-right: 10%;
  1350. }
  1351. }
  1352. }
  1353. .el-autocomplete {
  1354. width: 320px;
  1355. }
  1356. .my-autocomplete {
  1357. li {
  1358. line-height: normal;
  1359. padding: 7px;
  1360. .name {
  1361. text-overflow: ellipsis;
  1362. overflow: hidden;
  1363. }
  1364. .addr {
  1365. font-size: 12px;
  1366. color: #b4b4b4;
  1367. }
  1368. .highlighted .addr {
  1369. color: #ddd;
  1370. }
  1371. }
  1372. }
  1373. }
  1374. </style>