| @@ -19,6 +19,9 @@ type JobType string | |||
| type ModelArtsJobStatus string | |||
| const ( | |||
| NPUResource = "NPU" | |||
| GPUResource = "CPU/GPU" | |||
| JobWaiting CloudbrainStatus = "WAITING" | |||
| JobStopped CloudbrainStatus = "STOPPED" | |||
| JobSucceeded CloudbrainStatus = "SUCCEEDED" | |||
| @@ -106,7 +109,7 @@ type Cloudbrain struct { | |||
| IsLatestVersion string //是否是最新版本,1是,0否 | |||
| CommitID string //提交的仓库代码id | |||
| PreVersionName string //父版本名称 | |||
| ComputeResource string `xorm:"-"` //计算资源,例如npu | |||
| ComputeResource string //计算资源,例如npu | |||
| EngineID int64 //引擎id | |||
| TrainUrl string //输出模型的obs路径 | |||
| @@ -212,6 +212,7 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, | |||
| Image: image, | |||
| GpuQueue: gpuQueue, | |||
| ResourceSpecId: resourceSpecId, | |||
| ComputeResource: models.GPUResource, | |||
| }) | |||
| if err != nil { | |||
| @@ -51,10 +51,6 @@ const ( | |||
| PerPage = 10 | |||
| IsLatestVersion = "1" | |||
| NotLatestVersion = "0" | |||
| // ComputeResource = "NPU" | |||
| NPUResource = "NPU" | |||
| GPUResource = "CPU/GPU" | |||
| AllResource = "all" | |||
| DebugType = -1 | |||
| VersionCount = 1 | |||
| @@ -306,7 +302,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error | |||
| DatasetName: attach.Name, | |||
| CommitID: req.CommitID, | |||
| IsLatestVersion: req.IsLatestVersion, | |||
| //ComputeResource: NPUResource, | |||
| ComputeResource: models.NPUResource, | |||
| EngineID: req.EngineID, | |||
| TrainUrl: req.TrainUrl, | |||
| BranchName: req.BranchName, | |||
| @@ -389,7 +385,7 @@ func GenerateTrainJobVersion(ctx *context.Context, req *GenerateTrainJobReq, job | |||
| CommitID: req.CommitID, | |||
| IsLatestVersion: req.IsLatestVersion, | |||
| PreVersionName: req.PreVersionName, | |||
| ComputeResource: NPUResource, | |||
| ComputeResource: models.GPUResource, | |||
| EngineID: req.EngineID, | |||
| TrainUrl: req.TrainUrl, | |||
| BranchName: req.BranchName, | |||
| @@ -80,3 +80,7 @@ func (l *LocalStorage) HasObject(path string) (bool, error) { | |||
| func (l *LocalStorage) UploadObject(fileName, filePath string) error { | |||
| return nil | |||
| } | |||
| func (l *LocalStorage) DeleteDir(dir string) error { | |||
| return nil | |||
| } | |||
| @@ -11,7 +11,9 @@ import ( | |||
| "strings" | |||
| "time" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "github.com/minio/minio-go" | |||
| ) | |||
| @@ -77,6 +79,29 @@ func (m *MinioStorage) Delete(path string) error { | |||
| return m.client.RemoveObject(m.bucket, m.buildMinioPath(path)) | |||
| } | |||
| // Delete delete a file | |||
| func (m *MinioStorage) DeleteDir(dir string) error { | |||
| objectsCh := make(chan string) | |||
| // Send object names that are needed to be removed to objectsCh | |||
| go func() { | |||
| defer close(objectsCh) | |||
| // List all objects from a bucket-name with a matching prefix. | |||
| for object := range m.client.ListObjects(m.bucket, dir, true, nil) { | |||
| if object.Err != nil { | |||
| log.Error("ListObjects failed:%v", object.Err) | |||
| } | |||
| objectsCh <- object.Key | |||
| } | |||
| }() | |||
| for rErr := range m.client.RemoveObjects(m.bucket, objectsCh) { | |||
| log.Error("Error detected during deletion: ", rErr) | |||
| } | |||
| return nil | |||
| } | |||
| //Get Presigned URL for get object | |||
| func (m *MinioStorage) PresignedGetURL(path string, fileName string) (string, error) { | |||
| // Set request parameters for content-disposition. | |||
| @@ -23,6 +23,7 @@ type ObjectStorage interface { | |||
| Save(path string, r io.Reader) (int64, error) | |||
| Open(path string) (io.ReadCloser, error) | |||
| Delete(path string) error | |||
| DeleteDir(dir string) error | |||
| PresignedGetURL(path string, fileName string) (string, error) | |||
| PresignedPutURL(path string) (string, error) | |||
| HasObject(path string) (bool, error) | |||
| @@ -11655,6 +11655,11 @@ | |||
| "autolinker": "~0.28.0" | |||
| } | |||
| }, | |||
| "remixicon": { | |||
| "version": "2.5.0", | |||
| "resolved": "https://registry.npmjs.org/remixicon/-/remixicon-2.5.0.tgz", | |||
| "integrity": "sha512-q54ra2QutYDZpuSnFjmeagmEiN9IMo56/zz5dDNitzKD23oFRw77cWo4TsrAdmdkPiEn8mxlrTqxnkujDbEGww==" | |||
| }, | |||
| "remove-bom-buffer": { | |||
| "version": "3.0.0", | |||
| "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", | |||
| @@ -42,6 +42,7 @@ | |||
| "postcss-preset-env": "6.7.0", | |||
| "postcss-safe-parser": "4.0.2", | |||
| "qs": "6.9.4", | |||
| "remixicon": "2.5.0", | |||
| "spark-md5": "3.0.1", | |||
| "svg-sprite-loader": "5.0.0", | |||
| "svgo": "1.3.2", | |||
| @@ -7,6 +7,7 @@ package repo | |||
| import ( | |||
| "net/http" | |||
| "os" | |||
| "strconv" | |||
| "strings" | |||
| @@ -14,6 +15,7 @@ import ( | |||
| "code.gitea.io/gitea/modules/context" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/modelarts" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "code.gitea.io/gitea/modules/storage" | |||
| ) | |||
| @@ -237,7 +239,7 @@ func DelTrainJobVersion(ctx *context.APIContext) { | |||
| JobID: jobID, | |||
| }) | |||
| if err != nil { | |||
| ctx.ServerError("get VersionListCount faild", err) | |||
| ctx.ServerError("get VersionListCount failed", err) | |||
| return | |||
| } | |||
| if VersionListCount > 0 { | |||
| @@ -255,6 +257,8 @@ func DelTrainJobVersion(ctx *context.APIContext) { | |||
| return | |||
| } | |||
| } | |||
| } else { //已删除该任务下的所有版本 | |||
| deleteJobStorage(task.JobName) | |||
| } | |||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | |||
| @@ -321,3 +325,21 @@ func ModelList(ctx *context.APIContext) { | |||
| "PageIsCloudBrain": true, | |||
| }) | |||
| } | |||
| func deleteJobStorage(jobName string) error { | |||
| //delete local | |||
| localJobPath := setting.JobPath + jobName | |||
| err := os.RemoveAll(localJobPath) | |||
| if err != nil { | |||
| log.Error("RemoveAll(%s) failed:%v", localJobPath, err) | |||
| } | |||
| //delete oss | |||
| dirPath := setting.CodePathPrefix + jobName + "/" | |||
| err = storage.ObsRemoveObject(setting.Bucket, dirPath) | |||
| if err != nil { | |||
| log.Error("ObsRemoveObject(%s) failed:%v", localJobPath, err) | |||
| } | |||
| return nil | |||
| } | |||
| @@ -245,7 +245,7 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| ctx.RenderWithErr(err.Error(), tplCloudBrainNew, &form) | |||
| return | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||
| } | |||
| func CloudBrainRestart(ctx *context.Context) { | |||
| @@ -566,7 +566,9 @@ func CloudBrainDel(ctx *context.Context) { | |||
| ctx.ServerError("DeleteJob failed", err) | |||
| return | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||
| deleteJobStorage(task.JobName, models.TypeCloudBrainOne) | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||
| } | |||
| func CloudBrainShowModels(ctx *context.Context) { | |||
| @@ -840,6 +842,35 @@ func mkModelPath(modelPath string) error { | |||
| return nil | |||
| } | |||
| func deleteJobStorage(jobName string, cloudbrainType int) error { | |||
| //delete local | |||
| localJobPath := setting.JobPath + jobName | |||
| err := os.RemoveAll(localJobPath) | |||
| if err != nil { | |||
| log.Error("RemoveAll(%s) failed:%v", localJobPath, err) | |||
| } | |||
| //delete oss | |||
| if cloudbrainType == models.TypeCloudBrainOne { | |||
| dirPath := setting.CBCodePathPrefix + jobName + "/" | |||
| err = storage.Attachments.DeleteDir(dirPath) | |||
| if err != nil { | |||
| log.Error("DeleteDir(%s) failed:%v", localJobPath, err) | |||
| } | |||
| } else if cloudbrainType == models.TypeCloudBrainTwo { | |||
| //dirPath := setting.CodePathPrefix + jobName + "/" | |||
| //err = storage.ObsRemoveObject(setting.Bucket, dirPath) | |||
| //if err != nil { | |||
| // log.Error("ObsRemoveObject(%s) failed:%v", localJobPath, err) | |||
| //} | |||
| log.Info("no need to delete") | |||
| } else { | |||
| log.Error("cloudbrainType(%d) error", cloudbrainType) | |||
| } | |||
| return nil | |||
| } | |||
| func SyncCloudbrainStatus() { | |||
| cloudBrains, err := models.GetCloudBrainUnStoppedJob() | |||
| if err != nil { | |||
| @@ -56,11 +56,11 @@ func DebugJobIndex(ctx *context.Context) { | |||
| } | |||
| debugType := modelarts.DebugType | |||
| jobType := string(models.JobTypeDebug) | |||
| if debugListType == modelarts.GPUResource { | |||
| if debugListType == models.GPUResource { | |||
| debugType = models.TypeCloudBrainOne | |||
| jobType = "" | |||
| } | |||
| if debugListType == modelarts.NPUResource { | |||
| if debugListType == models.NPUResource { | |||
| debugType = models.TypeCloudBrainTwo | |||
| } | |||
| @@ -81,16 +81,10 @@ func DebugJobIndex(ctx *context.Context) { | |||
| for i, task := range ciTasks { | |||
| ciTasks[i].CanDebug = cloudbrain.CanCreateOrDebugJob(ctx) | |||
| ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||
| if task.Cloudbrain.Type == models.TypeCloudBrainOne { | |||
| ciTasks[i].Cloudbrain.ComputeResource = modelarts.GPUResource | |||
| } else if task.Cloudbrain.Type == models.TypeCloudBrainTwo { | |||
| ciTasks[i].Cloudbrain.ComputeResource = modelarts.NPUResource | |||
| } | |||
| ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource | |||
| } | |||
| pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | |||
| //pager.SetDefaultParams(ctx) | |||
| pager.AddParam(ctx, "debugListType", "ListType") | |||
| ctx.Data["Page"] = pager | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| @@ -350,7 +344,7 @@ func NotebookDel(ctx *context.Context) { | |||
| return | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||
| } | |||
| func TrainJobIndex(ctx *context.Context) { | |||
| @@ -380,7 +374,7 @@ func TrainJobIndex(ctx *context.Context) { | |||
| for i, task := range tasks { | |||
| tasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||
| tasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) | |||
| tasks[i].ComputeResource = modelarts.NPUResource | |||
| tasks[i].ComputeResource = models.NPUResource | |||
| } | |||
| pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | |||
| @@ -93,6 +93,14 @@ | |||
| display: none; | |||
| } | |||
| .icons{ | |||
| /* position: absolute !important; | |||
| right: 150px; | |||
| top: 14px; | |||
| z-index: 2; */ | |||
| } | |||
| </style> | |||
| <div id="mask"> | |||
| @@ -182,9 +190,10 @@ | |||
| </select> | |||
| </div> | |||
| <div class="inline required field"> | |||
| <div class="inline required field" style="position: relative;"> | |||
| <label>镜像</label> | |||
| <input type="text" list="cloudbrain_image" placeholder="选择镜像" name="image" required autofocus maxlength="254"> | |||
| <i class="times circle outline icon icons" style="visibility: hidden;" onclick="clearValue()"></i> | |||
| <datalist class="ui search" id="cloudbrain_image" style='width:385px;' name="image"> | |||
| {{range .images}} | |||
| <option name="image" value="{{.Place}}">{{.PlaceView}}</option> | |||
| @@ -261,9 +270,17 @@ | |||
| <script> | |||
| let form = document.getElementById('form_id'); | |||
| $('#messageInfo').css('display','none') | |||
| let inputs = document.querySelectorAll('input[list]'); | |||
| inputs[0].addEventListener('change', function() { | |||
| $(".icon.icons").css("visibility","visible") | |||
| }); | |||
| $('#messageInfo').css('display','none') | |||
| function clearValue(){ | |||
| context=inputs[0] | |||
| context.value='' | |||
| $(".icon.icons").css("visibility","hidden") | |||
| } | |||
| form.onsubmit = function(e){ | |||
| let value_task = $("input[name='job_name']").val() | |||
| let value_image = $("input[name='image']").val() | |||
| @@ -568,9 +568,10 @@ | |||
| $('#' + JobID+'-icon').removeClass().addClass(res.status) | |||
| $('#' + JobID+ '-text').text(res.status) | |||
| if(res.status==="STOPPED"){ | |||
| $('#model-debug-'+JobID).removeClass('blue').addClass('disabled').text("再次调试").css("margin","0") | |||
| $('#model-debug-'+JobID).removeClass('disabled').addClass('blue').text("再次调试").css("margin","0") | |||
| $('#model-image-'+JobID).removeClass('blue').addClass('disabled') | |||
| $('#stop-model-debug-'+JobID).removeClass('blue').addClass('disabled') | |||
| $('#model-delete-'+JobID).removeClass('disabled').addClass('blue') | |||
| } | |||
| else{ | |||
| $('#model-debug-'+JobID).removeClass('blue').addClass('disabled') | |||
| @@ -149,12 +149,6 @@ | |||
| {{.i18n.Tr "repo.model_manager"}} | |||
| </a> | |||
| {{end}} | |||
| {{if .Permission.CanRead $.UnitTypeModelManage}} | |||
| <a class="{{if .isModelManage}}active{{end}} item" href="{{.RepoLink}}/modelmanage/show_model"> | |||
| <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"/><path d="M3.741 1.408l18.462 10.154a.5.5 0 0 1 0 .876L3.741 22.592A.5.5 0 0 1 3 22.154V1.846a.5.5 0 0 1 .741-.438zM5 13v6.617L18.85 12 5 4.383V11h5v2H5z"/></svg> | |||
| {{.i18n.Tr "repo.model_manager"}} | |||
| </a> | |||
| {{end}} | |||
| {{if .Permission.CanRead $.UnitTypeCloudBrain}} | |||
| <a class="{{if .PageIsCloudBrain}}active{{end}} item" href="{{.RepoLink}}/debugjob?debugListType=all"> | |||
| <span> | |||
| @@ -121,7 +121,7 @@ | |||
| </div> | |||
| <!-- 任务运行时间 --> | |||
| <div class="two wide column text center padding0"> | |||
| <span style="font-size: 12px;" id="duration-{{.JobID}}"></span> | |||
| <span style="font-size: 12px;" id="duration-{{.JobID}}">{{.TrainJobDuration}}</span> | |||
| </div> | |||
| <!-- 计算资源 --> | |||
| <div class="two wide column text center padding0"> | |||
| @@ -253,35 +253,18 @@ | |||
| } | |||
| } | |||
| 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) | |||
| }) | |||
| }) | |||
| } | |||
| $(document).ready(loadJobDuration); | |||
| // 加载任务状态 | |||
| var timeid = window.setInterval(loadJobStatus, 15000); | |||
| $(document).ready(loadJobStatus); | |||
| function loadJobStatus() { | |||
| $(".job-status").each((index, job) => { | |||
| const jobID = job.dataset.jobid; | |||
| const repoPath = job.dataset.repopath; | |||
| const jobID = job.dataset.jobid | |||
| const repoPath = job.dataset.repopath | |||
| const versionname = job.dataset.version | |||
| if (job.textContent.trim() == 'IMAGE_FAILED' || job.textContent.trim() == 'SUBMIT_FAILED' || job.textContent.trim() == 'DELETE_FAILED' | |||
| || job.textContent.trim() == 'KILLED' || job.textContent.trim() == 'COMPLETED' || job.textContent.trim() == 'FAILED' | |||
| || job.textContent.trim() == 'CANCELED' || job.textContent.trim() == 'LOST') { | |||
| return | |||
| const status_text = $(`#${jobID}-text`).text() | |||
| if(['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED'].includes(status_text)){ | |||
| return | |||
| } | |||
| $.get(`/api/v1/repos/${repoPath}/modelarts/train-job/${jobID}?version_name=${versionname}`, (data) => { | |||
| const jobID = data.JobID | |||
| const status = data.JobStatus | |||
| @@ -329,7 +312,6 @@ | |||
| } | |||
| } | |||
| function stopVersion(version_name,jobID){ | |||
| const url = '/api/v1/repos/{{$.RepoRelPath}}/modelarts/train-job/'+jobID+'/stop_version' | |||
| $.post(url,{version_name:version_name},(data)=>{ | |||
| if(data.StatusOK===0){ | |||
| @@ -450,7 +450,6 @@ td, th { | |||
| {{template "base/footer" .}} | |||
| <script> | |||
| console.log({{.version_list_task}}) | |||
| $('.menu .item').tab() | |||
| $(document).ready(function(){ | |||
| @@ -495,14 +494,19 @@ td, th { | |||
| } | |||
| function loadJobStatus() { | |||
| $(".ui.accordion.border-according").each((index, job) => { | |||
| const jobID = job.dataset.jobid; | |||
| const repoPath = job.dataset.repopath; | |||
| const versionname = job.dataset.version | |||
| if (job.textContent.trim() == 'IMAGE_FAILED' || job.textContent.trim() == 'SUBMIT_FAILED' || job.textContent.trim() == 'DELETE_FAILED' | |||
| || job.textContent.trim() == 'KILLED' || job.textContent.trim() == 'COMPLETED' || job.textContent.trim() == 'FAILED' | |||
| || job.textContent.trim() == 'CANCELED' || job.textContent.trim() == 'LOST') { | |||
| return | |||
| // ['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED'] | |||
| // if (job.textContent.trim() == 'IMAGE_FAILED' || job.textContent.trim() == 'SUBMIT_FAILED' || job.textContent.trim() == 'DELETE_FAILED' | |||
| // || job.textContent.trim() == 'KILLED' || job.textContent.trim() == 'COMPLETED' || job.textContent.trim() == 'FAILED' | |||
| // || job.textContent.trim() == 'CANCELED' || job.textContent.trim() == 'LOST') { | |||
| // return | |||
| // } | |||
| let status = $(`#${versionname}-status-span`).text() | |||
| if(['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED'].includes(status)){ | |||
| return | |||
| } | |||
| let stopArray=["KILLED","FAILED","START_FAILED","KILLING","COMPLETED"] | |||
| $.get(`/api/v1/repos/${repoPath}/modelarts/train-job/${jobID}?version_name=${versionname}`, (data) => { | |||
| @@ -141,7 +141,6 @@ | |||
| <script> | |||
| 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) | |||
| @@ -110,7 +110,36 @@ | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">模型描述</td> | |||
| <td class="ti-text-form-content" ><div id="edit-td" style="display:flex"><span id="Description" title="" class="iword-elipsis"></span><i id="edit-pencil" data-id="" data-desc="" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div></td> | |||
| <td class="ti-text-form-content" > | |||
| <div id="edit-td" style="display:flex"> | |||
| <span id="Description" title="" class="iword-elipsis"></span> | |||
| <i id="edit-pencil" data-id="" data-desc="" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></i> | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">代码版本</td> | |||
| <td class="ti-text-form-content word-elipsis"><span id="CodeBranch" title=""></span></td> | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">启动文件</td> | |||
| <td class="ti-text-form-content word-elipsis"><span id="BootFile" title=""></span></td> | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">训练数据集</td> | |||
| <td class="ti-text-form-content word-elipsis"><span id="DatasetName" title=""></span></td> | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">运行参数</td> | |||
| <td class="ti-text-form-content word-elipsis"><span id="Parameters" title=""></span></td> | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">规格</td> | |||
| <td class="ti-text-form-content word-elipsis"><span id="FlavorName" title=""></span></td> | |||
| </tr> | |||
| <tr> | |||
| <td class="ti-text-form-label text-width80">计算节点</td> | |||
| <td class="ti-text-form-content word-elipsis"><span id="WorkServerNumber" title=""></span></td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| @@ -155,6 +184,7 @@ function changeInfo(version){ | |||
| let returnArray = [] | |||
| returnArray = transObj(versionData) | |||
| let [initObj,initModelAcc,id] = returnArray | |||
| editorCancel('','') | |||
| renderInfo(initObj,initModelAcc,id) | |||
| }) | |||
| } | |||
| @@ -175,8 +205,15 @@ function loadInfo(){ | |||
| }) | |||
| } | |||
| function transObj(data){ | |||
| let {ID,Name,Version,Label,Size,Description,CreatedUnix,Accuracy} = data[0] | |||
| let {ID,Name,Version,Label,Size,Description,CreatedUnix,Accuracy,CodeBranch,CodeCommitID,TrainTaskInfo} = data[0] | |||
| let modelAcc = JSON.parse(Accuracy) | |||
| TrainTaskInfo = JSON.parse(TrainTaskInfo) | |||
| // Parameters = JSON.parse(Parameters) | |||
| console.log("TrainTaskInfo",TrainTaskInfo) | |||
| let {Parameters} = TrainTaskInfo | |||
| Parameters = JSON.parse(Parameters) | |||
| Parameters = Parameters.parameter.length === 0 ? '--':Parameters.parameter | |||
| console.log(Parameters) | |||
| let size = tranSize(Size) | |||
| let time = transTime(CreatedUnix) | |||
| let initObj = { | |||
| @@ -186,6 +223,14 @@ function transObj(data){ | |||
| Size:size, | |||
| CreateTime:time, | |||
| Description:Description || '--', | |||
| CodeBranch:CodeBranch || '--', | |||
| CodeCommitID:CodeCommitID || '--', | |||
| BootFile:TrainTaskInfo.BootFile || '--', | |||
| DatasetName:TrainTaskInfo.DatasetName || '--', | |||
| Parameters:TrainTaskInfo.Parameters || '--', | |||
| FlavorName:TrainTaskInfo.FlavorName || '--', | |||
| WorkServerNumber:TrainTaskInfo.WorkServerNumber || '--', | |||
| Parameters:Parameters | |||
| } | |||
| let initModelAcc = { | |||
| Accuracy: modelAcc.Accuracy || '--', | |||
| @@ -221,15 +266,16 @@ function tranSize(value){ | |||
| function editorFn(context){ | |||
| let id= context.dataset.id | |||
| let text = context.dataset.desc | |||
| console.log(id,text) | |||
| $('#edit-td').replaceWith("<div id='edit-div' style='width:80%;display: inline-block;'><textarea id='textarea-value' value='' rows='3' maxlength='255' style='width:80%;' id='edit-text'>"+text+"</textarea><i class='check icon' style='color: #50d4ab;' onclick='editorSure(\"" + text + "\",\"" + id + "\")'></i><i class='times icon' style='color: #f66f6a;' onclick='editorCancel(\"" + text + "\",\"" + id + "\")'></i></div>"); | |||
| let textValue = text.replace(/enter;/g,'\r\n') | |||
| $('#edit-td').replaceWith(`<div id='edit-div' style='width:80%;display: inline-block;'><textarea id='textarea-value' value='' rows='3' maxlength='255' style='width:80%;white-space: nowrap;' id='edit-text'>${textValue}</textarea><i class='check icon' style='color: #50d4ab;' onclick='editorSure("${text}","${id}")'></i><i class='times icon' style='color: #f66f6a;' onclick='editorCancel("${text}","${id}")'></i></div>`); | |||
| } | |||
| function editorCancel(text,id){ | |||
| $('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${text}" class="iword-elipsis">${text}</span><i id="edit-pencil" data-id="${id}" data-desc="${text}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||
| let objkey = text.replace(/enter;/g,'\r\n') | |||
| $('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${objkey}" class="iword-elipsis">${objkey}</span><i id="edit-pencil" data-id="${id}" data-desc="${text}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||
| } | |||
| function editorSure(text,id){ | |||
| let description=$('#textarea-value').val() | |||
| let sourcetext = $('#textarea-value').val().replace(/\n/g,'enter;') | |||
| let data = { | |||
| ID:id, | |||
| Description:description | |||
| @@ -239,16 +285,18 @@ function editorSure(text,id){ | |||
| type:'PUT', | |||
| data:data | |||
| }).done((res)=>{ | |||
| $('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${description}" class="iword-elipsis">${description}</span><i id="edit-pencil" data-id="${id}" data-desc="${description}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||
| $('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${description}" class="iword-elipsis">${description}</span><i id="edit-pencil" data-id="${id}" data-desc="${sourcetext}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||
| }) | |||
| } | |||
| function renderInfo(obj,accObj,id){ | |||
| for(let key in obj){ | |||
| if(key==="Description"){ | |||
| let descriptionText=obj[key].replace(/\r\n|\n/g,'enter;') | |||
| $(`#${key}`).text(obj[key]) | |||
| $(`#${key}`).attr("title",obj[key]) | |||
| $('#edit-pencil').attr("data-id",id) | |||
| $('#edit-pencil').attr("data-desc",obj[key]) | |||
| $('#edit-pencil').attr("data-desc",descriptionText) | |||
| } | |||
| else if(key==="Label"){ | |||
| $('#Label').empty() | |||
| @@ -263,6 +311,29 @@ function renderInfo(obj,accObj,id){ | |||
| } | |||
| $('#Label').append(html) | |||
| } | |||
| } | |||
| else if(key==="CodeCommitID"){ | |||
| let codeCommit = obj[key].slice(0,10) | |||
| let html = `<a style="margin-left:1rem" class="ui label" title="${codeCommit}">${codeCommit}</a>` | |||
| $('#CodeBranch').append(html) | |||
| } | |||
| else if(key==="Parameters"){ | |||
| console.log("obj[key",obj[key]) | |||
| if(obj[key]==='--'){ | |||
| $(`#${key}`).text(obj[key]) | |||
| }else{ | |||
| const parameterArray = obj[key].map(element => { | |||
| let labelValue = `${element.label}=${element.value}` | |||
| return labelValue | |||
| }); | |||
| const parameter = parameterArray.join('; ') | |||
| console.log(parameter) | |||
| $(`#${key}`).text(parameter) | |||
| $(`#${key}`).attr("title",parameter) | |||
| } | |||
| } | |||
| else{ | |||
| $(`#${key}`).text(obj[key]) | |||
| @@ -263,6 +263,7 @@ export default { | |||
| let cName = $("input[name='Name']").val() | |||
| let version = $("input[name='Version']").val() | |||
| let data = $("#formId").serialize() | |||
| let url_href = version === '0.0.1' ? context.url_create_newModel : context.url_create_newVersion | |||
| $("#mask").css({"display":"block","z-index":"9999"}) | |||
| $.ajax({ | |||
| url:url_href, | |||
| @@ -292,7 +293,7 @@ export default { | |||
| if(!this.loadNodeMap.get(row.cName)){ | |||
| const parent = store.states.data | |||
| const index = parent.findIndex(child => child.ID == row.ID) | |||
| parent.splice(index, 1) | |||
| this.getModelList() | |||
| }else{ | |||
| let {tree,treeNode,resolve} = this.loadNodeMap.get(row.cName) | |||
| const keys = Object.keys(store.states.lazyTreeNodeMap); | |||
| @@ -406,6 +407,8 @@ export default { | |||
| this.getModelList() | |||
| this.url = location.href.split('show_model')[0] | |||
| this.submitId.addEventListener("click", this.submit) | |||
| this.url_create_newVersion = this.url + 'create_model' | |||
| this.url_create_newModel = this.url + 'create_new_model' | |||
| }, | |||
| beforeDestroy() { // 实例销毁之前对点击事件进行解绑 | |||
| @@ -517,4 +520,4 @@ export default { | |||
| opacity: .45 !important; | |||
| } | |||
| </style> | |||
| </style> | |||
| @@ -1,6 +1,6 @@ | |||
| @import "~highlight.js/styles/github.css"; | |||
| @import "./vendor/gitGraph.css"; | |||
| // @import "~/remixicon/fonts/remixicon.css"; | |||
| @import "_svg"; | |||
| @import "_tribute"; | |||
| @import "_base"; | |||