index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. <template>
  2. <div id="deviceList">
  3. <el-row class="left">
  4. <span style="float:right;">当前选择的部件类型:{{ category.Name }}</span>
  5. <!-- <div style="width:200px;display:inline-block;text-align:left;color:gray;">
  6. <span>隐藏自动填充的信息</span>
  7. <el-checkbox v-model="isWatch" @change="getTableHeader"></el-checkbox>
  8. </div> -->
  9. <el-select v-model="showType" @change="initTable" style="width:100px;margin-right:10px;vertical-align:bottom;">
  10. <el-option v-for="item in showTypes" :key="item.value" :label="item.label" :value="item.value">
  11. </el-option>
  12. </el-select>
  13. <span>增加</span>
  14. <el-input v-model="addNum" style="width:50px;" size="small"></el-input>
  15. <span>个{{ category.Name }}</span>
  16. <el-button @click="handleAddTableRow">增加</el-button>
  17. </el-row>
  18. <div class="tableBox">
  19. <div class="center middle_sty" style="flex:2;" v-show="tableData && !tableData.length">
  20. <p>
  21. <i class="icon-wushuju iconfont"></i>
  22. 暂无数据
  23. </p>
  24. </div>
  25. <div class="tableLeft" v-show="tableData && tableData.length">
  26. <handson-table ref="table"></handson-table>
  27. </div>
  28. </div>
  29. <el-row class="center">
  30. <el-button type="primary" size="medium" @click="handleCreateTableData" class="create_button">创建部件</el-button>
  31. </el-row>
  32. <!-- 二维码弹窗 -->
  33. <qrcode :dialog="myDialog" :qrcodeUrl="qrcodeUrl" :addBody="true" ref="qrcode"></qrcode>
  34. <upload-files-dialog :read="onlyRead ? true : false" ref="upload" @changeFile="fileChange" :keysArr="filesArr"
  35. :dialog="myDialog">
  36. </upload-files-dialog>
  37. <upload-img-dialog :read="onlyRead ? true : false" @changeFile="imgChange" :keysArr="imgsArr"
  38. :dialog="myDialog"></upload-img-dialog>
  39. <pic-dialog :read="onlyRead ? true : false" :dialog="myDialog" :keysArr="picsArr" @change="changePics"></pic-dialog>
  40. <details-dialog :iframeSrc="iframeSrc" v-if="myDialog.details" :dialog="myDialog"></details-dialog>
  41. <!-- 不支持的输入方式 -->
  42. <el-dialog title="临时维护信息点" :visible.sync="myDialog.update" @close="handleCloseUpdate" width="670px">
  43. <el-row>
  44. 该信息点未定义对应组件,现在维护数据不确定后续是否可用。如确实需要维护,请点击
  45. <el-link @click="updateInputShow = true" type="primary" :underline="false">继续维护</el-link>
  46. </el-row>
  47. <el-row style="margin-top:20px;" v-show="updateInputShow">
  48. <el-input type="textarea" :autosize="{ minRows: 4, maxRows: 8}" placeholder="请输入内容"
  49. v-model="updateInput"></el-input>
  50. </el-row>
  51. <span slot="footer" class="dialog-footer">
  52. <el-button @click="myDialog.update = false">取 消</el-button>
  53. <el-button type="primary" @click="handleClickUpdate">确 认</el-button>
  54. </span>
  55. </el-dialog>
  56. </div>
  57. </template>
  58. <script>
  59. import tools from "@/utils/scan/tools";
  60. import handsonUtils from "@/utils/hasontableUtils";
  61. import showTools from "@/utils/handsontable/notShow";
  62. import text from "@/utils/handsontable/mainText";
  63. import session from "@/framework/utils/storage";
  64. import handsonTable from "@/components/common/handsontable";
  65. import {
  66. // getDataDictionary,
  67. createPart,
  68. createPropertyData,
  69. getEquipBelongs
  70. } from "@/api/scan/request";
  71. import { getDataDictionary } from "@/api/dict";
  72. import { mapGetters, mapActions } from "vuex";
  73. import qrcode from "@/components/ledger/lib/qrcode";
  74. import uploadFilesDialog from "@/components/dialogs/list/filesDialog";
  75. import uploadImgDialog from "@/components/dialogs/list/uploadImgDialog";
  76. import picDialog from "@/components/dialogs/list/picDialog";
  77. export default {
  78. components: {
  79. qrcode, //二维码页面
  80. uploadFilesDialog,
  81. uploadImgDialog,
  82. picDialog,
  83. handsonTable
  84. },
  85. data() {
  86. return {
  87. addNum: 1,
  88. onlyRead: false,
  89. tableHeader: [],
  90. tableData: session.get("partsAddData")
  91. ? session.get("partsAddData").length
  92. ? session.get("partsAddData")
  93. : [{ Checked: 1 }]
  94. : [{ Checked: 1 }],
  95. showTypes: [
  96. { value: "partInfo", label: '隐藏信息点' },
  97. { value: "all", label: '全部' },
  98. { value: "Visible", label: '只看采集信息' }
  99. ],
  100. showType: this.$route.query.showType,
  101. copyTableData: [],
  102. category: "", //当前设备类
  103. myDialog: {
  104. qrcode: false, //二维码弹窗
  105. uploadFiles: false, //上传文件
  106. uploadImgs: false, //上传单个图片
  107. pic: false, //多个图片
  108. addDevice: false,
  109. systemType: false,
  110. details: false, //详情页
  111. changeRea: false,
  112. lookPic: false, //图片查看
  113. update: false,//临时维护信息点
  114. },
  115. inputMap: {
  116. flowBuild: {
  117. editable: true,
  118. code: "flowBuild",
  119. name: "建筑楼层",
  120. path: "flowBuild",
  121. category: 'STATIC',
  122. dataType: "ENUM"
  123. }
  124. }, //信息点和输入方式映射表
  125. updateInputShow: false, //是否显示临时维护输入框
  126. updateInfoPoint: '',//临时维护信息点
  127. updateInput: '', //临时维护信息点值
  128. qrcodeUrl: "", //二维码图片地址
  129. filesArr: [], //保存临时的文件key
  130. imgsArr: [], //临时保存的图片key数组
  131. picsArr: [], //临时设备图片keys数组
  132. systemId: null,
  133. graphyId: null,
  134. id: 0,
  135. EquipmentList: [],
  136. firmId: "" //品牌型号所需字段--族id三位编码(传设备类id或部件类id)
  137. };
  138. },
  139. computed: {
  140. ...mapGetters("layout", ["projectId", "secret", "userId"])
  141. },
  142. created() {
  143. this.category = this.$route.query;
  144. this.category.parentId = this.category.code.substr(0, this.category.code.length - 2);
  145. this.getBelongs();
  146. this.getTableHeader();
  147. },
  148. methods: {
  149. //查询部件类对应的 族
  150. getBelongs() {
  151. let params = {
  152. data: {
  153. filters: `equipCode='${this.category.code}'`,
  154. pageNumber: 1,
  155. pageSize: 50
  156. }
  157. }
  158. getEquipBelongs(params, res => {
  159. if (res.content.length) {
  160. this.firmId = res.content[0].family;
  161. }
  162. })
  163. },
  164. // 获取表头数据(初始化表格)
  165. async getTableHeader() {
  166. let params = {
  167. orders: "sort asc, name desc",
  168. pageNumber: 1,
  169. pageSize: 1000,
  170. type: this.category.code
  171. // Filters: `type='Equipment' or type='${this.category.Code}'`
  172. };
  173. await getDataDictionary(params, res => {
  174. this.tableHeader = res.content;
  175. this.tableHeader.forEach(item => {
  176. if (item.path) {
  177. this.inputMap[item.path] = item
  178. }
  179. });
  180. this.initTable();
  181. });
  182. },
  183. // 创建部件数据
  184. async handleCreateTableData() {
  185. let newData = this.tableData.filter(item => {
  186. let keys = Object.keys(item);
  187. keys.map(key => {
  188. //将值为空字符串的属性删除
  189. if (item[key] == "") {
  190. delete item[key];
  191. }
  192. });
  193. let newK = Object.keys(item)
  194. if ((item.Checked && newK.length > 1) || (!item.Checked && newK.length)) {
  195. return item;
  196. }
  197. });
  198. if (!newData.length) {
  199. this.$message("创建信息为空,请录入信息后再创建!");
  200. return;
  201. }
  202. let flag = false;
  203. newData.map(item => {
  204. if (item.Checked && !item.localName) {
  205. flag = true;
  206. }
  207. })
  208. if (flag) {
  209. this.$message.info("存在设备的本地名称为空,请检查")
  210. return;
  211. }
  212. for (let i = 0; i < newData.length; i++) {
  213. newData[i].parentId = this.category.deviceId //当前设备id
  214. newData[i].classCode = this.category.code //当前部件分类
  215. newData[i].family = this.firmId;
  216. //待接口修改为关联创建
  217. let param = {
  218. cascade: [],
  219. content: [newData[i]]
  220. }
  221. await createPart(param, async res => {
  222. if (newData[i].Checked) {//同时创建资产
  223. param.content[0].equipmentId = res.entityList[0].id
  224. await createPropertyData(param, res => {
  225. // todo 创建资产
  226. })
  227. }
  228. if (i == newData.length - 1) {
  229. this.$message.success('创建成功')
  230. session.remove("partsAddData")
  231. this.$router.push({
  232. path: "/ledger/partsmanage",
  233. query: {
  234. deviceId: this.category.deviceId,
  235. typeId: this.category.parentId,
  236. pageNo: this.category.pageNo,
  237. pageSize: this.category.pageSize
  238. }
  239. });
  240. }
  241. })
  242. }
  243. },
  244. // 删除表格行
  245. handleDeleteTableRow() {
  246. this.$message.success("删除成功");
  247. this.formaTableData();
  248. },
  249. // 添加行
  250. handleAddTableRow() {
  251. let addRowLength = this.addNum;
  252. for (let i = 0; i < addRowLength; i++) {
  253. this.tableData.push({ Checked: 1 });
  254. }
  255. this.initTable();
  256. this.formaTableData();
  257. },
  258. //修改
  259. handleUpdataTable(changeData, source) {
  260. if (!this.onlyRead && source != 'ObserveChanges.change') {
  261. this.formaTableData();
  262. }
  263. },
  264. //保存去掉空字段的新增数据
  265. formaTableData() {
  266. let newData = this.tableData.filter(item => {
  267. let keys = Object.keys(item);
  268. keys.map(key => {
  269. //将值为空字符串的属性删除
  270. if (item[key] == "") {
  271. delete item[key];
  272. }
  273. });
  274. if (keys.length && Object.keys(item).length) {
  275. return item;
  276. }
  277. });
  278. session.set("partsAddData", newData);
  279. },
  280. //格式化表头显示的数据
  281. formatHeaderData(list) {
  282. let arr = tools.copyArr(list)
  283. let data = showTools.headerTextFilter(arr, "parts", this.onlyRead, this.showType, true)
  284. data.unshift("同时创建资产")
  285. return data
  286. },
  287. formatHeaderType(list) {
  288. //格式化表头头映射的数据
  289. let arr = tools.copyArr(list);
  290. let data = showTools.headerTypeFilter(arr, "parts", this.onlyRead, this.showType, true)
  291. data.unshift({
  292. type: "checkbox",
  293. checkedTemplate: 1,
  294. uncheckedTemplate: 0,
  295. data: "Checked",
  296. label: {
  297. position: "after"
  298. }
  299. });
  300. return data;
  301. },
  302. initTable() {
  303. //实例化表格
  304. let settings = {
  305. data: this.tableData,
  306. colHeaders: this.formatHeaderData(this.tableHeader),
  307. columns: this.formatHeaderType(this.tableHeader),
  308. rowHeights: 30,
  309. maxRows: this.tableData.length,
  310. contextMenu: this.onlyRead ? false : {
  311. items: {
  312. remove_row: {
  313. name: "删除部件"
  314. }
  315. }
  316. },
  317. // 事件
  318. afterChange: this.handleUpdataTable, //修改后
  319. afterFilter: this.trimmedRows, //排序前
  320. afterRemoveRow: this.handleDeleteTableRow, //右键删除
  321. afterOnCellMouseDown: this.handleTdClick //鼠标点击
  322. };
  323. this.$nextTick(() => {
  324. this.tableExample = this.$refs.table.init(settings);
  325. });
  326. },
  327. //去除数组中相同的元素
  328. array_diff(a, b) {
  329. for (var i = 0; i < b.length; i++) {
  330. for (var j = 0; j < a.length; j++) {
  331. if (a[j] == b[i]) {
  332. a.splice(j, 1);
  333. j = j - 1;
  334. }
  335. }
  336. }
  337. return a;
  338. },
  339. //上传文件弹窗触发事件
  340. fileChange(keys) {
  341. this.setDataToMain(keys, this.messKey, this.row);
  342. },
  343. //上传图片弹窗触发事件
  344. imgChange(keys) {
  345. this.setDataToMain(keys, this.messKey, this.row);
  346. },
  347. //设备图片弹窗改变事件
  348. changePics(keys) {
  349. this.setDataToMain(keys, this.messKey, this.row);
  350. },
  351. //表格点击事件
  352. handleTdClick(el, rowArr) {
  353. //点击的是表头
  354. if (rowArr.row < 0) {
  355. return;
  356. }
  357. //被筛选过后的数组
  358. let trimmedArr = this.trimmedRows();
  359. //是否启用了排序
  360. let isSort = this.tableExample.getPlugin("columnSorting").isSorted();
  361. if (trimmedArr.length && isSort) {
  362. let sortArr = this.myHotArr.getPlugin("columnSorting").rowsMapper
  363. .__arrayMap;
  364. let infos = this.tableData[trimmedArr[sortArr[rowArr.row]]];
  365. this.getInfors(infos, { row: sortArr[rowArr.row], col: rowArr.col });
  366. } else if (isSort) {
  367. //排序后的数组
  368. let sortArr = this.tableExample.getPlugin("columnSorting").rowsMapper
  369. .__arrayMap;
  370. let infos = this.tableData[sortArr[rowArr.row]];
  371. this.getInfors(infos, { row: sortArr[rowArr.row], col: rowArr.col });
  372. } else if (trimmedArr.length) {
  373. let infos = this.tableData[trimmedArr[rowArr.row]];
  374. this.getInfors(infos, { row: trimmedArr[rowArr.row], col: rowArr.col });
  375. } else {
  376. let infos = this.tableData[rowArr.row];
  377. this.getInfors(infos, rowArr);
  378. }
  379. },
  380. //获取被筛选掉的行号
  381. trimmedRows() {
  382. var plugin = this.tableExample.getPlugin("trimRows").trimmedRows;
  383. let dataLength = this.tableData.length;
  384. let dataArr = new Array();
  385. for (let i = 0; i < dataLength; i++) {
  386. dataArr.push(i);
  387. }
  388. if (plugin.length <= 0) {
  389. dataArr = undefined;
  390. } else {
  391. dataArr = this.array_diff(dataArr, plugin);
  392. }
  393. return dataArr || [];
  394. },
  395. getInfors(infos, row) {
  396. //其他的开始判断
  397. let val = this.tableExample.colToProp(row.col);
  398. let inputData = this.inputMap[val];
  399. this.row = row.row;
  400. this.messKey = val;
  401. //设备二维码图片
  402. if (val == "defaultQRCode") {
  403. this.myDialog.qrcode = true;
  404. this.$refs.qrcode.getCanvas(1111);
  405. }
  406. if (
  407. val == "flowBuild" || //所属建筑楼层
  408. val == "infos.productDate" || //生产日期
  409. val == "infos.serialNum" || //出厂编号
  410. val == "infos.assetID" || //资产编号
  411. val == "infos.purchasePrice" || //采购价格
  412. val == "infos.insuranceNum" || //保险单号
  413. val == "infos.insuranceFile" //保险文件
  414. ) {
  415. const propertyId = this.tableData[row.row].propertyId;
  416. if (!propertyId) { //未关联资产
  417. this.$confirm('请先关联资产再维护该信息!', '提示', {
  418. confirmButtonText: '确定',
  419. showCancelButton: false,
  420. type: 'warning'
  421. }).then(() => {
  422. return false;
  423. });
  424. }
  425. return false
  426. }
  427. //保险文件--设备文档--安装质检报告
  428. if (
  429. val == "infos.insuranceFile" || //保险文件
  430. val == "infos.archive" || //设备文档
  431. val == "infos.checkReport" || //安装质检报告
  432. val == "infos.maintainManual" || //维修保养手册
  433. val == "infos.approachingAcceptance" || //进场验收单
  434. val == "infos.acceptanceReport" || //验收报告
  435. val == "infos.operationManual" || //操作说明书
  436. val == "infos.originalCertificate" || //原厂证明
  437. val == "infos.testReport" || //检测报告
  438. val == "infos.productCertification" || //产品合格证
  439. val == "infos.installInstruction" || //
  440. val == 'infos.supplierContract' || //供应合同
  441. val == "infos.drawing" || //设备图纸
  442. val == "infos.installDrawing" //安装图纸
  443. ) {
  444. let data = tools.dataForKey(this.tableData[row.row], val)
  445. this.filesArr = data ? data : []
  446. this.myDialog.uploadFiles = true;
  447. }
  448. //安装照片--设备铭牌照片
  449. if (
  450. val == "infos.installPic" ||
  451. val == "infos.nameplate"
  452. ) {
  453. let data = tools.dataForKey(this.tableData[row.row], val)
  454. this.imgsArr = data ? data : []
  455. this.myDialog.uploadImgs = true;
  456. }
  457. //设备照片
  458. if (val == "infos.pic") {
  459. let data = tools.dataForKey(this.tableData[row.row], val)
  460. this.picsArr = data ? data : []
  461. this.myDialog.pic = true;
  462. }
  463. if (!this.onlyRead && !inputData.editable) {
  464. this.$message("该信息点的值为自动生成,不可人工维护!");
  465. return false;
  466. }
  467. if (!this.onlyRead && showTools.inputModeArr.indexOf(inputData.dataType) == '-1') {
  468. this.updateInfoPoint = val;
  469. this.updateInput = tools.dataForKey(this.tableData[row.row], val);
  470. this.myDialog.update = true;
  471. return false;
  472. }
  473. },
  474. //关闭临时维护弹窗回调
  475. handleCloseUpdate() {
  476. this.updateInputShow = false
  477. this.updateInfoPoint = ''
  478. this.updateInput = ''
  479. },
  480. //更新临时维护信息点
  481. handleClickUpdate() {
  482. tools.setDataForKey(this.tableData[this.row], this.updateInfoPoint, this.updateInput)
  483. this.handleUpdataTable([[this.row, this.updateInfoPoint, null, this.updateInput]], "edit")
  484. this.updateInputShow = false
  485. this.myDialog.update = false
  486. this.updateInput = ''
  487. },
  488. utilToKey(key, name, data, messName) {
  489. if (key == name) {
  490. this.setDataToMain(data[key], messName, this.row);
  491. }
  492. },
  493. //判断是否有值,有值赋值
  494. setDataToMain(data, key, row) {
  495. if (!!data && data != "--") {
  496. if (!!this.tableData[row]) {
  497. //铭牌照片特殊处理
  498. tools.setDataForKey(this.tableData[row], key, data)
  499. // this.tableData[row][key] = data;
  500. } else {
  501. this.tableData[row] = {};
  502. tools.setDataForKey(this.tableData[row], key, data)
  503. }
  504. } else {
  505. tools.setDataForKey(this.tableData[row], key, "")
  506. }
  507. }
  508. }
  509. };
  510. </script>
  511. <style lang="less" scoped>
  512. #deviceList {
  513. overflow: hidden;
  514. height: 100%;
  515. background-color: #fff;
  516. padding: 10px;
  517. position: relative;
  518. .right {
  519. background: #fff;
  520. }
  521. .search-header {
  522. overflow: hidden;
  523. padding: 0 10px 10px 10px;
  524. border-bottom: 1px solid #bcbcbc;
  525. }
  526. .tableBox {
  527. display: flex;
  528. height: calc(100% - 100px);
  529. margin-top: 10px;
  530. .tableLeft {
  531. flex: 1;
  532. }
  533. }
  534. .create_button {
  535. margin-top: 10px;
  536. }
  537. }
  538. </style>