step1.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. <template>
  2. <div id="handsonStep1">
  3. <div class="btns-view">
  4. <el-button style="float:right;margin-top:4px;margin-left:10px;width:120px;" @click="saveData">保存</el-button>
  5. <el-button style="float:right;margin-top:4px;width:120px;" @click="addRow">新增行</el-button>
  6. <el-button style="float:right;margin-top:4px;width:120px;" @click="downData">导出配置点位表</el-button>
  7. <el-button style="float:right;margin-top:4px;width:120px;" @click="updateExcel = true">导入Excel</el-button>
  8. <el-button style="float:right;margin-top:4px;width:120px;" @click="downloadExcel = true">导出Excel模板</el-button>
  9. <el-checkbox style="float:right;line-height:40px;" @change="getData" v-model="checked">只显示使用的原始点位</el-checkbox>
  10. <el-button @click="clickPointVal">获取原始点位当前值</el-button>
  11. </div>
  12. <div id="handsontableSteps1" class="middle_sty" v-loading="isLoading">
  13. <handsontable-component v-if="!!allData.length" @delete="delePoint" ref="handsontable" @mouseDown="clickTable" @change="changeHand"></handsontable-component>
  14. <div v-else class="center">
  15. <i class="icon-wushuju iconfont"></i>
  16. 暂无数据
  17. </div>
  18. </div>
  19. <own-dialog :width="'500px'" :index="true" title="位置标签" :dialogVisible="localtionDialog" @cancel="closeFalg">
  20. <localtion-falg :renderData="renderData" @changeTag="changeLoc"></localtion-falg>
  21. </own-dialog>
  22. <own-dialog :width="'500px'" :index="true" title="导出excel模板" :dialogVisible="downloadExcel" :footer="footer" @cancel="close" @confirm="download">
  23. <span>请选择要导出的模板</span>
  24. <el-select v-model="exportTemplate" placeholder="请选择模板">
  25. <el-option label="模板一" value="0"></el-option>
  26. <el-option label="模板二" value="1" :disabled="protocolType!='common'"></el-option>
  27. </el-select>
  28. </own-dialog>
  29. <own-dialog :width="'500px'" :index="true" :footer="footer" title="导入excel" :dialogVisible="updateExcel" @confirm="sureOfUpload" @cancel="close">
  30. <div class="center" style="height:100px;">
  31. <upload-file accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" @change="changeFile"></upload-file>
  32. <p style="font-size:12px;">上传文件大小在1M以内</p>
  33. </div>
  34. <div>
  35. <span>请选择要导入的模板</span>
  36. <el-select v-model="importTemplate" placeholder="请选择模板">
  37. <el-option label="模板一" value="0"></el-option>
  38. <el-option label="模板二" value="1" :disabled="protocolType!='common'"></el-option>
  39. </el-select>
  40. </div>
  41. <div>
  42. <el-radio class="radio-left" v-model="radio" label="1">默认使用导入的全部原始点位</el-radio>
  43. <el-radio class="radio-left" v-model="radio" label="2">默认不使用导入的全部原始点位</el-radio>
  44. </div>
  45. </own-dialog>
  46. <div class="right">
  47. <pagination :page="pages" @change="changePage"></pagination>
  48. </div>
  49. </div>
  50. </template>
  51. <script>
  52. import tools from "@/utils/scan/tools"
  53. import handsontableComponent from "@/components/common/handsontable"
  54. import getHeaderSetting from "@/utils/point_edit/handson_header"
  55. import ownDialog from "@/components/el_pack/dialog"
  56. import localtionFalg from "@/components/config_point/location_flag"
  57. import pagination from "@/components/common/myPagination"
  58. // import "@/assets/js/chosen.jquery.min";
  59. // import "@/assets/js/handsontable-chosen-editor";
  60. // import Handsontable from "handsontable-pro"
  61. import {
  62. mapGetters,
  63. mapActions
  64. } from "vuex";
  65. import {
  66. changeHeader,
  67. showTypes
  68. } from "@/utils/handsontable/delType"
  69. import {
  70. queryPoint,
  71. updatePoint,
  72. createPoint,
  73. downloadTemplete,
  74. uploadPointFile,
  75. uploadPointFile2,
  76. deletePoint,
  77. getPointValue
  78. } from "@/fetch/point_http"
  79. import uploadFile from "@/components/common/uploadFile"
  80. import axios from 'axios'
  81. export default {
  82. data() {
  83. return {
  84. checked: false,
  85. settings: {},
  86. hot: null,
  87. changeFlag: true, //是否发生修改
  88. localtionDialog: false,
  89. renderData: {},
  90. allData: [],
  91. copyMain: [],
  92. pages: {
  93. size: 50,
  94. sizes: [10, 30, 50, 100, 150, 200],
  95. total: 0,
  96. currentPage: 0
  97. },
  98. oldPage: {
  99. currentPage: 0,
  100. size: 10
  101. },
  102. downloadExcel: false,
  103. isLoading: false,
  104. updateExcel: false,
  105. radio: '1',
  106. file: "", //上传的文件
  107. footer: {
  108. cancel: '取消',
  109. confirm: '确定'
  110. },
  111. exportTemplate:'0',
  112. importTemplate:'0'
  113. }
  114. },
  115. computed: {
  116. ...mapGetters("project", [
  117. "datasourceId",
  118. "protocolType"
  119. ]),
  120. projectId () {
  121. return this.$store.getters['layout/projectId']
  122. }
  123. },
  124. created() {},
  125. mounted() {
  126. if (!this.datasourceId) {
  127. this.$router.push({
  128. path: "/point/pointsetting"
  129. })
  130. } else {
  131. this.getData()
  132. }
  133. },
  134. methods: {
  135. //关闭弹窗
  136. close() {
  137. this.downloadExcel = false
  138. this.updateExcel = false
  139. this.getData()
  140. },
  141. closeFalg() {
  142. this.localtionDialog = false
  143. },
  144. clickPointVal(){
  145. let data = this.hot.getSourceData()
  146. if(!data || !data.length){
  147. return false
  148. }
  149. let param = {
  150. data: {
  151. DataSourceId: this.datasourceId,
  152. PointIds: data.map(item => {
  153. return item.Id
  154. })
  155. },
  156. type: this.protocolType
  157. }
  158. getPointValue(param,res => {
  159. if(!!res.Content && res.Content.length){
  160. data.map(item => {
  161. res.Content.map(child => {
  162. if(item.Id == child.PointId){
  163. item.pointValue = child.Data.Data
  164. item.pointDate = child.Data.Time
  165. }
  166. })
  167. return item
  168. })
  169. }
  170. })
  171. },
  172. changeLoc(val) {
  173. this.renderData.LocationFlag = val
  174. this.changeFlag = false
  175. },
  176. downData() {
  177. let param = {
  178. method: 'post',
  179. url: `/pointconfig/point/${this.protocolType}/pointlist-export`,
  180. data: {
  181. DataSourceId: this.datasourceId
  182. },
  183. responseType: 'blob',
  184. headers: {
  185. ProjectId: this.projectId
  186. }
  187. }
  188. axios(param).then(function(res) {
  189. var blob = new Blob([res.data], {
  190. type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
  191. });
  192. var fileName = res.headers['content-disposition'];
  193. if (fileName)
  194. fileName = fileName.substring(fileName.indexOf('=') + 1);
  195. if ('download' in document.createElement('a')) { // 非IE下载
  196. const elink = document.createElement('a')
  197. elink.download = fileName
  198. elink.style.display = 'none'
  199. elink.href = URL.createObjectURL(blob)
  200. document.body.appendChild(elink)
  201. elink.click()
  202. URL.revokeObjectURL(elink.href) // 释放URL 对象
  203. document.body.removeChild(elink)
  204. } else { // IE10+下载
  205. navigator.msSaveBlob(blob, fileName)
  206. }
  207. }).catch(function(err) {
  208. })
  209. },
  210. //删除点位
  211. delePoint(delData) {
  212. let param = {
  213. data: delData.map(item => {
  214. return item.Id
  215. }),
  216. type: this.protocolType
  217. }
  218. console.log(delData,'delllll')
  219. if (!delData.length) {
  220. return false
  221. }
  222. if(!!delData){
  223. console.log(delData,'delData')
  224. if(!delData[0].Id){
  225. return false
  226. }
  227. }
  228. this.$confirm('你确定要删除点位吗?').then(_ => {
  229. deletePoint(param, res => {
  230. this.$message.success("删除成功")
  231. this.getData()
  232. })
  233. }).catch(_ => {
  234. this.$message("取消删除")
  235. this.getData()
  236. })
  237. },
  238. //下载excel模板
  239. download() {
  240. let url = `/pointconfig/point/${this.protocolType}/template-export`
  241. if(this.exportTemplate=='1'){
  242. url += '2'
  243. }
  244. axios({
  245. method: 'post',
  246. url: url,
  247. data: {
  248. DataSourceId: this.datasourceId
  249. },
  250. headers: {
  251. ProjectId: this.projectId
  252. },
  253. responseType: 'blob'
  254. }).then(function(res) {
  255. console.log(res)
  256. var blob = new Blob([res.data], {
  257. type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
  258. });
  259. var fileName = res.headers['content-disposition'];
  260. if (fileName)
  261. fileName = fileName.substring(fileName.indexOf('=') + 1);
  262. if ('download' in document.createElement('a')) { // 非IE下载
  263. const elink = document.createElement('a')
  264. elink.download = fileName
  265. elink.style.display = 'none'
  266. elink.href = URL.createObjectURL(blob)
  267. document.body.appendChild(elink)
  268. elink.click()
  269. URL.revokeObjectURL(elink.href) // 释放URL 对象
  270. document.body.removeChild(elink)
  271. } else { // IE10+下载
  272. navigator.msSaveBlob(blob, fileName)
  273. }
  274. }).catch(function(err) {
  275. })
  276. },
  277. //点击表格
  278. clickTable(info, row) {
  279. let activeCell = this.hot.getActiveEditor()
  280. if(activeCell.prop == "Used"){
  281. info.Used = !info.Used
  282. }
  283. if (activeCell.prop == "LocationFlag") {
  284. this.renderData = info
  285. this.localtionDialog = true
  286. }
  287. },
  288. addRow() {
  289. if (!!this.allData.length) {
  290. let data = this.hot.getSourceData()
  291. data.unshift({
  292. Used: true,
  293. LocationFlag: []
  294. })
  295. this.hot.loadData(data)
  296. this.hot.updateSettings({
  297. maxRows: data.length
  298. })
  299. } else {
  300. this.allData = [{
  301. Used: true,
  302. LocationFlag: []
  303. }]
  304. this.createHot()
  305. }
  306. },
  307. //页面发生更改
  308. changePage() {
  309. if (!this.changeFlag) {
  310. //发生更改,提示是否保存
  311. this.$confirm('存在数据未保存, 是否继续?', '提示', {
  312. confirmButtonText: '确定',
  313. cancelButtonText: '取消',
  314. type: 'warning'
  315. }).then(() => {
  316. this.getData()
  317. }).catch(() => {
  318. this.pages.currentPage = this.oldPage.currentPage
  319. this.pages.size = this.oldPage.size
  320. return false
  321. });
  322. } else {
  323. this.getData()
  324. }
  325. },
  326. getData() {
  327. // width = (document.getElementById("app").clientWidth - 50) / header.length
  328. this.isLoading = true
  329. let param = {
  330. type: this.protocolType,
  331. data: {
  332. Filters: {
  333. DatasourceId: this.datasourceId,
  334. },
  335. "PageNumber": this.pages.currentPage || 1,
  336. "PageSize": this.pages.size,
  337. }
  338. }
  339. if (this.checked) {
  340. param.data.Filters.Used = true
  341. }
  342. this.oldPage = {
  343. size: this.pages.size,
  344. currentPage: this.pages.currentPage
  345. }
  346. queryPoint(param, res => {
  347. this.isLoading = false
  348. this.changeFlag = true
  349. this.allData = res.Content || []
  350. this.copyMain = JSON.parse(JSON.stringify(res.Content))
  351. this.pages.total = res.Total
  352. this.createHot()
  353. })
  354. },
  355. //创建实例
  356. createHot() {
  357. let header, width, settings
  358. header = getHeaderSetting(this.protocolType)
  359. settings = {
  360. data: this.allData,
  361. colHeaders: changeHeader(header),
  362. columns: showTypes(header),
  363. rowHeights: 30,
  364. maxRows: this.allData.length,
  365. contextMenu: {
  366. items: {
  367. remove_row: {
  368. name: "删除点位"
  369. }
  370. }
  371. }
  372. }
  373. if (!this.allData.length) {
  374. return false
  375. }
  376. this.$nextTick(_ => {
  377. this.hot = this.$refs.handsontable.init(settings)
  378. })
  379. },
  380. //修改提示
  381. changeHand(changeData, source) {
  382. if (!!changeData) {
  383. let tableData = this.hot.getSourceData()
  384. for(let i = 0; i < tableData.length; i++){
  385. let forFlag = true
  386. if(!tools.isObjectValueEqual(this.copyMain[i],tableData[i])) {
  387. this.changeFlag = false
  388. forFlag = false
  389. break
  390. } else if (i == tableData.length - 1 && forFlag) {
  391. this.changeFlag = true
  392. }
  393. }
  394. }
  395. return false
  396. },
  397. //保存
  398. saveData() {
  399. if (!!this.hot) {
  400. console.log(this.hot.getSourceData(),'getSourceData')
  401. let data = this.hot.getSourceData(),
  402. updateList = [],
  403. arr1 = [],
  404. createList = [];
  405. data.map(item => {
  406. if (!!item.Id) {
  407. delete item.CreateTime
  408. delete item.LastUpdate
  409. if(item.hasOwnProperty('pointDate')){
  410. delete item.pointDate
  411. }
  412. if(item.hasOwnProperty('pointValue')){
  413. delete item.pointValue
  414. }
  415. arr1.push(item)
  416. updateList.push(item)
  417. } else {
  418. createList.push(item)
  419. }
  420. })
  421. console.log(updateList,createList, arr1, "updateList")
  422. if (createList.length || updateList.length) {
  423. let flag = true
  424. if (createList.length) {
  425. for (let i = 0; i < createList.length; i++) {
  426. if (!(
  427. (createList[i].hasOwnProperty("SlaveId") &&
  428. createList[i].SlaveId &&
  429. createList[i].hasOwnProperty("RegistersAddress") &&
  430. createList[i].RegistersAddress &&
  431. createList[i].hasOwnProperty("RegistersQuality") &&
  432. createList[i].RegistersQuality &&
  433. createList[i].hasOwnProperty("ConvertType") &&
  434. createList[i].ConvertType
  435. ) ||
  436. (createList[i].hasOwnProperty("DeviceId") &&
  437. createList[i].DeviceId &&
  438. createList[i].hasOwnProperty("InstanceNumber") &&
  439. createList[i].InstanceNumber &&
  440. createList[i].hasOwnProperty("DataType") &&
  441. createList[i].DataType
  442. ) ||
  443. (createList[i].hasOwnProperty("Item") &&
  444. createList[i].Item
  445. ) ||
  446. (createList[i].hasOwnProperty("GroupAddress") &&
  447. createList[i].GroupAddress
  448. ) ||
  449. (createList[i].hasOwnProperty("Topic") &&
  450. createList[i].Topic
  451. ) ||
  452. (createList[i].hasOwnProperty("Exchange") &&
  453. createList[i].Exchange &&
  454. createList[i].hasOwnProperty("Type") &&
  455. createList[i].Type &&
  456. createList[i].hasOwnProperty("RoutingKey") &&
  457. createList[i].RoutingKey
  458. ) ||
  459. (createList[i].hasOwnProperty("JoinedInfo") &&
  460. createList[i].JoinedInfo
  461. )
  462. )) {
  463. this.$message("请输入所有必填字段(带“*”列为必填列)")
  464. flag = false
  465. return false
  466. } else if (!(createList[i].hasOwnProperty("Description") && createList[i].Description)) {
  467. this.$message("请输入全部的原始点位描述")
  468. flag = false
  469. return false
  470. }
  471. }
  472. }
  473. if (flag) {
  474. this.createList(createList)
  475. if (updateList.length) {
  476. this.update(updateList)
  477. }
  478. }
  479. }
  480. } else {
  481. this.$message.error("请确保存在数据")
  482. }
  483. },
  484. async createList(createList) {
  485. for (let i = 0; i < createList.length; i++) {
  486. await this.create(createList[i])
  487. }
  488. this.changeFlag = true
  489. },
  490. async create(obj) {
  491. for (let key in obj) {
  492. if (key == "LocationFlag" && obj[key] == "") {
  493. obj[key] = []
  494. }
  495. if (obj[key] === "") {
  496. obj[key] = null
  497. }
  498. }
  499. obj.DatasourceId = this.datasourceId
  500. obj.ProjectId = this.projectId
  501. await createPoint({
  502. data: obj,
  503. type: this.protocolType
  504. }, res => {
  505. obj.Id = res.Id
  506. this.getData()
  507. })
  508. },
  509. /**
  510. * @param {更新list} updateList
  511. *
  512. * 更新点位
  513. */
  514. update(updateList) {
  515. updatePoint({
  516. data: {
  517. Content: updateList
  518. },
  519. type: this.protocolType
  520. }, res => {
  521. this.getData()
  522. })
  523. },
  524. //没有保存的时候弹窗
  525. noSaveData() {
  526. return this.changeFlag
  527. },
  528. //上传文件
  529. changeFile(file) {
  530. this.file = file[0] || ''
  531. },
  532. //确定上传
  533. sureOfUpload() {
  534. if (!!this.file) {
  535. //有文件进行上传
  536. let param = {
  537. data: new FormData(),
  538. type: this.protocolType
  539. };
  540. param.data.set('DataSourceId', this.datasourceId)
  541. param.data.set('Used', this.radio == 1 ? true : false)
  542. param.data.set('multipartFile', this.file.raw)
  543. if(this.importTemplate=='1'){
  544. uploadPointFile2(param, res => {
  545. this.$message.success("上传成功")
  546. this.getData()
  547. this.updateExcel = false
  548. })
  549. } else {
  550. uploadPointFile(param, res => {
  551. this.$message.success("上传成功")
  552. this.getData()
  553. this.updateExcel = false
  554. })
  555. }
  556. } else {
  557. this.$message.info("请选择文件")
  558. }
  559. }
  560. },
  561. components: {
  562. handsontableComponent,
  563. ownDialog,
  564. localtionFalg,
  565. pagination,
  566. uploadFile
  567. },
  568. }
  569. </script>
  570. <style lang="scss" scoped>
  571. .radio-left {
  572. display: block;
  573. line-height: 30px;
  574. margin-left: 100px;
  575. }
  576. #handsonStep1 {
  577. flex: 1;
  578. display: flex;
  579. flex-flow: column;
  580. padding-bottom: 10px;
  581. .btns-view {
  582. height: 40px;
  583. line-height: 40px;
  584. margin-bottom: 10px;
  585. padding: 0 10px;
  586. }
  587. #handsontableSteps1 {
  588. flex: 1;
  589. overflow: hidden;
  590. position: relative;
  591. margin: 0 10px;
  592. }
  593. }
  594. </style>