From 0aea73e179800d8bef4a62e9d41f8ce3eac02a3e Mon Sep 17 00:00:00 2001
From: 潘志宝 <979469083@qq.com>
Date: 星期三, 18 九月 2024 13:54:31 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 src/router/modules/remaining.ts |   23 +
 src/views/mpk/MpkForm.vue       |  484 +++++++++++++++++++--------
 src/views/mpk/SettingForm.vue   |  270 +++++++++++++++
 src/views/mpk/mpk.vue           |   47 +-
 src/utils/dict.ts               |    3 
 src/views/mpk/SelectForm.vue    |  135 +++++++
 6 files changed, 789 insertions(+), 173 deletions(-)

diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts
index 825f9f0..e3af362 100644
--- a/src/router/modules/remaining.ts
+++ b/src/router/modules/remaining.ts
@@ -385,6 +385,29 @@
       }
     ]
   },
+  {
+    path: '/mpk',
+    component: Layout,
+    name: 'mpk',
+    meta: {
+      hidden: true
+    },
+    children: [
+      {
+        path: 'form/:id?',
+        component: () => import('@/views/mpk/MpkForm.vue'),
+        name: 'MpkForm',
+        meta: {
+          title: 'Mpk表单',
+          noCache: true,
+          hidden: true,
+          canTo: true,
+          icon: '',
+          activeMenu: '/model/mpk'
+        }
+      }
+    ]
+  },
 ]
 
 export default remainingRouter
diff --git a/src/utils/dict.ts b/src/utils/dict.ts
index be88689..686e68a 100644
--- a/src/utils/dict.ts
+++ b/src/utils/dict.ts
@@ -236,6 +236,9 @@
   SCHE_TRIGGER_METHOD = 'sche_trigger_method',
   MODEL_PARAM_TYPE = 'model_param_type',
   MODEL_METHOD = 'model_method',
+  MODEL_TYPE = 'model_type',
+  MODEL_METHOD_SETTING_TYPE = 'model_method_setting_type',
+  MODEL_METHOD_SETTING_VALUE_TYPE = 'model_method_setting_value_type',
 
   // ========== DATA - 数据平台模块  ==========
   DATA_FIELD_TYPE = 'data_field_type',
diff --git a/src/views/mpk/MpkForm.vue b/src/views/mpk/MpkForm.vue
index ee6fb7e..0bae832 100644
--- a/src/views/mpk/MpkForm.vue
+++ b/src/views/mpk/MpkForm.vue
@@ -1,137 +1,282 @@
 <template>
