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