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