@@ -30,9 +30,9 @@ const ( | |||||
) | ) | ||||
const ( | const ( | ||||
NPUResource = "NPU" | |||||
GPUResource = "CPU/GPU" | |||||
AllResource = "all" | |||||
NPUResource = "NPU" | |||||
GPUResource = "CPU/GPU" | |||||
AllResource = "all" | |||||
//notebook storage category | //notebook storage category | ||||
EVSCategory = "EVS" | EVSCategory = "EVS" | ||||
@@ -2173,7 +2173,18 @@ func GetDatasetInfo(uuidStr string) (map[string]DatasetInfo, string, error) { | |||||
log.Error("GetAttachmentsByUUIDs failed: %v", err) | log.Error("GetAttachmentsByUUIDs failed: %v", err) | ||||
return nil, datasetNames, err | return nil, datasetNames, err | ||||
} | } | ||||
for i, attach := range attachs { | |||||
for i, tmpUuid := range uuids { | |||||
var attach *Attachment | |||||
for _, tmpAttach := range attachs { | |||||
if tmpAttach.UUID == tmpUuid { | |||||
attach = tmpAttach | |||||
break | |||||
} | |||||
} | |||||
if attach == nil { | |||||
log.Error("GetAttachmentsByUUIDs failed: %v", err) | |||||
return nil, datasetNames, err | |||||
} | |||||
fileName := strings.TrimSuffix(strings.TrimSuffix(strings.TrimSuffix(attach.Name, ".zip"), ".tar.gz"), ".tgz") | fileName := strings.TrimSuffix(strings.TrimSuffix(strings.TrimSuffix(attach.Name, ".zip"), ".tar.gz"), ".tgz") | ||||
for _, datasetInfo := range datasetInfos { | for _, datasetInfo := range datasetInfos { | ||||
if fileName == datasetInfo.Name { | if fileName == datasetInfo.Name { | ||||
@@ -518,6 +518,10 @@ func UpdateLocalImageStatus(image *Image) error { | |||||
return err | return err | ||||
} | } | ||||
func UpdateAutoIncrementIndex() { | |||||
x.Exec("SELECT setval('image_id_seq', (SELECT MAX(id) from image))") | |||||
} | |||||
func DeleteLocalImage(id int64) error { | func DeleteLocalImage(id int64) error { | ||||
image := new(Image) | image := new(Image) | ||||
_, err := x.ID(id).Delete(image) | _, err := x.ID(id).Delete(image) | ||||
@@ -77,7 +77,10 @@ func (CloudbrainStopMsg) ShouldSend(ctx *TemplateContext) bool { | |||||
} | } | ||||
for _, v := range setting.CloudbrainStoppedNotifyList { | for _, v := range setting.CloudbrainStoppedNotifyList { | ||||
if v == ctx.Cloudbrain.JobType { | if v == ctx.Cloudbrain.JobType { | ||||
return true | |||||
if ctx.Cloudbrain.Duration > 0 && ctx.Cloudbrain.EndTime > 0 { | |||||
return true | |||||
} | |||||
break | |||||
} | } | ||||
} | } | ||||
return false | return false | ||||
@@ -27,11 +27,13 @@ func SendTemplateMsg(template Template, ctx *TemplateContext, userId int64) erro | |||||
} | } | ||||
}() | }() | ||||
if !template.ShouldSend(ctx) { | if !template.ShouldSend(ctx) { | ||||
log.Info("SendTemplateMsg should not Send.jobId=%d jobType=%s", ctx.Cloudbrain.ID, ctx.Cloudbrain.JobType) | |||||
return nil | return nil | ||||
} | } | ||||
openId := models.GetUserWechatOpenId(userId) | openId := models.GetUserWechatOpenId(userId) | ||||
if openId == "" { | if openId == "" { | ||||
log.Error("Wechat openId not exist,userId=%d", userId) | |||||
return errors.New("Wechat openId not exist") | return errors.New("Wechat openId not exist") | ||||
} | } | ||||
req := TemplateMsgRequest{ | req := TemplateMsgRequest{ | ||||
@@ -56,5 +58,6 @@ func SendTemplateMsg(template Template, ctx *TemplateContext, userId int64) erro | |||||
log.Error("SendTemplateMsg err. %v", err) | log.Error("SendTemplateMsg err. %v", err) | ||||
return err | return err | ||||
} | } | ||||
log.Info("SendTemplateMsg success") | |||||
return nil | return nil | ||||
} | } |
@@ -312,6 +312,7 @@ sendjob: | |||||
} | } | ||||
err = models.WithTx(func(ctx models.DBContext) error { | err = models.WithTx(func(ctx models.DBContext) error { | ||||
models.UpdateAutoIncrementIndex() | |||||
if dbImage != nil { | if dbImage != nil { | ||||
dbImage.IsPrivate = params.IsPrivate | dbImage.IsPrivate = params.IsPrivate | ||||
dbImage.Description = params.ImageDescription | dbImage.Description = params.ImageDescription | ||||
@@ -23,9 +23,7 @@ const ( | |||||
NpuWorkDir = "/cache/" | NpuWorkDir = "/cache/" | ||||
CommandPrepareScript = ";mkdir -p output;mkdir -p code;mkdir -p dataset;echo \"start loading script\";wget -q https://git.openi.org.cn/OpenIOSSG/script_for_grampus/archive/master.zip;" + | CommandPrepareScript = ";mkdir -p output;mkdir -p code;mkdir -p dataset;echo \"start loading script\";wget -q https://git.openi.org.cn/OpenIOSSG/script_for_grampus/archive/master.zip;" + | ||||
"echo \"finish loading script\";unzip -q master.zip;cd script_for_grampus;chmod 777 downloader_for_obs uploader_for_obs downloader_for_minio uploader_for_minio;" | |||||
//CommandPrepareScript = "pwd;cd /cache;mkdir -p output;mkdir -p code;mkdir -p dataset;echo \"start loading script\";wget -q https://git.openi.org.cn/OpenIOSSG/script_for_grampus/archive/master.zip;" + | |||||
// "echo \"finish loading script\";unzip -q master.zip;cd script_for_grampus;chmod 777 downloader_for_obs uploader_for_obs downloader_for_minio uploader_for_minio;" | |||||
"echo \"finish loading script\";unzip -q master.zip;cd script_for_grampus;chmod 777 downloader_for_obs uploader_for_npu downloader_for_minio uploader_for_gpu;" | |||||
CodeArchiveName = "master.zip" | CodeArchiveName = "master.zip" | ||||
) | ) | ||||
@@ -134,6 +134,7 @@ type GenerateInferenceJobReq struct { | |||||
ModelVersion string | ModelVersion string | ||||
CkptName string | CkptName string | ||||
ResultUrl string | ResultUrl string | ||||
DatasetName string | |||||
} | } | ||||
type VersionInfo struct { | type VersionInfo struct { | ||||
@@ -690,11 +691,11 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e | |||||
return err | return err | ||||
} | } | ||||
attach, err := models.GetAttachmentByUUID(req.Uuid) | |||||
if err != nil { | |||||
log.Error("GetAttachmentByUUID(%s) failed:%v", strconv.FormatInt(jobResult.JobID, 10), err.Error()) | |||||
return err | |||||
} | |||||
// attach, err := models.GetAttachmentByUUID(req.Uuid) | |||||
// if err != nil { | |||||
// log.Error("GetAttachmentByUUID(%s) failed:%v", strconv.FormatInt(jobResult.JobID, 10), err.Error()) | |||||
// return err | |||||
// } | |||||
jobID := strconv.FormatInt(jobResult.JobID, 10) | jobID := strconv.FormatInt(jobResult.JobID, 10) | ||||
err = models.CreateCloudbrain(&models.Cloudbrain{ | err = models.CreateCloudbrain(&models.Cloudbrain{ | ||||
Status: TransTrainJobStatus(jobResult.Status), | Status: TransTrainJobStatus(jobResult.Status), | ||||
@@ -708,7 +709,7 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e | |||||
VersionID: jobResult.VersionID, | VersionID: jobResult.VersionID, | ||||
VersionName: jobResult.VersionName, | VersionName: jobResult.VersionName, | ||||
Uuid: req.Uuid, | Uuid: req.Uuid, | ||||
DatasetName: attach.Name, | |||||
DatasetName: req.DatasetName, | |||||
CommitID: req.CommitID, | CommitID: req.CommitID, | ||||
EngineID: req.EngineID, | EngineID: req.EngineID, | ||||
TrainUrl: req.TrainUrl, | TrainUrl: req.TrainUrl, | ||||
@@ -7,6 +7,7 @@ package wechat | |||||
import ( | import ( | ||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/auth/wechat" | "code.gitea.io/gitea/modules/auth/wechat" | ||||
"code.gitea.io/gitea/modules/log" | |||||
"code.gitea.io/gitea/modules/notification/base" | "code.gitea.io/gitea/modules/notification/base" | ||||
) | ) | ||||
@@ -24,8 +25,10 @@ func NewNotifier() base.Notifier { | |||||
} | } | ||||
func (*wechatNotifier) NotifyChangeCloudbrainStatus(cloudbrain *models.Cloudbrain, oldStatus string) { | func (*wechatNotifier) NotifyChangeCloudbrainStatus(cloudbrain *models.Cloudbrain, oldStatus string) { | ||||
log.Info("NotifyChangeCloudbrainStatus cloudbrain.id=%d cloudbrain.status=%s oldStatus=%s", cloudbrain.ID, cloudbrain.Status, oldStatus) | |||||
operateType := wechat.GetJobOperateTypeFromCloudbrainStatus(cloudbrain) | operateType := wechat.GetJobOperateTypeFromCloudbrainStatus(cloudbrain) | ||||
if operateType == "" { | if operateType == "" { | ||||
log.Info("NotifyChangeCloudbrainStatus operateType is incorrect") | |||||
return | return | ||||
} | } | ||||
template := wechat.GetTemplateFromOperateType(operateType) | template := wechat.GetTemplateFromOperateType(operateType) | ||||
@@ -1099,7 +1099,8 @@ modelarts.status=Status | |||||
modelarts.createtime=CreateTime | modelarts.createtime=CreateTime | ||||
modelarts.version_nums = Version Nums | modelarts.version_nums = Version Nums | ||||
modelarts.version = Version | modelarts.version = Version | ||||
modelarts.computing_resources=compute Resources | |||||
modelarts.computing_resources=Compute Resources | |||||
modelarts.cluster.computing_resources=Cluster/Compute Resources | |||||
modelarts.ai_center=Ai Center | modelarts.ai_center=Ai Center | ||||
modelarts.card_type=Card Type | modelarts.card_type=Card Type | ||||
modelarts.cluster=Cluster | modelarts.cluster=Cluster | ||||
@@ -2990,15 +2991,15 @@ mirror_sync_delete = synced and deleted reference <code>%[2]s</code> at <a href= | |||||
approve_pull_request = `approved <a href="%s/pulls/%s">%s#%[2]s</a>` | approve_pull_request = `approved <a href="%s/pulls/%s">%s#%[2]s</a>` | ||||
reject_pull_request = `suggested changes for <a href="%s/pulls/%s">%s#%[2]s</a>` | reject_pull_request = `suggested changes for <a href="%s/pulls/%s">%s#%[2]s</a>` | ||||
upload_dataset=`upload dataset <a href="%s/datasets">%s</a>` | upload_dataset=`upload dataset <a href="%s/datasets">%s</a>` | ||||
task_gpudebugjob=`created CPU/GPU type debugging task<a href="%s/cloudbrain/%s">%s</a>` | |||||
task_gpudebugjob=`created CPU/GPU type debugging task <a href="%s/cloudbrain/%s">%s</a>` | |||||
task_npudebugjob=`created NPU type debugging task <a href="%s/modelarts/notebook/%s">%s</a>` | task_npudebugjob=`created NPU type debugging task <a href="%s/modelarts/notebook/%s">%s</a>` | ||||
task_nputrainjob=`created NPU training task<a href="%s/modelarts/train-job/%s">%s</a>` | |||||
task_nputrainjob=`created NPU training task <a href="%s/modelarts/train-job/%s">%s</a>` | |||||
task_inferencejob=`created reasoning task <a href="%s/modelarts/inference-job/%s">%s</a>` | task_inferencejob=`created reasoning task <a href="%s/modelarts/inference-job/%s">%s</a>` | ||||
task_benchmark=`created profiling task <a href="%s/cloudbrain/benchmark/%s">%s</a>` | task_benchmark=`created profiling task <a href="%s/cloudbrain/benchmark/%s">%s</a>` | ||||
task_createmodel=`created new model <a href="%s/modelmanage/show_model_info?name=%s">%s</a>` | task_createmodel=`created new model <a href="%s/modelmanage/show_model_info?name=%s">%s</a>` | ||||
task_gputrainjob=`created CPU/GPU training task<a href="%s/cloudbrain/train-job/%s">%s</a>` | |||||
task_c2netnputrainjob=`created NPU training task<a href="%s/grampus/train-job/%s">%s</a>` | |||||
task_c2netgputrainjob=`created CPU/GPU training task<a href="%s/grampus/train-job/%s">%s</a>` | |||||
task_gputrainjob=`created CPU/GPU training task <a href="%s/cloudbrain/train-job/%s">%s</a>` | |||||
task_c2netnputrainjob=`created NPU training task <a href="%s/grampus/train-job/%s">%s</a>` | |||||
task_c2netgputrainjob=`created CPU/GPU training task <a href="%s/grampus/train-job/%s">%s</a>` | |||||
[tool] | [tool] | ||||
ago = %s ago | ago = %s ago | ||||
@@ -3092,6 +3093,8 @@ all_ai_center=All Computing NET | |||||
resource_cluster = Resource Cluster | resource_cluster = Resource Cluster | ||||
resource_cluster_openi = OpenI Resource Cluster | resource_cluster_openi = OpenI Resource Cluster | ||||
resource_cluster_c2net = China Computing NET | resource_cluster_c2net = China Computing NET | ||||
resource_cluster_openi_simple = OpenI | |||||
resource_cluster_c2net_simple = Computing NET | |||||
compute_resource = Computing resources | compute_resource = Computing resources | ||||
task_name = Task name | task_name = Task name | ||||
task_type = Task type | task_type = Task type | ||||
@@ -1110,6 +1110,7 @@ modelarts.deletetime=删除时间 | |||||
modelarts.version_nums=版本数 | modelarts.version_nums=版本数 | ||||
modelarts.version=版本 | modelarts.version=版本 | ||||
modelarts.computing_resources=计算资源 | modelarts.computing_resources=计算资源 | ||||
modelarts.cluster.computing_resources=集群/计算资源 | |||||
modelarts.ai_center=智算中心 | modelarts.ai_center=智算中心 | ||||
modelarts.card_type=卡类型 | modelarts.card_type=卡类型 | ||||
modelarts.cluster=集群 | modelarts.cluster=集群 | ||||
@@ -3106,6 +3107,8 @@ all_ai_center=全部智算中心 | |||||
resource_cluster = 算力集群 | resource_cluster = 算力集群 | ||||
resource_cluster_openi = 启智集群 | resource_cluster_openi = 启智集群 | ||||
resource_cluster_c2net = 智算网络集群 | resource_cluster_c2net = 智算网络集群 | ||||
resource_cluster_openi_simple = 启智 | |||||
resource_cluster_c2net_simple = 智算网络 | |||||
compute_resource = 计算资源 | compute_resource = 计算资源 | ||||
task_name = 任务名称 | task_name = 任务名称 | ||||
task_type = 任务类型 | task_type = 任务类型 | ||||
@@ -916,6 +916,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Group("/cloudbrain", func() { | m.Group("/cloudbrain", func() { | ||||
m.Get("/:id", repo.GetCloudbrainTask) | m.Get("/:id", repo.GetCloudbrainTask) | ||||
m.Get("/:id/log", repo.CloudbrainGetLog) | m.Get("/:id/log", repo.CloudbrainGetLog) | ||||
m.Get("/:id/download_log_file", repo.CloudbrainDownloadLogFile) | |||||
m.Group("/train-job", func() { | m.Group("/train-job", func() { | ||||
m.Group("/:jobid", func() { | m.Group("/:jobid", func() { | ||||
m.Get("", repo.GetModelArtsTrainJobVersion) | m.Get("", repo.GetModelArtsTrainJobVersion) | ||||
@@ -6,13 +6,17 @@ | |||||
package repo | package repo | ||||
import ( | import ( | ||||
"code.gitea.io/gitea/modules/notification" | |||||
"bufio" | |||||
"encoding/json" | "encoding/json" | ||||
"io" | |||||
"net/http" | "net/http" | ||||
"os" | |||||
"sort" | "sort" | ||||
"strings" | "strings" | ||||
"time" | "time" | ||||
"code.gitea.io/gitea/modules/notification" | |||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
@@ -366,7 +370,7 @@ func CloudbrainForModelConvertGetLog(ctx *context.Context) { | |||||
ctx.JSON(http.StatusOK, result) | ctx.JSON(http.StatusOK, result) | ||||
} | } | ||||
func CloudbrainGetLog(ctx *context.Context) { | |||||
func CloudbrainDownloadLogFile(ctx *context.Context) { | |||||
ID := ctx.Params(":id") | ID := ctx.Params(":id") | ||||
job, err := models.GetCloudbrainByID(ID) | job, err := models.GetCloudbrainByID(ID) | ||||
if err != nil { | if err != nil { | ||||
@@ -374,14 +378,124 @@ func CloudbrainGetLog(ctx *context.Context) { | |||||
ctx.ServerError(err.Error(), err) | ctx.ServerError(err.Error(), err) | ||||
return | return | ||||
} | } | ||||
prefix := "/" + setting.CBCodePathPrefix + job.JobName + "/model" | |||||
files, err := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, "") | |||||
if err != nil { | |||||
log.Error("query cloudbrain model failed: %v", err) | |||||
return | |||||
} | |||||
fileName := "" | |||||
for _, file := range files { | |||||
if strings.HasSuffix(file.FileName, "log.txt") { | |||||
fileName = file.FileName | |||||
break | |||||
} | |||||
} | |||||
if fileName != "" { | |||||
url, err := storage.Attachments.PresignedGetURL(prefix+"/"+fileName, fileName) | |||||
if err != nil { | |||||
log.Error("Get minio get SignedUrl failed: %v", err.Error(), ctx.Data["msgID"]) | |||||
ctx.ServerError("Get minio get SignedUrl failed", err) | |||||
return | |||||
} | |||||
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) | |||||
} | |||||
} | |||||
result := CloudbrainGetLogByJobId(job.JobID, job.JobName) | |||||
func CloudbrainGetLog(ctx *context.Context) { | |||||
ID := ctx.Params(":id") | |||||
startLine := ctx.QueryInt("base_line") | |||||
lines := ctx.QueryInt("lines") | |||||
endLine := startLine + lines | |||||
order := ctx.Query("order") | |||||
if order == "asc" { | |||||
endLine = startLine | |||||
startLine = endLine - lines | |||||
if startLine < 0 { | |||||
startLine = 0 | |||||
} | |||||
} | |||||
job, err := models.GetCloudbrainByID(ID) | |||||
if err != nil { | |||||
log.Error("GetCloudbrainByJobName failed: %v", err, ctx.Data["MsgID"]) | |||||
ctx.ServerError(err.Error(), err) | |||||
return | |||||
} | |||||
result := getLogFromModelDir(job.JobName, startLine, endLine) | |||||
if result == nil { | if result == nil { | ||||
log.Error("GetJobLog failed: %v", err, ctx.Data["MsgID"]) | log.Error("GetJobLog failed: %v", err, ctx.Data["MsgID"]) | ||||
ctx.ServerError(err.Error(), err) | ctx.ServerError(err.Error(), err) | ||||
return | return | ||||
} | } | ||||
ctx.JSON(http.StatusOK, result) | |||||
re := map[string]interface{}{ | |||||
"JobID": ID, | |||||
"LogFileName": result["FileName"], | |||||
"StartLine": startLine, | |||||
"EndLine": result["endLine"], | |||||
"Content": result["Content"], | |||||
"Lines": result["lines"], | |||||
"CanLogDownload": result["FileName"] != "", | |||||
} | |||||
//result := CloudbrainGetLogByJobId(job.JobID, job.JobName) | |||||
ctx.JSON(http.StatusOK, re) | |||||
} | |||||
func getLogFromModelDir(jobName string, startLine int, endLine int) map[string]interface{} { | |||||
prefix := "/" + setting.CBCodePathPrefix + jobName + "/model" | |||||
files, err := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, "") | |||||
if err != nil { | |||||
log.Error("query cloudbrain model failed: %v", err) | |||||
return nil | |||||
} | |||||
re := "" | |||||
fileName := "" | |||||
count := 0 | |||||
fileEndLine := endLine | |||||
for _, file := range files { | |||||
if strings.HasSuffix(file.FileName, "log.txt") { | |||||
fileName = file.FileName | |||||
path := storage.GetMinioPath(jobName+"/model/", file.FileName) | |||||
log.Info("path=" + path) | |||||
reader, err := os.Open(path) | |||||
defer reader.Close() | |||||
if err == nil { | |||||
r := bufio.NewReader(reader) | |||||
for i := 0; i < endLine; i++ { | |||||
line, error := r.ReadString('\n') | |||||
log.Info("line=" + line) | |||||
fileEndLine = i | |||||
if error == io.EOF { | |||||
log.Info("read file completed.") | |||||
break | |||||
} | |||||
if error != nil { | |||||
log.Info("read file error." + error.Error()) | |||||
break | |||||
} | |||||
if error == nil { | |||||
if i >= startLine { | |||||
re = re + line | |||||
count++ | |||||
} | |||||
} | |||||
} | |||||
} else { | |||||
log.Info("error:" + err.Error()) | |||||
} | |||||
break | |||||
} | |||||
} | |||||
return map[string]interface{}{ | |||||
"JobName": jobName, | |||||
"Content": re, | |||||
"FileName": fileName, | |||||
"lines": count, | |||||
"endLine": fileEndLine, | |||||
} | |||||
} | } | ||||
func CloudBrainModelConvertList(ctx *context.APIContext) { | func CloudBrainModelConvertList(ctx *context.APIContext) { | ||||
@@ -154,6 +154,7 @@ func GetModelArtsTrainJobVersion(ctx *context.APIContext) { | |||||
if job.StartTime == 0 && result.JobInfo.StartedAt > 0 { | if job.StartTime == 0 && result.JobInfo.StartedAt > 0 { | ||||
job.StartTime = timeutil.TimeStamp(result.JobInfo.StartedAt) | job.StartTime = timeutil.TimeStamp(result.JobInfo.StartedAt) | ||||
} | } | ||||
oldStatus := job.Status | |||||
job.Status = grampus.TransTrainJobStatus(result.JobInfo.Status) | job.Status = grampus.TransTrainJobStatus(result.JobInfo.Status) | ||||
job.Duration = result.JobInfo.RunSec | job.Duration = result.JobInfo.RunSec | ||||
job.TrainJobDuration = models.ConvertDurationToStr(job.Duration) | job.TrainJobDuration = models.ConvertDurationToStr(job.Duration) | ||||
@@ -176,6 +177,9 @@ func GetModelArtsTrainJobVersion(ctx *context.APIContext) { | |||||
aiCenterName = temp[1] | aiCenterName = temp[1] | ||||
} | } | ||||
} | } | ||||
if oldStatus != job.Status { | |||||
notification.NotifyChangeCloudbrainStatus(job, oldStatus) | |||||
} | |||||
err = models.UpdateTrainJobVersion(job) | err = models.UpdateTrainJobVersion(job) | ||||
if err != nil { | if err != nil { | ||||
log.Error("UpdateJob failed:", err) | log.Error("UpdateJob failed:", err) | ||||
@@ -767,10 +767,6 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo | |||||
command += commandDownload | command += commandDownload | ||||
} | } | ||||
//check download result | |||||
commandCheckRes := "bash -c \"[[ $? -eq 0 ]] && exit 0 || exit -1;\";" | |||||
command += commandCheckRes | |||||
//unzip code & dataset | //unzip code & dataset | ||||
toolUnzip := "unzip -q '" | toolUnzip := "unzip -q '" | ||||
if strings.HasSuffix(datasetName, ".tar.gz") { | if strings.HasSuffix(datasetName, ".tar.gz") { | ||||
@@ -779,16 +775,22 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo | |||||
commandUnzip := "cd " + workDir + "code;unzip -q master.zip;echo \"start to unzip dataset\";cd " + workDir + "dataset;" + toolUnzip + datasetName + "';" | commandUnzip := "cd " + workDir + "code;unzip -q master.zip;echo \"start to unzip dataset\";cd " + workDir + "dataset;" + toolUnzip + datasetName + "';" | ||||
command += commandUnzip | command += commandUnzip | ||||
//check unzip result | |||||
commandCheckRes = "bash -c \"[[ $? -eq 0 ]] && exit 0 || exit -1;\";" | |||||
command += commandCheckRes | |||||
command += "echo \"unzip finished;start to exec code;\";" | command += "echo \"unzip finished;start to exec code;\";" | ||||
// set export | |||||
var commandExport string | |||||
if processorType == grampus.ProcessorTypeNPU { | |||||
commandExport = "export bucket=" + setting.Bucket + " && export remote_path=" + outputRemotePath + ";" | |||||
} else if processorType == grampus.ProcessorTypeGPU { | |||||
commandExport = "export env=" + setting.Grampus.Env + " && export remote_path=" + outputRemotePath + ";" | |||||
} | |||||
command += commandExport | |||||
//exec code | //exec code | ||||
var parameters models.Parameters | var parameters models.Parameters | ||||
var paramCode string | var paramCode string | ||||
param := make([]models.Parameter, 0) | |||||
if len(paramSrc) != 0 { | if len(paramSrc) != 0 { | ||||
err := json.Unmarshal([]byte(paramSrc), ¶meters) | err := json.Unmarshal([]byte(paramSrc), ¶meters) | ||||
if err != nil { | if err != nil { | ||||
@@ -797,10 +799,6 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo | |||||
} | } | ||||
for _, parameter := range parameters.Parameter { | for _, parameter := range parameters.Parameter { | ||||
param = append(param, models.Parameter{ | |||||
Label: parameter.Label, | |||||
Value: parameter.Value, | |||||
}) | |||||
paramCode += " --" + parameter.Label + "=" + parameter.Value | paramCode += " --" + parameter.Label + "=" + parameter.Value | ||||
} | } | ||||
} | } | ||||
@@ -820,15 +818,15 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo | |||||
//upload models | //upload models | ||||
if processorType == grampus.ProcessorTypeNPU { | if processorType == grampus.ProcessorTypeNPU { | ||||
commandUpload := "cd " + workDir + "script_for_grampus/;./uploader_for_obs " + setting.Bucket + " " + outputRemotePath + " " + workDir + "output/;" | |||||
commandUpload := "cd " + workDir + "script_for_grampus/;./uploader_for_npu " + setting.Bucket + " " + outputRemotePath + " " + workDir + "output/;" | |||||
command += commandUpload | command += commandUpload | ||||
} else if processorType == grampus.ProcessorTypeGPU { | } else if processorType == grampus.ProcessorTypeGPU { | ||||
commandUpload := "cd " + workDir + "script_for_grampus/;./uploader_for_minio " + setting.Grampus.Env + " " + outputRemotePath + " " + workDir + "output/;" | |||||
commandUpload := "cd " + workDir + "script_for_grampus/;./uploader_for_gpu " + setting.Grampus.Env + " " + outputRemotePath + " " + workDir + "output/;" | |||||
command += commandUpload | command += commandUpload | ||||
} | } | ||||
//check exec result | //check exec result | ||||
commandCheckRes = "bash -c \"[[ $result -eq 0 ]] && exit 0 || exit -1\"" | |||||
commandCheckRes := "bash -c \"[[ $result -eq 0 ]] && exit 0 || exit -1\"" | |||||
command += commandCheckRes | command += commandCheckRes | ||||
return command, nil | return command, nil | ||||
@@ -896,12 +896,12 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||||
ctx.Data["display_job_name"] = task.DisplayJobName | ctx.Data["display_job_name"] = task.DisplayJobName | ||||
ctx.Data["job_name"] = task.JobName | ctx.Data["job_name"] = task.JobName | ||||
attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||||
if err != nil { | |||||
ctx.ServerError("GetAllUserAttachments failed:", err) | |||||
return err | |||||
} | |||||
ctx.Data["attachments"] = attachs | |||||
// attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||||
// if err != nil { | |||||
// ctx.ServerError("GetAllUserAttachments failed:", err) | |||||
// return err | |||||
// } | |||||
// ctx.Data["attachments"] = attachs | |||||
var resourcePools modelarts.ResourcePool | var resourcePools modelarts.ResourcePool | ||||
if err = json.Unmarshal([]byte(setting.ResourcePools), &resourcePools); err != nil { | if err = json.Unmarshal([]byte(setting.ResourcePools), &resourcePools); err != nil { | ||||
@@ -945,12 +945,16 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||||
ctx.ServerError("GetBranches error:", err) | ctx.ServerError("GetBranches error:", err) | ||||
return err | return err | ||||
} | } | ||||
_, _, datasetNames, _, err := getDatasUrlListByUUIDS(task.Uuid) | |||||
if err != nil { | |||||
ctx.ServerError("GetAllUserAttachments failed:", err) | |||||
return err | |||||
} | |||||
ctx.Data["branches"] = branches | ctx.Data["branches"] = branches | ||||
ctx.Data["branch_name"] = task.BranchName | ctx.Data["branch_name"] = task.BranchName | ||||
ctx.Data["description"] = task.Description | ctx.Data["description"] = task.Description | ||||
ctx.Data["boot_file"] = task.BootFile | ctx.Data["boot_file"] = task.BootFile | ||||
ctx.Data["dataset_name"] = task.DatasetName | |||||
ctx.Data["dataset_name"] = datasetNames | |||||
ctx.Data["work_server_number"] = task.WorkServerNumber | ctx.Data["work_server_number"] = task.WorkServerNumber | ||||
ctx.Data["flavor_name"] = task.FlavorName | ctx.Data["flavor_name"] = task.FlavorName | ||||
ctx.Data["engine_name"] = task.EngineName | ctx.Data["engine_name"] = task.EngineName | ||||
@@ -1972,7 +1976,7 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||||
codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath | codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath | ||||
resultObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.ResultPath + VersionOutputPath + "/" | resultObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.ResultPath + VersionOutputPath + "/" | ||||
logObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.LogPath + VersionOutputPath + "/" | logObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.LogPath + VersionOutputPath + "/" | ||||
dataPath := "/" + setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + uuid + "/" | |||||
//dataPath := "/" + setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + uuid + "/" | |||||
branchName := form.BranchName | branchName := form.BranchName | ||||
FlavorName := form.FlavorName | FlavorName := form.FlavorName | ||||
EngineName := form.EngineName | EngineName := form.EngineName | ||||
@@ -2050,6 +2054,13 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||||
gitRepo, _ := git.OpenRepository(repo.RepoPath()) | gitRepo, _ := git.OpenRepository(repo.RepoPath()) | ||||
commitID, _ := gitRepo.GetBranchCommitID(branchName) | commitID, _ := gitRepo.GetBranchCommitID(branchName) | ||||
_, dataUrl, datasetNames, _, err := getDatasUrlListByUUIDS(uuid) | |||||
if err != nil { | |||||
inferenceJobErrorNewDataPrepare(ctx, form) | |||||
ctx.RenderWithErr(ctx.Tr(errStr), tplModelArtsInferenceJobNew, &form) | |||||
return | |||||
} | |||||
if err := downloadCode(repo, codeLocalPath, branchName); err != nil { | if err := downloadCode(repo, codeLocalPath, branchName); err != nil { | ||||
log.Error("Create task failed, server timed out: %s (%v)", repo.FullName(), err) | log.Error("Create task failed, server timed out: %s (%v)", repo.FullName(), err) | ||||
inferenceJobErrorNewDataPrepare(ctx, form) | inferenceJobErrorNewDataPrepare(ctx, form) | ||||
@@ -2120,7 +2131,7 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||||
req := &modelarts.GenerateInferenceJobReq{ | req := &modelarts.GenerateInferenceJobReq{ | ||||
JobName: jobName, | JobName: jobName, | ||||
DisplayJobName: displayJobName, | DisplayJobName: displayJobName, | ||||
DataUrl: dataPath, | |||||
DataUrl: dataUrl, | |||||
Description: description, | Description: description, | ||||
CodeObsPath: codeObsPath, | CodeObsPath: codeObsPath, | ||||
BootFileUrl: codeObsPath + bootFile, | BootFileUrl: codeObsPath + bootFile, | ||||
@@ -2146,6 +2157,7 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||||
ModelVersion: modelVersion, | ModelVersion: modelVersion, | ||||
CkptName: ckptName, | CkptName: ckptName, | ||||
ResultUrl: resultObsPath, | ResultUrl: resultObsPath, | ||||
DatasetName: datasetNames, | |||||
} | } | ||||
err = modelarts.GenerateInferenceJob(ctx, req) | err = modelarts.GenerateInferenceJob(ctx, req) | ||||
@@ -2700,11 +2712,23 @@ func getDatasUrlListByUUIDS(uuidStr string) ([]models.Datasurl, string, string, | |||||
datasetInfos := make(map[string]models.DatasetInfo) | datasetInfos := make(map[string]models.DatasetInfo) | ||||
attachs, err := models.GetAttachmentsByUUIDs(uuids) | attachs, err := models.GetAttachmentsByUUIDs(uuids) | ||||
if err != nil { | |||||
if err != nil || len(attachs) != len(uuids) { | |||||
log.Error("GetAttachmentsByUUIDs failed: %v", err) | log.Error("GetAttachmentsByUUIDs failed: %v", err) | ||||
return datasUrlList, dataUrl, datasetNames, isMultiDataset, errors.New("GetAttachmentsByUUIDs failed") | return datasUrlList, dataUrl, datasetNames, isMultiDataset, errors.New("GetAttachmentsByUUIDs failed") | ||||
} | } | ||||
for i, attach := range attachs { | |||||
for i, tmpUuid := range uuids { | |||||
var attach *models.Attachment | |||||
for _, tmpAttach := range attachs { | |||||
if tmpAttach.UUID == tmpUuid { | |||||
attach = tmpAttach | |||||
break | |||||
} | |||||
} | |||||
if attach == nil { | |||||
log.Error("GetAttachmentsByUUIDs failed: %v", err) | |||||
return datasUrlList, dataUrl, datasetNames, isMultiDataset, errors.New("GetAttachmentsByUUIDs failed") | |||||
} | |||||
fileName := strings.TrimSuffix(strings.TrimSuffix(strings.TrimSuffix(attach.Name, ".zip"), ".tar.gz"), ".tgz") | fileName := strings.TrimSuffix(strings.TrimSuffix(strings.TrimSuffix(attach.Name, ".zip"), ".tar.gz"), ".tgz") | ||||
for _, datasetInfo := range datasetInfos { | for _, datasetInfo := range datasetInfos { | ||||
if fileName == datasetInfo.Name { | if fileName == datasetInfo.Name { | ||||
@@ -1100,7 +1100,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.CloudBrainTrainJobDel) | m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.CloudBrainTrainJobDel) | ||||
//m.Get("/models", reqRepoCloudBrainReader, repo.CloudBrainShowModels) | //m.Get("/models", reqRepoCloudBrainReader, repo.CloudBrainShowModels) | ||||
m.Get("/download_model", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.CloudBrainDownloadModel) | m.Get("/download_model", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.CloudBrainDownloadModel) | ||||
//m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, repo.TrainJobNewVersion) | |||||
//m.Get("/get_log", cloudbrain.AdminOrJobCreaterRightForTrain, repo.GetLogFromModelDir) | |||||
//m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion) | //m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion) | ||||
}) | }) | ||||
m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, repo.CloudBrainTrainJobNew) | m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, repo.CloudBrainTrainJobNew) | ||||
@@ -186,8 +186,10 @@ | |||||
{{end}} | {{end}} | ||||
</select> | </select> | ||||
</div> | </div> | ||||
<!-- 数据集 --> | |||||
{{template "custom/select_dataset_train" .}} | |||||
<!-- 数据集--> | |||||
<div id="select-multi-dataset"> | |||||
</div> | |||||
<span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 1rem;"></span> | <span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 1rem;"></span> | ||||
<div class="inline min_title field required"> | <div class="inline min_title field required"> | ||||
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | ||||
@@ -268,7 +268,7 @@ | |||||
<a class="item load-model-file" data-tab="four" | <a class="item load-model-file" data-tab="four" | ||||
data-gpu-flag="true" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/cloudbrain/inference-job/{{.JobID}}/result_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a> | data-gpu-flag="true" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/cloudbrain/inference-job/{{.JobID}}/result_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a> | ||||
</div> | </div> | ||||
<div class="ui tab active" data-tab="first" style="height:400px"> | |||||
<div class="ui tab active" data-tab="first"> | |||||
<div style="padding-top: 10px;"> | <div style="padding-top: 10px;"> | ||||
<div class="tab_2_content"> | <div class="tab_2_content"> | ||||
<div class="ac-grid ac-grid-col2"> | <div class="ac-grid ac-grid-col2"> | ||||
@@ -461,19 +461,7 @@ | |||||
</div> | </div> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
<tr class="ti-no-ng-animate"> | |||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||||
{{$.i18n.Tr "repo.modelarts.infer_dataset"}} | |||||
</td> | |||||
<td class="ti-text-form-content"> | |||||
<div class="text-span text-span-w"> | |||||
{{range $m ,$n := $.datasetDownload}} | |||||
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a> | |||||
{{end}} | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
<tr class="ti-no-ng-animate"> | <tr class="ti-no-ng-animate"> | ||||
<td class="ti-no-ng-animate ti-text-form-label text-width80" > | <td class="ti-no-ng-animate ti-text-form-label text-width80" > | ||||
{{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}} | {{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}} | ||||
@@ -504,6 +492,22 @@ | |||||
</table> | </table> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div style="clear:both"> | |||||
<table style="border:none" class="ui fixed small stackable table"> | |||||
<thead> | |||||
<tr><th style="color: #8a8e99;font-size:12px" class="three wide left aligned">数据集文件</th> | |||||
</tr></thead> | |||||
<tbody> | |||||
{{range $m ,$n := $.datasetDownload}} | |||||
<tr> | |||||
<td style="word-wrap: break-word;word-break: break-all;"><a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a></td> | |||||
</tr> | |||||
{{end}} | |||||
</tbody> | |||||
</table> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -364,18 +364,7 @@ | |||||
</td> | </td> | ||||
</tr> | </tr> | ||||
<tr class="ti-no-ng-animate"> | |||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||||
{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}} | |||||
</td> | |||||
<td class="ti-text-form-content"> | |||||
<div class="text-span text-span-w" | |||||
id="{{.VersionName}}-duration"> | |||||
{{$.duration}} | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
@@ -404,20 +393,7 @@ | |||||
</div> | </div> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
<tr class="ti-no-ng-animate"> | |||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||||
{{$.i18n.Tr "repo.modelarts.train_job.dataset"}} | |||||
</td> | |||||
<td class="ti-text-form-content"> | |||||
<div class="text-span text-span-w" | |||||
id="{{.VersionName}}-BenchmarkTypeName"> | |||||
{{range $m ,$n := $.datasetDownload}} | |||||
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a> | |||||
{{end}} | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
<tr class="ti-no-ng-animate"> | <tr class="ti-no-ng-animate"> | ||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | <td class="ti-no-ng-animate ti-text-form-label text-width80"> | ||||
@@ -496,14 +472,40 @@ | |||||
</div> | </div> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
<tr class="ti-no-ng-animate"> | |||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||||
{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}} | |||||
</td> | |||||
<td class="ti-text-form-content"> | |||||
<div class="text-span text-span-w" | |||||
id="{{.VersionName}}-duration"> | |||||
{{$.duration}} | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div style="clear:both"> | |||||
<table style="border:none" class="ui fixed small stackable table"> | |||||
<thead> | |||||
<tr><th style="color: #8a8e99;font-size:12px" class="three wide left aligned">数据集文件</th> | |||||
</tr></thead> | |||||
<tbody> | |||||
{{range $m ,$n := $.datasetDownload}} | |||||
<tr> | |||||
<td style="word-wrap: break-word;word-break: break-all;"><a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a></td> | |||||
</tr> | |||||
{{end}} | |||||
</tbody> | |||||
</table> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="ui tab" data-tab="second{{$k}}"> | <div class="ui tab" data-tab="second{{$k}}"> | ||||
@@ -286,10 +286,14 @@ | |||||
<div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | <div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | ||||
<a class="active item" | <a class="active item" | ||||
data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | ||||
<a class="item" data-tab="second{{$k}}" | <a class="item" data-tab="second{{$k}}" | ||||
onclick="javascript:parseInfo()">{{$.i18n.Tr "repo.cloudbrain.runinfo"}}</a> | onclick="javascript:parseInfo()">{{$.i18n.Tr "repo.cloudbrain.runinfo"}}</a> | ||||
<a class="item" data-tab="third{{$k}}" | |||||
onclick="loadLog({{.VersionName}})">{{$.i18n.Tr "repo.modelarts.log"}}</a> | |||||
<a class="item log_bottom" data-tab="third{{$k}}" | |||||
data-version="{{.VersionName}}">{{$.i18n.Tr "repo.modelarts.log"}}</a> | |||||
<a class="item load-model-file" data-tab="four{{$k}}" data-gpu-flag="true" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/cloudbrain/train-job/{{.JobID}}/model_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a> | <a class="item load-model-file" data-tab="four{{$k}}" data-gpu-flag="true" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/cloudbrain/train-job/{{.JobID}}/model_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a> | ||||
</div> | </div> | ||||
<div class="ui tab active" data-tab="first{{$k}}"> | <div class="ui tab active" data-tab="first{{$k}}"> | ||||
@@ -423,19 +427,7 @@ | |||||
</td> | </td> | ||||
</tr> | </tr> | ||||
<tr class="ti-no-ng-animate"> | |||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||||
{{$.i18n.Tr "repo.modelarts.train_job.train_dataset"}} | |||||
</td> | |||||
<td class="ti-text-form-content"> | |||||
<div class="text-span text-span-w"> | |||||
{{range $m ,$n := $.datasetDownload}} | |||||
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a> | |||||
{{end}} | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
<tr class="ti-no-ng-animate"> | <tr class="ti-no-ng-animate"> | ||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | <td class="ti-no-ng-animate ti-text-form-label text-width80"> | ||||
@@ -464,6 +456,22 @@ | |||||
</table> | </table> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div style="clear:both"> | |||||
<table style="border:none" class="ui fixed small stackable table"> | |||||
<thead> | |||||
<tr><th style="color: #8a8e99;font-size:12px" class="three wide left aligned">数据集文件</th> | |||||
</tr></thead> | |||||
<tbody> | |||||
{{range $m ,$n := $.datasetDownload}} | |||||
<tr> | |||||
<td style="word-wrap: break-word;word-break: break-all;"><a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a></td> | |||||
</tr> | |||||
{{end}} | |||||
</tbody> | |||||
</table> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -474,7 +482,7 @@ | |||||
<div class="ui message message{{.VersionName}}" style="display: none;"> | <div class="ui message message{{.VersionName}}" style="display: none;"> | ||||
<div id="header"></div> | <div id="header"></div> | ||||
</div> | </div> | ||||
<div class="ui attached log" id="log{{.VersionName}}" | |||||
<div class="ui attached log" id="log_state{{.VersionName}}" | |||||
style="height: 390px !important; overflow: auto;"> | style="height: 390px !important; overflow: auto;"> | ||||
<input type="hidden" id="json_value" value="{{$.result.JobStatus.AppExitDiagnostics}}"> | <input type="hidden" id="json_value" value="{{$.result.JobStatus.AppExitDiagnostics}}"> | ||||
<input type="hidden" id="ExitDiagnostics" value="{{$.ExitDiagnostics}}"> | <input type="hidden" id="ExitDiagnostics" value="{{$.ExitDiagnostics}}"> | ||||
@@ -488,18 +496,41 @@ | |||||
</div> | </div> | ||||
<div class="ui tab" data-tab="third{{$k}}"> | <div class="ui tab" data-tab="third{{$k}}"> | ||||
<div> | |||||
<div> | |||||
<a id="{{.VersionName}}-log-down" | |||||
class='{{if $.canDownload}}ti-download-file{{else}}disabled{{end}}' | |||||
href="/api/v1/repos/{{$.RepoRelPath}}/cloudbrain/train-job/{{.JobID}}/download_log_file"> | |||||
<i class="ri-download-cloud-2-line"></i> | |||||
<span style="margin-left: 0.3rem;">{{$.i18n.Tr "repo.modelarts.download_log"}}</span> | |||||
</a> | |||||
</div> | |||||
<div | |||||
style="position: relative;border: 1px solid rgba(0,0,0,.2);padding: 0 10px;margin-top: 10px;"> | |||||
<span> | |||||
<a title="滚动到顶部" style="position: absolute; right: -32px;cursor: pointer;" | |||||
class="log_top" data-version="{{.VersionName}}"><i class="icon-to-top"></i></a> | |||||
</span> | |||||
<span class="log-info-{{.VersionName}}"> | |||||
<a title="滚动到底部" style="position: absolute; bottom: 10px;right: -32px;cursor: pointer;" | |||||
class="log_bottom" data-version="{{.VersionName}}"><i | |||||
class="icon-to-bottom"></i></a> | |||||
</span> | |||||
<div class="ui message message{{.VersionName}}" style="display: none;"> | <div class="ui message message{{.VersionName}}" style="display: none;"> | ||||
<div id="header"></div> | <div id="header"></div> | ||||
</div> | </div> | ||||
<div class="ui attached log" id="log{{.VersionName}}" | |||||
<div class="ui attached log log-scroll" id="log{{.VersionName}}" data-version="{{.VersionName}}" | |||||
style="height: 300px !important; overflow: auto;"> | style="height: 300px !important; overflow: auto;"> | ||||
<div class="ui inverted active dimmer"> | |||||
<div class="ui loader"></div> | |||||
</div> | |||||
<input type="hidden" name="end_line" value> | <input type="hidden" name="end_line" value> | ||||
<input type="hidden" name="start_line" value> | <input type="hidden" name="start_line" value> | ||||
<pre id="log_file{{.VersionName}}"></pre> | <pre id="log_file{{.VersionName}}"></pre> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -870,7 +901,15 @@ | |||||
function loadLog(version_name) { | function loadLog(version_name) { | ||||
document.getElementById("mask").style.display = "block" | document.getElementById("mask").style.display = "block" | ||||
$.get(`/api/v1/repos/${userName}/${repoPath}/cloudbrain/${taskID}/log?version_name=${version_name}&lines=50&order=asc`, (data) => { | |||||
let startLine = $('input[name=end_line]').val(); | |||||
if(startLine==""){ | |||||
startLine=0; | |||||
} | |||||
let endLine = $('input[name=end_line]').val(); | |||||
if(endLine==""){ | |||||
endLine = 50; | |||||
} | |||||
$.get(`/${userName}/${repoPath}/cloudbrain/train-job/${jobID}/get_log?endLine=${endLine}&startLine=${startLine}`, (data) => { | |||||
$('input[name=end_line]').val(data.EndLine) | $('input[name=end_line]').val(data.EndLine) | ||||
$('input[name=start_line]').val(data.StartLine) | $('input[name=start_line]').val(data.StartLine) | ||||
$(`#log_file${version_name}`).text(data.Content) | $(`#log_file${version_name}`).text(data.Content) | ||||
@@ -235,7 +235,8 @@ | |||||
<div class="two wide column text center"> | <div class="two wide column text center"> | ||||
<!-- 任务计算资源 --> | <!-- 任务计算资源 --> | ||||
<span style="font-size: 12px;margin-left: 0.4rem;" | <span style="font-size: 12px;margin-left: 0.4rem;" | ||||
class="">{{.ComputeResource}}</span> | |||||
class=""> | |||||
{{.ComputeResource}}</span> | |||||
</div> | </div> | ||||
<div class="one wide column text center"> | <div class="one wide column text center"> | ||||
{{if .User.Name}} | {{if .User.Name}} | ||||
@@ -40,6 +40,7 @@ | |||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
{{template "base/alert" .}} | {{template "base/alert" .}} | ||||
<div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="1" data-repo-link="{{.RepoLink}}"></div> | |||||
<h4 class="ui top attached header"> | <h4 class="ui top attached header"> | ||||
{{.i18n.Tr "repo.modelarts.train_job.new_infer"}} | {{.i18n.Tr "repo.modelarts.train_job.new_infer"}} | ||||
</h4> | </h4> | ||||
@@ -195,8 +196,11 @@ | |||||
{{end}} | {{end}} | ||||
</select> | </select> | ||||
</div> | </div> | ||||
<!-- 数据集 --> | |||||
{{template "custom/select_dataset_train" .}} | |||||
<span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 1rem;"></span> | |||||
<!-- 数据集 --> | |||||
<div id="select-multi-dataset"> | |||||
</div> | |||||
<span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 1rem;"></span> | <span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 1rem;"></span> | ||||
<div class="inline min_title field required"> | <div class="inline min_title field required"> | ||||
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | <label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | ||||
@@ -217,7 +217,7 @@ td, th { | |||||
<a class="item load-model-file" data-tab="third" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/modelarts/inference-job/{{.JobID}}/result_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a> | <a class="item load-model-file" data-tab="third" data-download-flag="{{$.canDownload}}" data-path="{{$.RepoLink}}/modelarts/inference-job/{{.JobID}}/result_list" data-version="{{.VersionName}}" data-parents="" data-filename="" data-init="init" >{{$.i18n.Tr "repo.model_download"}}</a> | ||||
</div> | </div> | ||||
<div class="ui tab active" data-tab="first" style="height:400px"> | |||||
<div class="ui tab active" data-tab="first"> | |||||
<div style="padding-top: 10px;"> | <div style="padding-top: 10px;"> | ||||
<div class="tab_2_content"> | <div class="tab_2_content"> | ||||
<div class="ac-grid ac-grid-col2"> | <div class="ac-grid ac-grid-col2"> | ||||
@@ -402,19 +402,7 @@ td, th { | |||||
</div> | </div> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
<tr class="ti-no-ng-animate"> | |||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||||
{{$.i18n.Tr "repo.modelarts.infer_dataset"}} | |||||
</td> | |||||
<td class="ti-text-form-content"> | |||||
<div class="text-span text-span-w"> | |||||
{{range $m ,$n := $.datasetDownload}} | |||||
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a> | |||||
{{end}} | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
<tr class="ti-no-ng-animate"> | <tr class="ti-no-ng-animate"> | ||||
<td class="ti-no-ng-animate ti-text-form-label text-width80" > | <td class="ti-no-ng-animate ti-text-form-label text-width80" > | ||||
{{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}} | {{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}} | ||||
@@ -445,6 +433,22 @@ td, th { | |||||
</table> | </table> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div style="clear:both"> | |||||
<table style="border:none" class="ui fixed small stackable table"> | |||||
<thead> | |||||
<tr><th style="color: #8a8e99;font-size:12px" class="three wide left aligned">数据集文件</th> | |||||
</tr></thead> | |||||
<tbody> | |||||
{{range $m ,$n := $.datasetDownload}} | |||||
<tr> | |||||
<td style="word-wrap: break-word;word-break: break-all;"><a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a></td> | |||||
</tr> | |||||
{{end}} | |||||
</tbody> | |||||
</table> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -95,7 +95,7 @@ | |||||
<span>{{$.i18n.Tr "repo.cloudbrain_status_runtime"}}</span> | <span>{{$.i18n.Tr "repo.cloudbrain_status_runtime"}}</span> | ||||
</div> | </div> | ||||
<div class="two wide column text center padding0"> | <div class="two wide column text center padding0"> | ||||
<span>{{$.i18n.Tr "repo.modelarts.computing_resources"}}</span> | |||||
<span>{{$.i18n.Tr "repo.modelarts.cluster.computing_resources"}}</span> | |||||
</div> | </div> | ||||
<div class="one wide column text center padding0"> | <div class="one wide column text center padding0"> | ||||
<span>{{$.i18n.Tr "repo.cloudbrain_creator"}}</span> | <span>{{$.i18n.Tr "repo.cloudbrain_creator"}}</span> | ||||
@@ -137,7 +137,13 @@ | |||||
</div> | </div> | ||||
<!-- 计算资源 --> | <!-- 计算资源 --> | ||||
<div class="two wide column text center padding0"> | <div class="two wide column text center padding0"> | ||||
<span style="font-size: 12px;">{{.ComputeResource}}</span> | |||||
<span style="font-size: 12px;"> | |||||
{{if eq .Cloudbrain.Type 2}} | |||||
{{$.i18n.Tr "cloudbrain.resource_cluster_c2net_simple"}} | |||||
{{else}} | |||||
{{$.i18n.Tr "cloudbrain.resource_cluster_openi_simple"}} | |||||
{{end}} | |||||
{{.ComputeResource}}</span> | |||||
</div> | </div> | ||||
<!-- 创建者 --> | <!-- 创建者 --> | ||||
<div class="one wide column text center padding0"> | <div class="one wide column text center padding0"> | ||||
@@ -397,16 +397,7 @@ | |||||
</div> | </div> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
<tr class="ti-no-ng-animate"> | |||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||||
{{$.i18n.Tr "repo.modelarts.train_job.compute_node"}} | |||||
</td> | |||||
<td class="ti-text-form-content"> | |||||
<div class="text-span text-span-w"> | |||||
{{.WorkServerNumber}} | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
</div> | </div> | ||||
@@ -445,23 +436,7 @@ | |||||
</div> | </div> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
<tr class="ti-no-ng-animate"> | |||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||||
{{$.i18n.Tr "repo.modelarts.train_job.train_dataset"}} | |||||
</td> | |||||
<td class="ti-text-form-content"> | |||||
<div class="text-span text-span-w"> | |||||
{{range $m ,$n := $.datasetList}} | |||||
{{if eq $k $m}} | |||||
{{range $f ,$g := $n}} | |||||
<a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a> | |||||
{{end}} | |||||
{{end}} | |||||
{{end}} | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
<tr class="ti-no-ng-animate"> | <tr class="ti-no-ng-animate"> | ||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | <td class="ti-no-ng-animate ti-text-form-label text-width80"> | ||||
{{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}} | {{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}} | ||||
@@ -486,10 +461,38 @@ | |||||
</div> | </div> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
<tr class="ti-no-ng-animate"> | |||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||||
{{$.i18n.Tr "repo.modelarts.train_job.compute_node"}} | |||||
</td> | |||||
<td class="ti-text-form-content"> | |||||
<div class="text-span text-span-w"> | |||||
{{.WorkServerNumber}} | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div style="clear:both"> | |||||
<table style="border:none" class="ui fixed small stackable table"> | |||||
<thead> | |||||
<tr><th style="color: #8a8e99;font-size:12px" class="three wide left aligned">数据集文件</th> | |||||
</tr></thead> | |||||
<tbody> | |||||
{{range $m ,$n := $.datasetList}} | |||||
{{if eq $k $m}} | |||||
{{range $f ,$g := $n}} | |||||
<tr> | |||||
<td style="word-wrap: break-word;word-break: break-all;"><a href="{{.RepositoryLink}}" target="_blank">{{.DatasetName}}</a></td> | |||||
</tr> | |||||
{{end}} | |||||
{{end}} | |||||
{{end}} | |||||
</tbody> | |||||
</table> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -55,6 +55,7 @@ | |||||
<div class="repository"> | <div class="repository"> | ||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
<div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}" data-dataset-uuid="{{.uuid}}" data-dataset-name="{{.dataset_name}}"></div> | |||||
{{template "base/alert" .}} | {{template "base/alert" .}} | ||||
<h4 class="ui top attached header"> | <h4 class="ui top attached header"> | ||||
{{.i18n.Tr "repo.modelarts.train_job.new"}} | {{.i18n.Tr "repo.modelarts.train_job.new"}} | ||||
@@ -151,7 +152,8 @@ | |||||
</span> | </span> | ||||
<a href="https://git.openi.org.cn/OpenIOSSG/MINIST_Example" target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a> | <a href="https://git.openi.org.cn/OpenIOSSG/MINIST_Example" target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a> | ||||
</div> | </div> | ||||
<div class="required unite min_title inline field"> | |||||
<!-- <div class="required unite min_title inline field"> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.dataset"}}</label> | <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.dataset"}}</label> | ||||
<select class="ui dropdown width80" id="trainjob_datasets" name="attachment" placeholder="{{.i18n.Tr "cloudbrain.select_dataset"}}"> | <select class="ui dropdown width80" id="trainjob_datasets" name="attachment" placeholder="{{.i18n.Tr "cloudbrain.select_dataset"}}"> | ||||
{{if .dataset_name}} | {{if .dataset_name}} | ||||
@@ -165,8 +167,11 @@ | |||||
{{end}} | {{end}} | ||||
</select> | </select> | ||||
<span class="tooltips">{{.i18n.Tr "cloudbrain.dataset_path_rule"}}</span> | <span class="tooltips">{{.i18n.Tr "cloudbrain.dataset_path_rule"}}</span> | ||||
</div> | |||||
</div> --> | |||||
<div id="select-multi-dataset"> | |||||
</div> | |||||
<span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 1rem;">{{.i18n.Tr "cloudbrain.dataset_path_rule"}}</span> | |||||
<div class="inline unite min_title field"> | <div class="inline unite min_title field"> | ||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | ||||
<span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | <span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | ||||
@@ -586,6 +586,8 @@ export default { | |||||
confirmFlag: false, | confirmFlag: false, | ||||
saveStatusList: [], | saveStatusList: [], | ||||
// 初始化已选择的数据集列表 | |||||
hasSelectDatasetList: [], | |||||
//当前项目数据集页面配置的初始化 | //当前项目数据集页面配置的初始化 | ||||
initCurrentPage: 1, | initCurrentPage: 1, | ||||
totalNumCurrent: 0, | totalNumCurrent: 0, | ||||
@@ -644,6 +646,7 @@ export default { | |||||
//tree 勾选触发事件 | //tree 勾选触发事件 | ||||
onCheck(data, checkedInfo) { | onCheck(data, checkedInfo) { | ||||
this.hasSelectDatasetList = []; | |||||
if ( | if ( | ||||
this.selectDatasetArray.length === 0 || | this.selectDatasetArray.length === 0 || | ||||
this.selectDatasetArray.every((item) => item.id !== data.id) | this.selectDatasetArray.every((item) => item.id !== data.id) | ||||
@@ -671,9 +674,8 @@ export default { | |||||
return item.label; | return item.label; | ||||
}); | }); | ||||
this.saveStatusList = this.selectDatasetArray.map((item) => { | this.saveStatusList = this.selectDatasetArray.map((item) => { | ||||
return item.UUID; | |||||
return item.id; | |||||
}); | }); | ||||
// this.confirmDatasetList = this.saveStatusList.join(";"); | |||||
}, | }, | ||||
//已选择数据集checkbox group 勾选事件 | //已选择数据集checkbox group 勾选事件 | ||||
changeCheckbox(checked, data) { | changeCheckbox(checked, data) { | ||||
@@ -686,7 +688,6 @@ export default { | |||||
}); | }); | ||||
this.selectDatasetArray.splice(index, 1); | this.selectDatasetArray.splice(index, 1); | ||||
this.saveStatusList.splice(index, 1); | this.saveStatusList.splice(index, 1); | ||||
// this.confirmDatasetList = this.saveStatusList.join(";"); | |||||
}, | }, | ||||
tableHeaderStyle({ row, column, rowIndex, columnIndex }) { | tableHeaderStyle({ row, column, rowIndex, columnIndex }) { | ||||
if (rowIndex === 0) { | if (rowIndex === 0) { | ||||
@@ -722,6 +723,7 @@ export default { | |||||
.then((res) => { | .then((res) => { | ||||
this.loadingCurrent = false; | this.loadingCurrent = false; | ||||
let data = JSON.parse(res.data.data); | let data = JSON.parse(res.data.data); | ||||
console.log(data); | |||||
this.currentDatasetList = this.transformeTreeData( | this.currentDatasetList = this.transformeTreeData( | ||||
data, | data, | ||||
"currentTree", | "currentTree", | ||||
@@ -734,7 +736,10 @@ export default { | |||||
let setCheckedKeysList = this.currentDatasetList.reduce( | let setCheckedKeysList = this.currentDatasetList.reduce( | ||||
(pre, cur) => { | (pre, cur) => { | ||||
cur.Attachments.forEach((item) => { | cur.Attachments.forEach((item) => { | ||||
if (this.saveStatusList.includes(item.id)) { | |||||
if ( | |||||
this.saveStatusList.includes(item.id) || | |||||
this.hasSelectDatasetList.includes(item.id) | |||||
) { | |||||
pre.push(item.id); | pre.push(item.id); | ||||
} | } | ||||
}); | }); | ||||
@@ -957,10 +962,32 @@ export default { | |||||
mounted() { | mounted() { | ||||
this.type = $(".cloudbrain-type").data("cloudbrain-type"); | this.type = $(".cloudbrain-type").data("cloudbrain-type"); | ||||
this.repoLink = $(".cloudbrain-type").data("repo-link"); | this.repoLink = $(".cloudbrain-type").data("repo-link"); | ||||
if ($(".cloudbrain-type").data("dataset-uuid")) { | |||||
this.hasSelectDatasetList = $(".cloudbrain-type") | |||||
.data("dataset-uuid") | |||||
.split(";"); | |||||
let hasSelectDatasetName = $(".cloudbrain-type") | |||||
.data("dataset-name") | |||||
.split(";"); | |||||
if (this.hasSelectDatasetList.length !== 0) { | |||||
this.saveStatusList = this.hasSelectDatasetList; | |||||
this.checkList = hasSelectDatasetName; | |||||
this.hasSelectDatasetList.forEach((item, index) => { | |||||
this.selectDatasetArray.push({ | |||||
id: item, | |||||
label: hasSelectDatasetName[index], | |||||
}); | |||||
}); | |||||
} | |||||
this.confirmDataset(); | |||||
} | |||||
if ( | if ( | ||||
location.href.indexOf("benchmark") !== -1 || | location.href.indexOf("benchmark") !== -1 || | ||||
location.href.indexOf("train-job") !== -1 | |||||
location.href.indexOf("train-job") !== -1 || | |||||
location.href.indexOf("inference") !== -1 | |||||
) { | ) { | ||||
console.log("this.benchmarkNew"); | |||||
this.benchmarkNew = true; | this.benchmarkNew = true; | ||||
} | } | ||||
if ( | if ( | ||||
@@ -100,7 +100,7 @@ | |||||
} | } | ||||
.issue.title { | .issue.title { | ||||
width: 80%; | |||||
width: 100%; | |||||
} | } | ||||
.push.news .content ul { | .push.news .content ul { | ||||