Browse Source

Merge branch 'fix-3244' of https://openi.pcl.ac.cn/OpenI/aiforge into fix-3244

pull/3291/head
liuzx 2 years ago
parent
commit
80543cee80
68 changed files with 4796 additions and 619 deletions
  1. +16
    -9
      custom/public/css/git.openi.css
  2. BIN
      custom/public/img/home-banner-01-en.jpg
  3. BIN
      custom/public/img/home-banner-01.jpg
  4. BIN
      custom/public/img/home-bg-ps.png
  5. +1
    -0
      custom/public/img/logo-footer.svg
  6. +45
    -1
      custom/public/img/logo-w.svg
  7. +14
    -6
      models/dataset.go
  8. +5
    -1
      models/repo_activity_custom.go
  9. +9
    -0
      models/resource_specification.go
  10. +1
    -1
      models/user.go
  11. +17
    -4
      modules/cloudbrain/cloudbrain.go
  12. +94
    -8
      modules/modelarts/modelarts.go
  13. +1
    -1
      modules/modelarts/resty.go
  14. +8
    -45
      modules/modelarts_cd/modelarts.go
  15. +29
    -0
      modules/setting/setting.go
  16. +8
    -0
      modules/structs/cloudbrain.go
  17. +3
    -0
      modules/templates/helper.go
  18. +25
    -5
      options/locale/locale_en-US.ini
  19. +22
    -4
      options/locale/locale_zh-CN.ini
  20. +360
    -56
      public/home/home.js
  21. +1
    -1
      public/img/search.svg
  22. +6
    -0
      routers/api/v1/api.go
  23. +76
    -7
      routers/api/v1/repo/cloudbrain.go
  24. +5
    -1
      routers/api/v1/repo/modelarts.go
  25. +58
    -15
      routers/home.go
  26. +0
    -1
      routers/repo/ai_model_convert.go
  27. +4
    -5
      routers/repo/aisafety.go
  28. +12
    -53
      routers/repo/cloudbrain.go
  29. +1
    -3
      routers/repo/grampus.go
  30. +35
    -10
      routers/repo/modelarts.go
  31. +3
    -2
      routers/routes/routes.go
  32. +362
    -0
      services/cloudbrain/cloudbrainTask/notebook.go
  33. +16
    -7
      services/cloudbrain/cloudbrainTask/sync_status.go
  34. +12
    -0
      services/cloudbrain/cloudbrainTask/train.go
  35. +26
    -0
      services/cloudbrain/util.go
  36. +6
    -10
      services/repository/repository.go
  37. +2
    -0
      templates/admin/cloudbrain/list.tmpl
  38. +45
    -5
      templates/base/footer_content.tmpl
  39. +1
    -0
      templates/base/head.tmpl
  40. +1
    -0
      templates/base/head_home.tmpl
  41. +39
    -18
      templates/base/head_navbar.tmpl
  42. +1
    -1
      templates/base/head_notice.tmpl
  43. +36
    -0
      templates/custom/home/home_activity.tmpl
  44. +85
    -0
      templates/custom/home/home_dataset.tmpl
  45. +20
    -0
      templates/custom/home/home_org.tmpl
  46. +21
    -0
      templates/custom/home/home_repo.tmpl
  47. +1942
    -0
      templates/custom/home/home_top.tmpl
  48. +133
    -0
      templates/custom/home/home_user_experience.tmpl
  49. +1
    -3
      templates/explore/repos.tmpl
  50. +25
    -87
      templates/home.tmpl
  51. +81
    -0
      templates/notice.tmpl
  52. +8
    -2
      templates/repo/debugjob/index.tmpl
  53. +4
    -4
      templates/repo/header.tmpl
  54. +29
    -29
      templates/repo/home.tmpl
  55. +3
    -1
      templates/repo/modelsafety/new.tmpl
  56. +15
    -4
      templates/user/auth/activate.tmpl
  57. +6
    -4
      templates/user/dashboard/cloudbrains.tmpl
  58. +23
    -12
      web_src/js/features/cloudrbanin.js
  59. +4
    -0
      web_src/js/features/i18nVue.js
  60. +19
    -1
      web_src/js/index.js
  61. +2
    -2
      web_src/less/openi.less
  62. +47
    -0
      web_src/vuepages/apis/modules/notobook.js
  63. +0
    -1
      web_src/vuepages/apis/service.js
  64. +30
    -2
      web_src/vuepages/langs/config/en-US.js
  65. +217
    -186
      web_src/vuepages/langs/config/zh-CN.js
  66. +1
    -1
      web_src/vuepages/pages/modelmanage/common/modelmanage-common-detail.vue
  67. +662
    -0
      web_src/vuepages/pages/notebook/debug/index.vue
  68. +12
    -0
      web_src/vuepages/pages/notebook/debug/vp-notebook-debug.js

+ 16
- 9
custom/public/css/git.openi.css View File

@@ -72,9 +72,7 @@
z-index: 10;
}
.ui.secondary.c2net.segment{
/* background: #f8faff;
border: none;*/
margin-bottom: 5em;
padding-bottom: 3em;
padding-top: 2em;
color: rgba(0,0,0,.87);
background-image: linear-gradient(to bottom left,var(--tw-gradient-stops));
@@ -176,7 +174,7 @@
}
.homeorg, .homepro, .homemodel, .i-env{
position: relative;
padding-bottom: 5em;
padding-bottom: 3em;
}
.homenews::before{
content: '';
@@ -203,7 +201,7 @@
padding: 0;
}
.newslist{
height: 300px;
height: 260px;
overflow: hidden;
}