-  <Dialog v-model="dialogVisible" :title="dialogTitle">
-    <el-form
-      ref="formRef"
-      v-loading="formLoading"
-      :model="formData"
-      :rules="formRules"
-      label-width="80px"
-    >
-      <el-divider content-position="left">模型信息</el-divider>
-      <el-row :gutter="8">
-        <el-col :span="12">
-          <el-form-item label="模型名称" prop="pyName">
-            <el-input disabled v-model="formData.pyName" placeholder=""/>
-          </el-form-item>
-        </el-col>
-        <el-col :span="12">
-          <el-upload
-            ref="uploadRef"
-            v-model:file-list="fileList"
-            :show-file-list="false"
-            :action="importUrl"
-            :auto-upload="true"
-            :disabled="uploadLoading"
-            :before-upload="beforeUpload"
-            :headers="uploadHeaders"
-            :on-error="submitFormError"
-            :on-success="submitFormSuccess"
-            accept=".pyd"
-          >
-            <el-button type="primary"><Icon icon="ep:upload" />模型上传</el-button>
-          </el-upload>
-        </el-col>
-      </el-row>
-      <el-row :gutter="8">
-        <el-col :span="12">
-          <el-form-item label="包名" prop="pkgName">
-            <el-input v-model="formData.pkgName" placeholder=""/>
-          </el-form-item>
-        </el-col>
-        <el-col :span="12">
-          <el-form-item label="模型路径" prop="pyModule">
-            <el-input v-model="formData.pyModule" placeholder=""/>
-          </el-form-item>
-        </el-col>
-      </el-row>
-      <el-row :gutter="20">
-        <el-col :span="24">
-          <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>
-        <el-table-column
-          prop=""
-          label="方法名"
-          align="center"
-          width="250">
-          <template #default="scope">
-            <el-select size="small" v-model="scope.row.methodName">
-              <el-option
-                v-for="item in getDictOptions(DICT_TYPE.MODEL_METHOD)"
-                :key="item.value"
-                :label="item.label"
-                :value="item.value"
-                :disabled="methodSelectDisabled(item.value)"
-              />
-            </el-select>
-          </template>
-        </el-table-column>
-        <el-table-column
-          prop=""
-          label="输入个数"
-          align="center">
-          <template #default="scope">
-            <el-input-number size="small" v-model="scope.row.dataLength" :min="1" :max="50"/>
-          </template>
-        </el-table-column>
-        <el-table-column
-          prop=""
-          label="是否有model"
-          align="center">
-          <template #default="scope">
-            <el-switch size="small" v-model="scope.row.model" :active-value="1"
-                       :inactive-value="0"/>
-          </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>
-    <template #footer>
-      <el-button type="primary" @click="submitForm">确 定</el-button>
-      <el-button @click="dialogVisible = false">取 消</el-button>
-    </template>
-  </Dialog>
+  <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="20">
+            <el-form-item label="模型名称" prop="pyName">
+              <el-input disabled v-model="formData.pyName" 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"
+              :before-upload="beforeUpload"
+              :headers="uploadHeaders"
+              :on-error="submitFormError"
+              :on-success="submitFormSuccess"
+              accept=".pyd"
+            >
+              <el-button type="primary">
+                <Icon icon="ep:upload"/>
+                模型上传
+              </el-button>
+            </el-upload>
+          </el-col>
+        </el-row>
+        <el-row :gutter="8">
+          <el-col :span="12">
+            <el-form-item label="模型中文名称" prop="pyChineseName">
+              <el-input v-model="formData.pyChineseName" placeholder=""/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="模型类型" prop="pyType">
+              <el-select
+                v-model="formData.pyType"
+                placeholder="请选择"
+                @change="pyTypeChange"
+              >
+                <el-option
+                  v-for="dict in getDictOptions(DICT_TYPE.MODEL_TYPE)"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="8">
+          <el-col :span="12">
+            <el-form-item label="包名" prop="pkgName">
+              <el-input v-model="formData.pkgName" placeholder=""/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="模型路径" prop="pyModule">
+              <el-input v-model="formData.pyModule" placeholder=""/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="8">
+          <el-col :span="12">
+            <el-form-item label="所属菜单" prop="menuName">
+              <el-input v-model="formData.menuName" placeholder=""/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="所属组" prop="groupName">
+              <el-input v-model="formData.groupName" placeholder=""/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="8">
+          <el-col :span="12">
+            <el-form-item label="icon" prop="icon">
+              <el-input v-model="formData.icon" placeholder=""/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <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="250">
+            <template #default="scope">
+              <el-input 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 size="small" step-strictly v-model="scope.row.dataLength" :min="1"
+                               :max="50"/>
+            </template>
+          </el-table-column>
+          <el-table-column
+            prop=""
+            label="是否有model"
+            align="center">
+            <template #default="scope">
+              <el-switch size="small" v-model="scope.row.model" :active-value="1"
+                         :inactive-value="0"/>
+            </template>
+          </el-table-column>
+          <el-table-column
+            prop=""
+            label="结果key"
+            align="center">
+            <template #default="scope">
+              <el-input size="small" v-model="scope.row.resultKey"/>
+            </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="key" prop="settingKey"/>
+                  <el-table-column align="center" label="参数名称" prop="name"/>
+                  <el-table-column align="center" label="参数默认值" prop="value"/>
+                  <el-table-column align="center" label="输入类型" prop="type">
+                    <template #default="props">
+                      <div class="flex file-row justify-center items-center">
+                        {{props.row.type}}
+                        <div class="ml-8px" v-if="props.row.type === 'select'">
+                          <el-popover placement="left" :width="400">
+                            <template #reference>
+                              <el-button size="small" link type="primary">
+                                <Icon icon="ep:more" />
+                              </el-button>
+                            </template>
+                            <el-table width="50%" :data="props.row.settingSelects" border size="small">
+                              <el-table-column align="center" label="key" prop="selectKey"/>
+                              <el-table-column align="center" label="name" prop="name"/>
+                            </el-table>
+                          </el-popover>
+                        </div>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column align="center" label="参数类型" prop="valueType"/>
+                  <el-table-column align="center" label="最大值" prop="max"/>
+                  <el-table-column align="center" label="最小值" prop="min"/>
+                  <!--                <el-table-column align="center" label="选项" width="50">-->
+                  <!--                  <template #default="props">-->
+                  <!--                    <div v-if="props.row.type === 'select'">-->
+                  <!--                      <el-popover placement="left" :width="400">-->
+                  <!--                        <template #reference>-->
+                  <!--                          <Icon icon="ep:more" />-->
+                  <!--                        </template>-->
+                  <!--                        <el-table width="50%" :data="props.row.settingSelects" border size="small">-->
+                  <!--                          <el-table-column align="center" label="key" prop="selectKey"/>-->
+                  <!--                          <el-table-column align="center" label="name" prop="name"/>-->
+                  <!--                        </el-table>-->
+                  <!--                      </el-popover>-->
+                  <!--                    </div>-->
+                  <!--                  </template>-->
+                  <!--                </el-table-column>-->
+                  <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="danger"
+                        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 MpkApi from '@/api/mpk/mpk'
   import {FormRules} from 'element-plus'
   import {getAccessToken, getTenantId} from "@/utils/auth";
