PlanCheckPoint_master104.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  1. <!-- 步骤2 -->
  2. <template>
  3. <div v-show="currentStep == 1" :class="className">
  4. <div class="title">测点导入</div>
  5. <div class="buttons">
  6. <div class="left">
  7. <!-- 批量删除 -->
  8. <div class="clear item">
  9. <el-button
  10. class="dark-button"
  11. icon="el-icon-delete"
  12. :disabled="!showDel"
  13. @click="multDelete()"
  14. >批量删除</el-button>
  15. </div>
  16. </div>
  17. <div class="right">
  18. <div class="item">
  19. <!-- 添加新测点 -->
  20. <el-button
  21. class="light-button"
  22. icon="el-icon-refresh-right"
  23. @click="updataTableData()"
  24. >刷新</el-button>
  25. </div>
  26. <div class="item">
  27. <!-- 导入即是上传文件 -->
  28. <el-upload
  29. ref="upload"
  30. :action="importCsvActionStr"
  31. :show-file-list="false"
  32. :auto-upload="false"
  33. accept=".csv"
  34. :on-change="submitUpload"
  35. >
  36. <el-button
  37. class="light-button"
  38. icon="el-icon-upload2"
  39. >导入</el-button>
  40. </el-upload>
  41. </div>
  42. <div class="export item">
  43. <el-button
  44. class="light-button"
  45. icon="el-icon-download"
  46. @click="getPlanExport()"
  47. >导出</el-button>
  48. </div>
  49. <div class="item">
  50. <!-- 添加新测点 -->
  51. <el-button
  52. class="dark-button"
  53. icon="el-icon-plus"
  54. @click="addCheckPoint()"
  55. >添加</el-button>
  56. </div>
  57. </div>
  58. </div>
  59. <div class="table-container">
  60. <el-table ref="multipleTable" v-loading="vloading" class="table-fixed" type="index" :data="tableData" :height="tableHeight" stripe @selection-change="handleSelectionChange">
  61. <el-table-column
  62. type="selection"
  63. />
  64. <!-- <el-table-column prop="id" label="序号" width="100" /> -->
  65. <el-table-column prop="iec104" label="104点号" width="100">
  66. <!-- rs.offset -->
  67. <template slot-scope="scope">
  68. <el-input
  69. v-model="scope.row.iec104"
  70. class="table-column-input"
  71. type="number"
  72. disabled
  73. />
  74. </template>
  75. </el-table-column>
  76. <el-table-column prop="name" label="* 测点名称" width="200">
  77. <template slot-scope="scope">
  78. <el-input
  79. v-model="scope.row.name"
  80. class="table-column-input"
  81. clearable
  82. placeholder="请输入名称"
  83. maxlength="32"
  84. />
  85. </template>
  86. </el-table-column>
  87. <el-table-column prop="name" label="* 设备名称" width="200">
  88. <template slot-scope="scope">
  89. <el-input
  90. v-model="scope.row.groupingName"
  91. class="table-column-input"
  92. clearable
  93. placeholder="请输入设备名称"
  94. maxlength="32"
  95. />
  96. </template>
  97. </el-table-column>
  98. <el-table-column prop="range" label="* 点号类型">
  99. <!-- rs.range -->
  100. <template slot-scope="scope">
  101. <el-select
  102. v-model="scope.row.range"
  103. class="table-column-input"
  104. placeholder=""
  105. :disabled="Boolean(scope.row.id)"
  106. >
  107. <el-option
  108. v-for="item in checkPointFuctionOptions"
  109. :key="item.id"
  110. :label="item.name"
  111. :value="item.id"
  112. />
  113. </el-select>
  114. </template>
  115. </el-table-column>
  116. <el-table-column prop="offset" label="* 点号">
  117. <!-- rs.offset -->
  118. <template slot-scope="scope">
  119. <el-input
  120. v-model="scope.row.offset"
  121. class="table-column-input"
  122. type="number"
  123. :disabled="Boolean(scope.row.id)"
  124. />
  125. </template>
  126. </el-table-column>
  127. <el-table-column prop="offset" label="关联遥信点号(仅遥控可关联)">
  128. <!-- rs.offset -->
  129. <template slot-scope="scope">
  130. <el-input
  131. v-if="scope.row.range=='COIL_STATUS'"
  132. v-model="scope.row.relationTag"
  133. class="table-column-input"
  134. placeholder="请输入遥信点号"
  135. type="number"
  136. />
  137. </template>
  138. </el-table-column>
  139. <el-table-column prop="offset" label="关联遥测点号(仅遥调可关联)">
  140. <!-- rs.offset -->
  141. <template slot-scope="scope">
  142. <el-input
  143. v-if="scope.row.range=='HOLDING_REGISTER'"
  144. v-model="scope.row.relationTag"
  145. class="table-column-input"
  146. placeholder="请输入遥测点号"
  147. type="number"
  148. />
  149. </template>
  150. </el-table-column>
  151. <el-table-column prop="scaling" label="倍率" width="80">
  152. <!-- scaling -->
  153. <template slot-scope="scope">
  154. <el-input
  155. v-model="scope.row.scaling"
  156. class="table-column-input"
  157. clearable
  158. type="number"
  159. maxlength="32"
  160. />
  161. </template>
  162. </el-table-column>
  163. <el-table-column prop="adjust" label="偏移量" width="80">
  164. <template slot-scope="scope">
  165. <el-input
  166. v-model="scope.row.adjust"
  167. class="table-column-input"
  168. clearable
  169. type="number"
  170. maxlength="32"
  171. />
  172. </template>
  173. </el-table-column>
  174. <el-table-column label="操作" width="180" fixed="right">
  175. <template slot-scope="scope">
  176. <el-button
  177. class="table-act"
  178. type="text"
  179. icon="el-icon-edit"
  180. size="small"
  181. @click="editClick(scope.row, scope.$index)"
  182. >
  183. 编辑
  184. </el-button>
  185. <el-button
  186. class="table-act"
  187. type="text"
  188. icon="el-icon-s-order"
  189. size="small"
  190. @click="saveClick(scope.row,scope.$index)"
  191. >保存</el-button>
  192. <el-button
  193. class="table-act"
  194. type="text"
  195. icon="el-icon-delete"
  196. size="small"
  197. @click="delClick(scope.row, scope.$index)"
  198. >删除</el-button>
  199. </template>
  200. </el-table-column>
  201. </el-table>
  202. </div>
  203. <!-- 编辑弹出的模态框套表单 -->
  204. <el-dialog title="测点信息" :close-on-click-modal="false" :visible.sync="dialogFormVisible">
  205. <el-form ref="form" :model="form">
  206. <el-form-item label="*测点名称" :label-width="formLabelWidth">
  207. <el-input v-model="form.name" autocomplete="off" maxlength="32" placeholder="请输入测点名称" />
  208. </el-form-item>
  209. <el-form-item label="*设备名称" :label-width="formLabelWidth">
  210. <el-input v-model="form.groupingName" maxlength="20" placeholder="请输入设备名称" />
  211. </el-form-item>
  212. <el-form-item class="modelInput" label="*测点类型" :label-width="formLabelWidth">
  213. <template slot-scope="scope">
  214. <el-select
  215. :key="toString(scope.row)"
  216. v-model="form.range"
  217. clearable
  218. placeholder=""
  219. >
  220. <el-option
  221. v-for="item in checkPointFuctionOptions"
  222. :key="item.id"
  223. :label="item.name"
  224. :value="item.id"
  225. />
  226. </el-select>
  227. </template>
  228. </el-form-item>
  229. <el-form-item label="*点号" :label-width="formLabelWidth">
  230. <el-input v-model="form.offset" maxlength="6" />
  231. </el-form-item>
  232. <el-form-item label="关联遥信点号 (仅遥控可关联)" :label-width="formLabelWidth">
  233. <el-input v-if="form.range=='COIL_STATUS'" v-model="form.relationTag" maxlength="6" placeholder="请输入遥信点号" />
  234. <el-input v-else v-model="form.relationTag" disabled />
  235. </el-form-item>
  236. <el-form-item label="关联遥测点号 (仅遥调可关联)" :label-width="formLabelWidth">
  237. <el-input v-if="form.range=='HOLDING_REGISTER'" v-model="form.relationTag" maxlength="6" placeholder="请输入遥测点号" />
  238. <el-input v-else v-model="form.relationTag" disabled />
  239. </el-form-item>
  240. <el-form-item label="倍率" :label-width="formLabelWidth">
  241. <el-input v-model="form.scaling" maxlength="5" />
  242. </el-form-item>
  243. <el-form-item label="偏移量" :label-width="formLabelWidth">
  244. <el-input v-model="form.adjust" maxlength="6" />
  245. </el-form-item>
  246. </el-form>
  247. <div slot="footer" class="dialog-footer">
  248. <el-button @click="dialogFormVisible = false">取 消</el-button>
  249. <el-button type="primary" @click="saveForm">确 定</el-button>
  250. </div>
  251. </el-dialog>
  252. <!-- 分页 -->
  253. <pagination
  254. background
  255. layout="pager"
  256. :limit="pageLimit"
  257. :total="paginationTotalElements"
  258. :current-page.sync="paginationNumber"
  259. :page="paginationNumber"
  260. @pagination="getPlanCheckPoint"
  261. />
  262. <!-- 底部按钮 -->
  263. <div class="bottom-button">
  264. <div class="cancel-plan">
  265. <el-button class="light-button" @click="backStep">上一步</el-button>
  266. </div>
  267. <div class="save-plan">
  268. <el-button class="dark-button" @click="submitPlan()">下一步</el-button>
  269. </div>
  270. </div>
  271. <!-- 检查本地存储是否成功 -->
  272. <!-- <el-button @click="checkStore()">checkStore</el-button> -->
  273. </div>
  274. </template>
  275. <script>
  276. import { planExport } from '@/api/plan'
  277. import { dictOptions } from '@/api/dict'
  278. import Pagination from '@/components/Pagination'
  279. import { delRecord, editRow, httpGet, putData } from '@/api/common-action'
  280. export default {
  281. components: { Pagination },
  282. props: {
  283. className: {
  284. type: String,
  285. default: 'steps-bar-default'
  286. },
  287. currentStep: {
  288. type: Number,
  289. default: 1
  290. },
  291. currentPlanData: {
  292. type: Object,
  293. default: function() {
  294. return
  295. }
  296. }
  297. },
  298. data() {
  299. return {
  300. vloading: true,
  301. // 表格默认数据
  302. tableData: [],
  303. tmpCheckPointId: 0,
  304. tmpTableData: [],
  305. // 每页显示多少条
  306. pageLimit: 20,
  307. paginationNumber: 1,
  308. // 一共多少条
  309. paginationTotalElements: 0,
  310. // 一共多少页
  311. // paginationTotalPages: 1,
  312. // 导入csv 请求参数
  313. importCsvActionStr: '#',
  314. // 功能码选项
  315. checkPointFuctionOptions: [],
  316. // 值类型列表
  317. valueTypeVale: '',
  318. valueTypeOptions: [],
  319. // 批量删除显示控制
  320. showDel: false,
  321. // 选中的arr
  322. delarr: [],
  323. dialogFormVisible: false,
  324. // 模态框内表单
  325. form: {},
  326. formLabelWidth: '120px',
  327. // 模态框表单内数据
  328. modalFromArr: [],
  329. stepIndex: '',
  330. tableHeight: '',
  331. // 多选框选中数据
  332. multipleSelection: ''
  333. }
  334. },
  335. watch: {
  336. multipleSelection(nv, ov) {
  337. if (nv.length === 0) {
  338. // console.log('nv = ', nv)
  339. this.showDel = false
  340. }
  341. },
  342. 'tableData': {
  343. handler() {
  344. this.$nextTick(() => {
  345. this.$refs.multipleTable.doLayout()
  346. })
  347. true
  348. },
  349. deep: true
  350. }
  351. },
  352. // computed: {
  353. // totalOfEle: () => {
  354. // console.log(this.tableData)
  355. // return this.tableData.length
  356. // }
  357. // },
  358. created() {
  359. const marginBottom = 500
  360. this.tableHeight = window.innerHeight - marginBottom
  361. },
  362. mounted() {
  363. this.$nextTick(() => {
  364. const envUrl = process.env.VUE_APP_BASE_API
  365. // 网页加载完成后执行
  366. this.importCsvActionStr = envUrl + `/product/model/0/models.csv`
  367. if (this.currentPlanData.id > 0) {
  368. // 如果获取到了PlanId再加载详细信息
  369. this.getPlanCheckPoint()
  370. this.importCsvActionStr = envUrl + `/product/model/${this.currentPlanData.product}/models.csv`
  371. }
  372. this.initFunctions()
  373. })
  374. },
  375. methods: {
  376. // 检查本地存储是否成功
  377. // checkStore() {
  378. // console.log('checkStore start ')
  379. // const planFromDataStorage = localStorage.getItem('planFromData')
  380. // console.log('planFromData=',planFromDataStorage)
  381. // }
  382. // 文件限制
  383. // handleExceed(files, fileList) {
  384. // this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
  385. // },
  386. // 初始化
  387. async initFunctions() {
  388. // 获取当前
  389. // 获取功能码选项 131
  390. let res = await dictOptions('131')
  391. this.checkPointFuctionOptions = res
  392. // 获取值类型列表
  393. res = await dictOptions('132')
  394. this.valueTypeOptions = res
  395. // console.log('获取值类型列表 this.valueTypeOptions=', this.valueTypeOptions)
  396. this.valueTypeVale = this.valueTypeOptions[0]
  397. },
  398. // 上一步
  399. backStep() {
  400. let currentStep = this.currentStep
  401. currentStep--
  402. this.$emit('changeStep', currentStep)
  403. },
  404. // 新加测试点
  405. addCheckPoint() {
  406. // console.log('addCheckPoint 新加测试点', this.valueTypeOptions)
  407. this.tmpCheckPointId++
  408. const newTable = {
  409. tmpCheckPointId: this.tmpCheckPointId,
  410. name: '',
  411. groupingName: '',
  412. relationTag: '',
  413. range: this.checkPointFuctionOptions[0].id,
  414. offset: 0,
  415. dataType: this.valueTypeOptions[0].id,
  416. swapByte: false,
  417. swapWord: false,
  418. scaling: 1,
  419. adjust: 0,
  420. value: 0,
  421. // point104: 0,
  422. id: null
  423. }
  424. this.tableData.unshift(newTable)
  425. // 保存到临时表格数据中
  426. this.tmpTableData.push(newTable)
  427. this.tmpTableData.forEach((element) => {
  428. // console.log(`this.tmpTableData element=${element.tmpCheckPointId}`)
  429. })
  430. },
  431. // 导入
  432. submitUpload() {
  433. this.$refs.upload.submit()
  434. // 上传之后刷新页面查看上传结果
  435. this.getPlanCheckPoint()
  436. },
  437. // 导出
  438. async getPlanExport() {
  439. // /product/model/:product/models.csv
  440. planExport(this.currentPlanData.product).then((response) => {
  441. const link = document.createElement('a')
  442. const blob = new Blob([response], {
  443. type: 'application/vnd.ms-excel;charset=utf-8'
  444. })
  445. link.style.display = 'none'
  446. link.href = URL.createObjectURL(blob)
  447. link.setAttribute('download', `导出数据.csv`)
  448. document.body.appendChild(link)
  449. link.click()
  450. document.body.removeChild(link)
  451. // this.msgSuccess('导出成功')
  452. })
  453. },
  454. // 清除
  455. planClear() {
  456. // console.log('planClear 清除')
  457. this.tableData = []
  458. },
  459. // 获取测点表格数据
  460. async getPlanCheckPoint(pageObj) {
  461. this.vloading = true
  462. // 翻页时pageObj对象才会有值,属性分别为page和limit
  463. if (pageObj == null) {
  464. pageObj = {
  465. page: 0,
  466. limit: this.pageLimit
  467. }
  468. this.paginationNumber = 0
  469. } else {
  470. this.pageLimit = pageObj.limit
  471. }
  472. // 返回值
  473. /* {
  474. adjust:0 //偏移量
  475. dataType:null //值类型
  476. id:null //
  477. name:"中文" //测点名称
  478. offset:0 //104点号
  479. range:null //测点类型
  480. scaling:1 //倍率
  481. swapByte: 0, //字内交换
  482. swapWord: 0, //字节交换
  483. value:0 //先不用管- 测点查询
  484. "manual": null, //先不用管 -单测点查询
  485. "stepSeconds": 0, //先不用管 -单测点查询
  486. "pollingCycle": 0, //先不用管 -单测点查询
  487. "disable": null //先不用管 -单测点查询
  488. }
  489. totalPages 总页数
  490. number 第几页
  491. 删除默认 tableData数据 */
  492. const getUrl = `product/model/${this.currentPlanData.product}/paging?page=${pageObj.page}&size=${pageObj.limit}`
  493. httpGet(getUrl).then((response) => {
  494. this.vloading = false
  495. if (response == null || response.content == null || response.content.length === 0) {
  496. this.tableData = []
  497. this.paginationNumber = 0
  498. this.paginationTotalPages = 0
  499. this.paginationTotalElements = 0
  500. return
  501. }
  502. // 计算104点号
  503. // response.content.map((item, index) => {
  504. // item.point104 = this.calPoint104(item.range, item.offset)
  505. // })
  506. this.tableData = response.content
  507. this.paginationTotalPages = response.totalPages
  508. this.paginationTotalElements = parseInt(response.totalElements)
  509. this.paginationNumber = response.number * 1 + 1
  510. })
  511. },
  512. // 表格重排
  513. tableLayout() {
  514. this.$nextTick(() => {
  515. this.$refs.multipleTable.doLayout()
  516. })
  517. },
  518. // input失焦 添加数据
  519. // inputBlur(inputBlurData) {
  520. // // 2023-05-29 应后端要求,取消失焦保存
  521. // // console.log('inputBlur inputBlurData=', inputBlurData)
  522. // // // 后端不支持多条数据一起添加,所以这里失焦就添加数据,不需要再判断是否是临时添加数据
  523. // // // 此处 // /product/model/:product 中的 :product 是上一步添加方案时返回的 product 的值
  524. // // const editPath = `/product/model/${this.currentPlanData.product}`
  525. // // const editData = this.getSubmitTableRowData(inputBlurData)
  526. // // console.log('inputBlur editData=', editData)
  527. // // editRow(editPath, editData)
  528. // },
  529. async saveClick(row, index) {
  530. // if (row.offset > 65535) {
  531. // this.$message({
  532. // type: 'error',
  533. // message: `寄存器地址不能大于65535`,
  534. // offset: window.screen.height / 3
  535. // })
  536. // return
  537. // }
  538. const editPath = `/product/model/${this.currentPlanData.product}`
  539. const editData = row
  540. // const editData = this.getSubmitTableRowData(row)
  541. // console.log('saveClick editData=', editData)
  542. // 校验必填项目
  543. let isNotPassMesage = ''
  544. let v = editData.name || ''
  545. v = v.toString().replace(/ /gi, '')
  546. if (v === '') {
  547. isNotPassMesage = '必填项(测点名称)不能为空'
  548. }
  549. v = editData.groupingName || ''
  550. v = v.toString().replace(/ /gi, '')
  551. if (v === '') {
  552. isNotPassMesage = '必填项(设备名称)不能为空'
  553. }
  554. v = editData.range || ''
  555. v = v.toString().replace(/ /gi, '')
  556. if (v === '') {
  557. isNotPassMesage = '必填项(点号类型)不能为空'
  558. }
  559. v = editData.offset || ''
  560. v = v.toString().replace(/ /gi, '')
  561. if (v === '') {
  562. isNotPassMesage = '必填项(点号)不能为空'
  563. }
  564. if (isNotPassMesage !== '') {
  565. this.$message({
  566. type: 'error',
  567. message: isNotPassMesage,
  568. offset: window.screen.height / 3
  569. })
  570. return
  571. }
  572. const res = await editRow(editPath, editData)
  573. if (res) {
  574. this.$set(this.tableData[index], 'id', res.id)
  575. this.$set(this.tableData[index], 'modbus', res.modbus)
  576. this.$set(this.tableData[index], 'iec104', res.iec104)
  577. this.$message({
  578. type: 'success',
  579. message: `${res.name} 保存成功.`,
  580. offset: window.screen.height / 3
  581. })
  582. }
  583. },
  584. delClick(row) {
  585. // return
  586. this.$confirm('此操作将永久删除该记录, 是否继续?', `删除:${row.name}`, {
  587. confirmButtonText: '确定',
  588. cancelButtonText: '取消',
  589. type: 'warning'
  590. }).then(async() => {
  591. if (row.id != null && row.id > 0) {
  592. // // :product 产品名称
  593. // // :tag 标签编号
  594. const delUrl = `/product/model/${this.currentPlanData.product}/${row.id}`
  595. await delRecord(delUrl)
  596. .then((response) => {
  597. // console.log('delRecord rs=', response)
  598. // 后端成功执行后,前端再删除选中行
  599. // this.tableData.splice(index, 1)
  600. // this.tableData = this.tableData.filter(item => item.id !== row.id)
  601. const newData = this.tableData.filter(item => item.id !== row.id)
  602. this.tableData = [...newData]
  603. })
  604. } else {
  605. // 如果是新增的临时行,直接删除选中行
  606. // this.tableData.splice(index, 1)
  607. // this.tableData = this.tableData.filter(item => item.tmpCheckPointId !== row.tmpCheckPointId)
  608. const newData = this.tableData.filter(item => item.tmpCheckPointId !== row.tmpCheckPointId)
  609. // console.log('newData=', newData)
  610. this.tableData = [...newData]
  611. }
  612. }).catch(() => {
  613. this.$message({
  614. type: 'info',
  615. message: '已取消删除',
  616. offset: window.screen.height / 3
  617. })
  618. })
  619. },
  620. // 刷新
  621. updataTableData() {
  622. this.planClear()
  623. this.getPlanCheckPoint()
  624. },
  625. // 提交
  626. // 提交 下一步
  627. submitPlan() {
  628. // console.log(`this.tmpTableData=`, this.tmpTableData)
  629. let currentStep = this.currentStep
  630. const noName = this.tableData.some(item => (!item.groupingName) || (!item.name) || (!item.range) || (!item.offset.toString()))
  631. if (noName) {
  632. this.$message({
  633. type: 'error',
  634. message: '必填项不能为空',
  635. offset: window.screen.height / 3
  636. })
  637. return
  638. }
  639. if (currentStep < 3) {
  640. // 如果没有数据
  641. if (!this.tableData.length) {
  642. currentStep = currentStep + 1
  643. this.$emit('changeStep', currentStep)
  644. return
  645. }
  646. // 不接受数组提交,只能单条提交,所以使用遍历提交
  647. this.tableData.forEach((item, index) => {
  648. const tableRowData = this.getSubmitTableRowData(item)
  649. // 保存步骤
  650. const editPath = `/product/model/${this.currentPlanData.product}`
  651. editRow(editPath, tableRowData).then(res => {
  652. // console.log('PlanCheckPoint submitPlan currentStep=', currentStep)
  653. // console.log('PlanCheckPoint submitPlan index=', index)
  654. if (index === this.tableData.length - 1) {
  655. // 如果是最后一条数据 提交成功,下一步
  656. currentStep = currentStep + 1
  657. this.$emit('changeStep', currentStep)
  658. }
  659. })
  660. })
  661. } else {
  662. // 已经是最后一步了
  663. }
  664. },
  665. // 公用函数
  666. // 获取提交的行数据
  667. getSubmitTableRowData(rowData) {
  668. if (rowData.id > 0 || rowData.tmpCheckPointId > 0) {
  669. let submitRowData = []
  670. // {
  671. // adjust:0 //偏移量
  672. // dataType:null //值类型
  673. // id:null //
  674. // name:"中文" //测点名称
  675. // offset:0 //寄存器地址
  676. // range:null //功能码
  677. // scaling:1 //倍率
  678. // swapByte: 0, //字内交换
  679. // swapWord: 0, //字节交换
  680. // value:0 //先不用管- 测点查询
  681. // "manual": null, //先不用管 -单测点查询
  682. // "stepSeconds": 0, //先不用管 -单测点查询
  683. // "pollingCycle": 0, //先不用管 -单测点查询
  684. // "disable": null //先不用管 -单测点查询
  685. // }
  686. if (!rowData.id) {
  687. rowData.id = null
  688. }
  689. // 组织出待提交数据
  690. // {"tmpCheckPointId":2,"name":"","range":"COIL_STATUS","offset":0,"dataType":"BOOL","swapByte":false,"swapWord":false,"scaling":1,"adjust":0,"value":0,"id":null}
  691. submitRowData = {
  692. id: rowData.id,
  693. groupingName: rowData.groupingName,
  694. relationTag: rowData.relationTag,
  695. name: rowData.name,
  696. range: rowData.range,
  697. offset: rowData.offset,
  698. dataType: rowData.dataType,
  699. swapByte: rowData.swapByte,
  700. swapWord: rowData.swapWord,
  701. scaling: rowData.scaling,
  702. adjust: rowData.adjust,
  703. value: rowData.value
  704. }
  705. return submitRowData
  706. } else {
  707. return []
  708. }
  709. },
  710. // 批量删除
  711. async multDelete() {
  712. /* const delUrl = `/product/model/${this.currentPlanData.product}/${item.id}`
  713. delRecord(delUrl).then((response) => {
  714. console.log('delRecord rs=', response)
  715. // 后端成功执行后,前端再删除选中行
  716. // this.tableData.splice(index, 1)
  717. // this.tableData = this.tableData.filter(item => item.id !== row.id)
  718. const newData = this.tableData.filter(par => par.id !== item.id)
  719. this.tableData = [...newData]
  720. }).catch((err) => {
  721. console.log('delRecord err rs=', err)
  722. }) */
  723. // 后端执行完成后,开始前端操作
  724. // 遍历 `tableData` 数组
  725. for (let i = 0; i < this.tableData.length; i++) {
  726. const item = this.tableData[i]
  727. // 判断当前行数据是否被选中
  728. if (this.multipleSelection.includes(item)) {
  729. // 如果选中,则从 开始删除
  730. if (item.id > 0) {
  731. // 如果 id > 0 则表示 是已经保存在后端的数据了,需要向后端发送删除请求
  732. const delUrl = `/product/model/${this.currentPlanData.product}/${item.id}`
  733. await delRecord(delUrl).then((response) => {
  734. // 后端成功执行后,前端再删除选中行
  735. this.tableData.splice(i, 1)
  736. i-- // 因为 `splice` 方法会修改数组长度,所以需要将 `i` 减去 1,避免漏删下一个元素
  737. })
  738. } else {
  739. // 如果是新增未保存过的数据,直接删除
  740. this.tableData.splice(i, 1)
  741. i-- // 因为 `splice` 方法会修改数组长度,所以需要将 `i` 减去 1,避免漏删下一个元素
  742. }
  743. }
  744. }
  745. // this.showDel = false
  746. },
  747. // 多选按钮状态改变 handleSelectionChange
  748. handleSelectionChange(val) {
  749. // 选中行存入临时变量中
  750. this.multipleSelection = val
  751. // console.log('handleSelectionChange val', val)
  752. // 批量删除按钮激活
  753. this.showDel = true
  754. },
  755. editClick(row, index) {
  756. // 单测点查询接口 /product/model/:product/:tag
  757. // 获取测点详细信息
  758. if (row.id) {
  759. const getUrl = `/product/model/${this.currentPlanData.product}/${row.id}`
  760. // console.log('PlanCheckPoint editClick getUrl=', getUrl)
  761. httpGet(getUrl).then(res => {
  762. this.form = res
  763. // this.form.swapByte = Boolean(res.swapByte)
  764. // this.form.swapWord = Boolean(res.swapWord)
  765. // console.log('PlanCheckPoint editClick this.form=', this.form)
  766. })
  767. } else {
  768. this.form = this.tableData[index]
  769. }
  770. this.stepIndex = index
  771. this.dialogFormVisible = true
  772. },
  773. saveForm() {
  774. // 修改测点接口 /product/model/:product
  775. if (this.form.id) {
  776. let isNotPassMesage = ''
  777. let v = this.form.name || ''
  778. v = v.toString().replace(/ /gi, '')
  779. if (v === '') {
  780. isNotPassMesage = '必填项(测点名称)不能为空'
  781. }
  782. v = this.form.groupingName || ''
  783. v = v.toString().replace(/ /gi, '')
  784. if (v === '') {
  785. isNotPassMesage = '必填项(设备名称)不能为空'
  786. }
  787. v = this.form.range || ''
  788. v = v.toString().replace(/ /gi, '')
  789. if (v === '') {
  790. isNotPassMesage = '必填项(点号类型)不能为空'
  791. }
  792. v = this.form.offset || ''
  793. v = v.toString().replace(/ /gi, '')
  794. if (v === '') {
  795. isNotPassMesage = '必填项(点号)不能为空'
  796. }
  797. if (isNotPassMesage !== '') {
  798. this.$message({
  799. type: 'error',
  800. message: isNotPassMesage,
  801. offset: window.screen.height / 3
  802. })
  803. return
  804. }
  805. const putUrl = `/product/model/${this.currentPlanData.product}`
  806. putData(putUrl, this.form).then(res => {
  807. // 保存表单
  808. // console.log('saveForm putData 1 tableData=', this.tableData)
  809. if (res == null) {
  810. return
  811. }
  812. // res.point104 = this.calPoint104(res.range, res.offset)
  813. this.$set(this.tableData, this.stepIndex, res)
  814. this.dialogFormVisible = false
  815. })
  816. } else {
  817. this.$set(this.tableData, this.stepIndex, this.form)
  818. this.dialogFormVisible = false
  819. }
  820. }
  821. }
  822. }
  823. </script>
  824. <style lang="scss" scoped>
  825. .plan-check-point {
  826. // border: 1px #f00 solid;
  827. text-align: center;
  828. font-size: 16px;
  829. width: 100%;
  830. padding:0 20px;
  831. .title {
  832. font-size: 20px;
  833. font-weight: bold;
  834. padding: 10px 0 10px 0;
  835. }
  836. .buttons {
  837. display: flex;
  838. justify-content: space-between;
  839. text-align: left;
  840. padding-bottom: 20px;
  841. .left,.right {
  842. width: 50%;
  843. }
  844. .right{
  845. display: flex;
  846. justify-content: right;
  847. }
  848. .item {
  849. margin: 0 10px;
  850. }
  851. }
  852. .modelInput{
  853. text-align: left;
  854. }
  855. // 分页
  856. .page-bar {
  857. display: flex;
  858. justify-content: center;
  859. // padding: 20px;
  860. .el-pagination.is-background {
  861. .el-pager {
  862. .number {
  863. color: #00706b;
  864. border: 1px #00706b solid;
  865. background-color: #fff;
  866. }
  867. }
  868. }
  869. }
  870. // 底部步骤按钮
  871. .bottom-button{
  872. margin-top: 20px;
  873. }
  874. .table-container{
  875. height: 100%;
  876. }
  877. // ::v-deep .pagination-container{
  878. // margin-top: 0;
  879. // }
  880. ::v-deep {
  881. // 表格输入框
  882. .table-column-input {
  883. .el-input__inner {
  884. border: none;
  885. background: transparent;
  886. padding-left: 0;
  887. }
  888. .el-input__inner:focus {
  889. border: 1px #00706b solid;
  890. }
  891. }
  892. }
  893. }
  894. ::v-deep input::-webkit-outer-spin-button,
  895. ::v-deep input::-webkit-inner-spin-button {
  896. -webkit-appearance: none !important;
  897. }
  898. ::v-deep input[type='number'] {
  899. -moz-appearance: textfield !important;
  900. }
  901. </style>