BaseEquipment.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. <template>
  2. <div id="equip_pro">
  3. <div class="title">设备实例本地名称</div>
  4. <el-tabs v-model="activeName" @tab-click="handleClick">
  5. <el-tab-pane label="属性" name="first">
  6. <div class="property">
  7. <div class="base-property">
  8. <div>
  9. <span>W</span>
  10. <el-input
  11. style="width: 74px; margin-left: 6px"
  12. size="mini"
  13. v-model="width"
  14. @input="changeWidth"
  15. placeholder="请输入内容"
  16. ></el-input>
  17. </div>
  18. <div>
  19. <span>H</span>
  20. <el-input
  21. style="width: 74px; margin-left: 6px"
  22. size="mini"
  23. v-model="height"
  24. @input="changeHeight"
  25. placeholder="请输入内容"
  26. ></el-input>
  27. </div>
  28. </div>
  29. <div class="base-property base-property-left">
  30. <div>
  31. <span>R</span>
  32. <el-input
  33. style="width: 74px; margin-left: 6px"
  34. size="mini"
  35. disabled
  36. @input="changeWidth"
  37. placeholder="请输入内容"
  38. ></el-input>
  39. </div>
  40. </div>
  41. <div class="imgUpdate">
  42. <div class="img-tit">设计图</div>
  43. <div class="btn-list">
  44. <el-upload
  45. class="avatar-uploader"
  46. action="https://jsonplaceholder.typicode.com/posts/"
  47. :show-file-list="false"
  48. :before-upload="beforeAvatarUpload"
  49. >
  50. <Button type="default">上传文件</Button>
  51. </el-upload>
  52. </div>
  53. </div>
  54. <div class="imgUpdate">
  55. <div class="img-tit">附加数据</div>
  56. <div class="textarea">
  57. <el-input type="textarea" @input="changeAnotherMsg" v-model="anotherMsg" :rows="2" placeholder="请输入内容">
  58. </el-input>
  59. </div>
  60. </div>
  61. </div>
  62. </el-tab-pane>
  63. <el-tab-pane label="信息点" name="second">
  64. <div class="msgPoint-box">
  65. <Input
  66. class="baseItemInput"
  67. :width="200"
  68. iconType="search"
  69. placeholder="搜索信息点"
  70. v-model="getPressMsg"
  71. @pressEnter="pressEnter"
  72. @clear="pressEnter"
  73. />
  74. <div
  75. class="msgPoint-list"
  76. ref="localDom"
  77. v-show="!pressMsgData.length"
  78. >
  79. <div class="type-list" v-for="(item, key) in msgData" :key="key">
  80. <div class="type-title" @click="clips(item)">
  81. <i
  82. v-bind:class="[
  83. item.showChildren ? 'caret-icon-active' : 'caret-icon',
  84. 'el-icon-caret-bottom',
  85. ]"
  86. ></i>
  87. <span>{{ item.tagName }}</span>
  88. </div>
  89. <el-collapse-transition>
  90. <ul class="list" v-show="item.showChildren">
  91. <li v-for="(a, b) in item.children" :key="'i' + b">
  92. <Checkbox
  93. :checked="a.checked ? 'checked' : 'uncheck'"
  94. @change="changeCheck(a)"
  95. />
  96. <p>{{ a.name }}</p>
  97. </li>
  98. </ul>
  99. </el-collapse-transition>
  100. </div>
  101. </div>
  102. <ul class="msgPoint-list-press" v-show="pressMsgData.length">
  103. <li v-for="(a, b) in pressMsgData" :key="b">
  104. <Checkbox
  105. :checked="a.checked ? 'checked' : 'uncheck'"
  106. @change="changeCheck(a)"
  107. />
  108. <p>{{ a.name }}</p>
  109. </li>
  110. </ul>
  111. </div>
  112. </el-tab-pane>
  113. </el-tabs>
  114. </div>
  115. </template>
  116. <script>
  117. import { queryEquipMsg, queryDict } from "@/api/editer";
  118. import bus from "@/bus/bus";
  119. const imgBaseUrl = window.__systemConf.imgServeUri;
  120. // 图上传路径
  121. const imgServeUpload = window.__systemConf.imgServeUpload;
  122. export default {
  123. props: ["InfoPointList", "EquipData", "equipHeight", "Width", "Height","AnotherMsg"],
  124. data() {
  125. return {
  126. width: 0,
  127. height: 0,
  128. activeName: "first",
  129. width: "",
  130. height: "",
  131. msgData: [], //存储二级树
  132. pressMsgData: [], // 搜索后得信息点数组
  133. getPressMsg: "", //输入信息
  134. local: "", //局部加载
  135. anotherMsg: "", // 附加信息
  136. };
  137. },
  138. methods: {
  139. // 折叠信息点操作
  140. clips(item) {
  141. item.showChildren = !item.showChildren;
  142. },
  143. // 点击切换
  144. handleClick(tab, event) {
  145. // 设置高度
  146. if (tab.paneName == "second") {
  147. const box = document.getElementsByClassName("msgPoint-list")[0];
  148. const box2 = document.getElementsByClassName("msgPoint-list-press")[0];
  149. box.style.height = this.equipHeight;
  150. box2.style.height = this.equipHeight;
  151. }
  152. },
  153. // 设置宽
  154. changeWidth(val) {
  155. bus.$emit("updateStyle", "sWidth", val);
  156. },
  157. // 设置高
  158. changeHeight(val) {
  159. bus.$emit("updateStyle", "sHeight", val);
  160. },
  161. // 设置附加信息
  162. changeAnotherMsg(val) {
  163. bus.$emit("updateStyle", "anotherMsg", val);
  164. },
  165. beforeAvatarUpload(file) {
  166. let that = this;
  167. const fileReader = new FileReader();
  168. fileReader.readAsDataURL(file); //读取图片
  169. const ftype = file.type;
  170. const fname = file.name;
  171. const uploadKey = file.uid;
  172. const imgType = ftype.split(".")[ftype.length - 1];
  173. fileReader.addEventListener("load", function () {
  174. // 读取完成
  175. let res = fileReader.result;
  176. //将canvas的base64位图片转换成图片png的file
  177. var blob = that.dataURLtoBlob(res, ftype);
  178. //将其转换成file对象
  179. let file = new File([blob], fname, {
  180. type: ftype,
  181. lastModified: Date.now(),
  182. }); //blob转file
  183. // try sending
  184. let reader = new FileReader();
  185. let fileType = file.name.split(".");
  186. let imgType = fileType[fileType.length - 1];
  187. let CreateTime = that.formatDate(new Date(file.lastModified));
  188. reader.onloadend = function () {
  189. // 这个事件在读取结束后,无论成功或者失败都会触发
  190. if (reader.error) {
  191. } else {
  192. // 构造 XMLHttpRequest 对象,发送文件 Binary 数据
  193. var xhr = new XMLHttpRequest();
  194. xhr.open(
  195. /* method */
  196. "POST",
  197. /* target url */
  198. imgServeUpload +
  199. uploadKey +
  200. "." +
  201. imgType
  202. );
  203. xhr.send(reader.result);
  204. xhr.onreadystatechange = function () {
  205. if (xhr.readyState == 4) {
  206. if (xhr.status == 200) {
  207. that.url = imgBaseUrl + uploadKey + "." + imgType;
  208. bus.$emit(
  209. "updateStyle",
  210. "url",
  211. imgBaseUrl + uploadKey + "." + imgType
  212. );
  213. }
  214. }
  215. };
  216. }
  217. };
  218. reader.readAsArrayBuffer(file);
  219. });
  220. },
  221. dataURLtoBlob(dataURI, type) {
  222. var binary = atob(dataURI.split(",")[1]);
  223. var array = [];
  224. for (var i = 0; i < binary.length; i++) {
  225. array.push(binary.charCodeAt(i));
  226. }
  227. return new Blob([new Uint8Array(array)], { type: type });
  228. },
  229. formatDate(now) {
  230. let year = now.getFullYear();
  231. let month = now.getMonth() + 1;
  232. let date = now.getDate();
  233. let hour = now.getHours();
  234. let minute = now.getMinutes();
  235. let second = now.getSeconds();
  236. return (
  237. year +
  238. "-" +
  239. month +
  240. "-" +
  241. (date > 10 ? date : "0" + date) +
  242. " " +
  243. hour +
  244. ":" +
  245. (minute > 10 ? minute : "0" + minute) +
  246. ":" +
  247. (second > 10 ? second : "0" + second)
  248. );
  249. },
  250. // 切换选中选项
  251. changeCheck(item) {
  252. item.checked = !item.checked;
  253. // 添加设备信息点
  254. Object.assign(item, {
  255. equipId: this.EquipData.attachObjectIds[0],
  256. });
  257. bus.$emit("changeEquipMsgPoint", item);
  258. },
  259. // 搜索回车操作
  260. pressEnter() {
  261. const list = [];
  262. if (!this.getPressMsg) {
  263. this.pressMsgData = [];
  264. return;
  265. }
  266. // 对信息点相同得提取出来
  267. this.msgData.forEach((item) => {
  268. item.children.forEach((a) => {
  269. if (a.name.includes(this.getPressMsg)) {
  270. list.push(a);
  271. }
  272. });
  273. });
  274. this.pressMsgData = list;
  275. },
  276. },
  277. watch: {
  278. EquipData(val) {
  279. this.msgData = []; //存储二级树
  280. this.pressMsgData = []; // 搜索后得信息点数组
  281. this.getPressMsg = ""; //输入信息
  282. // 启动局部 loading
  283. this.local = this.$loading({
  284. el: this.$refs.localDom,
  285. type: "local",
  286. size: "min",
  287. });
  288. const data = {
  289. Type: val.properties.classCode,
  290. };
  291. queryDict(data)
  292. .then((res) => {
  293. let arr = [];
  294. // 勾选设备中选中的对象
  295. const msgData = res.content;
  296. // 设置已经勾选数据
  297. if (this.InfoPointList && this.InfoPointList.length) {
  298. msgData.map((item) => {
  299. item.checked = false;
  300. this.InfoPointList.forEach((a) => {
  301. if (a.id == item.id) {
  302. item.checked = true;
  303. }
  304. });
  305. return item;
  306. });
  307. } else {
  308. msgData.map((item) => {
  309. item.checked = false;
  310. return item;
  311. });
  312. }
  313. // 生成二级树
  314. msgData.forEach((item) => {
  315. const itemTag = item.secondTag
  316. ? item.secondTag
  317. : item.firstTag
  318. ? item.firstTag
  319. : "--";
  320. if (arr.length) {
  321. let index = -1;
  322. arr.forEach((aItem) => {
  323. if (aItem.tag == itemTag) {
  324. index = 1;
  325. aItem.children.push(item);
  326. aItem.number++;
  327. }
  328. });
  329. if (index == -1) {
  330. const tag = item.secondTag
  331. ? item.secondTag
  332. : item.firstTag
  333. ? item.firstTag
  334. : "--";
  335. const tagName = item.secondName
  336. ? item.secondName
  337. : item.firstName
  338. ? item.firstName
  339. : "--";
  340. let obj = {
  341. tagName: tagName,
  342. tag: tag,
  343. children: [item],
  344. number: 1,
  345. showChildren: true,
  346. };
  347. arr.push(obj);
  348. }
  349. } else {
  350. const tag = item.secondTag
  351. ? item.secondTag
  352. : item.firstTag
  353. ? item.firstTag
  354. : "--";
  355. const tagName = item.secondName
  356. ? item.secondName
  357. : item.firstName
  358. ? item.firstName
  359. : "--";
  360. let obj = {
  361. tagName: tagName,
  362. tag: tag,
  363. children: [],
  364. number: 1,
  365. showChildren: true,
  366. };
  367. obj.children.push(item);
  368. arr.push(obj);
  369. }
  370. });
  371. this.msgData = arr;
  372. this.$loading.close(this.local);
  373. })
  374. .catch((err) => {
  375. console.log("接口报错", err);
  376. this.$loading.close(this.local);
  377. });
  378. },
  379. Width(val) {
  380. this.width = val;
  381. },
  382. Height(val) {
  383. this.height = val;
  384. },
  385. AnotherMsg(val) {
  386. this.anotherMsg = val;
  387. },
  388. },
  389. mounted() {},
  390. };
  391. </script>
  392. <style lang="less" scoped>
  393. ul,
  394. li,
  395. p {
  396. margin: 0;
  397. padding: 0;
  398. list-style-type: none;
  399. }
  400. #equip_pro {
  401. .title {
  402. height: 47px;
  403. border-bottom: 1px solid #979797;
  404. color: #646c73;
  405. font-size: 16px;
  406. padding-left: 12px;
  407. box-sizing: border-box;
  408. }
  409. .property {
  410. .base-property {
  411. display: flex;
  412. align-items: center;
  413. justify-content: space-around;
  414. }
  415. .base-property-left {
  416. display: flex;
  417. align-items: center;
  418. justify-content: flex-start;
  419. padding-left: 12px;
  420. padding-top: 12px;
  421. box-sizing: border-box;
  422. }
  423. .imgUpdate {
  424. border-top: 1px solid #e4e5e7;
  425. width: 100%;
  426. margin-bottom: 16px;
  427. padding: 0 12px 0 12px;
  428. box-sizing: border-box;
  429. .img-tit {
  430. margin: 12px 0 12px 0;
  431. color: #646a73;
  432. font-size: 12px;
  433. }
  434. }
  435. }
  436. .msgPoint-box {
  437. width: 100%;
  438. height: 100%;
  439. padding: 0 12px 0 12px;
  440. box-sizing: border-box;
  441. .msgPoint-list {
  442. margin-top: 20px;
  443. height: 100%;
  444. overflow-y: scroll;
  445. .type-list {
  446. .type-title {
  447. cursor: pointer;
  448. margin-bottom: 10px;
  449. span {
  450. margin-left: 12px;
  451. }
  452. }
  453. ul {
  454. width: 100%;
  455. padding-left: 28px;
  456. li {
  457. display: flex;
  458. height: 40px;
  459. align-items: center;
  460. justify-content: flex-start;
  461. cursor: pointer;
  462. p {
  463. margin-left: 12px;
  464. }
  465. &:hover {
  466. background: #f5f6f7;
  467. }
  468. }
  469. }
  470. }
  471. }
  472. .msgPoint-list-press {
  473. margin-top: 12px;
  474. overflow-y: scroll;
  475. li {
  476. display: flex;
  477. height: 40px;
  478. align-items: center;
  479. justify-content: flex-start;
  480. cursor: pointer;
  481. p {
  482. margin-left: 12px;
  483. }
  484. &:hover {
  485. background: #f5f6f7;
  486. }
  487. }
  488. }
  489. }
  490. .caret-icon {
  491. animation: nowhirling 0.2s linear forwards;
  492. }
  493. .caret-icon-active {
  494. animation: whirling 0.2s linear forwards;
  495. }
  496. @keyframes whirling {
  497. 0% {
  498. transform: rotate(-90deg);
  499. -ms-transform: rotate(-90deg); /* Internet Explorer */
  500. -moz-transform: rotate(-90deg); /* Firefox */
  501. -webkit-transform: rotate(-90deg); /* Safari 和 Chrome */
  502. -o-transform: rotate(-90deg); /* Opera */
  503. }
  504. 100% {
  505. transform: rotate(0deg);
  506. -ms-transform: rotate(0deg); /* Internet Explorer */
  507. -moz-transform: rotate(0deg); /* Firefox */
  508. -webkit-transform: rotate(0deg); /* Safari 和 Chrome */
  509. -o-transform: rotate(0deg); /* Opera */
  510. }
  511. }
  512. @keyframes nowhirling {
  513. 0% {
  514. transform: rotate(0deg);
  515. -ms-transform: rotate(0deg); /* Internet Explorer */
  516. -moz-transform: rotate(0deg); /* Firefox */
  517. -webkit-transform: rotate(0deg); /* Safari 和 Chrome */
  518. -o-transform: rotate(0deg); /* Opera */
  519. }
  520. 100% {
  521. transform: rotate(-90deg);
  522. -ms-transform: rotate(-90deg); /* Internet Explorer */
  523. -moz-transform: rotate(-90deg); /* Firefox */
  524. -webkit-transform: rotate(-90deg); /* Safari 和 Chrome */
  525. -o-transform: rotate(-90deg); /* Opera */
  526. }
  527. }
  528. }
  529. </style>