提交代码

This commit is contained in:
jiang 2024-12-15 17:33:04 +08:00
parent 7bd8f1d02f
commit 4014e2918a
10 changed files with 350 additions and 129 deletions

View File

@ -9,6 +9,14 @@ export function listManager(query) {
}) })
} }
export function listAll(query) {
return request({
url: '/ai/model/listAll',
method: 'get',
params: query
})
}
// 查询镜像管理详细 // 查询镜像管理详细
export function getManager(id) { export function getManager(id) {
return request({ return request({
@ -42,3 +50,15 @@ export function delManager(id) {
method: 'post' method: 'post'
}) })
} }
export function uploadFile(formData) {
return request({
url: '/ai/mirror/uploadFile',
method: 'post',
data: formData,
timeout: 600000, // 设置超时时间为 10 秒10000 毫秒)
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}

View File

@ -0,0 +1,18 @@
export default {
bind(el, binding) {
const debounce = (func, delay) => {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => func.apply(this, args), delay);
};
};
el.addEventListener('click', debounce(() => {
binding.value();
}, binding.arg || 300)); // 默认延迟300ms
},
unbind(el) {
el.removeEventListener('click', el._debounceClick);
},
};

View File

@ -37,7 +37,9 @@ import DictTag from '@/components/DictTag'
import VueMeta from 'vue-meta' import VueMeta from 'vue-meta'
// 字典数据组件 // 字典数据组件
import DictData from '@/components/DictData' import DictData from '@/components/DictData'
import debounce from './directives/debounce';
// 全局方法挂载
Vue.directive('debounce', debounce);
// 全局方法挂载 // 全局方法挂载
Vue.prototype.getDicts = getDicts Vue.prototype.getDicts = getDicts
Vue.prototype.getConfigKey = getConfigKey Vue.prototype.getConfigKey = getConfigKey

View File

@ -94,7 +94,7 @@
</div> </div>
</el-form> </el-form>
<template #footer> <template #footer>
<el-button type="primary" @click="submitForm"> </el-button> <el-button type="primary" v-debounce:500="submitForm"> </el-button>
<el-button @click="cancel"> </el-button> <el-button @click="cancel"> </el-button>
</template> </template>
</el-dialog> </el-dialog>

View File

@ -19,7 +19,7 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<el-button type="primary" @click="submitForm"> </el-button> <el-button type="primary" v-debounce:500="submitForm"> </el-button>
<el-button @click="cancel"> </el-button> <el-button @click="cancel"> </el-button>
</template> </template>
</el-dialog> </el-dialog>

View File

@ -31,7 +31,7 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<el-button type="primary" @click="submitForm"> </el-button> <el-button type="primary" v-debounce:500="submitForm"> </el-button>
<el-button @click="cancel"> </el-button> <el-button @click="cancel"> </el-button>
</template> </template>
</el-dialog> </el-dialog>

View File

@ -57,7 +57,6 @@
<dict-tag :options="dict.type.ai_annotate_type" :value="scope.row.annotationType"/> <dict-tag :options="dict.type.ai_annotate_type" :value="scope.row.annotationType"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="已审核数量" align="center" show-overflow-tooltip prop="auditedCount" min-width="100" />
<el-table-column label="操作" align="center" min-width="100" class-name="small-padding fixed-width" > <el-table-column label="操作" align="center" min-width="100" class-name="small-padding fixed-width" >
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button

View File

@ -28,12 +28,21 @@
:visible.sync="drawer" :visible.sync="drawer"
:before-close="handleClose" :before-close="handleClose"
:close-on-click-modal="false" :close-on-click-modal="false"
:wrapper-closable="false"> :wrapper-closable="false"
>
<!-- 显示所有文件的上传进度 --> <!-- 显示所有文件的上传进度 -->
<div v-for="([filename, progress], index) in Object.entries(uploadProgress)" :key="index" style="padding-left: 20px;padding-right: 20px"> <div v-for="([filename, progress], index) in Object.entries(uploadProgress)" :key="index"
<div style="display: flex;flex-direction: row;align-items: center;justify-content: flex-start;margin-bottom: 10px"> style="padding-left: 20px;padding-right: 20px"
<i v-if="progress ===100 && !uploadFailed[filename]" style="color: #13ce66;font-size: 18px" class="el-icon-success"></i> >
<i v-if="progress !==100 && !uploadFailed[filename]" style="font-size: 18px;color: rgba(110,106,106,0.3)" class="el-icon-upload"></i> <div
style="display: flex;flex-direction: row;align-items: center;justify-content: flex-start;margin-bottom: 10px"
>
<i v-if="progress ===100 && !uploadFailed[filename]" style="color: #13ce66;font-size: 18px"
class="el-icon-success"
></i>
<i v-if="progress !==100 && !uploadFailed[filename]" style="font-size: 18px;color: rgba(110,106,106,0.3)"
class="el-icon-upload"
></i>
<i v-if="uploadFailed[filename]" style="font-size: 18px;color: red" class="el-icon-warning"></i> <i v-if="uploadFailed[filename]" style="font-size: 18px;color: red" class="el-icon-warning"></i>
<span style="margin-left: 2%;font-size: 18px">{{ filename }}</span> <span style="margin-left: 2%;font-size: 18px">{{ filename }}</span>
</div> </div>
@ -52,19 +61,19 @@ export default {
props: { props: {
parentId: { parentId: {
type: String, type: String,
required: true, required: true
}, },
fileUrl: { fileUrl: {
type: String, type: String,
required: true, required: true
}, },
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false, default: false
}, },
getList: { getList: {
type: Function, type: Function
}, }
}, },
data() { data() {
return { return {
@ -75,136 +84,141 @@ export default {
uploadFailed: {}, // uploadFailed: {}, //
queue: [], // queue: [], //
maxConcurrentUploads: 5, // maxConcurrentUploads: 5, //
uploadsNum:{}, uploadsNum: {}
}; }
}, },
beforeMount() { beforeMount() {
this.resetComponent(); this.resetComponent()
}, },
mounted() { mounted() {
this.resetComponent(); // this.resetComponent() //
}, },
methods: { methods: {
handleClose(done) { handleClose(done) {
this.$modal this.$modal
.confirm('您确认要关闭吗?关闭后,未完成上传的文件将停止上传。') .confirm('您确认要关闭吗?关闭后,未完成上传的文件将停止上传。')
.then(() => { .then(() => {
this.queue = []; // this.queue = [] //
done(); done()
}) })
.then(() => { .then(() => {
this.resetComponent(); this.resetComponent()
this.getList && this.getList(); // this.getList && this.getList() //
})
.catch(() => {
}) })
.catch(() => {});
}, },
// //
resetComponent() { resetComponent() {
this.fileList = []; this.fileList = []
this.uploadProgress = {}; this.uploadProgress = {}
this.uploadFailed = {}; this.uploadFailed = {}
this.queue = []; this.queue = []
this.uploadsNum = {}; this.uploadsNum = {}
}, },
// //
customUpload(uploadFile) { customUpload(uploadFile) {
this.drawer = true; this.drawer = true
const file = uploadFile.file; const file = uploadFile.file
this.$set(this.uploadProgress, file.name, 0); // this.$set(this.uploadProgress, file.name, 0) //
// //
this.queue.push(file); this.queue.push(file)
this.startNextUpload(); this.startNextUpload()
}, },
// //
handleChange(file, fileList) { handleChange(file, fileList) {
// //
if (file && file.webkitRelativePath) { if (file && file.webkitRelativePath) {
const folderPath = file.webkitRelativePath.split('/')[0]; // const folderPath = file.webkitRelativePath.split('/')[0] //
const filesInFolder = fileList.filter(f => f.webkitRelativePath.startsWith(folderPath)); const filesInFolder = fileList.filter(f => f.webkitRelativePath.startsWith(folderPath))
} }
}, },
// //
uploadChunks(file) { uploadChunks(file) {
if (!this.drawer) return; // if (!this.drawer) return //
this.$set(this.uploadsNum, file.name, 0); this.$set(this.uploadsNum, file.name, 0)
const totalChunks = Math.ceil(file.size / this.chunkSize); const totalChunks = Math.ceil(file.size / this.chunkSize)
let currentChunk = 0; let currentChunk = 0
const uploadNextChunk = () => { const uploadNextChunk = () => {
if (!this.drawer) return; // if (!this.drawer) return //
const start = currentChunk * this.chunkSize; const start = currentChunk * this.chunkSize
const end = Math.min(file.size, start + this.chunkSize); const end = Math.min(file.size, start + this.chunkSize)
const chunk = file.slice(start, end); const chunk = file.slice(start, end)
const formData = new FormData(); const formData = new FormData()
formData.append('file', chunk); formData.append('file', chunk)
formData.append('filename', file.name); formData.append('filename', file.name)
formData.append('chunk', currentChunk + 1); formData.append('chunk', currentChunk + 1)
formData.append('totalChunks', totalChunks); formData.append('totalChunks', totalChunks)
formData.append('parentId', this.parentId); formData.append('parentId', this.parentId)
formData.append('fileUrl', this.fileUrl); formData.append('fileUrl', this.fileUrl)
uploadFiles(formData) uploadFiles(formData)
.then(() => { .then(() => {
currentChunk++; currentChunk++
const progress = Math.floor((currentChunk / totalChunks) * 100); const progress = Math.floor((currentChunk / totalChunks) * 100)
this.$set(this.uploadsNum, file.name, progress); this.$set(this.uploadsNum, file.name, progress)
this.$set(this.uploadProgress, file.name, progress); this.$set(this.uploadProgress, file.name, progress)
if (currentChunk < totalChunks) { if (currentChunk < totalChunks) {
uploadNextChunk(); uploadNextChunk()
} else { } else {
this.startNextUpload(); this.startNextUpload()
this.checkAllUploadsComplete(); this.checkAllUploadsComplete()
} }
}) })
.catch(() => { .catch(() => {
this.$set(this.uploadFailed, file.name, true); this.$set(this.uploadFailed, file.name, true)
this.startNextUpload(); this.startNextUpload()
}); })
}; }
uploadNextChunk(); uploadNextChunk()
}, },
checkAllUploadsComplete() { checkAllUploadsComplete() {
const allComplete = Object.values(this.uploadProgress).every(progress => progress === 100); const allComplete = Object.values(this.uploadProgress).every(progress => progress === 100)
if (allComplete) { if (allComplete) {
this.$message.success("所有文件上传完成!"); this.$message.success('所有文件上传完成!')
this.drawer = false; // this.drawer = false //
this.getList && this.getList(); // this.getList && this.getList() //
this.resetComponent(); this.resetComponent()
} }
}, },
// //
startNextUpload() { startNextUpload() {
if (!this.drawer) return; // if (!this.drawer) return //
Object.keys(this.uploadsNum).forEach((fileName) => { Object.keys(this.uploadsNum).forEach((fileName) => {
if (this.uploadsNum[fileName] === 100) { if (this.uploadsNum[fileName] === 100) {
delete this.uploadsNum[fileName]; delete this.uploadsNum[fileName]
} }
}); })
if (this.queue.length === 0 || Object.values(this.uploadsNum).length >= this.maxConcurrentUploads) { if (this.queue.length === 0 || Object.values(this.uploadsNum).length >= this.maxConcurrentUploads) {
return; return
} }
const nextFile = this.queue.shift(); const nextFile = this.queue.shift()
this.uploadChunks(nextFile); this.uploadChunks(nextFile)
}, },
beforeUpload(file) { beforeUpload(file) {
const maxSize = 2 * 1024 * 1024*1024; // 5MB const maxSize = 2 * 1024 * 1024 * 1024 // 5MB
if (file.size > maxSize) { if (file.size > maxSize) {
this.$message.error('文件大小不能超过 2GB'); this.$message.error('文件大小不能超过 2GB')
return false; // return false //
} }
console.log(file)
return true; // if (file.size <= 0) {
this.$message.error('文件大小不正确')
return false //
}
return true //
}, },
// //
handleExceed(files, fileList) { handleExceed(files, fileList) {
this.$message.warning(`最多只能选择50个文件当前选择了 ${files.length + fileList.length} 个文件`); this.$message.warning(`最多只能选择50个文件当前选择了 ${files.length + fileList.length} 个文件`)
}
} }
} }
};
</script> </script>
<style scoped> <style scoped>

