Browse Source

Merge branch 'zouap' of https://git.openi.org.cn/OpenI/aiforge into zouap

pull/1036/head
zouap 3 years ago
parent
commit
2912d917ff
4 changed files with 561 additions and 111 deletions
  1. +156
    -109
      templates/repo/modelmanage/index.tmpl
  2. +6
    -0
      templates/repo/modelmanage/showinfo.tmpl
  3. +381
    -0
      web_src/js/components/Model.vue
  4. +18
    -2
      web_src/js/index.js

+ 156
- 109
templates/repo/modelmanage/index.tmpl View File

@@ -43,9 +43,9 @@
<div class="row">
<div class="ui sixteen wide column">
<!-- 任务展示 -->
<div class="dataset list">
<div class="dataset list" id="model_list">
<!-- 表头 -->
<div class="ui grid stackable" style="background: #f0f0f0;;">
<!-- <div class="ui grid stackable" style="background: #f0f0f0;;">
<div class="row">
<div class="three wide column padding0">
<span style="margin:0 6px">{{$.i18n.Tr "repo.modelarts.model_name"}}</span>
@@ -77,43 +77,43 @@

</div>
</div>
</div> -->
<div class="ui grid stackable item">
<!-- <div class="ui grid stackable item">
<div class="row">
<!-- 任务名 -->
<div class="three wide column padding0">
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 12px;">
<span class="fitted" style="vertical-align: middle;">{{svg "octicon-tasklist" 16}}</span>
<span class="fitted" style="width: 90%;vertical-align: middle;margin-left: 0.4rem;">Model-abcd</span>
</a>
</div>
<!-- 当前版本 -->
<div class="one wide column text center padding0">
<span>0.0.3</span>
</div>
<!-- 版本数量 -->
<div class="one wide column text center padding0" style="width: 7.25%!important;">
<span>20</span>
</div>
<!-- 模型大小 -->
<div class="two wide column padding0 text center" style="width: 11.5%!important;">
<span>20.28MB</span>
</div>
<!-- AI引擎 -->
<div class="two wide column padding0 text center" style="width: 8.5%!important;">
<span>Mindspore</span>
</div>
<!-- 计算资源 -->
<div class="two wide column text center padding0" style="width: 11.5%!important;">
<span style="font-size: 12px;">CPU</span>
</div>
<!-- 创建时间 -->
<div class="two wide column text center padding0">
<span style="font-size: 12px;">2021/09/20 12:06:13</span>
</div>
<!-- 创建者 -->
<div class="one wide column text center padding0">
{{if .User.Name}}
<a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img class="ui avatar image" src="{{.User.RelAvatarLink}}"></a>
@@ -130,7 +130,7 @@
</div>
</div>
</div>
</div>
</div> -->
</div>

@@ -167,14 +167,17 @@
</div>
</div>
</div>

<div id="newmodel">
<div class="ui modal second">
<div class="header" style="padding: 1rem;background-color: rgba(240, 240, 240, 100);">
<h4>导入新模型</h4>
</div>
<div class="content content-padding">
<form class="ui form" action="{{.Link}}" method="post">
<form id="formId" method="POST" class="ui form">
<div class="ui error message">
<p></p>
</div>
<input type="hidden" name="_csrf" value="">
<div class="two inline fields ">
<div class="required ten wide field">
<label style="margin-left: -23px;">选择训练任务</label>
@@ -182,26 +185,25 @@
<option name="model_name" value="1">1</option>
<option name="model_version" value="11">11</option>
</select> -->
<div class="ui dropdown selection search width83">
<input type="hidden" name="model_name">
<div class="default text">Select Gender</div>
<div class="ui dropdown selection search width83 loading" id="choice_model">
<input type="hidden" id="JobId" name="JobId" required>
<div class="default text">选择训练任务</div>
<i class="dropdown icon"></i>
<div class="menu">
<div class="item" data-value="male">Male</div>
<div class="item" data-value="female">Female</div>
<div class="menu" id="job-name">
<!-- <div class="item" data-value="">Male</div>
<div class="item" data-value="female">Female</div> -->
</div>
</div>
</div>
<div class="required six widde field">
<label>版本</label>
<div class="ui dropdown selection search width70">
<input type="hidden" name="model_version">
<div class="default text">Select Gender</div>
<div class="ui dropdown selection search width70" id="choice_version">
<input type="hidden" id="VersionName" name="VersionName" required>
<div class="default text">选择版本</div>
<i class="dropdown icon"></i>
<div class="menu">
<div class="item" data-value="male">Male</div>
<div class="item" data-value="female">Female</div>
<div class="menu" id="job-version">
</div>
</div>
<!-- <select class="ui dropdown search width70" name="model_version">
@@ -211,25 +213,25 @@
</div>
</div>

