Commit 60993455 authored by chenshouchao's avatar chenshouchao

Merge branch 'feat-20221012-environment' into 'staging'

Feat 20221012 environment

See merge request !144
parents 8d09417b c5554013
This diff is collapsed.
......@@ -21,6 +21,7 @@
"@types/node": "^16.11.33",
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.3",
"@uiw/react-codemirror": "^4.12.4",
"ahooks": "^3.3.12",
"axios": "^0.27.2",
"babel-jest": "^27.4.2",
......@@ -48,6 +49,7 @@
"jest": "^27.4.3",
"jest-resolve": "^27.4.2",
"jest-watch-typeahead": "^1.0.0",
"js-base64": "^3.7.2",
"kekule": "^0.9.7",
"lodash": "^4.17.21",
"mini-css-extract-plugin": "^2.4.5",
......@@ -180,7 +182,9 @@
]
},
"devDependencies": {
"@babel/standalone": "^7.19.5",
"@types/crypto-js": "^4.1.1",
"@types/mockjs": "^1.0.6"
"@types/mockjs": "^1.0.6",
"raw-loader": "^4.0.2"
}
}
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>iconfont Demo</title>
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg" type="image/x-icon"/>
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
<style>
.main .logo {
margin-top: 0;
height: auto;
}
.main .logo a {
display: flex;
align-items: center;
}
.main .logo .sub-title {
margin-left: 0.5em;
font-size: 22px;
color: #fff;
background: linear-gradient(-45deg, #3967FF, #B500FE);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=3701233" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe607;</span>
<div class="name">点赞</div>
<div class="code-name">&amp;#xe607;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe9b2;</span>
<div class="name">搜索-223</div>
<div class="code-name">&amp;#xe9b2;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.woff2?t=1665568301019') format('woff2'),
url('iconfont.woff?t=1665568301019') format('woff'),
url('iconfont.ttf?t=1665568301019') format('truetype');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-dianzan"></span>
<div class="name">
点赞
</div>
<div class="code-name">.icon-dianzan
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-sousuo-223"></span>
<div class="name">
搜索-223
</div>
<div class="code-name">.icon-sousuo-223
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-dianzan"></use>
</svg>
<div class="name">点赞</div>
<div class="code-name">#icon-dianzan</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-sousuo-223"></use>
</svg>
<div class="name">搜索-223</div>
<div class="code-name">#icon-sousuo-223</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>
@font-face {
font-family: "iconfont"; /* Project id 3701233 */
src: url('iconfont.woff2?t=1665568301019') format('woff2'),
url('iconfont.woff?t=1665568301019') format('woff'),
url('iconfont.ttf?t=1665568301019') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-dianzan:before {
content: "\e607";
}
.icon-sousuo-223:before {
content: "\e9b2";
}
window._iconfont_svg_string_3701233='<svg><symbol id="icon-dianzan" viewBox="0 0 1064 1024"><path d="M204.8 440.32a30.72 30.72 0 0 0-30.72 30.72v368.64c0 16.95744 13.76256 30.72 30.72 30.72h51.2v-430.08H204.8z m-133.12 30.72A133.12 133.12 0 0 1 204.8 337.92h102.4c28.2624 0 51.2 22.9376 51.2 51.2v532.48c0 28.2624-22.9376 51.2-51.2 51.2H204.8a133.12 133.12 0 0 1-133.12-133.12v-368.64z" fill="#1D1D1F" ></path><path d="M512.94208 140.41088c-23.18336 71.35232-57.42592 138.89536-89.45664 190.0544-16.384 26.17344-32.80896 48.98816-47.59552 66.31424-7.3728 8.6016-14.99136 16.62976-22.65088 23.26528-6.10304 5.24288-18.0224 14.82752-33.5872 18.75968a51.2 51.2 0 0 1-33.01376-96.58368c2.4576-2.12992 6.26688-5.98016 11.38688-12.00128 10.6496-12.45184 24.1664-30.88384 38.66624-54.14912 29.12256-46.4896 60.2112-108.29824 80.32256-171.86816 7.08608-22.28224 23.7568-45.99808 52.18304-56.89344 47.5136-18.18624 125.7472-27.27936 172.60544 40.50944 21.01248 30.43328 30.22848 70.41024 30.3104 117.30944 0.08192 32.11264-4.096 69.30432-12.98432 112.31232h167.1168c46.61248 0 101.82656 19.0464 130.37568 70.8608 60.66176 110.01856 85.1968 302.4896-81.79712 521.17504-32.31744 42.27072-82.3296 63.32416-131.8912 63.32416H307.2a51.2 51.2 0 1 1 0-102.4h435.77344c21.34016 0 39.7312-9.0112 50.46272-23.10144 142.9504-187.14624 114.11456-335.91296 73.5232-409.6-4.87424-8.8064-18.0224-17.85856-40.67328-17.85856H593.92a51.2 51.2 0 0 1-49.31584-64.9216c18.432-66.27328 25.1904-114.85184 25.14944-149.54496-0.08192-35.06176-7.168-52.0192-12.20608-59.35104-4.99712-7.20896-16.67072-14.58176-44.60544-5.61152zM284.672 343.81824l0.69632-0.49152a4.096 4.096 0 0 1-0.69632 0.49152z" fill="#1D1D1F" ></path></symbol><symbol id="icon-sousuo-223" viewBox="0 0 1024 1024"><path d="M467.456 900.949333C228.522667 900.949333 34.133333 706.56 34.133333 467.456S228.522667 34.133333 467.456 34.133333s433.493333 194.389333 433.493333 433.322667-194.389333 433.493333-433.493333 433.493333z m0-815.616C256.853333 85.333333 85.333333 256.853333 85.333333 467.456s171.52 382.122667 382.122667 382.122667 382.293333-171.52 382.293333-382.122667S678.229333 85.333333 467.456 85.333333z" fill="#333333" ></path><path d="M331.776 333.482667c-6.485333 0-13.141333-2.56-18.090667-7.509334a25.429333 25.429333 0 0 1 0-36.181333c41.130667-41.130667 95.744-63.658667 153.770667-63.658667 58.197333 0 112.810667 22.698667 153.770667 63.658667 10.069333 10.069333 10.069333 26.282667 0 36.181333-10.069333 10.069333-26.282667 10.069333-36.181334 0a165.239467 165.239467 0 0 0-117.589333-48.64c-44.373333 0-86.186667 17.237333-117.589333 48.64-4.949333 4.949333-11.434667 7.509333-18.090667 7.509334zM964.266667 989.866667c-6.485333 0-13.141333-2.56-18.090667-7.509334L742.570667 778.752c-10.069333-10.069333-10.069333-26.282667 0-36.181333s26.282667-10.069333 36.181333 0l203.605333 203.605333c10.069333 10.069333 10.069333 26.282667 0 36.181333-4.949333 4.949333-11.605333 7.509333-18.090666 7.509334z" fill="#333333" ></path></symbol></svg>',function(n){var t=(t=document.getElementsByTagName("script"))[t.length-1],e=t.getAttribute("data-injectcss"),t=t.getAttribute("data-disable-injectsvg");if(!t){var i,o,c,a,d,s=function(t,e){e.parentNode.insertBefore(t,e)};if(e&&!n.__iconfont__svg__cssinject__){n.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(t){console&&console.log(t)}}i=function(){var t,e=document.createElement("div");e.innerHTML=n._iconfont_svg_string_3701233,(e=e.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",e=e,(t=document.body).firstChild?s(e,t.firstChild):t.appendChild(e))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(i,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),i()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(c=i,a=n.document,d=!1,r(),a.onreadystatechange=function(){"complete"==a.readyState&&(a.onreadystatechange=null,l())})}function l(){d||(d=!0,c())}function r(){try{a.documentElement.doScroll("left")}catch(t){return void setTimeout(r,50)}l()}}(window);
\ No newline at end of file
{
"id": "3701233",
"name": "云平台",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "北鲲云云平台",
"glyphs": [
{
"icon_id": "32228179",
"name": "点赞",
"font_class": "dianzan",
"unicode": "e607",
"unicode_decimal": 58887
},
{
"icon_id": "28529168",
"name": "搜索-223",
"font_class": "sousuo-223",
"unicode": "e9b2",
"unicode_decimal": 59826
}
]
}
......@@ -23,6 +23,7 @@
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="%PUBLIC_URL%/iconfont/iconfont.css" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
......
......@@ -49,6 +49,9 @@ const RESTAPI = {
API_ADD_PROJECT_USER:`${BACKEND_API_URI_PREFIX}/cpp/project/updatemember`, // 添加项目成员
API_GET_PROJECT_POWER:`${BACKEND_API_URI_PREFIX}/cpp/project/listroles`, // 获取项目权限
API_GET_HARDWARE:`${BACKEND_API_URI_PREFIX}/cpp/cpce/hardware`, // 获取计算队列列表
API_GET_PUBLIC_ENV:`${BACKEND_API_URI_PREFIX}/cpp/common/public/env`, // 获取公共环境
API_GET_PUBLIC_PROJECT:`${BACKEND_API_URI_PREFIX}/cpp/common/public/project`, // 获取公共环境
API_ACTORENV_BUILDENV:`${BACKEND_API_URI_PREFIX}/cpp/actorenv/buildenv`, // 新增应用环境
};
export default RESTAPI;
......@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:17:48
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-08-30 16:22:15
* @LastEditTime: 2022-10-17 11:51:35
* @FilePath: /bkunyun/src/api/api_prefix.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -36,7 +36,7 @@ switch (process.env.REACT_APP_ENV) {
BACKEND_API_URI_PREFIX = "https://www.cloudam.cn";
}
else {
BACKEND_API_URI_PREFIX = "http://47.75.104.171";
BACKEND_API_URI_PREFIX = "http://47.57.4.97";
}
break;
}
......
......@@ -105,7 +105,7 @@ class CloudEController {
headers["Cache-Control"] = "no-cache";
headers["delfilepath"] = Base64.stringify(Utf8.parse(urls));
let url = "";
if (getLoaclStorageOfKey("userinfo")) {
if (getLoaclStorageOfKey("userInfo")) {
url += urlToken(filetoken, projectId);
}
return axios.get(APIOPTION() + "/delete/" + url, {
......@@ -129,7 +129,7 @@ class CloudEController {
) {
if (ApiUtils.getAuthorizationHeaders(headers)) {
headers["Cache-Control"] = "no-cache";
if (getLoaclStorageOfKey("userinfo")) {
if (getLoaclStorageOfKey("userInfo")) {
url += urlToken(filetoken, projectId);
}
return axios.get(
......@@ -151,7 +151,7 @@ class CloudEController {
if (ApiUtils.getAuthorizationHeaders(headers)) {
headers["Cache-Control"] = "no-cache";
// headers['parentName'] = ''
if (getLoaclStorageOfKey("userinfo")) {
if (getLoaclStorageOfKey("userInfo")) {
url += urlToken(filetoken, projectId);
}
return axios.get(
......@@ -172,7 +172,7 @@ class CloudEController {
) {
if (ApiUtils.getAuthorizationHeaders(headers)) {
headers["Cache-Control"] = "no-cache";
if (getLoaclStorageOfKey("userinfo")) {
if (getLoaclStorageOfKey("userInfo")) {
url = urlToken(filetoken, projectId) + "&q=" + url;
}
return axios.get(
......@@ -188,7 +188,7 @@ class CloudEController {
// static JobOutFileListMove(url: any, filetoken: string, projectId: string) {
// if (ApiUtils.getAuthorizationHeaders(headers)) {
// headers["Cache-Control"] = "no-cache";
// if (getLoaclStorageOfKey("userinfo")) {
// if (getLoaclStorageOfKey("userInfo")) {
// url += urlToken(filetoken, projectId);
// }
// return axios.get(APIOPTION() + "/download" + url, {
......
......@@ -30,14 +30,14 @@ const APIPORT = function () {
// 当前计算区
// let currentRegion = localStorage.getItem("current-region");
// let currentRegionJson = currentRegion && JSON.parse(currentRegion);
// let user = getLoaclStorageOfKey("userinfo");
// let user = getLoaclStorageOfKey("userInfo");
// 文件路径
// const FILEPATH =
// currentRegionJson &&
// currentRegionJson.location &&
// currentRegionJson.location === "ON_PREMISE" &&
// localStorage.getItem("userinfo")
// localStorage.getItem("userInfo")
// ? `/home/${user.name}`
// : "/home/cloudam";
const FILEPATH_SHARE = "/share";
......@@ -62,7 +62,7 @@ const urlToken = (filetoken: string, projectId: string) => {
};
const getUuid = () => {
const userInfo = getLoaclStorageOfKey("userinfo");
const userInfo = getLoaclStorageOfKey("userInfo");
// 是否共有文件系统
if (
localStorage.getItem("isShareFileSystem") &&
......@@ -75,12 +75,12 @@ const getUuid = () => {
};
const USERNAME = () => {
return getLoaclStorageOfKey("userinfo").name;
return getLoaclStorageOfKey("userInfo").name;
};
// 加密传输
const encryptTransfer = () => {
const userInfo = getLoaclStorageOfKey("userinfo");
const userInfo = getLoaclStorageOfKey("userInfo");
if (userInfo) {
let encryptTransfer = userInfo.encryptTransfer;
if (encryptTransfer) {
......
......@@ -354,7 +354,6 @@ const getHardwreList = (params: {zoneId: string, computeType: string}) => {
params,
});
}
//
export {
current,
......
import request from "@/utils/axios/service";
import Api from "./api_manager";
type addActorenvBuildenvParams = {
title: string,
desc: string,
baseEnvId: string,
type: "BATCH" | "FLOW",
filePaths: Array<string>,
bashScript: string,
computeType: string,
publicProjectId: string,
}
// 获取公共项目
const getPublicProject = () => {
return request({
url: Api.API_GET_PUBLIC_PROJECT,
method: "get",
});
}
// 获取公共环境
const getPublicEnv = (params: {taskType: 'BATCH' | 'FLOW'}) => {
return request({
url: Api.API_GET_PUBLIC_ENV,
method: "get",
params,
});
};
// 新增应用环境
const addActorenvBuildenv = (params: addActorenvBuildenvParams) => {
return request({
url: Api.API_ACTORENV_BUILDENV,
method: "post",
data: {...params, name: '123'},
});
};
export {
getPublicEnv,
getPublicProject,
addActorenvBuildenv,
};
This diff is collapsed.
This diff is collapsed.
......@@ -17,8 +17,8 @@ export type IQueueLi = {
coreNum: number;
memory: number;
total: number;
id: string;
partition: string;
enabled: boolean;
};
type IQueueSelectProps = {
......@@ -29,12 +29,13 @@ type IQueueSelectProps = {
error?: boolean;
helperText?: string;
disabled?: boolean;
cpuLoading?: boolean;
gpuLoading?: boolean;
};
type IMemoryLi = {
memory: number;
total: number;
id: string;
partition: string;
};
......@@ -43,8 +44,8 @@ export type IShowCPULi = {
picUrl: string;
cpuName: string;
coreNum: number;
id: string;
partition: string;
enabled: boolean;
memoryList: Array<IMemoryLi>;
};
......@@ -68,7 +69,10 @@ const QueueSelect = (props: IQueueSelectProps) => {
error,
helperText,
disabled,
cpuLoading = false,
gpuLoading = false,
} = props;
// 队列列表由外面传入的设计是考虑到一个表单可能有多次队列选择, 请求队列接口在表单页面完成可以减少请求
const Message = useMessage();
const [activePartition, setActivePartition] = useState("");
const [open, setOpen] = useState(false);
......@@ -78,11 +82,10 @@ const QueueSelect = (props: IQueueSelectProps) => {
setOpen(true);
};
// 队列id、partition和前端展示的队列信息的映射关系
// 队列partition和前端展示的队列信息的映射关系
const idInfoMap = useMemo(() => {
return [
...originalCpuList.map((item) => ({
id: item.id,
partition: item.partition,
title: `${item.name}/${item.coreNum}${item.coreNum * item.memory}G/${
item.coreNum
......@@ -90,7 +93,6 @@ const QueueSelect = (props: IQueueSelectProps) => {
total: item.total,
})),
...originalGpuList.map((item) => ({
id: item.id,
partition: item.partition,
title: `${item.name}/${item.gpuNum}${item.coreNum}${item.memory}G/${item.gpuNum}总卡数`,
total: item.total,
......@@ -98,41 +100,6 @@ const QueueSelect = (props: IQueueSelectProps) => {
];
}, [originalCpuList, originalGpuList]);
useEffect(() => {
let resultList: Array<IShowCPULi> = [];
originalCpuList.forEach((item) => {
const targetIndex = resultList.findIndex((resultLi) => {
return resultLi.name === item.name;
});
if (targetIndex === -1) {
resultList.push({
name: item.name,
picUrl: item.picUrl,
cpuName: item.cpuName,
coreNum: item.coreNum,
id: item.id,
partition: item.partition,
memoryList: [
{
memory: item.memory,
total: item.total,
id: item.id,
partition: item.partition,
},
],
});
} else {
resultList[targetIndex].memoryList.push({
memory: item.memory,
total: item.total,
id: item.id,
partition: item.partition,
});
}
});
setShowCpuList(resultList);
}, [originalCpuList]);
const cpuHeadCells = [
{
id: "type",
......@@ -174,6 +141,58 @@ const QueueSelect = (props: IQueueSelectProps) => {
},
];
// 有初始值的话显示初始值
useEffect(() => {
let resultList: Array<IShowCPULi> = [];
originalCpuList.forEach((item) => {
const targetIndex = resultList.findIndex((resultLi) => {
return resultLi.name === item.name;
});
if (targetIndex === -1) {
resultList.push({
name: item.name,
picUrl: item.picUrl,
cpuName: item.cpuName,
coreNum: item.coreNum,
partition: item.partition,
enabled: item.enabled,
memoryList: [
{
memory: item.memory,
total: item.total,
partition: item.partition,
},
],
});
} else {
resultList[targetIndex].memoryList.push({
memory: item.memory,
total: item.total,
partition: item.partition,
});
}
});
if (open && value) {
const cpuActivePartitionIndex = originalCpuList.findIndex(
(li) => li.partition === value
);
let cpuActivePartitionName = "";
if (cpuActivePartitionIndex !== -1) {
cpuActivePartitionName = originalCpuList[cpuActivePartitionIndex].name;
}
if (cpuActivePartitionIndex !== -1) {
resultList.forEach((li, index) => {
if (li.name === cpuActivePartitionName) {
resultList[index].partition = value;
}
});
}
setActivePartition(value);
}
setShowCpuList(resultList);
// eslint-disable-next-line
}, [open, value, originalCpuList]);
const renderType = (item: IShowCPULi) => {
return (
<div className={style.cpuType}>
......@@ -223,6 +242,9 @@ const QueueSelect = (props: IQueueSelectProps) => {
}))}
hasTriangle={true}
setValue={setMemory}
sx={{
zIndex: 1601,
}}
>
<span className={style.cpuMemory}>
{
......@@ -293,6 +315,17 @@ const QueueSelect = (props: IQueueSelectProps) => {
</span>
</div>
}
sx={{
zIndex: 1600,
// 让提示文案在弹窗下
"& .MuiDialog-container": {
"& .MuiPaper-root": {
// 设置最大宽度, 实际宽度让子元素撑大
maxWidth: "1920px",
borderRadius: "8px",
},
},
}}
>
<div className={style.queueSelectContentBox}>
<RadioGroupOfButtonStyle
......@@ -316,6 +349,8 @@ const QueueSelect = (props: IQueueSelectProps) => {
handleRow={(e: any) => handleRow(e)}
activeId={activePartition}
tableKey="partition"
loading={cpuLoading}
disableFn={(row: any) => !row.enabled}
></MyTable>
)}
{queueType === "GPU" && (
......@@ -332,6 +367,8 @@ const QueueSelect = (props: IQueueSelectProps) => {
handleRow={(e: any) => handleRow(e)}
activeId={activePartition}
tableKey="partition"
loading={gpuLoading}
disableFn={(row: any) => !row.enabled}
></MyTable>
)}
</div>
......
import CodeMirror from "@uiw/react-codemirror";
type ICodeType = {
value: string;
onChange: any;
height?: string;
theme?: "light" | "dark";
};
const Code = (props: ICodeType) => {
const { value, onChange, height, theme = "dark" } = props;
return (
<CodeMirror
height={height || "100%"}
value={value}
onChange={(e) => onChange(e)}
theme={theme}
/>
);
};
export default Code;
......@@ -5,13 +5,14 @@ import {
DialogActions,
DialogContent,
DialogTitle,
DialogProps,
} from "@mui/material";
import CloseIcon from "@mui/icons-material/Close";
import { ThemeProvider, createTheme } from "@mui/material/styles";
import MyButton from "./MyButton";
export interface IDialogProps {
export interface IDialogProps extends DialogProps {
/** 自定义类名 */
className?: string;
/** 自定义样式 */
......@@ -101,6 +102,7 @@ const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
okColor = "primary",
isText = false,
leftSideOfButtonContent = null,
...other
} = props;
const handelClose = (
......@@ -184,6 +186,7 @@ const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
},
},
}}
{...other}
>
{isHideHeader ? null : (
<DialogTitle id="alert-dialog-title" sx={{ padding: "20px 24px" }}>
......
......@@ -121,6 +121,13 @@ const MyInput = (props: MyInputProps) => {
},
},
},
MuiFormHelperText: {
styleOverrides: {
root: {
marginLeft: "0px",
},
},
},
},
});
......
// 单选下拉框, 是input还是text还是其他由children决定
import * as React from "react";
import Menu from "@mui/material/Menu";
import Menu, { MenuProps } from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
import CheckIcon from "@mui/icons-material/Check";
import { ThemeProvider, createTheme } from "@mui/material/styles";
......@@ -12,13 +12,13 @@ type IOption = {
value: string;
};
type IMyMenuProps = {
interface IMyMenuProps extends Omit<MenuProps, "open"> {
children: React.ReactNode;
options: Array<IOption>;
value: string;
setValue?: any;
hasTriangle?: boolean;
};
}
const theme = createTheme({
components: {
......@@ -65,7 +65,14 @@ const theme = createTheme({
});
const MyMenu = (props: IMyMenuProps) => {
const { children, options, value, setValue, hasTriangle = false } = props;
const {
children,
options,
value,
setValue,
hasTriangle = false,
...other
} = props;
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
......@@ -112,6 +119,7 @@ const MyMenu = (props: IMyMenuProps) => {
MenuListProps={{
"aria-labelledby": "basic-button",
}}
{...other}
>
{options.map((option, index) => {
return (
......
......@@ -200,7 +200,10 @@ export default function MySelect(props: IProps) {
<ThemeProvider theme={theme}>
<FormControl fullWidth={fullWidth} variant={variant} error={error}>
{isTitle ? (
<InputLabel id="demo-simple-select-label">
<InputLabel
id="demo-simple-select-label"
sx={{ color: "rgba(194, 198, 204, 1)" }}
>
{title || "请选择"}
</InputLabel>
) : null}
......
......@@ -46,6 +46,7 @@ interface IMyTableProps {
nodataText?: any; // 无数据文案
handleRow?: any; // 点击一行
activeId?: string; // 选中的一行的id
disableFn?: any; // 禁用时根据disableFn来判断是否禁用
}
const MyTable = (props: IMyTableProps) => {
......@@ -71,6 +72,7 @@ const MyTable = (props: IMyTableProps) => {
nodataText,
handleRow,
activeId,
disableFn,
} = props;
const theme = useMemo(() => {
......@@ -236,6 +238,17 @@ const MyTable = (props: IMyTableProps) => {
[selectItems, setSelectItems]
);
const handleRowFn = useCallback(
(row: any) => {
if (!disableFn) {
handleRow && handleRow(row);
} else {
!disableFn(row) && handleRow && handleRow(row);
}
},
[disableFn, handleRow]
);
const handleSort = useCallback(
(field: string) => {
if (sortState?.field === field) {
......@@ -370,10 +383,13 @@ const MyTable = (props: IMyTableProps) => {
{rows.map((row, rowIndex) => (
<TableRow
key={row[tableKey] || rowIndex}
onClick={() => handleRow && handleRow(row)}
// onClick={() => handleRow && handleRow(row)}
onClick={() => handleRowFn(row)}
sx={{
background:
activeId === row[tableKey] ? "rgba(237, 244, 255, 1)" : "",
cursor: disableFn && disableFn(row) ? "no-drop" : "",
opacity: disableFn && disableFn(row) ? "0.3" : "",
}}
>
{hasCheckbox && (
......@@ -393,12 +409,10 @@ const MyTable = (props: IMyTableProps) => {
)}
{headCells.map((headCell, index) => (
<TableCell key={index} align="left" width={headCell.width}>
{/* {row[headCell.id]} */}
{headCell.showOverflowTooltip && (
<MyTooltip title={row[headCell.id]}>
<div
style={{
// width: headCell.width,
width: Number(headCell.width) - 32 || "",
overflow: "hidden",
textOverflow: "ellipsis",
......@@ -433,8 +447,9 @@ const MyTable = (props: IMyTableProps) => {
headCells,
nodataText,
loading,
handleRow,
handleRowFn,
activeId,
disableFn,
]);
const randerTableFooter = useMemo(() => {
......
.titleBox {
font-size: 18px;
padding-left: 24px;
line-height: 26px;
font-weight: 600;
color: #1e2633;
line-height: 48px;
}
.titleBox::after {
content: "|";
padding: 0 24px;
color: #dde1e6;
}
......@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-09-01 19:34:35
* @LastEditTime: 2022-10-17 16:16:42
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -14,6 +14,9 @@ import Tab from "@mui/material/Tab";
import { ThemeProvider, createTheme } from "@mui/material/styles";
import { TabContext, TabList, TabPanel } from "@mui/lab";
import { Typography } from "@mui/material";
import classNames from "classnames";
import styles from "./index.module.css";
interface ITabList {
label: string;
......@@ -27,12 +30,22 @@ interface ITabList {
}
interface IProps {
/** 标题 */
title?: string;
/** title样式class */
titleClass?: any;
/** 选中值 */
value?: string;
/** 值 */
onChange?: (val: string) => void;
/** tab页面数组 */
tabList: ITabList[];
/** 默认选中tab */
defaultValue?: string;
/** 面板样式 */
tabPanelSx?: any;
allowNullValue?: boolean; // 是否允许空值
/** 是否允许空值 */
allowNullValue?: boolean;
}
const theme = createTheme({
......@@ -78,6 +91,8 @@ const Tabs = (props: IProps) => {
onChange,
allowNullValue = false,
tabPanelSx = { padding: "24px 0 0 0" },
title,
titleClass,
} = props;
const [tabValue, setTabValue] = useState(
......@@ -148,6 +163,16 @@ const Tabs = (props: IProps) => {
onTabChange(val);
}}
>
{title ? (
<span
className={classNames({
[styles.titleBox]: true,
[titleClass]: titleClass,
})}
>
{title}
</span>
) : null}
{tabList
?.filter((item) => !item.hide)
.map((item, key) => {
......
......@@ -19,6 +19,7 @@ import ProjectWorkbench from "@/views/Project/ProjectWorkbench";
import ProjectSubmitWork from "@/views/Project/ProjectSubmitWork";
import ProjectJobDetail from "@/views/Project/ProjectJobDetail";
import ProjectOverview from "@/views/Project/ProjectOverview";
import UserResources from "@/views/ResourceCenter/UserResources";
export type route = {
id?: string;
......@@ -51,6 +52,7 @@ export const elements: {
}) => JSX.Element | any;
} = {
Demo: Demo,
UserResources: UserResources,
ProjectSetting: ProjectSetting,
ProjectData: ProjectData,
ProjectWorkbench: ProjectWorkbench,
......
......@@ -90,7 +90,7 @@ export const storageUnitFromB = (b: number) => {
} else if (b < 1024 * 1024 * 1024 * 1024) {
return `${(b / (1024 * 1024 * 1024)).toFixed(2)}G`;
} else {
return `${(b / (1024 * 1024 * 1024 * 1024)).toFixed(2)}t`;
return `${(b / (1024 * 1024 * 1024 * 1024)).toFixed(2)}T`;
}
};
......
......@@ -46,3 +46,11 @@
background-color: #e6eaf0;
font-weight: 500;
}
.asideTop {
padding: 19px 24px 13px;
line-height: 24px;
font-size: 16px;
color: rgba(30, 38, 51, 1);
font-weight: 550;
}
......@@ -8,7 +8,7 @@
*/
import { Box, List } from "@mui/material";
import CurrentProject from "../Project/components/CurrentProject";
import React from "react";
import React, { useMemo } from "react";
import { Outlet, useNavigate, useLocation } from "react-router-dom";
import style from "./index.module.css";
import { observer } from "mobx-react-lite";
......@@ -44,10 +44,34 @@ const MenuLayout = observer(() => {
}
};
// // 左侧菜单顶部是否显示当前项目组件
// const showCurrentProject = useMemo(() => {
// const noCurrentProjectRouterApp = ["userCenter", "resourceCenter"];
// return noCurrentProjectRouterApp.every((item) => {
// return pathname.indexOf(item) === -1;
// });
// }, [pathname]);
const renderAsideTop = useMemo(() => {
const noCurrentProjectRouterApp = ["userCenter", "resourceCenter"];
if (
noCurrentProjectRouterApp.every((item) => {
return pathname.indexOf(item) === -1;
})
) {
return <CurrentProject />;
}
if (pathname.indexOf("resourceCenter") !== -1) {
return <div className={style.asideTop}>资源中心</div>;
}
return null;
}, [pathname]);
return (
<Box className={style.container}>
<Box className={style.aside}>
{pathname.indexOf("userCenter") < 0 && <CurrentProject />}
{renderAsideTop}
{/* {showCurrentProject && <CurrentProject />} */}
<List
sx={{
paddingTop: 0,
......
......@@ -28,6 +28,7 @@ type IMoveFileProps = {
const UpLoaderFile = observer((props: IMoveFileProps) => {
const { path, list, uploaderDialogOpen, setUploaderDialogOpen } = props;
console.log(path);
const { fileListStore } = useStores();
const message = useMessage();
......@@ -41,6 +42,7 @@ const UpLoaderFile = observer((props: IMoveFileProps) => {
const currentProjectStore = toJS(useGlobalStore("currentProjectStore"));
const uploadInfoStore = toJS(useGlobalStore("fileListStore"));
console.log(uploadInfoStore);
const { uploadFile } = UseTusUpload(uploadInfoStore);
const onDrop = useCallback(
......
import { useMemo, useCallback, useEffect, useState } from "react";
import { useMemo, useCallback, useState } from "react";
import { useNavigate } from "react-router-dom";
import MyProgress from "@/components/mui/MyProgress";
import { getDatasetPath } from "../../ProjectJobDetail/utils";
import style from "./index.module.css";
import { useStores } from "@/store";
import { toJS } from "mobx";
......@@ -27,7 +28,7 @@ type TaskCardProps = {
outputs: Array<any>;
};
const TaskCard = (props: TaskCardProps) => {
const TaskCard = observer((props: TaskCardProps) => {
const {
id,
name,
......@@ -66,15 +67,17 @@ const TaskCard = (props: TaskCardProps) => {
// 结果文件跳转
const goToProjectData = (info: any) => {
let { path = "", type = "" } = info;
const lastIndex = path.lastIndexOf("/");
// /projectData
// dataType
if (lastIndex !== -1) {
path = path.slice(0, lastIndex);
if (type === "file") {
const lastIndex = path.lastIndexOf("/");
if (lastIndex !== -1) {
path = path.slice(0, lastIndex);
}
path = path.slice(12);
} else {
path = getDatasetPath(path);
}
path = path.slice(12);
navigate(`/product/${productId || "cadd"}/projectData`, {
state: { pathName: path || "/", dataType: type },
state: { pathName: path, dataType: type },
});
};
// 跳转详情页
......@@ -247,6 +250,6 @@ const TaskCard = (props: TaskCardProps) => {
</div>
</div>
);
};
});
export default TaskCard;
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-13 16:51:56
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-17 15:36:29
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -15,7 +15,7 @@ import NoProject from "@/components/BusinessComponents/NoProject";
import { observer } from "mobx-react-lite";
import ProjectMembers from "./ProjectMembers";
import BaseInfo from "./BaseInfo";
import Tabs from "@/components/mui/Tabs";
import Tabs from "@/components/mui/MyTabs";
import usePass from "@/hooks/usePass";
const ProjectSetting = observer(() => {
......
......@@ -43,27 +43,36 @@ const ConfigForm = (props: ConfigFormProps) => {
const [cpuList, setCpuList] = useState<Array<IQueueLi>>([]);
const [gpuList, setGpuList] = useState<Array<IQueueLi>>([]);
const { run: getHardwreListFn } = useMyRequest(getHardwreList, {
onSuccess: (res, params) => {
if (params[0].computeType === "CPU") {
const { run: getCpuList, loading: cpuLoading } = useMyRequest(
getHardwreList,
{
onSuccess: (res) => {
setCpuList(res.data);
} else {
},
}
);
const { run: getGpuList, loading: gpuLoading } = useMyRequest(
getHardwreList,
{
onSuccess: (res) => {
setGpuList(res.data);
}
},
});
},
}
);
useEffect(() => {
getHardwreListFn({
zoneId,
computeType: "CPU",
});
}, [getHardwreListFn, zoneId]);
zoneId &&
getCpuList({
zoneId,
computeType: "CPU",
});
}, [getCpuList, zoneId]);
useEffect(() => {
getHardwreListFn({
zoneId,
computeType: "GPU",
});
}, [getHardwreListFn, zoneId]);
zoneId &&
getGpuList({
zoneId,
computeType: "GPU",
});
}, [getGpuList, zoneId]);
const [nameHelp, setNameHelp] = useState({
error: false,
......@@ -332,6 +341,8 @@ const ConfigForm = (props: ConfigFormProps) => {
originalGpuList={gpuList}
error={parameter.error || false}
helperText={parameter.helperText}
cpuLoading={cpuLoading}
gpuLoading={gpuLoading}
></QueueSelect>
)}
{(parameter.domType || "").toLowerCase() === "input" && (
......
......@@ -93,8 +93,10 @@ const ProjectSubmitWork = observer(() => {
: String(parameter.defaultValue);
} else if ((parameter.domType || "").toLowerCase() === "radio") {
value = false;
} else if ((parameter.domType || "").toLowerCase() === "partition") {
value = false;
} else {
value = "";
value = parameter.defaultValue;
}
parameter.value = value;
});
......
......@@ -2,7 +2,7 @@
* @Author: rocosen
* @Date: 2022-06-12 10:05:13
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-09-01 11:51:16
* @LastEditTime: 2022-10-17 15:36:38
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -14,7 +14,7 @@ import { useStores } from "@/store/index";
import WorkbenchTemplate from "./workbenchTemplate";
import WorkbenchList from "./workbenchList";
import Tabs from "@/components/mui/Tabs";
import Tabs from "@/components/mui/MyTabs";
import usePass from "@/hooks/usePass";
import NoProject from "@/components/BusinessComponents/NoProject";
import Template from "@/assets/project/workbenchTemplate.svg";
......
......@@ -20,7 +20,9 @@ const RemindBudgetDialog = observer((props: any) => {
};
const footerRender = () => {
return (
<DialogActions style={{ padding: "16px 24px 16px 24px" }}>
<DialogActions
style={{ padding: "16px 24px 16px 24px", justifyContent: "flex-end" }}
>
<MyButton
text="继续使用"
onClick={() => goToProjectSubmitWork(id)}
......
.addEnvironment {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: #fff;
display: flex;
}
.left {
/* width: 412px; */
box-sizing: border-box;
background-color: rgba(247, 248, 250, 1);
}
.right {
flex: 1;
padding: 64px 44px 40px;
min-height: 100vh;
overflow: overlay;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.title {
color: rgba(30, 38, 51, 1);
margin-bottom: 40px;
font-size: 24px;
line-height: 32px;
font-weight: 550;
}
.content {
display: flex;
border-radius: 4px;
margin-bottom: 24px;
height: 600px;
}
.form {
width: 368px;
box-sizing: border-box;
padding: 16px 24px;
border: 1px solid #ebedf0;
border-right: none;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.codeBox {
flex: 1;
display: flex;
flex-direction: column;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
.codeTitle {
background-color: rgba(230, 233, 237, 1);
padding: 11px 20px;
color: rgba(30, 38, 51, 1);
font-size: 14px;
line-height: 22px;
font-weight: 550;
border-top-right-radius: 4px;
}
.code {
background-color: rgba(247, 248, 250, 1);
flex: 1;
}
.label {
color: rgba(30, 38, 51, 1);
font-size: 14px;
line-height: 22px;
font-weight: 550;
margin-bottom: 8px;
position: relative;
}
.zipText {
color: rgba(138, 144, 153, 1);
font-weight: 400;
}
.required {
color: rgba(255, 78, 78, 1);
}
.download {
position: absolute;
right: 0;
cursor: pointer;
color: rgba(19, 112, 255, 1);
font-weight: 400;
}
.formItem {
position: relative;
margin-bottom: 24px;
}
.uploadBox {
border-radius: 4px;
border: 1px dashed #dde1e6;
height: 153px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.formItemHaveHelperText {
margin-bottom: 10px;
}
import { useEffect, useState, useCallback } from "react";
import MyInput from "@/components/mui/MyInput";
import MySelect from "@/components/mui/MySelect";
import MyButton from "@/components/mui/MyButton";
import style from "./index.module.css";
import useMyRequest from "@/hooks/useMyRequest";
import { urlToken } from "@/api/fileserver/raysyncApi";
import * as tus from "tus-js-client";
import { useDropzone } from "react-dropzone";
import SwitchBatchFolw from "@/views/ResourceCenter/components/SwitchBatchFolw";
import { getLoaclStorageOfKey } from "@/api/fileserver/utils";
import Code from "@/components/CommonComponents/Code";
import * as Base64 from "js-base64";
import { getDataFileToken, hpczone } from "@/api/project_api";
import {
getPublicEnv,
getPublicProject,
addActorenvBuildenv,
} from "@/api/resourceCenter";
import classNames from "classnames";
import { getTokenInfo } from "@/utils/util";
type IAddEnvironmentProps = {
setAddopen: any;
};
const AddEnvironment = (props: IAddEnvironmentProps) => {
const { setAddopen } = props;
let tokenInfo = getTokenInfo();
const [hpczoneList, setHpczoneList] = useState<Array<any>>([]);
const [publicProjectId, setPublicProjectId] = useState("");
const [publicZoneId, setPublicZoneId] = useState("");
const [computeType, setComputeType] = useState("");
const [fileToken, setFileToken] = useState("");
const [taskType, setTaskType] = useState<"BATCH" | "FLOW">("BATCH");
const [name, setName] = useState("");
const [desc, setDesc] = useState("");
const [baseEnvId, setBaseEnvId] = useState("");
const [filePaths, setFilePaths] = useState<Array<string>>([]);
// const [bashScript, setBashScript] = useState('');
const [envList, setEnvList] = useState<Array<any>>([]);
const [progress, setProgress] = useState("0%");
const [code, setCode] = useState("");
console.log(code);
const [nameHelper, setNameHelper] = useState({
error: false,
text: "30字符以内,仅限字母、数字、中文",
});
const onDrop = useCallback(
(acceptedFiles: any) => {
let origin = "";
hpczoneList.forEach((item) => {
if (item.id === publicZoneId) {
origin = item?.storageConfig?.fileServerEndPoint;
}
});
const fileInfo = acceptedFiles[0];
const { path } = fileInfo;
const userInfo = getLoaclStorageOfKey("userInfo");
const homeDirectoryMountPoint = userInfo?.homeDirectoryMountPoint;
const url =
origin + "/parallelupload/" + urlToken(fileToken, publicProjectId);
let headers = {
username: publicProjectId,
token: tokenInfo?.access_token || "",
filetoken: fileToken,
share: false,
project: true,
};
let upload = new tus.Upload(fileInfo, {
endpoint: url,
parallelUploads: 1,
chunkSize: 5 * 1024 * 1024,
metadata: {
filepath: "/" + homeDirectoryMountPoint + "/" + path,
},
retryDelays: [0, 3000, 5000, 10000, 20000],
headers: headers,
onbeforeunload: () => {
setProgress(`0%`);
},
onError: function (error: string) {
console.log("Failed because: " + error);
},
onProgress: function (bytesUploaded: number, bytesTotal: number) {
setProgress(`${bytesUploaded / bytesTotal}%`);
console.log(`${bytesUploaded / bytesTotal}%`);
},
onSuccess: function () {
setFilePaths([`/ProjectData/${homeDirectoryMountPoint}/${path}`]);
},
});
upload.start();
},
[
fileToken,
publicProjectId,
tokenInfo?.access_token,
hpczoneList,
publicZoneId,
]
);
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
const { run: getPublicEnvFn } = useMyRequest(getPublicEnv, {
onSuccess: (res: any) => {
console.log(res);
let arr = res.data.map((item: any) => {
return {
label: item.title,
value: item.id,
computeType: item.computeType,
};
});
setEnvList(arr);
if (arr.length >= 1) {
setBaseEnvId(arr[0].value);
setComputeType(arr[0].computeType);
}
},
});
const { run: getPublicProjectFn } = useMyRequest(getPublicProject, {
onSuccess: (res: any) => {
console.log(res);
setPublicProjectId(res.data[0].id);
setPublicZoneId(res.data[0].zoneId);
getDataFileTokenFn({ id: res.data[0].id });
},
});
const { run: getDataFileTokenFn } = useMyRequest(getDataFileToken, {
onSuccess: (res: any) => {
console.log(res);
setFileToken(res.data);
},
});
const { run: addActorenvBuildenvFn } = useMyRequest(addActorenvBuildenv, {
onSuccess: (res: any) => {
console.log(res);
},
});
useEffect(() => {
getPublicProjectFn();
}, [getPublicProjectFn]);
useEffect(() => {
getPublicEnvFn({ taskType });
}, [getPublicEnvFn, taskType]);
const { run: hpczoneFn } = useMyRequest(hpczone, {
onSuccess: (res: any) => {
setHpczoneList(res.data);
},
});
useEffect(() => {
hpczoneFn();
}, [hpczoneFn]);
const handleNameChange = (e: any) => {
setName(e.target.value);
};
const handleDescChange = (e: any) => {
setDesc(e.target.value);
};
const handelBaseEnvIdChange = (e: any) => {
setBaseEnvId(e);
let index = envList.findIndex((item) => {
return item.value === e;
});
setComputeType(envList[index].computeType);
};
const handleSubmit = () => {
addActorenvBuildenvFn({
title: name,
desc,
baseEnvId,
type: taskType,
filePaths,
bashScript: Base64.encode(code),
publicProjectId,
computeType,
});
};
return (
<div className={style.addEnvironment}>
<div className={style.left}>
<SwitchBatchFolw
active={taskType}
setActive={setTaskType}
goBack={() => setAddopen(false)}
></SwitchBatchFolw>
</div>
<div className={style.right}>
<div className={style.title}>
{taskType === "BATCH" ? "批式环境信息" : "流式环境信息"}
</div>
<div className={style.content}>
<div className={style.form}>
<div className={style.label}>
环境名称<span className={style.required}>*</span>
</div>
<div
className={classNames({
[style.formItem]: true,
[style.formItemHaveHelperText]: nameHelper.text,
})}
>
<MyInput
value={name}
onChange={handleNameChange}
error={nameHelper.error}
helperText={nameHelper.text}
placeholder="给环境起个名称"
></MyInput>
</div>
<div className={style.label}>
描述<span className={style.required}>*</span>
</div>
<div className={style.formItem}>
<MyInput
value={desc}
id="desc"
// label="项目描述"
multiline
rows={4}
placeholder="请输入项目描述"
onChange={handleDescChange}
/>
<span
style={{
position: "absolute",
fontSize: "14px",
bottom: "7px",
right: "12px",
color: desc.length >= 300 ? "#d32f2f" : "#C2C6CC",
}}
>
{desc.length}/300
</span>
</div>
<div className={style.label}>
基础环境<span className={style.required}>*</span>
</div>
<div className={style.formItem}>
<MySelect
options={envList}
fullWidth
value={baseEnvId}
onChange={(e) => handelBaseEnvIdChange(e)}
></MySelect>
</div>
<div className={style.label}>
上传环境压缩包<span className={style.zipText}>(.zip)</span>
<span className={style.required}>*</span>
<span className={style.download}>下载模板</span>
</div>
<div className={style.formItem}>
<div className={style.uploadBox} {...getRootProps()}>
<input {...getInputProps()} />
<span>点击选择环境包或将文件</span>
<span>拖到此处上传</span>
</div>
</div>
</div>
<div className={style.codeBox}>
<div className={style.codeTitle}>
{taskType === "BATCH" ? "Shell脚本" : "Python脚本"}
</div>
<div className={style.code}>
<Code
value={code}
onChange={(e: string) => setCode(e)}
height="535px"
/>
</div>
</div>
</div>
<div className={style.button}>
<MyButton text="开始构建" onClick={() => handleSubmit()}></MyButton>
</div>
</div>
</div>
);
};
export default AddEnvironment;
.environment {
}
.top {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
// 应用环境
import { useState } from "react";
import style from "./index.module.css";
import SearchInput from "@/components/BusinessComponents/SearchInput";
import MySelect from "@/components/mui/MySelect";
import MyButton from "@/components/mui/MyButton";
import AddEnvironment from "./AddEnvironment";
const UserResourcesEnvironment = () => {
const [addOpen, setAddopen] = useState(false);
return (
<div className={style.environment}>
<div className={style.top}>
<div className={style.topLeft}>
<SearchInput sx={{ width: 340, marginRight: "16px" }}></SearchInput>
<MySelect
options={[
{
label: "环境类型",
value: "a",
},
]}
sx={{ width: "150px", height: "32px" }}
></MySelect>
</div>
<div className={style.topRight}>
<MyButton
text="构建应用环境"
img={
<span
style={{ fontSize: "14px", marginRight: "8px" }}
className="iconfont icon-dianzan"
></span>
}
onClick={() => setAddopen(true)}
></MyButton>
</div>
</div>
UserResourcesEnvironment
{addOpen && <AddEnvironment setAddopen={setAddopen}></AddEnvironment>}
</div>
);
};
export default UserResourcesEnvironment;
.itemBox {
width: 334px;
height: 108px;
padding: 20px;
margin: 0 20px 20px 0;
background: linear-gradient(180deg, #f5f7fa 0%, #ffffff 100%);
box-shadow: 0px 6px 24px 0px rgba(3, 47, 105, 0.14);
border-radius: 6px;
border: 2px solid #ffffff;
}
.itemHeaderBox {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.itemContentBox {
display: flex;
flex-wrap: wrap;
}
.titleBox {
display: block;
font-size: 16px;
color: #1e2633;
}
.titleBox {
display: block;
font-size: 16px;
color: #1e2633;
}
.operatorTypeBox {
display: block;
color: #8a9099;
font-size: 12px;
}
.infoBox {
width: 50%;
font-weight: 400;
color: #8a9099;
font-size: 14px;
line-height: 26px;
}
.infoBox > span {
color: #1e2633;
}
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-17 14:35:11
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-17 18:35:09
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import styles from "./index.module.css";
const OperatorCard = () => {
return (
<div className={styles.itemBox}>
<div className={styles.itemHeaderBox}>
<img alt="" style={{ width: 36, height: 36 }} />
<div>
<b className={styles.titleBox}>Desktop</b>
<span className={styles.operatorTypeBox}>批算子</span>
</div>
</div>
<div className={styles.itemContentBox}>
<p className={styles.infoBox}>
产品类型:<span>CADD</span>
</p>
<p className={styles.infoBox}>
算子版本:<span>V1.0.0</span>
</p>
<p className={styles.infoBox}>
创建时间:<span>2022-10-11</span>
</p>
</div>
</div>
);
};
export default OperatorCard;
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-17 14:35:11
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-17 19:27:00
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import styles from "./index.module.css";
const OperatorDetails = () => {
return (
<div className={styles.detailsBox}>
<div>
<h2>基础信息</h2>
<tr>
<td>所属产品</td>
<td>创建时间</td>
<td>创建人</td>
<td>算子版本</td>
<td>应用环境</td>
</tr>
<tr>
<td>所属产品</td>
<td>创建时间</td>
<td>创建人</td>
<td>算子版本</td>
<td>应用环境</td>
</tr>
</div>
</div>
);
};
export default OperatorDetails;
.indexBox {
padding: 0 4px;
}
.headerBox {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding: 0 20px;
}
.searchSelectBox {
margin-left: 12px;
}
.contentBox {
display: flex;
flex-wrap: wrap;
padding-left: 20px;
}
/*
* @Author: 吴永生 15770852798@163.com
* @Date: 2022-10-17 14:35:11
* @LastEditors: 吴永生 15770852798@163.com
* @LastEditTime: 2022-10-17 17:50:30
* @FilePath: /bkunyun/src/views/ResourceCenter/UserResources/WorkflowOperator/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// 应用环境
import { useState } from "react";
import SearchInput from "@/components/BusinessComponents/SearchInput";
import MySelect from "@/components/mui/MySelect";
import MyButton from "@/components/mui/MyButton";
import OperatorCard from "./components/OperatorCard";
import styles from "./index.module.css";
const WorkflowOperator = () => {
const [addOpen, setAddopen] = useState(false);
return (
<div className={styles.indexBox}>
<div className={styles.headerBox}>
<div>
<SearchInput
sx={{ width: 340, marginRight: "16px" }}
placeholder="输入关键词搜索"
/>
<MySelect
options={[
{
label: "环境类型",
value: "a",
},
]}
placeholder="环境类型"
className={styles.searchSelectBox}
sx={{ width: "150px", height: "32px" }}
/>
<MySelect
options={[
{
label: "环境类型",
value: "a",
},
]}
placeholder="批/流类型"
className={styles.searchSelectBox}
sx={{ width: "150px", height: "32px" }}
/>
</div>
<MyButton
text="构建算子"
img={
<span
style={{ fontSize: "14px", marginRight: "8px" }}
className="iconfont icon-dianzan"
></span>
}
></MyButton>
</div>
<div className={styles.contentBox}>
{[1, 2, 3, 4, 5].map((item) => {
return <OperatorCard />;
})}
</div>
</div>
);
};
export default WorkflowOperator;
.userResources {
height: calc(100vh - 57px);
width: 100%;
}
.top {
display: flex;
justify-content: flex-start;
align-items: center;
border-bottom: 1px solid rgba(235, 237, 240, 1);
}
.title {
padding: 14px 24px;
color: rgba(30, 38, 51, 1);
font-size: 18px;
line-height: 26px;
font-weight: 550;
}
.line {
width: 1px;
height: 20px;
background-color: rgba(221, 225, 230, 1);
}
.tabs {
display: flex;
justify-content: flex-start;
align-items: center;
}
.tab {
margin-left: 24px;
font-size: 16px;
line-height: 24px;
color: rgba(138, 144, 153, 1);
border-bottom: 2px solid transparent;
padding: 14px 0;
cursor: pointer;
}
.activeTab {
color: rgba(19, 112, 255, 1);
border-bottom: 2px solid rgba(19, 112, 255, 1);
}
.content {
padding: 20px 24px;
height: calc(100% - 55px);
box-sizing: border-box;
}
import style from "./index.module.css";
import usePass from "@/hooks/usePass";
import UserResourcesEnvironment from "./UserResourcesEnvironment";
import { useMemo, useState } from "react";
import classNames from "classnames";
import Tabs from "@/components/mui/MyTabs";
import WorkflowOperator from "./WorkflowOperator";
const UserResources = () => {
const isPass = usePass();
const tabList = useMemo(() => {
return [
{
label: "工作流模版",
value: "USERRESOURCES_TEMPLATE",
component: <div />,
hide: !isPass("USERRESOURCES_TEMPLATE"),
},
{
label: "工作流算子",
value: "USERRESOURCES_FLOE",
component: <WorkflowOperator />,
hide: !isPass("USERRESOURCES_FLOE"),
},
{
label: "应用环境",
value: "USERRESOURCES_ENVIRONMENT",
component: <UserResourcesEnvironment />,
hide: !isPass("USERRESOURCES_ENVIRONMENT"),
},
];
}, [isPass]);
return (
<div className={style.userResources}>
<Tabs
title="个人资源"
tabList={tabList}
defaultValue={"USERRESOURCES_ENVIRONMENT"}
/>
</div>
);
};
export default UserResources;
.switchBatchFolw {
height: 100vh;
width: 50vh;
background-color: rgba(247, 248, 250, 1);
display: flex;
flex-direction: column;
}
.goBackBox {
box-sizing: border-box;
height: 110px;
padding: 64px 0 14px 25%;
line-height: 32px;
font-size: 18px;
color: #8a9099;
display: flex;
justify-content: flex-start;
align-items: center;
}
.goBackIcon {
width: 32px;
height: 32px;
background-color: #fff;
border-radius: 4px;
margin-right: 12px;
box-shadow: 0px 2px 5px 0px rgba(3, 47, 105, 0.09);
cursor: pointer;
}
.goBackText {
line-height: 32px;
font-size: 18px;
color: #8a9099;
}
.switchBox {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: flex-end;
position: relative;
}
.switchItem {
width: 100%;
position: relative;
padding-right: 44px;
display: flex;
flex-direction: column;
align-items: flex-end;
}
.activeSwitchItem {
padding-right: 34px;
}
.itemImg {
width: 58%;
cursor: pointer;
}
.itemImg:hover {
box-shadow: 0px 8px 20px -6px rgba(3, 47, 105, 0.14);
}
.activeImg {
width: 64%;
box-shadow: 0px 12px 30px -8px rgba(3, 47, 105, 0.18);
}
.activeImg:hover {
box-shadow: 0px 12px 30px -8px rgba(3, 47, 105, 0.18);
}
.arrow {
width: 0px;
height: 0px;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-right: 25px solid #fff;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}
import batchImg from "@/assets/resourceCenter/batchImg.svg";
import flowImg from "@/assets/resourceCenter/flowImg.svg";
import classNames from "classnames";
import goback from "@/assets/project/goback.svg";
import style from "./index.module.css";
type ISwitchBatchFolwProps = {
active: "BATCH" | "FLOW";
setActive: any;
goBack: any;
};
const SwitchBatchFolw = (props: ISwitchBatchFolwProps) => {
const { active, setActive, goBack } = props;
return (
<div className={style.switchBatchFolw}>
<div className={style.goBackBox}>
<img
className={style.goBackIcon}
src={goback}
alt=""
onClick={() => goBack()}
/>
<span className={style.goBackText}>返回</span>
</div>
<div className={style.switchBox}>
<div
className={classNames({
[style.switchItem]: true,
[style.activeSwitchItem]: active === "BATCH",
})}
>
<img
onClick={() => setActive("BATCH")}
className={classNames({
[style.itemImg]: true,
[style.activeImg]: active === "BATCH",
})}
src={batchImg}
alt=""
/>
{active === "BATCH" && <div className={style.arrow}></div>}
</div>
<div
className={classNames({
[style.switchItem]: true,
[style.activeSwitchItem]: active === "FLOW",
})}
>
<img
onClick={() => setActive("FLOW")}
className={classNames({
[style.itemImg]: true,
[style.activeImg]: active === "FLOW",
})}
src={flowImg}
alt=""
/>
{active === "FLOW" && <div className={style.arrow}></div>}
</div>
</div>
</div>
);
};
export default SwitchBatchFolw;
......@@ -2,10 +2,8 @@ import _ from "lodash";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import classNames from "classnames";
import QueueSelect from "@/components/BusinessComponents/QueueSelect";
import useMyRequest from "@/hooks/useMyRequest";
import { getHardwreList } from "@/api/project_api";
import { IQueueLi } from "@/components/BusinessComponents/QueueSelect";
import QueueSelect from "@/components/BusinessComponents/QueueSelect";
import {
ITask,
IParameter,
......@@ -21,7 +19,7 @@ import MyRadio from "@/components/mui/MyRadio";
import questionMark from "@/assets/project/questionMark.svg";
import fileSelectIcon from "@/assets/project/fileSelect.svg";
import MySwitch from "@/components/mui/MySwitch";
import Tabs from "@/components/mui/Tabs";
import Tabs from "@/components/mui/MyTabs";
import { getCustomTemplateParameterCheckResult } from "../../util";
import MyTooltip from "@/components/mui/MyTooltip";
import { useSize } from "ahooks";
......@@ -32,10 +30,21 @@ type IParameterSettingProps = {
templateConfigInfo: ITask[];
taskId: string;
setTemplateConfigInfo: any;
zoneId: string;
cpuList: Array<IQueueLi>;
gpuList: Array<IQueueLi>;
cpuLoading?: boolean;
gpuLoading?: boolean;
};
const ParameterSetting = (props: IParameterSettingProps) => {
const { templateConfigInfo, setTemplateConfigInfo, taskId, zoneId } = props; // 算子大数组
const {
templateConfigInfo,
setTemplateConfigInfo,
taskId,
cpuList,
gpuList,
cpuLoading = false,
gpuLoading = false,
} = props; // 算子大数组
const [isShowAllDese, setIsShowAllDese] = useState(false); // 是否展示全部描述
const [fileSelectOpen, setFileSelectOpen] = useState(false); // 选择输出路径的弹窗显示控制
const [fileSelectType, setFileSelectType] = useState<FileSelectType>("path");
......@@ -43,31 +52,6 @@ const ParameterSetting = (props: IParameterSettingProps) => {
const resizeRef = useRef<HTMLDivElement>(null);
const [activeParamsTab, setActiveParamsTab] = useState<string>("");
const [cpuList, setCpuList] = useState<Array<IQueueLi>>([]);
const [gpuList, setGpuList] = useState<Array<IQueueLi>>([]);
const { run: getHardwreListFn } = useMyRequest(getHardwreList, {
onSuccess: (res, params) => {
if (params[0].computeType === "CPU") {
setCpuList(res.data);
} else {
setGpuList(res.data);
}
},
});
useEffect(() => {
getHardwreListFn({
zoneId,
computeType: "CPU",
});
}, [getHardwreListFn, zoneId]);
useEffect(() => {
getHardwreListFn({
zoneId,
computeType: "GPU",
});
}, [getHardwreListFn, zoneId]);
const size = useSize(resizeRef);
// 文件夹路线选择器弹窗
......@@ -314,6 +298,8 @@ const ParameterSetting = (props: IParameterSettingProps) => {
error={parameter.error || false}
helperText={parameter.helperText}
disabled={parameter.parameterGroup === "out"}
cpuLoading={cpuLoading}
gpuLoading={gpuLoading}
></QueueSelect>
)}
{(parameter.domType || "").toLowerCase() === "input" && (
......
......@@ -11,7 +11,9 @@ import _ from "lodash";
import { useStores } from "@/store";
import { toJS } from "mobx";
import { observer } from "mobx-react-lite";
import useMyRequest from "@/hooks/useMyRequest";
import { getHardwreList } from "@/api/project_api";
import { IQueueLi } from "@/components/BusinessComponents/QueueSelect";
import MyPopconfirm from "@/components/mui/MyPopconfirm";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import MyButton from "@/components/mui/MyButton";
......@@ -22,7 +24,6 @@ import { useMessage } from "@/components/MySnackbar";
import { ITask } from "../Project/ProjectSubmitWork/interface";
import { fetchTemplateConfigInfo } from "@/api/project_api";
import { getCustomTemplateParameterCheckResult } from "./util";
import useMyRequest from "@/hooks/useMyRequest";
import CustomOperator from "../CustomOperator";
import SaveCustomTemplate from "./components/SaveCustomTemplate";
import AddIcon from "@mui/icons-material/Add";
......@@ -66,6 +67,39 @@ const WorkFlowEdit = observer((props: IProps) => {
// 确认弹窗标题
"返回后,当前页面已填写内容将不保存,确认返回吗?"
);
const [cpuList, setCpuList] = useState<Array<IQueueLi>>([]);
const [gpuList, setGpuList] = useState<Array<IQueueLi>>([]);
const { run: getCpuList, loading: cpuLoading } = useMyRequest(
getHardwreList,
{
onSuccess: (res) => {
setCpuList(res.data);
},
}
);
const { run: getGpuList, loading: gpuLoading } = useMyRequest(
getHardwreList,
{
onSuccess: (res) => {
setGpuList(res.data);
},
}
);
useEffect(() => {
zoneId &&
getCpuList({
zoneId,
computeType: "CPU",
});
}, [getCpuList, zoneId]);
useEffect(() => {
zoneId &&
getGpuList({
zoneId,
computeType: "GPU",
});
}, [getGpuList, zoneId]);
// 是否要监听删除时间
const listenState = useMemo(() => {
......@@ -247,7 +281,10 @@ const WorkFlowEdit = observer((props: IProps) => {
templateConfigInfo={templateConfigInfo}
setTemplateConfigInfo={setTemplateConfigInfo}
taskId={selectTaskId || ""}
zoneId={zoneId as string}
cpuList={cpuList}
gpuList={gpuList}
cpuLoading={cpuLoading}
gpuLoading={gpuLoading}
/>
)}
<div
......
const IconfontDemo = () => {
return (
<div>
IconfontDemo
<div style={{ fontSize: "50px", color: "red" }}>
<svg className="icon" aria-hidden="true">
<use xlinkHref="#icon-sousuo-223"></use>
</svg>
</div>
<div style={{ fontSize: "50px", color: "red" }}>
<svg className="icon" aria-hidden="true">
<use xlinkHref="#icon-dianzan"></use>
</svg>
</div>
<span
style={{ fontSize: "50px", color: "red" }}
className="iconfont icon-dianzan"
></span>
</div>
);
};
export default IconfontDemo;
import MyTableDemo from "./MyTableDemo";
import QueueSelectDemo from "./QueueSelectDemo";
import IconfontDemo from "./IconfontDemo";
import RadioGroupOfButtonStyle from "@/components/CommonComponents/RadioGroupOfButtonStyle";
import { useState } from "react";
import styles from "./index.module.css";
const Demo = () => {
const radioOptionsArr = [
{
value: "iconfont",
label: "iconfont",
},
{
value: "队列选择器",
label: "队列选择器",
......@@ -22,7 +27,7 @@ const Demo = () => {
const handleRadio = (e: string) => {
setSelectDemo(e);
};
const [selectDemo, setSelectDemo] = useState("队列选择器");
const [selectDemo, setSelectDemo] = useState("iconfont");
return (
<div className={styles.demoBox}>
......@@ -32,6 +37,7 @@ const Demo = () => {
handleRadio={handleRadio}
/>
<div className={styles.demoContentBox}>
{selectDemo === "iconfont" && <IconfontDemo></IconfontDemo>}
{selectDemo === "队列选择器" && <QueueSelectDemo></QueueSelectDemo>}
{selectDemo === "表格" && <MyTableDemo></MyTableDemo>}
{selectDemo === "box" && <div>box</div>}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment