提交 | 用户 | 时间
2f0aa4 1 <template>
442724 2   <Dialog v-model="dialogVisible" :title="dialogTitle" width="75%">
2f0aa4 3     <el-form
4       ref="formRef"
5       v-loading="formLoading"
6       :model="formData"
7       :rules="formRules"
8       label-width="120px"
9     >
22bece 10       <el-divider content-position="left">基本信息</el-divider>
2f0aa4 11       <el-row>
12         <el-col :span="12">
13           <el-form-item label="模型编号" prop="modelCode">
14             <el-input v-model="formData.modelCode" placeholder="请输入模型编号" />
15           </el-form-item>
16         </el-col>
17       </el-row>
18       <el-row>
19         <el-col :span="12">
20           <el-form-item label="模型类型" prop="modelType">
6badb7 21             <el-select v-model="formData.modelType" placeholder="请选择">
22               <el-option
8ea580 23                 v-for="dict in getStrDictOptions(DICT_TYPE.SCHE_MODEL_TYPE)"
6badb7 24                 :key="dict.value"
25                 :label="dict.label"
26                 :value="dict.value"
27               />
28             </el-select>
2f0aa4 29           </el-form-item>
30         </el-col>
31         <el-col :span="12">
32           <el-form-item label="调用方式" prop="invocation">
6badb7 33             <el-select v-model="formData.invocation" placeholder="请选择">
34               <el-option
8ea580 35                 v-for="dict in getStrDictOptions(DICT_TYPE.SCHE_MODEL_INVOCATION)"
6badb7 36                 :key="dict.value"
37                 :label="dict.label"
38                 :value="dict.value"
39               />
40             </el-select>
2f0aa4 41           </el-form-item>
42         </el-col>
43       </el-row>
22bece 44       <el-divider content-position="left">模型信息</el-divider>
D 45       <div style="width: 120px;text-align: right;margin-bottom: 8px">
e4de9b 46         <el-popover placement="right" :width="300" trigger="click" ref="modelPopover" @before-enter="model = undefined">
22bece 47           <template #reference>
D 48             <span style="color: #409eff;cursor: pointer">关联模型信息</span>
49           </template>
50           <template #default>
51             <div style="display:flex;flex-direction: row;align-items: center;">
52               <el-cascader style="width: 100%" v-model="model" placeholder="选择模型" :teleported="false" @change="changeModel" :options="scheduleModelList"/>
53             </div>
54           </template>
55         </el-popover>
56       </div>
2f0aa4 57       <el-row>
22bece 58         <el-col :span="12">
D 59           <el-form-item label="模型名称" prop="modelName">
091c7e 60             <el-input v-model="formData.modelName" placeholder="请输入模型名称"/>
22bece 61           </el-form-item>
D 62         </el-col>
63         <el-col :span="12">
2f0aa4 64           <el-form-item label="类名" prop="className">
22bece 65             <el-input v-model="formData.className" placeholder="请输入类名" :disabled="true" />
2f0aa4 66           </el-form-item>
67         </el-col>
68       </el-row>
69       <el-row>
70         <el-col :span="12">
71           <el-form-item label="方法名" prop="methodName">
22bece 72             <el-input v-model="formData.methodName" placeholder="请输入方法名" :disabled="true" />
2f0aa4 73           </el-form-item>
74         </el-col>
75         <el-col :span="12">
76           <el-form-item label="参数数量" prop="portLength">
22bece 77             <el-input-number v-model="formData.portLength" :min="0" controls-position="right" :disabled="true" />
2f0aa4 78           </el-form-item>
79         </el-col>
80       </el-row>
81       <el-row>
82         <el-col :span="24">
83           <el-form-item label="参数构造" prop="paramStructure">
22bece 84             <el-input v-model="formData.paramStructure" placeholder="请输入参数构造" :disabled="true" />
2f0aa4 85           </el-form-item>
86         </el-col>
87       </el-row>
88       <el-row>
89         <el-col :span="24">
90           <el-form-item label="模型路径" prop="modelPath">
22bece 91             <el-input v-model="formData.modelPath" placeholder="模型路径" :disabled="true" />
2f0aa4 92           </el-form-item>
93         </el-col>
94       </el-row>
95       <el-divider content-position="left">输入参数</el-divider>
96       <el-table
97         :data="formData.paramList"
98         border
99         style="width: 100%; margin-top: 5px;">
100         <el-table-column
101           prop=""
102           label="端口"
103           width="100"
104           align="center">
6badb7 105           <template #default="scope">
9215b4 106             <el-input v-model="scope.row.modelparamportorder" maxlength="5" clearable
6badb7 107                       style="width:100%; hight:100%"/>
2f0aa4 108           </template>
109         </el-table-column>
110         <el-table-column
111           prop=""
112           label="序号"
113           width="100"
114           align="center">
6badb7 115           <template #default="scope">
22bece 116             <el-input v-model="scope.row.modelparamorder" maxlength="5" clearable
6badb7 117                       style="width:100%;hight:100%"/>
2f0aa4 118           </template>
119         </el-table-column>
120         <el-table-column
121           prop=""
122           label="类型"
123           width="150"
124           align="center">
6badb7 125           <template #default="scope">
22bece 126             <el-select v-model="scope.row.modelparamtype" placeholder="请选择" @change="changeModelparamtype(scope.row)">
2f0aa4 127               <el-option
8ea580 128                 v-for="dict in getStrDictOptions(DICT_TYPE.MODEL_PARAM_TYPE)"
2f0aa4 129                 :key="dict.value"
130                 :label="dict.label"
131                 :value="dict.value"
132               />
133             </el-select>
134           </template>
135         </el-table-column>
8ea580 136         <el-table-column
2f0aa4 137           prop=""
138           label="参数名称"
139           align="center">
6badb7 140           <template #default="scope">
442724 141             <el-select-v2 v-if="scope.row.modelparamtype === 'NormalItem'"
22bece 142               v-model="scope.row.modelparamid"
442724 143               :options="modelparamListMap['NormalItem'] || []"
22bece 144               placeholder="请选择"
442724 145               :props="{value:'value',label:'label',options:'children'}"
D 146               clearable
22bece 147               filterable
442724 148               :fit-input-width="false"
D 149             />
150             <el-select-v2 v-else
2f0aa4 151               v-model="scope.row.modelparamid"
442724 152               :options="modelparamListMap[scope.row.modelparamtype] || []"
D 153               placeholder="请选择"
154               :props="{value:'id',label:'name'}"
155               clearable
2f0aa4 156               filterable
442724 157               :fit-input-width="false"
D 158             />
2f0aa4 159           </template>
8ea580 160         </el-table-column>
2f0aa4 161         <el-table-column
162           prop=""
163           label="参数长度"
d3ee81 164           width="160"
2f0aa4 165           align="center">
6badb7 166           <template #default="scope">
d3ee81 167             <el-input-number v-model="scope.row.datalength" :min="0" clearable controls-position="right"
168                              style="width:100%;hight:100%"/>
2f0aa4 169           </template>
170         </el-table-column>
171         <el-table-column
172           prop=""
173           label="操作"
174           width="100"
175           align="center">
6badb7 176           <template #default="scope">
2f0aa4 177             <el-button
6badb7 178               link
179               @click.prevent="addRow(scope.$index, formData.paramList)"
180               type="primary"
2f0aa4 181               size="small">
182               添加
183             </el-button>
184             <el-button
6badb7 185               link
22bece 186               @click.prevent="deleteRow(scope.$index, scope.row, formData.paramList)"
6badb7 187               type="primary"
2f0aa4 188               size="small">
189               删除
190             </el-button>
191           </template>
192         </el-table-column>
193       </el-table>
194
195       <el-divider content-position="left">设置参数</el-divider>
196       <el-table
6badb7 197         :data="formData.settingList"
2f0aa4 198         border
199         style="width: 100%; margin-top: 5px;">
200         <el-table-column
201           prop=""
202           label="键"
5e26f4 203           min-width="150"
2f0aa4 204           align="center">
6badb7 205           <template #default="scope">
22bece 206             <el-input v-model="scope.row.key" maxlength="20" clearable :disabled="true"
6badb7 207                       style="width:100%;hight:100%"/>
2f0aa4 208           </template>
209         </el-table-column>
210         <el-table-column
211           prop=""
212           label="名称"
5e26f4 213           min-width="150"
2f0aa4 214           align="center">
6badb7 215           <template #default="scope">
22bece 216             <el-input v-model="scope.row.name" maxlength="20" clearable :disabled="true"
6badb7 217                       style="width:100%;hight:100%"/>
2f0aa4 218           </template>
219         </el-table-column>
220         <el-table-column
221           prop=""
222           label="类型"
5e26f4 223           min-width="100"
2f0aa4 224           align="center">
6badb7 225           <template #default="scope">
22bece 226             <el-select v-model="scope.row.valuetype" placeholder="请选择" :disabled="true">
d3ee81 227               <el-option
228                 v-for="dict in getStrDictOptions(DICT_TYPE.MODEL_METHOD_SETTING_VALUE_TYPE)"
229                 :key="dict.value"
230                 :label="dict.label"
231                 :value="dict.value"
232               />
233             </el-select>
2f0aa4 234           </template>
235         </el-table-column>
236         <el-table-column
237           prop=""
238           label="值"
5e26f4 239           min-width="300"
2f0aa4 240           align="center">
6badb7 241           <template #default="scope">
5e26f4 242             <el-input v-model="scope.row.value" maxlength="256" clearable
243                       :disabled="scope.row.key === 'pyFile_BAK'"
6badb7 244                       style="width:100%;hight:100%"/>
2f0aa4 245           </template>
246         </el-table-column>
247       </el-table>
23c8b8 248       <el-divider content-position="left">模型下发配置</el-divider>
D 249       <el-row :gutter="20">
250         <el-col :span="4">
251           <el-button type="primary" size="small" @click="addRowOut()" >新增</el-button>
252         </el-col>
253       </el-row>
254       <el-table
255         :data="formData.modelOut"
256         border
257         style="width: 100%; margin-top: 5px;">
fa3d25 258         <el-table-column prop="resultKey" label="输出key" align="center" min-width="100">
23c8b8 259           <template #default="scope">
442724 260             <el-input size="small" v-model="scope.row.resultKey" style="width:100%;height:100%"/>
23c8b8 261           </template>
D 262         </el-table-column>
442724 263         <el-table-column prop="resultType" label="数据类型" align="center" width="150">
23c8b8 264           <template #default="scope">
fa3d25 265             <el-select v-model="scope.row.resultType" placeholder="请选择">
D 266               <el-option
267                 v-for="dict in getStrDictOptions(DICT_TYPE.RESULT_TYPE)"
268                 :key="dict.value"
269                 :label="dict.label"
270                 :value="dict.value"
271               />
272             </el-select>
23c8b8 273           </template>
D 274         </el-table-column>
442724 275         <el-table-column prop="resultPort" label="角标1" align="center" width="100">
23c8b8 276           <template #default="scope">
442724 277             <el-input-number :min="0" clearable controls-position="right" size="small" v-model="scope.row.resultPort" style="width:100%;height:100%"/>
23c8b8 278           </template>
D 279         </el-table-column>
442724 280         <el-table-column prop="resultIndex" label="角标2" align="center" width="100">
23c8b8 281           <template #default="scope">
442724 282             <el-input-number :min="0" clearable controls-position="right" size="small" v-model="scope.row.resultIndex" style="width:100%;height:100%"/>
23c8b8 283           </template>
D 284         </el-table-column>
442724 285         <el-table-column prop="isWrite" label="是否下发" align="center" width="100">
23c8b8 286           <template #default="scope">
D 287             <el-switch size="small" v-model="scope.row.isWrite" :active-value="1"
288                        :inactive-value="0"/>
289           </template>
290         </el-table-column>
291         <el-table-column
292           prop=""
293           label="测点名称"
294           align="center" min-width="200">
295           <template #default="scope">
442724 296             <el-select-v2
D 297               v-model="scope.row.pointNo"
298               :options="modelparamListMap['DATAPOINT'] || []"
299               placeholder="请选择"
300               :props="{value:'itemNo',label:'name'}"
301               clearable
302               filterable
303               :fit-input-width="false"
304             />
23c8b8 305           </template>
D 306         </el-table-column>
307         <el-table-column prop="disturbancePointNo’" label="无扰切换点位" align="center" min-width="200">
308           <template #default="scope">
442724 309             <el-select-v2
D 310               v-model="scope.row.disturbancePointNo"
311               :options="modelparamListMap['DATAPOINT'] || []"
312               placeholder="请选择"
313               :props="{value:'itemNo',label:'name'}"
314               clearable
315               filterable
316               :fit-input-width="false"
317             />
23c8b8 318           </template>
D 319         </el-table-column>
320         <el-table-column label="操作" fixed="right" header-align="center" align="center" width="100">
321           <template #default="scope">
322             <el-button
323               @click="deleteModelOutRow(scope.$index)"
324               key="danger"
325               type="danger"
326               link
327             >删除
328             </el-button>
329           </template>
330         </el-table-column>
331       </el-table>
2f0aa4 332     </el-form>
333     <template #footer>
334       <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
335       <el-button @click="dialogVisible = false">取 消</el-button>
336     </template>
337   </Dialog>
338 </template>
339 <script lang="ts" setup>
8ea580 340   import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
2f0aa4 341   import * as ScheduleModelApi from '@/api/model/sche/model'
342   import { CommonStatusEnum } from '@/utils/constants'
22bece 343   import * as MpkApi from "@/api/model/mpk/mpk";
23c8b8 344   import {generateUUID} from "@/utils";
9215b4 345   import { ElMessage,ElMessageBox } from 'element-plus'
D 346   import { Refresh } from '@element-plus/icons-vue'
2f0aa4 347
348   defineOptions({ name: 'ScheduleModelForm' })
349
350   const { t } = useI18n() // 国际化
351   const message = useMessage() // 消息弹窗
352   const dialogVisible = ref(false) // 弹窗的是否展示
353   const dialogTitle = ref('') // 弹窗的标题
354   const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
355   const formType = ref('') // 表单的类型:create - 新增;update - 修改
356   const formData = ref({
357     id: undefined,
358     modelCode: undefined,
359     modelName: undefined,
360     modelType: undefined,
361     className: undefined,
362     methodName: undefined,
363     portLength: undefined,
364     paramStructure: undefined,
365     modelPath: undefined,
366     resultStrId: undefined,
367     invocation: undefined,
8ea580 368     status: CommonStatusEnum.ENABLE,
9215b4 369     paramList: [{
D 370       modelparamportorder: 1 + '',
371       modelparamorder: '1',
372       modelparamtype: '',
373       modelparamid: '',
374       datalength: 0
375     }],
23c8b8 376     settingList: [],
D 377     modelOut: []
2f0aa4 378   })
379   const formRules = reactive({
380     modelCode: [{ required: true, message: '模型编号不能为空', trigger: 'blur' }],
381     modelName: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
382     modelType: [{ required: true, message: '模型类型不能为空', trigger: 'blur' }]
383   })
384   const formRef = ref() // 表单 Ref
6badb7 385   const modelparamListMap = ref({})
22bece 386   // 调度模型列表
D 387   const scheduleModelList = ref([])
388   const model = ref()
389   const modelPopover = ref()
2f0aa4 390
391   const addRow = function (index, rows) {
392     let row = JSON.parse(JSON.stringify(rows[index]))
393     rows.splice(index, 0, row)
394     this.orderRow(rows)
395   }
396
22bece 397   const deleteRow = function (index, row, rows) {
D 398     if (!rows || rows.length === 1 || rows.filter(e => e.modelparamportorder === row.modelparamportorder).length === 1) {
399       message.error('不可删除!')
2f0aa4 400       return
401     }
402     rows.splice(index, 1)
403     this.orderRow(rows)
404   }
405
406   const orderRow = function (rows) {
407     let modelparamorder = 0
408     let modelparamportorder = 0
409     rows.forEach(function (value) {
410       if (value.modelparamportorder !== modelparamportorder) {
411         modelparamportorder = value.modelparamportorder
412         modelparamorder = 1
413       }
414       value.modelparamorder = modelparamorder
415       modelparamorder++
416     })
417   }
418
419   /** 打开弹窗 */
420   const open = async (type: string, id?: number) => {
421     dialogVisible.value = true
422     dialogTitle.value = t('action.' + type)
423     formType.value = type
424     resetForm()
425     // 修改时,设置数据
426     if (id) {
427       formLoading.value = true
428       try {
429         formData.value = await ScheduleModelApi.getScheduleModel(id)
430       } finally {
431         formLoading.value = false
432       }
433     }
d3ee81 434     // 加载参数列表
442724 435     modelparamListMap.value = await ScheduleModelApi.getModelParamList(id)
22bece 436     // 加载调度模型列表
D 437     getScheduleModelList()
2f0aa4 438   }
439   defineExpose({ open }) // 提供 open 方法,用于打开弹窗
440
441   /** 提交表单 */
442   const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
443   const submitForm = async () => {
444     // 校验表单
445     if (!formRef) return
446     const valid = await formRef.value.validate()
447     if (!valid) return
82c481 448     //校验模型输入
D 449     formData.value.paramList.forEach(e => {
450       if (e.modelparamid == undefined || e.modelparamid == '') {
451         message.error("输入数据异常")
452         throw new Error('输入数据异常');
453       }
454       // ind_ascii类型输出的序号必须是1,且所在端口序号最大为1(一个ind_ascii类型输入独占一个端口)
455       if (e.modelparamtype === 'IND_ASCII') {
456         if (e.modelparamorder != 1 || formData.value.paramList.filter(p => p.modelparamportorder === e.modelparamportorder).length != 1) {
457           message.error("输入数据异常:IND_ASCII类型输入独占一个端口")
458           throw new Error('输入数据异常:IND_ASCII类型输入独占一个端口');
459         }
460       }
461     })
462
2f0aa4 463     // 提交请求
464     formLoading.value = true
465     try {
466       const data = formData.value as unknown as ScheduleModelApi.ScheduleModelVO
467       if (formType.value === 'create') {
468         await ScheduleModelApi.createScheduleModel(data)
469         message.success(t('common.createSuccess'))
470       } else {
471         await ScheduleModelApi.updateScheduleModel(data)
472         message.success(t('common.updateSuccess'))
473       }
474       dialogVisible.value = false
475       // 发送操作成功的事件
476       emit('success')
477     } finally {
478       formLoading.value = false
479     }
480   }
481
482   /** 重置表单 */
483   const resetForm = () => {
484     formData.value = {
485       id: undefined,
486       modelCode: undefined,
487       modelName: undefined,
488       modelType: undefined,
489       className: undefined,
490       methodName: undefined,
491       portLength: undefined,
492       paramStructure: undefined,
493       modelPath: undefined,
494       resultStrId: undefined,
495       invocation: undefined,
6badb7 496       status: CommonStatusEnum.ENABLE,
9215b4 497       paramList: [{
D 498         modelparamportorder: 1 + '',
499         modelparamorder: '1',
500         modelparamtype: '',
501         modelparamid: '',
502         datalength: 0
503       }],
23c8b8 504       settingList: [],
D 505       modelOut: []
2f0aa4 506     }
507     formRef.value?.resetFields()
508   }
22bece 509
D 510   const getScheduleModelList = async () => {
511     let list = await MpkApi.list({pyType: 'schedul'})
512     if (list && list.length > 0) {
513       scheduleModelList.value = list.map(e => {
514         return {
515           label: e.pyChineseName,
516           value: e,
517           children: e.modelMethods.map(m => {
518             return {
519               label: m.methodName,
520               value: m
521             }
522           })
523         }
524       })
525     }
526   }
527
528   // 选择调度模型
529   const changeModel = async () => {
530     // 校验
531     if (model.value && model.value.length > 0) {
9215b4 532       ElMessageBox.confirm(
D 533         '是否更新输入参数?',
534         '提示',
535         {confirmButtonText: '是', cancelButtonText: '否', type: 'success',icon: markRaw(Refresh),closeOnClickModal:false,closeOnPressEscape:false}
536       ).then(() => {
537         relevanceModel(true)
538       }).catch(() => {
539         relevanceModel(false)
540       })
541     }else {
542       message.error("请先选择模型")
543     }
544   }
545
546   function relevanceModel(refreshParam) {
547     const modelInfo = model.value[0]
548     const methodInfo = model.value[1]
549     formData.value.modelName = modelInfo.pyChineseName
550     formData.value.className = modelInfo.pkgName + '.impl.' + modelInfo.pyName + 'Impl';
551     formData.value.methodName = methodInfo.methodName
552     formData.value.portLength = methodInfo.dataLength
553     // 参数构造
554     let paramStructure = []
555     for (let i = 0; i < methodInfo.dataLength; i++) {
556       paramStructure.push('[[D')
557     }
558     if (methodInfo.model === 1) {
22bece 559       paramStructure.push('java.util.HashMap')
9215b4 560     }
D 561     paramStructure.push('java.util.HashMap')
562     formData.value.paramStructure = paramStructure.join(',')
563     formData.value.modelPath = modelInfo.pyModule
564     if (refreshParam) {
22bece 565       // 输入参数
D 566       let paramList = []
567       for (let i = 0; i < methodInfo.dataLength; i++) {
568         paramList.push({
569           modelparamportorder: i+1 + '',
570           modelparamorder: '1',
571           modelparamtype: '',
572           modelparamid: '',
573           datalength: 0
574         })
575       }
576       formData.value.paramList = paramList
577     }
9215b4 578     // 设置参数
D 579     let settingList = []
580     methodInfo.methodSettings.forEach(e => {
581       settingList.push({
582         key: e.settingKey,
583         value: e.value,
584         valuetype: e.valueType,
585         name: e.name
586       })
587     })
588     formData.value.settingList = settingList
589     modelPopover.value.hide()
22bece 590   }
D 591
592   function changeModelparamtype(row) {
593     row.modelparamid = ''
594   }
23c8b8 595   const addRowOut= function () {
D 596     if(formData.value.modelOut===undefined) {
597       formData.value.modelOut = []
598     }
599     formData.value.modelOut.push({
600       id: generateUUID(),
601       resultKey: undefined,
602       resultType: "double[][]",
603       port: 0,
604       index: 0,
605       isWrite: 1,
606       pointNo:undefined,
607       sort:undefined,
608       disturbancePointNo:undefined,
609     })
610   }
611   const deleteModelOutRow = function (index) {
612     formData.value.modelOut.splice(index, 1)
613   }
2f0aa4 614 </script>