<div class="required inline field">
<div class="required inline field" id="modelname">
<label>模型名称</label>
<input style="width: 45%;" name="job_name" required maxlength="255">
<input style="width: 45%;" id="name" name="Name" required maxlength="255">
</div>
<div class="required inline field">
<div class="required inline field" id="verionname">
<label>模型版本</label>
<input style="width: 45%;" name="job_name" required maxlength="255">
<input style="width: 45%;" id="version" name="Version" value="" readonly required maxlength="255">
</div>
<div class="required inline field">
<div class="inline field">
<label>模型标签</label>
<input style="width: 83%;" name="job_name" required maxlength="255">
<input style="width: 83%;margin-left: 7px;" name="Label" maxlength="255">
</div>
<div class="required inline field">
<div class="inline field">
<label for="description">模型描述</label>
<textarea style="width: 83%;" id="description" name="description" rows="3" maxlength="255" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}} onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 256)"></textarea>
<textarea style="width: 83%;margin-left: 7px;" id="Description" name="description" rows="3" maxlength="255" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}} onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 256)"></textarea>
</div>

<div class="inline field" style="margin-left: 75px;">
<button class="ui create_train_job green button" style="position: absolute;">
<button id="submitId" type="button" class="ui create_train_job green button" style="position: absolute;">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
</div>
@@ -246,25 +248,39 @@
{{template "base/footer" .}}