-
+  import SettingForm from './SettingForm.vue'
+  import {generateUUID} from "@/utils";
 
   const {t} = useI18n() // 国际化
   const message = useMessage() // 消息弹窗
-
-  const dialogVisible = ref(false) // 弹窗的是否展示
-  const dialogTitle = ref('') // 弹窗的标题
+  const title = ref('') // 弹窗的标题
   const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
   const formType = ref('') // 表单的类型:create - 新增;update - 修改
+  const route = useRoute() // 路由
+  const router = useRouter();
+
+  /** settingForm弹窗 */
+  const settingFormRef = ref()
+  // 添加setting
+  const addSetting = (methodSettings) => {
+    settingFormRef.value.open(undefined,methodSettings)
+  }
+
+  // 修改setting
+  const updateSetting = (info) => {
+    settingFormRef.value.open(info)
+  }
+
+  const methodExpandedRowKeys = ref([])
+  const methodExpandChange = async (row: any, expandedRows: any[]) => {
+    methodExpandedRowKeys.value = expandedRows.map(e => e.id)
+  }
+
   const formData = ref({
-    id: undefined,
+    id: route.params.id,
+    pyChineseName: undefined,
     pyName: undefined,
     pkgName: undefined,
     pyType: undefined,
     className: undefined,
     pyModule: undefined,
+    icon: undefined,
+    menuName: undefined,
+    groupName: undefined,
     remark: undefined,
     modelMethods: [],
     filePath: undefined,
@@ -140,6 +285,9 @@
   const formRules = reactive<FormRules>({
     pyName: [
       {required: true, message: '模型名称不能为空,请上传模型文件', trigger: 'blur'}
+    ],
+    pyChineseName: [
+      {required: true, message: '模型中文名称不能为空', trigger: 'blur'}
     ],
     pyType: [
       {required: true, message: '模型类型不能为空', trigger: 'blur'}
@@ -153,30 +301,14 @@
     pyModule: [
       {required: true, message: '模型路径不能为空', trigger: 'blur'}
     ],
+    menuName: [
+      {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
-    resetForm()
-    // 修改时,设置数据
-    if (id) {
-      formLoading.value = true
-      try {
-        formData.value = await MpkApi.getMpk(id)
-      } finally {
-        formLoading.value = false
-      }
-    }
-  }
-  defineExpose({open}) // 提供 open 方法,用于打开弹窗
-
   /** 提交表单 */
-  const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
   const submitForm = async () => {
     // 校验表单
     if (!formRef) return
@@ -188,7 +320,7 @@
       return
     }
     // 模型方法名称校验
-    if (formData.value.modelMethods.some(e => e.methodName === undefined || e.methodName === '')) {
+    if (formData.value.modelMethods.some(e => e.methodName === undefined || e.methodName === '' || e.dataLength === undefined || e.dataLength === null)) {
       message.error('存在不合法模型方法名')
       return
     }
@@ -203,12 +335,11 @@
         await MpkApi.updateMpk(data)
         message.success(t('common.updateSuccess'))
       }
-      dialogVisible.value = false
-      // 发送操作成功的事件
-      emit('success')
     } finally {
       formLoading.value = false
     }
+    // router.push({path:'/model/mpk'})
+    router.back()
   }
 
   /** 重置表单 */
@@ -216,10 +347,14 @@
     formData.value = {
       id: undefined,
       pyName: undefined,
+      pyChineseName: undefined,
       pkgName: undefined,
       pyType: undefined,
       className: undefined,
       pyModule: undefined,
+      icon: undefined,
+      menuName: undefined,
+      groupName: undefined,
       remark: undefined,
       modelMethods: [],
       filePath: undefined
@@ -229,21 +364,16 @@
 
   const addRow = function () {
     formData.value.modelMethods.push({
+      id: generateUUID(),
       methodName: undefined,
       dataLength: 1,
-      model: 0
+      model: 0,
+      resultKey: undefined,
+      methodSettings: []
     })
   }
   const deleteRow = function (index) {
     formData.value.modelMethods.splice(index, 1)
-  }
-
-  // 模型方法下拉禁用
-  const methodSelectDisabled = (value) => {
-    if (formData.value.modelMethods.some(e => e.methodName === value)) {
-      return true;
-    }
-    return false;
   }
 
   const fileList = ref([]) // 文件列表
@@ -271,8 +401,64 @@
     }
     const data = response.data;
     formData.value.filePath = data.filePath
-    formData.value.pyName = data.fileName.replace('.pyd','')
+    formData.value.pyName = data.fileName.replace('.pyd', '')
     message.success('上传成功')
     uploadLoading.value = false
   }
+
+  onMounted(async () => {
+    const id = formData.value.id;
+    const type = id ? 'edit' : 'create'
+    title.value = t('action.' + type)
+    formType.value = type
+    resetForm()
+    // 修改时,设置数据
+    if (id) {
+      formLoading.value = true
+      try {
+        formData.value = await MpkApi.getMpk(id)
+      } finally {
+        formLoading.value = false
+      }
+    }
+  })
+
+  const pyTypeChange = () => {
+    if (formData.value.pyType === 'predict') {
+      formData.value.modelMethods = [
+        {
+          id: generateUUID(),
+          methodName: 'train',
+          dataLength: 1,
+          model: 0,
+          resultKey: undefined,
+          methodSettings: []
+        },
+        {
+
+          id: generateUUID(),
+          methodName: 'predict',
+          dataLength: 1,
+          model: 1,
+          resultKey: undefined,
+          methodSettings: []
+        }
+      ]
+      debugger
+    }else {
+      formData.value.modelMethods = [
+        {
+          id: generateUUID(),
+          methodName: 'schedul',
+          dataLength: 1,
+          model: 0,
+          resultKey: undefined,
+          methodSettings: []
+        }
+      ]
+    }
+  }
 </script>
+
+<style scoped lang="scss">
+</style>
diff --git a/src/views/mpk/SelectForm.vue b/src/views/mpk/SelectForm.vue
new file mode 100644
index 0000000..78f6890
--- /dev/null
+++ b/src/views/mpk/SelectForm.vue
@@ -0,0 +1,135 @@
+<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="key" prop="selectKey">
+            <el-input v-model="formData.settingKey" placeholder=""/>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="8">
+        <el-col :span="12">
+          <el-form-item label="name" prop="name">
+            <el-input v-model="formData.name" 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 * as ProjectApi from '@/api/mpk/project'
+  import * as MpkApi from '@/api/mpk/mpk'
+  import {FormRules} from 'element-plus'
+  import {generateUUID} from "@/utils";
+
+
+  const {t} = useI18n() // 国际化
+  const message = useMessage() // 消息弹窗
+
+  const dialogVisible = ref(false) // 弹窗的是否展示
+  const dialogTitle = ref('选项设置') // 弹窗的标题
+  const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+  const formData = ref({
+    settingKey: undefined,
+    name: undefined,
+    type: undefined,
+    valueType: undefined,
+    value: undefined,
+    max: undefined,
+    min: undefined,
+  })
+
+
+  const formRules = reactive<FormRules>({
+    settingKey: [
+      {required: true, message: 'key不能为空', trigger: 'blur'},
+    ],
+    name: [
+      {required: true, message: '参数名称不能为空', trigger: 'blur'},
+    ],
+    type: [
+      {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];
+        }
+      }else {
+        // 新增
+        const info = {...formData.value};
+        info.id = generateUUID()
+        methodSettingsRef.push(info)
+      }
+      dialogVisible.value = false
+    } finally {
+      formLoading.value = false
+    }
+  }
+
+  /** 重置表单 */
+  const resetForm = () => {
+    formData.value = {
+      settingKey: undefined,
+      name: undefined,
+      type: undefined,
+      valueType: undefined,
+      value: undefined,
+      max: undefined,
+      min: undefined,
+    }
+    formRef.value?.resetFields()
+  }
+</script>
diff --git a/src/views/mpk/SettingForm.vue b/src/views/mpk/SettingForm.vue
new file mode 100644
index 0000000..aa95209
--- /dev/null
+++ b/src/views/mpk/SettingForm.vue
@@ -0,0 +1,270 @@
+<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="key" prop="settingKey">
+            <el-input v-model="formData.settingKey" placeholder=""/>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="参数名称" prop="name">
+            <el-input v-model="formData.name" placeholder=""/>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="8">
+        <el-col :span="12">
+          <el-form-item label="输入类型" prop="type">
+            <el-select v-model="formData.type" @change="typeChange">
+              <el-option
+                v-for="item in getDictOptions(DICT_TYPE.MODEL_METHOD_SETTING_TYPE)"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </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"
+                :disabled="valueTypeSelectDisabled(item.value)"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <div v-if="formData.type === 'input'">
+        <el-row :gutter="8">
+          <el-col :span="8">
+            <el-form-item label="默认值" prop="value">
+              <el-input v-model="formData.value" placeholder=""/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="最大值" prop="max">
+              <el-input-number v-model="formData.max" placeholder=""/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="最小值" prop="min">
+              <el-input-number v-model="formData.min" placeholder=""/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </div>
+      <div v-if="formData.type === 'select'">
+        <el-divider content-position="left">选项信息</el-divider>
+        <el-row :gutter="8">
+          <el-col :span="4">
+            <el-button type="primary" size="small" @click="addRow()">新增</el-button>
+          </el-col>
+        </el-row>
+        <el-table :data="formData.settingSelects" border>
+          <el-table-column
+            prop=""
+            label="key"
+            align="center">
+            <template #default="scope">
+              <el-input size="small" v-model="scope.row.selectKey" maxlength="50" clearable />
+            </template>
+          </el-table-column>
+          <el-table-column
+            prop=""
+            label="name"
+            align="center">
+            <template #default="scope">
+              <el-input size="small" v-model="scope.row.name" 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"
+                link
+              >删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </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 * as ProjectApi from '@/api/mpk/project'
+  import * as MpkApi from '@/api/mpk/mpk'
+  import {FormRules} from 'element-plus'
+  import {generateUUID} from "@/utils";
+  import {func} from "vue-types";
+
+
+  const {t} = useI18n() // 国际化
+  const message = useMessage() // 消息弹窗
+
+  const dialogVisible = ref(false) // 弹窗的是否展示
+  const dialogTitle = ref('参数设置') // 弹窗的标题
+  const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+  const formData = ref({
+    settingKey: undefined,
+    name: undefined,
+    type: undefined,
+    valueType: undefined,
+    value: undefined,
+    max: undefined,
+    min: undefined,
+    settingSelects: []
+  })
+
+
+  const formRules = reactive<FormRules>({
+    settingKey: [
+      {required: true, message: 'key不能为空', trigger: 'blur'},
+    ],
+    name: [
+      {required: true, message: '参数名称不能为空', trigger: 'blur'},
+    ],
+    type: [
+      {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
+
+    //校验select
+    if (formData.value.type === 'select') {
+      if (formData.value.settingSelects?.length === 0) {
+        message.error('选项为空');
+        return
+      }
+    }
+
+    // 提交请求
+    formLoading.value = true
+    try {
+      if (infoRef) {
+        // 修改
+        for (let key in formData.value) {
+          infoRef[key] = formData.value[key];
+        }
+      }else {
+        // 新增
+        methodSettingsRef.push({...formData.value})
+      }
+      dialogVisible.value = false
+    } finally {
+      formLoading.value = false
+    }
+  }
+
+  /** 重置表单 */
+  const resetForm = () => {
+    formData.value = {
+      settingKey: undefined,
+      name: undefined,
+      type: undefined,
+      valueType: undefined,
+      value: undefined,
+      max: undefined,
+      min: undefined,
+      settingSelects: []
+    }
+    formRef.value?.resetFields()
+  }
+
+  const valueTypeSelectDisabled = (value) => {
+    const type = formData.value.type;
+    switch (type) {
+      case "input":
+        if (['int','decimal','decimalArray','string'].includes(value)) {
+          return false
+        }else {
+          return true
+        }
+      case "file":
+        if (['file'].includes(value)) {
+          return false
+        }else {
+          return true
+        }
+      case "select":
+        if (['int','string'].includes(value)) {
+          return false
+        }else {
+          return true
+        }
+      default :
+        return true
+    }
+  }
+
+  const typeChange = () => {
+    formData.value.valueType = undefined
+    formData.value.value = undefined
+    formData.value.max = undefined
+    formData.value.min = undefined
+    formData.value.settingSelects = []
+  }
+
+  const addRow = function () {
+    formData.value.settingSelects.push({
+      selectKey: '',
+      name: ''
+    })
+  }
+  const deleteRow = function (index) {
+    formData.value.settingSelects.splice(index, 1)
+  }
+</script>
diff --git a/src/views/mpk/mpk.vue b/src/views/mpk/mpk.vue
index 9354e60..fa4fb84 100644
--- a/src/views/mpk/mpk.vue
+++ b/src/views/mpk/mpk.vue
@@ -25,15 +25,13 @@
           <Icon icon="ep:refresh" class="mr-5px"/>
           重置
         </el-button>
-        <el-button
-          type="primary"
-          plain
-          @click="openForm('create')"
-          v-hasPermi="['mpk:create']"
-        >
-          <Icon icon="ep:plus" class="mr-5px"/>
-          新增
-        </el-button>
+        <div class="ml-12px">
+          <router-link :to="'/mpk/form'">
+            <el-button type="primary" plain v-hasPermi="['mpk:create']">
+              <Icon icon="ep:plus" class="mr-5px"/>新增</el-button>
+          </router-link>
+        </div>
+
       </el-form-item>
     </el-form>
   </ContentWrap>
@@ -45,17 +43,21 @@
       :data="list"
       row-key="id"
     >
+      <el-table-column prop="pyChineseName" label="模型中文名称"/>
       <el-table-column prop="pyName" label="模型名称"/>
-      <el-table-column prop="pkgName" label="包名"/>
-      <el-table-column prop="pyModule" label="模型路径" width="200px"/>
-      <el-table-column prop="remark" label="备注" width="300px"/>
+      <el-table-column prop="pyType" label="模型类型" :formatter="(r,c,v) => getDictLabel(DICT_TYPE.MODEL_TYPE,v)"/>
+      <el-table-column prop="menuName" label="所属菜单" width="120px"/>
+      <el-table-column prop="groupName" label="所属组" width="120px"/>
+      <el-table-column prop="remark" label="备注" width="200px"/>
       <el-table-column prop="createDate" label="创建时间" :formatter="dateFormatter" width="170px"/>
       <el-table-column label="操作" align="center" width="200px">
         <template #default="scope">
           <div class="flex items-center justify-center">
-            <el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['mpk:update']">
-              <Icon icon="ep:edit"/>修改
-            </el-button>
+            <router-link :to="'/mpk/form/' + scope.row.id">
+              <el-button type="primary" link v-hasPermi="['mpk:update']">
+                <Icon icon="ep:edit"/>修改
+              </el-button>
+            </router-link>
             <el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['mpk:delete']">
               <Icon icon="ep:delete"/>删除
             </el-button>
@@ -98,8 +100,6 @@
     />
   </ContentWrap>
 
-  <!-- 表单弹窗:添加/修改 -->
-  <MpkForm ref="formRef" @success="getList"/>
   <MpkGenerator ref="mpkGenerator"/>
   <GeneratorCodeHistory ref="generatorCodeHistory"/>
   <MpkRun ref="mpkRun"/>
@@ -107,11 +107,12 @@
 <script lang="ts" setup>
   import {dateFormatter} from '@/utils/formatTime'
   import * as MpkApi from '@/api/mpk/mpk'
-  import MpkForm from './MpkForm.vue'
   import MpkGenerator from './MpkGenerator.vue'
   import GeneratorCodeHistory from './MpkGeneratorHistory.vue'
   import MpkRun from './MpkRun.vue'
   import * as UserApi from "@/api/system/user";
+  import { DICT_TYPE, getDictLabel } from '@/utils/dict'
+  import {useAppStoreWithOut} from "@/store/modules/app";
 
   defineOptions({name: 'Mpk'})
 
@@ -183,12 +184,6 @@
     handleQuery()
   }
 
-  /** 添加/修改操作 */
-  const formRef = ref()
-  const openForm = (type: string, id?: number) => {
-    formRef.value.open(type, id)
-  }
-
   /** 删除按钮操作 */
   const handleDelete = async (id: number) => {
     try {
@@ -203,6 +198,10 @@
     }
   }
 
+  onActivated((to) => {
+    getList()
+  })
+
   /** 初始化 **/
   onMounted(async () => {
     await getList()

--
Gitblit v1.9.3