src/api/model/matlab/mlModel.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/model/matlab/project.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/router/modules/remaining.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/utils/dict.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/model/matlab/model/MatlabModelForm.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/model/matlab/model/MatlabModelSettingForm.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/model/matlab/model/MatlabRun.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/model/matlab/model/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/model/matlab/project/MatlabProjectForm.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/model/matlab/project/MatlabProjectModelDialog.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/model/matlab/project/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/api/model/matlab/mlModel.ts
对比新文件 @@ -0,0 +1,29 @@ import request from '@/config/axios' export const getPage = async (params: PageParam) => { return await request.get({ url: '/model/matlab/model/page', params }) } export const get = async (id: number) => { return await request.get({ url: '/model/matlab/model/' + id }) } export const create = async (data) => { return await request.post({ url: '/model/matlab/model', data: data }) } export const update = async (params) => { return await request.put({ url: '/model/matlab/model', data: params }) } export const deleteModel = async (id: number) => { return await request.delete({ url: '/model/matlab/model?id=' + id }) } export const list = (params) => { return request.get({ url: '/model/matlab/model/list', params}) } export const test = (data) => { return request.post({ url: '/model/matlab/model/test', data}) } src/api/model/matlab/project.ts
对比新文件 @@ -0,0 +1,33 @@ import request from '@/config/axios' export const getPage = async (params) => { return await request.get({ url: '/model/matlab/project/page', params }) } export const getProject = async (id: number) => { return await request.get({ url: '/model/matlab/project/' + id }) } export const createProject = async (data) => { return await request.post({ url: '/model/matlab/project', data: data }) } export const updateProject = async (params) => { return await request.put({ url: '/model/matlab/project', data: params }) } export const deleteProject = async (id: number) => { return await request.delete({ url: '/model/matlab/project?id=' + id }) } export const list = () => { return request.get({ url: '/model/packageProject/project/list'}) } export const getProjectModel = async (params) => { return await request.get({ url: '/model/matlab/project/getProjectModel', params }) } export const publish = async (data) => { return await request.post({ url: '/model/matlab/project/publish', data }) } src/router/modules/remaining.ts
@@ -447,6 +447,29 @@ } ] }, { path: '/matlab', component: Layout, name: 'matlab', meta: { hidden: true }, children: [ { path: 'model/form/:id?', component: () => import('@/views/model/matlab/model/MatlabModelForm.vue'), name: 'MatlabModelForm', meta: { title: 'Matlab模型表单', noCache: true, hidden: true, canTo: true, icon: '', activeMenu: '/matlab/model' } } ] }, ] export default remainingRouter src/utils/dict.ts
@@ -166,6 +166,8 @@ PRED_GRANULARITY = 'pred_granularity', ITEM_RUN_STATUS = 'item_run_status', RESULT_TYPE = 'result_type', MATLAB_PLATFORM= 'matlab_platform', MATLAB_VERSION= 'matlab_version', // ========== DATA - 数据平台模块 ========== DATA_FIELD_TYPE = 'data_field_type', TAG_DATA_TYPE = 'tag_data_type', src/views/model/matlab/model/MatlabModelForm.vue
对比新文件 @@ -0,0 +1,394 @@ <template> <div class="p-16px" style="background-color: #ffffff"> <el-header> {{title}} </el-header> <el-main> <el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="120px" > <el-divider content-position="left">模型信息</el-divider> <el-row :gutter="8"> <el-col :span="12"> <el-form-item label="模型类型" prop="modelType"> <el-radio-group v-model="formData.modelType"> <el-radio-button :disabled="actionType == 'edit'" v-for="dict in getDictOptions(DICT_TYPE.MODEL_TYPE)" :key="dict.label" :label="dict.value" > {{ dict.label }} </el-radio-button> </el-radio-group> </el-form-item> </el-col> </el-row> <el-row :gutter="8"> <el-col :span="12"> <el-form-item label="模型名称" prop="modelName"> <el-input v-model="formData.modelName" placeholder=""/> </el-form-item> </el-col> </el-row> <el-row :gutter="8"> <el-col :span="12"> <el-form-item label="模型文件" prop="modelFileName"> <el-input disabled v-model="formData.modelFileName" placeholder=""/> </el-form-item> </el-col> <el-col :span="4"> <el-upload ref="uploadRef" v-model:file-list="fileList" :show-file-list="false" :action="importUrl" :auto-upload="true" :disabled="uploadLoading" v-loading="uploadLoading" :before-upload="beforeUpload" :headers="uploadHeaders" :on-error="submitFormError" :on-success="submitFormSuccess" accept=".jar" > <el-tooltip content="上传算法封装.jar文件" placement="top" effect="light"> <el-button type="primary"> <Icon icon="ep:upload"/> 模型上传 </el-button> </el-tooltip> </el-upload> </el-col> </el-row> <el-row :gutter="8"> <el-col :span="6"> <el-form-item label="MATLAB平台" prop="matlabPlatform"> <el-select v-model="formData.matlabPlatform"> <el-option v-for="item in getDictOptions(DICT_TYPE.MATLAB_PLATFORM)" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="MATLAB版本" prop="matlabVersion"> <el-select v-model="formData.matlabVersion"> <el-option v-for="item in getDictOptions(DICT_TYPE.MATLAB_VERSION)" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="备注" prop="remark"> <el-input v-model="formData.remark" placeholder="" type="textarea"/> </el-form-item> </el-col> </el-row> <el-divider content-position="left">模型方法</el-divider> <!-- <el-row :gutter="20">--> <!-- <el-col :span="4">--> <!-- <el-button type="primary" size="small" @click="addRow()" >新增</el-button>--> <!-- </el-col>--> <!-- </el-row>--> <el-table :data="formData.modelMethods" border @expand-change="methodExpandChange" :expand-row-keys="methodExpandedRowKeys" :row-key="row => row.id"> <el-table-column prop="" label="全类名" align="center" width="400"> <template #default="scope"> <el-input disabled size="small" v-model="scope.row.className" placeholder=""/> </template> </el-table-column> <el-table-column prop="" label="方法名" align="center" width="250"> <template #default="scope"> <el-input disabled size="small" v-model="scope.row.methodName" placeholder=""/> </template> </el-table-column> <el-table-column prop="" label="数据长度" align="center"> <template #default="scope"> <el-input-number disabled size="small" step-strictly v-model="scope.row.dataLength" :min="1" :max="50" value-on-clear="min"/> </template> </el-table-column> <el-table-column prop="" label="输出长度" align="center"> <template #default="scope"> <el-input-number disabled size="small" step-strictly v-model="scope.row.outLength" :min="1" :max="50" value-on-clear="min"/> </template> </el-table-column> <el-table-column label="方法参数" type="expand" width="100px"> <template #default="props"> <div class="m-16px"> <el-button type="primary" size="small" @click="addSetting(props.row.methodSettings)">新增参数</el-button> <el-table :data="props.row.methodSettings" border size="small"> <el-table-column align="center" label="参数名称" prop="name"/> <el-table-column align="center" label="key" prop="settingKey"/> <el-table-column align="center" label="value" prop="settingValue"/> <el-table-column align="center" label="参数类型" prop="valueType"/> <el-table-column label="操作" fixed="right" header-align="center" align="center" width="100"> <template #default="scope"> <el-button @click="updateSetting(scope.row)" key="danger" type="primary" link >修改 </el-button> <el-button @click="deleteSetting(props.row.methodSettings,scope.$index)" key="danger" type="danger" link >删除 </el-button> </template> </el-table-column> </el-table> </div> </template> </el-table-column> <el-table-column label="操作" fixed="right" header-align="center" align="center" width="100"> <template #default="scope"> <el-button @click="deleteRow(scope.$index)" key="danger" type="danger" link >删除 </el-button> </template> </el-table-column> </el-table> </el-form> </el-main> <el-footer> <div class="flex flex-row justify-end items-center"> <el-button type="primary" @click="submitForm">确 定</el-button> </div> </el-footer> </div> <SettingForm ref="settingFormRef"/> </template> <script lang="ts" setup> import {DICT_TYPE,getDictOptions} from '@/utils/dict'; import * as MatlabApi from '@/api/model/matlab/mlModel' import {FormRules} from 'element-plus' import {getAccessToken, getTenantId} from "@/utils/auth"; import SettingForm from './MatlabModelSettingForm.vue' import {generateUUID} from "@/utils"; const {t} = useI18n() // 国际化 const message = useMessage() // 消息弹窗 const title = ref('') // 弹窗的标题 const actionType = ref('') // 操作类型 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formType = ref('') // 表单的类型:create - 新增;update - 修改 const route = useRoute() // 路由 const router = useRouter(); const staticDir = ref(import.meta.env.VITE_STATIC_DIR) /** settingForm弹窗 */ const settingFormRef = ref() // 添加setting const addSetting = (methodSettings) => { settingFormRef.value.open(undefined,methodSettings) } // 修改setting const updateSetting = (info) => { settingFormRef.value.open(info) } // 删除setting const deleteSetting = (methodSettings,index) => { methodSettings.splice(index, 1); } const methodExpandedRowKeys = ref([]) const methodExpandChange = async (row: any, expandedRows: any[]) => { methodExpandedRowKeys.value = expandedRows.map(e => e.id) } const formData = ref({ id: route.params.id, modelName: undefined, modelFileName: undefined, modelFilePath: undefined, modelType: 'predict', matlabPlatform: undefined, matlabVersion: undefined, remark: undefined, modelMethods: [], }) const formRules = reactive<FormRules>({ modelFileName: [ {required: true, message: '模型名称不能为空,请上传模型jar文件', trigger: 'blur'} ], modelName: [ {required: true, message: '模型中文名称不能为空', trigger: 'blur'} ], modelType: [ {required: true, message: '模型类型不能为空', trigger: 'blur'} ], matlabPlatform: [ {required: true, message: 'MATLAB平台不能为空', trigger: 'blur'} ], matlabVersion: [ {required: true, message: 'MATLAB版本不能为空', trigger: 'blur'} ], }) const formRef = ref() // 表单 Ref /** 提交表单 */ const submitForm = async () => { // 校验表单 if (!formRef) return const valid = await formRef.value.validate() if (!valid) return // 模型方法校验 if (formData.value.modelMethods?.length <= 0) { message.error('模型方法为空') return } // 模型方法名称校验 if (formData.value.modelMethods.some(e => e.methodName === undefined || e.methodName === '' || e.dataLength === undefined || e.dataLength === null)) { message.error('存在不合法模型方法名') return } // 提交请求 formLoading.value = true try { const data = formData.value if (formType.value === 'create') { await MatlabApi.create(data) message.success(t('common.createSuccess')) } else { await MatlabApi.update(data) message.success(t('common.updateSuccess')) } } finally { formLoading.value = false } // router.push({path:'/model/mpk'}) router.back() } /** 重置表单 */ const resetForm = () => { formData.value = { id: undefined, modelFileName: undefined, modelName: undefined, modelType: 'predict', remark: undefined, modelMethods: [], modelFilePath: undefined } formRef.value?.resetFields() } const handleChange = function () { } const addRow = function () { formData.value.modelMethods.push({ id: generateUUID(), className: undefined, methodName: undefined, dataLength: 1, outLength: 1, methodSettings: [] }) } const deleteRow = function (index) { formData.value.modelMethods.splice(index, 1) } const fileList = ref([]) // 文件列表 const importUrl = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/model/matlab/model/upload' const uploadLoading = ref(false) // 表单的加载中 const uploadHeaders = ref() // 上传 Header 头 const beforeUpload = function (file) { // 提交请求 uploadHeaders.value = { Authorization: 'Bearer ' + getAccessToken(), 'tenant-id': getTenantId() } uploadLoading.value = true return true; } const submitFormError = (): void => { message.error('上传失败!') uploadLoading.value = false } const submitFormSuccess = (response: any) => { if (response.code !== 0) { message.error(response.msg) uploadLoading.value = false return } const data = response.data; formData.value.modelFilePath = data.filePath formData.value.modelFileName = data.fileName const modelMethods = (data.classInfos || []).flatMap(e => { return (e.methodInfos || []).map(m => { return { ...m,id: generateUUID(), className: e.className,methodSettings: [] }; }); }); formData.value.modelMethods = modelMethods message.success('上传成功') uploadLoading.value = false } onMounted(async () => { const id = formData.value.id; const type = id ? 'edit' : 'create' actionType.value = type title.value = t('action.' + type) formType.value = type resetForm() // 修改时,设置数据 if (id) { formLoading.value = true try { debugger formData.value = await MatlabApi.get(id) debugger } finally { formLoading.value = false } } }) </script> <style scoped lang="scss"> </style> src/views/model/matlab/model/MatlabModelSettingForm.vue
对比新文件 @@ -0,0 +1,144 @@ <template> <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" > <el-row :gutter="8"> <el-col :span="12"> <el-form-item label="参数名称" prop="name"> <el-input v-model="formData.name" placeholder=""/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="参数类型" prop="valueType"> <el-select v-model="formData.valueType"> <el-option v-for="item in getDictOptions(DICT_TYPE.MODEL_METHOD_SETTING_VALUE_TYPE)" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> </el-col> </el-row> <el-row :gutter="8"> <el-col :span="12"> <el-form-item label="key" prop="settingKey"> <el-input v-model="formData.settingKey" placeholder=""/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="value" prop="settingValue"> <el-input v-model="formData.settingValue" placeholder=""/> </el-form-item> </el-col> </el-row> </el-form> <template #footer> <el-button type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> <script lang="ts" setup> import {DICT_TYPE,getDictOptions} from '@/utils/dict'; import {FormRules} from 'element-plus' const {t} = useI18n() // 国际化 const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 const dialogTitle = ref('参数设置') // 弹窗的标题 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formData = ref({ settingKey: undefined, settingValue: undefined, name: undefined, valueType: undefined }) const formRules = reactive<FormRules>({ settingKey: [ {required: true, message: 'key不能为空', trigger: 'blur'}, ], settingValue: [ {required: true, message: 'value不能为空', trigger: 'blur'}, ], name: [ {required: true, message: '参数名称不能为空', trigger: 'blur'}, ], valueType: [ {required: true, message: '参数类型不能为空', trigger: 'blur'}, ] }) const formRef = ref() // 表单 Ref let methodSettingsRef = undefined let infoRef = undefined /** 打开弹窗 */ const open = async (info,methodSettings) => { dialogVisible.value = true resetForm() // 修改时,设置数据 if (info) { infoRef = info formLoading.value = true try { formData.value = {...info} } finally { formLoading.value = false } }else { methodSettingsRef = methodSettings } } defineExpose({open}) // 提供 open 方法,用于打开弹窗 // 数据回调 const emit = defineEmits(['addSettingCallback']) /** 提交表单 */ const submitForm = async () => { // 校验表单 if (!formRef) return const valid = await formRef.value.validate() if (!valid) return // 提交请求 formLoading.value = true try { if (infoRef) { // 修改 for (let key in formData.value) { infoRef[key] = formData.value[key]; } infoRef = undefined; }else { // 新增 methodSettingsRef.push({...formData.value}) } dialogVisible.value = false } finally { formLoading.value = false } } /** 重置表单 */ const resetForm = () => { formData.value = { settingKey: undefined, settingValue: undefined, name: undefined, valueType: undefined, } formRef.value?.resetFields() } </script> src/views/model/matlab/model/MatlabRun.vue
对比新文件 @@ -0,0 +1,279 @@ <template> <Dialog v-model="dialogVisible" :title="dialogTitle"> <el-form class="-mb-15px" :model="formData" ref="formRef" :inline="true" :rules="formRules" label-width="68px" v-loading="formLoading" > <el-form-item style="width: 100%"> <el-divider content-position="left">模型信息</el-divider> </el-form-item> <el-row> <el-col :span="24"> <el-form-item label="全类名" style="width: 100%" prop="className"> <el-input disabled v-model="formData.className" placeholder=""/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="方法名" prop="methodName"> <el-select v-model="formData.methodId" @change="methodChange" style="width: 240px"> <el-option v-for="item in methodList" :key="item.id" :label="item.className + '.' + item.methodName + '()'" :value="item.id" /> </el-select> </el-form-item> </el-col> </el-row> <el-divider content-position="left">模型参数信息</el-divider> <div style="display:flex;flex-direction: row;align-items: center;margin-bottom: 6px"> <el-button tag="a" :href="staticDir + '/template/模型参数导入模板.xlsx'" download="模型参数导入模板.xlsx" style="text-decoration: none;" type="primary" size="small" link>模板下载</el-button> <el-upload ref="uploadRef" v-model:file-list="fileList" :show-file-list="false" :action="importUrl" :auto-upload="true" :disabled="formLoading" :before-upload="beforeUpload" :headers="uploadHeaders" :on-error="submitFormError" :on-success="submitFormSuccess" accept=".xlsx" > <el-button type="primary" size="small" link>参数导入</el-button> </el-upload> </div> <el-row v-for="(item,index) in datas" :key="index" :gutter="20"> <el-col :span="24"> <el-form-item :label="'参数_' + (index)" required style="width: 100%"> <el-input type="textarea" :disabled="true" :rows="3" v-model="datas[index]" placeholder="" /> </el-form-item> </el-col> </el-row> <el-divider content-position="left">模型设置信息</el-divider> <!-- <el-row :gutter="20">--> <!-- <el-col :span="4">--> <!-- <el-button type="primary" size="small" @click="addRow()">新增</el-button>--> <!-- </el-col>--> <!-- </el-row>--> <el-table :data="formData.modelSettings" border> <el-table-column prop="" label="参数key" align="center"> <template #default="scope"> <el-input size="small" v-model="scope.row.settingKey" :disabled="true" maxlength="50" clearable /> </template> </el-table-column> <el-table-column prop="" label="参数名称" align="center"> <template #default="scope"> <el-input size="small" v-model="scope.row.name" :disabled="true" maxlength="50" clearable /> </template> </el-table-column> <el-table-column prop="" label="参数value" align="center"> <template #default="scope"> <el-input size="small" v-model="scope.row.settingValue" :disabled="scope.row.settingKey === 'pyFile'" maxlength="50" clearable /> </template> </el-table-column> <!-- <el-table-column label="操作" fixed="right" header-align="center" align="center" width="100">--> <!-- <template #default="scope">--> <!-- <el-button--> <!-- @click="deleteRow(scope.$index)"--> <!-- key="danger"--> <!-- type="danger"--> <!-- :disabled="scope.row.settingKey === 'pyFile'"--> <!-- link--> <!-- >删除</el-button>--> <!-- </template>--> <!-- </el-table-column>--> </el-table> <el-divider content-position="left">模型运行结果</el-divider> <el-input v-model="modelRunResult" placeholder="" rows="4" type="textarea" /> <div style="display: flex;flex-direction: row;justify-content: end;margin-top: 16px"> <el-button :loading="modelRunloading" type="primary" @click="modelRun()">运行</el-button> </div> </el-form> </Dialog> </template> <script lang="ts" setup> import * as MlModelApi from '@/api/model/matlab/mlModel' import {FormRules} from "element-plus"; import {getAccessToken, getTenantId} from "@/utils/auth"; import download from "@/utils/download"; const staticDir = ref(import.meta.env.VITE_STATIC_DIR) const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 const dialogTitle = ref('模型运行') // 弹窗的标题 const formData = reactive({ modelFileName: '', className: '', methodName: '', methodId: '', uuids: [], modelSettings: [], outLength: 1 }) const datas = ref([]) // 模型方法下拉列表 const methodList = ref([]) /** 打开弹窗 */ const open = async (row) => { dialogVisible.value = true formData.modelFileName = row.modelFileName const matlabModel = await MlModelApi.get(row.id) methodList.value = matlabModel.modelMethods formData.className = matlabModel.modelMethods[0].className formData.methodId = matlabModel.modelMethods[0].id formData.methodName = matlabModel.modelMethods[0].methodName formData.outLength = matlabModel.modelMethods[0].outLength datas.value = [] formData.uuids = []; for (let i = 0 ; i < matlabModel.modelMethods[0].dataLength ; i++) { datas.value[i] = '[[]]'; formData.uuids[i] = ''; } // 回显参数 if (matlabModel.modelMethods[0].methodSettings && matlabModel.modelMethods[0].methodSettings.length > 0) { formData.modelSettings = matlabModel.modelMethods[0].methodSettings } } defineExpose({ open }) // 提供 open 方法,用于打开弹窗 const formRules = reactive<FormRules>({ methodName: [ {required: true, message: '方法名不能为空', trigger: 'blur'} ], className: [ {required: true, message: '全类名不能为空', trigger: 'blur'} ] }) const addRow = function () { formData.modelSettings.push({ settingKey: '', settingValue: '' }) } const deleteRow = function (index) { formData.modelSettings.splice(index, 1) } const methodChange = function (value) { datas.value = [] formData.uuids = []; var method = methodList.value.find(e => e.id === value); formData.methodName = method.methodName formData.className = method.className for (let i = 0 ; i < method?.dataLength ; i++) { datas.value[i] = '[[]]'; formData.uuids[i] = ''; } // 回显参数 if (method.methodSettings && method.methodSettings.length > 0) { formData.modelSettings = method.methodSettings }else { formData.modelSettings = [] } } const fileList = ref([]) // 文件列表 const importUrl = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/model/matlab/model/importData' const formLoading = ref(false) // 表单的加载中 const uploadHeaders = ref() // 上传 Header 头 /** 上传错误提示 */ const submitFormError = (): void => { message.error('导入失败,请检查导入文件!') formLoading.value = false } const submitFormSuccess = (response: any) => { try { if (response.code !== 0) { message.error(response.msg) return } const data = response.data; if (datas.value.length > data.length) { message.error("导入数据长度为" + data.length + ",应≥" + datas.value.length) return } for (let i = 0; i < datas.value.length; i++) { datas.value[i] = data[i].data formData.uuids[i] = data[i].uuid; } message.success('导入成功') } finally { formLoading.value = false } } const beforeUpload = function (file) { // 提交请求 uploadHeaders.value = { Authorization: 'Bearer ' + getAccessToken(), 'tenant-id': getTenantId() } formLoading.value = true return true; } // 模型运行结果 const modelRunResult = ref('') // 模型运行loading const modelRunloading = ref(false) // 表单 Ref const formRef = ref() // 运行 const modelRun = async () => { modelRunResult.value = '' // 校验表单 if (!formRef) return const valid = await formRef.value.validate() if (!valid) return // 提交请求 modelRunloading.value = true try { const data = { ...formData } //处理modelSettings // let settingsPredict = {}; // data.modelSettings.forEach(e => { // settingsPredict[e.settingKey] = e.settingValue; // }) // data.modelSettings = settingsPredict let result = await MlModelApi.test(data) modelRunResult.value = result; message.success('运行成功') } finally { modelRunloading.value = false } } </script> src/views/model/matlab/model/index.vue
对比新文件 @@ -0,0 +1,188 @@ <template> <!-- 搜索工作栏 --> <ContentWrap> <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px" @submit.prevent > <el-form-item label="模型名称" prop="pyChineseName"> <el-input v-model="queryParams.modelName" placeholder="请输入模型名称" clearable class="!w-240px" /> </el-form-item> <el-form-item label="模型文件" prop="modelFileName"> <el-input v-model="queryParams.modelFileName" placeholder="请输入模型文件名称" clearable class="!w-240px" /> </el-form-item> <el-form-item> <el-button @click="handleQuery"> <Icon icon="ep:search" class="mr-5px"/> 搜索 </el-button> <el-button @click="resetQuery"> <Icon icon="ep:refresh" class="mr-5px"/> 重置 </el-button> <div class="ml-12px"> <router-link :to="'/matlab/model/form'"> <el-button type="primary" plain v-hasPermi="['ml:model:create']"> <Icon icon="ep:plus" class="mr-5px"/>新增</el-button> </router-link> </div> </el-form-item> </el-form> </ContentWrap> <!-- 列表 --> <ContentWrap> <el-table v-loading="loading" :data="list" row-key="id" > <el-table-column prop="modelName" label="模型名称" header-align="center" align="center" min-width="100" /> <el-table-column prop="modelFileName" label="模型文件" header-align="center" align="center" min-width="250"/> <el-table-column prop="modelType" label="模型类型" header-align="center" align="center" :formatter="(r,c,v) => getDictLabel(DICT_TYPE.MODEL_TYPE,v)"/> <el-table-column prop="matlabPlatform" label="matlab平台" header-align="center" align="center"/> <el-table-column prop="matlabVersion" label="matlab版本" header-align="center" align="center"/> <!-- <el-table-column prop="remark" label="备注" header-align="center" align="center" min-width="100px"/>--> <el-table-column prop="createDate" label="创建时间" header-align="center" align="center" :formatter="dateFormatter" width="180px"/> <el-table-column prop="updateDate" label="修改时间" header-align="center" align="center" :formatter="dateFormatter" width="180px"/> <el-table-column label="操作" align="center" width="200px"> <template #default="scope"> <div class="flex items-center justify-center"> <router-link :to="'/matlab/model/form/' + scope.row.id"> <el-button type="primary" link v-hasPermi="['ml:model:update']"> <Icon icon="ep:edit"/>修改 </el-button> </router-link> <el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['ml:model:delete']"> <Icon icon="ep:delete"/>删除 </el-button> <div class="pl-12px"> <el-dropdown @command="(command) => handleCommand(command, scope.row)" trigger="click"> <el-button type="primary" link> <Icon icon="ep:d-arrow-right" /> 更多 </el-button> <template #dropdown> <el-dropdown-menu> <el-dropdown-item command="mpkRunDialog" > 运行 </el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> </div> </div> </template> </el-table-column> </el-table> <!-- 分页 --> <Pagination v-model:limit="queryParams.limit" v-model:page="queryParams.page" :total="total" @pagination="getList" /> </ContentWrap> <MatlabRun ref="matlabRun" /> </template> <script lang="ts" setup> import {dateFormatter} from '@/utils/formatTime' import * as MlModelApi from '@/api/model/matlab/mlModel' import { DICT_TYPE, getDictLabel } from '@/utils/dict' import MatlabRun from './MatlabRun.vue' defineOptions({name: 'MatlabModel'}) const message = useMessage() // 消息弹窗 const {t} = useI18n() // 国际化 const loading = ref(true) // 列表的加载中 const total = ref(0) // 列表的总页数 const list = ref([]) // 字典表格数据 const queryParams = reactive({ page: 1, limit: 10, modelName: '', modelFileName: '' }) const queryFormRef = ref() // 搜索的表单 const getList = async () => { loading.value = true try { const data = await MlModelApi.getPage(queryParams) list.value = data.list total.value = data.total } finally { loading.value = false } } /** 操作分发 */ const handleCommand = (command: string, row) => { switch (command) { case 'mpkRunDialog': matlabRunDialog(row) break default: break } } /** 搜索按钮操作 */ const handleQuery = () => { getList() } /** 重置按钮操作 */ const resetQuery = () => { queryParams.page = 1 queryFormRef.value.resetFields() handleQuery() } /** 删除按钮操作 */ const handleDelete = async (id: number) => { try { // 删除的二次确认 await message.delConfirm() // 发起删除 await MlModelApi.deleteModel(id) message.success(t('common.delSuccess')) // 刷新列表 await getList() } catch { } } const matlabRun = ref(); const matlabRunDialog = (row) => { matlabRun.value.open(row); } onActivated((to) => { getList() }) /** 初始化 **/ onMounted(async () => { await getList() }) </script> src/views/model/matlab/project/MatlabProjectForm.vue
对比新文件 @@ -0,0 +1,156 @@ <template> <Dialog v-model="dialogVisible" :title="dialogTitle" width="60%"> <el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px" > <el-row :gutter="20"> <el-col :span="10"> <el-form-item label="项目名称" prop="projectName"> <el-input v-model="formData.projectName" placeholder=""/> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="10"> <el-form-item label="项目编码" prop="projectCode"> <el-input v-model="formData.projectCode" placeholder=""/> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="24"> <el-form-item label="关联模型" prop="models"> <el-transfer style="width: 100%" :props="{key: 'id',label: 'modelFileName'}" :titles="['未选模型', '已选模型']" target-order="unshift" filterable :filter-method="filterMethod" v-model="formData.models" :data="modelList"> <template #default="{ option }"> <span :title="option.modelFileName + '【' + option.modelName + '】'">{{ option.modelFileName}}</span> </template> </el-transfer> </el-form-item> </el-col> </el-row> </el-form> <template #footer> <el-button type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> <script lang="ts" setup> import * as ProjectApi from '@/api/model/matlab/project' import * as MlModelApi from '@/api/model/matlab/mlModel' import {FormRules} from 'element-plus' const {t} = useI18n() // 国际化 const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 const dialogTitle = ref('') // 弹窗的标题 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formType = ref('') // 表单的类型:create - 新增;update - 修改 const formData = ref({ id: undefined, projectName: undefined, projectCode: undefined, models: undefined, }) const formRules = reactive<FormRules>({ projectName: [ {required: true, message: '项目名称不能为空', trigger: 'blur'}, ], projectCode: [ {required: true, message: '项目编码不能为空', trigger: 'blur'}, ], }) const formRef = ref() // 表单 Ref /** 打开弹窗 */ const open = async (type: string, id?: number) => { dialogVisible.value = true dialogTitle.value = t('action.' + type) formType.value = type getModelList(); resetForm() // 修改时,设置数据 if (id) { formLoading.value = true try { const data = await ProjectApi.getProject(id) data.models = data.models.map(e => e.id) formData.value = { ...data } } finally { formLoading.value = false } } } defineExpose({open}) // 提供 open 方法,用于打开弹窗 /** 提交表单 */ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 const submitForm = async () => { // 校验表单 if (!formRef) return const valid = await formRef.value.validate() if (!valid) return // 提交请求 formLoading.value = true try { const data = { ...formData.value } if (data.models && data.models.length > 0) { data.models = data.models.map(e => { return {id: e} }) } if (formType.value === 'create') { await ProjectApi.createProject(data) message.success(t('common.createSuccess')) } else { await ProjectApi.updateProject(data) message.success(t('common.updateSuccess')) } dialogVisible.value = false // 发送操作成功的事件 emit('success') } finally { formLoading.value = false } } /** 重置表单 */ const resetForm = () => { formData.value = { id: undefined, projectName: undefined, projectCode: undefined, } formRef.value?.resetFields() } // 所有模型列表 const modelList = ref([]) const getModelList = async () => { modelList.value = await MlModelApi.list({}) } // 模型筛选 const filterMethod = function (query, item) { return item.modelFileName.toLowerCase().indexOf(query.toLowerCase()) !== -1 } </script> <style scoped> :deep(.el-transfer-panel) { width: 40%; } </style> src/views/model/matlab/project/MatlabProjectModelDialog.vue
对比新文件 @@ -0,0 +1,101 @@ <template> <Dialog v-model="dialogVisible" :title="dialogTitle" width="80%"> <!-- 搜索工作栏 --> <ContentWrap> <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px" > <el-form-item label="模型名称" prop="modelFileName"> <el-input v-model="queryParams.modelFileName" placeholder="请输入模型名称" clearable class="!w-240px" /> </el-form-item> <el-form-item> <el-button @click="getList"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> </el-form-item> </el-form> </ContentWrap> <!-- 列表 --> <ContentWrap> <el-table v-loading="loading" :data="list" row-key="id" border > <el-table-column prop="modelName" label="模型中文名称"/> <el-table-column prop="modelFileName" label="模型名称"/> <el-table-column prop="modelType" label="模型类型" :formatter="(r,c,v) => getDictLabel(DICT_TYPE.MODEL_TYPE,v)"/> <el-table-column prop="remark" label="备注" width="300px"/> <el-table-column label="模型方法" type="expand" width="100px"> <template #default="props"> <el-table :data="props.row.modelMethods"> <el-table-column align="center" label="全类名" prop="className" /> <el-table-column align="center" label="方法名" prop="methodName" /> <el-table-column align="center" label="参数长度" prop="dataLength" /> <el-table-column align="center" label="输出长度" prop="outLength" /> </el-table> </template> </el-table-column> </el-table> <!-- 分页 --> <Pagination v-model:limit="queryParams.pageSize" v-model:page="queryParams.page" :total="total" @pagination="getList" /> </ContentWrap> </Dialog> </template> <script lang="ts" setup> import download from "@/utils/download"; import * as projectApi from '@/api/model/matlab/project' import { dateFormatter } from '@/utils/formatTime' import { DICT_TYPE, getDictLabel } from '@/utils/dict' const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 const dialogTitle = ref('关联模型') // 弹窗的标题 const loading = ref(true) // 列表的加载中 const total = ref(0) // 列表的总页数 const list = ref([]) // 字典表格数据 const queryParams = reactive({ page: 1, pageSize: 10, projectId: undefined, modelFileName: undefined, }) /** 打开弹窗 */ const open = async (projectId: String) => { dialogVisible.value = true queryParams.projectId = projectId; getList() } defineExpose({ open }) // 提供 open 方法,用于打开弹窗 const getList = async () => { loading.value = true try { let data = await projectApi.getProjectModel(queryParams) list.value = data.list total.value = data.total } finally { loading.value = false } } </script> src/views/model/matlab/project/index.vue
对比新文件 @@ -0,0 +1,221 @@ <template> <!-- 搜索工作栏 --> <ContentWrap> <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px" > <el-form-item label="项目名称" prop="projectName"> <el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable class="!w-240px" /> </el-form-item> <el-form-item label="项目编码" prop="projectCode"> <el-input v-model="queryParams.projectCode" placeholder="请输入项目编码" clearable class="!w-240px" /> </el-form-item> <el-form-item> <el-button @click="handleQuery"> <Icon icon="ep:search" class="mr-5px"/> 搜索 </el-button> <el-button @click="resetQuery"> <Icon icon="ep:refresh" class="mr-5px"/> 重置 </el-button> <el-button type="primary" plain @click="openForm('create')" v-hasPermi="['mpk:project:create']" > <Icon icon="ep:plus" class="mr-5px"/> 新增 </el-button> </el-form-item> </el-form> </ContentWrap> <!-- 列表 --> <ContentWrap> <el-table v-loading="loading" :data="list" row-key="id" > <el-table-column prop="projectName" label="项目名称"/> <el-table-column prop="projectCode" label="项目编码"/> <el-table-column prop="createTime" label="创建时间" :formatter="dateFormatter" width="300px"/> <el-table-column label="操作" align="center" width="300px"> <template #default="scope"> <div class="flex items-center justify-center"> <el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['mpk:project:update']" > <Icon icon="ep:edit"/> 修改 </el-button> <el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['mpk:project:delete']" > <Icon icon="ep:delete"/> 删除 </el-button> <el-button link type="primary" @click="viewRelevanceModel(scope.row.id)" > <Icon icon="ep:link"/> 查看关联模型 </el-button> <div class="pl-12px"> <el-dropdown @command="(command) => handleCommand(command, scope.row)" trigger="click"> <el-button type="primary" link> <Icon icon="ep:d-arrow-right"/> 更多 </el-button> <template #dropdown> <el-dropdown-menu> <el-dropdown-item command="publish" > <el-button link>发布</el-button> </el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> </div> </div> </template> </el-table-column> </el-table> <!-- 分页 --> <Pagination v-model:limit="queryParams.limit" v-model:page="queryParams.page" :total="total" @pagination="getList" /> </ContentWrap> <!-- 表单弹窗:添加/修改 --> <ProjectForm ref="formRef" @success="getList"/> <!-- 关联模型 --> <RelevanceModel ref="relevanceModelRef"/> </template> <script lang="ts" setup> import {dateFormatter} from '@/utils/formatTime' import * as ProjectApi from '@/api/model/matlab/project' import ProjectForm from './MatlabProjectForm.vue' import RelevanceModel from './MatlabProjectModelDialog.vue' defineOptions({name: 'MatlabProject'}) const message = useMessage() // 消息弹窗 const {t} = useI18n() // 国际化 const loading = ref(true) // 列表的加载中 const total = ref(0) // 列表的总页数 const list = ref([]) // 字典表格数据 const queryParams = reactive({ page: 1, limit: 10, projectName: '', projectCode: '' }) const queryFormRef = ref() // 搜索的表单 const getList = async () => { loading.value = true try { const data = await ProjectApi.getPage(queryParams) list.value = data.list total.value = data.total } finally { loading.value = false } } /** 操作分发 */ const handleCommand = (command: string, row) => { switch (command) { case 'publish': publish(row.id,row.projectName) break default: break } } // 发布 const publish = async (projectId,projectName) => { // 发布的二次确认 await message.confirm('确认发布 ' + projectName) // 发布 await ProjectApi.publish({projectId}) message.success('发布成功'); } /** 搜索按钮操作 */ const handleQuery = () => { getList() } /** 重置按钮操作 */ const resetQuery = () => { queryParams.page = 1 queryFormRef.value.resetFields() handleQuery() } /** 添加/修改操作 */ const formRef = ref() const openForm = (type: string, id?: number) => { formRef.value.open(type, id) } /** 删除按钮操作 */ const handleDelete = async (id: number) => { try { // 删除的二次确认 await message.delConfirm() // 发起删除 await ProjectApi.deleteProject(id) message.success(t('common.delSuccess')) // 刷新列表 await getList() } catch { } } // 查看关联模型 const relevanceModelRef = ref() const viewRelevanceModel = (id) => { relevanceModelRef.value.open(id) } /** 初始化 **/ onMounted(async () => { await getList() }) </script>