<script>
let url_href = window.location.pathname.split('create')[0]
// $(".ui.button.cancel").attr('href',url_href)
function showcreate(obj){
let repolink = {{.RepoLink}}
let repoId = {{$repository}}
let url_href = window.location.pathname.split('show_model')[0] + 'create_model'
const {_AppSubUrl, _StaticUrlPrefix, csrf} = window.config;
$('input[name="_csrf"]').val(csrf)

function createModelName(){
let repoName = location.pathname.split('/')[2]
let modelName = repoName + '_model_' + Math.random().toString(36).substr(2, 4)
console.log("repoName",modelName)
$('#name').val(modelName)
$('#version').val("0.0.1")
}
function showcreate(obj){
$('.ui.modal.second')
.modal({
centered: false,
onShow:function(){
$('.ui.dimmer').css({"background-color":"rgb(136, 136, 136,0.7)"})
$("#job-name").empty()
createModelName()
loadTrainList()
},
onHide:function(){
document.getElementById("formId").reset();
$('#choice_model').dropdown('clear')
$('#choice_version').dropdown('clear')
$('.ui.dimmer').css({"background-color":""})
}
})
.modal('show')
// $('.ui.dimmer').css({"background-color":"rgb(136, 136, 136,0.7)"})
}
// 删除时用户确认
function assertDelete(obj) {
if (obj.style.color == "rgb(204, 204, 204)") {
@@ -290,84 +306,115 @@
.modal('show')
}
}

function loadJobDuration() {
$(".job-status").each((index, job) => {
const jobID = job.dataset.jobid;
const repoPath = job.dataset.repopath;
const versionname = job.dataset.version
$.get(`/api/v1/repos/${repoPath}/modelarts/train-job/${jobID}?version_name=${versionname}`, (data) => {
console.log(data)
const duration = data.JobDuration
const jobID = data.JobID
$('#duration-'+jobID).text(duration)
})
$(function(){
$('#choice_model').dropdown({
onChange:function(value){
$(".ui.dropdown.selection.search.width70").addClass("loading")
$("#job-version").empty()
loadTrainVersion(value)
}
})
})
function versionAdd(version){
let versionArray = version.split('.')
if(versionArray[2]=='9'){
if(versionArray[1]=='9'){
versionArray[0] = String(Number(versionArray[1])+1)
versionArray[1] = '0'
}else{
versionArray[1]=String(Number(versionArray[1])+1)
}
}else{
versionArray[2]=String(Number(versionArray[2])+1)
}
console.log(versionArray.join('.'))
return versionArray.join('.')
}

function loadTrainList(){

let repolink = {{.RepoLink}}
let repoId = {{$repository}}
$.get(`${repolink}/modelmanage/query_train_job?repoId=${repoId}`, (data) => {
const train_list = data.filter((lists)=>{
return lists.Status==="COMPLETED"
})
console.log(data)
console.log(train_list)
const n_length = data.length
let train_html=''
for (let i=0;i<n_length;i++){
train_html += `<div class="item" data-value="${data[i].JobID}">${data[i].JobName}</div>`
train_html += '</div>'
}
$("#job-name").append(train_html)
$(".ui.dropdown.selection.search.width83").removeClass("loading")
})
}
$(document).ready(loadTrainList)
// 获取弹窗
var modal = document.getElementById('imageModal');

// 打开弹窗的按钮对象
var btns = document.getElementsByClassName("imageBtn");

// 获取 <span> 元素,用于关闭弹窗
var spans = document.getElementsByClassName('close');

// 点击按钮打开弹窗
for (i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
modal.style.display = "block";
}
function loadTrainVersion(value){
$.get(`${repolink}/modelmanage/query_train_job_version?JobID=${value}`, (data) => {
const n_length = data.length
let train_html=''
for (let i=0;i<n_length;i++){
train_html += `<div class="item" data-value="${data[i].VersionName}">${data[i].VersionName}</div>`
train_html += '</div>'
}
$("#job-version").append(train_html)
$(".ui.dropdown.selection.search.width70").removeClass("loading")
})
}

// 点击 <span> (x), 关闭弹窗
for (i = 0; i < spans.length; i++) {
spans[i].onclick = function() {
modal.style.display = "none";
function check(){
let jobid = document.getElementById("JobId").value
let versionname = document.getElementById("VersionName").value
let name= document.getElementById("name").value
let version= document.getElementById("version").value
if(jobid==""){
$(".required.ten.wide.field").addClass("error")
return false
}else{
$(".required.ten.wide.field").removeClass("error")
}
}

// 在用户点击其他地方时,关闭弹窗
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
if(versionname==""){
$(".required.six.widde.field").addClass("error")
return false
}else{
$(".required.six.widde.field").removeClass("error")
}
if(name==""){
$("#modelname").addClass("error")
return false
}else{
$("#modelname").removeClass("error")
}
if(versionname==""){
$("#verionname").addClass("error")
return false
}else{
$("#verionname").removeClass("error")
}
return true
}

// 显示弹窗,弹出相应的信息
function showmask() {
$('#imageModal').css('display', 'none')
$('#mask').css('display', 'block')

$("iframe[name=iframeContent]").on("load", function() {  
var responseText = $("iframe")[0].contentDocument.body.getElementsByTagName("pre")[0].innerHTML; 
var json1 = JSON.parse(responseText)
$('#mask').css('display', 'none')
parent.location.href

if (json1.result_code === "0") {
$('.alert').html('操作成功!').removeClass('alert-danger').addClass('alert-success').show().delay(1500).fadeOut();
} else {
$('.alert').html(json1.error_msg).removeClass('alert-success').addClass('alert-danger').show().delay(5000).fadeOut();
}
})
}
$('#submitId').click(function(){
let flag=check()
if(flag){
let data = $("#formId").serialize()
$("#mask").css({"display":"block","z-index":"9999"})
$.ajax({
url:url_href,
type:'POST',
data:data,
success:function(res){
$('.ui.modal.second').modal('hide')
window.location.href=location.href
},
error: function (xhr) {
// 隐藏 loading
// 只有请求不正常(状态码不为200)才会执行
$('.ui.error.message').text(xhr.responseText)
},
complete:function(xhr){
$("#mask").css({"display":"none","z-index":"1"})
}
})
}else{
return false
}
})
</script>


+ 6
- 0
templates/repo/modelmanage/showinfo.tmpl View File

@@ -0,0 +1,6 @@
{{template "base/head" .}}
<div class="repository">
{{template "repo/header" .}}
<div class="ui container">
</div>
</div>

+ 381
- 0
web_src/js/components/Model.vue View File

@@ -0,0 +1,381 @@
<template>
<div>
<div class="ui container" id="header">
<el-row style="margin-top:15px;" v-loading.fullscreen.lock="fullscreenLoading">
<el-table
:data="tableData"
style="min-width: 100%"
row-key="ID"
lazy
:load="load"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
:header-cell-style="tableHeaderStyle"
>
<el-table-column
prop="Name"
label="模型名称"
align="left"
min-width="18%"
>
<template slot-scope="scope">
<div class="expand-icon" v-if="scope.row.hasChildren===false">
<i class="el-icon-arrow-right"></i>
</div>
<!-- <i class="el-icon-time"></i> -->
<a class="text-over" :title="scope.row.Name">{{ scope.row.Name }}</a>
</template>
</el-table-column>
<el-table-column
prop="Version"
label="版本"
align="center"
min-width="6.5%"
>
<template slot-scope="scope">
<span class="text-over" :title="scope.row.Version">{{ scope.row.Version}}</span>
</template>
</el-table-column>
<el-table-column
prop="VersionCount"
label="版本数"
align="center"
min-width="7.5%"
>
<template slot-scope="scope">
<span class="text-over" :title="scope.row.VersionCount">{{ scope.row.VersionCount}}</span>
</template>
</el-table-column>

<el-table-column
prop="Size"
label="模型大小"
align="center"
min-width="10.5%"
>
<template slot-scope="scope">
<span class="text-over">{{ renderSize(scope.row.Size)}}</span>
</template>
</el-table-column>
<el-table-column
prop="EngineName"
label="AI引擎"
align="center"
min-width="8.5%"
>
<template slot-scope="scope">
<span class="text-over">{{ scope.row.EngineName}}</span>
</template>
</el-table-column>
<el-table-column
prop="ComputeResource"
label="计算资源"
align="center"
min-width="10.5%"
>
<template slot-scope="scope">
<span class="text-over">{{ scope.row.ComputeResource}}</span>
</template>
</el-table-column>
<el-table-column
prop="CreatedUnix"
label="创建时间"
align="center"
min-width="13.75%"
>
<template slot-scope="scope">
{{transTime(scope.row.CreatedUnix)}}
</template>
</el-table-column>
<el-table-column
prop="UserName"
label="创建者"
align="center"
min-width="6.75%"
>
<template slot-scope="scope">
<a :href="'/'+scope.row.UserName" :title="scope.row.UserName">
<img class="ui avatar image" :src="scope.row.UserRelAvatarLink">
</a>
</template>
</el-table-column>

<el-table-column label="操作" min-width="18%" align="center">
<template slot-scope="scope">
<div class="space-around">
<a :style="{visibility:!scope.row.Children ? 'visible':'hidden'}" @click="showcreateVue(scope.row.Name,scope.row.Version)">创建新版本</a>
<a :href="loadhref+scope.row.ID">下载</a>
<a @click="deleteModel(scope.row.ID)">删除</a>
</div>
</template>
</el-table-column>
</el-table>
</el-row>
<div class="ui container" style="margin-top:50px;text-align:center">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="totalNum">
</el-pagination>
</div>
</div>
</div>

</template>

<script>

const {_AppSubUrl, _StaticUrlPrefix, csrf} = window.config;




export default {
components: {
},
data() {
return {
currentPage:1,
pageSize:10,
totalNum:0,
params:{page:0,pageSize:10},
tableData: [],
fullscreenLoading: false,
url:''
};
},
methods: {
load(tree, treeNode, resolve) {
console.log("tree",tree)
this.$axios.get(this.url+'show_model_child_api',{params:{
name:tree.Name
}}).then((res)=>{
console.log(res)
let TrainTaskInfo
let tableData
tableData= res.data
console.log("-----tableData---",tableData)
for(let i=0;i<tableData.length;i++){
TrainTaskInfo = JSON.parse(res.data[i].TrainTaskInfo)
tableData[i].EngineName = TrainTaskInfo.EngineName.split('-')[0]
tableData[i].ComputeResource = TrainTaskInfo.ComputeResource
tableData[i].Name=''
tableData[i].VersionCount = ''
tableData[i].Children = true

}
console.log("=====-----tabledata---",tableData)
resolve(tableData)
})
},
tableHeaderStyle({row,column,rowIndex,columnIndex}){
if(rowIndex===0){
return 'background:#f5f5f6;color:#606266'
}
},
handleSizeChange(val){
this.params.size = val
this.getImageList()
},
handleCurrentChange(val){
this.params.page = val
this.getImageList()
},
showcreateVue(name,version){
$('.ui.modal.second')
.modal({
centered: false,
onShow:function(){
$('.ui.dimmer').css({"background-color":"rgb(136, 136, 136,0.7)"})
$("#job-name").empty()
$('#name').val(name)
let version_string = versionAdd(version)
$('#version').val(version_string)
loadTrainList()
},
onHide:function(){
document.getElementById("formId").reset();
$('#choice_model').dropdown('clear')
$('#choice_version').dropdown('clear')
$('.ui.dimmer').css({"background-color":""})
}
})
.modal('show')
},
deleteModel(id){
this.$axios.delete(this.url+'delete_model',{
params:{
ID:id
}}).then((res)=>{
console.log(res)
this.getModelList()
})
},
getModelList(){
this.fullscreenLoading = true
this.$axios.get(location.href+'_api',{
params:this.params
}).then((res)=>{
let TrainTaskInfo
this.tableData = res.data.data
for(let i=0;i<res.data.count;i++){
TrainTaskInfo = JSON.parse(res.data.data[i].TrainTaskInfo)
this.tableData[i].EngineName = TrainTaskInfo.EngineName.split('-')[0]
this.tableData[i].ComputeResource = TrainTaskInfo.ComputeResource
this.tableData[i].hasChildren = res.data.data[i].VersionCount===1 ? false : true
}
this.totalNum = this.tableData.length
console.log("this.tableData.",this.tableData)
this.fullscreenLoading = false
})
},
},
computed:{
loadhref(){
return this.url+'downloadall?ID='
},
transTime(){
return function(time){
let date = new Date(time * 1000);//时间戳为10位需*1000,时间戳为13位的话不需乘1000
let Y = date.getFullYear() + '-';
let M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1):date.getMonth()+1) + '-';
let D = (date.getDate()< 10 ? '0'+date.getDate():date.getDate())+ ' ';
let h = (date.getHours() < 10 ? '0'+date.getHours():date.getHours())+ ':';
let m = (date.getMinutes() < 10 ? '0'+date.getMinutes():date.getMinutes()) + ':';
let s = date.getSeconds() < 10 ? '0'+date.getSeconds():date.getSeconds();
return Y+M+D+h+m+s;
}
},
renderSize(){
return function(value){
if(null==value||value==''){
return "0 Bytes";
}
var unitArr = new Array("Bytes","KB","MB","GB","TB","PB","EB","ZB","YB");
var index=0;
var srcsize = parseFloat(value);
index=Math.floor(Math.log(srcsize)/Math.log(1024));
var size =srcsize/Math.pow(1024,index);
size=size.toFixed(2);//保留的小数位数
return size+unitArr[index];
}
}
},
mounted() {
this.getModelList()
this.url = location.href.split('show_model')[0]
}

};
</script>

<style scoped>






/deep/ .el-pagination.is-background .el-pager li:not(.disabled).active {
background-color: #5bb973;
color: #FFF;
}
/deep/ .el-pagination.is-background .el-pager li.active {
color: #fff;
cursor: default;
}
/deep/ .el-pagination.is-background .el-pager li:hover {
color: #5bb973;
}
/deep/ .el-pagination.is-background .el-pager li:not(.disabled):hover {
color: #5bb973;
}
/deep/ .el-pagination.is-background .el-pager li:not(.disabled).active:hover {
background-color: #5bb973;
color: #FFF;
}

/deep/ .el-pager li.active {
color: #08C0B9;
cursor: default;
}
/deep/ .el-pagination .el-pager li:hover {
color: #08C0B9;
}
/deep/ .el-pagination .el-pager li:not(.disabled):hover {
color: #08C0B9;
}

.text-over{
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
}
.el-icon-arrow-right{
font-family: element-icons!important;
speak: none;
font-style: normal;
font-weight: 400;
font-feature-settings: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
vertical-align: middle;
display: inline-block;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
border: 1px solid #D4D4D5;
border-radius: 50%;
color: #D4D4D5;
margin-right: 4px;
}
.el-icon-arrow-right::before{
content: "\e6e0";
}
.expand-icon{
display: inline-block;
width: 20px;
line-height: 20px;
height: 20px;
text-align: center;
margin-right: 3px;
font-size: 12px;
}
/deep/ .el-table__expand-icon .el-icon-arrow-right{
font-family: element-icons!important;
speak: none;
font-style: normal;
font-weight: 400;
font-feature-settings: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
vertical-align: middle;
display: inline-block;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
border: 1px solid #3291F8;
border-radius: 50%;
color: #3291F8;
margin-right: 4px;
}
.space-around{
display: flex;
justify-content: space-around;
}

</style>

+ 18
- 2
web_src/js/index.js View File

@@ -39,6 +39,7 @@ import Images from './components/Images.vue';
import EditTopics from './components/EditTopics.vue';
import DataAnalysis from './components/DataAnalysis.vue'
import Contributors from './components/Contributors.vue'
import Model from './components/Model.vue';

Vue.use(ElementUI);
Vue.prototype.$axios = axios;
@@ -2916,11 +2917,12 @@ $(document).ready(async () => {
initVueEditTopic();
initVueContributors();
initVueImages();
initVueModel();
initVueDataAnalysis();
initTeamSettings();
initCtrlEnterSubmit();
initNavbarContentToggle();
// initTopicbar();
// initTopicbar();vim
// closeTopicbar();
initU2FAuth();
initU2FRegister();
@@ -3646,7 +3648,7 @@ function initVueContributors() {

function initVueImages() {
const el = document.getElementById('images');
console.log("el",el)
if (!el) {
return;
@@ -3658,6 +3660,20 @@ function initVueImages() {
render: h => h(Images)
});
}
function initVueModel() {
const el = document.getElementById('model_list');
if (!el) {
return;
}

new Vue({
el: el,
render: h => h(Model)
});
}
function initVueDataAnalysis() {
const el = document.getElementById('data_analysis');
console.log("el",el)


Loading…
Cancel
Save