你确认删除该任务么?此任务一旦删除不可恢复。
+diff --git a/custom/conf/app.ini.sample b/custom/conf/app.ini.sample index e4dd5ec2f..49daa6e8d 100755 --- a/custom/conf/app.ini.sample +++ b/custom/conf/app.ini.sample @@ -1071,7 +1071,8 @@ HOST = http://192.168.207.84:3002/ COMMIT_VALID_DATE = 2021-01-15 [obs] -ENDPOINT = 112.95.163.82 +#ENDPOINT = 112.95.163.82 +ENDPOINT = https://obs.cn-south-222.ai.pcl.cn ACCESS_KEY_ID = FDP3LRMHLB9S77VWEHE3 SECRET_ACCESS_KEY = LyM82Wk80pgjhs2z7AdDcsdpCWhbsJtSzQ7hkESN BUCKET = testopendata @@ -1079,7 +1080,8 @@ LOCATION = cn-south-222 BASE_PATH = attachment/ [modelarts] -ENDPOINT = 112.95.163.80 +#ENDPOINT = 112.95.163.80 +ENDPOINT = https://modelarts.cn-south-222.ai.pcl.cn PROJECT_ID = edfccf24aace4e17a56da6bcbb55a5aa PROJECT_NAME = cn-south-222_test USERNAME = test1 diff --git a/models/attachment.go b/models/attachment.go index f9e697966..2dfe934a5 100755 --- a/models/attachment.go +++ b/models/attachment.go @@ -351,7 +351,7 @@ func GetUnDecompressAttachments() ([]*Attachment, error) { func getUnDecompressAttachments(e Engine) ([]*Attachment, error) { attachments := make([]*Attachment, 0, 10) - return attachments, e.Where("decompress_state = ? and dataset_id != 0 and type = ? and name like '%.zip'", DecompressStateInit, TypeCloudBrainOne).Find(&attachments) + return attachments, e.Where("decompress_state = ? and dataset_id != 0 and attachment.type = ? and name like '%.zip'", DecompressStateInit, TypeCloudBrainOne).Find(&attachments) } func GetAllPublicAttachments() ([]*AttachmentUsername, error) { @@ -361,7 +361,7 @@ func GetAllPublicAttachments() ([]*AttachmentUsername, error) { func getAllPublicAttachments(e Engine) ([]*AttachmentUsername, error) { attachments := make([]*AttachmentUsername, 0, 10) if err := e.Table("attachment").Join("LEFT", "`user`", "attachment.uploader_id "+ - "= `user`.id").Where("decompress_state= ? and is_private= ? and type = ?", DecompressStateDone, false, TypeCloudBrainOne).Find(&attachments); err != nil { + "= `user`.id").Where("decompress_state= ? and is_private= ? and attachment.type = ?", DecompressStateDone, false, TypeCloudBrainOne).Find(&attachments); err != nil { return nil, err } return attachments, nil @@ -379,7 +379,7 @@ func GetPrivateAttachments(username string) ([]*AttachmentUsername, error) { func getPrivateAttachments(e Engine, userID int64) ([]*AttachmentUsername, error) { attachments := make([]*AttachmentUsername, 0, 10) if err := e.Table("attachment").Join("LEFT", "`user`", "attachment.uploader_id "+ - "= `user`.id").Where("decompress_state= ? and uploader_id= ? and type = ?", DecompressStateDone, userID, TypeCloudBrainOne).Find(&attachments); err != nil { + "= `user`.id").Where("decompress_state= ? and uploader_id= ? and attachment.type = ?", DecompressStateDone, userID, TypeCloudBrainOne).Find(&attachments); err != nil { return nil, err } return attachments, nil @@ -388,7 +388,7 @@ func getPrivateAttachments(e Engine, userID int64) ([]*AttachmentUsername, error func getAllUserAttachments(e Engine, userID int64) ([]*AttachmentUsername, error) { attachments := make([]*AttachmentUsername, 0, 10) if err := e.Table("attachment").Join("LEFT", "`user`", "attachment.uploader_id "+ - "= `user`.id").Where("decompress_state= ? and type = ? and (uploader_id= ? or is_private = ?)", DecompressStateDone, TypeCloudBrainOne, userID, false).Find(&attachments); err != nil { + "= `user`.id").Where("decompress_state= ? and attachment.type = ? and (uploader_id= ? or is_private = ?)", DecompressStateDone, TypeCloudBrainOne, userID, false).Find(&attachments); err != nil { return nil, err } return attachments, nil @@ -401,7 +401,7 @@ func GetAllUserAttachments(userID int64) ([]*AttachmentUsername, error) { func getModelArtsUserAttachments(e Engine, userID int64) ([]*AttachmentUsername, error) { attachments := make([]*AttachmentUsername, 0, 10) if err := e.Table("attachment").Join("LEFT", "`user`", "attachment.uploader_id "+ - "= `user`.id").Where("type = ? and (uploader_id= ? or is_private = ?)", TypeCloudBrainTwo, userID, false).Find(&attachments); err != nil { + "= `user`.id").Where("attachment.type = ? and (uploader_id= ? or is_private = ?)", TypeCloudBrainTwo, userID, false).Find(&attachments); err != nil { return nil, err } return attachments, nil diff --git a/models/repo.go b/models/repo.go index f99e909ae..21dca5daa 100755 --- a/models/repo.go +++ b/models/repo.go @@ -1069,7 +1069,8 @@ func CreateRepository(ctx DBContext, doer, u *User, repo *Repository) (err error return err } - _, err = blockchain.NewRepo(string(repo.ID), u.PublicKey, repo.Name) + strRepoID := strconv.FormatInt(repo.ID, 10) + _, err = blockchain.NewRepo(strRepoID, u.PublicKey, repo.Name) if err != nil { log.Error("newRepo failed:", err.Error()) } diff --git a/modules/auth/modelarts.go b/modules/auth/modelarts.go index b15de3c37..1bef4c825 100755 --- a/modules/auth/modelarts.go +++ b/modules/auth/modelarts.go @@ -7,10 +7,7 @@ import ( type CreateModelArtsForm struct { JobName string `form:"job_name" binding:"Required"` - Image string `form:"image" binding:"Required"` - Command string `form:"command" binding:"Required"` Attachment string `form:"attachment" binding:"Required"` - JobType string `form:"job_type" binding:"Required"` } func (f *CreateModelArtsForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { diff --git a/modules/modelarts/modelarts.go b/modules/modelarts/modelarts.go index abfe2a398..3cae0f2c6 100755 --- a/modules/modelarts/modelarts.go +++ b/modules/modelarts/modelarts.go @@ -17,7 +17,10 @@ const ( subTaskName = "task1" - DataSetMountPath = "/home/ma-user/work" + DataSetMountPath = "/home/ma-user/work" + NotebookEnv = "Python3" + NotebookType = "Ascend" + FlavorInfo = "Ascend: 1*Ascend 910 CPU: 24 核 96GiB (modelarts.kat1.xlarge)" ) func GenerateTask(ctx *context.Context, jobName, uuid string) error { diff --git a/modules/modelarts/resty.go b/modules/modelarts/resty.go index 2c225c603..b8be5ec6d 100755 --- a/modules/modelarts/resty.go +++ b/modules/modelarts/resty.go @@ -35,7 +35,10 @@ func checkSetting() { return } - getToken() + err := getToken() + if err != nil { + log.Error("getToken falied:", err.Error()) + } } func getToken() error { diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 3e49cb21a..4d6295370 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -2440,6 +2440,7 @@ file_status=文件处理状态: file_init_status=等待上传 waitting_uploading=请等待文件传输完成 md5_computing=计算MD5 +obs-connecting=obs连接中 loading_file=加载文件 uploading=正在上传 upload_complete=上传完成 diff --git a/package-lock.json b/package-lock.json index f60fe03a3..42cd4ec4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1954,6 +1954,28 @@ "object.assign": "^4.1.0" } }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npm.taobao.org/babel-polyfill/download/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "requires": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + }, + "dependencies": { + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npm.taobao.org/core-js/download/core-js-2.6.12.tgz?cache=0&sync_timestamp=1611040749668&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-2.6.12.tgz", + "integrity": "sha1-2TM9+nsGXjR8xWgiGdb2kIWcwuw=" + }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + } + } + }, "babel-runtime": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", @@ -2143,6 +2165,11 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, + "blueimp-md5": { + "version": "2.18.0", + "resolved": "https://registry.npm.taobao.org/blueimp-md5/download/blueimp-md5-2.18.0.tgz", + "integrity": "sha1-EVK+EzXwxrORHtnjbbVPPmrFKTU=" + }, "bn.js": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.1.tgz", @@ -3419,8 +3446,7 @@ "date-format": { "version": "3.0.0", "resolved": "https://registry.npm.taobao.org/date-format/download/date-format-3.0.0.tgz", - "integrity": "sha1-64eANlx9KxURB4+0keZHl4DzrZU=", - "dev": true + "integrity": "sha1-64eANlx9KxURB4+0keZHl4DzrZU=" }, "dateformat": { "version": "2.2.0", @@ -4033,11 +4059,33 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "esdk-obs-browserjs": { + "version": "3.20.7", + "resolved": "https://registry.npm.taobao.org/esdk-obs-browserjs/download/esdk-obs-browserjs-3.20.7.tgz", + "integrity": "sha1-vhziRlKEhW3PgZPl0DyX68bJI0s=", + "requires": { + "axios": "^0.19.0", + "babel-polyfill": "^6.26.0", + "blueimp-md5": "^2.10.0", + "js-base64": "^2.3.2", + "jssha": "^2.3.1", + "urijs": "^1.19.1" + }, + "dependencies": { + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npm.taobao.org/axios/download/axios-0.19.2.tgz?cache=0&sync_timestamp=1608609215811&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faxios%2Fdownload%2Faxios-0.19.2.tgz", + "integrity": "sha1-PqNsXYgY0NX4qKl6bTa4bNwAyyc=", + "requires": { + "follow-redirects": "1.5.10" + } + } + } + }, "esdk-obs-nodejs": { "version": "3.20.11", "resolved": "https://registry.npm.taobao.org/esdk-obs-nodejs/download/esdk-obs-nodejs-3.20.11.tgz?cache=0&sync_timestamp=1610351636380&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fesdk-obs-nodejs%2Fdownload%2Fesdk-obs-nodejs-3.20.11.tgz", "integrity": "sha1-/bMuzu3qoT+xLgmCcgg8yM6MIsE=", - "dev": true, "requires": { "log4js": "^6.3.0", "xml2js": "^0.4.23" @@ -5218,8 +5266,7 @@ "flatted": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==" }, "flatten": { "version": "1.0.3", @@ -5235,6 +5282,29 @@ "readable-stream": "^2.3.6" } }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.5.10.tgz?cache=0&sync_timestamp=1611606737937&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffollow-redirects%2Fdownload%2Ffollow-redirects-1.5.10.tgz", + "integrity": "sha1-e3qfmuov3/NnhqlP9kPtB/T/Xio=", + "requires": { + "debug": "=3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz?cache=0&sync_timestamp=1607566533140&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433842694&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "fomantic-ui": { "version": "2.8.4", "resolved": "https://registry.npmjs.org/fomantic-ui/-/fomantic-ui-2.8.4.tgz", @@ -5376,7 +5446,6 @@ "version": "8.1.0", "resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-8.1.0.tgz?cache=0&sync_timestamp=1611075469998&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffs-extra%2Fdownload%2Ffs-extra-8.1.0.tgz", "integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=", - "dev": true, "requires": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -7720,7 +7789,6 @@ "version": "4.0.0", "resolved": "https://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz?cache=0&sync_timestamp=1604161797011&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsonfile%2Fdownload%2Fjsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, "requires": { "graceful-fs": "^4.1.6" } @@ -7737,6 +7805,11 @@ "verror": "1.10.0" } }, + "jssha": { + "version": "2.4.2", + "resolved": "https://registry.npm.taobao.org/jssha/download/jssha-2.4.2.tgz", + "integrity": "sha1-2VCwlWNJKL1rK9odQtqaOnYtZek=" + }, "just-debounce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", @@ -8213,7 +8286,6 @@ "version": "6.3.0", "resolved": "https://registry.npm.taobao.org/log4js/download/log4js-6.3.0.tgz", "integrity": "sha1-EN+vu0NDUaPjAnegC5h5RG9xW8s=", - "dev": true, "requires": { "date-format": "^3.0.0", "debug": "^4.1.1", @@ -11862,8 +11934,7 @@ "rfdc": { "version": "1.2.0", "resolved": "https://registry.npm.taobao.org/rfdc/download/rfdc-1.2.0.tgz?cache=0&sync_timestamp=1610744108114&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frfdc%2Fdownload%2Frfdc-1.2.0.tgz", - "integrity": "sha1-npiUJY9I8oS0PDFDxoBwpPNzuUk=", - "dev": true + "integrity": "sha1-npiUJY9I8oS0PDFDxoBwpPNzuUk=" }, "rgb-regex": { "version": "1.0.1", @@ -12476,7 +12547,6 @@ "version": "2.2.4", "resolved": "https://registry.npm.taobao.org/streamroller/download/streamroller-2.2.4.tgz", "integrity": "sha1-wZjO1C25QIamGTYIGHzoCl8rDlM=", - "dev": true, "requires": { "date-format": "^2.1.0", "debug": "^4.1.1", @@ -12486,8 +12556,7 @@ "date-format": { "version": "2.1.0", "resolved": "https://registry.npm.taobao.org/date-format/download/date-format-2.1.0.tgz", - "integrity": "sha1-MdW16iEc9f12TNOLr50DPffhJc8=", - "dev": true + "integrity": "sha1-MdW16iEc9f12TNOLr50DPffhJc8=" } } }, @@ -14049,8 +14118,7 @@ "universalify": { "version": "0.1.2", "resolved": "https://registry.npm.taobao.org/universalify/download/universalify-0.1.2.tgz?cache=0&sync_timestamp=1603179967633&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funiversalify%2Fdownload%2Funiversalify-0.1.2.tgz", - "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=", - "dev": true + "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=" }, "unquote": { "version": "1.1.1", @@ -14122,6 +14190,11 @@ "punycode": "^2.1.0" } }, + "urijs": { + "version": "1.19.5", + "resolved": "https://registry.npm.taobao.org/urijs/download/urijs-1.19.5.tgz", + "integrity": "sha1-EZaDq0svsL1jfl6m3ZEXvKxo0+Q=" + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -15108,7 +15181,6 @@ "version": "0.4.23", "resolved": "https://registry.npm.taobao.org/xml2js/download/xml2js-0.4.23.tgz?cache=0&sync_timestamp=1599054229598&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fxml2js%2Fdownload%2Fxml2js-0.4.23.tgz", "integrity": "sha1-oMaVFnUkIesqx1juTUzPWIQ+rGY=", - "dev": true, "requires": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" @@ -15117,8 +15189,7 @@ "xmlbuilder": { "version": "11.0.1", "resolved": "https://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-11.0.1.tgz", - "integrity": "sha1-vpuuHIoEbnazESdyY0fQrXACvrM=", - "dev": true + "integrity": "sha1-vpuuHIoEbnazESdyY0fQrXACvrM=" }, "xtend": { "version": "4.0.2", diff --git a/package.json b/package.json index 2a37bebf9..ec165423a 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,8 @@ "cssnano": "4.1.10", "domino": "2.1.5", "dropzone": "5.7.2", + "esdk-obs-browserjs": "3.20.7", + "esdk-obs-nodejs": "3.20.11", "fast-glob": "3.2.2", "file-loader": "6.0.0", "fomantic-ui": "2.8.4", @@ -55,7 +57,6 @@ "worker-loader": "2.0.0" }, "devDependencies": { - "esdk-obs-nodejs": "3.20.11", "eslint": "6.8.0", "eslint-config-airbnb-base": "14.1.0", "eslint-plugin-import": "2.20.2", diff --git a/routers/repo/modelarts.go b/routers/repo/modelarts.go index defb0b858..8b3c71e4f 100755 --- a/routers/repo/modelarts.go +++ b/routers/repo/modelarts.go @@ -82,20 +82,26 @@ func ModelArtsNew(ctx *context.Context) { ctx.Data["attachments"] = attachs ctx.Data["dataset_path"] = modelarts.DataSetMountPath + ctx.Data["env"] = modelarts.NotebookEnv + ctx.Data["notebook_type"] = modelarts.NotebookType + ctx.Data["flavor"] = modelarts.FlavorInfo ctx.HTML(200, tplModelArtsNew) } -func ModelArtsCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { +func ModelArtsCreate(ctx *context.Context, form auth.CreateModelArtsForm) { ctx.Data["PageIsCloudBrain"] = true jobName := form.JobName uuid := form.Attachment //repo := ctx.Repo.Repository + log.Info(uuid) + err := modelarts.GenerateTask(ctx, jobName, uuid) if err != nil { ctx.RenderWithErr(err.Error(), tplModelArtsNew, &form) return } + ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts") } diff --git a/templates/repo/datasets/index.tmpl b/templates/repo/datasets/index.tmpl index f2eaab004..e5e93a01a 100755 --- a/templates/repo/datasets/index.tmpl +++ b/templates/repo/datasets/index.tmpl @@ -97,6 +97,7 @@ data-file-init-status='{{.i18n.Tr "dropzone.file_init_status"}}' data-waitting-uploading='{{.i18n.Tr "dropzone.waitting_uploading"}}' data-md5-computing='{{.i18n.Tr "dropzone.md5_computing"}}' + data-obs-connecting='{{.i18n.Tr "dropzone.obs-connecting"}}' data-loading-file='{{.i18n.Tr "dropzone.loading_file"}}' data-upload-complete='{{.i18n.Tr "dropzone.upload_complete"}}' data-uploading='{{.i18n.Tr "dropzone.uploading"}}' diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl index 75d67853b..ac4776a2c 100755 --- a/templates/repo/header.tmpl +++ b/templates/repo/header.tmpl @@ -220,7 +220,7 @@ if(checked_radio=='0'){ window.location.href = repolink+'/cloudbrain' }else if(checked_radio=='1'){ - window.location.href = repolink+'/blockchain' + window.location.href = repolink+'/modelarts' }else{ return; diff --git a/templates/repo/modelarts/index.tmpl b/templates/repo/modelarts/index.tmpl new file mode 100755 index 000000000..e65f554d1 --- /dev/null +++ b/templates/repo/modelarts/index.tmpl @@ -0,0 +1,492 @@ + +{{template "base/head" .}} + + + + +
你确认删除该任务么?此任务一旦删除不可恢复。
+任务名称: {{.JobName}}
+ {{end}} +任务结果:
+ {{with .taskRes}} + {{range .TaskStatuses}} +| 状态 | +{{.State}} | +
| 开始时间 | +{{.StartTime}} | +
| 结束时间 | +{{.FinishedTime}} | +
| ExitCode | +{{.ExitCode}} | +
| 退出信息 | +{{.ExitDiagnostics| nl2br}} | +
| 硬件信息 | |
|---|---|
| CPU | +{{.Resource.CPU}} | +
| Memory | +{{.Resource.Memory}} | +
| NvidiaComGpu | +{{.Resource.NvidiaComGpu}} | +
| 调试信息 | |
|---|---|
| 状态 | +{{.Platform}} | +
| 开始时间 | +{{.JobStatus.StartTime}} | +
| 结束时间 | +{{.JobStatus.EndTime}} | +
| ExitCode | +{{.JobStatus.AppExitCode}} | +
| 退出信息 | +{{.JobStatus.AppExitDiagnostics | nl2br}} | +
+ {{ file_status_text }} + {{ status }} +
+