View File

@ -1,39 +1,67 @@
<template> <template>
<div> <div>
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> <el-dialog :title="title" :visible.sync="isOpen" width="500px" append-to-body @close="cancel"
:close-on-click-modal="false"
>
<el-form ref="form" :model="form" :rules="rules" label-width="80px"> <el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="镜像名称" prop="mirrorName"> <el-form-item label="镜像名称" prop="mirrorName">
<el-input v-model="form.mirrorName" placeholder="请输入镜像名称"/> <el-input v-model="form.mirrorName" maxlength="100" placeholder="请输入镜像名称"/>
</el-form-item>
<el-form-item label="镜像版本" prop="mirrorVersion">
<el-input v-model="form.mirrorVersion" placeholder="请输入镜像名称"/>
</el-form-item> </el-form-item>
<el-form-item label="所属模型" prop="ownModel"> <el-form-item label="所属模型" prop="ownModel">
<el-input v-model="form.ownModel" placeholder="请输入所属模型"/> <el-select v-model="form.ownModel" placeholder="请选择所属模型" clearable style="width: 100%">
<el-option v-for="dict in modelList" :key="dict.id" :label="dict.modelName +' - '+dict.modelVersion"
:value="dict.id"
/>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="运行环境" prop="runEnvironment"> <el-form-item label="运行环境" prop="runEnvironment">
<el-input v-model="form.runEnvironment" type="textarea" placeholder="请输入内容"/> <el-select v-model="form.runEnvironment" placeholder="请选择运行环境" clearable style="width: 100%">
<el-option v-for="dict in runEnvironmentList" :key="dict.value" :label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="模型框架" prop="modelFrame"> <el-form-item label="模型框架" prop="modelFrame">
<el-input v-model="form.modelFrame" placeholder="请输入模型框架"/> <el-select v-model="form.modelFrame" placeholder="请选择模型框架" clearable style="width: 100%">
<el-option v-for="dict in dict.type.ai_frame_type" :key="dict.value" :label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="语言" prop="language"> <el-form-item label="语言" prop="language">
<el-input v-model="form.language" placeholder="请输入语言"/> <el-select v-model="form.language" placeholder="请选择语言" clearable style="width: 100%">
<el-option v-for="dict in languageList" :key="dict.value" :label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="镜像文件path" prop="mirrorPath"> <el-form-item label="镜像文件" prop="modelFileName">
<el-input v-model="form.mirrorPath" placeholder="请输入镜像文件path"/> <div class="custom-upload">
<input type="file" ref="modelInput" style="display: none" @change="handleFileChange('modelFile', $event)"
accept=".zip"
/>
<el-button size="mini" type="text" v-if="!form.modelFileName" @click="triggerFileInput('modelInput')">选择文件
</el-button>
<span style="cursor: pointer;" @click="triggerFileInput('modelInput')" v-if="form.modelFileName"
>{{ form.modelFileName }}</span>
<el-progress v-if="uploading" :percentage="uploadProgress.modelFile"/>
</div>
</el-form-item> </el-form-item>
<el-form-item label="备注" prop="remark"> <el-form-item label="接口文档" prop="manualFileName">
<el-input v-model="form.remark" placeholder="请输入备注"/> <div class="custom-upload">
</el-form-item> <input type="file" ref="manualInput" style="display: none"
<el-form-item label="是否删除" prop="isActive"> @change="handleFileChange('manualFile', $event)" accept=".doc,.docx,.pdf"
<el-input v-model="form.isActive" placeholder="请输入是否删除"/> />
</el-form-item> <el-button size="mini" type="text" v-if="!form.manualFileName" @click="triggerFileInput('manualInput')">
<el-form-item label="数据集id" prop="datasetId"> 选择文件
<el-input v-model="form.datasetId" placeholder="请输入数据集id"/> </el-button>
</el-form-item> <span style="cursor: pointer;" @click="triggerFileInput('manualInput')" v-if="form.manualFileName"
<el-form-item label="模型文件名" prop="modelFileName"> >{{ form.manualFileName }}<i></i></span>
<el-input v-model="form.modelFileName" placeholder="请输入模型文件名"/> <el-progress v-if="uploading" :percentage="uploadProgress.manualFile"/>
</el-form-item> </div>
<el-form-item label="使用手册文件名" prop="manualFileName">
<el-input v-model="form.manualFileName" placeholder="请输入使用手册文件名"/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
@ -45,7 +73,7 @@
</template> </template>
<script> <script>
import { getManager, addManager, updateManager, uploadFile } from '@/api/dataCenter/model' import { getManager, addManager, updateManager, uploadFile, listAll } from '@/api/dataCenter/mirror'
import { datasetList } from '@/api/dataCenter/dataSet' import { datasetList } from '@/api/dataCenter/dataSet'
import { generateUUID } from '../../../../utils/configure' import { generateUUID } from '../../../../utils/configure'
@ -69,22 +97,47 @@ export default {
}, },
data() { data() {
return { return {
datasetList: [], runEnvironmentList: [{
value: '0',
label: 'CPU'
},
{
value: '1',
label: 'GPU'
}],
languageList: [
{ 'value': '0', 'label': 'Java' },
{ 'value': '1', 'label': 'Python' },
{ 'value': '2', 'label': 'JavaScript (Node.js)' },
{ 'value': '3', 'label': 'PHP' },
{ 'value': '4', 'label': 'C# (.NET)' },
{ 'value': '5', 'label': 'Ruby' },
{ 'value': '6', 'label': 'Go (Golang)' },
{ 'value': '7', 'label': 'C/C++' },
{ 'value': '8', 'label': 'Kotlin' },
{ 'value': '9', 'label': 'Rust' },
{ 'value': '10', 'label': 'Scala' },
{ 'value': '11', 'label': 'Perl' },
{ 'value': '12', 'label': 'Swift' },
{ 'value': '13', 'label': 'Elixir' }
],
modelList: [],
uploadProgress: { modelFile: 0, manualFile: 0 }, uploadProgress: { modelFile: 0, manualFile: 0 },
uploading: false, uploading: false,
chunkSize: 1024 * 1024 * 20, // 20MB chunkSize: 1024 * 1024 * 20, // 20MB
form: { modelFile: null, manualFile: null, modelFileName: '', manualFileName: '' }, form: { modelFile: null, manualFile: null, modelFileName: '', manualFileName: '' },
rules: { rules: {
modelName: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }], mirrorName: [{ required: true, message: '镜像名称不能为空', trigger: 'blur' }],
modelVersion: [{ mirrorVersion: [{
required: true, required: true,
message: '版本号不能为空', message: '版本号不能为空',
trigger: 'blur' trigger: 'blur'
}, { pattern: /^V\d{1,3}(\.\d{1,3}){2}$/, message: '版本名称式不正确,应为 VX.Y.Z 格式', trigger: 'blur' }], }, { pattern: /^V\d{1,3}(\.\d{1,3}){2}$/, message: '版本名称式不正确,应为 VX.Y.Z 格式', trigger: 'blur' }],
modelType: [{ required: true, message: '请选择模型类型', trigger: 'blur' }], runEnvironment: [{ required: true, message: '请选择运行环境', trigger: 'blur' }],
language: [{ required: true, message: '请选择语言', trigger: 'blur' }],
modelFrame: [{ required: true, message: '请选择模型框架', trigger: 'blur' }], modelFrame: [{ required: true, message: '请选择模型框架', trigger: 'blur' }],
modelFileName: [{ required: true, message: '请上传模型文件', trigger: 'blur' }], modelFileName: [{ required: true, message: '请上传镜像文件', trigger: 'blur' }],
manualFileName: [{ required: true, message: '请上传使用手册', trigger: 'blur' }] manualFileName: [{ required: true, message: '请上传接口文档', trigger: 'blur' }]
}, },
currentUpload: { modelFile: null, manualFile: null } // currentUpload: { modelFile: null, manualFile: null } //
} }
@ -92,13 +145,14 @@ export default {
watch: { watch: {
isOpen(newVal) { isOpen(newVal) {
if (newVal) { if (newVal) {
datasetList({}).then(response => { console.log(this.mirrorId)
this.datasetList = response.data
})
if (this.mirrorId) { if (this.mirrorId) {
getManager(this.mirrorId).then(response => { getManager(this.mirrorId).then(response => {
this.form = response.data this.form = response.data
}) })
listAll().then(response => {
this.modelList = response.data
})
} }
} }
} }
@ -153,10 +207,10 @@ export default {
uploadNextChunk() uploadNextChunk()
} else { } else {
if (field === 'modelFile') { if (field === 'modelFile') {
this.form.modelPath = res.data.fileUrl this.form.mirrorPath = res.data.fileUrl
} }
if (field === 'manualFile') { if (field === 'manualFile') {
this.form.modelManual = res.data.fileUrl this.form.documentPath = res.data.fileUrl
} }
resolve() // resolve() //
} }

View File

@ -56,17 +56,56 @@
<el-table v-loading="loading" :data="managerList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="managerList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center"/> <el-table-column type="selection" width="55" align="center"/>
<el-table-column type="index" label="序号" align="center" :index="indexMethod" width="50"/>
<el-table-column label="镜像名称" align="center" prop="mirrorName"/> <el-table-column label="镜像名称" align="center" prop="mirrorName"/>
<el-table-column label="所属模型" align="center" prop="ownModel"/> <el-table-column label="镜像版本" align="center" prop="mirrorVersion"/>
<el-table-column label="运行环境" align="center" prop="runEnvironment"/> <el-table-column label="所属模型" align="center" prop="datasetId"/>
<el-table-column label="模型框架" align="center" prop="modelFrame"/> <el-table-column label="运行环境" align="center" prop="runEnvironment">
<el-table-column label="语言" align="center" prop="language"/> <template slot-scope="scope">
<el-table-column label="镜像文件path" align="center" prop="mirrorPath"/> <span>{{
<el-table-column label="备注" align="center" prop="remark"/> (runEnvironmentList.find(item => item.value == scope.row.runEnvironment) || {}).label || 'Unknown'
<el-table-column label="是否删除" align="center" prop="isActive"/> }}</span>
<el-table-column label="数据集id" align="center" prop="datasetId"/> </template>
<el-table-column label="模型文件名" align="center" prop="modelFileName"/> </el-table-column>
<el-table-column label="使用手册文件名" align="center" prop="manualFileName"/> <el-table-column label="架构类型" align="center" prop="modelFrame">
<template slot-scope="scope">
<dict-tag :options="dict.type.ai_frame_type" :value="scope.row.modelFrame"/>
</template>
</el-table-column>
<el-table-column label="语言" align="center" prop="language">
<template slot-scope="scope">
<span>{{ (languageList.find(item => item.value == scope.row.language) || {}).label || 'Unknown' }}</span>
</template>
</el-table-column>
<el-table-column label="镜像文件" align="center" prop="mirrorPath">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="handleDownload(scope.row.mirrorPath,scope.row.modelFileName)"
v-hasPermi="['model:manager:edit']"
>下载
</el-button>
</template>
</el-table-column>
<el-table-column label="接口文档" align="center" prop="modelFrame">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="handleDownload(scope.row.documentPath,scope.row.manualFileName)"
v-hasPermi="['model:manager:edit']"
>下载
</el-button>
<el-button
size="mini"
type="text"
@click="handleSee(scope.row.documentPath)"
v-hasPermi="['model:manager:remove']"
>查看
</el-button>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
@ -98,19 +137,46 @@
/> />
<!-- 添加或修改镜像管理对话框 --> <!-- 添加或修改镜像管理对话框 -->
<custom-dialog :title="title" :get-list="getList" :open="open" :model-id="mirrorId" @dialog-cancel="handleCancel"/> <custom-dialog :title="title" :get-list="getList" :open="open" :mirror-id="mirrorId" @dialog-cancel="handleCancel"/>
</div> </div>
</template> </template>
<script> <script>
import { listManager, delManager } from '@/api/dataCenter/mirror' import { listManager, delManager } from '@/api/dataCenter/mirror'
import customDialog from '../model/child/customDialog.vue' import customDialog from '../mirror/child/customDialog.vue'
import { Base64 } from 'js-base64'
import { encryptCBC } from '../../../utils/aescbc'
export default { export default {
name: 'Mirror', name: 'Mirror',
dicts: ['ai_annotate_type', 'ai_frame_type'],
components: { customDialog }, components: { customDialog },
data() { data() {
return { return {
runEnvironmentList: [{
value: '0',
label: 'CPU'
},
{
value: '1',
label: 'GPU'
}],
languageList: [
{ 'value': '0', 'label': 'Java' },
{ 'value': '1', 'label': 'Python' },
{ 'value': '2', 'label': 'JavaScript (Node.js)' },
{ 'value': '3', 'label': 'PHP' },
{ 'value': '4', 'label': 'C# (.NET)' },
{ 'value': '5', 'label': 'Ruby' },
{ 'value': '6', 'label': 'Go (Golang)' },
{ 'value': '7', 'label': 'C/C++' },
{ 'value': '8', 'label': 'Kotlin' },
{ 'value': '9', 'label': 'Rust' },
{ 'value': '10', 'label': 'Scala' },
{ 'value': '11', 'label': 'Perl' },
{ 'value': '12', 'label': 'Swift' },
{ 'value': '13', 'label': 'Elixir' }
],
mirrorId: null, mirrorId: null,
// //
loading: true, loading: true,
@ -142,6 +208,9 @@ export default {
this.getList() this.getList()
}, },
methods: { methods: {
indexMethod(index) {
return (this.queryParams.pageNum - 1) * this.queryParams.pageSize + index + 1
},
/** 查询镜像管理列表 */ /** 查询镜像管理列表 */
getList() { getList() {
this.loading = true this.loading = true
@ -176,7 +245,7 @@ export default {
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.mirrorId = row.id || this.ids[0] this.mirrorId = row.id || this.ids[0]
this.title = '添加' this.title = '修改'
this.open = true this.open = true
}, },
@ -190,6 +259,51 @@ export default {
this.$modal.msgSuccess('删除成功') this.$modal.msgSuccess('删除成功')
}).catch(() => { }).catch(() => {
}) })
},
handleCancel() {
this.open = false
},
handleDownload(url, fileName) {
// XMLHttpRequest
const xhr = new XMLHttpRequest()
// blob
xhr.responseType = 'blob'
//
xhr.onload = function() {
if (this.status === 200) {
// blob
const blob = this.response
//
const downloadLink = document.createElement('a')
// URL blob
downloadLink.href = URL.createObjectURL(blob)
//
downloadLink.download = fileName
//
downloadLink.click()
// URL
URL.revokeObjectURL(downloadLink.href)
}
}
//
xhr.onerror = function() {
console.error('下载请求出现错误')
}
// 使 GET
xhr.open('GET', `${JSON.parse(localStorage.getItem('minIoUrl')).minioUrl}${url}`, true)
//
xhr.send()
},
handleSee(url) {
let b64Encoded = Base64.encode(`${JSON.parse(localStorage.getItem('minIoUrl')).minioUrl}${url}`)
window.open(`http://192.168.0.14:8012/onlinePreview?url=${b64Encoded}&token=${this.generateToken()}`, '_blank')
},
generateToken() {
//
const currentTimeStamp = Math.floor(Date.now())
//
const timeStampString = currentTimeStamp.toString()
return encryptCBC(timeStampString)
} }
} }
} }