潘志宝
2024-10-31 13c97d76348b5451381320aa54efa0706f38ecb6
提交 | 用户 | 时间
1c14d6 1 <template>
c4b4d2 2   <Dialog v-model="dialogVisible" :title="dialogTitle" width="60%">
1c14d6 3     <el-form
L 4       ref="formRef"
5       v-loading="formLoading"
6       :model="formData"
7       :rules="formRules"
8       label-width="120px"
9     >
10       <el-row>
11         <el-col :span="12">
12           <el-form-item label="测点编码" prop="pointNo">
e9d8f9 13             <el-input v-model="formData.pointNo" disabled/>
1c14d6 14           </el-form-item>
L 15         </el-col>
16         <el-col :span="12">
17           <el-form-item label="测点名称" prop="pointName">
660c92 18             <el-input v-model="formData.pointName" placeholder="请输入测点名称"/>
1c14d6 19           </el-form-item>
L 20         </el-col>
660c92 21       </el-row>
L 22       <el-row>
1c14d6 23         <el-col :span="12">
L 24           <el-form-item label="测点类型" prop="pointType">
660c92 25             <el-select
L 26               v-model="formData.pointType"
27               clearable
28               placeholder="请选择测点类型"
29             >
30               <el-option
e9d8f9 31                 v-for="dict in getDictOptions(DICT_TYPE.DATA_POINT_TYPE)"
660c92 32                 :key="dict.value"
L 33                 :label="dict.label"
34                 :value="dict.value"
35               />
36             </el-select>
1c14d6 37           </el-form-item>
L 38         </el-col>
39         <el-col :span="12">
40           <el-form-item label="数据类型" prop="dataType">
660c92 41             <el-select
L 42               v-model="formData.dataType"
43               clearable
44               placeholder="请选择数据类型"
45             >
46               <el-option
e9d8f9 47                 v-for="dict in getDictOptions(DICT_TYPE.POINT_DATA_TYPE)"
660c92 48                 :key="dict.value"
L 49                 :label="dict.label"
50                 :value="dict.value"
51               />
52             </el-select>
1c14d6 53           </el-form-item>
L 54         </el-col>
55       </el-row>
56       <el-row>
57         <el-col :span="12">
58           <el-form-item label="测量单位" prop="unit">
660c92 59             <el-input v-model="formData.unit" placeholder="请输入测量单位"/>
1c14d6 60           </el-form-item>
L 61         </el-col>
62         <el-col :span="12">
63           <el-form-item label="单位转换" prop="unittransfactor">
15a226 64             <el-input-number v-model="formData.unittransfactor" style="width: 100%" :controls="false"/>
1c14d6 65           </el-form-item>
L 66         </el-col>
67       </el-row>
68       <el-row>
69         <el-col :span="12">
70           <el-form-item label="采集频率" prop="minfreqid">
660c92 71             <el-select
L 72               v-model="formData.minfreqid"
73               clearable
74               placeholder="请选择采集频率"
75             >
76               <el-option
77                 v-for="dict in getDictOptions(DICT_TYPE.MINFREQID)"
78                 :key="dict.value"
79                 :label="dict.label"
80                 :value="dict.value"
81               />
82             </el-select>
1c14d6 83           </el-form-item>
L 84         </el-col>
85         <el-col :span="12">
660c92 86           <el-form-item label="默认值" prop="defaultValue">
L 87             <el-input-number v-model="formData.defaultValue" style="width: 100%" :controls="false"/>
88           </el-form-item>
89         </el-col>
90       </el-row>
91       <el-row>
92         <el-col :span="12">
93           <el-form-item label="最大值" prop="maxValue">
94             <el-input-number v-model="formData.maxValue" style="width: 100%" :controls="false"/>
95           </el-form-item>
96         </el-col>
97         <el-col :span="12">
98           <el-form-item label="最小值" prop="minValue">
99             <el-input-number v-model="formData.minValue" style="width: 100%" :controls="false"/>
1c14d6 100           </el-form-item>
L 101         </el-col>
102       </el-row>
103       <el-row>
104         <el-col :span="12">
105           <el-form-item label="是否启用" prop="isEnable">
660c92 106             <el-select
L 107               v-model="formData.isEnable"
108               clearable
109               placeholder="请选择是否启用"
110             >
111               <el-option
e9d8f9 112                 v-for="dict in getIntDictOptions(DICT_TYPE.COM_IS_INT)"
660c92 113                 :key="dict.value"
L 114                 :label="dict.label"
115                 :value="dict.value"
116               />
117             </el-select>
118           </el-form-item>
119         </el-col>
120         <el-col :span="12">
121           <el-form-item label="备注" prop="remark">
122             <el-input v-model="formData.remark" placeholder="请输入备注"/>
123           </el-form-item>
124         </el-col>
125       </el-row>
126       <!--计量点-->
127       <el-row v-if="formData.pointType === 'MEASURE'">
e9d8f9 128         <el-col :span="24">
660c92 129           <el-form-item prop="sourceOption" label="数据源">
L 130             <el-cascader
131               style="width: 100%;"
132               v-model="formData.sourceOption"
133               :options="sourceOptions"
134               filterable/>
135           </el-form-item>
136         </el-col>
137       </el-row>
c4da14 138       <el-row v-if="formData.pointType === 'MEASURE'">
L 139         <el-col :span="12">
c4b4d2 140           <el-form-item label="测量值类型" prop="measurePoint.valueType">
c4da14 141             <el-select
L 142               v-model="formData.measurePoint.valueType"
143               clearable
144               placeholder="请选择值类型"
145             >
146               <el-option
c4b4d2 147                 v-for="dict in getDictOptions(DICT_TYPE.MEASURE_VALUE_TYPE)"
c4da14 148                 :key="dict.value"
L 149                 :label="dict.label"
150                 :value="dict.value"
151               />
152             </el-select>
153           </el-form-item>
154         </el-col>
155         <el-col :span="12">
c4b4d2 156           <el-form-item label="平滑尺度(min)" prop="measurePoint.dimension">
157             <el-input-number v-model="formData.measurePoint.dimension" style="width: 100%"
158                              :min="0" :max="100"
159                              :controls="false"/>
c4da14 160           </el-form-item>
L 161         </el-col>
162       </el-row>
660c92 163       <!--计算点-->
L 164       <el-row :gutter="20" v-if="formData.pointType === 'CALCULATE'">
165         <el-col :span="24">
166           <el-form-item label="表达式">
167             <el-table
168               :data="expressionList"
169               border
170               style="width: 100%">
c4b4d2 171               <el-table-column
660c92 172                 type="index"
L 173                 align="center"
c4b4d2 174                 width="60"
175                 label="序号"/>
660c92 176               <el-table-column
L 177                 prop=""
178                 label="左括号"
179                 width="140"
180                 align="center">
181                 <template #default="scope">
182                   <el-input
183                     v-model="scope.row.parenthesesLeft"
184                     placeholder=""
185                     readonly
186                     maxlength="16">
187                     <template #prepend>
188                       <el-button @click="addParenthesesLeft(scope.$index, scope.row)">+</el-button>
189                     </template>
190                     <template #append>
191                       <el-button @click="removeParenthesesLeft(scope.$index, scope.row)">-</el-button>
192                     </template>
193                   </el-input>
194                 </template>
195               </el-table-column>
196               <el-table-column
197                 prop=""
198                 label="测点"
c4b4d2 199                 min-width="160"
660c92 200                 align="center">
L 201                 <template #default="scope">
202                   <el-select
203                     v-model="scope.row.point"
204                     filterable
205                     placeholder="请选择">
206                     <el-option
207                       v-for="(item, index) in pointList"
208                       :key="index"
209                       :label="item.pointName"
210                       :value="item.pointNo"/>
211                   </el-select>
212                 </template>
213               </el-table-column>
214               <el-table-column
215                 prop=""
216                 label="运算值"
c4b4d2 217                 min-width="120"
660c92 218                 align="center">
L 219                 <template #default="scope">
220                   <el-input
221                     v-model="scope.row.point"
222                     placeholder="运算值"
223                     maxlength="16"
224                     clearable/>
225                 </template>
226               </el-table-column>
227               <el-table-column
228                 prop=""
229                 label="右括号"
230                 width="140"
231                 align="center">
232                 <template #default="scope">
233                   <el-input
234                     v-model="scope.row.parenthesesRight"
235                     placeholder=""
236                     readonly
237                     maxlength="16">
238                     <template #prepend>
239                       <el-button @click="addParenthesesRight(scope.$index, scope.row)">+</el-button>
240                     </template>
241                     <template #append>
242                       <el-button @click="removeParenthesesRight(scope.$index, scope.row)">-</el-button>
243                     </template>
244                   </el-input>
245                 </template>
246               </el-table-column>
247               <el-table-column
248                 prop=""
249                 label="运算符"
c4b4d2 250                 width="100"
660c92 251                 align="center">
L 252                 <template #default="scope">
253                   <el-select v-model="scope.row.operator" clearable>
254                     <el-option
255                       v-for="item in operatorList"
256                       :key="item"
257                       :label="item"
258                       :value="item"/>
259                   </el-select>
260                 </template>
261               </el-table-column>
262               <el-table-column
263                 prop=""
264                 label="操作"
c4b4d2 265                 width="120"
660c92 266                 align="center">
L 267                 <template #default="scope">
268                   <el-button
269                     @click="addExpressionRow(scope.$index, expressionList)"
270                     type="text"
c4b4d2 271                     size="mini">
660c92 272                     添加
L 273                   </el-button>
274                   <el-button
275                     @click="deleteExpressionRow(scope.$index, expressionList)"
276                     type="text"
c4b4d2 277                     size="mini">
660c92 278                     删除
L 279                   </el-button>
280                 </template>
281               </el-table-column>
282             </el-table>
1c14d6 283           </el-form-item>
L 284         </el-col>
285       </el-row>
286     </el-form>
287     <template #footer>
288       <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
289       <el-button @click="dialogVisible = false">取 消</el-button>
290     </template>
291   </Dialog>
292 </template>
293 <script lang="ts" setup>
294 import * as DaPoint from '@/api/data/da/point'
660c92 295 import * as TagApi from '@/api/data/channel/tag'
L 296 import {DICT_TYPE, getDictOptions, getIntDictOptions} from "@/utils/dict";
1c14d6 297
660c92 298 defineOptions({name: 'DataDaPointForm'})
1c14d6 299
660c92 300 const {t} = useI18n() // 国际化
L 301 const message = useMessage() // 消息弹窗
302 const dialogVisible = ref(false) // 弹窗的是否展示
303 const dialogTitle = ref('') // 弹窗的标题
304 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
305 const formType = ref('') // 表单的类型:create - 新增;update - 修改
306 const sourceOptions = ref([])
307 const expressionList = ref([])
308 const pointList = ref([{
309   pointName: '',
310   pointNo: ''
311 }])
312 const queryParams = reactive({
13c97d 313   pointTypes: "MEASURE,CONSTANT",
660c92 314 })
L 315 const operatorList = ref(['+', '-', '*', '/', '&', '|', '!', '>', '<'])
316 const formData = ref({
317   id: undefined,
318   pointNo: undefined,
319   pointName: undefined,
320   pointType: undefined,
321   dataType: undefined,
322   valueType: undefined,
323   storeType: undefined,
324   unit: undefined,
325   unittransfactor: undefined,
326   defaultValue: undefined,
327   maxValue: undefined,
328   minValue: undefined,
329   minfreqid: undefined,
330   remark: undefined,
331   isEnable: undefined,
332   sourceOption: [],
333   mathPoint: {
334     id: '',
335     pointId: '',
336     expression: ''
337   },
338   measurePoint: {
339     id: '',
340     pointId: '',
341     sourceType: '',
342     sourceId: '',
343     tagNo: '',
344     dimension: '',
15a226 345     valueType: '',
660c92 346   }
L 347 })
348 const formRules = reactive({
349   pointName: [{required: true, message: '测点名称不能为空', trigger: 'blur'}],
350   pointType: [{required: true, message: '测点类型不能为空', trigger: 'blur'}],
351   dataType: [{required: true, message: '数据类型不能为空', trigger: 'blur'}],
c4b4d2 352   minfreqid: [{required: true, message: '采集频率不能为空', trigger: 'blur'}],
353   "measurePoint.valueType": [{required: true, message: '采集频率不能为空', trigger: 'blur'}],
354   "measurePoint.dimension": [{required: true, message: '采集频率不能为空', trigger: 'blur'}],
660c92 355 })
L 356 const formRef = ref() // 表单 Ref
357
358 /** 打开弹窗 */
359 const open = async (type: string, id?: number) => {
360   dialogVisible.value = true
361   dialogTitle.value = t('action.' + type)
362   formType.value = type
363   resetForm()
364   getSourceOption()
365   getPointList()
366   // 修改时,设置数据
367   if (id) {
368     formLoading.value = true
369     try {
370       getInfo(id)
371     } finally {
372       formLoading.value = false
373     }
374   }
375 }
376 defineExpose({open}) // 提供 open 方法,用于打开弹窗
377
378 /** 提交表单 */
379 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
380 const submitForm = async () => {
381   // 校验表单
382   if (!formRef) return
383   const valid = await formRef.value.validate()
384   if (!valid) return
385   // 提交请求
386   formLoading.value = true
387   try {
388     if (formData.value.pointType === 'CALCULATE' &&
389       expressionList.value && expressionList.value.length > 0) {
390       let parenthesesLeftRex = /^[(]*$/
391       let parenthesesRightRex = /^[)]*$/
392       let expression = ''
393       debugger
394       for (let i = 0; i < expressionList.value.length; i++) {
395         let value = expressionList.value[i]
396         if (!parenthesesLeftRex.test(value.parenthesesLeft)) {
397           message.error('第${i + 1}行左括号输入不正确!')
398           return
399         }
400         if (!parenthesesRightRex.test(value.parenthesesRight)) {
401           message.error('第${i + 1}行右括号输入不正确!')
402           return
403         }
404         if (i !== (expressionList.value.length - 1) && !value.operator) {
405           message.error('第${i + 1}行运算符不能为空!')
406           return
407         }
408         expression = expression + value.parenthesesLeft + value.point + value.parenthesesRight + (i === (expressionList.value.length - 1) ? '' : value.operator)
409       }
410       formData.value['mathPoint']['expression'] = expression
411     } else {
412       formData.value['mathPoint'] = {}
413     }
414     const data = formData.value as unknown as DaPoint.DaPointVO
415     if (formType.value === 'create') {
416       await DaPoint.createDaPoint(data)
417       message.success(t('common.createSuccess'))
418     } else {
419       await DaPoint.updateDaPoint(data)
420       message.success(t('common.updateSuccess'))
421     }
422     dialogVisible.value = false
423     // 发送操作成功的事件
424     emit('success')
425   } finally {
426     formLoading.value = false
427   }
428 }
429
430 /** 重置表单 */
431 const resetForm = () => {
432   expressionList.value = [{
433     parenthesesLeft: '',
434     point: '',
435     parenthesesRight: '',
436     operator: ''
437   }]
438   formData.value = {
1c14d6 439     id: undefined,
L 440     pointNo: undefined,
441     pointName: undefined,
442     pointType: undefined,
443     dataType: undefined,
444     valueType: undefined,
445     storeType: undefined,
446     unit: undefined,
660c92 447     unittransfactor: 1,
c4b4d2 448     defaultValue: 0,
449     maxValue: 100000000,
660c92 450     minValue: 0,
1c14d6 451     minfreqid: undefined,
L 452     remark: undefined,
660c92 453     isEnable: 1,
L 454     sourceOption: [],
dead8d 455     mathPoint: {
L 456       id: '',
457       pointId: '',
458       expression: ''
459     },
460     measurePoint: {
461       id: '',
462       pointId: '',
463       sourceType: '',
464       sourceId: '',
465       tagNo: '',
466       dimension: '1',
467       valueType: 'SIMULATE',
468     }
1c14d6 469   }
660c92 470   formRef.value?.resetFields()
L 471 }
1c14d6 472
660c92 473 function deleteExpressionRow(index, rows) {
L 474   if (!rows || rows.length === 1) {
475     message.error('不能全部删除!')
476     return
477   }
478   rows.splice(index, 1)
479 }
480
481 function addExpressionRow(index, rows) {
482   let row = JSON.parse(JSON.stringify(rows[index]))
483   rows.splice(index, 0, row)
484 }
485
486 function addParenthesesLeft(index, row) {
487   if (row.parenthesesLeft) {
488     row.parenthesesLeft = row.parenthesesLeft + '('
489   } else {
490     row.parenthesesLeft = '('
491   }
492 }
493
494 function removeParenthesesLeft(index, row) {
495   if (row.parenthesesLeft) {
496     row.parenthesesLeft = row.parenthesesLeft.substring(0, row.parenthesesLeft.length - 1)
497   } else {
498     row.parenthesesLeft = ''
499   }
500 }
501
502 function addParenthesesRight(index, row) {
503   if (row.parenthesesRight) {
504     row.parenthesesRight = row.parenthesesRight + ')'
505   } else {
506     row.parenthesesRight = ')'
507   }
508 }
509
510 function removeParenthesesRight(index, row) {
511   if (row.parenthesesRight) {
512     row.parenthesesRight = row.parenthesesRight.substring(0, row.parenthesesRight.length - 1)
513   } else {
514     row.parenthesesRight = ''
515   }
516 }
517
518 function numAscSort(a, b) {
519   return a - b
520 }
521
522 // 获取数据源选项
523 const getSourceOption = async () => {
524   sourceOptions.value = await TagApi.getTagTree()
525 }
526
527 const getPointList = async () => {
528   pointList.value = await DaPoint.getPointList(queryParams)
529 }
530
531 const getInfo = async (id) => {
532   formData.value = await DaPoint.getDaPoint(id)
533   expressionList.value = []
534   if (formData.value.pointType &&
535     formData.value.pointType === 'CALCULATE' &&
536     formData.value.mathPoint.expression) {
537     let expression = formData.value.mathPoint.expression
538     do {
539       let indexArray = [
540         expression.indexOf('+'),
541         expression.indexOf('-'),
542         expression.indexOf('*'),
543         expression.indexOf('/'),
544         expression.indexOf('&'),
545         expression.indexOf('|'),
546         expression.indexOf('!'),
547         expression.indexOf('>'),
548         expression.indexOf('<')
549       ].sort(numAscSort)
550       if (indexArray[indexArray.length - 1] !== -1) {
551         let endIndex = 0
552         for (let key in indexArray) {
553           if (indexArray[key] > -1) {
554             endIndex = indexArray[key]
555             break
556           }
557         }
558
559         // 运算值
560         let pointStr = expression.substring(0, endIndex)
561         debugger
562         // 运算符
563         let operator = expression.substr(endIndex, 1)
564         let indexOfParenthesesLeft = pointStr.indexOf('(')
565         let lastIndexOfParenthesesLeft = pointStr.lastIndexOf('(')
566
567         // 左括号
568         let parenthesesLeft = ''
569         if (indexOfParenthesesLeft !== -1 && lastIndexOfParenthesesLeft !== -1) {
570           parenthesesLeft = pointStr.substring(indexOfParenthesesLeft, lastIndexOfParenthesesLeft + 1)
571           pointStr = pointStr.substring(lastIndexOfParenthesesLeft + 1)
572         }
573
574         let indexOfParenthesesRight = pointStr.indexOf(')')
575         let lastIndexOfParenthesesRight = pointStr.lastIndexOf(')')
576
577         // 右括号
578         let parenthesesRight = ''
579         if (indexOfParenthesesRight !== -1 && lastIndexOfParenthesesRight !== -1) {
580           parenthesesRight = pointStr.substring(indexOfParenthesesRight, lastIndexOfParenthesesRight + 1)
581           pointStr = pointStr.substring(0, indexOfParenthesesRight)
582         }
583         expressionList.value.push({
584           parenthesesLeft: parenthesesLeft,
585           point: pointStr,
586           parenthesesRight: parenthesesRight,
587           operator: operator
588         })
589         expression = expression.substring(endIndex + 1)
1c14d6 590       } else {
660c92 591         let pointStr = expression
L 592         let indexOfParenthesesLeft = pointStr.indexOf('(')
593         let lastIndexOfParenthesesLeft = pointStr.lastIndexOf('(')
594         let parenthesesLeft = ''
595         if (indexOfParenthesesLeft !== -1 && lastIndexOfParenthesesLeft !== -1) {
596           parenthesesLeft = pointStr.substring(indexOfParenthesesLeft, lastIndexOfParenthesesLeft + 1)
597           pointStr = pointStr.substring(lastIndexOfParenthesesLeft + 1)
598         }
599         let indexOfParenthesesRight = pointStr.indexOf(')')
600         let lastIndexOfParenthesesRight = pointStr.lastIndexOf(')')
601         let parenthesesRight = ''
602         if (indexOfParenthesesRight !== -1 && lastIndexOfParenthesesRight !== -1) {
603           parenthesesRight = pointStr.substring(indexOfParenthesesRight, lastIndexOfParenthesesRight + 1)
604           pointStr = pointStr.substring(0, indexOfParenthesesRight)
605         }
606         expressionList.value.push({
607           parenthesesLeft: parenthesesLeft,
608           point: pointStr,
609           parenthesesRight: parenthesesRight,
610           operator: ''
611         })
612         expression = ''
1c14d6 613       }
660c92 614     } while (expression && expression.length > 0)
1c14d6 615   }
660c92 616 }
1c14d6 617
L 618 </script>
660c92 619 <style>
L 620 .el-select {
621   width: 100%
622 }
623 </style>