@@ -278,7 +276,7 @@
z-index: 9;
}
.homeorg-list .card{
background-image: linear-gradient(#FFF, #FFF 60%, #DFF0EF) !important;
/* background-image: linear-gradient(#FFF, #FFF 60%, #DFF0EF) !important; */
box-shadow: none !important;
}
.homeorg-list .card .ui.small.header .content{
@@ -299,7 +297,7 @@
background-color: #FFF;
box-shadow: 0px 5px 10px 0px rgba(105, 192, 255, .3);
border: 1px solid rgba(105, 192, 255, .4);
min-height: 10.8em;
/* min-height: 10.8em; */
}
.homepro-list .ui.card>.content>.header{
line-height: 40px !important;
@@ -307,7 +305,7 @@

.homepro-list .swiper-pagination-bullet-active, .homeorg-list .swiper-pagination-bullet-active{
width: 40px;
border-radius: 4px;
border-radius: 4px;
}
.i-env > div{
position: relative;
@@ -317,6 +315,15 @@
}

@media only screen and (max-width: 767px) {
.mobile-margin-left-20 {
margin-left: 20px !important;
}
.mobile-text-align-center {
text-align: center !important;
}
.mobile-justify-content-center {
justify-content: center !important;
}
.am-mt-30{ margin-top: 1.5rem !important;}
.ui.secondary.hometop.segment{
margin-bottom: 5.0rem;
@@ -341,7 +348,7 @@
background: #FFF;
}
.homeorg{
padding-left: 3.5em;
/* padding-left: 3.5em; */
}
.homeorg-tit::after {
left: -2.3em;


BIN
custom/public/img/home-banner-01-en.jpg View File

Before After
Width: 1920  |  Height: 580  |  Size: 180 kB

BIN
custom/public/img/home-banner-01.jpg View File

Before After
Width: 1920  |  Height: 580  |  Size: 174 kB

BIN
custom/public/img/home-bg-ps.png View File

Before After
Width: 681  |  Height: 800  |  Size: 62 kB

+ 1
- 0
custom/public/img/logo-footer.svg
File diff suppressed because it is too large
View File


+ 45
- 1
custom/public/img/logo-w.svg View File

@@ -1 +1,45 @@
<svg id="图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 50"><defs><style>.cls-1{fill:#5bb973;}.cls-2{fill:#fff;}</style></defs><title>logo-w</title><path class="cls-1" d="M42.08,12.13l-15.65-9a4.44,4.44,0,0,0-4.43,0l-15.65,9A4.44,4.44,0,0,0,4.13,16V34a4.44,4.44,0,0,0,2.22,3.84l3.83,2.21a2.88,2.88,0,0,0-.06.59,2.95,2.95,0,1,0,1-2.17L7.26,36.3A2.63,2.63,0,0,1,6,34V16A2.62,2.62,0,0,1,7.26,13.7l15.65-9a2.59,2.59,0,0,1,2.61,0l15.65,9A2.63,2.63,0,0,1,42.47,16V34a2.64,2.64,0,0,1-1.3,2.27l-15.65,9a3.16,3.16,0,0,1-.5.22V39.88a1.31,1.31,0,0,0,0-.28V36.35l.1,0,9-6a.92.92,0,0,0,.41-.75V20a3,3,0,1,0-1.82,0v9L25,34.18V15.94a3,3,0,1,0-1.82,0v12l-5.08-2.95V20.19a3,3,0,1,0-1.82,0v5.26a.9.9,0,0,0,.45.79L23.2,30v8.16L12.11,31.73V23.84a2.93,2.93,0,1,0-1.82,0v8.41a.94.94,0,0,0,.46.79l12.45,7.2v6.34a.22.22,0,0,0,0,.08v.09l0,.1s0,0,0,.07l.06.1s0,0,0,0l.08.1,0,0a.39.39,0,0,0,.1.08l0,0,.12.07,0,0,.14,0h0a.39.39,0,0,0,.15,0h.16a4.44,4.44,0,0,0,2.22-.59l15.65-9A4.46,4.46,0,0,0,44.29,34V16a4.45,4.45,0,0,0-2.21-3.83m-29,27.42a1.12,1.12,0,1,1-1.12,1.12,1.12,1.12,0,0,1,1.12-1.12m20.6-23.46a1.12,1.12,0,1,1-1.12,1.12,1.12,1.12,0,0,1,1.12-1.12m-16.45.19a1.12,1.12,0,1,1-1.12,1.12,1.12,1.12,0,0,1,1.12-1.12m-6,3.65a1.12,1.12,0,1,1-1.12,1.12,1.12,1.12,0,0,1,1.12-1.12M24.13,12A1.12,1.12,0,1,1,23,13.14,1.12,1.12,0,0,1,24.13,12"/><path class="cls-2" d="M81.68,26.69H67.86c-2,.1-3.06,1-3.06,2.85v6.33c.1,1.68,1.16,2.53,3.06,2.63H81.57c1.9-.1,2.85-1,3-2.74V29.54A2.71,2.71,0,0,0,81.68,26.69Zm-.53,8c-.11.73-.53,1.16-1.48,1.26H69.54c-1-.21-1.37-.53-1.47-1.26V30.59a1.44,1.44,0,0,1,1.47-1.48h10a1.54,1.54,0,0,1,1.58,1.48Z"/><path class="cls-2" d="M63.21,20.57V17A1.63,1.63,0,0,1,64.8,15.4H79.25c1.06-.11,1.58.42,1.58,1.37V19.3c0,.85-.52,1.27-1.47,1.27H64.59V23H81.47c1.79,0,2.74-.85,2.74-2.43V15.72A2.45,2.45,0,0,0,81.47,13H74.08V11H70.6v2H62.69c-2,0-3,.95-3,3v9.39a42.65,42.65,0,0,1-2,13l3.27.64a43.43,43.43,0,0,0,2.11-13V20.57Z"/><path class="cls-2" d="M90,24.47l3.38,1.8a10.1,10.1,0,0,0,3.9-5.81h5.91V18H97.82a25.57,25.57,0,0,0,.21-3h5V12.55H93.7V11H90.22v4h4.43a17.38,17.38,0,0,1-.21,2.95H89.38v2.53h4.43A7.05,7.05,0,0,1,90,24.47Z"/><path class="cls-2" d="M97.82,21.62A21.82,21.82,0,0,1,100,26.05h3.7a25.8,25.8,0,0,0-2.22-4.43Z"/><path class="cls-2" d="M112.17,26.79H93.39c-1.8.21-2.85,1.06-3,2.64v4.75H112v1c0,.85-.52,1.27-1.58,1.27h-15c-1,0-1.48-.42-1.48-1.16H90.54v1A2.75,2.75,0,0,0,93.18,39h19.09c2-.1,3.06-1,3.06-2.64V29.54A3.21,3.21,0,0,0,112.17,26.79Zm-.32,4.86h-18V30.8a1.43,1.43,0,0,1,1.48-1.47h15c1,0,1.58.52,1.58,1.47Z"/><path class="cls-2" d="M113.64,12h-6.22q-2.53.17-2.85,2.22V23.1a2.33,2.33,0,0,0,2.32,2.22h6.65c1.47-.11,2.32-.85,2.32-2.22V14.24C116,13,115.23,12.23,113.64,12Zm-1,9.29c0,1.05-.53,1.58-1.48,1.58h-1.79A1.39,1.39,0,0,1,108,21.31V16a1.42,1.42,0,0,1,1.47-1.47H111A1.53,1.53,0,0,1,112.59,16Z"/></svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 160 64" style="enable-background:new 0 0 160 64;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{display:none;fill:#FFFFFF;}
</style>
<g>
<path class="st0" d="M105.3,33.3H87.1c-2.6,0.1-4,1.3-4,3.8v8.3c0.1,2.2,1.5,3.3,4,3.5h18c2.5-0.1,3.8-1.3,3.9-3.6v-8.2
c0.1-2-1.4-3.6-3.4-3.8C105.6,33.3,105.4,33.3,105.3,33.3z M104.6,43.9c-0.1,1-0.7,1.5-1.9,1.7H89.3c-1.3-0.3-1.8-0.7-1.9-1.7v-5.4
c0-1,0.8-1.9,1.8-1.9c0,0,0.1,0,0.1,0h13.1c1.1,0,2,0.8,2.1,2L104.6,43.9z"/>
<path class="st0" d="M81,25.3v-4.7c0-1.1,0.9-2.1,2.1-2.1h19c1.4-0.1,2.1,0.5,2.1,1.8v3.3c0,1.1-0.7,1.7-1.9,1.7H82.8v3.2H105
c2.3,0,3.6-1.1,3.6-3.2v-6.4c0.2-1.8-1.1-3.4-2.8-3.6c-0.3,0-0.5,0-0.8,0h-9.7v-2.6h-4.6v2.6H80.3c-2.6,0-3.9,1.2-3.9,3.9v12.3
c0,5.8-0.9,11.6-2.6,17.1l4.3,0.8c1.8-5.5,2.7-11.3,2.8-17.1v-7.2H81z"/>
<path class="st0" d="M116.2,30.4l4.4,2.4c2.6-1.9,4.4-4.6,5.1-7.6h7.8v-3.2h-7.1c0.2-1.3,0.3-2.6,0.3-3.9h6.6v-3.2h-12.3v-2h-4.6
V18h5.8c0,1.3-0.1,2.6-0.3,3.9h-6.7v3.3h5.8C120.4,27.5,118.6,29.4,116.2,30.4z"/>
<path class="st0" d="M126.5,26.7c1.2,1.8,2.1,3.8,2.9,5.8h4.9c-0.8-2-1.8-4-2.9-5.8H126.5z"/>
<path class="st0" d="M145.4,33.5h-24.7c-2.4,0.3-3.8,1.4-3.9,3.5v6.2h28.4v1.3c0,1.1-0.7,1.7-2.1,1.7h-19.7c-1.3,0-1.9-0.5-1.9-1.5
h-4.5V46c0,1.9,1.6,3.5,3.5,3.6h25.1c2.6-0.1,4-1.3,4-3.5v-9C149.2,35,147.5,33.5,145.4,33.5z M145,39.9h-23.7v-1.1
c0-1,0.8-1.9,1.8-1.9c0,0,0.1,0,0.1,0H143c1.3,0,2.1,0.7,2.1,1.9L145,39.9z"/>
<path class="st0" d="M147.3,14h-8.2c-2.2,0.1-3.5,1.1-3.8,2.9v11.7c0.1,1.6,1.4,2.9,3.1,2.9h8.7c1.9-0.1,3.1-1.1,3.1-2.9V17
C150.4,15.4,149.4,14.3,147.3,14z M146,26.2c0,1.4-0.7,2.1-1.9,2.1h-2.4c-1,0-1.8-0.8-1.8-1.8c0-0.1,0-0.1,0-0.2v-7
c0-1,0.8-1.9,1.8-1.9c0,0,0.1,0,0.1,0h2c1.1,0,2.1,0.8,2.1,1.9l0,0L146,26.2z"/>
</g>
<path class="st1" d="M67.2,44.1V20c0-2.6-1.4-5.1-3.7-6.4l-20.9-12c-2.3-1.3-5.1-1.3-7.4,0l-20.9,12c-2.3,1.3-3.7,3.8-3.7,6.4v24.1
c0,2.6,1.4,5.1,3.7,6.4l20.9,12c2.3,1.3,5.1,1.3,7.4,0l20.9-12C65.8,49.2,67.2,46.7,67.2,44.1z"/>
<path class="st0" d="M61.9,15.4L42,3.9c-1.9-1.1-4.3-1.1-6.2,0L15.9,15.4c-1.9,1.1-3.1,3.2-3.1,5.4v22.9c0,2.2,1.2,4.3,3.1,5.4
l3.8,2c0.8,0.4,0.8,1,0.8,1.9c0,0,0,0.1,0,0.1c0.1,1.6,1.8,3.5,4.2,3.5c2.3,0,4.3-1.9,4.4-4.2c0-1.6-0.8-3.1-2.3-3.9
c-0.6-0.3-1.7-0.5-2.9-0.4c-0.9,0.1-1,0.6-2.8-0.5l-2.8-1.6c-0.8-0.5-1.7-1.3-1.6-2.3V22c0-1.8,0.8-2.8,2.1-3.5L37,7.8
C38.1,7,40.2,7.2,41.5,8l16.4,9.5c2.9,1.6,3,3,3,4v19.7c0,2.3-1.5,4-2.3,4.5l-15.1,8.5C42.8,54.5,42,54,42,53.3l0-2.5
c0-0.1,0-0.3,0-0.4v-2.5c0-0.8,0.4-1.6,1.1-2l8.8-5.7c1.4-0.9,2-1.7,2-3.8L53.7,28c0-1,0.4-1.9,1.2-2.5c1.5-1.3,2-3.7,0.8-5.6
c-0.8-1.4-2.4-2.2-4-2c-1.6,0.1-2.8,1-3.5,2.4c-0.5,1-0.6,2.2-0.3,3.3c0.2,0.8,0.7,1.4,1.3,2c0.7,0.6,1.2,1.5,1.2,2.5v7.2
c0,1.1-0.5,2.1-1.5,2.7l-5.5,2.8c-0.7,0.5-1.6,0-1.6-0.8l-0.2-17.1c0-1,0.5-1.9,1.2-2.5c0.4-0.3,0.7-0.8,1-1.3
c0.7-1.3,0.7-2.9-0.1-4.3c-0.8-1.4-2.5-2.2-4.1-2.1c-2.9,0.3-4.6,3.1-3.8,5.7c0.2,0.8,0.7,1.4,1.3,2c0.7,0.6,1.2,1.5,1.2,2.5v9.9
c0,0.8-0.8,1.3-1.5,0.9L34,32.5c-0.7-0.4-1.2-1.2-1.2-2.1v-2.2c0-1,0.4-1.9,1.2-2.5c1.5-1.3,2-3.7,0.8-5.6c-0.8-1.3-2.4-2.1-4-2
c-2.9,0.2-4.7,3.1-3.8,5.7c0.2,0.8,0.7,1.5,1.3,2c0.7,0.6,1.2,1.5,1.2,2.5l0,3.5c0,1,0,2,1.6,3.1l5.5,3c0.7,0.4,1.2,1.2,1.2,2.1v4.5
c0,0.8-0.8,1.3-1.5,0.9L26.6,41c-0.7-0.4-1.2-1.2-1.2-2.1l-0.2-6.1c0-1,0.4-1.8,1.1-2.5c1.4-1.3,1.9-3.4,0.9-5.3
c-0.8-1.4-2.4-2.3-4-2.2c-2.9,0.2-4.6,3-3.8,5.6c0.2,0.7,0.7,1.4,1.2,1.9c0.7,0.6,1.1,1.5,1.1,2.5l-0.5,6.8c0,1.9,0.3,2.8,1.8,3.5
l11.8,6.3c1,0.6,1.6,1.7,1.6,2.8l0,3.1c0,3.1,4.3,5.7,8.7,3.3l16.4-9.8c1.9-1,3.2-3,3.4-5.2V20.7C65,18.5,63.8,16.5,61.9,15.4z
M24.2,50.7c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C22.2,51.7,23.1,50.7,24.2,50.7z M48.7,21.5c0-1.1,0.9-2,2-2
s2,0.9,2,2c0,1.1-0.9,2-2,2S48.7,22.6,48.7,21.5z M30.6,23.8c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S31.8,23.8,30.6,23.8z
M22.2,26.4c0-1.1,0.9-2,2-2c1.1,0,2,0.9,2,2s-0.9,2-2,2C23.1,28.4,22.2,27.5,22.2,26.4z M40,17.9c-1.1,0-2-0.9-2-2c0-1.1,0.9-2,2-2
c1.1,0,2,0.9,2,2C42,17,41.1,17.9,40,17.9z"/>
</svg>

+ 14
- 6
models/dataset.go View File

@@ -122,22 +122,22 @@ func (datasets DatasetList) loadAttachmentAttributes(opts *SearchDatasetOptions)
for i := range datasets {
if attachment.DatasetID == datasets[i].ID {

if !attachment.IsPrivate{
if !attachment.IsPrivate {
datasets[i].Attachments = append(datasets[i].Attachments, attachment)
}else{
} else {
permission, ok := permissionMap[datasets[i].ID]
if !ok {

permission = false
datasets[i].Repo.GetOwner()
if !permission {
if datasets[i].Repo.OwnerID==opts.User.ID{
if datasets[i].Repo.OwnerID == opts.User.ID {
permission = true
}else{
} else {
isCollaborator, _ := datasets[i].Repo.IsCollaborator(opts.User.ID)
isInRepoTeam,_:=datasets[i].Repo.IsInRepoTeam(opts.User.ID)
isInRepoTeam, _ := datasets[i].Repo.IsInRepoTeam(opts.User.ID)

if isCollaborator ||isInRepoTeam {
if isCollaborator || isInRepoTeam {
permission = true
}
}
@@ -603,3 +603,11 @@ func UpdateDatasetCreateUser(ID int64, user *User) error {
}
return nil
}

func QueryDatasetGroupByTask() ([]map[string]interface{}, error) {
rows, err := x.QueryInterface("SELECT count(*) as total,task FROM public.dataset where task <>'' group by task order by total desc limit 7")
if err != nil {
return nil, err
}
return rows, nil
}

+ 5
- 1
models/repo_activity_custom.go View File

@@ -263,7 +263,11 @@ func GetAllUserKPIStats(startTime time.Time, endTime time.Time) (map[string]*git
log.Warn("get user kpi status err:"+repository.RepoPath(), err1.Error())
continue
}

// if repository.Name == "yolov5" {
// log.Info("repoName=" + repository.Name + " owner=" + repository.RepoPath())
// authorsOneRepoJson, _ := json.Marshal(authorsOneRepo)
// log.Info("authorsOneRepoJson=" + string(authorsOneRepoJson))
// }
for key, value := range authorsOneRepo {
if _, ok := authors[key]; !ok {
authors[key] = &git.UserKPIStats{


+ 9
- 0
models/resource_specification.go View File

@@ -298,6 +298,15 @@ func ResourceSpecOffShelf(id int64) (int64, error) {
return n, err
}

func GetResourceSpecificationByIds(ids []int64) ([]*Specification, error) {
r := make([]*Specification, 0)
err := x.In("resource_specification.id", ids).
Join("INNER", "resource_queue", "resource_queue.id = resource_specification.queue_id").
Find(&r)
return r, err

}

func GetResourceSpecification(r *ResourceSpecification) (*ResourceSpecification, error) {
has, err := x.Get(r)
if err != nil {


+ 1
- 1
models/user.go View File

@@ -346,7 +346,7 @@ func (u *User) DashboardLink() string {
if u.IsOrganization() {
return setting.AppSubURL + "/org/" + u.Name + "/dashboard/"
}
return setting.AppSubURL + "/"
return setting.AppSubURL + "/dashboard"
}

// HomeLink returns the user or organization home page link.


+ 17
- 4
modules/cloudbrain/cloudbrain.go View File

@@ -145,7 +145,7 @@ func isAdminOrImageCreater(ctx *context.Context, image *models.Image, err error)
func AdminOrOwnerOrJobCreaterRight(ctx *context.Context) {

var id = ctx.Params(":id")
job, err := models.GetCloudbrainByID(id)
job, err := GetCloudBrainByIdOrJobId(id)
if err != nil {
log.Error("GetCloudbrainByID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -161,7 +161,7 @@ func AdminOrOwnerOrJobCreaterRight(ctx *context.Context) {
func AdminOrJobCreaterRight(ctx *context.Context) {

var id = ctx.Params(":id")
job, err := models.GetCloudbrainByID(id)
job, err := GetCloudBrainByIdOrJobId(id)
if err != nil {
log.Error("GetCloudbrainByID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -177,7 +177,7 @@ func AdminOrJobCreaterRight(ctx *context.Context) {
func AdminOrOwnerOrJobCreaterRightForTrain(ctx *context.Context) {

var jobID = ctx.Params(":jobid")
job, err := models.GetCloudbrainByJobID(jobID)
job, err := GetCloudBrainByIdOrJobId(jobID)
if err != nil {
log.Error("GetCloudbrainByJobID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -193,7 +193,7 @@ func AdminOrOwnerOrJobCreaterRightForTrain(ctx *context.Context) {
func AdminOrJobCreaterRightForTrain(ctx *context.Context) {

var jobID = ctx.Params(":jobid")
job, err := models.GetCloudbrainByJobID(jobID)
job, err := GetCloudBrainByIdOrJobId(jobID)
if err != nil {
log.Error("GetCloudbrainByJobID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -652,3 +652,16 @@ func IsElementExist(s []string, str string) bool {
}
return false
}

func GetCloudBrainByIdOrJobId(id string) (*models.Cloudbrain,error) {
_, err := strconv.ParseInt(id, 10, 64)
var job *models.Cloudbrain
if err != nil {

job, err = models.GetCloudbrainByJobID(id)
} else {
job, err = models.GetCloudbrainByID(id)

}
return job,err
}

+ 94
- 8
modules/modelarts/modelarts.go View File

@@ -1,13 +1,18 @@
package modelarts

import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"path"
"strconv"
"strings"

"code.gitea.io/gitea/modules/cloudbrain"

"code.gitea.io/gitea/modules/modelarts_cd"

"code.gitea.io/gitea/models"
@@ -23,7 +28,7 @@ const (
//notebook
storageTypeOBS = "obs"
autoStopDuration = 4 * 60 * 60
autoStopDurationMs = 4 * 60 * 60 * 1000
AutoStopDurationMs = 4 * 60 * 60 * 1000
MORDELART_USER_IMAGE_ENGINE_ID = -1
DataSetMountPath = "/home/ma-user/work"
NotebookEnv = "Python3"
@@ -276,7 +281,7 @@ func GenerateTask(ctx *context.Context, jobName, uuid, description, flavor strin
return nil
}

func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, description, imageId string, spec *models.Specification) error {
func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, description, imageId string, spec *models.Specification, bootFile string,autoStopDurationInMs int64) (string, error) {
if poolInfos == nil {
json.Unmarshal([]byte(setting.PoolInfos), &poolInfos)
}
@@ -284,14 +289,14 @@ func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, desc
imageName, err := GetNotebookImageName(imageId)
if err != nil {
log.Error("GetNotebookImageName failed: %v", err.Error())
return err
return "", err
}
createTime := timeutil.TimeStampNow()
jobResult, err := createNotebook2(models.CreateNotebook2Params{
JobName: jobName,
Description: description,
Flavor: spec.SourceSpecId,
Duration: autoStopDurationMs,
Duration: autoStopDurationInMs,
ImageID: imageId,
PoolID: poolInfos.PoolInfo[0].PoolId,
Feature: models.NotebookFeature,
@@ -316,10 +321,10 @@ func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, desc
})
if errTemp != nil {
log.Error("InsertCloudbrainTemp failed: %v", errTemp.Error())
return errTemp
return "", errTemp
}
}
return err
return "", err
}
task := &models.Cloudbrain{
Status: jobResult.Status,
@@ -334,6 +339,7 @@ func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, desc
Uuid: uuid,
ComputeResource: models.NPUResource,
Image: imageName,
BootFile: bootFile,
Description: description,
CreatedUnix: createTime,
UpdatedUnix: createTime,
@@ -342,12 +348,12 @@ func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, desc

err = models.CreateCloudbrain(task)
if err != nil {
return err
return "", err
}

stringId := strconv.FormatInt(task.ID, 10)
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateDebugNPUTask)
return nil
return jobResult.ID, nil
}

func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (jobId string, err error) {
@@ -907,6 +913,11 @@ func HandleNotebookInfo(task *models.Cloudbrain) error {
if task.FlavorCode == "" {
task.FlavorCode = result.Flavor
}

if oldStatus != task.Status && task.Status == string(models.ModelArtsRunning) && task.BootFile != "" {
uploadNoteBookFile(task, result)

}
err = models.UpdateJob(task)
if err != nil {
log.Error("UpdateJob(%s) failed:%v", task.DisplayJobName, err)
@@ -917,6 +928,81 @@ func HandleNotebookInfo(task *models.Cloudbrain) error {
return nil
}

func uploadNoteBookFile(task *models.Cloudbrain, result *models.GetNotebook2Result) {
jupyterUrl := result.Url + "?token=" + result.Token

cookies, xsrf := getCookiesAndCsrf(jupyterUrl)
if xsrf == "" {
log.Error("browser jupyterUrl failed:%v", task.DisplayJobName)
} else {

codePath := setting.JobPath + task.JobName + cloudbrain.CodeMountPath
fileContents, err := ioutil.ReadFile(codePath + "/" + task.BootFile)
if err != nil {
log.Error("read jupyter file failed:%v", task.DisplayJobName, err)
}

base64Content := base64.StdEncoding.EncodeToString(fileContents)
client := getRestyClient()
uploadUrl := getJupyterBaseUrl(result.Url) + "api/contents/" + path.Base(task.BootFile)
res, err := client.R().
SetCookies(cookies).
SetHeader("X-XSRFToken", xsrf).
SetBody(map[string]interface{}{
"type": "file",
"format": "base64",
"name": path.Base(task.BootFile),
"path": path.Base(task.BootFile),
"content": base64Content}).
Put(uploadUrl)
if err != nil {
log.Error("upload jupyter file failed:%v", task.DisplayJobName, err)
} else if res.StatusCode() != http.StatusCreated {
log.Error("upload jupyter file failed:%v", task.DisplayJobName, err)
}

}

}

func getJupyterBaseUrl(url string) string {
jupyterUrlLength := len(url)
baseUrl := url[0 : jupyterUrlLength-len(path.Base(url))]
return baseUrl
}

func getCookiesAndCsrf(jupyterUrl string) ([]*http.Cookie, string) {
log.Info("jupyter url:"+jupyterUrl)
var cookies []*http.Cookie
const retryTimes = 10
for i := 0; i < retryTimes; i++ {
res, err := http.Get(jupyterUrl)
if err != nil {
log.Error("browser jupyterUrl failed.",err)
if i==retryTimes-1{
return cookies, ""
}

} else {
cookies = res.Cookies()
xsrf := ""
for _, cookie := range cookies {
if cookie.Name == "_xsrf" {
xsrf = cookie.Value
break
}

}
if xsrf != "" {
return cookies, xsrf
}

}
}
return cookies, ""

}

func SyncTempStatusJob() {
jobs, err := models.GetCloudBrainTempJobs()
if err != nil {


+ 1
- 1
modules/modelarts/resty.go View File

@@ -280,7 +280,7 @@ sendjob:
SetHeader("Content-Type", "application/json").
SetAuthToken(TOKEN).
SetResult(&result).
Post(HOST + "/v1/" + setting.ProjectID + urlNotebook2 + "/" + jobID + "/" + param.Action + "?duration=" + strconv.Itoa(autoStopDurationMs))
Post(HOST + "/v1/" + setting.ProjectID + urlNotebook2 + "/" + jobID + "/" + param.Action + "?duration=" + strconv.Itoa(AutoStopDurationMs))

if err != nil {
return &result, fmt.Errorf("resty ManageNotebook2: %v", err)


+ 8
- 45
modules/modelarts_cd/modelarts.go View File

@@ -88,18 +88,18 @@ type Parameters struct {
} `json:"parameter"`
}

func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, description, imageId string, spec *models.Specification) error {
func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, description, imageId string, spec *models.Specification, bootFile string,autoStopDurationInMs int64) (string, error) {
imageName, err := GetNotebookImageName(imageId)
if err != nil {
log.Error("GetNotebookImageName failed: %v", err.Error())
return err
return "", err
}
createTime := timeutil.TimeStampNow()
jobResult, err := createNotebook(models.CreateNotebookWithoutPoolParams{
JobName: jobName,
Description: description,
Flavor: spec.SourceSpecId,
Duration: autoStopDurationMs,
Duration: autoStopDurationInMs,
ImageID: imageId,
Feature: models.NotebookFeature,
Volume: models.VolumeReq{
@@ -123,10 +123,10 @@ func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, descr
})
if errTemp != nil {
log.Error("InsertCloudbrainTemp failed: %v", errTemp.Error())
return errTemp
return "", errTemp
}
}
return err
return "", err
}
task := &models.Cloudbrain{
Status: jobResult.Status,
@@ -145,16 +145,17 @@ func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, descr
CreatedUnix: createTime,
UpdatedUnix: createTime,
Spec: spec,
BootFile: bootFile,
}

err = models.CreateCloudbrain(task)
if err != nil {
return err
return "", err
}

stringId := strconv.FormatInt(task.ID, 10)
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateDebugNPUTask)
return nil
return jobResult.ID, nil
}

func GetNotebookImageName(imageId string) (string, error) {
@@ -175,41 +176,3 @@ func GetNotebookImageName(imageId string) (string, error) {

return imageName, nil
}

/*
func HandleNotebookInfo(task *models.Cloudbrain) error {

result, err := GetNotebook(task.JobID)
if err != nil {
log.Error("GetNotebook2(%s) failed:%v", task.DisplayJobName, err)
return err
}

if result != nil {
oldStatus := task.Status
task.Status = result.Status
if task.StartTime == 0 && result.Lease.UpdateTime > 0 {
task.StartTime = timeutil.TimeStamp(result.Lease.UpdateTime / 1000)
}
if task.EndTime == 0 && models.IsModelArtsDebugJobTerminal(task.Status) {
task.EndTime = timeutil.TimeStampNow()
}
task.CorrectCreateUnix()
task.ComputeAndSetDuration()
if oldStatus != task.Status {
notification.NotifyChangeCloudbrainStatus(task, oldStatus)
}
if task.FlavorCode == "" {
task.FlavorCode = result.Flavor
}
err = models.UpdateJob(task)
if err != nil {
log.Error("UpdateJob(%s) failed:%v", task.DisplayJobName, err)
return err
}
}

return nil
}

*/

+ 29
- 0
modules/setting/setting.go View File

@@ -717,6 +717,21 @@ var (
TeamName string
}{}

FileNoteBook = struct {
ProjectName string
ImageGPU string
SpecIdGPU int64
SpecIdCPU int64
ImageIdNPU string
SpecIdNPU int64
ImageIdNPUCD string
SpecIdNPUCD int64
ImageCPUDescription string
ImageGPUDescription string
ImageNPUDescription string
ImageNPUCDDescription string
}{}

ModelConvert = struct {
GPU_PYTORCH_IMAGE string
GpuQueue string
@@ -1582,6 +1597,20 @@ func NewContext() {
Course.OrgName = sec.Key("org_name").MustString("")
Course.TeamName = sec.Key("team_name").MustString("")

sec = Cfg.Section("file_notebook")
FileNoteBook.ProjectName = sec.Key("project_name").MustString("openi-notebook")
FileNoteBook.ImageIdNPU = sec.Key("imageid_npu").MustString("")
FileNoteBook.ImageGPU = sec.Key("image_gpu").MustString("")
FileNoteBook.SpecIdCPU = sec.Key("specid_cpu").MustInt64(-1)
FileNoteBook.SpecIdGPU = sec.Key("specid_gpu").MustInt64(-1)
FileNoteBook.SpecIdNPU = sec.Key("specid_npu").MustInt64(-1)
FileNoteBook.ImageIdNPUCD = sec.Key("imageid_npu_cd").MustString("")
FileNoteBook.SpecIdNPUCD = sec.Key("specid_npu_cd").MustInt64(-1)
FileNoteBook.ImageCPUDescription = sec.Key("image_cpu_desc").MustString("")
FileNoteBook.ImageGPUDescription = sec.Key("image_gpu_desc").MustString("")
FileNoteBook.ImageNPUDescription = sec.Key("image_npu_desc").MustString("")
FileNoteBook.ImageNPUCDDescription = sec.Key("image_npu_cd_desc").MustString("")

sec = Cfg.Section("kanban")
IsCloudbrainTimingEnabled = sec.Key("ENABLED").MustBool(false)



+ 8
- 0
modules/structs/cloudbrain.go View File

@@ -41,6 +41,14 @@ type CreateTrainJobOption struct {
SpecId int64 `json:"spec_id" binding:"Required"`
}

type CreateFileNotebookJobOption struct {
Type int `json:"type"` //0 CPU 1 GPU 2 NPU
File string `json:"file" binding:"Required"`
BranchName string `json:"branch_name" binding:"Required"`
OwnerName string `json:"owner_name" binding:"Required"`
ProjectName string `json:"project_name" binding:"Required"`
}

type Cloudbrain struct {
ID int64 `json:"id"`
JobID string `json:"job_id"`


+ 3
- 0
modules/templates/helper.go View File

@@ -151,6 +151,9 @@ func NewFuncMap() []template.FuncMap {
"EscapePound": func(str string) string {
return strings.NewReplacer("%", "%25", "#", "%23", " ", "%20", "?", "%3F").Replace(str)
},
"IpynbBool":func(str string) bool{
return strings.Contains(str, ".ipynb")
},
"nl2br": func(text string) template.HTML {
return template.HTML(strings.Replace(template.HTMLEscapeString(text), "\n", "<br>", -1))
},


+ 25
- 5
options/locale/locale_en-US.ini View File

@@ -24,6 +24,7 @@ enable_javascript = This website works better with JavaScript.
toc = Table of Contents
return=Back OpenI
calculation_points = Calculation Points
notice_announcement = Notice Announcement

username = Username
email = Email Address
@@ -236,7 +237,7 @@ page_title=Explore Better AI
page_small_title=OpenI AI Development Cooperation Platform
page_description=The one-stop collaborative development environment for AI field provides AI development pipeline integrating code development, data management, model debugging, reasoning and evaluation
page_use=Use Now
page_only_dynamic=Only show the dynamics of open source projects
page_only_dynamic=The dynamics of open source projects
page_recommend_org=Recommended Organizations
page_recommend_org_desc=These excellent organizations are using the OpenI AI Collaboration Platform for collaborative development of projects. To show your organization here,
page_recommend_org_commit=Click here to submit.
@@ -260,7 +261,7 @@ page_dev_env_desc3_title=Once Configuration, Multiple Reuse
page_dev_env_desc3_desc=Provide execution environment sharing, Once Configuration, Multiple Reuse. Lower the threshold of model development, and avoid spending repetitive time configuring complex environments.
page_dev_yunlao=OpenI AI Collaboration Platform
page_dev_yunlao_desc1=OpenI AI collaboration platform has cooperated with Pengcheng cloud brain and China computing power network (C²NET) can be used to complete AI development tasks by using the rich computing resources of Pengcheng cloud brain and China computing network.
page_dev_yunlao_desc2=Pengcheng CloudBrain's existing AI computing power is 100p FLOPS@FP16 (billions of half precision floating-point calculations per second), the main hardware infrastructure consists of GPU servers equipped with NVIDIA Tesla V100 and A100, and Atlas 900 AI clusters equipped with Kunpeng and shengteng processors.
page_dev_yunlao_desc2=Pengcheng CloudBrain is existing AI computing power is 100p FLOPS@FP16 (billions of half precision floating-point calculations per second), the main hardware infrastructure consists of GPU servers equipped with NVIDIA Tesla V100 and A100, and Atlas 900 AI clusters equipped with Kunpeng and shengteng processors.
page_dev_yunlao_desc3=China computing power network (C²NET) phase I can realize high-speed network interconnection between different artificial intelligence computing centers, and realize reasonable scheduling of computing power and flexible allocation of resources. At present, 11 intelligent computing centers have been connected, and the total scale of computing power is 1924p OPS@FP16. OpenI AI collaboration platform has been connected to Pengcheng Cloud Computing Institute, Chengdu Intelligent Computing Center, Zhongyuan Intelligent Computing Center, Hefei brain and other nodes.
page_dev_yunlao_desc4=Developers can freely select the corresponding computing resources according to the use needs, and can test the adaptability, performance, stability, etc. of the model in different hardware environments.
page_dev_yunlao_desc5=If your model requires more computing resources, you can also apply for it separately.
@@ -283,6 +284,7 @@ search_ge=
wecome_AI_plt = Welcome to OpenI AI Collaboration Platform!
explore_AI = Explore better AI, come here to find more interesting
datasets = Datasets
datasets_descr = Open source dataset base, seamlessly integrated with your project. View all
repositories = Repositories
use_plt__fuction = To use the AI collaboration functions provided by this platform, such as: hosting code, sharing data, debugging algorithms or training models, start with
provide_resoure = Computing resources of CPU/GPU/NPU are provided freely for various types of AI tasks.
@@ -290,6 +292,12 @@ activity = Activity
no_events = There are no events related
or_t = or
powerdby=Powered_by Pengcheng CloudBrain、China Computing NET(C²NET)、
experience_officer=Experience Officer
openi_experience_officer_plan=OpenI AI experience officer growth plan
more_benefits=, More benefits
org_see=See
more_notice=More notices
vedio_detail=Video details

[explore]
repos = Repositories
@@ -345,8 +353,10 @@ account_activated = Account has been activated
prohibit_login = Sign In Prohibited
prohibit_login_desc = Your account is prohibited to sign in, please contact your site administrator.
resent_limit_prompt = You have already requested an activation email recently. Please wait 3 minutes and try again.
has_unconfirmed_mail = Hi %s, you have an unconfirmed email address (<b>%s</b>). If you haven't received a confirmation email or need to resend a new one, please click on the button below.
resend_mail = Click here to resend your activation email
has_unconfirmed_mail = Hi %s, you have an unconfirmed email address (<b>%s</b>).
has_unconfirmed_mail_resend = If you did not receive the activation email, or need to resend it, please click the "Resend Confirmation Email" button below.
has_unconfirmed_mail_change=If you need to change the mailbox and then activate the mail, please click the "Modify Mailbox" button below.
resend_mail = Resend your activation email
email_not_associate = The email address is not associated with any account.
email_not_main=The email address is wrong, please input your primary email address.
email_not_right=The email address is not associated with any account, please input the right email address.
@@ -1010,6 +1020,8 @@ readme = README
readme_helper = Select a README file template.
auto_init = Initialize Repository (Adds .gitignore, License and README)
create_repo = Create Repository
failed_to_create_repo=Failed to create repository, please try again later.
failed_to_create_notebook_repo=Failed to create %s repository, please check whether you have the same name project, if yes please update or delete it first.
create_course = Publish Course
failed_to_create_course=Failed to publish course, please try again later.
default_branch = Default Branch
@@ -1044,6 +1056,10 @@ model_experience = Model Experience
model_noright=You have no right to do the operation.
model_rename=Duplicate model name, please modify model name.

notebook_file_not_exist=Notebook file does not exist.
notebook_select_wrong=Please select a Notebook(.ipynb) file first.
notebook_file_no_right=You have no right to access the Notebook(.ipynb) file.

date=Date
repo_add=Project Increment
repo_total=Project Total
@@ -1223,7 +1239,7 @@ cloudbrain.benchmark.evaluate_test=Test Script
cloudbrain.benchmark.types={"type":[{"id":1,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=detection","first":"Target detection","second":[{"id":1,"value":"None","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"yangzhx","repo_name":"detection_benchmark_script"}]},{"id":2,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=reid","first":"Target re-identification","second":[{"id":1,"value":"Vehicle re-identification","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"},{"id":2,"value":"Image-based person re-identification","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"}]},{"id":3,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=tracking","first":"Multi-target tracking","second":[{"id":1,"value":"None","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"lix07","repo_name":"MOT_benchmark_script"}]}]}
cloudbrain.morethanonejob=You already have a running or waiting task, create it after that task is over.
cloudbrain.morethanonejob1=You have created an <span style="color:rgba(242, 113, 28, 1);"> equivalent task </span> that is waiting or running, please wait for the task to finish before creating it.
cloudbrain.morethanonejob2=You can view all your Cloud Brain tasks in <a href="/cloudbrains" target="_blank"> Home > Cloudbrain Task </a>.
cloudbrain.morethanonejob2=You can view all your Cloud Brain tasks in <a href="/cloudbrains" target="_blank"> Home > Cloudbrain Task </a>.

modelarts.infer_job_model = Model
modelarts.infer_job_model_file = Model File
@@ -1443,6 +1459,7 @@ blame = Blame
normal_view = Normal View
line = line
lines = lines
notebook_open = Open in Notebook

editor.new_file = New File
editor.upload_file = Upload File
@@ -3196,6 +3213,9 @@ foot.copyright= Copyright: New Generation Artificial Intelligence Open Source Op
Platform_Tutorial = Tutorial
foot.advice_feedback = Feedback
resource_description = Resource Note
foot.openi_subscription_number = OpenI subscription number
foot.user_communication_group = User communication group

[cloudbrain]
all_resource_cluster=All Cluster
all_ai_center=All Computing NET


+ 22
- 4
options/locale/locale_zh-CN.ini View File

@@ -24,6 +24,7 @@ enable_javascript=使用 JavaScript能使本网站更好的工作。
toc=目录
return=返回OpenI
calculation_points=算力积分
notice_announcement=通知公告

username=用户名
email=电子邮件地址
@@ -238,7 +239,7 @@ page_title=探索更好的AI
page_small_title=启智AI协作平台
page_description=面向AI领域的一站式协同开发环境,提供集代码开发、数据管理、模型调试、推理和评测为一体的AI开发流水线
page_use=立即使用
page_only_dynamic=仅展示开源项目动态
page_only_dynamic=社区开源项目动态
page_recommend_org=推荐组织
page_recommend_org_desc=这些优秀的组织正在使用启智AI开发协作平台;你的组织也想展示到这里,
page_recommend_org_commit=点此提交
@@ -285,6 +286,7 @@ search_ge=个
wecome_AI_plt=欢迎来到启智AI协作平台!
explore_AI = 探索更好的AI,来这里发现更有意思的
datasets = 数据集
datasets_descr=开源数据集大本营,同你的项目无缝集成。查看所有
repositories = 项目
use_plt__fuction = 使用本平台提供的AI协作功能,如:托管代码、共享数据、调试算法或训练模型,请先
provide_resoure = 平台目前提供CPU、GPU、NPU的普惠算力资源,可进行多种类型的AI任务。
@@ -293,7 +295,12 @@ activity = 活动
no_events = 还没有与您相关的活动
or_t = 或
powerdby=Powered_by 鹏城实验室云脑、中国算力网(C²NET)、

experience_officer=体验官
openi_experience_officer_plan=启智社区体验官成长计划
more_benefits=,超多福利大放送
org_see=。查看
more_notice=更多通知
vedio_detail=详细介绍视频

[explore]
repos=项目
@@ -349,8 +356,10 @@ account_activated=帐户已激活
prohibit_login=禁止登录
prohibit_login_desc=您的帐户被禁止登录,请与网站管理员联系。
resent_limit_prompt=您请求发送激活邮件过于频繁,请等待 3 分钟后再试!
has_unconfirmed_mail=%s 您好,系统检测到您有一封发送至 <b>%s</b> 但未被确认的邮件。如果您未收到激活邮件,或需要重新发送,请单击下方的按钮。
resend_mail=单击此处重新发送确认邮件
has_unconfirmed_mail=%s 您好,系统检测到您有一封发送至 <b>%s</b> 但未被确认的邮件。
has_unconfirmed_mail_resend=如果您未收到激活邮件,或需要重新发送,请单击下方的 "重新发送确认邮件 " 按钮。
has_unconfirmed_mail_change=如果需要更改邮箱后再激活邮件,请单击下方的 "修改邮箱" 按钮
resend_mail=重新发送确认邮件
email_not_associate=您输入的邮箱地址未被关联到任何帐号!
email_not_main=电子邮箱地址不正确,请输入您设置的主要邮箱地址。
email_not_right=您输入了不存在的邮箱地址,请输入正确的邮箱地址。
@@ -1016,6 +1025,8 @@ readme=自述
readme_helper=选择自述文件模板。
auto_init=初始化存储库 (添加. gitignore、许可证和自述文件)
create_repo=创建项目
failed_to_create_repo=创建项目失败,请稍后再试。
failed_to_create_notebook_repo=创建项目%s失败,请检查您是否有同名的项目,如果有请先手工修改或删除后重试。
create_course=发布课程
failed_to_create_course=发布课程失败,请稍后再试。
default_branch=默认分支
@@ -1044,6 +1055,9 @@ model_experience = 模型体验
model_noright=您没有操作权限。
model_rename=模型名称重复,请修改模型名称

notebook_file_not_exist=Notebook文件不存在。
notebook_select_wrong=请先选择Notebook(.ipynb)文件。
notebook_file_no_right=您没有这个Notebook文件的读权限。

date=日期
repo_add=新增项目
@@ -1462,6 +1476,8 @@ normal_view=普通视图
line=行
lines=行

notebook_open = 在Notebook中打开

editor.new_file=新建文件
editor.upload_file=上传文件
editor.edit_file=编辑文件
@@ -3214,6 +3230,8 @@ foot.copyright= 版权所有:新一代人工智能开源开放平台(OpenI
Platform_Tutorial=新手指引
foot.advice_feedback = 意见反馈
resource_description = 资源说明
foot.openi_subscription_number = 启智社区订阅号
foot.user_communication_group = 用户交流群

[cloudbrain]
all_resource_cluster=全部集群


+ 360
- 56
public/home/home.js View File

@@ -9,16 +9,20 @@ if(isEmpty(token)){

var swiperNewMessage = new Swiper(".newslist", {
direction: "vertical",
slidesPerView: 9,
slidesPerView: 6,
loop: true,
spaceBetween: 8,
autoplay: {
delay: 2500,
disableOnInteraction: false,
},
});
var swiperEvent = new Swiper(".event-list", {
slidesPerView: 3,
spaceBetween: 30,

var swiperRepo = new Swiper(".homepro-list", {
slidesPerView: 1,
// slidesPerColumn: 2,
// slidesPerColumnFill:'row',
spaceBetween: 20,
pagination: {
el: ".swiper-pagination",
clickable: true,
@@ -27,49 +31,130 @@ var swiperEvent = new Swiper(".event-list", {
delay: 2500,
disableOnInteraction: false,
},
breakpoints: {
768: {
slidesPerView: 2,
},
1024: {
slidesPerView: 2,
},
1200: {
slidesPerView: 3,
},
1440: {
slidesPerView: 3,
},
1840: {
slidesPerView: 3,
},
1920: {
slidesPerView: 3,
},
},
});
var swiperRepo = new Swiper(".homepro-list", {

var swiperOrg = new Swiper(".homeorg-list", {
slidesPerView: 1,
slidesPerColumn: 2,
slidesPerColumnFill:'row',
spaceBetween: 30,
spaceBetween: 25,
pagination: {
el: ".swiper-pagination",
clickable: true,
},
autoplay: {
delay: 2500,
delay: 4500,
disableOnInteraction: false,
},
breakpoints: {
768: {
slidesPerView: 2,
slidesPerView: 3,
slidesPerColumn: 2,
},
1024: {
slidesPerView: 3,
slidesPerColumn: 2,
},
1200: {
slidesPerView: 4,
slidesPerColumn: 2,
},
1440: {
slidesPerView: 4,
slidesPerColumn: 2,
},
1840: {
slidesPerView: 4,
slidesPerColumn: 2,
},
1920: {
slidesPerView: 4,
slidesPerColumn: 2,
},
},
});

var swiperOrg = new Swiper(".homeorg-list", {
var swiperUserExp = new Swiper(".home-user-exp-list", {
slidesPerView: 1,
slidesPerColumn: 4,
spaceBetween: 0,
navigation: {
nextEl: '.homeuserexp .swiper-prev',
prevEl: '.homeuserexp .swiper-next',
},
autoplay: {
delay: 2500,
disableOnInteraction: false,
},
breakpoints: {
768: {
slidesPerView: 2,
},
1200: {
slidesPerView: 3,
},
1440: {
slidesPerView: 4,
},
1840: {
slidesPerView: 4,
},
1920: {
slidesPerView: 5,
},
},
});

var swiperDataset = new Swiper(".home-dataset-list", {
slidesPerView: 2,
slidesPerColumn: 1,
slidesPerColumnFill:'row',
spaceBetween: 15,
spaceBetween: 30,
pagination: {
el: ".swiper-pagination",
clickable: true,
},
autoplay: {
delay: 4500,
delay: 2500,
disableOnInteraction: false,
},
breakpoints: {
676: {
slidesPerView: 3,
},
768: {
slidesPerView: 2,
slidesPerView: 4,
},
1024: {
slidesPerView: 3,
1320: {
slidesPerView: 5,
},
1520: {
slidesPerView: 6,
},
1720: {
slidesPerView: 7,
},
1920: {
slidesPerView: 7,
},
},
});
@@ -85,7 +170,7 @@ document.onreadystatechange = function () {
if(document.readyState != "complete"){
return;
}
console.log("Start to open WebSocket." + document.readyState);
console.log("Start to open WebSocket." + document.readyState);
queryRecommendData();

var output = document.getElementById("newmessage");
@@ -101,6 +186,7 @@ document.onreadystatechange = function () {
};

socket.onmessage = function (e) {
if (!output) return;
var data =JSON.parse(e.data)
var html = "";
if (data != null){
@@ -177,18 +263,17 @@ document.onreadystatechange = function () {
var time = getTime(record.CreatedUnix,currentTime);
html += " " + time;
}
html += "</div>";
html += "</div></div>";
html += "</div>";
}
}
output.innerHTML = html;
$('#homenews p').show();
swiperNewMessage.updateSlides();
swiperNewMessage.updateProgress();
};
}



function getTaskLink(record){
var re = getRepoLink(record);
if(record.OpType == 24){
@@ -223,7 +308,7 @@ function getMsg(record){
}else{
console.log("act user is null.");
}
html += " <img class=\"ui avatar image\" src=\"/user/avatar/" + name + "/-1\" alt=\"\">"
html += "<div class=\"content-c\"><img class=\"ui avatar image\" src=\"/user/avatar/" + name + "/-1\" alt=\"\">"
html += " <div class=\"middle aligned content nowrap\">"
html += " <a href=\"/" + encodeURI(name) + "\" title=\"\">" + name + "</a>"
return html;
@@ -236,6 +321,7 @@ function getRepotext(record){
return record.Repo.OwnerName + "/" + record.Repo.Name;
}
}

function getRepoLink(record){
return encodeURI(record.Repo.OwnerName + "/" + record.Repo.Name);

@@ -437,10 +523,6 @@ function getAction(opType,isZh){
}
}





function queryRecommendData(){
$.ajax({
type:"GET",
@@ -453,7 +535,10 @@ function queryRecommendData(){
success:function(json){
displayOrg(json.org);
displayRepo(json.repo);
displayActivity(json.image);
displayActivity(json.activity);
displayDataset(json.dataset);
displayUserExp(json.user_experience);
LetterAvatar && LetterAvatar.transform();
},
error:function(response) {
}
@@ -463,49 +548,99 @@ function queryRecommendData(){

function displayActivity(json){
var activityDiv = document.getElementById("recommendactivity");
if (!activityDiv) return;
var html = "";
if (json != null && json.length > 0){
for(var i = 0; i < json.length;i++){
var record = json[i]
html += "<div class=\"swiper-slide\">";
html += "<a href=\"" + record["image_link"] + "\" class=\"ui fluid card\">";
html += " <div class=\"image\"><img src=\"" + record["url"] + "\"></div>"
var record = json[i];
var name = isZh ? (record["name"] || '') : (record["name_en"] || record["name"]);
html += "<div class=\"swiper-slide\" style=\"text-align:center;\">";
html += "<a href=\"" + record["image_link"] + "\">";
html += " <div class=\"image ui card\"><img src=\"" + record["url"] + "\">";
html += ' <div class="image-name" title="' + name + '">' + name + "</div>";
html += "</div>";
html += "</a>";
html += "</div>";
}
var swiperEvent = new Swiper(".event-list", {
slidesPerView: 1,
spaceBetween: 30,
// pagination: {
// el: ".swiper-pagination",
// clickable: true,
// },
autoplay: {
delay: 2500,
disableOnInteraction: false,
},
breakpoints: {
768: {
slidesPerView: Math.min(2, json.length),
},
1024: {
slidesPerView: Math.min(3, json.length),
},
1200: {
slidesPerView: Math.min(3, json.length),
},
1440: {
slidesPerView: Math.min(4, json.length),
},
1840: {
slidesPerView: Math.min(4, json.length),
},
1920: {
slidesPerView: Math.min(4, json.length),
},
},
});
activityDiv.innerHTML = html;
swiperEvent.updateSlides();
swiperEvent.updateProgress();
}
activityDiv.innerHTML = html;
swiperEvent.updateSlides();
swiperEvent.updateProgress();
}

function displayRepo(json){
var orgRepo = document.getElementById("recommendrepo");
var html = "";
if (json != null && json.length > 0){
for(var i = 0; i < json.length;i++){
var record = json[i]
html += "<div class=\"swiper-slide\">";
html += " <div class=\"ui fluid card\">";
html += " <div class=\"content\">";
html += " <span class=\"right floated meta\">";
html += " <i class=\"ri-star-line\"></i>" + record["NumStars"] + "<i class=\"ri-git-branch-line am-ml-10\"></i>" + record["NumForks"];
html += " </span>";
html += " <img class=\"left floated mini ui image\" src=\"" + record["Avatar"] + "\">";
html += " <a class=\"header nowrap\" href=\"/" + record["OwnerName"] + "/" + record["Name"] + "\">" + record["Alias"] +"</a>";
html += " <div class=\"description nowrap-2\">" + record["Description"] + " </div>";
html += " <div class=\"ui tags nowrap am-mt-10\">"
if(record["Topics"] != null){
for(var j = 0; j < record["Topics"].length; j++){
topic = record["Topics"][j];
url = "/explore/repos?q=" + (topic) + "&amp;topic="
html += "<a class=\"ui small label topic\" href=\"" + url + "\">" + topic + "</a>";
}
var repoMap = {};
for (var i = 0, iLen = json.length; i < iLen; i++) {
var repo = json[i];
var labelSearch = repo.Label;
var label = isZh ? repo.Label : repo.Label_en;
if (repoMap[label]) {
repoMap[label].push(repo);
} else {
repoMap[label] = [repo];
}
html += " </div>";
html += " </div>";
html += " </div>";
html += "</div>";
}

for (var label in repoMap) {
var repos = repoMap[label];
html += `<div class="swiper-slide"><div><a style="color:rgb(50, 145, 248);font-size:16px;font-weight:550;" href="/explore/repos?q=&topic=${labelSearch}&sort=hot"># ${label}</a></div>`;
for (var i = 0, iLen = repos.length; i < iLen; i++) {
if (i >= 4) break;
var repo = repos[i];
// <i class="ri-star-line"></i>${repo["NumStars"]}<i class="ri-git-branch-line am-ml-10"></i>${repo["NumForks"]}</span> <div class="ui tags nowrap am-mt-10"></div>
html += `<div class="ui fluid card" style="border-radius:6px;">
<div class="content">
${repo["Avatar"] ? `<img class="left floated mini ui image" src="${repo["Avatar"]}">` : `<img class="left floated mini ui image" avatar="${repo["OwnerName"]}">`}
<a class="header nowrap" style="color:rgb(50, 145, 248);font-size:14px;" href="/${repo["OwnerName"]}/${repo["Name"]}" title="${repo["Alias"]}">${repo["Alias"]}</a>
<div class="description nowrap-2" style="rgba(136,136,136,1);;font-size:12px;" title="${repo["Description"]}">${repo["Description"]}</div>
`;
// if (repo["Topics"] != null) {
// for(var j = 0; j < repo["Topics"].length; j++){
// var topic = repo["Topics"][j];
// var url = "/explore/repos?q=" + (topic) + "&amp;topic="
// html += `<a class="ui small label topic" href=" ${url}">${topic}</a>`;
// }
// }
html += `
</div>
</div>`;
}
html += '</div>'
}
}
orgRepo.innerHTML = html;
@@ -513,7 +648,6 @@ function displayRepo(json){
swiperRepo.updateProgress();
}


function getRepoOrOrg(key,isZhLang,numbers=1){
if(numbers > 1){
key+="1";
@@ -537,7 +671,7 @@ function displayOrg(json){
html += " <img class=\"ui image\" src=\"" + record["Avatar"] + "\">";
html += " <div class=\"content nowrap\">";
html += " <span class=\"ui blue\">" + record["Name"] + "</span> " + record["FullName"];
html += " <div class=\"sub header\">" + record["NumRepos"] +" " + getRepoOrOrg(1,isZh,record["NumRepos"]) + " ・ " + record["NumMembers"] +" " + getRepoOrOrg(2,isZh,record["NumMembers"]) + " ・ " + record["NumTeams"] + " " + getRepoOrOrg(3,isZh,record["NumTeams"]) + "</div>";
html += " <div class=\"sub header\" style=\"margin-top:4px;\"><span style=\"color:rgb(54, 56, 64)\">" + record["NumRepos"] +"</span> " + getRepoOrOrg(1,isZh,record["NumRepos"]) + " ・ <span style=\"color:rgb(54, 56, 64)\">" + record["NumMembers"] +"</span> " + getRepoOrOrg(2,isZh,record["NumMembers"]) + " ・ <span style=\"color:rgb(54, 56, 64)\">" + record["NumTeams"] + "</span> " + getRepoOrOrg(3,isZh,record["NumTeams"]) + "</div>";
html += " </div>";
html += " </div>";
html += " </div>";
@@ -548,3 +682,173 @@ function displayOrg(json){
orgDiv.innerHTML = html;
swiperOrg.updateSlides();
}

function displayDataset(data) {
var homeDatasetEl = document.getElementById("home_dataset");
if (!homeDatasetEl) return;
var html = '';
var svgStrMap = {
'0': '<svg xmlns="http://www.w3.org/2000/svg" class="svg svg-icon-path-icon fill" viewBox="0 0 32 32" width="32" height="32"><defs data-reactroot=""><linearGradient id="ila93em9ydx6bi61,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs" x1="0" x2="100%" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="#82d1f6" stop-opacity="1" offset="0"></stop><stop stop-color="#29b6f4" stop-opacity="1" offset="0.5"></stop><stop stop-color="#0089cd" stop-opacity="1" offset="0.99"></stop></linearGradient></defs><g><path d="M16 4c7.189 0 13.171 5.173 14.425 12-1.253 6.827-7.236 12-14.425 12s-13.171-5.173-14.425-12c1.253-6.827 7.236-12 14.425-12zM16 25.333c5.682-0.001 10.442-3.949 11.687-9.252l0.016-0.081c-1.265-5.379-6.024-9.322-11.703-9.322s-10.437 3.943-11.686 9.241l-0.016 0.081c1.261 5.384 6.021 9.332 11.703 9.333h0zM16 22c-3.314 0-6-2.686-6-6s2.686-6 6-6v0c3.314 0 6 2.686 6 6s-2.686 6-6 6v0zM16 19.333c1.841 0 3.333-1.492 3.333-3.333s-1.492-3.333-3.333-3.333v0c-1.841 0-3.333 1.492-3.333 3.333s1.492 3.333 3.333 3.333v0z"></path></g></svg>',
'1': '<svg xmlns="http://www.w3.org/2000/svg" class="svg svg-icon-path-icon fill" viewBox="0 0 32 32" width="32" height="32"><defs data-reactroot=""><linearGradient id="ila93gapd7aoa4d1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs" x1="0" x2="100%" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="#82d1f6" stop-opacity="1" offset="0"></stop><stop stop-color="#29b6f4" stop-opacity="1" offset="0.5"></stop><stop stop-color="#0089cd" stop-opacity="1" offset="0.99"></stop></linearGradient></defs><g><path d="M2.667 16c0-7.364 5.969-13.333 13.333-13.333s13.333 5.969 13.333 13.333-5.969 13.333-13.333 13.333h-13.333l3.905-3.905c-2.413-2.407-3.905-5.735-3.905-9.411 0-0.006 0-0.012 0-0.018v0.001zM9.104 26.667h6.896c5.891 0 10.667-4.776 10.667-10.667s-4.776-10.667-10.667-10.667c-5.891 0-10.667 4.776-10.667 10.667v0c0 2.869 1.135 5.553 3.124 7.543l1.885 1.885-1.239 1.239zM14.667 8h2.667v16h-2.667v-16zM9.333 12h2.667v8h-2.667v-8zM20 12h2.667v8h-2.667v-8z"></path></g></svg>',
'2': '<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-16fsqc8-0 lhfskE svg-icon-path-icon fill" viewBox="0 0 48 48" width="32" height="32"><defs data-reactroot=""><linearGradient id="ila93j5tkotzm421,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs" x1="0" x2="100%" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="#82d1f6" stop-opacity="1" offset="0"></stop><stop stop-color="#29b6f4" stop-opacity="1" offset="0.5"></stop><stop stop-color="#0089cd" stop-opacity="1" offset="0.99"></stop></linearGradient></defs><g><rect width="48" height="48" fill-opacity="0.01" fill="url(#ila93j5tkotzm421,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" storke="none"></rect><path stroke="url(#ila93j5tkotzm421,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" d="M4 24C4 24 10 15 14 15C18 15 22 17 24 17C26 17 30 15 34 15C38 15 44 24 44 24C44 24 34 34 24 34C14 34 4 24 4 24Z" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path><path stroke="url(#ila93j5tkotzm421,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" d="M4 24H44" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>',
'3': '<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-16fsqc8-0 beWLko svg-icon-path-icon fill" viewBox="0 0 48 48" width="32" height="32"><defs data-reactroot=""><linearGradient id="ila93k86om2ayqg1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs" x1="0" x2="100%" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="#82d1f6" stop-opacity="1" offset="0"></stop><stop stop-color="#29b6f4" stop-opacity="1" offset="0.5"></stop><stop stop-color="#0089cd" stop-opacity="1" offset="0.99"></stop></linearGradient></defs><g><path d="M6 25C6 15.0589 14.0589 7 24 7C30.8669 7 36.8357 10.8453 39.8706 16.5" stroke="url(#ila93k86om2ayqg1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4"></path><path d="M41 25H43L42 24L41 25Z" stroke="url(#ila93k86om2ayqg1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4"></path><path d="M31 34L28.375 27L25 18H23L19.625 27L17 34" stroke="url(#ila93k86om2ayqg1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4"></path><path d="M28.375 27H19.625" stroke="url(#ila93k86om2ayqg1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4"></path><path d="M7 25H5L6 26L7 25Z" stroke="url(#ila93k86om2ayqg1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4"></path><path d="M42 25C42 34.9411 33.9411 43 24 43C17.1331 43 11.1643 39.1547 8.12939 33.5" stroke="url(#ila93k86om2ayqg1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4"></path></g></svg>',
'4': '<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-16fsqc8-0 kqqJug svg-icon-path-icon fill" viewBox="0 0 48 48" width="32" height="32"><defs data-reactroot=""><linearGradient id="ila93lcoqm7710i1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs" x1="0" x2="100%" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="#82d1f6" stop-opacity="1" offset="0"></stop><stop stop-color="#29b6f4" stop-opacity="1" offset="0.5"></stop><stop stop-color="#0089cd" stop-opacity="1" offset="0.99"></stop></linearGradient></defs><g><path d="M33 4.99976H41C42.1046 4.99976 43 5.89519 43 6.99976V14.9998M43 32.9998V40.9998C43 42.1043 42.1046 42.9998 41 42.9998H33M15 42.9998H7C5.89543 42.9998 5 42.1043 5 40.9998V32.9998M5 14.9998V6.99976C5 5.89519 5.89543 4.99976 7 4.99976H15" stroke="url(#ila93lcoqm7710i1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path><path d="M24 38C30.6274 38 36 31.732 36 24C36 16.268 30.6274 10 24 10C17.3726 10 12 16.268 12 24C12 31.732 17.3726 38 24 38Z" stroke="url(#ila93lcoqm7710i1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4"></path><path d="M6 24H42" stroke="url(#ila93lcoqm7710i1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4" stroke-linecap="round"></path><path d="M20.0693 30.1057C21.3372 31.0429 22.6473 31.5115 23.9996 31.5115C25.3519 31.5115 26.698 31.0429 28.0378 30.1057" stroke="url(#ila93lcoqm7710i1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4" stroke-linecap="round"></path></g></svg>',
'5': '<svg xmlns="http://www.w3.org/2000/svg" class="svg svg-icon-path-icon fill" viewBox="0 0 32 32" width="32" height="32"><defs data-reactroot=""><linearGradient id="ila93mrrwzocn0r1,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs" x1="0" x2="100%" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="#82d1f6" stop-opacity="1" offset="0"></stop><stop stop-color="#29b6f4" stop-opacity="1" offset="0.5"></stop><stop stop-color="#0089cd" stop-opacity="1" offset="0.99"></stop></linearGradient></defs><g><path d="M16 26.667c5.891 0 10.667-4.776 10.667-10.667s-4.776-10.667-10.667-10.667v0c-5.891 0-10.667 4.776-10.667 10.667s4.776 10.667 10.667 10.667v0zM16 29.333c-7.364 0-13.333-5.969-13.333-13.333s5.969-13.333 13.333-13.333 13.333 5.969 13.333 13.333-5.969 13.333-13.333 13.333zM16 21.333c2.946 0 5.333-2.388 5.333-5.333s-2.388-5.333-5.333-5.333v0c-2.946 0-5.333 2.388-5.333 5.333s2.388 5.333 5.333 5.333v0zM16 24c-4.418 0-8-3.582-8-8s3.582-8 8-8v0c4.418 0 8 3.582 8 8s-3.582 8-8 8v0zM16 18.667c-1.473 0-2.667-1.194-2.667-2.667s1.194-2.667 2.667-2.667v0c1.473 0 2.667 1.194 2.667 2.667s-1.194 2.667-2.667 2.667v0z"></path></g></svg>',
'6': '<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-16fsqc8-0 cAmoNA svg-icon-path-icon fill" viewBox="0 0 48 48" width="32" height="32"><defs data-reactroot=""><linearGradient id="ila93oiqy4t1x861,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs" x1="0" x2="100%" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="#82d1f6" stop-opacity="1" offset="0"></stop><stop stop-color="#29b6f4" stop-opacity="1" offset="0.5"></stop><stop stop-color="#0089cd" stop-opacity="1" offset="0.99"></stop></linearGradient></defs><g><rect width="48" height="48" fill="white" fill-opacity="0.01"></rect><path d="M14.5397 20.0186C12.8522 17.9434 11.2675 17.4979 9.78564 18.6821C7.5629 20.4583 6.92453 26.6496 8.71324 32.1086C10.502 37.5676 13.9801 45.0017 21.0016 45.0017C28.0231 45.0017 29.684 37.5222 32.5485 33.0001C35.413 28.478 36.9285 24.1152 34.1208 18.6821" stroke="url(#ila93oiqy4t1x861,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11 18.0368C9.29707 15.4428 7.96374 13.4306 6.99996 12.0002C5.5543 9.85464 9.25107 7.08164 11 8.96807C12.1659 10.2257 13.7148 12.078 15.6466 14.5249" stroke="url(#ila93oiqy4t1x861,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4" stroke-linecap="round"></path><path d="M15.0236 25.6396C14.5391 19.5759 14.9333 15.6276 16.2062 13.7947C18.1155 11.0455 21.6631 10.0031 25.0035 10.0031C26.9924 10.0031 28.8087 10.8502 30.4525 12.5444" stroke="url(#ila93oiqy4t1x861,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M41.0003 12.6128C41.5858 14.6492 40.6294 16.5097 37.6844 16.931C34.7393 17.3523 32.5313 18.8332 30.9388 20.079C29.3463 21.3248 26.4983 25.1046 25.9361 27.0023C25.3738 28.9 22.1602 27.1547 21.2971 26.3971C20.434 25.6394 19.5855 23.9806 21.2971 22.2457C23.0086 20.5108 22.6383 20.1646 22.6383 18.4052C22.6383 16.6459 32.0003 10.8263 37.2729 10.2941C38.4449 10.2257 40.4147 10.5763 41.0003 12.6128Z" stroke="url(#ila93oiqy4t1x861,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4"></path><path d="M23.0078 4.00014V9.26283" stroke="url(#ila93oiqy4t1x861,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4" stroke-linecap="round"></path><path d="M20.3066 10.7178C17.2888 6.92534 14.8555 4.80868 13.0068 4.36781" stroke="url(#ila93oiqy4t1x861,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4" stroke-linecap="round"></path><path d="M17.0039 7.02894L17.9944 2.96156" stroke="url(#ila93oiqy4t1x861,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4" stroke-linecap="round"></path><path d="M35.6128 10.7174C35.2905 11.8219 35.2905 12.8575 35.6128 13.8241C35.935 14.7908 36.6255 15.8264 37.6842 16.9308" stroke="url(#ila93oiqy4t1x861,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs)" fill="none" stroke-width="4" stroke-linecap="round"></path></g></svg>',
}
for (var i = 0, iLen = data.length; i < iLen; i++) {
var dataI = data[i];
html += `<div class="swiper-slide">
<a href="/explore/datasets?sort=default&q=&tab=&category=&task=${dataI.task}&license=">
<div class="ui fluid dataset-card">
<div><div class="content icon-c">
${svgStrMap[i % 7]}
</div></div>
<div><div class="content label" title="${i18n[dataI.task] || dataI.task}">${i18n[dataI.task] || dataI.task}</div></div>
<div><div class="content count" style="">${i18n['about']} ${dataI.total} ${i18n['count']}</div></div>
</div>
</a>
</div>`
}
homeDatasetEl.innerHTML = html;
swiperDataset.updateSlides();
swiperDataset.updateProgress();
}

function displayUserExp(data) {
var homeUserExpEl = document.getElementById("home_user-exp");
if (!homeUserExpEl) return;
var html = '';
for (var i = 0, iLen = data.length; i < iLen; i++) {
var dataI = data[i];
html += `<div class="swiper-slide">
<div class="ui fluid user-card">
<div><div class="content img-c">
<a href="/${dataI.name}">
<div class="img" style="width:60px;height:60px;background-image:url('${dataI.avatar}')"></div>
</a>
</div></div>
<div><div class="content label" title="${dataI.fullname || dataI.name}">${dataI.fullname || dataI.name}</div></div>
<div><div class="content descr" title="${dataI.desc}">${dataI.desc}</div></div>
</div>
</div>`
}
homeUserExpEl.innerHTML = html;
swiperUserExp.updateSlides();
swiperUserExp.updateProgress();
}

function getNotice() {
$.ajax({
type:"GET",
url:"/dashboard/invitation",
headers: { authorization:token, },
dataType:"json",
data: {
filename: 'notice/notice.json',
},
success:function(json){
if (json) {
try {
var noticeList = JSON.parse(json).Notices || [];
var noticeEls = $('._hm-recommend-info-area-1 a._hm-notice');
for (var i = 0, iLen = noticeEls.length; i < iLen; i++) {
var noticeEl = noticeEls.eq(i);
var noticeObj = noticeList[i];
if (noticeObj) {
var title = isZh ? noticeObj.Title : (noticeObj.Title_en || noticeObj.Title);
noticeEl.attr('href', noticeObj.Link);
noticeEl.find('span').text(title).attr('title', title);
noticeEl.show();
} else {
noticeEl.hide();
}
}
} catch (e) {
console.info(e);
}
}
},
error:function(response) {
}
});
}

function getRecommendModule() {
$.ajax({
type:"GET",
url:"/dashboard/invitation",
headers: { authorization:token, },
dataType:"json",
data: {
filename: 'home/newfunction',
},
success:function(json){
if (json) {
try {
var recommendModuleList = JSON.parse(json) || [];
var recommendModuleEls = $('._hm-recommend-info-area a._hm-link');
for (var i = 0, iLen = recommendModuleEls.length; i < iLen; i++) {
var recommendModuleEl = recommendModuleEls.eq(i);
var recommendModuleObj = recommendModuleList[i];
if (recommendModuleObj) {
recommendModuleEl.attr('href', recommendModuleObj.image_link);
recommendModuleEl.text(isZh ? recommendModuleObj.name : (recommendModuleObj.name_en || recommendModuleObj.name));
} else {
}
}
} catch (e) {
console.info(e);
}
}
},
error:function(response) {
}
});
}

function initHomeTopBanner() {
var homeSlideTimer = null;
var homeSlideDuration = 8000;
function homeSlide(direction) {
var slidePages = $('._hm-pg-c ._hm-pg');
var currentPage = slidePages.filter('._hm-pg-show');
var currentIndex = currentPage.index();
var next = direction == 'left' ? currentIndex - 1 : currentIndex + 1;
if (next < 0) next = slidePages.length - 1;
if (next == slidePages.length) next = 0;
slidePages.removeClass('_hm-pg-show');
slidePages.eq(next).addClass('_hm-pg-show');
}

function startSlide() {
homeSlideTimer && clearTimeout(homeSlideTimer);
homeSlideTimer = setTimeout(function() {
homeSlide('right');
startSlide();
}, homeSlideDuration);
}

function stopSlide() {
homeSlideTimer && clearTimeout(homeSlideTimer);
}

$('._hm-slide-btn').on('click', function () {
if ($(this).hasClass('_hm-slide-btn-left')) {
homeSlide('left');
} else {
homeSlide('right');
}
startSlide();
});
$('._hm-pg #homenews').on('mouseenter', function() {
stopSlide();
}).on('mouseleave', function() {
startSlide();
});
setTimeout(function() { startSlide(); }, 500);
}

initHomeTopBanner();
getNotice();
getRecommendModule();

+ 1
- 1
public/img/search.svg View File

@@ -1 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1638433773401" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2884" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M469.333333 768c-166.4 0-298.666667-132.266667-298.666666-298.666667s132.266667-298.666667 298.666666-298.666666 298.666667 132.266667 298.666667 298.666666-132.266667 298.666667-298.666667 298.666667z m0-85.333333c119.466667 0 213.333333-93.866667 213.333334-213.333334s-93.866667-213.333333-213.333334-213.333333-213.333333 93.866667-213.333333 213.333333 93.866667 213.333333 213.333333 213.333334z m251.733334 0l119.466666 119.466666-59.733333 59.733334-119.466667-119.466667 59.733334-59.733333z" fill="#5BB973" p-id="2885"></path></svg>
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-16fsqc8-0 fPsHiw svg-icon-path-icon fill" viewBox="0 0 32 32" width="24" height="24"><defs data-reactroot=""></defs><g><path fill="rgb(255, 255, 255)" d="M14.667 2.667c6.624 0 12 5.376 12 12s-5.376 12-12 12-12-5.376-12-12 5.376-12 12-12zM14.667 24c5.156 0 9.333-4.177 9.333-9.333 0-5.157-4.177-9.333-9.333-9.333-5.157 0-9.333 4.176-9.333 9.333 0 5.156 4.176 9.333 9.333 9.333zM25.98 24.095l3.772 3.771-1.887 1.887-3.771-3.772 1.885-1.885z"></path></g></svg>

+ 6
- 0
routers/api/v1/api.go View File

@@ -737,6 +737,12 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/my_favorite", repo.MyFavoriteDatasetMultiple)
}, reqToken(), repoAssignment())

m.Group("/file_notebook", func() {
m.Get("", reqToken(), repo.GetFileNoteBookInfo)
m.Post("/create", reqToken(), reqWeChat(), bind(api.CreateFileNotebookJobOption{}), repo.CreateFileNoteBook)

})

m.Group("/repos", func() {
m.Get("/search", repo.Search)



+ 76
- 7
routers/api/v1/repo/cloudbrain.go View File

@@ -79,6 +79,75 @@ func CloudBrainShow(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, models.BaseMessageWithDataApi{Code: 0, Message: "", Data: convert.ToCloudBrain(task)})

}
func CreateFileNoteBook(ctx *context.APIContext, option api.CreateFileNotebookJobOption) {
cloudbrainTask.FileNotebookCreate(ctx.Context, option)
}

func GetFileNoteBookInfo(ctx *context.APIContext) {
//image description spec description waiting count

specs, err := models.GetResourceSpecificationByIds([]int64{setting.FileNoteBook.SpecIdCPU, setting.FileNoteBook.SpecIdGPU, setting.FileNoteBook.SpecIdNPU, setting.FileNoteBook.SpecIdNPUCD})
if err != nil {
log.Error("Fail to query specifications", err)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_query_fail")))
return
}

var specCPU, specGpu, specNPU, specNPUCD *api.SpecificationShow
var specGpuQueueCode string
for _, spec := range specs {
if spec.ID == setting.FileNoteBook.SpecIdCPU {
specCPU = convert.ToSpecification(spec)
} else if spec.ID == setting.FileNoteBook.SpecIdGPU {
specGpu = convert.ToSpecification(spec)
specGpuQueueCode = spec.QueueCode
} else if spec.ID == setting.FileNoteBook.SpecIdNPU {
specNPU = convert.ToSpecification(spec)
} else if spec.ID == setting.FileNoteBook.SpecIdNPUCD {
specNPUCD = convert.ToSpecification(spec)
}
}

waitCountNpu := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "")

queuesMap, err := cloudbrain.GetQueuesDetail()
if err != nil {
log.Error("Fail to query gpu queues waiting count", err)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_query_fail")))
return
}
waitCountGPU := (*queuesMap)[specGpuQueueCode]
if !setting.ModelartsCD.Enabled{
ctx.JSON(http.StatusOK, map[string]interface{}{
"code": 0,
"projectName":setting.FileNoteBook.ProjectName,
"specCpu": specCPU,
"specGpu": specGpu,
"specNpu": specNPU,
"waitCountGpu": waitCountGPU,
"waitCountNpu": waitCountNpu,
"imageCpuDescription": setting.FileNoteBook.ImageCPUDescription,
"imageGpuDescription": setting.FileNoteBook.ImageGPUDescription,
"imageNpuDescription": setting.FileNoteBook.ImageNPUDescription,

})
} else{
ctx.JSON(http.StatusOK, map[string]interface{}{
"code": 0,
"projectName":setting.FileNoteBook.ProjectName,
"specCpu": specCPU,
"specGpu": specGpu,
"specNpu": specNPUCD,
"waitCountGpu": waitCountGPU,
"waitCountNpu": waitCountNpu,
"imageCpuDescription": setting.FileNoteBook.ImageCPUDescription,
"imageGpuDescription": setting.FileNoteBook.ImageGPUDescription,
"imageNpuDescription": setting.FileNoteBook.ImageNPUCDDescription,
})

}

}

func CreateCloudBrain(ctx *context.APIContext, option api.CreateTrainJobOption) {
if option.Type == cloudbrainTask.TaskTypeCloudbrainOne {
@@ -141,10 +210,11 @@ func GetCloudbrainTask(ctx *context.APIContext) {
)

ID := ctx.Params(":id")
job, err := models.GetCloudbrainByID(ID)

job,err := cloudbrain.GetCloudBrainByIdOrJobId(ID)

if err != nil {
ctx.NotFound(err)
log.Error("GetCloudbrainByID failed:", err)
return
}
if job.JobType == string(models.JobTypeModelSafety) {
@@ -566,7 +636,6 @@ func CloudbrainDownloadLogFile(ctx *context.Context) {
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
}
log.Info("fileName=" + fileName)
@@ -650,7 +719,7 @@ func CloudbrainGetLog(ctx *context.APIContext) {
result = getLogFromModelDir(job.JobName, startLine, endLine, resultPath)
if result == nil {
log.Error("GetJobLog failed: %v", err, ctx.Data["MsgID"])
ctx.ServerError(err.Error(), err)
//ctx.ServerError(err.Error(), err)
return
}
}
@@ -865,7 +934,7 @@ func CloudBrainModelConvertList(ctx *context.APIContext) {
err = json.Unmarshal([]byte(dirs), &fileInfos)
if err != nil {
log.Error("json.Unmarshal failed:%v", err.Error(), ctx.Data["msgID"])
ctx.ServerError("json.Unmarshal failed:", err)
//ctx.ServerError("json.Unmarshal failed:", err)
return
}

@@ -896,7 +965,7 @@ func CloudBrainModelConvertList(ctx *context.APIContext) {
models, err := storage.GetObsListObject(job.ID, "output/", parentDir, versionName)
if err != nil {
log.Info("get TrainJobListModel failed:", err)
ctx.ServerError("GetObsListObject:", err)
//ctx.ServerError("GetObsListObject:", err)
return
}

@@ -941,7 +1010,7 @@ func CloudBrainModelList(ctx *context.APIContext) {
err = json.Unmarshal([]byte(dirs), &fileInfos)
if err != nil {
log.Error("json.Unmarshal failed:%v", err.Error(), ctx.Data["msgID"])
ctx.ServerError("json.Unmarshal failed:", err)
//ctx.ServerError("json.Unmarshal failed:", err)
return
}



+ 5
- 1
routers/api/v1/repo/modelarts.go View File

@@ -6,6 +6,7 @@
package repo

import (
"code.gitea.io/gitea/modules/cloudbrain"
"encoding/json"
"net/http"
"path"
@@ -37,11 +38,14 @@ func GetModelArtsNotebook2(ctx *context.APIContext) {
)

ID := ctx.Params(":id")
job, err := models.GetCloudbrainByID(ID)

job,err := cloudbrain.GetCloudBrainByIdOrJobId(ID)

if err != nil {
ctx.NotFound(err)
return
}

err = modelarts.HandleNotebookInfo(job)
if err != nil {
ctx.NotFound(err)


+ 58
- 15
routers/home.go View File

@@ -7,6 +7,7 @@ package routers

import (
"bytes"
"encoding/json"
"net/http"
"strconv"
"strings"
@@ -672,7 +673,7 @@ func NotFound(ctx *context.Context) {
}

func getRecommendOrg() ([]map[string]interface{}, error) {
url := setting.RecommentRepoAddr + "organizations"
url := setting.RecommentRepoAddr + "home/organizations"
result, err := repository.RecommendFromPromote(url)

if err != nil {
@@ -745,7 +746,7 @@ func GetMapInfo(ctx *context.Context) {
}

func GetRankUser(index string) ([]map[string]interface{}, error) {
url := setting.RecommentRepoAddr + "user_rank_" + index
url := setting.RecommentRepoAddr + "user_rank/user_rank_" + index
result, err := repository.RecommendFromPromote(url)

if err != nil {
@@ -756,13 +757,25 @@ func GetRankUser(index string) ([]map[string]interface{}, error) {
tmpIndex := strings.Index(userRank, " ")
userName := userRank
score := 0
label := ""
if tmpIndex != -1 {
userName = userRank[0:tmpIndex]
tmpScore, err := strconv.Atoi(userRank[tmpIndex+1:])
if err != nil {
log.Info("convert to int error.")
left := userRank[tmpIndex+1:]
tmpIndex1 := strings.Index(left, " ")
if tmpIndex1 != -1 {
tmpScore, err := strconv.Atoi(left[0:tmpIndex1])
if err != nil {
log.Info("convert to int error.")
}
score = tmpScore
label = left[tmpIndex1+1:]
} else {
tmpScore, err := strconv.Atoi(left[tmpIndex+1:])
if err != nil {
log.Info("convert to int error.")
}
score = tmpScore
}
score = tmpScore
}
user, err := models.GetUserByName(userName)
if err == nil {
@@ -772,6 +785,7 @@ func GetRankUser(index string) ([]map[string]interface{}, error) {
userMap["FullName"] = user.FullName
userMap["HomeLink"] = user.HomeLink()
userMap["ID"] = user.ID
userMap["Label"] = label
userMap["Avatar"] = user.RelAvatarLink()
userMap["Score"] = score
resultOrg = append(resultOrg, userMap)
@@ -792,25 +806,54 @@ func GetUserRankFromPromote(ctx *context.Context) {
ctx.JSON(200, resultUserRank)
}

func getMapContent(fileName string) []map[string]string {
url := setting.RecommentRepoAddr + fileName
result, err := repository.RecommendContentFromPromote(url)
remap := make([]map[string]string, 0)
if err == nil {
json.Unmarshal([]byte(result), &remap)
}
return remap
}

func HomeNoticeTmpl(ctx *context.Context) {
ctx.Data["url_params"] = ""
ctx.HTML(200, "notice")
}

func RecommendHomeInfo(ctx *context.Context) {
resultOrg, err := getRecommendOrg()
if err != nil {
log.Info("error." + err.Error())
}
resultRepo, err := repository.GetRecommendRepoFromPromote("projects")
repoMap := getMapContent("home/projects")
resultRepo, err := repository.GetRecommendRepoFromPromote(repoMap)
if err != nil {
log.Info("error." + err.Error())
}
resultImage, err := getImageInfo("picture_info")
if err != nil {
log.Info("error." + err.Error())
}

resultActivityInfo := getMapContent("home/activity_info")
mapInterface := make(map[string]interface{})
mapInterface["org"] = resultOrg
mapInterface["repo"] = resultRepo
mapInterface["image"] = resultImage
//mapInterface["cloudbrain"] = resultCloudBrain
mapInterface["activity"] = resultActivityInfo

user_experience := getMapContent("home/user_experience")
for _, amap := range user_experience {
userId := amap["userid"]
userIntId, _ := strconv.Atoi(userId)
user, err := models.GetUserByID(int64(userIntId))
if err == nil {
amap["name"] = user.Name
amap["fullname"] = user.FullName
amap["detail"] = user.Description
amap["avatar"] = user.AvatarLink()
}
}
mapInterface["user_experience"] = user_experience
dataset, err := models.QueryDatasetGroupByTask()
if err == nil {
mapInterface["dataset"] = dataset
}
ctx.JSON(http.StatusOK, mapInterface)
}

@@ -824,4 +867,4 @@ func HomePrivacy(ctx *context.Context) {

func HomeResoruceDesc(ctx *context.Context) {
ctx.HTML(200, tplResoruceDesc)
}
}

+ 0
- 1
routers/repo/ai_model_convert.go View File

@@ -828,5 +828,4 @@ func ModelConvertDownloadModel(ctx *context.Context) {
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusTemporaryRedirect)
}
}

}

+ 4
- 5
routers/repo/aisafety.go View File

@@ -11,7 +11,8 @@ import (
"os"
"strconv"
"strings"
"time"

cloudbrainService "code.gitea.io/gitea/services/cloudbrain"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/aisafety"
@@ -483,7 +484,6 @@ func isTaskNotFinished(status string) bool {
}

func AiSafetyCreateForGetGPU(ctx *context.Context) {
t := time.Now()
ctx.Data["PageIsCloudBrain"] = true
ctx.Data["IsCreate"] = true
ctx.Data["type"] = models.TypeCloudBrainOne
@@ -497,7 +497,7 @@ func AiSafetyCreateForGetGPU(ctx *context.Context) {
log.Info("GPUBaseDataSetUUID=" + setting.ModelSafetyTest.GPUBaseDataSetUUID)
log.Info("GPUCombatDataSetName=" + setting.ModelSafetyTest.GPUCombatDataSetName)
log.Info("GPUCombatDataSetUUID=" + setting.ModelSafetyTest.GPUCombatDataSetUUID)
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName
prepareCloudbrainOneSpecs(ctx)
queuesDetail, _ := cloudbrain.GetQueuesDetail()
@@ -514,12 +514,11 @@ func AiSafetyCreateForGetGPU(ctx *context.Context) {
}

func AiSafetyCreateForGetNPU(ctx *context.Context) {
t := time.Now()
ctx.Data["PageIsCloudBrain"] = true
ctx.Data["IsCreate"] = true
ctx.Data["type"] = models.TypeCloudBrainTwo
ctx.Data["compute_resource"] = models.NPUResource
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName
ctx.Data["datasetType"] = models.TypeCloudBrainTwo
ctx.Data["BaseDataSetName"] = setting.ModelSafetyTest.NPUBaseDataSetName


+ 12
- 53
routers/repo/cloudbrain.go View File

@@ -15,6 +15,8 @@ import (
"time"
"unicode/utf8"

cloudbrainService "code.gitea.io/gitea/services/cloudbrain"

"code.gitea.io/gitea/modules/urfs_client/urchin"

"code.gitea.io/gitea/modules/dataset"
@@ -92,28 +94,9 @@ func MustEnableCloudbrain(ctx *context.Context) {
}
}

func cutString(str string, lens int) string {
if len(str) < lens {
return str
}
return str[:lens]
}

func jobNamePrefixValid(s string) string {
lowStr := strings.ToLower(s)
re := regexp.MustCompile(`[^a-z0-9_\\-]+`)

removeSpecial := re.ReplaceAllString(lowStr, "")

re = regexp.MustCompile(`^[_\\-]+`)
return re.ReplaceAllString(removeSpecial, "")

}

func cloudBrainNewDataPrepare(ctx *context.Context, jobType string) error {
ctx.Data["PageIsCloudBrain"] = true
t := time.Now()
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName

ctx.Data["command"] = cloudbrain.GetCloudbrainDebugCommand()
@@ -696,7 +679,7 @@ func CloudBrainRestart(ctx *context.Context) {
} else {
if count >= 1 {
log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
resultCode = "-1"
resultCode = "2"
errorMsg = ctx.Tr("repo.cloudbrain.morethanonejob")
break
}
@@ -759,43 +742,13 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
return
}
if task.Status == string(models.JobWaiting) || task.Status == string(models.JobRunning) {
result, err := cloudbrain.GetJob(task.JobID)
task, err = cloudbrainTask.SyncCloudBrainOneStatus(task)
if err != nil {
log.Info("error:" + err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
return
}

if result != nil {
jobRes, _ := models.ConvertToJobResultPayload(result.Payload)
taskRoles := jobRes.TaskRoles
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))
ctx.Data["taskRes"] = taskRes
ctx.Data["ExitDiagnostics"] = taskRes.TaskStatuses[0].ExitDiagnostics
oldStatus := task.Status
task.Status = taskRes.TaskStatuses[0].State
task.ContainerIp = ""
task.ContainerID = taskRes.TaskStatuses[0].ContainerID
models.ParseAndSetDurationFromCloudBrainOne(jobRes, task)

if task.DeletedAt.IsZero() { //normal record
if oldStatus != task.Status {
notification.NotifyChangeCloudbrainStatus(task, oldStatus)
}
err = models.UpdateJob(task)
if err != nil {
ctx.Data["error"] = err.Error()
return
}
} else { //deleted record

}

ctx.Data["result"] = jobRes
} else {
log.Info("error:" + err.Error())
return
}
}

user, err := models.GetUserByID(task.UserID)
@@ -889,7 +842,13 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
func CloudBrainDebug(ctx *context.Context) {
task := ctx.Cloudbrain
debugUrl := setting.DebugServerHost + "jpylab_" + task.JobID + "_" + task.SubTaskName
ctx.Redirect(debugUrl)
if task.BootFile!=""{
ctx.Redirect(getFileUrl(debugUrl,task.BootFile))

}else{
ctx.Redirect(debugUrl)
}

}

func prepareSpec4Show(ctx *context.Context, task *models.Cloudbrain) {


+ 1
- 3
routers/repo/grampus.go View File

@@ -10,7 +10,6 @@ import (
"path"
"strconv"
"strings"
"time"

"code.gitea.io/gitea/modules/urfs_client/urchin"
"code.gitea.io/gitea/routers/response"
@@ -77,8 +76,7 @@ func GrampusTrainJobNPUNew(ctx *context.Context) {
func grampusTrainJobNewDataPrepare(ctx *context.Context, processType string) error {
ctx.Data["PageIsCloudBrain"] = true

t := time.Now()
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName

//get valid images


+ 35
- 10
routers/repo/modelarts.go View File

@@ -15,6 +15,8 @@ import (
"time"
"unicode/utf8"

cloudbrainService "code.gitea.io/gitea/services/cloudbrain"

"code.gitea.io/gitea/services/cloudbrain/cloudbrainTask"

"code.gitea.io/gitea/modules/dataset"
@@ -128,8 +130,7 @@ func NotebookNew(ctx *context.Context) {

func notebookNewDataPrepare(ctx *context.Context) error {
ctx.Data["PageIsCloudBrain"] = true
t := time.Now()
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName

attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID)
@@ -239,9 +240,9 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm
}

if setting.ModelartsCD.Enabled {
err = modelarts_cd.GenerateNotebook(ctx, displayJobName, jobName, uuid, description, imageId, spec)
_, err = modelarts_cd.GenerateNotebook(ctx, displayJobName, jobName, uuid, description, imageId, spec, "",modelarts.AutoStopDurationMs)
} else {
err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, uuid, description, imageId, spec)
_, err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, uuid, description, imageId, spec, "",modelarts.AutoStopDurationMs)
}

if err != nil {
@@ -387,8 +388,33 @@ func NotebookDebug2(ctx *context.Context) {
ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil)
return
}
if task.BootFile!=""{
ctx.Redirect(getFileUrl(result.Url,task.BootFile) + "?token="+ result.Token)
}else{
ctx.Redirect(result.Url + "?token=" + result.Token)
}


ctx.Redirect(result.Url + "?token=" + result.Token)
}

func getFileUrl(url string,filename string) string{
middle:=""
if url[len(url)-3:]=="lab" || url[len(url)-4:]=="lab/" {
if url[len(url)-1] == '/' {
middle="tree/"
} else {
middle= "/tree/"
}
}else{
if url[len(url)-1] == '/' {
middle = "lab/tree/"
} else {
middle= "/lab/tree/"
}
}


return url+middle+path.Base(filename)
}

func NotebookRestart(ctx *context.Context) {
@@ -420,7 +446,8 @@ func NotebookRestart(ctx *context.Context) {
} else {
if count >= 1 {
log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
errorMsg = "you have already a running or waiting task, can not create more"
resultCode="2"
errorMsg = ctx.Tr("repo.cloudbrain.morethanonejob")
break
}
}
@@ -714,8 +741,7 @@ func trainJobNewDataPrepare(ctx *context.Context) error {
// return
//}

t := time.Now()
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName

attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID)
@@ -2351,8 +2377,7 @@ func inferenceJobNewDataPrepare(ctx *context.Context) error {
ctx.Data["PageIsCloudBrain"] = true
ctx.Data["newInference"] = true

t := time.Now()
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName

attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID)


+ 3
- 2
routers/routes/routes.go View File

@@ -359,6 +359,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/all/dosearch/", routers.SearchApi)
m.Post("/user/login/kanban", user.SignInPostAPI)
m.Get("/home/term", routers.HomeTerm)
m.Get("/home/notice", routers.HomeNoticeTmpl)
m.Get("/home/privacy", routers.HomePrivacy)
m.Get("/extension/tuomin/upload", modelapp.ProcessImageUI)
m.Post("/extension/tuomin/upload", reqSignIn, modelapp.ProcessImage)
@@ -1273,8 +1274,8 @@ func RegisterRoutes(m *macaron.Macaron) {

m.Group("/modelsafety", func() {
m.Group("/:id", func() {
m.Get("/show", reqRepoCloudBrainWriter, repo.GetAiSafetyTaskTmpl)
m.Get("", reqRepoCloudBrainWriter, repo.GetAiSafetyTask)
m.Get("/show", reqRepoCloudBrainReader, repo.GetAiSafetyTaskTmpl)
m.Get("", reqRepoCloudBrainReader, repo.GetAiSafetyTask)
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.StopAiSafetyTask)
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.DelAiSafetyTask)
})


+ 362
- 0
services/cloudbrain/cloudbrainTask/notebook.go View File

@@ -0,0 +1,362 @@
package cloudbrainTask

import (
"fmt"
"net/http"
"path"

"code.gitea.io/gitea/modules/modelarts"
"code.gitea.io/gitea/modules/modelarts_cd"

"code.gitea.io/gitea/modules/git"

"code.gitea.io/gitea/modules/cloudbrain"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/redis/redis_key"
"code.gitea.io/gitea/modules/redis/redis_lock"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/services/cloudbrain/resource"
"code.gitea.io/gitea/services/reward/point/account"

"code.gitea.io/gitea/modules/setting"
cloudbrainService "code.gitea.io/gitea/services/cloudbrain"
repo_service "code.gitea.io/gitea/services/repository"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
)

const NoteBookExtension = ".ipynb"

func FileNotebookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption) {

if ctx.Written() {
return
}

if path.Ext(option.File) != NoteBookExtension {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_select_wrong")))
return
}

isNotebookFileExist, _ := isNoteBookFileExist(ctx, option)
if !isNotebookFileExist {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist")))
return
}

sourceRepo, err := models.GetRepositoryByOwnerAndName(option.OwnerName, option.ProjectName)
if err != nil {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist")))
return
}

permission, err := models.GetUserRepoPermission(sourceRepo, ctx.User)
if err != nil {
log.Error("Get permission failed", err)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_no_right")))
return
}

if !permission.CanRead(models.UnitTypeCode) {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_no_right")))
return
}

//create repo if not exist
repo, err := models.GetRepositoryByName(ctx.User.ID, setting.FileNoteBook.ProjectName)
if repo == nil {
repo, err = repo_service.CreateRepository(ctx.User, ctx.User, models.CreateRepoOptions{
Name: setting.FileNoteBook.ProjectName,
Alias: "",
Description: "",
IssueLabels: "",
Gitignores: "",
License: "",
Readme: "Default",
IsPrivate: false,
AutoInit: true,
DefaultBranch: "master",
})
}
if err != nil {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.failed_to_create_notebook_repo",setting.FileNoteBook.ProjectName)))
return
}
if option.Type <= 1 {
cloudBrainFileNoteBookCreate(ctx, option, repo, sourceRepo)
} else {
modelartsFileNoteBookCreate(ctx, option, repo, sourceRepo)
}

}

func cloudBrainFileNoteBookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption, repo *models.Repository, sourceRepo *models.Repository) {

displayJobName := cloudbrainService.GetDisplayJobName(ctx.User.Name)
jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
jobType := string(models.JobTypeDebug)

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), jobType, displayJobName))
defer lock.UnLock()
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
return
}

tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName)
if err == nil {
if len(tasks) != 0 {
log.Error("the job name did already exist", ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
return
}
} else {
if !models.IsErrJobNotExist(err) {
log.Error("system error, %v", err, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error."))
return
}
}

count, err := GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType)
if err != nil {
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error."))
return
} else {
if count >= 1 {
log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
ctx.JSON(http.StatusOK,models.BaseMessageApi{
Code: 2,
Message: ctx.Tr("repo.cloudbrain.morethanonejob"),
})
return
}
}

errStr := uploadCodeFile(sourceRepo, getCodePath(jobName), option.BranchName, option.File, jobName)
if errStr != "" {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist")))
return
}
command := cloudbrain.GetCloudbrainDebugCommand()
specId := setting.FileNoteBook.SpecIdGPU
if option.Type == 0 {
specId = setting.FileNoteBook.SpecIdCPU
}
spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, models.FindSpecsOptions{
JobType: models.JobType(jobType),
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.wrong_specification")))
return
}

if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
return
}
ctx.Repo = &context.Repository{
Repository: repo,
}

req := cloudbrain.GenerateCloudBrainTaskReq{
Ctx: ctx,
DisplayJobName: displayJobName,
JobName: jobName,
Image: setting.FileNoteBook.ImageGPU,
Command: command,
Uuids: "",
DatasetNames: "",
DatasetInfos: nil,
CodePath: storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"),
ModelPath: storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"),
BenchmarkPath: storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"),
Snn4ImageNetPath: storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"),
BrainScorePath: storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"),
JobType: jobType,
Description: getDescription(option),
BranchName: option.BranchName,
BootFile: option.File,
Params: "{\"parameter\":[]}",
CommitID: "",
BenchmarkTypeID: 0,
BenchmarkChildTypeID: 0,
ResultPath: storage.GetMinioPath(jobName, cloudbrain.ResultPath+"/"),
Spec: spec,
}

jobId, err := cloudbrain.GenerateTask(req)
if err != nil {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(err.Error()))
return
}
ctx.JSON(http.StatusOK, models.BaseMessageApi{
Code: 0,
Message: jobId,
})

}

func getCodePath(jobName string) string {
return setting.JobPath + jobName + cloudbrain.CodeMountPath
}

func getDescription(option api.CreateFileNotebookJobOption) string {
return option.OwnerName + "/" + option.ProjectName + "/" + option.File
}

func modelartsFileNoteBookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption, repo *models.Repository, sourceRepo *models.Repository) {
displayJobName := cloudbrainService.GetDisplayJobName(ctx.User.Name)
jobName := util.ConvertDisplayJobNameToJobName(displayJobName)

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeDebug), displayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
return
}
defer lock.UnLock()

count, err := GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeDebug))

if err != nil {
log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"])

ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error."))
return
} else {
if count >= 1 {
log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
ctx.JSON(http.StatusOK,models.BaseMessageApi{
Code: 2,
Message: ctx.Tr("repo.cloudbrain.morethanonejob"),
})
return
}
}

tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeDebug), displayJobName)
if err == nil {
if len(tasks) != 0 {
log.Error("the job name did already exist", ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
return
}
} else {
if !models.IsErrJobNotExist(err) {
log.Error("system error, %v", err, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error."))
return
}
}

err = downloadCode(sourceRepo, getCodePath(jobName), option.BranchName)
if err != nil {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.load_code_failed")))
return
}

var aiCenterCode = models.AICenterOfCloudBrainTwo
var specId = setting.FileNoteBook.SpecIdNPU
if setting.ModelartsCD.Enabled {
aiCenterCode = models.AICenterOfChengdu
specId = setting.FileNoteBook.SpecIdNPUCD
}
spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, models.FindSpecsOptions{
JobType: models.JobTypeDebug,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: aiCenterCode})
if err != nil || spec == nil {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.wrong_specification")))
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
return
}
ctx.Repo = &context.Repository{
Repository: repo,
}

var jobId string
if setting.ModelartsCD.Enabled {
jobId, err = modelarts_cd.GenerateNotebook(ctx, displayJobName, jobName, "", getDescription(option), setting.FileNoteBook.ImageIdNPUCD, spec, option.File,modelarts.AutoStopDurationMs/4)
} else {
jobId, err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, "", getDescription(option), setting.FileNoteBook.ImageIdNPU, spec, option.File,modelarts.AutoStopDurationMs/4)
}

if err != nil {
log.Error("GenerateNotebook2 failed, %v", err, ctx.Data["MsgID"])

ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(err.Error()))

return
}

ctx.JSON(http.StatusOK, models.BaseMessageApi{
Code: 0,
Message: jobId,
})

}

func isNoteBookFileExist(ctx *context.Context, option api.CreateFileNotebookJobOption) (bool, error) {
repoPathOfNoteBook := models.RepoPath(option.OwnerName, option.ProjectName)

gitRepoOfNoteBook, err := git.OpenRepository(repoPathOfNoteBook)
if err != nil {
log.Error("RepoRef Invalid repo "+repoPathOfNoteBook, err.Error())
return false, err
}
// We opened it, we should close it
defer func() {
// If it's been set to nil then assume someone else has closed it.
if gitRepoOfNoteBook != nil {
gitRepoOfNoteBook.Close()
}
}()
fileExist, err := fileExists(gitRepoOfNoteBook, option.File, option.BranchName)
if err != nil || !fileExist {
log.Error("Get file error:", err, ctx.Data["MsgID"])

return false, err
}
return true, nil
}

func uploadCodeFile(repo *models.Repository, codePath string, branchName string, filePath string, jobName string) string {
err := downloadCode(repo, codePath, branchName)
if err != nil {
return "cloudbrain.load_code_failed"
}

err = uploadOneFileToMinio(codePath, filePath, jobName, cloudbrain.CodeMountPath+"/")
if err != nil {
return "cloudbrain.load_code_failed"
}
return ""
}

func fileExists(gitRepo *git.Repository, path string, branch string) (bool, error) {

commit, err := gitRepo.GetBranchCommit(branch)
if err != nil {
return false, err
}
if _, err := commit.GetTreeEntryByPath(path); err != nil {
return false, err
}
return true, nil
}

+ 16
- 7
services/cloudbrain/cloudbrainTask/sync_status.go View File

@@ -1,20 +1,21 @@
package cloudbrainTask

import (
"net/http"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/cloudbrain"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/setting"
"net/http"
"strconv"
)

var noteBookOKMap = make(map[int64]int, 20)
var noteBookFailMap = make(map[int64]int, 20)

//if a task notebook url can get two times, the notebook can browser.
//if a task notebook url can get successfulCount times, the notebook can browser.
const successfulCount = 3
const maxSuccessfulCount=10

func SyncCloudBrainOneStatus(task *models.Cloudbrain) (*models.Cloudbrain, error) {
jobResult, err := cloudbrain.GetJob(task.JobID)
@@ -62,21 +63,29 @@ func isNoteBookReady(task *models.Cloudbrain) bool {
return true
}
noteBookUrl := setting.DebugServerHost + "jpylab_" + task.JobID + "_" + task.SubTaskName
r := httplib.Get(noteBookUrl)
res, err := r.Response()
res,err := http.Get(noteBookUrl)
if err != nil {
return false
}
log.Info("notebook success count:"+strconv.Itoa(noteBookOKMap[task.ID])+",fail count:"+strconv.Itoa(noteBookFailMap[task.ID]))
if res.StatusCode == http.StatusOK {
count := noteBookOKMap[task.ID]
if count < successfulCount-1 {
if count==0{ //如果是第一次成功,把失败数重置为0
noteBookFailMap[task.ID]=0
}

if count < successfulCount-1 || (noteBookFailMap[task.ID]==0 && count < maxSuccessfulCount-1) {
noteBookOKMap[task.ID] = count + 1
return false
} else {
log.Info("notebook success count:"+strconv.Itoa(count)+",fail count:"+strconv.Itoa(noteBookFailMap[task.ID]))
delete(noteBookOKMap, task.ID)
delete(noteBookFailMap, task.ID)
return true
}

}else{
noteBookFailMap[task.ID]+=1
}
return false



+ 12
- 0
services/cloudbrain/cloudbrainTask/train.go View File

@@ -810,6 +810,18 @@ func uploadCodeToMinio(codePath, jobName, parentDir string) error {
return nil
}

func uploadOneFileToMinio(codePath, filePath, jobName, parentDir string) error {
destObject := setting.CBCodePathPrefix + jobName + parentDir + path.Base(filePath)
sourceFile := codePath + "/" + filePath
err := storage.Attachments.UploadObject(destObject, sourceFile)
if err != nil {
log.Error("UploadObject(%s) failed: %s", filePath, err.Error())
return err
}
return nil

}

func readDir(dirname string) ([]os.FileInfo, error) {
f, err := os.Open(dirname)
if err != nil {


+ 26
- 0
services/cloudbrain/util.go View File

@@ -1,7 +1,11 @@
package cloudbrain

import (
"regexp"
"strconv"
"strings"
"time"


"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
@@ -33,6 +37,28 @@ func GetAiCenterShow(aiCenter string, ctx *context.Context) string {

}

func GetDisplayJobName(username string) string {
t := time.Now()
return jobNamePrefixValid(cutString(username, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
}

func cutString(str string, lens int) string {
if len(str) < lens {
return str
}
return str[:lens]
}

func jobNamePrefixValid(s string) string {
lowStr := strings.ToLower(s)
re := regexp.MustCompile(`[^a-z0-9_\\-]+`)

removeSpecial := re.ReplaceAllString(lowStr, "")

re = regexp.MustCompile(`^[_\\-]+`)
return re.ReplaceAllString(removeSpecial, "")
}

func GetAiCenterInfoByCenterCode(aiCenterCode string) *setting.C2NetSequenceInfo {
if setting.AiCenterCodeAndNameMapInfo != nil {
if info, ok := setting.AiCenterCodeAndNameMapInfo[aiCenterCode]; ok {


+ 6
- 10
services/repository/repository.go View File

@@ -107,18 +107,13 @@ func GetRecommendCourseKeyWords() ([]string, error) {

}

func GetRecommendRepoFromPromote(filename string) ([]map[string]interface{}, error) {
func GetRecommendRepoFromPromote(repoMap []map[string]string) ([]map[string]interface{}, error) {
resultRepo := make([]map[string]interface{}, 0)
url := setting.RecommentRepoAddr + filename
result, err := RecommendFromPromote(url)

if err != nil {

return resultRepo, err
}

//resultRepo := make([]*models.Repository, 0)
for _, repoName := range result {
for _, record := range repoMap {
repoName := record["project_url"]
//log.Info("repoName=" + repoName + " tmpIndex1=" + fmt.Sprint(tmpIndex1) + " len(repoName)=" + fmt.Sprint(len(repoName)))
tmpIndex := strings.Index(repoName, "/")
if tmpIndex == -1 {
log.Info("error repo name format.")
@@ -131,7 +126,8 @@ func GetRecommendRepoFromPromote(filename string) ([]map[string]interface{}, err
repoMap["ID"] = fmt.Sprint(repo.ID)
repoMap["Name"] = repo.Name
repoMap["Alias"] = repo.Alias

repoMap["Label"] = record["class"]
repoMap["Label_en"] = record["class_en"]
repoMap["OwnerName"] = repo.OwnerName
repoMap["NumStars"] = repo.NumStars
repoMap["NumForks"] = repo.NumForks


+ 2
- 0
templates/admin/cloudbrain/list.tmpl View File

@@ -238,6 +238,7 @@
{{$.i18n.Tr "repo.debug"}}
</a>
{{else}}
{{if not .BootFile}}
<a id="ai-debug-{{$JobID}}"
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button'
data-jobid="{{$JobID}}"
@@ -245,6 +246,7 @@
{{$.i18n.Tr "repo.debug_again"}}
</a>
{{end}}
{{end}}
</form>
</div>
{{end}}


+ 45
- 5
templates/base/footer_content.tmpl View File

@@ -1,15 +1,17 @@
<footer>
<footer style="border-top:none;">
<div class="ui container">
<div class="ui grid">
<div class="sixteen wide mobile eight wide tablet eight wide computer column">
<div class="sixteen wide mobile wide tablet three wide computer column mobile-text-align-center">
<img style="width:166px;height:66px;margin-top:24px;" src="/img/logo-footer.svg" />
</div>
<div class="sixteen wide mobile wide tablet seven wide computer column" style="padding-left:20px;">
<div class="ui three column grid">
<div class="column ui vertical text menu">
<div class="header item">{{.i18n.Tr "custom.head.community"}}</div>
<a href="https://openi.org.cn/html/Club/2019/0227/14.html" class="item">{{.i18n.Tr "custom.foot.council"}}</a>
<a href="https://openi.org.cn/html/Club/2019/0227/14.html" class="item">{{.i18n.Tr "custom.foot.technical_committee"}}</a>
<a href="https://openi.org.cn/html/Club/2019/0228/17.html" class="item">{{.i18n.Tr "custom.foot.join"}}</a>
<a href="{{AppSubUrl}}/home/term/" class="item">{{.i18n.Tr "custom.foot.agreement"}}</a>
<a href="{{AppSubUrl}}/home/term/" class="item">{{.i18n.Tr "custom.foot.agreement"}}</a>
</div>
<div class="column ui vertical text menu">
<div class="header item">{{.i18n.Tr "custom.foot.news"}}</div>
@@ -61,7 +63,40 @@
</div>
</div>
</div>
<div class="sixteen wide mobile eight wide tablet eight wide computer column" style=" margin:2.0rem 0">
<style>
.contacts-qr-code-c {
margin:2.0rem 0;
display:flex !important;
justify-content:flex-end;
}
</style>
<div class="sixteen wide mobile wide tablet six wide computer column contacts-qr-code-c mobile-justify-content-center">
<div style="text-align:center;">
<div style="width:80px;height:80px;display:inline-block;
background-image: url('https://openi.pcl.ac.cn/zeizei/OpenI_Learning/raw/branch/master/img/official_account_mini.png');
background-repeat: no-repeat;
background-attachment: scroll;
background-position: -2px -2px;
background-size: 84px 84px;
background-color: transparent;"
></div>
<p style="margin-top:4px;color:rgb(16, 16, 16);">{{.i18n.Tr "custom.foot.openi_subscription_number"}}</p>
</div>
<div style="text-align:center;margin-left:40px;">
<div style="width:80px;height:80px;display:inline-block;
background-image: url('https://openi.pcl.ac.cn/zeizei/OpenI_Learning/raw/branch/master/img/wechatgroup.jpg');
background-repeat: no-repeat;
background-attachment: scroll;
background-position: -7px -25px;
background-size: 94px 117px;
background-color: transparent;"
></div>
<p style="margin-top:4px;color:rgb(16, 16, 16);">{{.i18n.Tr "custom.foot.user_communication_group"}}</p>
</div>
</div>
</div>
<div class="ui grid" style="margin-top:2rem;margin-bottom:2rem;border-top:1px solid #d6d6d6;">
<div class="sixteen wide mobile sixteen wide tablet wide computer column" style=" margin:1.0rem 0;text-align:center;">
{{.i18n.Tr "custom.foot.copyright"}} <a href="http://beian.miit.gov.cn/" target="_blank">京ICP备18004880号</a>
<br>
{{.i18n.Tr "home.powerdby"}}<a href="https://www.trustie.net/" target="_blank">Trustie确实</a>{{.i18n.Tr "、Gitea"}}
@@ -69,4 +104,9 @@
</div>
</div>
</div>
<div class="__go-top" style="display:none;z-index:100;width:44px;height:44px;bottom:50px;right:50px;background:rgba(16, 16, 16, 0.1);position:fixed;cursor:pointer;border-radius:5px;">
<div style="display:flex;align-items:center;justify-content:center;height:100%;">
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-16fsqc8-0 mHEdk svg-icon-path-icon fill" viewBox="0 0 32 32" width="30" height="30"><defs data-reactroot=""></defs><g><path fill="rgba(16, 16, 16, 0.6)" d="M17.333 10.437v16.229h-2.667v-16.229l-7.152 7.152-1.885-1.885 10.371-10.371 10.371 10.371-1.885 1.885-7.152-7.152z"></path></g></svg>
</div>
</div>
</footer>

+ 1
- 0
templates/base/head.tmpl View File

@@ -240,6 +240,7 @@ var _hmt = _hmt || [];
}
}
if (isShowNoticeTag){
if (!document.getElementById("notic_content")) return;
if(isNewNotice){
document.getElementById("notic_content").style.display='block'
}else{


+ 1
- 0
templates/base/head_home.tmpl View File

@@ -247,6 +247,7 @@ var _hmt = _hmt || [];
}
}
if (isShowNoticeTag){
if (!document.getElementById("notic_content")) return;
if(isNewNotice){
document.getElementById("notic_content").style.display='block'
}else{


+ 39
- 18
templates/base/head_navbar.tmpl View File

@@ -1,5 +1,5 @@
<div class="ui container" id="navbar">
<div class="item brand" style="justify-content: space-between;">
<div class="item brand" style="justify-content: space-between;height:62px;">
<a href="https://openi.org.cn/">
<img class="ui mini image" src="{{StaticUrlPrefix}}/img/logo-w.svg">
</a>
@@ -7,15 +7,18 @@
<i class="sidebar icon"></i>
</div>
</div>
<div style="width:1px;background:#606266;height:80%;margin:auto 0.5rem"></div>
<div class="item brand" style="margin-left: 0.9rem;">
<div class="item brand" style="padding-right:1.9rem">
<a href="/">
<img class="ui mini image" style="height: 1.3rem;" src="{{StaticUrlPrefix}}/img/git-logo.svg">
<!-- <img class="ui mini image" style="height: 1.3rem;" src="{{StaticUrlPrefix}}/img/git-logo.svg"> -->
<div>
<div style="display:flex">
<div style="line-height:24px;font-weight:700;font-size:24px;color:rgba(91,185,115,1);margin-right:2px;">AI</div>
<div style="line-height:24px;font-weight:700;font-size:21px;color:rgba(91,185,115,1);">协作平台</div>
</div>
<div style="font-weight:300;font-size:12px;color: rgba(254,221,89,1);font-style:normal;letter-spacing: 0.1px;line-height:17px;">Powered by C²NET</div>
</div>
</a>
</div>


{{if .IsSigned}}
<div class=" item edge">
<div class="dropdown-menu">
@@ -116,14 +119,14 @@
{{if .IsSigned}}
<div class="right stackable menu">
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post">
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;">
<div class="ui fluid action input" style="background:transparent ;border-radius: 5px;width: 200px;height:30px;border:rgb(233,233,233) solid 1px;">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..."
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;">
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:white;background:transparent;color:white;border: none;outline: none;">
<input type="hidden" name="tab" value="{{$.TabName}}">
<input type="hidden" name="sort" value="hot">
<button style="border: none;background-color: #363840;outline: none;border-radius:5px"><img type = "submit" style="width: 25px; height: 25px;margin: auto;" src="/img/search.svg" >
</button>
<!-- <button class="ui green button">{{.i18n.Tr "explore.search"}}</button> -->
<button style="border:none;background-color:transparent;outline:none;border-radius:5px;cursor:pointer;">
<img type="submit" style="width:21px;height:21px;margin:auto;vertical-align:bottom;" src="/img/search.svg" >
</button>
</div>
</form>
<a href="{{AppSubUrl}}/notifications" class="item poping up" data-content='{{.i18n.Tr "notifications"}}' data-variation="tiny inverted">
@@ -160,7 +163,7 @@
</div><!-- end dropdown menu create new -->

<div class="ui simple dropdown jump item poping up" tabindex="-1" data-content="{{.i18n.Tr "user_profile_and_more"}}" data-variation="tiny inverted">
<span class="text">
<span class="text" style="display:flex;align-items:center;">
<img class="ui tiny avatar image" width="24" height="24" src="{{.SignedUser.RelAvatarLink}}">
<span class="sr-only">{{.i18n.Tr "user_profile_and_more"}}</span>
<span class="mobile-only">{{.SignedUser.Name}}</span>
@@ -216,6 +219,13 @@
</a>
</div><!-- end content avatar menu -->
</div><!-- end dropdown avatar menu -->
<div class="ui simple item poping up" data-content="{{.i18n.Tr "help"}}" data-variation="tiny inverted">
<a target="_blank" href="{{AppSubUrl}}/docs/index.html">
<div style="display:flex;justify-content:center;align-items:center;font-size:10px;cursor:pointer;width:26px;height:26px;border-radius:100%;text-align:center;background: url(&quot;data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20version%3D%221.1%22%3E%3Cdefs%3E%3CradialGradient%20id%3D%221%22%20cx%3D%220%22%20cy%3D%220%22%20r%3D%221%22%20gradientTransform%3D%22matrix(0.7%2C%20-0.5250000000000001%2C%200.5250000000000001%2C%200.7%2C%200.283%2C%200.767)%22%3E%3Cstop%20stop-color%3D%22%2361d8dc%22%20stop-opacity%3D%221%22%20offset%3D%220%22%3E%3C%2Fstop%3E%3Cstop%20stop-color%3D%22%23498af9%22%20stop-opacity%3D%221%22%20offset%3D%220.63%22%3E%3C%2Fstop%3E%3Cstop%20stop-color%3D%22%23e840f7%22%20stop-opacity%3D%221%22%20offset%3D%221%22%3E%3C%2Fstop%3E%3C%2FradialGradient%3E%3C%2Fdefs%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22url(%231)%22%3E%3C%2Frect%3E%3C%2Fsvg%3E&quot;);">
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-16fsqc8-0 fPsHiw svg-icon-path-icon fill" viewBox="0 0 384 512" width="16" height="16"><defs data-reactroot=""></defs><g><path fill="rgb(255,255,255)" d="M202.021 0C122.202 0 70.503 32.703 29.914 91.026c-7.363 10.58-5.093 25.086 5.178 32.874l43.138 32.709c10.373 7.865 25.132 6.026 33.253-4.148 25.049-31.381 43.63-49.449 82.757-49.449 30.764 0 68.816 19.799 68.816 49.631 0 22.552-18.617 34.134-48.993 51.164-35.423 19.86-82.299 44.576-82.299 106.405V320c0 13.255 10.745 24 24 24h72.471c13.255 0 24-10.745 24-24v-5.773c0-42.86 125.268-44.645 125.268-160.627C377.504 66.256 286.902 0 202.021 0zM192 373.459c-38.196 0-69.271 31.075-69.271 69.271 0 38.195 31.075 69.27 69.271 69.27s69.271-31.075 69.271-69.271-31.075-69.27-69.271-69.27z"></path></g></svg>
</div>
</a>
</div>
</div><!-- end signed user right menu -->

{{else}}
@@ -224,14 +234,14 @@
<div class="right stackable menu">
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post">
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;">
<div class="ui fluid action input" style="background:transparent ;border-radius: 5px;width: 200px;height:30px;border:rgb(233,233,233) solid 1px;">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..."
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;">
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:white;background:transparent;color:white;border: none;outline: none;">
<input type="hidden" name="tab" value="{{$.TabName}}">
<input type="hidden" name="sort" value="hot">
<button style="border: none;background-color: #363840;outline: none;border-radius:5px"><img type = "submit" style="width: 25px; height: 25px;margin: auto;" src="/img/search.svg" >
</button>
<!-- <button class="ui green button">{{.i18n.Tr "explore.search"}}</button> -->
<button style="border:none;background-color:transparent;outline:none;border-radius:5px;cursor:pointer;">
<img type="submit" style="width:21px;height:21px;margin:auto;vertical-align:bottom;" src="/img/search.svg" >
</button>
</div>
</form>
{{if .ShowRegistrationButton}}
@@ -254,9 +264,20 @@
{{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}}
</a>
{{end}}

<div class="ui simple item poping up" data-content="{{.i18n.Tr "help"}}" data-variation="tiny inverted">
<a target="_blank" href="{{AppSubUrl}}/docs/index.html">
<div style="display:flex;justify-content:center;align-items:center;font-size:10px;cursor:pointer;width:26px;height:26px;border-radius:100%;text-align:center;background: url(&quot;data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20version%3D%221.1%22%3E%3Cdefs%3E%3CradialGradient%20id%3D%221%22%20cx%3D%220%22%20cy%3D%220%22%20r%3D%221%22%20gradientTransform%3D%22matrix(0.7%2C%20-0.5250000000000001%2C%200.5250000000000001%2C%200.7%2C%200.283%2C%200.767)%22%3E%3Cstop%20stop-color%3D%22%2361d8dc%22%20stop-opacity%3D%221%22%20offset%3D%220%22%3E%3C%2Fstop%3E%3Cstop%20stop-color%3D%22%23498af9%22%20stop-opacity%3D%221%22%20offset%3D%220.63%22%3E%3C%2Fstop%3E%3Cstop%20stop-color%3D%22%23e840f7%22%20stop-opacity%3D%221%22%20offset%3D%221%22%3E%3C%2Fstop%3E%3C%2FradialGradient%3E%3C%2Fdefs%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22url(%231)%22%3E%3C%2Frect%3E%3C%2Fsvg%3E&quot;);">
<svg xmlns="http://www.w3.org/2000/svg" class="styles__StyledSVGIconPathComponent-sc-16fsqc8-0 fPsHiw svg-icon-path-icon fill" viewBox="0 0 384 512" width="16" height="16"><defs data-reactroot=""></defs><g><path fill="rgb(255,255,255)" d="M202.021 0C122.202 0 70.503 32.703 29.914 91.026c-7.363 10.58-5.093 25.086 5.178 32.874l43.138 32.709c10.373 7.865 25.132 6.026 33.253-4.148 25.049-31.381 43.63-49.449 82.757-49.449 30.764 0 68.816 19.799 68.816 49.631 0 22.552-18.617 34.134-48.993 51.164-35.423 19.86-82.299 44.576-82.299 106.405V320c0 13.255 10.745 24 24 24h72.471c13.255 0 24-10.745 24-24v-5.773c0-42.86 125.268-44.645 125.268-160.627C377.504 66.256 286.902 0 202.021 0zM192 373.459c-38.196 0-69.271 31.075-69.271 69.271 0 38.195 31.075 69.27 69.271 69.27s69.271-31.075 69.271-69.271-31.075-69.27-69.271-69.27z"></path></g></svg>
</div>
</a>
</div>

</div><!-- end anonymous right menu -->

{{end}}



</div>


+ 1
- 1
templates/base/head_notice.tmpl View File

@@ -1,5 +1,5 @@
{{if not .IsCourse}}
{{ if .notices}}
{{ if (and .notices (not .PageIsHome)) }}
<div class="notic_content" id ="notic_content" style="display: block; position: relative">
<div class="ui container">
<marquee behavior="scroll" direction="left">


+ 36
- 0
templates/custom/home/home_activity.tmpl View File

@@ -0,0 +1,36 @@
<style>
.homeactivity {
padding-top: 5rem;
padding-bottom: 6rem;
overflow: hidden;
}
.homeactivity .card {
width: 360px !important;
height: 160px !important;
}
.homeactivity img {
width: 100% !important;
height: 100% !important;
}
.homeactivity .image-name {
font-size: 14px;
color: rgb(16, 16, 16);
text-align: center;
margin-top: 0.8em;
overflow: hidden;
text-overflow: ellipsis;
padding: 0 20px;
box-sizing: border-box;
white-space: nowrap;
}
</style>
<div class="ui container homeactivity _hm-container">
<div class="ui center homepro-tit am-mb-20">
<h2>{{.page_recommend_activity}}</h2>
<p><span class="ui text grey">{{.page_recommend_activity_desc}}</p>
</div>
<div class="event-list">
<div class="swiper-wrapper" id="recommendactivity"></div>
<div class="swiper-pagination"></div>
</div>
</div>

+ 85
- 0
templates/custom/home/home_dataset.tmpl View File

@@ -0,0 +1,85 @@
<style>
.homedataset {
padding-top: 4em;
padding-bottom: 4em;
}
.home-dataset-list {
position: relative;
z-index: 9;
padding: 0em 1em 3em;
overflow: hidden;
}
.home-dataset-list .swiper-slide {
padding-top: 5px;
}
.home-dataset-list .dataset-card {
height: 130px;
width: 130px;
border: 1px solid rgba(157, 197, 226, 0.4);
box-shadow: rgb(157 197 226 / 20%) 0px 5px 10px 0px;
color: rgb(16, 16, 16);
border-radius: 6px;
display:flex;
justify-content: center;
align-items: center;
flex-direction: column;
transition: all 0.1s;
}
.home-dataset-list .dataset-card:hover {
transform: translateY(-3px);
}
.home-dataset-list .dataset-card>div {
width:100%;
display: flex;
justify-content: center;
}
.home-dataset-list .dataset-card .content {
width:100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: center;
padding: 0 10px;
}
.home-dataset-list .dataset-card .icon-c {
font-size: 14px;
color: #101010;
display:flex;
justify-content: center;
align-items: center;
margin-bottom: 8px;
}
.home-dataset-list .dataset-card .label {
font-size: 14px;
color: #101010;
margin-bottom: 8px;
}
.home-dataset-list .dataset-card .svg.fill:not([stroke]) {
fill: url(#ila93em9ydx6bi61,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs);
}
.home-dataset-list .dataset-card .svg.fill:not([fill]) {
fill: url(#ila93em9ydx6bi61,1,rs,1,f000f000,f0rsf000,f000,00e6msqtrs,dw4hjuqlrs,ri00exmcrs);
}
.home-dataset-list .dataset-card .count {
font-size:12px;
color:rgb(136,136,136);
}
.home-dataset-list .swiper-pagination-bullet-active {
width: 40px;
border-radius: 4px;
}
</style>
<div class="ui container homedataset _hm-container">
<div class="ui stackable grid">
<div class="sixteen wide tablet four wide computer column mobile-text-align-center">
<h2>{{.i18n.Tr "home.search_dataset"}}</h2>
<p><span class="ui text grey">{{.i18n.Tr "home.datasets_descr"}}&nbsp;</span><a href="/explore/datasets">{{.i18n.Tr "home.search_dataset"}}</a></p>
</div>
<div class="sixteen wide tablet twelve wide computer column">
<div class="home-dataset-list">
<div class="swiper-wrapper" id="home_dataset"></div>
<div class="swiper-pagination"></div>
</div>
</div>
</div>
</div>

+ 20
- 0
templates/custom/home/home_org.tmpl View File

@@ -0,0 +1,20 @@
<style>

</style>
<div class="ui container homeorg _hm-container" style="max-width:1200px;">
<div class="ui stackable grid">
<div class="sixteen wide tablet sixteen wide computer column mobile-text-align-center" style="text-align:center;">
<h2>{{.page_recommend_org}}</h2>
<p><span class="ui text grey">{{.page_recommend_org_desc}}&nbsp;</span><a href="{{.RecommendURL}}">{{.page_recommend_org_commit}}</a>
{{.i18n.Tr "home.org_see"}}
<a href="{{AppSubUrl}}/explore/organizations" class="">{{.page_recommend_org_more}}</a>
</p>
</div>
<div class="sixteen wide tablet sixteen wide computer column">
<div class="homeorg-list">
<div class="swiper-wrapper" id="recommendorg"></div>
<div class="swiper-pagination"></div>
</div>
</div>
</div>
</div>

+ 21
- 0
templates/custom/home/home_repo.tmpl View File

@@ -0,0 +1,21 @@
<style>
.homepro-bg {
background: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20version%3D%221.1%22%3E%3Cdefs%3E%3ClinearGradient%20id%3D%221%22%20x1%3D%220%22%20x2%3D%221%22%20y1%3D%220%22%20y2%3D%220%22%20gradientTransform%3D%22matrix(0.013999999999999973%2C%201.0040000000000002%2C%20-0.1807553452932099%2C%200.013999999999999973%2C%200.374%2C%20-0.007)%22%3E%3Cstop%20stop-color%3D%22%23eee9da%22%20stop-opacity%3D%220.2%22%20offset%3D%220%22%3E%3C%2Fstop%3E%3Cstop%20stop-color%3D%22%23f3e7f7%22%20stop-opacity%3D%220.26%22%20offset%3D%220.29%22%3E%3C%2Fstop%3E%3Cstop%20stop-color%3D%22%23d0e7ff%22%20stop-opacity%3D%220.3%22%20offset%3D%221%22%3E%3C%2Fstop%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22url(%231)%22%3E%3C%2Frect%3E%3C%2Fsvg%3E");
}
</style>
<div class="homepro-bg">
<div class="ui container homepro _hm-container" style="padding-top:4rem;padding-bottom:3rem;">
<div class="ui stackable grid">
<div class="sixteen wide tablet four wide computer column mobile-text-align-center">
<h2>{{.page_recommend_repo}}</h2>
<p><span class="ui text grey">{{.page_recommend_repo_desc}}&nbsp;</span><a href="{{.RecommendURL}}">{{.page_recommend_repo_commit}}</a>&nbsp;<span class="ui text grey">{{.page_recommend_repo_go}}</span>&nbsp;<a href="{{AppSubUrl}}/explore/">{{.page_recommend_repo_more}}</a></p>
</div>
<div class="sixteen wide tablet twelve wide computer column">
<div class="homepro-list">
<div class="swiper-wrapper" id="recommendrepo"></div>
<div class="swiper-pagination"></div>
</div>
</div>
</div>
</div>
</div>

+ 1942
- 0
templates/custom/home/home_top.tmpl
File diff suppressed because it is too large
View File


+ 133
- 0
templates/custom/home/home_user_experience.tmpl View File

@@ -0,0 +1,133 @@
<style>
.homeuserexp-bg {
background: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20version%3D%221.1%22%3E%3Cdefs%3E%3ClinearGradient%20id%3D%221%22%20x1%3D%220%22%20x2%3D%221%22%20y1%3D%220%22%20y2%3D%220%22%20gradientTransform%3D%22matrix(0.04900000000000009%2C%201.104%2C%20-0.06118479166666667%2C%200.04900000000000009%2C%200.339%2C%20-0.107)%22%3E%3Cstop%20stop-color%3D%22%23ffffff%22%20stop-opacity%3D%220.33%22%20offset%3D%220%22%3E%3C%2Fstop%3E%3Cstop%20stop-color%3D%22%23e5e7eb%22%20stop-opacity%3D%220.3%22%20offset%3D%221%22%3E%3C%2Fstop%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22url(%231)%22%3E%3C%2Frect%3E%3C%2Fsvg%3E");
}
.homeuserexp {
padding-top: 5em;
padding-bottom: 2em;
}

.homeuserexp .swiper-prev {
position: absolute;
top: 104px;
left: 14px;
z-index: 10;
}

.homeuserexp .swiper-next {
position: absolute;
top: 104px;
right: 14px;
z-index: 10;
}
.homeuserexp .prev-next-i {
font-size: 22px;
border: 1px solid rgb(0, 122, 255);
border-radius: 100%;
color: rgb(0, 122, 255);
cursor: pointer;
}
.homeuserexp .swiper-prev.swiper-button-disabled .prev-next-i, .homeuserexp .swiper-next.swiper-button-disabled .prev-next-i {
opacity: 0.35;
cursor: default;
}

.home-user-exp-list {
position: relative;
z-index: 9;
padding: 0em 1.2em 3em 1.2em;
overflow: hidden;
}

.home-user-exp-list .user-card {
width: 240px;
height: 180px;
color: rgb(16, 16, 16);
border-radius: 6px;
display:flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.home-user-exp-list .swiper-slide {
display: flex;
justify-content: center;
}

.home-user-exp-list .user-card>div {
width:100%;
display: flex;
justify-content: center;
}

.home-user-exp-list .user-card .content {
width:100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: center;
padding: 0 10px;
}

.home-user-exp-list .user-card .img-c {
font-size: 14px;
color: #101010;
display:flex;
justify-content: center;
align-items: center;
height: 74px;
margin-bottom: 8px;
}

.home-user-exp-list .user-card .img {
border: 3px solid rgb(243, 240, 164);
border-radius: 100%;
box-shadow: rgb(255 220 144) 0px 0px 0px 2px;
height: 60px;
width: 60px;
display: block;
background-size:cover;
}

.home-user-exp-list .user-card .label {
font-size: 14px;
color: #101010;
margin-bottom: 8px;
font-weight: 550;
}

.home-user-exp-list .user-card .descr {
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
font-size:12px;
color:rgb(136,136,136);
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
max-height: 50px;
white-space: break-spaces;
}
</style>
<div class="homeuserexp-bg">
<div class="ui container homeuserexp _hm-container">
<div class="ui stackable grid">
<div class="sixteen wide tablet four wide computer column mobile-text-align-center">
<h2>{{.i18n.Tr "home.experience_officer"}}</h2>
<p><a href="https://openi.org.cn/index.php?m=content&c=index&a=lists&catid=220">{{.i18n.Tr "home.openi_experience_officer_plan"}}</a><span class="ui text grey">{{.i18n.Tr "home.more_benefits"}}</span></p>
</div>
<div class="sixteen wide tablet twelve wide computer column">
<div class="home-user-exp-list">
<div class="swiper-wrapper" id="home_user-exp"></div>
<div style="display:none;" class="swiper-button-prev"></div>
<div style="display:none;" class="swiper-button-next"></div>
</div>
<div class="swiper-prev"><i class="ri-arrow-left-line prev-next-i"></i></div>
<div class="swiper-next"><i class="ri-arrow-right-line prev-next-i"></i></div>
</div>
</div>
</div>
</div>

+ 1
- 3
templates/explore/repos.tmpl View File

@@ -1,9 +1,7 @@
{{template "base/head_pro" .}}
{{template "base/head_home" .}}
<div class="explore repositories">

{{template "explore/repo_search" .}}
{{template "explore/repo_orgtop" .}}
<div class="ui container">
<div class="ui grid">
{{template "explore/repo_left" .}}


+ 25
- 87
templates/home.tmpl View File

@@ -1,91 +1,25 @@
{{template "base/head_home" .}}
<div class="ui vertical masthead secondary hometop segment">
<div class="ui container" style="position: relative;">
<div class="ui center homebanner">
<h1 class="ui huge header">
{{.page_title}}
<div class="sub header">
{{.page_small_title}}
</div>
</h1>
<p class="ui am-lh-18">{{.page_description}}</p>
{{if .IsSigned}}
<a class="circular huge ui secondary button" href="{{AppSubUrl}}/dashboard">{{.page_use}} <i class="right arrow icon"></i></a>
{{else}}
<a class="circular huge ui secondary button" href="{{AppSubUrl}}/user/login">{{.page_use}} <i class="right arrow icon"></i></a>
{{end}}
</div>
<div class="bannerpic"><img class="ui fluid image" src="/img/gitopeni-index-01.svg"></div>
<div id="homenews">
<p>* {{.page_only_dynamic}}</p>
<div class="ui grid">
<div class="sixteen wide mobile twelve wide tablet ten wide computer column homenews">
<div class="newslist">
<div class="ui mini aligned list swiper-wrapper" id="newmessage">
</div>
</div>
</div>
</div>
</div><!-- end homenews -->
</div>
</div><!-- end segment -->
<div class="ui vertical masthead secondary hometop segment" style="background:transparent;margin-bottom:0">
{{template "custom/home/home_top" .}}
</div>

<!--组织-->
<div class="ui container homeorg">
<div class="ui stackable grid">
<div class="sixteen wide tablet four wide computer column homeorg-tit">
<h2>{{.page_recommend_org}}</h2>
<p><span class="ui text grey">{{.page_recommend_org_desc}}&nbsp;</span><a href="{{.RecommendURL}}">{{.page_recommend_org_commit}}</a></p>
<a href="{{AppSubUrl}}/explore/organizations" class="circular ui primary basic button">{{.page_recommend_org_more}} <i class="arrow circle right icon"></i></a>
</div>
<div class="sixteen wide tablet twelve wide computer column">
<div class="homeorg-list">
<div class="swiper-wrapper" id="recommendorg">
</div>
<div class="swiper-pagination"></div>
</div>
</div>
{{template "custom/home/home_org" .}}

<div class="sixteen wide tablet four wide computer column homeorg-tit">
<h2>{{.page_recommend_activity}}</h2>
<p><span class="ui text grey">{{.page_recommend_activity_desc}}</p>
</div>
<div class="sixteen wide tablet twelve wide computer column">
<div class="event-list">
<div class="swiper-wrapper" id="recommendactivity">
</div>
<div class="swiper-pagination"></div>
</div>
</div>
</div>
<div class="leftline01"></div>
</div>
<!--项目-->
<div class="ui container homepro">
<div class="leftline02"></div>
<div class="leftline02-2"></div>
<div class="ui center homepro-tit am-mb-20">
<h2>{{.page_recommend_repo}}</h2>
<p><span class="ui text grey">{{.page_recommend_repo_desc}}&nbsp;</span><a href="{{.RecommendURL}}">{{.page_recommend_repo_commit}}</a>{{.page_recommend_repo_go}}&nbsp;<a href="{{AppSubUrl}}/explore/">{{.page_recommend_repo_more}}</a></p>
</div>
<!-- 项目 -->
{{template "custom/home/home_repo" .}}

<div class="homepro-list">
<div class="swiper-wrapper" id="recommendrepo">
</div>
<div class="swiper-pagination"></div>
</div>
</div>
<!-- 数据集 -->
{{template "custom/home/home_dataset" .}}

<!-- 体验官 -->
{{template "custom/home/home_user_experience" .}}

<!-- 社区活动 -->
{{template "custom/home/home_activity" .}}

<!-- 中国算力网(C²NET) -->
<div class="ui vertical masthead secondary c2net segment">
<div class="ui container">
<div class="ui center am-pt-30 am-pb-30">
@@ -136,11 +70,11 @@
</div>
</div><!--rotation3D end-->
</div>
</div>
</div>

<!-- 协同开发环境 -->
<a name="fourth"></a>
<div class="ui container i-env">
<div class="ui container i-env _hm-container" style="padding-bottom:0rem;padding-top:4rem;">
<div class="ui center am-pb-30">
<h2>{{.page_dev_env}}</h2>
<p><span class="ui text grey">{{.page_dev_env_desc}}</p>
@@ -193,8 +127,10 @@
</div>
</div>

<!-- 启智AI协作平台 介绍 -->
<!--
<a name="fifth"></a>
<div class="ui container">
<div class="ui container _hm-container">
<div class="ui very padded inverted segment radius15">
<div class="ui stackable grid">
<div class="six wide column">
@@ -221,7 +157,9 @@
</div>
</div>
</div>
<div class="am-mt-30"></div>
-->

<!-- <div class="am-mt-30"></div> -->
<script src="/self/js/jquery.min.js" type="text/javascript"></script>
<script src="/home/home.js?v={{MD5 AppVer}}" type="text/javascript"></script>



+ 81
- 0
templates/notice.tmpl View File

@@ -0,0 +1,81 @@

{{template "base/head_home" .}}
<style>
.notice-container {
}
.notice-row {
display: flex;
justify-content: space-between;
align-items: center;
height: 52px;
border-bottom: 1px solid rgba(157, 197, 226, 0.2);
padding: 0 16px;
}
.notice-title {
flex: 1;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.notice-title a {
font-size: 16px;
color: rgb(16, 16, 16);
}
.notice-title a:hover {
opacity: 0.8;
}
.notice-time {
width: 150px;
text-align: right;
font-size: 14px;
color: rgba(16, 16, 16, 0.6);
}
</style>
<div class="ui container">
<h3 class="ui center am-pt-30 am-pb-20">{{.i18n.Tr "notice_announcement"}}</h3>
<div class="notice-container">
</div>
</div>
{{template "base/footer" .}}
<script>
;(function() {
var isZh = document.documentElement.getAttribute('lang') == 'zh-CN';
function getNotice() {
$.ajax({
type:"GET",
url:"/dashboard/invitation",
dataType:"json",
data: {
filename: 'notice/notice.json',
},
success:function(data){
if (!data) return;
try {
var noticeList = JSON.parse(data).Notices || [];
var noticeEl = $('.notice-container');
for (var i = 0, iLen = noticeList.length; i < iLen; i++) {
var noticeObj = noticeList[i];
noticeEl.append(`<div class="notice-row">
<div class="notice-title">
<a class="_hm-notice" href="${noticeObj.Link}">
<i class="ri-arrow-right-s-line" style="vertical-align:-2px;"></i>
<span>${isZh ? noticeObj.Title : (noticeObj.Title_en || noticeObj.Title)}</span>
</a>
</div>
<div class="notice-time">${noticeObj.Date || ''}</div>
</div>`);
}
} catch (e) {
console.info(e);
}
},
error:function(err) {
console.info(err);
}
});
}
getNotice();
})();
</script>

+ 8
- 2
templates/repo/debugjob/index.tmpl View File

@@ -221,7 +221,7 @@
<!--任务状态 -->
<span class="job-status" id="{{.Cloudbrain.ID}}"
data-repopath="{{$.RepoRelPath}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}"
data-jobid="{{.Cloudbrain.ID}}" data-resource="{{.ComputeResource}}">
data-jobid="{{.Cloudbrain.ID}}" data-resource="{{.ComputeResource}}" data-bootfile="{{.BootFile}}">
<span><i id="{{.Cloudbrain.ID}}-icon" style="vertical-align: middle;"
class="{{.Status}}"></i><span id="{{.Cloudbrain.ID}}-text"
style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
@@ -266,6 +266,7 @@
{{$.i18n.Tr "repo.debug"}}
</a>
{{else}}
{{if not .BootFile}}
<a id="ai-debug-{{.Cloudbrain.ID}}"
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button'
data-jobid="{{.Cloudbrain.ID}}"
@@ -274,6 +275,7 @@
{{$.i18n.Tr "repo.debug_again"}}
</a>
{{end}}
{{end}}
{{else}}
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}}
<a class="ui basic disabled button">
@@ -294,7 +296,9 @@
<a id="ai-stop-{{.Cloudbrain.ID}}"
class='ui basic ai_stop {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING" "SUCCEEDED" "CREATE_FAILED" "DELETED"}}disabled {{else}}blue {{end}}button'
data-repopath="{{$.RepoLink}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}/{{.Cloudbrain.ID}}/stop"
data-jobid="{{.Cloudbrain.ID}}">
data-jobid="{{.Cloudbrain.ID}}"
{{if .BootFile}}data-bootfile="{{.BootFile}}"{{end}}>
{{$.i18n.Tr "repo.stop"}}
</a>
{{else}}
@@ -322,6 +326,7 @@
{{end}}
</form>
</div>
{{if not .BootFile}}
<div class="ui compact buttons"
style="{{if eq .ComputeResource "CPU/GPU"}} visibility: visible {{else}} visibility: hidden{{end}}">
<div class="ui dropdown" id="model_more"
@@ -363,6 +368,7 @@
</div>
</div>
</div>
{{end}}
</div>
<!-- 镜像列表弹窗 -->



+ 4
- 4
templates/repo/header.tmpl View File

@@ -52,13 +52,13 @@
{{if not .IsBeingCreated}}
<div class="repo-buttons">
<div class="ui labeled button" tabindex="0">
<div class="ui compact basic button" onclick="$('.__watch_btn__').dropdown('show')">
<div style="position:relative;" class="ui compact basic button" onclick="$('.__watch_btn__').dropdown('show')">
<i class="icon fa-eye{{if not $.IsWatchingRepo}}-slash{{end}}"></i>{{if $.IsWatchingRepo}}{{$.i18n.Tr "repo.watched"}}{{else}}{{$.i18n.Tr "repo.notWatched"}}{{end}}
<i class="dropdown icon" style="margin:0 -8px 0 4px"></i>
<div class="ui dropdown floating __watch_btn__" onclick="event.stopPropagation();">
<div style="position:absolute;left:0;top:23px;" class="ui dropdown floating __watch_btn__" onclick="event.stopPropagation();">
<div class="text" style="display:none;"></div>
{{$WatchNotifyType := or $.WatchNotifyType 0}}
<div class="menu" style="margin-left:-64px;">
<div class="menu">
<div class="item {{if not $.IsWatchingRepo}}active selected{{end}}">
<form method="post" style="margin: 0;" action="{{$.RepoLink}}/action/unwatch?redirect_to={{$.Link}}">
{{$.CsrfTokenHtml}}
@@ -133,7 +133,7 @@
{{end}}
<div class="ui tabs container">
{{if not .Repository.IsBeingCreated}}
<div class="ui tabular menu navbar">
<div class="ui tabular menu navbar" style="overflow-x:auto;overflow-y:hidden">
{{if .Permission.CanRead $.UnitTypeCode}}
<div class="dropdown-menu">
<a class="{{if or .PageIsViewCode .PageIsReleaseList .PageIsWiki .PageIsActivity .PageIsViewCode}}active{{end}} item hover_active" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}">


+ 29
- 29
templates/repo/home.tmpl View File

@@ -99,6 +99,9 @@
animation-fill-mode: both;
}
</style>
{{if and (.IsViewFile) (IpynbBool .TreePath)}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-notebook-debug.css?v={{MD5 AppVer}}" />
{{end}}
<div class="repository file list">
{{template "repo/header" .}}
<div class="ui container">
@@ -154,7 +157,9 @@
{{.i18n.Tr "repo.archive.title"}}
</div>
{{end}}
{{if not .IsViewFile}}
{{template "repo/sub_menu" .}}
{{end}}
<div class="ui stackable secondary menu mobile--margin-between-items mobile--no-negative-margins">
{{template "repo/branch_dropdown" .}}
{{ $n := len .TreeNames}}
@@ -200,6 +205,7 @@
class="section"><a href="{{EscapePound $.BranchLink}}/{{EscapePound $p}}"
title="{{$v}}">{{EllipsisString $v 30}}</a></span>{{end}}{{end}}</span></div>
{{end}}
<div class="right fitted item" id="file-buttons">
<div class="ui tiny blue buttons">
{{if .Repository.CanEnableEditor}}
@@ -223,7 +229,6 @@
</a>
{{end}}
</div>

</div>
<div class="fitted item">
{{if eq $n 0}}
@@ -237,7 +242,6 @@
{{end}}
</div>
<div class="fitted item">

<!-- Only show clone panel in repository home page -->
{{if eq $n 0}}
<div class="ui action tiny input" id="clone-panel">
@@ -279,10 +283,22 @@
</div>
{{end}}
</div>
{{if and (.IsViewFile) (IpynbBool .TreePath)}}
<div class="right fitted item">
<button class="ui green button tiny" id="notebook-debug" style="display: flex;align-items: center;">
<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 3h18a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm1 2v14h16V5H4zm8 10h6v2h-6v-2zm-3.333-3L5.838 9.172l1.415-1.415L11.495 12l-4.242 4.243-1.415-1.415L8.667 12z" fill="rgba(255,255,255,1)"/></svg>
<span style="margin-left:0.3rem;font-size: 14px;">{{.i18n.Tr "repo.notebook_open"}}</span>
</button>
</div>
{{end}}
</div>
<div class="ui container">
<div class="ui mobile reversed stackable grid">
{{if not .IsViewFile}}
<div class="ui ten wide tablet twelve wide computer column">
{{else}}
<div class="ui sixteen wide tablet sixteen wide computer column">
{{end}}
{{if .IsViewFile}}
{{template "repo/view_file" .}}
{{else if .IsBlame}}
@@ -291,6 +307,7 @@
{{template "repo/view_list" .}}
{{end}}
</div>
{{if not .IsViewFile}}
<div class="ui six wide tablet four wide computer column">
<div id="repo-desc" data-IsAdmin="{{.Permission.IsAdmin}}"
data-IsArchived="{{.Repository.IsArchived}}">
@@ -303,25 +320,17 @@
{{else}}
<span class="no-description text-italic">{{.i18n.Tr "repo.no_desc"}}</span>
{{end}}

</p>

</div>



{{if .Repository.Website}}
<p class="ui">
<i class="gray linkify icon"></i>
<a class="link edit-link" target="_blank" title="{{.Repository.Website}}"
href="{{.Repository.Website}}">{{.Repository.Website}}</a>
</p>

{{end}}

<div class="ui" id="repo-topics" style="display: flex;position: relative;margin-bottom: 1.0rem;">
<i class="grey bookmark icon"></i>

<div id="repo-topics1" style="flex: 1;">
{{range .Topics}}
<a class="ui repo-topic small label topic"
@@ -334,32 +343,22 @@
</div>
<div id="topic_edit" class="vue_menu" style="display:none">
<div id="topic_edit1">

</div>
</div>

</div>


<p class="ui">
<i class="grey code icon"></i>
{{range .LanguageStats}}
{{.Language}}
{{end}}
</p>



{{if .LICENSE}}
<p class="ui">
<i class="grey clone icon"></i>
{{.LICENSE}}
</p>

{{end}}

<div class="ui divider"></div>

<div>
<h4 class="ui header">
{{$lenCon := len .ContributorInfo}}
@@ -387,19 +386,20 @@
{{end}}
</div>
</div>

</div>
{{end}}
</div>
</div>

</div>
{{if and (.IsViewFile) (IpynbBool .TreePath)}}
<div id="__vue-root"></div>
<div id="__vue-self-data" data-branch="{{.BranchName}}" data-owner="{{.Repository.OwnerName}}" data-name="{{.SignedUser.Name}}" data-project="{{.Repository.Name}}"
data-file="{{.TreePath}}">
</div>
{{end}}
</div>

<script type="text/javascript">
// $(document).ready(function(){
// $(".membersmore").click(function(){
// $("#contributorInfo > a:nth-child(n+25)").show();
// });
// });
</script>
{{if and (.IsViewFile) (IpynbBool .TreePath)}}
<script src="{{StaticUrlPrefix}}/js/vp-notebook-debug.js?v={{MD5 AppVer}}"></script>
{{end}}
{{template "base/footer" .}}

+ 3
- 1
templates/repo/modelsafety/new.tmpl View File

@@ -217,7 +217,9 @@
{{end}}
{{else}}
{{range .engine_versions}}
<option value="{{.ID}}">{{.Value}}</option>
{{if not (eq .ID -1)}}
<option value="{{.ID}}">{{.Value}}</option>
{{end}}
{{end}}
{{end}}
</select>


+ 15
- 4
templates/user/auth/activate.tmpl View File

@@ -23,7 +23,11 @@
{{else if .IsActivateFailed}}
<p>{{.i18n.Tr "auth.invalid_code"}}</p>
{{else}}
<p>{{.i18n.Tr "auth.has_unconfirmed_mail" .SignedUser.Name .SignedUser.Email | Str2html}}</p>
<p style="margin-bottom: 0;">{{.i18n.Tr "auth.has_unconfirmed_mail" .SignedUser.Name .SignedUser.Email | Str2html}}</p>
<ul style="margin-top: 0;">
<li style="line-height: 30px;">{{.i18n.Tr "auth.has_unconfirmed_mail_resend"}}</li>
<li>{{.i18n.Tr "auth.has_unconfirmed_mail_change"}}</li>
</ul>
<div class="ui divider"></div>
<div class="text right">
<button type="button" class="ui blue button change">{{.i18n.Tr "auth.change_email"}}</button>
@@ -40,14 +44,15 @@
<div class="header" style="padding: 1rem;background-color: rgba(240, 240, 240, 100);">
<h4>{{.i18n.Tr "auth.change_email_address"}}</h4>
</div>
<form id="formId" action="{{AppSubUrl}}/user/update_email" method="POST" class="ui form">
<form id="form-email" class="ui form ignore-dirty" action="{{AppSubUrl}}/user/update_email" method="POST" >
<div class="content content-padding">
<div class="ui error message">
</div>
{{$.CsrfTokenHtml}}
<div class="inline required field">
<label>{{.i18n.Tr "auth.new_email_address"}}</label>
<input style="width: 80%;" id="label" name="NewEmail" maxlength="255" value="{{.SignedUser.Email}}">
<input type="email" style="width: 80%;" id="label" name="NewEmail" maxlength="255" value="{{.SignedUser.Email}}"
pattern="([a-zA-Z0-9_-])+@(163\.com|126\.com|qq\.com|yahoo\.com|sina\.com|sina\.cn|outlook\.com|pcl\.ac\.cn|foxmail\.com|ict\.ac\.cn|21cn\.com|yeah\.net|139\.com)">
</div>
</div>
<div class="center actions">
@@ -61,6 +66,12 @@
{{template "base/footer" .}}
<script>
$('.ui.blue.button.change').on('click',function(){
$('.ui.modal').modal('show')
$('.ui.modal')
.modal({
onShow:function(){
$('.ui.dimmer').css({ "background-color": "rgb(136, 136, 136,0.7)" })
}
})
.modal('show')
})
</script>

+ 6
- 4
templates/user/dashboard/cloudbrains.tmpl View File

@@ -124,7 +124,8 @@
style="width: 8% !important;">
<span class="job-status" id="{{$JobID}}"
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "DEBUG"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts{{end}}/inference-job{{else if eq .JobType "TRAIN"}}{{if eq .ComputeResource "NPU"}}/modelarts/train-job{{else}}/cloudbrain/train-job{{end}}{{else if eq .JobType "BENCHMARK" "MODELSAFETY"}}/cloudbrain{{end}}'
data-jobid="{{$JobID}}" data-version="{{.VersionName}}">
data-jobid="{{$JobID}}" data-version="{{.VersionName}}"
data-bootfile="{{.BootFile}}">
<span><i id="{{$JobID}}-icon" style="vertical-align: middle;"
class="{{.Status}}"></i><span id="{{$JobID}}-text"
style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
@@ -185,7 +186,6 @@
<a href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}"
title="{{.Repo.OwnerName}}/{{.Repo.Alias}}">{{.Repo.OwnerName}}/{{.Repo.Alias}}</a>
</div>

<div class="three wide column text center nowrap" style="width: 15%!important;">
{{if eq .JobType "DEBUG"}}
<div class="ui compact buttons">
@@ -199,6 +199,7 @@
{{$.i18n.Tr "repo.debug"}}
</a>
{{else}}
{{if not .BootFile}}
<a id="ai-debug-{{$JobID}}"
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button'
data-jobid="{{$JobID}}"
@@ -206,6 +207,7 @@
{{$.i18n.Tr "repo.debug_again"}}
</a>
{{end}}
{{end}}
</form>
</div>
{{end}}
@@ -228,7 +230,7 @@
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}"
class='ui basic ai_stop {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED" "STOPPING" "CREATE_FAILED"}}disabled {{else}} blue {{end}}button'
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else if eq .JobType "BENCHMARK" }}/cloudbrain/benchmark{{else if eq .ComputeResource "NPU" }}/modelarts/notebook{{end}}/{{$JobID}}/stop'
data-jobid="{{$JobID}}">
data-jobid="{{$JobID}}" data-bootfile="{{.BootFile}}">
{{$.i18n.Tr "repo.stop"}}
</a>
</form>
@@ -236,7 +238,7 @@
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}"
class='ui basic ai_stop_version {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "STOPPED" "SUCCEEDED" "CREATE_FAILED"}}disabled {{else}} blue {{end}}button'
data-repopath='{{.Repo.OwnerName}}/{{.Repo.Name}}/{{if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 1}}modelarts/inference-job{{else}}cloudbrain/train-job{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}modelarts/train-job{{else if eq .Cloudbrain.Type 0}}cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}grampus/train-job{{end}}{{end}}'
data-jobid="{{$JobID}}" data-version="{{.VersionName}}">
data-jobid="{{$JobID}}" data-version="{{.VersionName}}" data-bootfile="{{.BootFile}}">
{{$.i18n.Tr "repo.stop"}}
</a>
{{end}}


+ 23
- 12
web_src/js/features/cloudrbanin.js View File

@@ -24,6 +24,7 @@ export default async function initCloudrain() {
const repoPath = job.dataset.repopath;
// const computeResource = job.dataset.resource
const versionname = job.dataset.version;
const bootfile = job.dataset.bootfile;
const status_text = $(`#${ID}-text`).text();
const finalState = [
"STOPPED",
@@ -99,11 +100,16 @@ export default async function initCloudrain() {
"SUCCEEDED",
].includes(status)
) {
$("#ai-debug-" + ID)
.removeClass("disabled")
.addClass("blue")
.text(debug_again_button)
.css("margin", "0");
if (!bootfile) {
$("#ai-debug-" + ID)
.removeClass("disabled")
.addClass("blue")
.text(debug_again_button)
.css("margin", "0");
} else {
$("#ai-debug-" + ID).remove()
}
}
if (["RUNNING", "WAITING"].includes(status)) {
$("#ai-stop-" + ID)
@@ -289,7 +295,7 @@ export default async function initCloudrain() {
assertDelete(this);
}
});
function stopDebug(ID, stopUrl) {
function stopDebug(ID, stopUrl,bootFile) {
$.ajax({
type: "POST",
url: stopUrl,
@@ -301,11 +307,15 @@ export default async function initCloudrain() {
.addClass(res.status);
$("#" + ID + "-text").text(res.status);
if (res.status === "STOPPED") {
$("#ai-debug-" + ID)
.removeClass("disabled")
.addClass("blue")
.text(debug_again_button)
.css("margin", "0");
if (!bootFile) {
$("#ai-debug-" + ID)
.removeClass("disabled")
.addClass("blue")
.text(debug_again_button)
.css("margin", "0");
} else {
$("#ai-debug-" + ID).remove()
}
$("#ai-image-" + ID)
.removeClass("blue")
.addClass("disabled");
@@ -344,7 +354,8 @@ export default async function initCloudrain() {
$(".ui.basic.ai_stop").click(function () {
const ID = this.dataset.jobid;
const repoPath = this.dataset.repopath;
stopDebug(ID, repoPath);
const bootFile = this.dataset.bootfile
stopDebug(ID, repoPath,bootFile);
});

function stopVersion(version_name, ID, repoPath) {


+ 4
- 0
web_src/js/features/i18nVue.js View File

@@ -108,6 +108,8 @@ export const i18nVue = {
local:"本地",
online:"线上",
modify:"修改",
about:"约",
count:"个",
},
US: {
computer_vision: "computer vision",
@@ -222,5 +224,7 @@ export const i18nVue = {
local:"Local",
online:"Online",
modify:"Modify",
about:"About",
count:"",
},
};

+ 19
- 1
web_src/js/index.js View File

@@ -5207,4 +5207,22 @@ Fancybox.bind('.gallery img', {
// Custom animations
showClass: "fancybox-zoomIn",
hideClass: "fancybox-zoomOut",
});
});

function initTopToHome() {
const topToHomeEl = $('.__go-top');
$(window).scroll(function (e) {
const scrollTop = $(document).scrollTop();
const winHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
if (scrollTop > winHeight * 1.2) {
topToHomeEl.fadeIn();
} else {
topToHomeEl.fadeOut();
}
});
topToHomeEl.on('click', function() {
$('html').animate({ scrollTop: 0 }, 'slow', 'swing');
});
}

initTopToHome();

+ 2
- 2
web_src/less/openi.less View File

@@ -34,7 +34,7 @@ a {
}

.following.bar.dark {
background-color: #363840;
background-color: rgb(16, 16, 16);
}
.ui.secondary.menu.dark .item {
color: #fff;
@@ -94,7 +94,7 @@ footer {
}
@media only screen and (min-width: 1600px) {
.ui.ui.ui.container:not(.fluid) {
width: 1200px;
width: 1440px;
}
}



+ 47
- 0
web_src/vuepages/apis/modules/notobook.js View File

@@ -0,0 +1,47 @@
import service from "../service";

// Notebook新建页面需要的信息
export const getFileNotebook = () => {
return service({
url: "/api/v1/file_notebook",
method: "get",
params: {},
});
};

// Notebook新建调试任务
// type, file, branch_name, owner_name, project_name
export const createNotebook = (data) => {
return service({
url: "/api/v1/file_notebook/create",
method: "post",
data,
params: {},
});
};

// Notebook获取云脑I调试任务状态
export const getCb1Notebook = (path,jobid) => {
return service({
url: `/api/v1/${path}/cloudbrain/${jobid}`,
method: "get",
params: {},
});
};

// Notebook获取云脑I调试任务状态
export const getCb2Notebook = (path,jobid) => {
return service({
url: `/api/v1/${path}/modelarts/notebook/${jobid}`,
method: "get",
params: {},
});
};

export const stopNotebook = (url) => {
return service({
url: url,
method: "post",
params: {},
});
};

+ 0
- 1
web_src/vuepages/apis/service.js View File

@@ -2,7 +2,6 @@ import axios from 'axios';

const service = axios.create({
baseURL: '/',
timeout: 20000,
});

service.interceptors.request.use((config) => {


+ 30
- 2
web_src/vuepages/langs/config/en-US.js View File

@@ -157,7 +157,7 @@ const en = {
computeCluster: 'Compute Cluster',
resourceSpecification: 'Resource Specification',
lastUpdateTime: 'Last Update Time',
resSceneDeleteConfirm: 'Are you sure to delete the current Resource Scene?',
resSceneDeleteConfirm: 'Are you sure to delete the current Resource Scene?',
resourceSpecificationIsAvailable: 'Specification Is Available',
resourceSpecificationIsAvailableAll: 'Specification Is Available(All)',
available: 'Available',
@@ -192,7 +192,35 @@ const en = {
dataDesensitizationModelExperience:'Data desensitization model experience',
dataDesensitizationModelDesc:'Use AI technology to desensitize the face and license plate number in the picture. For more information about this model, please visit the project',
limitFilesUpload:'Only jpg/jpeg/png files can be uploaded',
limitSizeUpload:'The size of the uploaded file cannot exceed 20M!',
limitSizeUpload: 'The size of the uploaded file cannot exceed 20M!',
notebook: {
createNewNotebook: "Create new notebook debug task",
sameTaskTips1: "You have created an",
sameTaskTips2: "equivalent task",
sameTaskTips3: "that is waiting or running, please wait for the task to finish before creating it.",
sameTaskTips4: "You can view all your Cloudbrain tasks in",
sameTaskTips5: "Home",
sameTaskTips6: "Cloudbrain Task",
sameTaskTips7: "",
cpuEnv: "CPU Environment",
gpuEnv: "GPU Environment",
npuEnv: "NPU environment",
newTask: "Create new task",
noQuene: "The current resources are sufficient and no tasks are queued",
queneTips1: "There are currently",
queneTips2: "tasks queued",
watiResource: "Waiting for resources to be allocated, please be patient",
debug: "Debug",
stop: "Stop",
stopping: "Stopping",
notebookRunning: "The debugging environment has been started, and it will automatically close after 4 hours ",
stopSuccess: "Stop task succeeded",
specification: "Specification",
graphicMemory: "Graphic Memory",
memory: "Memory",
sharedMemory: "Shared Memory",
tips: 'The newly created debugging task will be placed in the project openi-notebook under your name. If there is no such project, the system will automatically create a new one.'
},
modelManage: {
modelManage: 'Model management',
modelName: 'Model name',


+ 217
- 186
web_src/vuepages/langs/config/zh-CN.js View File

@@ -1,198 +1,227 @@
const zh = {
loading: '加载中...',
noData: '暂无数据',
date: '日期',
loading: "加载中...",
noData: "暂无数据",
date: "日期",

confirm: '确定',
cancel: '取消',
confirm1: '确认',
pleaseCompleteTheInformationFirst: '请先完善信息!',
submittedSuccessfully: '提交成功!',
submittedFailed: '提交失败!',
operation: '操作',
edit: '修改',
delete: '删除',
tips: '提示',
confirm: "确定",
cancel: "取消",
confirm1: "确认",
pleaseCompleteTheInformationFirst: "请先完善信息!",
submittedSuccessfully: "提交成功!",
submittedFailed: "提交失败!",
operation: "操作",
edit: "修改",
delete: "删除",
tips: "提示",

accomplishTask: '积分任务',
adminOperate: '管理员操作',
runCloudBrainTask: '运行云脑任务',
operating: '消耗中',
succeeded: '已完成',
debugTask: '调试任务',
trainTask: '训练任务',
inferenceTask: '推理任务',
benchmarkTask: '评测任务',
createPublicProject: '创建公开项目',
dailyPutforwardTasks: '每日提出任务',
dailyPR: '每日提出PR',
comment: '发表评论',
uploadDatasetFile: '上传数据集文件',
importNewModel: '导入新模型',
completeWechatCodeScanningVerification: '完成微信扫码验证',
dailyRunCloudbrainTasks: '每日运行云脑任务',
datasetRecommendedByThePlatform: '数据集被平台推荐',
submitNewPublicImage: '提交新公开镜像',
imageRecommendedByThePlatform: '镜像被平台推荐',
firstChangeofAvatar: '首次更换头像',
dailyCommit: '每日commit',
calcPointDetails: '算力积分明细',
calcPointAcquisitionInstructions: '积分获取说明',
CurrAvailableCalcPoints: '当前可用算力积分(分)',
totalGainCalcPoints: '总获取算力积分(分)',
totalConsumeCalcPoints: '总消耗算力积分(分)',
gainDetail: '获取明细',
consumeDetail: '消耗明细',
serialNumber: '流水号',
time: '时间',
scene: '场景',
behaviorOfPoint: '积分行为',
explanation: '说明',
points: '积分',
status: '状态',
runTime: '运行时长',
taskName: '任务名称',
accomplishTask: "积分任务",
adminOperate: "管理员操作",
runCloudBrainTask: "运行云脑任务",
operating: "消耗中",
succeeded: "已完成",
debugTask: "调试任务",
trainTask: "训练任务",
inferenceTask: "推理任务",
benchmarkTask: "评测任务",
createPublicProject: "创建公开项目",
dailyPutforwardTasks: "每日提出任务",
dailyPR: "每日提出PR",
comment: "发表评论",
uploadDatasetFile: "上传数据集文件",
importNewModel: "导入新模型",
completeWechatCodeScanningVerification: "完成微信扫码验证",
dailyRunCloudbrainTasks: "每日运行云脑任务",
datasetRecommendedByThePlatform: "数据集被平台推荐",
submitNewPublicImage: "提交新公开镜像",
imageRecommendedByThePlatform: "镜像被平台推荐",
firstChangeofAvatar: "首次更换头像",
dailyCommit: "每日commit",
calcPointDetails: "算力积分明细",
calcPointAcquisitionInstructions: "积分获取说明",
CurrAvailableCalcPoints: "当前可用算力积分(分)",
totalGainCalcPoints: "总获取算力积分(分)",
totalConsumeCalcPoints: "总消耗算力积分(分)",
gainDetail: "获取明细",
consumeDetail: "消耗明细",
serialNumber: "流水号",
time: "时间",
scene: "场景",
behaviorOfPoint: "积分行为",
explanation: "说明",
points: "积分",
status: "状态",
runTime: "运行时长",
taskName: "任务名称",

createdRepository: '创建了项目',
repositoryWasDel: '项目已删除',
openedIssue: '创建了任务',
createdPullRequest: '创建了合并请求',
commentedOnIssue: '评论了任务',
uploadDataset: '上传了数据集文件',
createdNewModel: '导入了新模型',
firstBindingWechatRewards: '首次绑定微信奖励',
created: '创建了',
type: '类型',
dataset: '数据集',
setAsRecommendedDataset: '被设置为推荐数据集',
committedImage: '提交了镜像',
image: '镜像',
setAsRecommendedImage: '被设置为推荐镜像',
updatedAvatar: '更新了头像',
pushedBranch: '推送了{branch}分支代码到',
deleteBranch: '从{repo}删除分支{branch}',
pushedTag: '推送了标签{tag}到',
deleteTag: '从{repo}删除了标签{tag}',
dailyMaxTips: '达到每日上限积分,不能拿满分',
memory: '内存',
sharedMemory: '共享内存',
';': ';',
createdRepository: "创建了项目",
repositoryWasDel: "项目已删除",
openedIssue: "创建了任务",
createdPullRequest: "创建了合并请求",
commentedOnIssue: "评论了任务",
uploadDataset: "上传了数据集文件",
createdNewModel: "导入了新模型",
firstBindingWechatRewards: "首次绑定微信奖励",
created: "创建了",
type: "类型",
dataset: "数据集",
setAsRecommendedDataset: "被设置为推荐数据集",
committedImage: "提交了镜像",
image: "镜像",
setAsRecommendedImage: "被设置为推荐镜像",
updatedAvatar: "更新了头像",
pushedBranch: "推送了{branch}分支代码到",
deleteBranch: "从{repo}删除分支{branch}",
pushedTag: "推送了标签{tag}到",
deleteTag: "从{repo}删除了标签{tag}",
dailyMaxTips: "达到每日上限积分,不能拿满分",
memory: "内存",
sharedMemory: "共享内存",
";": ";",

noPointGainRecord: '还没有积分获取记录',
noPointConsumeRecord: '还没有积分消耗记录',
noPointGainRecord: "还没有积分获取记录",
noPointConsumeRecord: "还没有积分消耗记录",

resourcesManagement: {
OpenI: '启智集群',
C2Net: '智算集群',
OpenIOne: '云脑一',
OpenITwo: '云脑二',
OpenIChengdu: '启智成都智算',
chengduCenter: '成都智算',
pclcci: '鹏城云计算所',
hefeiCenter: '合肥类脑类脑智能开放平台',
xuchangCenter: '中原人工智能计算中心',
willOnShelf: '待上架',
onShelf: '已上架',
offShelf: '已下架',
toOnShelf: '上架',
toOffShelf: '下架',
toSetPriceAndOnShelf: '定价上架',
status: '状态',
allStatus: '全部状态',
syncAiNetwork: '同步智算网络',
resQueue: '资源池(队列)',
allResQueue: '全部资源池(队列)',
addResQueue: '新建资源池(队列)',
addResQueueBtn: '新增资源池',
editResQueue: '修改资源池(队列)',
resQueueName: '资源池(队列)名称',
whichCluster: '所属集群',
allCluster: '全部集群',
aiCenter: '智算中心',
aiCenterID: '智算中心ID',
allAiCenter: '全部智算中心',
computeResource: '计算资源',
allComputeResource: '全部计算资源',
accCardType: '卡类型',
allAccCardType: '全部卡类型',
cardsTotalNum: '卡数',
accCardsNum: '卡数',
remark: '备注',
pleaseEnterRemark: '请输入备注(最大长度不超过255)',
pleaseEnterPositiveIntegerCardsTotalNum: '请输入正整数的卡数!',
addResSpecificationAndPriceInfo: '新增资源规格和单价信息',
addResSpecificationBtn: '新增资源规格',
editResSpecificationAndPriceInfo: '修改资源规格和单价信息',
resSpecificationAndPriceManagement: '资源规格单价管理',
sourceSpecCode: '对应资源编码',
sourceSpecCodeTips: '云脑II需要填写对应的资源编码',
sourceSpecId: '智算网络资源规格ID',
cpuNum: 'CPU数',
gpuMem: '显存',
mem: '内存',
shareMem: '共享内存',
unitPrice: '单价',
point_hr: '积分/时',
node: '节点',
free: '免费',
onShelfConfirm: '请确认上架该规格?',
offShelfConfirm: '请确认下架该规格?',
onShelfCode1001: '上架失败,资源池(队列)不可用。',
onShelfCode1003: '上架失败,资源规格不可用。',
offShelfDlgTip1: '当前资源规格已在以下场景中使用:',
offShelfDlgTip2: '请确认进行下架操作?',
resSceneManagement: '算力资源应用场景管理',
addResScene: '新建算力资源应用场景',
addResSceneBtn: '新增应用场景',
editResScene: '修改算力资源应用场景',
resSceneName: '应用场景名称',
jobType: '任务类型',
allJobType: '全部任务类型',
isExclusive: '是否专属',
allExclusiveAndCommonUse: '全部专属和通用',
exclusive: '专属',
commonUse: '通用',
exclusiveOrg: '专属组织',
exclusiveOrgTips: '多个组织名之间用英文分号隔开',
computeCluster: '算力集群',
resourceSpecification: '资源规格',
lastUpdateTime: '最后更新时间',
resSceneDeleteConfirm: '是否确认删除当前应用场景?',
resourceSpecificationIsAvailable: '资源规格是否可用',
resourceSpecificationIsAvailableAll: '资源规格是否可用(全部)',
available: '可用',
notAvailable: '不可用',
OpenI: "启智集群",
C2Net: "智算集群",
OpenIOne: "云脑一",
OpenITwo: "云脑二",
OpenIChengdu: "启智成都智算",
chengduCenter: "成都智算",
pclcci: "鹏城云计算所",
hefeiCenter: "合肥类脑类脑智能开放平台",
xuchangCenter: "中原人工智能计算中心",
willOnShelf: "待上架",
onShelf: "已上架",
offShelf: "已下架",
toOnShelf: "上架",
toOffShelf: "下架",
toSetPriceAndOnShelf: "定价上架",
status: "状态",
allStatus: "全部状态",
syncAiNetwork: "同步智算网络",
resQueue: "资源池(队列)",
allResQueue: "全部资源池(队列)",
addResQueue: "新建资源池(队列)",
addResQueueBtn: "新增资源池",
editResQueue: "修改资源池(队列)",
resQueueName: "资源池(队列)名称",
whichCluster: "所属集群",
allCluster: "全部集群",
aiCenter: "智算中心",
aiCenterID: "智算中心ID",
allAiCenter: "全部智算中心",
computeResource: "计算资源",
allComputeResource: "全部计算资源",
accCardType: "卡类型",
allAccCardType: "全部卡类型",
cardsTotalNum: "卡数",
accCardsNum: "卡数",
remark: "备注",
pleaseEnterRemark: "请输入备注(最大长度不超过255)",
pleaseEnterPositiveIntegerCardsTotalNum: "请输入正整数的卡数!",
addResSpecificationAndPriceInfo: "新增资源规格和单价信息",
addResSpecificationBtn: "新增资源规格",
editResSpecificationAndPriceInfo: "修改资源规格和单价信息",
resSpecificationAndPriceManagement: "资源规格单价管理",
sourceSpecCode: "对应资源编码",
sourceSpecCodeTips: "云脑II需要填写对应的资源编码",
sourceSpecId: "智算网络资源规格ID",
cpuNum: "CPU数",
gpuMem: "显存",
mem: "内存",
shareMem: "共享内存",
unitPrice: "单价",
point_hr: "积分/时",
node: "节点",
free: "免费",
onShelfConfirm: "请确认上架该规格?",
offShelfConfirm: "请确认下架该规格?",
onShelfCode1001: "上架失败,资源池(队列)不可用。",
onShelfCode1003: "上架失败,资源规格不可用。",
offShelfDlgTip1: "当前资源规格已在以下场景中使用:",
offShelfDlgTip2: "请确认进行下架操作?",
resSceneManagement: "算力资源应用场景管理",
addResScene: "新建算力资源应用场景",
addResSceneBtn: "新增应用场景",
editResScene: "修改算力资源应用场景",
resSceneName: "应用场景名称",
jobType: "任务类型",
allJobType: "全部任务类型",
isExclusive: "是否专属",
allExclusiveAndCommonUse: "全部专属和通用",
exclusive: "专属",
commonUse: "通用",
exclusiveOrg: "专属组织",
exclusiveOrgTips: "多个组织名之间用英文分号隔开",
computeCluster: "算力集群",
resourceSpecification: "资源规格",
lastUpdateTime: "最后更新时间",
resSceneDeleteConfirm: "是否确认删除当前应用场景?",
resourceSpecificationIsAvailable: "资源规格是否可用",
resourceSpecificationIsAvailableAll: "资源规格是否可用(全部)",
available: "可用",
notAvailable: "不可用",
},
user: {
inviteFriends: '邀请好友',
inviteFriendsTips: '复制二维码或者注册邀请链接分享给好友',
clickToViewTheEventDetails: '点击查看活动详情',
copyRegistrationInvitationLink: '复制注册邀请链接',
registrationAdress: '注册地址:',
recommender: '推荐人:',
invitedFriends: '已邀请好友',
registrationTime: '注册时间',
theSharedContentHasBeenCopiedToTheClipboard: '分享内容已复制到剪切板',
copyError: '复制错误',
Activated: '已激活',
notActive: '未激活',
inviteFriends: "邀请好友",
inviteFriendsTips: "复制二维码或者注册邀请链接分享给好友",
clickToViewTheEventDetails: "点击查看活动详情",
copyRegistrationInvitationLink: "复制注册邀请链接",
registrationAdress: "注册地址:",
recommender: "推荐人:",
invitedFriends: "已邀请好友",
registrationTime: "注册时间",
theSharedContentHasBeenCopiedToTheClipboard: "分享内容已复制到剪切板",
copyError: "复制错误",
Activated: "已激活",
notActive: "未激活",
},
tranformImageFailed: "图片脱敏失败",
originPicture: "原始图片",
desensitizationPicture: "脱敏图片",
desensitizationObject: "脱敏对象",
example: "示例",
startDesensitization: "开始处理",
all: "全部",
onlyFace: "仅人脸",
onlyLicensePlate: "仅车牌",
dragThePictureHere: "拖动图片到这里",
or: "或",
clickUpload: "点击上传",
dataDesensitizationModelExperience: "数据脱敏模型体验",
dataDesensitizationModelDesc:
"利用人工智能AI技术,把图片中的人脸、车牌号码进行脱敏处理。该模型更多信息请访问项目",
limitFilesUpload: "只能上传 jpg/jpeg/png 格式的文件",
limitSizeUpload: "上传文件大小不能超过 20M !",
notebook: {
createNewNotebook: "新建Notebook调试任务",
sameTaskTips1: "您已经有",
sameTaskTips2: "同类任务",
sameTaskTips3: "正在等待或运行中,请等待任务结束再创建",
sameTaskTips4: "可以在",
sameTaskTips5: "个人中心",
sameTaskTips6: "云脑任务",
sameTaskTips7: "查看您所有的云脑任务。",
cpuEnv: "CPU 环境",
gpuEnv: "GPU 环境",
npuEnv: "NPU 环境",
newTask: "新建任务",
noQuene: "当前资源充足,没有任务排队",
queneTips1: "当前有",
queneTips2: "个任务正在排队",
watiResource: "正在等待分配资源,请耐心等待",
debug: "调试",
stop: "停止",
stopping: "停止中",
notebookRunning: "调试环境已启动,单次连接 4 小时后自动关闭",
stopSuccess: "停止任务成功",
specification: "规格",
graphicMemory: "显存",
memory: "内存",
sharedMemory: "共享内存",
tips:'本次新建的调试任务会放在您名下项目openi-notebook中,如果没有该项目系统会自动新建一个。'
},
tranformImageFailed:'图片脱敏失败',
originPicture:'原始图片',
desensitizationPicture:'脱敏图片',
desensitizationObject:'脱敏对象',
example:'示例',
startDesensitization:'开始处理',
all:'全部',
onlyFace:'仅人脸',
onlyLicensePlate:'仅车牌',
dragThePictureHere:'拖动图片到这里',
or:'或',
clickUpload:'点击上传',
dataDesensitizationModelExperience:'数据脱敏模型体验',
dataDesensitizationModelDesc:'利用人工智能AI技术,把图片中的人脸、车牌号码进行脱敏处理。该模型更多信息请访问项目',
limitFilesUpload:'只能上传 jpg/jpeg/png 格式的文件',
limitSizeUpload:'上传文件大小不能超过 20M !',
modelManage: {
modelManage: '模型管理',
modelName: '模型名称',
@@ -254,6 +283,8 @@ const zh = {
deleteModelFileConfirmTips: '请确认是否删除当前模型文件?',
modelFileDeleteFailed: '模型文件删除失败',
},
}
};



export default zh;

+ 1
- 1
web_src/vuepages/pages/modelmanage/common/modelmanage-common-detail.vue View File

@@ -339,7 +339,7 @@ export default {
bootFile: trainTaskInfo.BootFile,
datasetName: trainTaskInfo.DatasetName,
parameters: parametersStr || '--',
workServerNumber: trainTaskInfo.WorkServerNumber || '--',
workServerNumber: trainTaskInfo.WorkServerNumber || '1',
specStr: sepcStr || '--',
});
}


+ 662
- 0
web_src/vuepages/pages/notebook/debug/index.vue View File

@@ -0,0 +1,662 @@
<template>
<div>
<el-dialog
:title="$t('notebook.createNewNotebook')"
:visible.sync="dialogVisible"
width="50%"
:close-on-click-modal="false"
@closed="handleClose"
>
<div class="wrapper" v-loading="loading" element-loading-spinner="el-icon-loading">
<div style="text-align: center;padding-bottom: 12px;">
<span class="text-tip">{{$t('notebook.tips')}}</span>
</div>
<div v-show="alertCb" class="ui message alert-info">
<div style="display: flex;align-items: center;">
<i class="ri-information-line" style="font-size: 35px;color: rgba(242, 113, 28, 1);;"></i>
<div style="text-align: left;margin-left: 1rem;">
<div style="font-weight: 600;line-height: 2;">{{$t('notebook.sameTaskTips1')}} <span style="color:rgba(242, 113, 28, 1);">{{$t('notebook.sameTaskTips2')}}</span> {{$t('notebook.sameTaskTips3')}}</div>
<div style="color:#939393">{{$t('notebook.sameTaskTips4')}} “<a href="/cloudbrains" target="_blank">{{$t('notebook.sameTaskTips5')}} &gt; {{$t('notebook.sameTaskTips6')}}</a>” {{$t('notebook.sameTaskTips7')}}</div>
</div>
</div>
</div>
<div
class="three-resource-type"
:class="{ active: selectIndex == 0 }"
@click="selectResource(0)"
>
<div class="resource-child-node">
<div class="resource-type-icon background-C">
<span class="text">C</span>
</div>
<div class="resource-type-detail">
<div class="detail-title"><span>{{$t('notebook.cpuEnv')}}</span></div>
<div class="detail-spec">
<span>{{cpuSpec}}</span>
</div>
<div class="detail-spec">
<span>{{$t('image')}}:{{notebookInfo.imageCpuDescription}}</span>
</div>
</div>
<div class="resource-select">
<i v-if="selectIndex===0" :class="{'slide-in-bottom': !slideActive && !initSelect }" class="ri-checkbox-circle-line green"></i>
<i
class="ri-checkbox-blank-circle-line gray"
:class="{'fade-out':selectIndex===0}"
></i>
</div>
</div>
</div>
<div
class="three-resource-type"
:class="{ active: selectIndex == 2 }"
@click="selectResource(2)"
>
<div class="resource-child-node">
<div class="resource-type-icon background-N">
<span class="text">N</span>
</div>
<div class="resource-type-detail">
<div class="detail-title"><span>{{$t('notebook.npuEnv')}}</span></div>
<div class="detail-spec">
<span>{{npuSpec}}</span>
</div>
<div class="detail-spec">
<span>{{$t('image')}}:{{notebookInfo.imageNpuDescription}}</span>
</div>
</div>
<div class="resource-select">
<i v-if="selectIndex===2" :class="[slideActive && !initSelect ?'slide-in-top':'slide-in-bottom']" class="ri-checkbox-circle-line green"></i>
<i
class="ri-checkbox-blank-circle-line gray"
:class="{'fade-out':selectIndex===2}"
></i>
</div>
</div>
</div>
<div
class="three-resource-type"
:class="{ active: selectIndex == 1 }"
@click="selectResource(1)"
>
<div class="resource-child-node">
<div class="resource-type-icon background-G">
<span class="text">G</span>
</div>
<div class="resource-type-detail">
<div class="detail-title"><span>{{$t('notebook.gpuEnv')}}</span></div>
<div class="detail-spec">
<span>{{gpuSpec}}</span>
</div>
<div class="detail-spec">
<span>{{$t('image')}}:{{notebookInfo.imageGpuDescription}}</span>
</div>
</div>
<div class="resource-select">
<i v-if="selectIndex===1 && !initSelect" :class="{'slide-in-top': slideActive && !initSelect}" class="ri-checkbox-circle-line green"></i>
<i v-if="selectIndex===1 && initSelect" class="ri-checkbox-circle-line green"></i>
<i
class="ri-checkbox-blank-circle-line gray"
:class="{'fade-out':selectIndex===1}"
></i>
</div>
</div>
</div>
<div class="resource-footer">
<div class="resource-operate" v-if="selectIndex==0">
<div v-if="btnStatus[0]===0">
<button class="ui green small button" @click="createTask(0)"></i>{{$t('notebook.newTask')}}</button>
<span v-if="notebookInfo.waitCountGpu==0" class="text">{{$t('notebook.noQuene')}}</span>
<span v-else class="text">{{$t('notebook.queneTips1')}} <span style="color: red;">{{notebookInfo.waitCountGpu}}</span> {{$t('notebook.queneTips2')}}</span>
</div>
<div v-else-if="btnStatus[0]===1">
<button class="ui disabled small button" style="background-color: #888;"><i class="loading spinner icon" style="color: #fff;"></i>{{$t('notebook.newTask')}}</button>
<span class="text">{{$t('notebook.watiResource')}}</span>
</div>
<div v-else-if="btnStatus[0]===2">
<button class="ui small button" style="background-color: #1684fc;">
<a style="color:#fff" :href="deubgUrlGpu" target="_blank">{{$t('notebook.debug')}}</a>
</button>
<button class="ui small button" @click="stopDebug(0)">{{$t('notebook.stop')}}</button>
<span class="text">{{$t('notebook.notebookRunning')}}</span>
</div>
<div v-else>
<button class="ui disabled small button" style="background-color: #888;"><i class="loading spinner icon" style="color: #fff;"></i>{{$t('notebook.stopping')}}</button>
</div>
</div>
<div class="resource-operate" v-if="selectIndex==2">
<div v-if="btnStatus[2]===0">
<button class="ui green small button" @click="createTask(2)"></i>{{$t('notebook.newTask')}}</button>
<span v-if="notebookInfo.waitCountNpu==0" class="text">{{$t('notebook.noQuene')}}</span>
<span v-else class="text">{{$t('notebook.queneTips1')}} <span style="color: red;">{{notebookInfo.waitCountNpu}}</span> {{$t('notebook.queneTips2')}}</span>
</div>
<div v-else-if="btnStatus[2]===1">
<button class="ui disabled small button" style="background-color: #888;"><i class="loading spinner icon" style="color: #fff;"></i>{{$t('notebook.newTask')}}</button>
<span class="text">{{$t('notebook.watiResource')}}</span>
</div>
<div v-else-if="btnStatus[2]===2">
<button class="ui small button" style="background-color: #1684fc;">
<a style="color:#fff" :href="deubgUrlNpu" target="_blank">{{$t('notebook.debug')}}</a>
</button>
<button class="ui small button" @click="stopDebug(2)">{{$t('notebook.stop')}}</button>
<span class="text">{{$t('notebook.notebookRunning')}}</span>
</div>
<div v-else>
<button class="ui disabled small button" style="background-color: #888;"><i class="loading spinner icon" style="color: #fff;"></i>{{$t('notebook.stopping')}}</button>
</div>
</div>
<div class="resource-operate" v-if="selectIndex==1">
<div v-if="btnStatus[1]===0">
<button class="ui green small button" @click="createTask(1)"></i>{{$t('notebook.newTask')}}</button>
<span v-if="notebookInfo.waitCountGpu==0" class="text">{{$t('notebook.noQuene')}}</span>
<span v-else class="text">{{$t('notebook.queneTips1')}} <span style="color: red;">{{notebookInfo.waitCountGpu}}</span> {{$t('notebook.queneTips2')}}</span>
</div>
<div v-else-if="btnStatus[1]===1">
<button class="ui disabled small button" style="background-color: #888;"><i class="loading spinner icon" style="color: #fff;"></i>{{$t('notebook.newTask')}}</button>
<span class="text">{{$t('notebook.watiResource')}}</span>
</div>
<div v-else-if="btnStatus[1]===2">
<button class="ui small button" style="background-color: #1684fc;">
<a style="color:#fff" :href="deubgUrlGpu" target="_blank">{{$t('notebook.debug')}}</a>
</button>
<button class="ui small button" @click="stopDebug(1)">{{$t('notebook.stop')}}</button>
<span class="text">{{$t('notebook.notebookRunning')}}</span>
</div>
<div v-else>
<button class="ui disabled small button" style="background-color: #888;"><i class="loading spinner icon" style="color: #fff;"></i>{{$t('notebook.stopping')}}</button>
</div>
</div>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import { getFileNotebook,createNotebook,getCb1Notebook,getCb2Notebook,stopNotebook } from "~/apis/modules/notobook";
import { Message } from "element-ui";
let timerCb1,timerCb2
let {AppSubUrl} = window.config
const finalState = [
"STOPPED",
"CREATE_FAILED",
"UNAVAILABLE",
"DELETED",
"RESIZE_FAILED",
"SUCCEEDED",
"IMAGE_FAILED",
"SUBMIT_FAILED",
"DELETE_FAILED",
"KILLED",
"COMPLETED",
"FAILED",
"CANCELED",
"LOST",
"START_FAILED",
"SUBMIT_MODEL_FAILED",
"DEPLOY_SERVICE_FAILED",
"CHECK_FAILED",
"STOPPING"
];
export default {
data() {
return {
dialogVisible: false,
selectIndex: 0,
slideActive:true,
initSelect:true,
notebookInfo:{specCpu:{acc_cards_num:0},specGpu:{acc_cards_num:0},specNpu:{acc_cards_num:0}},
fileInfo:{
file:'',
branch_name:'',
owner_name:'',
project_name:'',
sign_name:''
},
btnStatus:{0:0,1:0,2:0},
alertCb:false,
deubgUrlNpu:'',
deubgUrlGpu:'',
deubgUrlNpuStop:'',
deubgUrlGpuStop:'',
loading:false,
activeLoadFirst:true
};
},
methods: {
handleClose(done) {
this.initSelect = true
this.alertCb = false
},
selectResource(index) {
this.getNotebookInfo()
if(index==this.selectIndex){
return
}
if(index>this.selectIndex && this.selectIndex!==1){
this.slideActive = true
}else if(index<this.selectIndex && index==1){
this.slideActive = true
}else{
this.slideActive = false
}
this.selectIndex = index;
this.initSelect = false
this.alertCb = false
},
getNotebookInfo(){
if(this.activeLoadFirst){
this.loading = true
}
getFileNotebook().then((res)=>{
if(res.data.code==0){
this.notebookInfo = res.data
}else{
Message.error(res.data.message)
}
this.loading = false
this.activeLoadFirst = false
}).catch((err)=>{
Message.error(err)
this.loading = false
this.activeLoadFirst = false
})
},
getCb1NotebookInfo(path,id,index){
getCb1Notebook(path,id).then((res)=>{
if(res.status===200){
if(res.data.JobStatus==="RUNNING"){
this.btnStatus[index]=2
this.deubgUrlGpu = `${AppSubUrl}/${this.fileInfo.sign_name}/${this.notebookInfo.projectName}/cloudbrain/${id}/debug`
this.deubgUrlGpuStop = `${AppSubUrl}/${this.fileInfo.sign_name}/${this.notebookInfo.projectName}/cloudbrain/${id}/stop`
clearInterval(timerCb1)
}
if(finalState.includes(res.data.JobStatus)){
this.btnStatus[index] = 0
clearInterval(timerCb1)
}
}
})
},
getCb2NotebookInfo(path,id){
getCb2Notebook(path,id).then((res)=>{
if(res.status===200){
if(res.data.JobStatus==="RUNNING"){
this.btnStatus[2]=2
this.deubgUrlNpu = `${AppSubUrl}/${this.fileInfo.sign_name}/${this.notebookInfo.projectName}/modelarts/notebook/${id}/debug`
this.deubgUrlNpuStop = `${AppSubUrl}/${this.fileInfo.sign_name}/${this.notebookInfo.projectName}/modelarts/notebook/${id}/stop`
clearInterval(timerCb2)
}
if(finalState.includes(res.data.JobStatus)){
this.btnStatus[2] = 0
clearInterval(timerCb2)
}
}
})
},
stopDebug(index){
this.btnStatus[index]=3
let url = index===2 ? this.deubgUrlNpuStop :this.deubgUrlGpuStop
stopNotebook(url).then((res)=>{
if(res.data.result_code==='0'){
this.btnStatus[index]=0
Message.success(this.$t("notebook.stopSuccess"))
}else{
this.btnStatus[index]=0
Message.error(res.data.error_msg)
}
}).catch((err)=>{
this.btnStatus[index]=0
Message.error(err)
})
},
createTask(index){
this.btnStatus[index]=1
const data = {type:index,...this.fileInfo}
let repoPath = `repos/${this.fileInfo.owner_name}/${this.fileInfo.project_name}`
createNotebook(data).then((res)=>{
if(res.data.code===0 && res.status===200){
if(index===2){
timerCb2 = setInterval(() => {
setTimeout(this.getCb2NotebookInfo(repoPath,res.data.message), 0)
}, 10000)
}else{
timerCb1 = setInterval(() => {
setTimeout(this.getCb1NotebookInfo(repoPath,res.data.message,index), 0)
}, 10000)
}
this.alertCb = false
}else if(res.data.code==2){
this.btnStatus[index]=0
this.alertCb = true
}else{
this.btnStatus[index]=0
Message.error(res.data.message)
}
}).catch((err)=>{
if(err.response.status===403 && err.response.data.code===1 ){
location.href=`${AppSubUrl}/authentication/wechat/bind`
}
this.btnStatus[index]=0
this.alertCb = false
Message.error(err)
})
}
},
computed: {
cpuSpec(){
let cpu_spec = `${this.$t("notebook.specification")}:GPU: ${this.notebookInfo.specCpu.acc_cards_num}*${this.notebookInfo.specCpu.acc_card_type}, CPU: ${this.notebookInfo.specCpu.cpu_cores}`
if(this.notebookInfo.specCpu.gpu_mem_gi_b!==0){
cpu_spec += `, ${this.$t("notebook.graphicMemory")}: ${this.notebookInfo.specCpu.gpu_mem_gi_b}GB`
}
if(this.notebookInfo.specCpu.mem_gi_b!==0){
cpu_spec += `, ${this.$t("notebook.memory")}: ${this.notebookInfo.specCpu.mem_gi_b}GB`
}
if(this.notebookInfo.specCpu.share_mem_gi_b!==0){
cpu_spec += `, ${this.$t("notebook.sharedMemory")}: ${this.notebookInfo.specCpu.share_mem_gi_b}GB`
}
return cpu_spec
},
npuSpec(){
let acc_card_type = ''
if(this.notebookInfo.specNpu.acc_card_type==="ASCEND910"){
acc_card_type = "Ascend 910"
}
let npu_spec = `${this.$t("notebook.specification")}:NPU: ${this.notebookInfo.specNpu.acc_cards_num}*${acc_card_type}, CPU: ${this.notebookInfo.specNpu.cpu_cores}`
if(this.notebookInfo.specNpu.gpu_mem_gi_b!==0){
npu_spec += `, ${this.$t("notebook.graphicMemory")}: ${this.notebookInfo.specNpu.gpu_mem_gi_b}GB`
}
if(this.notebookInfo.specNpu.mem_gi_b!==0){
npu_spec += `, ${this.$t("notebook.memory")}: ${this.notebookInfo.specNpu.mem_gi_b}GB`
}
if(this.notebookInfo.specNpu.share_mem_gi_b!==0){
npu_spec += `, ${this.$t("notebook.sharedMemory")}: ${this.notebookInfo.specNpu.share_mem_gi_b}GB`
}
return npu_spec
},
gpuSpec(){
let gpu_spec = `${this.$t("notebook.specification")}:GPU: ${this.notebookInfo.specGpu.acc_cards_num}*${this.notebookInfo.specGpu.acc_card_type}, CPU: ${this.notebookInfo.specGpu.cpu_cores}`
if(this.notebookInfo.specGpu.gpu_mem_gi_b!==0){
gpu_spec += `, ${this.$t("notebook.graphicMemory")}: ${this.notebookInfo.specGpu.gpu_mem_gi_b}GB`
}
if(this.notebookInfo.specGpu.mem_gi_b!==0){
gpu_spec += `, ${this.$t("notebook.memory")}: ${this.notebookInfo.specGpu.mem_gi_b}GB`
}
if(this.notebookInfo.specGpu.share_mem_gi_b!==0){
gpu_spec += `, ${this.$t("notebook.sharedMemory")}: ${this.notebookInfo.specGpu.share_mem_gi_b}GB`
}
return gpu_spec
}
},
beforeDestroy() {
clearInterval(timerCb1)
clearInterval(timerCb2)
},
mounted() {
const selfData = document.querySelector('#__vue-self-data')
this.fileInfo.file = selfData.getAttribute('data-file')
this.fileInfo.branch_name = selfData.getAttribute('data-branch')
this.fileInfo.owner_name = selfData.getAttribute('data-owner')
this.fileInfo.project_name = selfData.getAttribute('data-project')
this.fileInfo.sign_name = selfData.getAttribute('data-name')
let that = this;
document
.querySelector("#notebook-debug")
.addEventListener("click", function () {
that.getNotebookInfo()
that.dialogVisible = true;
});
},
};
</script>
<style scoped lang="less">
/deep/ .el-dialog__header {
text-align: left;
height: 45px;
background: rgb(240, 240, 240);
border-radius: 5px 5px 0px 0px;
border-bottom: 1px solid rgb(212, 212, 213);
padding: 0 15px;
display: flex;
align-items: center;
font-weight: 500;
font-size: 16px;
color: rgb(16, 16, 16);
font-family: Roboto;

.el-dialog__title {
font-weight: 600;
font-size: 15px;
color: rgb(16, 16, 16);
}

.el-dialog__headerbtn {
top: 15px;
right: 15px;
}
}

/deep/ .el-dialog__body {
padding: 55px 15px 0 15px;
}
.wrapper {
width: 100%;
.active {
background: linear-gradient(
269.2deg,
rgba(183, 247, 255, 0.5) 0%,
rgba(233, 233, 255, 0) 78.67%
);
border-radius: 5px 5px 0px 0px;
}
.text-tip{
color: #888;
font-size: 12px;
}
.text-tip::before{
content: '*';
color: #f2711c;
}
.alert-info{
width: 70%;
background-color: rgba(242, 113, 28, 0.05);
border: 1px solid rgb(242, 113, 28);
border-radius: 5px;
margin: 0 auto;
padding-bottom: 10px;
}
& >.three-resource-type:nth-child(2){
border:none;
}
.three-resource-type {
width: 70%;
margin: 0 auto;
display: flex;
border-top: 1px solid rgba(16, 16, 16, 0.1);
cursor: pointer;
.resource-child-node {
display: flex;
align-items: center;
width: 100%;
height: 115px;
.resource-type-icon {
width: 50px;
height: 50px;
line-height: 20px;
border-radius: 25px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
.text {
font-size: 26px;
color: rgba(251, 251, 251, 1);
font-family: ZKXiaoWeiLogo-regular;
}
}
.background-C {
background: linear-gradient(
134.2deg,
rgba(130, 209, 246, 1) 0%,
rgba(41, 182, 244, 1) 51.94%,
rgba(0, 137, 205, 1) 102.83%
);
}
.background-N {
background: linear-gradient(
151.47deg,
rgba(123, 50, 178, 1) 20.02%,
rgba(64, 26, 93, 1) 100%
);
}
.background-G {
background: linear-gradient(
-25.25deg,
rgba(254, 86, 77, 1) 9.3%,
rgba(251, 155, 54, 1) 38.86%,
rgba(249, 202, 38, 1) 67.95%
);
}
}
.resource-type-detail {
margin-left: 23px;
.detail-title {
font-family: SourceHanSansSC;
font-weight: 500;
font-size: 16px;
color: rgb(16, 16, 16);
font-style: normal;
letter-spacing: 0px;
line-height: 32px;
text-decoration: none;
}
.detail-spec {
font-family: SourceHanSansSC;
font-weight: 400;
font-size: 14px;
color: rgba(136, 136, 136, 1);
font-style: normal;
letter-spacing: 0px;
line-height: 24px;
text-decoration: none;
}
}
.resource-select {
margin-left: auto;
margin-right: 20px;
font-size: 20px;
height: 100%;
display: flex;
align-items: center;
.green {
color: green;
}
.gray {
color: rgba(16, 16, 16, 0.1);
}
}
}
.resource-footer {
margin-top: 40px;
border-top: 1px solid rgba(16, 16, 16, 0.1);
height: 71px;
display: flex;
align-items: center;
.resource-operate {
display: flex;
align-items: center;
.text{
color: #101010;
margin-left: 20px;
}
}
}
.slide-in-top {
-webkit-animation: slide-in-top 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
animation: slide-in-top 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}
.slide-in-bottom {
-webkit-animation: slide-in-bottom 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
animation: slide-in-bottom 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}
.fade-out {
-webkit-animation: fade-in 1.2s cubic-bezier(0.39, 0.575, 0.565, 1) both;
animation: fade-in 1.2s cubic-bezier(0.39, 0.575, 0.565, 1) both;
position: absolute
}
@-webkit-keyframes slide-in-top {
0% {
-webkit-transform: translateY(-50px);
transform: translateY(-50px);
opacity: 0;
}
100% {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
}
@keyframes slide-in-top {
0% {
-webkit-transform: translateY(-50px);
transform: translateY(-50px);
opacity: 0;
}
100% {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
}
@-webkit-keyframes slide-in-bottom {
0% {
-webkit-transform: translateY(50px);
transform: translateY(50px);
opacity: 0;
}
100% {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
}
@keyframes slide-in-bottom {
0% {
-webkit-transform: translateY(50px);
transform: translateY(50px);
opacity: 0;
}
100% {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
}
@-webkit-keyframes fade-in {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes fade-in {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
}
</style>

+ 12
- 0
web_src/vuepages/pages/notebook/debug/vp-notebook-debug.js View File

@@ -0,0 +1,12 @@
import Vue from 'vue';
import {Dialog,Loading} from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import { i18n, lang } from '~/langs';
import App from './index.vue';

Vue.use(Dialog)
Vue.use(Loading.directive)
new Vue({
i18n,
render: (h) => h(App),
}).$mount('#__vue-root');

Loading…
Cancel
Save