对比新文件 |
| | |
| | | <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="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 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: 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, |
| | | }) |
| | | |
| | | const formRules = reactive<FormRules>({ |
| | | pyName: [ |
| | | {required: true, message: '模型名称不能为空,请上传模型文件', trigger: 'blur'} |
| | | ], |
| | | pyChineseName: [ |
| | | {required: true, message: '模型中文名称不能为空', trigger: 'blur'} |
| | | ], |
| | | pyType: [ |
| | | {required: true, message: '模型类型不能为空', trigger: 'blur'} |
| | | ], |
| | | pkgName: [ |
| | | {required: true, message: '包名不能为空', trigger: 'blur'} |
| | | ], |
| | | className: [ |
| | | {required: true, message: '类名不能为空', trigger: 'blur'} |
| | | ], |
| | | pyModule: [ |
| | | {required: true, message: '模型路径不能为空', trigger: 'blur'} |
| | | ], |
| | | menuName: [ |
| | | {required: true, message: '所属目录不能为空', 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 as unknown as MpkApi.MpkVO |
| | | if (formType.value === 'create') { |
| | | await MpkApi.createMpk(data) |
| | | message.success(t('common.createSuccess')) |
| | | } else { |
| | | await MpkApi.updateMpk(data) |
| | | message.success(t('common.updateSuccess')) |
| | | } |
| | | } finally { |
| | | formLoading.value = false |
| | | } |
| | | // router.push({path:'/model/mpk'}) |
| | | router.back() |
| | | } |
| | | |
| | | /** 重置表单 */ |
| | | const resetForm = () => { |
| | | 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 |
| | | } |
| | | formRef.value?.resetFields() |
| | | } |
| | | |
| | | const addRow = function () { |
| | | formData.value.modelMethods.push({ |
| | | id: generateUUID(), |
| | | methodName: undefined, |
| | | dataLength: 1, |
| | | model: 0, |
| | | resultKey: undefined, |
| | | 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/mpk/file/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.filePath = data.filePath |
| | | 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> |
对比新文件 |
| | |
| | | <template> |
| | | <Dialog v-model="dialogVisible" :title="dialogTitle"> |
| | | <el-input |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="备注" |
| | | v-model="remark"/> |
| | | <div style="width: 100%;display: flex;flex-direction: row;justify-content: end;margin-top: 16px"> |
| | | <el-button @click="generatorCode()" type="primary">生成</el-button> |
| | | </div> |
| | | </Dialog> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import * as MpkApi from '@/api/mpk/mpk' |
| | | import download from "@/utils/download"; |
| | | import {formatToDateString} from "@/utils/dateUtil"; |
| | | |
| | | |
| | | const { t } = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('生成代码') // 弹窗的标题 |
| | | |
| | | const remark = ref('') |
| | | const id = ref() |
| | | const zipFileName = ref() |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (modelId: string,pyName: string) => { |
| | | dialogVisible.value = true |
| | | id.value = modelId; |
| | | zipFileName.value = pyName + '_' + formatToDateString(new Date()) + '.zip'; |
| | | remark.value = ""; |
| | | } |
| | | defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | /** 提交表单 */ |
| | | const generatorCode = async () => { |
| | | const param = { |
| | | 'id': id.value, |
| | | 'remark': remark.value, |
| | | 'zipFileName': zipFileName.value |
| | | } |
| | | const data = await MpkApi.generatorCode(param) |
| | | download.zip(data, zipFileName.value) |
| | | dialogVisible.value = false |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <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 prop="startTime"> |
| | | <el-date-picker |
| | | v-model="queryParams.startTime" |
| | | type="datetime" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | placeholder="选择日期时间"/> |
| | | </el-form-item> |
| | | <el-form-item prop="endTime"> |
| | | <el-date-picker |
| | | v-model="queryParams.endTime" |
| | | type="datetime" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | placeholder="选择日期时间"/> |
| | | </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 label="文件名" header-align="center" align="center"> |
| | | <template #default="scope"> |
| | | <a style="cursor: pointer;color: #409eff" @click="downloadHistory(scope.row.id,scope.row.fileName)">{{ scope.row.fileName }}</a> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="remark" label="备注" header-align="center" align="center"/> |
| | | <el-table-column prop="createTime" label="生成时间" :formatter="dateFormatter" header-align="center" align="center" width="200"/> |
| | | </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 HistoryApi from "@/api/mpk/mpkHistory"; |
| | | import { dateFormatter } from '@/utils/formatTime' |
| | | |
| | | |
| | | 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, |
| | | mdkId: '', |
| | | startTime: undefined, |
| | | endTime: undefined, |
| | | }) |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (mdkId: String) => { |
| | | dialogVisible.value = true |
| | | queryParams.mdkId = mdkId; |
| | | queryParams.startTime = undefined; |
| | | queryParams.endTime = undefined; |
| | | getList() |
| | | } |
| | | defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const data = await HistoryApi.getPage(queryParams) |
| | | list.value = data.list |
| | | total.value = data.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | const downloadHistory = async (id,fileName) => { |
| | | const param = { |
| | | 'id': id, |
| | | } |
| | | const data = await HistoryApi.download(param) |
| | | download.zip(data, fileName) |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <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-form-item label="全类名" style="width: 90%" prop="className"> |
| | | <el-input v-model="formData.className" placeholder=""/> |
| | | </el-form-item> |
| | | <el-form-item label="方法名" prop="methodName"> |
| | | <el-select v-model="formData.methodName" @change="methodChange" style="width: 240px"> |
| | | <el-option |
| | | v-for="item in methodList" |
| | | :key="item.id" |
| | | :label="item.methodName" |
| | | :value="item.methodName" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-divider content-position="left">模型参数信息</el-divider> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="2" style="margin-bottom: 10px;margin-left: 20px"> |
| | | <el-button tag="a" href="/template/模型参数导入模板.xlsx" download="模型参数导入模板.xlsx" style="text-decoration: none;" type="primary" size="small" link>模板下载</el-button> |
| | | </el-col> |
| | | <el-col :span="2" style="margin-bottom: 10px;"> |
| | | <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> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row v-for="(item,index) in formData.datas" :key="index" :gutter="20"> |
| | | <el-col :span="20"> |
| | | <el-form-item :label="'参数_' + (index)" required style="width: 100%"> |
| | | <el-input v-model="formData.datas[index]" placeholder="" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row v-if="hasModel" :gutter="20"> |
| | | <el-col :span="20"> |
| | | <el-form-item label="model" required style="width: 100%"> |
| | | <el-input v-model="formData.model" 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" 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" 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> |
| | | <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 MpkApi from '@/api/mpk/mpk' |
| | | import {FormRules} from "element-plus"; |
| | | import {getAccessToken, getTenantId} from "@/utils/auth"; |
| | | |
| | | const { t } = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('模型运行') // 弹窗的标题 |
| | | |
| | | const formData = reactive({ |
| | | className: '', |
| | | methodName: '', |
| | | datas: [], |
| | | modelSettings: [], |
| | | model: undefined |
| | | }) |
| | | |
| | | // 模型方法下拉列表 |
| | | const methodList = ref([]) |
| | | const hasModel = ref(false) |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (row) => { |
| | | dialogVisible.value = true |
| | | formData.className = row.pkgName + '.impl.' + row.pyName + 'Impl'; |
| | | const mpk = await MpkApi.getMpk(row.id) |
| | | methodList.value = mpk.modelMethods |
| | | formData.methodName = mpk.modelMethods[0].methodName |
| | | formData.datas = [] |
| | | for (let i = 0 ; i < mpk.modelMethods[0].dataLength ; i++) { |
| | | formData.datas[i] = '[[]]' |
| | | } |
| | | hasModel.value = mpk.modelMethods[0].model === 1 |
| | | } |
| | | 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) { |
| | | formData.datas = [] |
| | | for (let i = 0 ; i < methodList.value.find(e => e.methodName === value)?.dataLength ; i++) { |
| | | formData.datas[i] = '[[]]' |
| | | } |
| | | hasModel.value = methodList.value.find(e => e.methodName === value)?.model === 1 |
| | | } |
| | | |
| | | const fileList = ref([]) // 文件列表 |
| | | const importUrl = |
| | | import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/model/mpk/api/import' |
| | | const formLoading = ref(false) // 表单的加载中 |
| | | const uploadHeaders = ref() // 上传 Header 头 |
| | | /** 上传错误提示 */ |
| | | const submitFormError = (): void => { |
| | | message.error('导入失败,请检查导入文件!') |
| | | formLoading.value = false |
| | | } |
| | | const submitFormSuccess = (response: any) => { |
| | | if (response.code !== 0) { |
| | | message.error(response.msg) |
| | | formLoading.value = false |
| | | return |
| | | } |
| | | const datas = response.data; |
| | | for (let i=0;i<formData.datas.length;i++) { |
| | | formData.datas[i] = datas[i] |
| | | } |
| | | message.success('导入成功') |
| | | 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 () => { |
| | | // 校验表单 |
| | | 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 |
| | | data.hasModel = hasModel.value |
| | | if (data.hasModel && data.model) { |
| | | data.model = {model_path:data.model} |
| | | }else { |
| | | data.model = undefined |
| | | } |
| | | |
| | | modelRunResult.value = await MpkApi.modelRun(data) |
| | | modelRunloading.value = false |
| | | message.success('运行成功') |
| | | } finally { |
| | | modelRunloading.value = false |
| | | } |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <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> |
对比新文件 |
| | |
| | | <template> |
| | | <!-- 搜索工作栏 --> |
| | | <ContentWrap> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="queryParams" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | > |
| | | <el-form-item label="模型名称" prop="pyName"> |
| | | <el-input |
| | | v-model="queryParams.pyName" |
| | | 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="'/mpk/form'"> |
| | | <el-button type="primary" plain v-hasPermi="['mpk:file: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="pyChineseName" label="模型中文名称"/> |
| | | <el-table-column prop="pyName" label="模型名称"/> |
| | | <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"> |
| | | <router-link :to="'/mpk/form/' + scope.row.id"> |
| | | <el-button type="primary" link v-hasPermi="['mpk:file:update']"> |
| | | <Icon icon="ep:edit"/>修改 |
| | | </el-button> |
| | | </router-link> |
| | | <el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['mpk:file: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="generatorCode" |
| | | > |
| | | 生成代码 |
| | | </el-dropdown-item> |
| | | <el-dropdown-item |
| | | command="generatorHistory" |
| | | > |
| | | 生成历史 |
| | | </el-dropdown-item> |
| | | <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.pageSize" |
| | | v-model:page="queryParams.page" |
| | | :total="total" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | |
| | | <MpkGenerator ref="mpkGenerator"/> |
| | | <GeneratorCodeHistory ref="generatorCodeHistory"/> |
| | | <MpkRun ref="mpkRun"/> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import {dateFormatter} from '@/utils/formatTime' |
| | | import * as MpkApi from '@/api/mpk/mpk' |
| | | 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: 'MpkFile'}) |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const {t} = useI18n() // 国际化 |
| | | |
| | | const loading = ref(true) // 列表的加载中 |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 字典表格数据 |
| | | const queryParams = reactive({ |
| | | page: 1, |
| | | pageSize: 10, |
| | | pyName: '' |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const data = await MpkApi.getPage(queryParams) |
| | | list.value = data.list |
| | | total.value = data.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 操作分发 */ |
| | | const handleCommand = (command: string, row) => { |
| | | switch (command) { |
| | | case 'generatorCode': |
| | | generatorCode(row.id,row.pyName) |
| | | break |
| | | case 'generatorHistory': |
| | | generatorHistory(row.id) |
| | | break |
| | | case 'mpkRunDialog': |
| | | mpkRunDialog(row) |
| | | break |
| | | default: |
| | | break |
| | | } |
| | | } |
| | | |
| | | const mpkGenerator = ref(); |
| | | const generatorCode = (id,pyName) => { |
| | | mpkGenerator.value.open(id,pyName); |
| | | } |
| | | |
| | | const generatorCodeHistory = ref(); |
| | | const generatorHistory = (id) => { |
| | | generatorCodeHistory.value.open(id); |
| | | } |
| | | |
| | | const mpkRun = ref(); |
| | | const mpkRunDialog = (row) => { |
| | | mpkRun.value.open(row); |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | getList() |
| | | } |
| | | |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryParams.page = 1 |
| | | queryFormRef.value.resetFields() |
| | | handleQuery() |
| | | } |
| | | |
| | | /** 删除按钮操作 */ |
| | | const handleDelete = async (id: number) => { |
| | | try { |
| | | // 删除的二次确认 |
| | | await message.delConfirm() |
| | | // 发起删除 |
| | | await MpkApi.deleteMpk(id) |
| | | message.success(t('common.delSuccess')) |
| | | // 刷新列表 |
| | | await getList() |
| | | } catch { |
| | | } |
| | | } |
| | | |
| | | onActivated((to) => { |
| | | getList() |
| | | }) |
| | | |
| | | /** 初始化 **/ |
| | | onMounted(async () => { |
| | | await getList() |
| | | }) |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <Dialog v-model="dialogVisible" :title="dialogTitle"> |
| | | <el-form |
| | | ref="formRef" |
| | | v-loading="formLoading" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="80px" |
| | | > |
| | | <el-row :gutter="20"> |
| | | <el-col :span="20"> |
| | | <el-form-item label="项目名称" prop="projectName" style="width: 100%"> |
| | | <el-input v-model="formData.projectName" placeholder="" style="width: 100%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="20"> |
| | | <el-form-item label="项目编码" prop="projectCode" style="width: 100%"> |
| | | <el-input v-model="formData.projectCode" placeholder="" style="width: 100%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col> |
| | | <el-form-item label="关联模型" prop="models"> |
| | | <el-transfer :props="{key: 'id',label: 'pyName'}" :titles="['未选模型', '已选模型']" target-order="unshift" filterable :filter-method="filterMethod" v-model="formData.models" :data="modelList"> |
| | | <template #default="{ option }"> |
| | | <span :title="option.pyName">{{ option.pyName}}</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/mpk/project' |
| | | import * as MpkApi from '@/api/mpk/mpk' |
| | | 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, |
| | | }) |
| | | |
| | | |
| | | 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 |
| | | } |
| | | 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 MpkApi.list() |
| | | } |
| | | |
| | | // 模型筛选 |
| | | const filterMethod = function (query, item) { |
| | | return item.pyName.toLowerCase().indexOf(query.toLowerCase()) !== -1 |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | :deep(.el-transfer-panel) { |
| | | width: 35%; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <Dialog v-model="dialogVisible" :title="dialogTitle"> |
| | | <el-form |
| | | ref="formRef" |
| | | v-loading="formLoading" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="80px" |
| | | > |
| | | <el-row> |
| | | <el-col :span="8"> |
| | | <el-form-item label="版本号" prop="version"> |
| | | <el-input v-model="formData.version" placeholder="请输入版本号"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="更新日志" prop="log"> |
| | | <el-input type="textarea" :rows="4" placeholder="请输入更新日志" v-model="formData.log"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row justify="end"> |
| | | <el-col :span="3"> |
| | | <el-button @click="packageProject()" type="primary">打包</el-button> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </Dialog> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import * as ProjectApi from '@/api/mpk/project' |
| | | import download from "@/utils/download"; |
| | | import {FormRules} from "element-plus"; |
| | | import {formatToDateString} from "@/utils/dateUtil"; |
| | | |
| | | |
| | | const { t } = useI18n() // 国际化 |
| | | const message = useMessage() // 消息弹窗 |
| | | |
| | | const dialogVisible = ref(false) // 弹窗的是否展示 |
| | | const dialogTitle = ref('打包') // 弹窗的标题 |
| | | const formLoading = ref(false) // 表单的加载中 |
| | | |
| | | const formRules = reactive<FormRules>({ |
| | | version: [ |
| | | {required: true, message: '版本号不能为空', trigger: 'blur'}, |
| | | ], |
| | | log: [ |
| | | {required: true, message: '更新日志不能为空', trigger: 'blur'}, |
| | | ] |
| | | }) |
| | | |
| | | const formData = reactive({ |
| | | log: undefined, |
| | | projectId: undefined, |
| | | projectName: undefined, |
| | | projectCode: undefined, |
| | | ids: undefined, |
| | | version: undefined, |
| | | }) |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (projectId,projectName,projectCode,ids) => { |
| | | dialogVisible.value = true |
| | | formData.projectId = projectId |
| | | formData.projectName = projectName |
| | | formData.projectCode = projectCode |
| | | formData.ids = ids |
| | | formData.log = undefined |
| | | formData.version = 'V' |
| | | } |
| | | defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | const formRef = ref() // 表单 Ref |
| | | /** 提交表单 */ |
| | | const packageProject = async () => { |
| | | // 校验表单 |
| | | try { |
| | | if (!formRef) return |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) return |
| | | |
| | | formLoading.value = true |
| | | formData.zipFileName = 'IAILMPK.' + formData.projectCode + '.' + formatToDateString(new Date()) + '.zip' |
| | | const data = await ProjectApi.packageProject(formData) |
| | | debugger |
| | | download.zip(data, formData.zipFileName) |
| | | formLoading.value = false |
| | | dialogVisible.value = false |
| | | } catch (e) { |
| | | formLoading.value = false |
| | | } |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <ContentWrap> |
| | | <el-form |
| | | class="-mb-15px" |
| | | :model="queryParams" |
| | | ref="queryFormRef" |
| | | :inline="true" |
| | | label-width="68px" |
| | | > |
| | | <el-form-item label="项目名称" prop="projectId"> |
| | | <el-select v-model="queryParams.projectId" class="!w-240px"> |
| | | <el-option |
| | | v-for="item in projectList" |
| | | :key="item.id" |
| | | :label="item.projectName" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="开始时间" prop="startTime"> |
| | | <el-date-picker |
| | | v-model="queryParams.startTime" |
| | | type="datetime" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | placeholder="选择日期时间"/> |
| | | </el-form-item> |
| | | <el-form-item label="结束时间" prop="endTime"> |
| | | <el-date-picker |
| | | v-model="queryParams.endTime" |
| | | type="datetime" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | placeholder="选择日期时间"/> |
| | | </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-form-item> |
| | | </el-form> |
| | | </ContentWrap> |
| | | |
| | | <!-- 列表 --> |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column label="文件名" header-align="center" align="center" width="400"> |
| | | <template #default="scope"> |
| | | <a style="cursor: pointer;color: #409eff" |
| | | @click="downloadHistory(scope.row.filePath,scope.row.fileName)">{{ scope.row.fileName |
| | | }}</a> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="version" label="版本号" header-align="center" align="center" width="200"/> |
| | | <el-table-column prop="log" label="更新日志" header-align="center" align="center"/> |
| | | <el-table-column prop="createTime" label="打包时间" :formatter="dateFormatter" header-align="center" align="center" width="200"/> |
| | | <el-table-column label="操作" align="center" width="230px"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="viewPackageModel(scope.row.id)" |
| | | > |
| | | <Icon icon="ep:link"/> |
| | | 查看关联模型 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | :total="total" |
| | | v-model:page="queryParams.pageNo" |
| | | v-model:limit="queryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | |
| | | <PackageModel ref="packageModelRef"/> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import download from "@/utils/download"; |
| | | import * as PackageHistoryApi from '@/api/mpk/projectPackageHistory' |
| | | import * as ProjectApi from '@/api/mpk/project' |
| | | import {dateFormatter} from '@/utils/formatTime' |
| | | import PackageModel from './ProjectPackageModelDialog.vue' |
| | | |
| | | defineOptions({name: 'ProjectPackageHistory'}) |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const {t} = useI18n() // 国际化 |
| | | const route = useRoute() // 路由 |
| | | |
| | | const loading = ref(true) // 列表的加载中 |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 列表的数据 |
| | | const queryParams = reactive({ |
| | | pageNo: 1, |
| | | pageSize: 10, |
| | | projectId: route.params.projectId, |
| | | startTime: undefined, |
| | | endTime: undefined, |
| | | }) |
| | | const queryFormRef = ref() // 搜索的表单 |
| | | const projectList = ref() // 字典类型的列表 |
| | | |
| | | /** 查询列表 */ |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | const data = await PackageHistoryApi.getPage(queryParams) |
| | | list.value = data.list |
| | | total.value = data.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | queryParams.pageNo = 1 |
| | | getList() |
| | | } |
| | | |
| | | /** 重置按钮操作 */ |
| | | const resetQuery = () => { |
| | | queryFormRef.value.resetFields() |
| | | handleQuery() |
| | | } |
| | | |
| | | const downloadHistory = async (filePath,fileName) => { |
| | | const param = { |
| | | filePath, |
| | | fileName, |
| | | } |
| | | const data = await PackageHistoryApi.download(param) |
| | | download.zip(data, fileName) |
| | | } |
| | | |
| | | const packageModelRef = ref() |
| | | const viewPackageModel = (id) => { |
| | | packageModelRef.value.open('package',id) |
| | | } |
| | | |
| | | /** 初始化 **/ |
| | | onMounted(async () => { |
| | | await getList() |
| | | // 查询字典(精简)列表 |
| | | projectList.value = await ProjectApi.list() |
| | | }) |
| | | </script> |
对比新文件 |
| | |
| | | <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="pyName"> |
| | | <el-input |
| | | v-model="queryParams.pyName" |
| | | 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="pyName" label="模型名称"/> |
| | | <el-table-column prop="pkgName" label="包名"/> |
| | | <el-table-column prop="pyModule" label="模型路径" width="300px"/> |
| | | <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="methodName" /> |
| | | <el-table-column align="center" label="参数长度" prop="dataLength" /> |
| | | <el-table-column align="center" label="是否有model" prop="model" :formatter="(row,column,cellValue) => cellValue === 1 ? 'true' : 'false'" /> |
| | | </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 projectHistoryApi from '@/api/mpk/projectPackageHistory' |
| | | import * as projectApi from '@/api/mpk/project' |
| | | import { dateFormatter } from '@/utils/formatTime' |
| | | |
| | | |
| | | 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, |
| | | packageHistoryId: undefined, |
| | | projectId: undefined, |
| | | pyName: undefined, |
| | | }) |
| | | |
| | | const dialogType = ref('') |
| | | |
| | | /** 打开弹窗 */ |
| | | const open = async (type: String,id: String) => { |
| | | dialogVisible.value = true |
| | | dialogType.value = type |
| | | |
| | | if (dialogType.value === 'package') { |
| | | queryParams.packageHistoryId = id; |
| | | }else if (dialogType.value === 'project') { |
| | | queryParams.projectId = id; |
| | | } |
| | | |
| | | queryParams.pyName = undefined; |
| | | getList() |
| | | } |
| | | defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
| | | |
| | | const getList = async () => { |
| | | loading.value = true |
| | | try { |
| | | let data = undefined; |
| | | if (dialogType.value === 'package') { |
| | | data = await projectHistoryApi.getPackageModel(queryParams) |
| | | data.list.forEach(e => { |
| | | e.modelMethods = JSON.parse(e.methodInfo) |
| | | }) |
| | | }else if (dialogType.value === 'project') { |
| | | data = await projectApi.getProjectModel(queryParams) |
| | | } |
| | | |
| | | list.value = data.list |
| | | total.value = data.total |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <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> |
对比新文件 |
| | |
| | | <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="packageModel" |
| | | > |
| | | <el-button link>打包</el-button> |
| | | </el-dropdown-item> |
| | | <el-dropdown-item |
| | | > |
| | | <router-link :to="'/project/package/history/' + scope.row.id"> |
| | | <el-button link>打包历史</el-button> |
| | | </router-link> |
| | | </el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </template> |
| | | </el-dropdown> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | v-model:limit="queryParams.pageSize" |
| | | v-model:page="queryParams.page" |
| | | :total="total" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | |
| | | <!-- 表单弹窗:添加/修改 --> |
| | | <ProjectForm ref="formRef" @success="getList"/> |
| | | <ProjectPackage ref="projectPackageRef"/> |
| | | <RelevanceModel ref="relevanceModelRef"/> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import {dateFormatter} from '@/utils/formatTime' |
| | | import * as ProjectApi from '@/api/mpk/project' |
| | | import ProjectForm from './ProjectForm.vue' |
| | | import ProjectPackage from './ProjectPackage.vue' |
| | | import RelevanceModel from './ProjectPackageModelDialog.vue' |
| | | |
| | | defineOptions({name: 'MpkProject'}) |
| | | |
| | | const message = useMessage() // 消息弹窗 |
| | | const {t} = useI18n() // 国际化 |
| | | |
| | | const loading = ref(true) // 列表的加载中 |
| | | const total = ref(0) // 列表的总页数 |
| | | const list = ref([]) // 字典表格数据 |
| | | const queryParams = reactive({ |
| | | page: 1, |
| | | pageSize: 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 'packageModel': |
| | | packageModel(row.id, row.projectName, row.projectCode, row.models) |
| | | break |
| | | default: |
| | | break |
| | | } |
| | | } |
| | | |
| | | //打包 |
| | | const projectPackageRef = ref(); |
| | | const packageModel = (projectId, projectName, projectCode, models) => { |
| | | let ids = models.map(e => e.id); |
| | | if (ids && ids.length > 0) { |
| | | projectPackageRef.value.open(projectId, projectName, projectCode, ids.join(",")); |
| | | } else { |
| | | message.error("请先为项目添加模型!") |
| | | } |
| | | } |
| | | |
| | | /** 搜索按钮操作 */ |
| | | 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('project',id) |
| | | } |
| | | |
| | | /** 初始化 **/ |
| | | onMounted(async () => { |
| | | await getList() |
| | | }) |
| | | </script> |