handsontable.vue 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. <template>
  2. <div id="handsontable" v-loading="isLoading">
  3. <div style="overflow:hidden;margin-bottom:10px;margin-right:20px;height:50px;">
  4. <el-button @click="undo" style="float:right;margin-top:5px;margin-left:10px;">撤回</el-button>
  5. <el-button @click="reset" style="float:right;margin-top:5px;">刷新</el-button>
  6. <el-button @click="addSp" style="float:right;margin-top:5px;">添加</el-button>
  7. </div>
  8. <div v-show="main &&main.length" :id="id"></div>
  9. <div class="center" v-show="!main || !main.length" style="height: 400px;padding-top:140px;box-sizing:border-box;">
  10. <i class="iconwushuju iconfont"></i>
  11. 暂无数据
  12. </div>
  13. <!-- <add-business :buildMess="buildMess" :dialog="dialog"></add-business> -->
  14. <div class="right" v-show="main && main.length">
  15. <my-pagination :page="page" @change="pageChange"></my-pagination>
  16. </div>
  17. <!-- 二维码弹窗 -->
  18. <qrcode :dialog="dialog" :qrcodeUrl="qrcodeUrl" :addBody="true" ref="qrcode"></qrcode>
  19. </div>
  20. </template>
  21. <script>
  22. // 引用handsontable插件
  23. import "@/assets/js/chosen.jquery.min";
  24. import tools from "@/utils/scan/tools";
  25. import "@/assets/js/handsontable-chosen-editor";
  26. import myPagination from "@/components/common/myPagination";
  27. import addBusiness from "@/components/business_space/dialogs/addDialog/businessDialog"
  28. import showTools from "@/utils/handsontable/notShow"
  29. import Handsontable from "handsontable-pro"
  30. import 'handsontable-pro/dist/handsontable.full.css'
  31. import zhCN from 'handsontable-pro/languages/zh-CN';
  32. import qrcode from "@/components/ledger/lib/qrcode";
  33. console.log(Handsontable,"Handsontable")
  34. import {
  35. updateBusiness,
  36. createBusiness,
  37. createBusinessList,
  38. delManySpace,
  39. isSpaceBuss
  40. } from "@/api/scan/request";
  41. import {
  42. mapGetters,
  43. mapActions
  44. } from "vuex";
  45. export default {
  46. props: {
  47. id: {
  48. type: String
  49. }
  50. },
  51. components: {
  52. qrcode, //二维码页面
  53. myPagination,
  54. addBusiness
  55. },
  56. computed: {
  57. ...mapGetters("layout", [
  58. "projectId",
  59. "secret",
  60. "userId"
  61. ])
  62. },
  63. data() {
  64. return {
  65. dialog: {
  66. qrcode: false, //二维码弹窗
  67. addDevice: false
  68. },
  69. qrcodeUrl: "",//二维码图片地址
  70. headers: null,
  71. main: null,
  72. hot: null,
  73. tableData: [],
  74. isLoading: true,
  75. allData: null,
  76. page: {
  77. size: 50,
  78. sizes: [10, 30, 50, 100, 150, 200],
  79. total: 2,
  80. currentPage: 1
  81. },
  82. param: {
  83. ProjId: this.projectId, //项目id
  84. UserId: this.userId, //用户id
  85. secret: this.secret
  86. },
  87. buildMess: null,
  88. filtersArr: [], //表格数据被过滤后的下标
  89. copyMain: null, //深拷贝数组
  90. activeType: {}
  91. };
  92. },
  93. created() {
  94. this.setData()
  95. },
  96. mounted() {},
  97. methods: {
  98. setData(){
  99. this.param.ProjId = this.projectId
  100. this.param.UserId = this.userId
  101. this.param.secret = this.secret
  102. },
  103. //获取表头
  104. getHeader(headers, activeTabType) {
  105. this.headers = headers.map(item => {
  106. let dataSoucse = item.DataSource
  107. console.log(dataSoucse)
  108. if (!dataSoucse) {
  109. return item
  110. }
  111. dataSoucse.map(keys => {
  112. if (!!keys.Content && keys.Content.length) {
  113. keys.Content.map(child => {
  114. dataSoucse.push({
  115. Code: child.Code,
  116. Name: child.Name,
  117. })
  118. if (!!child.Content && child.Content.length) {
  119. child.Content.map(node => {
  120. dataSoucse.push({
  121. Code: node.Code,
  122. Name: node.Name,
  123. })
  124. })
  125. }
  126. })
  127. }
  128. })
  129. return item
  130. });
  131. console.log(this.headers, "headers")
  132. this.activeType = activeTabType
  133. },
  134. getData(buildMess) {
  135. if (!!buildMess) {
  136. this.buildMess = buildMess;
  137. }
  138. let param = {
  139. id: this.buildMess.code,
  140. type: ["Sp"],
  141. data: {
  142. customInfo: true,
  143. criteria: {
  144. floor: this.buildMess.code, // 必填, 指定楼层id
  145. business_type: this.activeType.code, // 必填, 楼层下某个类型的业务空间PowerSupplyZone, 默认是空字符串
  146. rel_type: this.activeType.rel_type, // 必填, 指定业务类型的关系类型(参考数据平台),
  147. // 数字型字符串, 例如: 通用是99
  148. }
  149. },
  150. ProjId: this.param.ProjId,
  151. secret: this.param.secret
  152. };
  153. isSpaceBuss(param).then(res => {
  154. if (res.data.Result == "success") {
  155. this.allData = res.data.Content;
  156. this.page.total = res.data.Count;
  157. this.getMain(
  158. this.pagination(this.page.currentPage, this.page.size, this.allData)
  159. );
  160. } else {
  161. this.$message.error("请求错误");
  162. }
  163. });
  164. },
  165. //获取表格主体内容
  166. getMain(main) {
  167. this.main = main;
  168. if (this.main && this.main.length && this.main[0].id) {
  169. this.copyMain = tools.deepCopy(this.main);
  170. }
  171. this.isLoading = true;
  172. if (!!this.hot) {
  173. this.hot.destroy();
  174. this.hot = null;
  175. }
  176. this.$nextTick(() => {
  177. this.initHot();
  178. });
  179. },
  180. //初始化handsontable组件
  181. initHot() {
  182. let id = this.id
  183. console.log(id)
  184. var container = document.getElementById(this.id);
  185. let winHeight = document.documentElement.clientHeight;
  186. this.hot = new Handsontable(container, {
  187. data: this.main,
  188. colHeaders: this.delHeader(this.headers), //表头文案
  189. columns: this.getType(this.headers), //数据显示格式
  190. filters: true,
  191. maxRows: this.main.length,
  192. height: winHeight - 100 - 50 - 176,
  193. columnSorting: true, //添加排序
  194. sortIndicator: true, //添加排序
  195. renderAllRows: true,
  196. autoColumnSize: true,
  197. language: "zh-CN",
  198. manualColumnResize: true,
  199. manualColumnMove: true,
  200. dropdownMenu: [
  201. "filter_by_condition",
  202. "filter_by_value",
  203. "filter_action_bar"
  204. ],
  205. contextMenu: {
  206. items: {
  207. remove_row: {
  208. name: "删除该业务空间"
  209. }
  210. }
  211. },
  212. // 事件
  213. afterChange: this.tdChange, //修改后
  214. afterFilter: this.trimmedRows, //排序前
  215. beforeRemoveRow: this.romoveFm, //右键删除
  216. afterOnCellMouseDown: this.eventClick //鼠标点击
  217. });
  218. let pro = document.getElementById("hot-display-license-info");
  219. if (!!pro) {
  220. pro.parentNode.removeChild(pro);
  221. }
  222. this.isLoading = false;
  223. },
  224. //表格中的查看详情
  225. eventClick(el, rowArr) {
  226. let filter = this.filtersArr;
  227. //被筛选过后的数组
  228. let trimmedArr = this.trimmedRows();
  229. //是否启用了排序
  230. let isSort = this.hot.getPlugin("columnSorting").isSorted();
  231. // debugger
  232. if (trimmedArr.length && isSort) {
  233. let sortArr = this.myHotArr.getPlugin("columnSorting").rowsMapper
  234. .__arrayMap;
  235. let infos = this.main[trimmedArr[sortArr[rowArr.row]]];
  236. this.getInfors(infos, rowArr);
  237. } else if (isSort) {
  238. //排序后的数组
  239. let sortArr = this.hot.getPlugin("columnSorting").rowsMapper.__arrayMap;
  240. let infos = this.main[sortArr[rowArr.row]];
  241. this.getInfors(infos, rowArr);
  242. } else if (trimmedArr.length) {
  243. let infos = this.main[trimmedArr[rowArr.row]];
  244. this.getInfors(infos, rowArr);
  245. } else {
  246. let infos = this.main[rowArr.row];
  247. this.getInfors(infos, rowArr);
  248. }
  249. },
  250. getInfors(infos, row) {
  251. let val = this.hot.colToProp(row.col);
  252. if (val == "point") {
  253. this.$emit("lookEqu", infos);
  254. } else if (val == "infos.RoomQRCode") {
  255. this.qrcodeUrl = this.main[row.row].infos.RoomQRCode
  256. if (!!this.qrcodeUrl) {
  257. this.dialog.qrcode = true;
  258. } else {
  259. this.$message("此设备没有设备二维码")
  260. }
  261. } else {
  262. return false;
  263. }
  264. },
  265. //表格发生更改
  266. tdChange(changeData, source) {
  267. let filter = this.filtersArr;
  268. if (changeData) {
  269. let param = this.getParam(changeData, source);
  270. let data = [];
  271. for (let i = 0; i < param.length; i++) {
  272. if (!!param[i].id) {
  273. data.push(param[i]);
  274. } else {
  275. this.createSq(param[i], changeData);
  276. }
  277. }
  278. if (data && data.length) {
  279. this.updateBusiness(data, changeData);
  280. }
  281. }
  282. },
  283. //右键删除
  284. romoveFm(index, amout, physicalRows, source) {
  285. if (physicalRows && physicalRows.length) {
  286. let items = [],
  287. text = null;
  288. physicalRows.map(item => {
  289. text = text ?
  290. this.copyMain[item].infos.RoomName + "、" + text :
  291. this.copyMain[item].infos.RoomName;
  292. items.push(this.copyMain[item].id);
  293. });
  294. this.$confirm("您正在删除" + text + ", 是否继续?", "提示", {
  295. confirmButtonText: "确定",
  296. cancelButtonText: "取消",
  297. type: "warning"
  298. })
  299. .then(() => {
  300. this.delBusiness(items);
  301. })
  302. .catch(() => {
  303. this.hot.loadData(tools.deepCopy(this.copyMain));
  304. });
  305. }
  306. },
  307. delBusiness(items) {
  308. let param = {
  309. ProjId: this.param.ProjId,
  310. secret: this.param.secret,
  311. data: {
  312. criteria: {
  313. ids: items
  314. }
  315. }
  316. };
  317. delManySpace(param)
  318. .then(res => {
  319. if (res.data.Result == "success") {
  320. this.$message.success("删除成功");
  321. this.getData();
  322. } else {
  323. this.$message.error("删除失败");
  324. }
  325. })
  326. .catch(() => {
  327. this.$message.error("请求发生错误");
  328. });
  329. },
  330. // 新建
  331. createSq(param, change) {
  332. let seedData = {
  333. building_id: this.buildMess.buildCode,
  334. floor_id: this.buildMess.code,
  335. business_type: this.activeType.code == "GeneralZone" ? null : this.activeType.code,
  336. infos: {}
  337. };
  338. for (let i = 0; i < change.length; i++) {
  339. let arr = change[i][1].split(".");
  340. seedData[arr[0]][arr[1]] = [{
  341. value: change[i][3] != "" ? change[i][3] : null
  342. }];
  343. }
  344. this.createSpace(seedData);
  345. },
  346. // 修改
  347. updateBusiness(data, change) {
  348. let param = {
  349. ProjId: this.param.ProjId,
  350. secret: this.param.secret,
  351. data: {
  352. criterias: []
  353. }
  354. };
  355. data.map((item, index) => {
  356. console.log(change[index][1]);
  357. let arr = change[index][1].split(".");
  358. let info = {};
  359. info[arr[1]] = [{
  360. value: change[index][3] != "" ? change[index][3] : null
  361. }];
  362. param.data.criterias.push({
  363. id: item.id,
  364. infos: info
  365. });
  366. });
  367. updateBusiness(param).then(res => {
  368. console.log(res);
  369. });
  370. },
  371. /** 请求部分 ------------------------------------ */
  372. createSpace(data) {
  373. let param = {
  374. ProjId: this.param.ProjId,
  375. secret: this.param.secret,
  376. data: {
  377. criterias: [data]
  378. }
  379. };
  380. createBusinessList(param).then(res => {
  381. if (res.data.Result == "success") {
  382. console.log(this.main);
  383. this.main.map(item => {
  384. if (!item.id) {
  385. item.id = res.data.id;
  386. item.infos.RoomID = res.data.id;
  387. item.infos.RoomName = res.data.RoomName;
  388. }
  389. });
  390. this.hot.loadData(this.main);
  391. this.reset()
  392. } else {
  393. this.$message.error("创建发生错误:" + res.data.ResultMsg);
  394. }
  395. });
  396. },
  397. /**
  398. * 获取被排序后的数组
  399. *
  400. * @param changeData 发生改变的数据
  401. * @param source 数组
  402. *
  403. * @return array 经过排序后或者经过搜索后的数组
  404. */
  405. getParam(changeData, source) {
  406. let param = "";
  407. //被筛选过后的数组
  408. let trimmedArr = this.trimmedRows();
  409. //是否启用了排序
  410. let isSort = this.hot.getPlugin("columnSorting").isSorted();
  411. if (trimmedArr.length && isSort) {
  412. //排序后的数组
  413. let sortArr = this.hot.getPlugin("columnSorting").rowsMapper.__arrayMap;
  414. param = changeData.map(item => {
  415. return this.hot.getSourceDataAtRow(trimmedArr[sortArr[item[0]]]);
  416. });
  417. } else if (isSort) {
  418. //排序后的数组
  419. let sortArr = this.hot.getPlugin("columnSorting").rowsMapper.__arrayMap;
  420. param = changeData.map(item => {
  421. return this.hot.getSourceDataAtRow(sortArr[item[0]]);
  422. });
  423. } else if (trimmedArr.length) {
  424. param = changeData.map(item => {
  425. return this.hot.getSourceDataAtRow(trimmedArr[item[0]]);
  426. });
  427. } else {
  428. param = changeData.map(item => {
  429. return this.hot.getSourceDataAtRow(item[0]);
  430. });
  431. }
  432. return param;
  433. },
  434. //获取被筛选掉的行号
  435. trimmedRows() {
  436. // var plugin = hot.getPlugin('trimRows').trimmedRows;//获取被筛选掉的行号
  437. var plugin = this.hot.getPlugin("trimRows").trimmedRows;
  438. let dataLength = this.main.length;
  439. let dataArr = new Array();
  440. for (let i = 0; i < dataLength; i++) {
  441. dataArr.push(i);
  442. }
  443. if (plugin.length <= 0) {
  444. dataArr = undefined;
  445. } else {
  446. dataArr = this.array_diff(dataArr, plugin);
  447. }
  448. this.filtersArr = dataArr;
  449. return dataArr || [];
  450. // var DataArray = new Array();
  451. // for (var i = 0; i < plugin.length; i++) {
  452. // // 通过行号获取数据
  453. // DataArray.push(this.hot.getSourceDataAtRow(plugin[i]));
  454. // }
  455. },
  456. //去除数组中相同的元素
  457. array_diff(a, b) {
  458. for (var i = 0; i < b.length; i++) {
  459. for (var j = 0; j < a.length; j++) {
  460. if (a[j] == b[i]) {
  461. a.splice(j, 1);
  462. j = j - 1;
  463. }
  464. }
  465. }
  466. return a;
  467. },
  468. /**
  469. * 表头文案处理函数
  470. * @param list header数组数据
  471. *
  472. * @return 处理好的文案
  473. */
  474. delHeader(list) {
  475. let arr = tools.copyArr(list)
  476. // 如果不是只读状态,添加四大厂商选择
  477. let readArr = ["A1", "A2", "B1", "C5", "D1", "D2", "X", "L", "L1", "L2", "F1", "F2"]
  478. if (!this.onlyRead) {
  479. arr = showTools.arrToArr(arr)
  480. readArr.push("Own")
  481. }
  482. let data = showTools.changeHeader(arr, readArr, false, false, true, false, true)
  483. data.unshift("是否关联平面图", "与空间相关联的设备");
  484. console.log("header", data)
  485. return data;
  486. },
  487. /**
  488. * 表头数据处理函数
  489. * @param arr header数组数据
  490. *
  491. * @return 处理好的数据格式
  492. */
  493. getType(list) {
  494. let arr = tools.copyArr(list)
  495. let data = showTools.showTypes(arr, false, false, true, false)
  496. data.unshift({
  497. data: "hasSi",
  498. renderer: this.myRenderer,
  499. readOnly: true
  500. }, {
  501. data: "point",
  502. renderer: this.facilityRender,
  503. readOnly: true
  504. });
  505. data = data.filter(item => item);
  506. console.log(data)
  507. return data;
  508. },
  509. myRenderer(instance, td, row, col, prop, value, cellProperties) {
  510. if (value) {
  511. td.innerHTML = "已关联";
  512. } else {
  513. td.innerHTML = "未关联";
  514. }
  515. return td;
  516. },
  517. facilityRender(instance, td, row, col, prop, value, cellProperties) {
  518. td.style.color = "#409EFF";
  519. td.style.cursor = "pointer";
  520. td.innerHTML = "点击查看";
  521. return td;
  522. },
  523. //下拉插件修改
  524. customDropdownRenderer(
  525. instance,
  526. td,
  527. row,
  528. col,
  529. prop,
  530. value,
  531. cellProperties
  532. ) {
  533. var selectedId;
  534. var optionsList = cellProperties.chosenOptions.data;
  535. if (
  536. typeof optionsList === "undefined" ||
  537. typeof optionsList.length === "undefined" ||
  538. !optionsList.length
  539. ) {
  540. Handsontable.renderers.TextRenderer(
  541. instance,
  542. td,
  543. row,
  544. col,
  545. prop,
  546. value,
  547. cellProperties
  548. );
  549. return td;
  550. }
  551. var values = (value + "").split(",");
  552. value = [];
  553. for (var index = 0; index < optionsList.length; index++) {
  554. if (optionsList[index].content && optionsList[index].content.length) {
  555. for (let i = 0; i < optionsList[index].content.length; i++) {
  556. if (
  557. optionsList[index].content[i] &&
  558. optionsList[index].content[i].length
  559. ) {
  560. for (let j = 0; j < optionsList[index].content[i].length; j++) {
  561. if (
  562. values.indexOf(
  563. optionsList[index].content[i].content[j].code + ""
  564. ) > -1
  565. ) {
  566. selectedId = optionsList[index].content[i].content[j].code;
  567. value.push(optionsList[index].content[i].content[j].name);
  568. }
  569. }
  570. } else {
  571. if (
  572. values.indexOf(optionsList[index].content[i].code + "") > -1
  573. ) {
  574. selectedId = optionsList[index].content[i].code;
  575. value.push(optionsList[index].content[i].name);
  576. }
  577. }
  578. }
  579. } else {
  580. if (values.indexOf(optionsList[index].code + "") > -1) {
  581. selectedId = optionsList[index].code;
  582. value.push(optionsList[index].name);
  583. }
  584. }
  585. }
  586. value = value.join(", ");
  587. Handsontable.renderers.TextRenderer(
  588. instance,
  589. td,
  590. row,
  591. col,
  592. prop,
  593. value,
  594. cellProperties
  595. );
  596. return td;
  597. },
  598. /** 页面中的按钮事件--------------------------- */
  599. addSp() {
  600. // this.dialog.addDevice = true
  601. // this.hot.downloadFile()
  602. // this.hot.getPlugin('exportFile').downloadFile("csv", { columnHeaders: true, exportHiddenRows: true, exportHiddenColumns: true, rowHeaders: true })
  603. if (this.main && this.main.length && !!this.main[0].id) {
  604. this.hot.destroy();
  605. this.hot = null;
  606. this.main.unshift([]);
  607. this.getMain(this.main);
  608. } else {
  609. if (this.main && this.main.length) {
  610. this.$message.error("请添加完成后继续添加");
  611. } else {
  612. this.main.unshift([]);
  613. this.getMain(this.main);
  614. }
  615. }
  616. },
  617. //刷新
  618. reset() {
  619. this.getData();
  620. },
  621. //撤回操作
  622. undo() {
  623. this.hot.undo();
  624. },
  625. /** 分页事件------------------------ */
  626. pageChange() {
  627. this.getMain(
  628. this.pagination(this.page.currentPage, this.page.size, this.allData)
  629. );
  630. },
  631. pagination(pageNo, pageSize, array) {
  632. let offset = (pageNo - 1) * pageSize;
  633. return offset + pageSize >= array.length ?
  634. array.slice(offset, array.length) :
  635. array.slice(offset, offset + pageSize);
  636. }
  637. },
  638. watch: {
  639. projectId(){
  640. this.setData()
  641. this.main = null
  642. }
  643. }
  644. };
  645. </script>
  646. <style lang="less" scoped>
  647. #handsontable {
  648. .no-data {
  649. height: 150px;
  650. line-height: 150px;
  651. text-align: center;
  652. color: gray;
  653. }
  654. }
  655. </style>