From f84c0f2de793be5dac3bda0e952afe14c625f596 Mon Sep 17 00:00:00 2001 From: dongyukun <1208714201@qq.com> Date: 星期四, 26 六月 2025 16:35:28 +0800 Subject: [PATCH] ai模型绑定 --- src/views/model/sche/model/ScheduleModelForm.vue | 364 +++++++++++++++++++++++++++++++++++---------------- 1 files changed, 249 insertions(+), 115 deletions(-) diff --git a/src/views/model/sche/model/ScheduleModelForm.vue b/src/views/model/sche/model/ScheduleModelForm.vue index 42d96b3..dd68526 100644 --- a/src/views/model/sche/model/ScheduleModelForm.vue +++ b/src/views/model/sche/model/ScheduleModelForm.vue @@ -1,5 +1,5 @@ <template> - <Dialog v-model="dialogVisible" :title="dialogTitle" width="60%"> + <Dialog v-model="dialogVisible" :title="dialogTitle" width="75%"> <el-form ref="formRef" v-loading="formLoading" @@ -11,7 +11,7 @@ <el-row> <el-col :span="12"> <el-form-item label="模型编号" prop="modelCode"> - <el-input v-model="formData.modelCode" placeholder="请输入模型编号" /> + <el-input v-model="formData.modelCode" placeholder="请输入模型编号"/> </el-form-item> </el-col> </el-row> @@ -43,13 +43,17 @@ </el-row> <el-divider content-position="left">模型信息</el-divider> <div style="width: 120px;text-align: right;margin-bottom: 8px"> - <el-popover placement="right" :width="300" trigger="click" ref="modelPopover" @before-enter="model = undefined"> + <el-popover placement="right" :width="300" trigger="click" ref="modelPopover" + @before-enter="model = undefined"> <template #reference> <span style="color: #409eff;cursor: pointer">关联模型信息</span> </template> <template #default> <div style="display:flex;flex-direction: row;align-items: center;"> - <el-cascader style="width: 100%" v-model="model" placeholder="选择模型" :teleported="false" @change="changeModel" :options="scheduleModelList"/> + <el-cascader style="width: 100%" v-model="model" placeholder="选择模型" + :teleported="false" @change="changeModel" :options="scheduleModelList" v-if="formData.invocation != '4'"/> + <el-cascader style="width: 100%" v-model="model" placeholder="选择模型" + :teleported="false" @change="changeAiModel" :options="aiModelList" v-if="formData.invocation === '4'"/> </div> </template> </el-popover> @@ -62,33 +66,34 @@ </el-col> <el-col :span="12"> <el-form-item label="类名" prop="className"> - <el-input v-model="formData.className" placeholder="请输入类名" :disabled="true" /> + <el-input v-model="formData.className" placeholder="请输入类名" :disabled="true"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="方法名" prop="methodName"> - <el-input v-model="formData.methodName" placeholder="请输入方法名" :disabled="true" /> + <el-input v-model="formData.methodName" placeholder="请输入方法名" :disabled="true"/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="参数数量" prop="portLength"> - <el-input-number v-model="formData.portLength" :min="0" controls-position="right" :disabled="true" /> + <el-input-number v-model="formData.portLength" :min="0" controls-position="right" + :disabled="true"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="参数构造" prop="paramStructure"> - <el-input v-model="formData.paramStructure" placeholder="请输入参数构造" :disabled="true" /> + <el-input v-model="formData.paramStructure" placeholder="请输入参数构造" :disabled="true"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="模型路径" prop="modelPath"> - <el-input v-model="formData.modelPath" placeholder="模型路径" :disabled="true" /> + <el-input v-model="formData.modelPath" placeholder="模型路径" :disabled="true"/> </el-form-item> </el-col> </el-row> @@ -103,7 +108,7 @@ width="100" align="center"> <template #default="scope"> - <el-input v-model="scope.row.modelparamportorder" maxlength="5" clearable :disabled="true" + <el-input v-model="scope.row.modelparamportorder" maxlength="5" clearable style="width:100%; hight:100%"/> </template> </el-table-column> @@ -123,7 +128,8 @@ width="150" align="center"> <template #default="scope"> - <el-select v-model="scope.row.modelparamtype" placeholder="请选择" @change="changeModelparamtype(scope.row)"> + <el-select v-model="scope.row.modelparamtype" placeholder="请选择" + @change="changeModelparamtype(scope.row)"> <el-option v-for="dict in getStrDictOptions(DICT_TYPE.MODEL_PARAM_TYPE)" :key="dict.value" @@ -138,34 +144,24 @@ label="参数名称" align="center"> <template #default="scope"> - <el-select v-if="scope.row.modelparamtype === 'NormalItem'" - v-model="scope.row.modelparamid" - placeholder="请选择" - filterable - style="width: 100%"> - <el-option-group - v-for="group in modelparamListMap['NormalItem']" - :key="group.value" - :label="group.label" - > - <el-option - v-for="item in group.children" - :key="item.value" - :label="item.label" - :value="item.value" - /> - </el-option-group> - </el-select> - <el-select v-else - v-model="scope.row.modelparamid" - filterable - placeholder="请选择"> - <el-option - v-for="(item, index) in modelparamListMap[scope.row.modelparamtype]" - :key="index" - :label="item.name" - :value="item.id"/> - </el-select> + <el-select-v2 v-if="scope.row.modelparamtype === 'NormalItem'" + v-model="scope.row.modelparamid" + :options="modelparamListMap['NormalItem'] || []" + placeholder="请选择" + :props="{value:'value',label:'label',options:'children'}" + clearable + filterable + :fit-input-width="false" + /> + <el-select-v2 v-else + v-model="scope.row.modelparamid" + :options="modelparamListMap[scope.row.modelparamtype] || []" + placeholder="请选择" + :props="{value:'id',label:'name'}" + clearable + filterable + :fit-input-width="false" + /> </template> </el-table-column> <el-table-column @@ -174,7 +170,8 @@ width="160" align="center"> <template #default="scope"> - <el-input-number v-model="scope.row.datalength" :min="0" clearable controls-position="right" + <el-input-number v-model="scope.row.datalength" :min="0" clearable + controls-position="right" style="width:100%;hight:100%"/> </template> </el-table-column> @@ -258,7 +255,7 @@ <el-divider content-position="left">模型下发配置</el-divider> <el-row :gutter="20"> <el-col :span="4"> - <el-button type="primary" size="small" @click="addRowOut()" >新增</el-button> + <el-button type="primary" size="small" @click="addRowOut()">新增</el-button> </el-col> </el-row> <el-table @@ -267,10 +264,10 @@ style="width: 100%; margin-top: 5px;"> <el-table-column prop="resultKey" label="输出key" align="center" min-width="100"> <template #default="scope"> - <el-input size="mini" v-model="scope.row.resultKey" style="width:100%;height:100%"/> + <el-input size="small" v-model="scope.row.resultKey" style="width:100%;height:100%"/> </template> </el-table-column> - <el-table-column prop="resultType" label="数据类型" align="center" min-width="150"> + <el-table-column prop="resultType" label="数据类型" align="center" width="150"> <template #default="scope"> <el-select v-model="scope.row.resultType" placeholder="请选择"> <el-option @@ -282,17 +279,19 @@ </el-select> </template> </el-table-column> - <el-table-column prop="resultPort" label="角标1" align="center" min-width="100"> + <el-table-column prop="resultPort" label="角标1" align="center" width="100"> <template #default="scope"> - <el-input-number :min="0" clearable controls-position="right" size="mini" v-model="scope.row.resultPort" style="width:100%;height:100%"/> + <el-input-number :min="0" clearable controls-position="right" size="small" + v-model="scope.row.resultPort" style="width:100%;height:100%"/> </template> </el-table-column> - <el-table-column prop="resultIndex" label="角标2" align="center" min-width="100"> + <el-table-column prop="resultIndex" label="角标2" align="center" width="100"> <template #default="scope"> - <el-input-number :min="0" clearable controls-position="right" size="mini" v-model="scope.row.resultIndex" style="width:100%;height:100%"/> + <el-input-number :min="0" clearable controls-position="right" size="small" + v-model="scope.row.resultIndex" style="width:100%;height:100%"/> </template> </el-table-column> - <el-table-column prop="isWrite" label="是否下发" align="center" min-width="100"> + <el-table-column prop="isWrite" label="是否下发" align="center" width="100"> <template #default="scope"> <el-switch size="small" v-model="scope.row.isWrite" :active-value="1" :inactive-value="0"/> @@ -303,28 +302,28 @@ label="测点名称" align="center" min-width="200"> <template #default="scope"> - <el-select v-model="scope.row.pointNo" - filterable - placeholder="请选择"> - <el-option - v-for="(item, index) in modelparamListMap['DATAPOINT']" - :key="index" - :label="item.name" - :value="item.itemNo"/> - </el-select> + <el-select-v2 + v-model="scope.row.pointNo" + :options="modelparamListMap['DATAPOINT'] || []" + placeholder="请选择" + :props="{value:'itemNo',label:'name'}" + clearable + filterable + :fit-input-width="false" + /> </template> </el-table-column> - <el-table-column prop="disturbancePointNo’" label="无扰切换点位" align="center" min-width="200"> + <el-table-column prop="disturbancePointNo" label="无扰切换点位" align="center" min-width="200"> <template #default="scope"> - <el-select v-model="scope.row.disturbancePointNo" - filterable - placeholder="请选择"> - <el-option - v-for="(item, index) in modelparamListMap['DATAPOINT']" - :key="index" - :label="item.name" - :value="item.itemNo"/> - </el-select> + <el-select-v2 + v-model="scope.row.disturbancePointNo" + :options="modelparamListMap['DATAPOINT'] || []" + placeholder="请选择" + :props="{value:'itemNo',label:'name'}" + clearable + filterable + :fit-input-width="false" + /> </template> </el-table-column> <el-table-column label="操作" fixed="right" header-align="center" align="center" width="100"> @@ -347,15 +346,17 @@ </Dialog> </template> <script lang="ts" setup> - import { DICT_TYPE, getStrDictOptions } from '@/utils/dict' + import {DICT_TYPE, getStrDictOptions} from '@/utils/dict' import * as ScheduleModelApi from '@/api/model/sche/model' - import { CommonStatusEnum } from '@/utils/constants' + import {CommonStatusEnum} from '@/utils/constants' import * as MpkApi from "@/api/model/mpk/mpk"; import {generateUUID} from "@/utils"; + import {ElMessage, ElMessageBox} from 'element-plus' + import {Refresh} from '@element-plus/icons-vue' - defineOptions({ name: 'ScheduleModelForm' }) + defineOptions({name: 'ScheduleModelForm'}) - const { t } = useI18n() // 国际化 + const {t} = useI18n() // 国际化 const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 const dialogTitle = ref('') // 弹窗的标题 @@ -374,19 +375,27 @@ resultStrId: undefined, invocation: undefined, status: CommonStatusEnum.ENABLE, - paramList: [], + paramList: [{ + modelparamportorder: 1 + '', + modelparamorder: '1', + modelparamtype: '', + modelparamid: '', + datalength: 0 + }], settingList: [], modelOut: [] }) const formRules = reactive({ - modelCode: [{ required: true, message: '模型编号不能为空', trigger: 'blur' }], - modelName: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }], - modelType: [{ required: true, message: '模型类型不能为空', trigger: 'blur' }] + modelCode: [{required: true, message: '模型编号不能为空', trigger: 'blur'}], + modelName: [{required: true, message: '模型名称不能为空', trigger: 'blur'}], + modelType: [{required: true, message: '模型类型不能为空', trigger: 'blur'}] }) const formRef = ref() // 表单 Ref const modelparamListMap = ref({}) // 调度模型列表 const scheduleModelList = ref([]) + const aiModelList = ref([]) + const aiModel = ref([]) const model = ref() const modelPopover = ref() @@ -434,11 +443,13 @@ } } // 加载参数列表 - modelparamListMap.value = await ScheduleModelApi.getModelParamList() + modelparamListMap.value = await ScheduleModelApi.getModelParamList(id) // 加载调度模型列表 getScheduleModelList() + // 加载ai模型列表 + getAiModelList() } - defineExpose({ open }) // 提供 open 方法,用于打开弹窗 + defineExpose({open}) // 提供 open 方法,用于打开弹窗 /** 提交表单 */ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 @@ -447,6 +458,21 @@ if (!formRef) return const valid = await formRef.value.validate() if (!valid) return + //校验模型输入 + formData.value.paramList.forEach(e => { + if (e.modelparamid == undefined || e.modelparamid == '') { + message.error("输入数据异常") + throw new Error('输入数据异常'); + } + // ind_ascii类型输出的序号必须是1,且所在端口序号最大为1(一个ind_ascii类型输入独占一个端口) + if (e.modelparamtype === 'IND_ASCII') { + if (e.modelparamorder != 1 || formData.value.paramList.filter(p => p.modelparamportorder === e.modelparamportorder).length != 1) { + message.error("输入数据异常:IND_ASCII类型输入独占一个端口") + throw new Error('输入数据异常:IND_ASCII类型输入独占一个端口'); + } + } + }) + // 提交请求 formLoading.value = true try { @@ -481,7 +507,13 @@ resultStrId: undefined, invocation: undefined, status: CommonStatusEnum.ENABLE, - paramList: [], + paramList: [{ + modelparamportorder: 1 + '', + modelparamorder: '1', + modelparamtype: '', + modelparamid: '', + datalength: 0 + }], settingList: [], modelOut: [] } @@ -506,62 +538,164 @@ } } + const getAiModelList = async () => { + aiModel.value = await MpkApi.aiList(null) + if (aiModel.value && aiModel.value.length > 0) { + aiModelList.value = aiModel.value.map(e => { + return { + value: e.id, + label: e.name, + children: e.children.map(template => { + return { + value: template.id, + label: template.questionName + } + }) + } + }) + } + }; + // 选择调度模型 const changeModel = async () => { // 校验 if (model.value && model.value.length > 0) { - const modelInfo = model.value[0] - const methodInfo = model.value[1] - formData.value.modelName = modelInfo.pyChineseName - formData.value.className = modelInfo.pkgName + '.impl.' + modelInfo.pyName + 'Impl'; - formData.value.methodName = methodInfo.methodName - formData.value.portLength = methodInfo.dataLength - // 参数构造 - let paramStructure = [] - for (let i = 0; i < methodInfo.dataLength; i++) { - paramStructure.push('[[D') + ElMessageBox.confirm( + '是否更新输入参数?', + '提示', + { + confirmButtonText: '是', + cancelButtonText: '否', + type: 'success', + icon: markRaw(Refresh), + closeOnClickModal: false, + closeOnPressEscape: false + } + ).then(() => { + relevanceModel(true) + }).catch(() => { + relevanceModel(false) + }) + } else { + message.error("请先选择模型") + } + } + + // 选择ai模型 + const changeAiModel = () => { + if (!model.value && model.value.length > 0) return + // 查找选中的模型组 + const modelGroup = aiModel.value.find( + group => group.id === model.value[0] + ) + // 查找选中的模板 + const template = modelGroup?.children.find( + t => t.id === model.value[1] + ) + if (!modelGroup || !template) return + // 弹窗确认 + ElMessageBox.confirm( + '是否更新输入参数?', + '提示', + { + confirmButtonText: '是', + cancelButtonText: '否', + type: 'success', + icon: markRaw(Refresh), + closeOnClickModal: false, + closeOnPressEscape: false } - if (methodInfo.model === 1) { - paramStructure.push('java.util.HashMap') + ).then(() => { + // 更新表单数据 + updateAiModelForm(modelGroup, template, true) + }).catch(() => { + updateAiModelForm(modelGroup, template, false) + }) + } + + // 更新AI模型表单数据 + const updateAiModelForm = (modelGroup, template, updateParams) => { + // 设置基本信息 + formData.value.modelName = modelGroup.name + formData.value.methodName = template.questionName + formData.value.portLength = template.dataLength + + // 设置参数列表转换 + formData.value.settingList = template.settingList.map(setting => { + return { + key: setting.settingKey, + name: setting.settingName, + value: setting.settingValue, + valuetype: 'string' } - paramStructure.push('java.util.HashMap') - formData.value.paramStructure = paramStructure.join(',') - formData.value.modelPath = modelInfo.pyModule + }) // 输入参数 let paramList = [] - for (let i = 0; i < methodInfo.dataLength; i++) { + for (let i = 0; i < formData.value.portLength; i++) { paramList.push({ - modelparamportorder: i+1 + '', + modelparamportorder: i + 1 + '', modelparamorder: '1', modelparamtype: '', modelparamid: '', datalength: 0 }) } - formData.value.paramList = paramList - // 设置参数 - let settingList = [] - methodInfo.methodSettings.forEach(e => { - settingList.push({ - key: e.settingKey, - value: e.value, - valuetype: e.valueType, - name: e.name - }) - }) - formData.value.settingList = settingList - modelPopover.value.hide() - }else { - message.error("请先选择模型") } + + + function relevanceModel(refreshParam) { + const modelInfo = model.value[0] + const methodInfo = model.value[1] + formData.value.modelName = modelInfo.pyChineseName + formData.value.className = modelInfo.pkgName + '.impl.' + modelInfo.pyName + 'Impl'; + formData.value.methodName = methodInfo.methodName + formData.value.portLength = methodInfo.dataLength + // 参数构造 + let paramStructure = [] + for (let i = 0; i < methodInfo.dataLength; i++) { + paramStructure.push('[[D') + } + if (methodInfo.model === 1) { + paramStructure.push('java.util.HashMap') + } + paramStructure.push('java.util.HashMap') + formData.value.paramStructure = paramStructure.join(',') + formData.value.modelPath = modelInfo.pyModule + if (refreshParam) { + // 输入参数 + let paramList = [] + for (let i = 0; i < methodInfo.dataLength; i++) { + paramList.push({ + modelparamportorder: i + 1 + '', + modelparamorder: '1', + modelparamtype: '', + modelparamid: '', + datalength: 0 + }) + } + formData.value.paramList = paramList + } + // 设置参数 + let settingList = [] + methodInfo.methodSettings.forEach(e => { + settingList.push({ + key: e.settingKey, + value: e.value, + valuetype: e.valueType, + name: e.name + }) + }) + formData.value.settingList = settingList + modelPopover.value.hide() } function changeModelparamtype(row) { row.modelparamid = '' } - const addRowOut= function () { - if(formData.value.modelOut===undefined) { + + const addRowOut = function () { + if (formData.value.modelOut === undefined) { formData.value.modelOut = [] } formData.value.modelOut.push({ @@ -571,9 +705,9 @@ port: 0, index: 0, isWrite: 1, - pointNo:undefined, - sort:undefined, - disturbancePointNo:undefined, + pointNo: undefined, + sort: undefined, + disturbancePointNo: undefined, }) } const deleteModelOutRow = function (index) { -- Gitblit v1.9.3