测试 #810
|
|
@ -1,5 +1,5 @@
|
|||
<h3>前端react环境安装:</h3>
|
||||
<p>1、 安装node v6.9.x;此安装包含了node和npm。</p>
|
||||
<p>1、 安装node v14.12.3;此安装包含了node和npm。</p>
|
||||
<p>2、 安装cnpm(命令行): npm install -g cnpm --registry=https://registry.npm.taobao.org</p>
|
||||
<p>3、 安装依赖的js库(public/react目录下<即项目package.json所在目录>,开启命令行): cnpm install</p>
|
||||
<p>4、 如果你的ruby服务使用的是3000端口,则需要在package.json中修改"port"参数的值</p>
|
||||
|
|
@ -8,9 +8,4 @@
|
|||
|
||||
|
||||
<h3>分支信息:</h3>
|
||||
<p>相关代码提交到对应分支,能上线的代码先提交到develop分支上测试版,测试通过后合并提交到master分支上线正式版</p>
|
||||
<p>master:开发环境(正式环境)</p>
|
||||
<p>develop:测试环境</p>
|
||||
<p>dev_local:本地版本</p>
|
||||
<p>dev_chain:含有区块链相关内容的分支</p>
|
||||
<p>PS:新增加的需求功能先新建新分支开发,在测试版测试没问题后再分别合并到develop和master分支</p>
|
||||
<p>102:4000环境</p>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -21,6 +21,8 @@
|
|||
"code-prettify": "^0.1.0",
|
||||
"codemirror": "^5.64.0",
|
||||
"connected-react-router": "4.4.1",
|
||||
"core-js": "^3.34.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dompurify": "^2.3.3",
|
||||
"dotenv": "4.0.0",
|
||||
"dotenv-expand": "4.2.0",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,539 @@
|
|||
/* 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
@font-face {
|
||||
font-family: "iconfontColor"; /* Project id 4313222 */
|
||||
/* Color fonts */
|
||||
src:
|
||||
url('iconfont.woff2?t=1702282377802') format('woff2'),
|
||||
url('iconfont.woff?t=1702282377802') format('woff'),
|
||||
url('iconfont.ttf?t=1702282377802') format('truetype');
|
||||
}
|
||||
|
||||
.iconfontColor {
|
||||
font-family: "iconfontColor" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.iconcolor-a-zu1428:before {
|
||||
content: "\e6e4";
|
||||
}
|
||||
|
||||
.iconcolor-wenjianicon:before {
|
||||
content: "\e6e5";
|
||||
}
|
||||
|
||||
.iconcolor-biaotiicon:before {
|
||||
content: "\e6e6";
|
||||
}
|
||||
|
||||
.iconcolor-tuoguanicon:before {
|
||||
content: "\e6df";
|
||||
}
|
||||
|
||||
.iconcolor-zuicon:before {
|
||||
content: "\e6e1";
|
||||
}
|
||||
|
||||
.iconcolor-dailiicon:before {
|
||||
content: "\e6e3";
|
||||
}
|
||||
|
||||
.iconcolor-xuqiuicon:before {
|
||||
content: "\e6dd";
|
||||
}
|
||||
|
||||
.iconcolor-xiangmuliebiaoicon:before {
|
||||
content: "\e6e2";
|
||||
}
|
||||
|
||||
.iconcolor-renwuicon:before {
|
||||
content: "\e6de";
|
||||
}
|
||||
|
||||
.iconcolor-quexianicon:before {
|
||||
content: "\e6e0";
|
||||
}
|
||||
|
||||
.iconcolor-xuanzhong-daimakuicon:before {
|
||||
content: "\e6d4";
|
||||
}
|
||||
|
||||
.iconcolor-xuanzhong-wendangicon:before {
|
||||
content: "\e6d5";
|
||||
}
|
||||
|
||||
.iconcolor-xuanzhong-liushuixianicon:before {
|
||||
content: "\e6d6";
|
||||
}
|
||||
|
||||
.iconcolor-xuanzhong-xiangmuicon:before {
|
||||
content: "\e6d7";
|
||||
}
|
||||
|
||||
.iconcolor-xuanzhong-zhipinkuicon:before {
|
||||
content: "\e6d8";
|
||||
}
|
||||
|
||||
.iconcolor-xuanzhong-chengyuanicon:before {
|
||||
content: "\e6d9";
|
||||
}
|
||||
|
||||
.iconcolor-xuanzhong-shezhiicon:before {
|
||||
content: "\e6da";
|
||||
}
|
||||
|
||||
.iconcolor-xuanzhong-chanpinicon:before {
|
||||
content: "\e6db";
|
||||
}
|
||||
|
||||
.iconcolor-gongzuotaiicon:before {
|
||||
content: "\e6dc";
|
||||
}
|
||||
|
||||
.iconcolor-chanpinliebiaoicon:before {
|
||||
content: "\e6d3";
|
||||
}
|
||||
|
||||
.iconcolor-gengduoicon:before {
|
||||
content: "\e60b";
|
||||
}
|
||||
|
||||
.iconcolor-chengyuanicon:before {
|
||||
content: "\e6c1";
|
||||
}
|
||||
|
||||
.iconcolor-xuanzhong-gongzuotaiicon:before {
|
||||
content: "\e6c2";
|
||||
}
|
||||
|
||||
.iconcolor-wendangicon:before {
|
||||
content: "\e6b9";
|
||||
}
|
||||
|
||||
.iconcolor-xiangmuicon:before {
|
||||
content: "\e6b8";
|
||||
}
|
||||
|
||||
.iconcolor-zhipinkuicon:before {
|
||||
content: "\e6ba";
|
||||
}
|
||||
|
||||
.iconcolor-chanpinicon:before {
|
||||
content: "\e6bb";
|
||||
}
|
||||
|
||||
.iconcolor-shezhiicon:before {
|
||||
content: "\e6bc";
|
||||
}
|
||||
|
||||
.iconcolor-daimakuicon:before {
|
||||
content: "\e6bd";
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,212 @@
|
|||
{
|
||||
"id": "4313222",
|
||||
"name": "项目管理系统-color",
|
||||
"font_family": "iconfontColor",
|
||||
"css_prefix_text": "iconcolor-",
|
||||
"description": "项目管理系统彩色icon",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "38315554",
|
||||
"name": "组 1428",
|
||||
"font_class": "a-zu1428",
|
||||
"unicode": "e6e4",
|
||||
"unicode_decimal": 59108
|
||||
},
|
||||
{
|
||||
"icon_id": "38405284",
|
||||
"name": "文件icon",
|
||||
"font_class": "wenjianicon",
|
||||
"unicode": "e6e5",
|
||||
"unicode_decimal": 59109
|
||||
},
|
||||
{
|
||||
"icon_id": "38405285",
|
||||
"name": "标题icon",
|
||||
"font_class": "biaotiicon",
|
||||
"unicode": "e6e6",
|
||||
"unicode_decimal": 59110
|
||||
},
|
||||
{
|
||||
"icon_id": "38405286",
|
||||
"name": "托管icon",
|
||||
"font_class": "tuoguanicon",
|
||||
"unicode": "e6df",
|
||||
"unicode_decimal": 59103
|
||||
},
|
||||
{
|
||||
"icon_id": "38405289",
|
||||
"name": "组icon",
|
||||
"font_class": "zuicon",
|
||||
"unicode": "e6e1",
|
||||
"unicode_decimal": 59105
|
||||
},
|
||||
{
|
||||
"icon_id": "38405290",
|
||||
"name": "代理icon",
|
||||
"font_class": "dailiicon",
|
||||
"unicode": "e6e3",
|
||||
"unicode_decimal": 59107
|
||||
},
|
||||
{
|
||||
"icon_id": "37938701",
|
||||
"name": "需求icon",
|
||||
"font_class": "xuqiuicon",
|
||||
"unicode": "e6dd",
|
||||
"unicode_decimal": 59101
|
||||
},
|
||||
{
|
||||
"icon_id": "37938697",
|
||||
"name": "项目列表icon",
|
||||
"font_class": "xiangmuliebiaoicon",
|
||||
"unicode": "e6e2",
|
||||
"unicode_decimal": 59106
|
||||
},
|
||||
{
|
||||
"icon_id": "37938700",
|
||||
"name": "任务icon",
|
||||
"font_class": "renwuicon",
|
||||
"unicode": "e6de",
|
||||
"unicode_decimal": 59102
|
||||
},
|
||||
{
|
||||
"icon_id": "37938699",
|
||||
"name": "缺陷icon",
|
||||
"font_class": "quexianicon",
|
||||
"unicode": "e6e0",
|
||||
"unicode_decimal": 59104
|
||||
},
|
||||
{
|
||||
"icon_id": "37708678",
|
||||
"name": "选中-代码库icon",
|
||||
"font_class": "xuanzhong-daimakuicon",
|
||||
"unicode": "e6d4",
|
||||
"unicode_decimal": 59092
|
||||
},
|
||||
{
|
||||
"icon_id": "37708677",
|
||||
"name": "选中-文档icon",
|
||||
"font_class": "xuanzhong-wendangicon",
|
||||
"unicode": "e6d5",
|
||||
"unicode_decimal": 59093
|
||||
},
|
||||
{
|
||||
"icon_id": "37708675",
|
||||
"name": "选中-流水线icon",
|
||||
"font_class": "xuanzhong-liushuixianicon",
|
||||
"unicode": "e6d6",
|
||||
"unicode_decimal": 59094
|
||||
},
|
||||
{
|
||||
"icon_id": "37708676",
|
||||
"name": "选中-项目icon",
|
||||
"font_class": "xuanzhong-xiangmuicon",
|
||||
"unicode": "e6d7",
|
||||
"unicode_decimal": 59095
|
||||
},
|
||||
{
|
||||
"icon_id": "37708674",
|
||||
"name": "选中-制品库icon",
|
||||
"font_class": "xuanzhong-zhipinkuicon",
|
||||
"unicode": "e6d8",
|
||||
"unicode_decimal": 59096
|
||||
},
|
||||
{
|
||||
"icon_id": "37708673",
|
||||
"name": "选中-成员icon",
|
||||
"font_class": "xuanzhong-chengyuanicon",
|
||||
"unicode": "e6d9",
|
||||
"unicode_decimal": 59097
|
||||
},
|
||||
{
|
||||
"icon_id": "37708672",
|
||||
"name": "选中-设置icon",
|
||||
"font_class": "xuanzhong-shezhiicon",
|
||||
"unicode": "e6da",
|
||||
"unicode_decimal": 59098
|
||||
},
|
||||
{
|
||||
"icon_id": "37708671",
|
||||
"name": "选中-产品icon",
|
||||
"font_class": "xuanzhong-chanpinicon",
|
||||
"unicode": "e6db",
|
||||
"unicode_decimal": 59099
|
||||
},
|
||||
{
|
||||
"icon_id": "37708670",
|
||||
"name": "工作台icon",
|
||||
"font_class": "gongzuotaiicon",
|
||||
"unicode": "e6dc",
|
||||
"unicode_decimal": 59100
|
||||
},
|
||||
{
|
||||
"icon_id": "37708691",
|
||||
"name": "产品列表icon",
|
||||
"font_class": "chanpinliebiaoicon",
|
||||
"unicode": "e6d3",
|
||||
"unicode_decimal": 59091
|
||||
},
|
||||
{
|
||||
"icon_id": "1919171",
|
||||
"name": "菜单",
|
||||
"font_class": "gengduoicon",
|
||||
"unicode": "e60b",
|
||||
"unicode_decimal": 58891
|
||||
},
|
||||
{
|
||||
"icon_id": "37537539",
|
||||
"name": "成员icon",
|
||||
"font_class": "chengyuanicon",
|
||||
"unicode": "e6c1",
|
||||
"unicode_decimal": 59073
|
||||
},
|
||||
{
|
||||
"icon_id": "37537538",
|
||||
"name": "选中-工作台icon",
|
||||
"font_class": "xuanzhong-gongzuotaiicon",
|
||||
"unicode": "e6c2",
|
||||
"unicode_decimal": 59074
|
||||
},
|
||||
{
|
||||
"icon_id": "37537549",
|
||||
"name": "文档icon",
|
||||
"font_class": "wendangicon",
|
||||
"unicode": "e6b9",
|
||||
"unicode_decimal": 59065
|
||||
},
|
||||
{
|
||||
"icon_id": "37537546",
|
||||
"name": "项目icon",
|
||||
"font_class": "xiangmuicon",
|
||||
"unicode": "e6b8",
|
||||
"unicode_decimal": 59064
|
||||
},
|
||||
{
|
||||
"icon_id": "37537547",
|
||||
"name": "制品库icon",
|
||||
"font_class": "zhipinkuicon",
|
||||
"unicode": "e6ba",
|
||||
"unicode_decimal": 59066
|
||||
},
|
||||
{
|
||||
"icon_id": "37537540",
|
||||
"name": "产品icon",
|
||||
"font_class": "chanpinicon",
|
||||
"unicode": "e6bb",
|
||||
"unicode_decimal": 59067
|
||||
},
|
||||
{
|
||||
"icon_id": "37537545",
|
||||
"name": "设置icon",
|
||||
"font_class": "shezhiicon",
|
||||
"unicode": "e6bc",
|
||||
"unicode_decimal": 59068
|
||||
},
|
||||
{
|
||||
"icon_id": "37537544",
|
||||
"name": "代码库icon",
|
||||
"font_class": "daimakuicon",
|
||||
"unicode": "e6bd",
|
||||
"unicode_decimal": 59069
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -20,7 +20,6 @@
|
|||
<meta name="octolytics-dimension-repository_nwo" content="GitLink"></meta>
|
||||
<meta name="octolytics-dimension-repository_network_root_nwo" content="GitLink"></meta>
|
||||
<meta name="theme-color" content="#000000">
|
||||
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta name="twitter:image:src" content="https://www.gitlink.org.cn/images/logo.png">
|
||||
<meta name="twitter:site" content="@gitlink">
|
||||
|
|
@ -33,6 +32,7 @@
|
|||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/alex/alex.all.global.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/iconfont.css">
|
||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/iconColor/iconfont.css">
|
||||
<!-- <link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/edu-purge.css"> -->
|
||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/editormd.min.css">
|
||||
<!-- <link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/merge.css"> -->
|
||||
|
|
@ -45,8 +45,10 @@
|
|||
<div id="md_div" style="display: none;"></div>
|
||||
<div id="root" class="page -layout-v -fit widthunit"></div>
|
||||
<div id="picture_display" style="display: none;"></div>
|
||||
<script src="https://gw.alipayobjects.com/os/lib/react/16.14.0/umd/react.%REACT_URL%.js"></script>
|
||||
<script src="https://gw.alipayobjects.com/os/lib/react-dom/16.14.0/umd/react-dom.%REACT_URL%.js"></script>
|
||||
<!-- <script src="https://gw.alipayobjects.com/os/lib/react/16.14.0/umd/react.%REACT_URL%.js"></script>
|
||||
<script src="https://gw.alipayobjects.com/os/lib/react-dom/16.14.0/umd/react-dom.%REACT_URL%.js"></script> -->
|
||||
<script src="%PUBLIC_URL%js/react.%REACT_URL%.js"></script>
|
||||
<script src="%PUBLIC_URL%js/react-dom.%REACT_URL%.js"></script>
|
||||
<script src="%PUBLIC_URL%js/jquery-1.8.3.min.js"></script>
|
||||
<script src="%PUBLIC_URL%js/js_min_all.js"></script>
|
||||
<!-- <script src="%PUBLIC_URL%js/common.js"></script> -->
|
||||
|
|
@ -54,18 +56,18 @@
|
|||
<script src="%PUBLIC_URL%js/editormd/editormd.min.js"></script>
|
||||
<script src="%PUBLIC_URL%js/codemirror/merge/merge.js"></script>
|
||||
<script src="%PUBLIC_URL%js/alex/moment.js"></script>
|
||||
<script src="https://gw.alipayobjects.com/os/lib/alipay/alex/2.0.19/bundle/alex.all.global.min.js"></script>
|
||||
<!-- <script src="https://gw.alipayobjects.com/os/lib/alipay/alex/2.0.19/bundle/alex.all.global.min.js"></script> -->
|
||||
<meta name="viewport" content="">
|
||||
<%= htmlWebpackPlugin.tags.bodyTags %>
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?7e2def1fe918f15f9f1c5c061f69b256";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
// (function() {
|
||||
// var hm = document.createElement("script");
|
||||
// hm.src = "https://hm.baidu.com/hm.js?7e2def1fe918f15f9f1c5c061f69b256";
|
||||
// var s = document.getElementsByTagName("script")[0];
|
||||
// s.parentNode.insertBefore(hm, s);
|
||||
|
||||
})();
|
||||
// })();
|
||||
window.onload=function(){
|
||||
$(".newContainer").delegate("a.anchors","click",function(){
|
||||
let h = $(this).offset().top - 180;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
@import url(./font/font.css);
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
|||
33
src/App.js
33
src/App.js
|
|
@ -112,7 +112,7 @@ const Relaction = Loadable({
|
|||
loading: Loading,
|
||||
});
|
||||
const LoginRegisterPage = Loadable({
|
||||
loader: () => import("./modules/loginRegister/LoginRegisterPage"),
|
||||
loader: () => import("./modules/loginRegister/LoginRegisterPageNew"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
|
|
@ -140,10 +140,10 @@ const SoftBot = Loadable({
|
|||
loading: Loading,
|
||||
})
|
||||
|
||||
const WebIDE = Loadable({
|
||||
loader: () => import('./forge/Newfile/webIDE'),
|
||||
loading: Loading,
|
||||
});
|
||||
// const WebIDE = Loadable({
|
||||
// loader: () => import('./forge/Newfile/webIDE'),
|
||||
// loading: Loading,
|
||||
// });
|
||||
|
||||
const Badge = Loadable({
|
||||
loader: () => import('./forge/Badge/Index'),
|
||||
|
|
@ -159,8 +159,13 @@ const Topic = Loadable({
|
|||
loading: Loading,
|
||||
})
|
||||
|
||||
const Iframe = Loadable({
|
||||
loader: () => import("./forge/iframe"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
// 此处仅维护前端可能的一级路由,不用进行项目或者组织判断的字段。
|
||||
const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder", "glcc","bindlogin", "softbot","zone"];
|
||||
const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder", "glcc","bindlogin", "softbot","zone", "hiagent"];
|
||||
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
|
|
@ -333,9 +338,15 @@ class App extends Component {
|
|||
<MuiThemeProvider theme={theme}>
|
||||
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={() => this.Modifyloginvalue()}></LoginDialog>
|
||||
{/* <GlccModal /> */}
|
||||
{!pathName || (pathName && pathName.toLowerCase() !== 'glcc') ? <SiderBar {...this.props}/> : <SiderBarHelp/>}
|
||||
{/* {!pathName || (pathName && pathName.toLowerCase() !== 'glcc') ? <SiderBar {...this.props}/> : <SiderBarHelp/>} */}
|
||||
{/* <Router> */}
|
||||
<Switch>
|
||||
{/* iframe页面 */}
|
||||
<Route path="/hiagent"
|
||||
render={
|
||||
(props) => (<Iframe {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* wiki预览 */}
|
||||
<Route path="/:owner/:projectsId/wiki/preview/:projectName/:projectId" render={
|
||||
(props) => {
|
||||
|
|
@ -351,11 +362,11 @@ class App extends Component {
|
|||
} />
|
||||
|
||||
{/* webIDE */}
|
||||
<Route path="/:owner/:projectsId/webIDE/tree/:branchName"
|
||||
{/* <Route path="/:owner/:projectsId/webIDE/tree/:branchName"
|
||||
render={
|
||||
(props) => (<WebIDE {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
></Route> */}
|
||||
|
||||
{/* 项目PR */}
|
||||
<Route path="/:owner/:projectsId/compare"
|
||||
|
|
@ -443,10 +454,10 @@ class App extends Component {
|
|||
></Route>
|
||||
|
||||
{/* 忘记密码 */}
|
||||
<Route
|
||||
{/* <Route
|
||||
path="/resetPassword"
|
||||
render={(props) =><LoginRegisterPage {...this.props} {...props} mygetHelmetapi={mygetHelmetapi}/>}
|
||||
></Route>
|
||||
></Route> */}
|
||||
|
||||
{/* 关于我们 */}
|
||||
<Route
|
||||
|
|
|
|||
|
|
@ -66,6 +66,11 @@ export function initAxiosInterceptors(props) {
|
|||
return
|
||||
}
|
||||
const config = response.config;
|
||||
|
||||
if (response.data.status === 401) {
|
||||
window.location.href = "/login"
|
||||
}
|
||||
|
||||
if (response.data.status === -1) {
|
||||
if (window.location.pathname.startsWith('/tasks/')) {
|
||||
props.showSnackbar(response.data.message || '服务器异常,请联系管理员。')
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import CryptoJS from 'crypto-js';
|
||||
|
||||
export function isDev() {
|
||||
return window.location.port === "3007";
|
||||
}
|
||||
|
|
@ -6,3 +8,12 @@ export function isDev() {
|
|||
export const isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
|
||||
|
||||
// const isWeiXin = (/MicroMessenger/i.test(navigator.userAgent.toLowerCase()));
|
||||
|
||||
export function Encrypt(str){
|
||||
let result = CryptoJS.AES.encrypt(str,CryptoJS.enc.Utf8.parse('59c96c3572ab8cc1'),{
|
||||
iv:CryptoJS.enc.Utf8.parse('59c96c3572ab8cc1'),
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
})
|
||||
return result.toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,15 +6,11 @@ const { Search } = Input;
|
|||
const $ = window.$;
|
||||
const isDev = window.location.port == 3007;
|
||||
const isdev2= window.location.hostname ==='www.educoder.net'
|
||||
export const TEST_HOST = "https://testforgeplus.trustie.net/"
|
||||
export const TEST_HOST = "https://testforgeplus.trustie.net"
|
||||
export function getImageUrl(path) {
|
||||
// https://www.educoder.net
|
||||
// https://testbdweb.trustie.net
|
||||
// const local = 'http://localhost:3000'
|
||||
path && !path.startsWith('/') && !path.startsWith('http') && (path = '/'.concat(path));
|
||||
const local = 'https://testforgeplus.trustie.net';
|
||||
if (isDev) {
|
||||
return `${local}${path}`
|
||||
return `${TEST_HOST}${path}`
|
||||
}
|
||||
return `${path}`;
|
||||
}
|
||||
|
|
@ -35,14 +31,10 @@ export function IsPC(){
|
|||
}
|
||||
|
||||
export function getImageUrlAbsolute(path) {
|
||||
// https://www.educoder.net
|
||||
// https://testbdweb.trustie.net
|
||||
// const local = 'http://localhost:3000'
|
||||
path && !path.startsWith('/') && !path.startsWith('http') && (path = '/'.concat(path));
|
||||
const local = 'https://testforgeplus.trustie.net';
|
||||
const prod = window.location.origin;
|
||||
if (isDev) {
|
||||
return `${local}${path}`
|
||||
return `${TEST_HOST}${path}`
|
||||
}else{
|
||||
return `${prod}${path}`;
|
||||
}
|
||||
|
|
@ -295,13 +287,13 @@ export function turnbar(str){
|
|||
let s = str;
|
||||
if(s && s.length>0){
|
||||
if(s.indexOf("%")>-1){
|
||||
s = s.replaceAll('%','_25');
|
||||
s = s.replace(/%/g,'_25');
|
||||
}
|
||||
if(s.indexOf("#")>-1){
|
||||
s = s.replaceAll('#','%23');
|
||||
s = s.replace(/#/g,'%23');
|
||||
}
|
||||
if(s.indexOf("/")>-1){
|
||||
s = s.replaceAll('/','%2F');
|
||||
s = s.replace(/\//g,'%2F');
|
||||
}
|
||||
}
|
||||
return s;
|
||||
|
|
@ -310,13 +302,13 @@ export function returnbar(str){
|
|||
let s = str;
|
||||
if(s && s.length>0){
|
||||
if(str.indexOf("_25")>-1){
|
||||
s = s.replaceAll('_25','%');
|
||||
s = s.replace(/_25/g,'%');
|
||||
}
|
||||
if(s.indexOf("%23")>-1){
|
||||
s = s.replaceAll('%23','#');
|
||||
s = s.replace(/%23/g,'#');
|
||||
}
|
||||
if(s.indexOf("%2F")>-1){
|
||||
s = s.replaceAll('%2F','/');
|
||||
s = s.replace(/%2F/g,'/');
|
||||
}
|
||||
}
|
||||
return s;
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ export default ({
|
|||
for(var x=0;x<issues.length;x++){
|
||||
let item = issues[x];
|
||||
let content = item.id ? `<a href="`+`/${owner}/${projectsId}/issues/${item.project_issues_index}`+`">#${item.project_issues_index}:${item.subject}</a>` : `<span>#${item.project_issues_index}(已删除)</span>`;
|
||||
rs = rs.replaceAll(`<a href="`+`/${owner}/${projectsId}/issues/${item.project_issues_index}`+`">#${item.project_issues_index}</a>`,content);
|
||||
rs = rs.replace(new RegExp(`<a href="/${owner}/${projectsId}/issues/${item.project_issues_index}">#${item.project_issues_index}</a>`, 'g'), content);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +102,9 @@ export default ({
|
|||
return renderToString(_unescape(expression) || '', { displayMode: type === 'block', throwOnError: false, output: 'html' })
|
||||
})
|
||||
rs = dompurify.sanitize(rs.replace(/▁/g, "▁▁▁"))
|
||||
rs = rs.replaceAll('<img ', `<img onerror="javascript:this.src='${ imgError }';"`)
|
||||
rs = rs.replace(/<img\s+/g, function(match) {
|
||||
return match + `onerror="javascript:this.src='${imgError}';" `;
|
||||
});
|
||||
resetMathExpressions()
|
||||
return rs
|
||||
}, [str,issues]);
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,5 @@
|
|||
/* 导航栏 */
|
||||
@font-face {
|
||||
font-family: "YouSheBiaoTiHei";
|
||||
src: url('./YouSheBiaoTiHei-2.ttf');
|
||||
}
|
||||
Binary file not shown.
|
|
@ -1,6 +1,7 @@
|
|||
.aboutPanels{
|
||||
max-width: 1200px;
|
||||
margin:0px auto;
|
||||
// max-width: 1200px;
|
||||
// margin:0px auto;
|
||||
padding:0px 20px;
|
||||
.aboutContent{
|
||||
border-radius: 2px;
|
||||
// border: 1px solid #EEEEEE;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React, { Component } from 'react';
|
|||
import { Link } from 'react-router-dom';
|
||||
import './activity.css';
|
||||
import { getImageUrl } from 'educoder';
|
||||
import { truncateCommitId } from "../common/util";
|
||||
|
||||
|
||||
class ActivityItem extends Component {
|
||||
|
|
@ -25,9 +26,16 @@ class ActivityItem extends Component {
|
|||
<span className="activity_type">{item.trend_type}</span>
|
||||
</p >
|
||||
:
|
||||
// 如果是commit--CommitLog
|
||||
item.trend_type === "CommitLog" ?
|
||||
<p className="itemLine">
|
||||
<Link to={`/${owner}/${projectsId}/commits/${item.commit_log && truncateCommitId(item.commit_log.commit_id)}`} className="font-16">{item.name}</Link>
|
||||
<span className="activity_type">{item.trend_type}</span>
|
||||
</p >
|
||||
:
|
||||
// 如果是合并请求
|
||||
<p className="itemLine">
|
||||
<Link to={`/${owner}/${projectsId}/pulls/${item.trend_id}`} className="font-16">{item.name}</Link>
|
||||
<Link to={`/${item.project && item.project.owner&& item.project.owner.login}/${item.project && item.project.identifier}/pulls/${item.trend_id}`} className="font-16">{item.name}</Link>
|
||||
<span className="activity_type">{item.trend_type}</span>
|
||||
</p >
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@
|
|||
padding-bottom: 20px!important;
|
||||
}
|
||||
.contentBox{
|
||||
width: 1200px;
|
||||
margin:0px auto;
|
||||
/* width: 1200px;
|
||||
margin:0px auto; */
|
||||
padding:0px 20px;
|
||||
}
|
||||
.pageDIV{
|
||||
text-align: center;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { Link } from 'react-router-dom';
|
|||
|
||||
/**
|
||||
* nav:{list:[],active:0} */
|
||||
export default(({ header , nav })=>{
|
||||
export default(({ header , nav, history })=>{
|
||||
return(
|
||||
<ul className="list-l-Menu">
|
||||
{header}
|
||||
|
|
@ -13,11 +13,11 @@ export default(({ header , nav })=>{
|
|||
return(
|
||||
!item.hide &&<li key={key} className={nav.active === key?"active":''}>
|
||||
<p>
|
||||
<Link to={item.href}>
|
||||
<a onClick={()=>{ item.href.indexOf("https") !== -1 ? window.location.href = item.href : history.push(item.href)}}>
|
||||
{item.icon && <i className={`iconfont ${item.icon || 'icon-huabanfuben'} font-18 mr10`}></i>}
|
||||
{item.img && <img src={item.img} alt="" width="20px" className="mr10"/>}
|
||||
{item.name}
|
||||
</Link>
|
||||
</a>
|
||||
</p>
|
||||
</li>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,20 +3,19 @@ import AccountProfile from "../../modules/user/AccountProfile";
|
|||
import { getImageUrl } from 'educoder'
|
||||
import axios from 'axios';
|
||||
import cookie from 'react-cookies';
|
||||
import { notification , Dropdown ,Popover, Menu,Badge } from 'antd';
|
||||
import { notification , Dropdown , Menu , Icon } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import LoginDialog from '../../modules/login/LoginDialog';
|
||||
import HeadSearch from '../Component/HeadSearch';
|
||||
import { getOrzCompanyList } from '../../forge/Information/api';
|
||||
|
||||
import AddProjectModal from './AddProjectModal';
|
||||
import '../../modules/tpm/TPMIndex.css';
|
||||
import CheckProfile from '../Component/ProfileModal/Profile';
|
||||
import logo from './img/logo.png'
|
||||
|
||||
import './header.scss';
|
||||
import NoticeContent from './NoticeContent';
|
||||
import MainLogo from './img/logo.png';
|
||||
// TODO 这部分脚本从公共脚本中直接调用
|
||||
const { SubMenu } = Menu
|
||||
|
||||
window._header_componentHandler = null;
|
||||
// 非trustie链接则新开页跳转
|
||||
|
|
@ -47,6 +46,7 @@ class NewHeader extends Component {
|
|||
visible:false, //浮动消息框展示控制
|
||||
showSubMenu: false,
|
||||
zoneList: [], // 专区列表
|
||||
companyList:[] //已开通工作台列表
|
||||
}
|
||||
}
|
||||
componentDidMount() {
|
||||
|
|
@ -60,6 +60,7 @@ class NewHeader extends Component {
|
|||
window._header_componentHandler = this;
|
||||
|
||||
this.getZoneList(settings && settings.common.zone +'/api')
|
||||
this.getComlist();
|
||||
|
||||
try {
|
||||
window.sessionStorage.setItem("yslgeturls", JSON.stringify(window.location.href))
|
||||
|
|
@ -101,8 +102,8 @@ class NewHeader extends Component {
|
|||
//退出账号
|
||||
var url = `/accounts/logout.json`;
|
||||
axios.get((url)).then((result) => {
|
||||
if (result !== undefined) {
|
||||
window.location.href = "/";
|
||||
if (result) {
|
||||
this.props.history.push("/login");
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
|
|
@ -267,11 +268,18 @@ class NewHeader extends Component {
|
|||
}
|
||||
|
||||
renderMenu=(personal)=>{
|
||||
const { current_user } = this.props;
|
||||
const { mygetHelmetapi } = this.props;
|
||||
const { companyList } = this.state;
|
||||
return(
|
||||
<Menu className="currentMenu">
|
||||
<Menu.Item>
|
||||
{/* <Menu.Item>
|
||||
<span className="currentName" title={current_user && current_user.username}>{current_user && current_user.username}</span>
|
||||
</Menu.Item> */}
|
||||
{/* <Menu.Item>
|
||||
<a href={`/${this.props.current_user && this.props.current_user.login}`}>首页</a>
|
||||
</Menu.Item> */}
|
||||
<Menu.Item>
|
||||
<a href={`/${this.props.current_user && this.props.current_user.login}`}>代码库主页</a>
|
||||
</Menu.Item>
|
||||
{
|
||||
personal && personal.length > 0 && personal.map((item,key)=>{
|
||||
|
|
@ -280,8 +288,19 @@ class NewHeader extends Component {
|
|||
)
|
||||
})
|
||||
}
|
||||
{/* <li><Link to={`/settings/profile`}>设置</Link></li> */}
|
||||
<Menu.Item><a onClick={() => this.educoderloginysl()}>退出</a></Menu.Item>
|
||||
|
||||
<SubMenu title={<span>我的工作台<Icon type="right" /></span>} Icon={null} popupClassName='subMyworkList'>
|
||||
{
|
||||
companyList && companyList.length>0 ?
|
||||
companyList.map((i,k)=>{
|
||||
return(
|
||||
<Menu.Item><a href={`${ mygetHelmetapi && mygetHelmetapi.common.zone }/${i.enterpriseIdentifier}`} target='_blank'>{i.enterpriseName}</a></Menu.Item>
|
||||
)
|
||||
})
|
||||
:<span>暂无工作台</span>
|
||||
}
|
||||
</SubMenu>
|
||||
<Menu.Item><a onClick={() => this.educoderloginysl()}>退出登录</a></Menu.Item>
|
||||
</Menu>
|
||||
)
|
||||
}
|
||||
|
|
@ -290,6 +309,16 @@ class NewHeader extends Component {
|
|||
this.setState({ visible });
|
||||
};
|
||||
|
||||
getComlist=()=>{
|
||||
getOrzCompanyList().then(res=>{
|
||||
if(res){
|
||||
this.setState({
|
||||
companyList:res.data.rows
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { resetUserInfo ,showNotification,publicNav,mygetHelmetapi} = this.props;
|
||||
let settings = mygetHelmetapi;
|
||||
|
|
@ -306,6 +335,10 @@ class NewHeader extends Component {
|
|||
return (
|
||||
<div className={publicNav ? `newHeaders publicNav`:`newHeaders`} id="nHeader">
|
||||
<div className="headerContent">
|
||||
<div className="titleByHead">
|
||||
<img src={logo} alt="" style={{width: '32px'}} />
|
||||
<span className='font32 ml15'>{mygetHelmetapi && mygetHelmetapi.name}</span>
|
||||
</div>
|
||||
{isRender === true ?
|
||||
<LoginDialog
|
||||
{...this.props}
|
||||
|
|
@ -319,24 +352,15 @@ class NewHeader extends Component {
|
|||
{...this.props}
|
||||
{...this.state}
|
||||
/> : ""}
|
||||
<div style={{width:"78px"}}>
|
||||
{
|
||||
publicNav &&
|
||||
<a href={'https://www.ccf.org.cn/'} className={"fl"}>
|
||||
<img src={MainLogo} alt="ccf" width="63px"/>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
{
|
||||
{/* {
|
||||
settings && settings.nav_logo_url ?
|
||||
<a href={settings && settings.new_course.default_url} className={"fl mr30"}>
|
||||
<img alt="可控开源社区" className="logoimg" src={getImageUrl(`/${settings.nav_logo_url}`)}></img>
|
||||
</a>
|
||||
:
|
||||
""
|
||||
}
|
||||
{/* <div className="head-nav pr"> */}
|
||||
{
|
||||
} */}
|
||||
{/*{
|
||||
settings && settings.navbar && settings.navbar.length > 0 ?
|
||||
<ul id="header-nav" className="head-nav pr">
|
||||
{
|
||||
|
|
@ -373,21 +397,20 @@ class NewHeader extends Component {
|
|||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
: ""
|
||||
}
|
||||
{/* </div> */}
|
||||
<div className="head-right">
|
||||
{ search_url && <HeadSearch {...this.props}/>}
|
||||
{
|
||||
}*/}
|
||||
{/*<div className="head-right">
|
||||
{ search_url && <HeadSearch {...this.props}/>} */}
|
||||
{/* {
|
||||
current_user && (current_user.main_site || current_user.login) && (settings && settings.add && settings.add.length>0)?
|
||||
<Dropdown overlay={this.addMenu(settings && settings.add)} placement="bottomRight">
|
||||
<img src={require(`./img/add.png`)} alt="" width="16px" className="mr15 ml30"/>
|
||||
</Dropdown>:""
|
||||
}
|
||||
} */}
|
||||
|
||||
{ (settings && settings.common && settings.common.notice) && (current_user && current_user.login)?
|
||||
{/* { (settings && settings.common && settings.common.notice) && (current_user && current_user.login)?
|
||||
<Popover
|
||||
overlayClassName="notice-popover"
|
||||
placement={`bottomRight`}
|
||||
|
|
@ -403,11 +426,11 @@ class NewHeader extends Component {
|
|||
</Link>
|
||||
</Popover>
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>*/}
|
||||
{!user || (user && !user.login) ?
|
||||
<span className="font-15 ml30">
|
||||
<a onClick={() => this.educoderlogin()} className="mr5 color-white">登录</a>
|
||||
<Link to="/login" className="mr5 color-white">登录</Link>
|
||||
{
|
||||
(settings && settings.common && settings.common.register) ?
|
||||
publicNav ?
|
||||
|
|
@ -419,9 +442,7 @@ class NewHeader extends Component {
|
|||
</span>
|
||||
:
|
||||
<Dropdown placement={`bottomRight`} overlay={this.renderMenu(settings && settings.personal)}>
|
||||
<a href={`/${this.props.current_user && this.props.current_user.login}`}>
|
||||
<img alt="头像" src={getImageUrl(`/${user.image_url}`)} className="currentImg"></img>
|
||||
</a>
|
||||
<img alt="头像" src={getImageUrl(`/${user.image_url}`)} className="currentImg"></img>
|
||||
</Dropdown>
|
||||
}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,30 @@
|
|||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.subMyworkList {
|
||||
li{
|
||||
&:hover{
|
||||
background-color: #4cacff;
|
||||
a{color: #fff!important;}
|
||||
}
|
||||
a{
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
max-width: 150px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
padding:0px 12px;
|
||||
}
|
||||
}
|
||||
span{
|
||||
display: block;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding:0px 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-dropdown-menu.currentMenu{
|
||||
width: 120px;
|
||||
text-align: center;
|
||||
|
|
@ -38,6 +62,21 @@
|
|||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
}
|
||||
.ant-dropdown-menu-submenu .ant-dropdown-menu-submenu-title{
|
||||
height: 100%;
|
||||
line-height: 40px;
|
||||
padding: 0px 10px;
|
||||
&:hover{
|
||||
background: #829BFF;
|
||||
color: #fff;
|
||||
}
|
||||
i{
|
||||
margin-right: 0px;
|
||||
}
|
||||
}
|
||||
.ant-dropdown-menu-submenu-arrow{
|
||||
display: none;
|
||||
}
|
||||
li{
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 3.1 KiB |
|
|
@ -252,4 +252,44 @@ export function updateMyResource(data) {
|
|||
method: 'PUT',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/** 非专区接口,组织工作台相关 */
|
||||
// 获取已开通企业的组织列表
|
||||
export function getOrzCompanyList(){
|
||||
return fetch({
|
||||
url:`/pms/pmsEnterprise/myList`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
// 查询组织是否开通企业
|
||||
export function checkOpenedEnterprise(orgId){
|
||||
return fetch({
|
||||
url:`/pms/pmsEnterprise/${orgId}/workbenchUrl`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
// 组织升级为企业
|
||||
export function createEnterpriseByGitlinkOrgId(orgId, data) {
|
||||
return fetch({
|
||||
url: `/pms/pmsEnterprise/createByGitlinkOrgId/${orgId}`,
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 可选角色列表
|
||||
export function getRoleList(){
|
||||
return fetch({
|
||||
url:`/pms/pmsEnterprise/roleList`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
// 获取工作台初始用户列表
|
||||
export function getUserList(orgId){
|
||||
return fetch({
|
||||
url:`/pms/pmsEnterprise/gitlinkUserList/${orgId}`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
import axios from 'axios';
|
||||
import cookie from 'react-cookies';
|
||||
import { message , notification } from 'antd';
|
||||
import { TokenKey } from '../javaFetch';
|
||||
|
||||
function beforeFetch(actionUrl){
|
||||
if (window.location.href.indexOf('localhost') < 0) {
|
||||
|
|
@ -11,6 +13,15 @@ function beforeFetch(actionUrl){
|
|||
timeout: 1800000, // 请求超时时间
|
||||
});
|
||||
|
||||
service.interceptors.request.use(config => {
|
||||
if (cookie.load(TokenKey)) {
|
||||
config.headers['Authorization'] = cookie.load(TokenKey); // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||
}
|
||||
return config;
|
||||
}, error => {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
service.interceptors.response.use(
|
||||
response => {
|
||||
const res = response||{};
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import Nodata from '../Nodata';
|
|||
import Invite from './sub/Invite';
|
||||
import CheckProfile from '../Component/ProfileModal/Profile';
|
||||
import RenderHtml from '../../components/render-html';
|
||||
import imNoneImg from './img/importNone.png';
|
||||
/**
|
||||
* projectDetail.type:0是托管项目,1是镜像项目,2是同步镜像项目(为2时不支持在线创建、在线上传、在线修改、在线删除、创建合并请求等功能)
|
||||
*/
|
||||
|
|
@ -399,7 +400,7 @@ function CoderDepot(props){
|
|||
<WhiteBack>
|
||||
{mirror_status ===0 && <UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} topicsInfo={topics} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/> }
|
||||
<Spin spinning={isSpin}>
|
||||
{
|
||||
{/* {
|
||||
((dirInfo || fileInfo) && mirror_status===0 ) &&
|
||||
<React.Fragment>
|
||||
<DrawerPanel
|
||||
|
|
@ -417,10 +418,27 @@ function CoderDepot(props){
|
|||
<span>目录</span>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
} */}
|
||||
<div style={{minHeight:"500px"}}>
|
||||
{
|
||||
projectDetail && mirror_status === 2 &&
|
||||
<div className='importFailTip'>
|
||||
<img src={imNoneImg} alt="" width={325}/>
|
||||
{
|
||||
projectDetail.permission && ["Manager","Admin","Owner"].includes(projectDetail.permission) ?
|
||||
<div className='failInfo'>
|
||||
<p className='font-18 weight500 color-grey-3'>导入项目失败,可能存在以下原因:</p>
|
||||
<li>1、导入的仓库 URL 错误。</li>
|
||||
<li>2、您需要导入的可能是一个您无权访问的私有仓库,需要输入授权验证仓库的帐号、密码(或者个人令牌),此信息仅用于本次代码同步,不做任何记录。</li>
|
||||
<p className='font-18 weight500 color-grey-3'>请前往 <Link className='color-blue' to={`/${owner}/${projectsId}/settings`}>仓库设置</Link> 删除本项目后重新导入!</p>
|
||||
</div>
|
||||
:
|
||||
<p>导入项目失败,请联系管理员重新导入!</p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
{
|
||||
projectDetail &&
|
||||
projectDetail && mirror_status === 0 &&
|
||||
<Box className="Panels">
|
||||
<LongWidth>
|
||||
<div className="panelmenu">
|
||||
|
|
@ -493,10 +511,10 @@ function CoderDepot(props){
|
|||
baseOperate &&
|
||||
<CheckProfile {...props} sureFunc={compare}>+ 合并请求</CheckProfile>
|
||||
}
|
||||
{
|
||||
{/* {
|
||||
issuesFlag &&
|
||||
<CheckProfile {...props} sureFunc={createIssue} checklogin>+ 疑修</CheckProfile>
|
||||
}
|
||||
} */}
|
||||
|
||||
</div>
|
||||
{ fileOperate &&
|
||||
|
|
@ -509,12 +527,12 @@ function CoderDepot(props){
|
|||
<a>文件 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-grey-6 mr-5"></i></a>
|
||||
</Dropdown>
|
||||
}
|
||||
{
|
||||
{/* {
|
||||
checkIfLogin && checkIfLogin()?
|
||||
<a className='newBtn' onClick={()=>eventTrack(`/${owner}/${projectsId}/webIDE/tree/${branchName||defaultBranch}`)}>Web IDE <div className='newBtnImg'></div></a>
|
||||
:
|
||||
<a className='newBtn' onClick={()=>{showLoginDialog(`/${owner}/${projectsId}`)}}>Web IDE <div className='newBtnImg'></div></a>
|
||||
}
|
||||
} */}
|
||||
|
||||
<Dropdown overlay={downloadMenu} placement="bottomRight" trigger={['click']}>
|
||||
<Button type={'primary'}>下载 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-white mr-3"></i></Button>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ class CoderRootFileDetail extends Component {
|
|||
description: props.detail.replace_content,
|
||||
menuList:undefined,
|
||||
replaceVisible:false,
|
||||
loading:false
|
||||
loading:false,
|
||||
random:0,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -140,6 +141,12 @@ class CoderRootFileDetail extends Component {
|
|||
EditFile = (flag) => {
|
||||
const { onEdit } = this.props;
|
||||
onEdit && onEdit(flag);
|
||||
if(flag){
|
||||
let num = Math.random();
|
||||
this.setState({
|
||||
random:num
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
DownLoadFile = (url) => {
|
||||
|
|
@ -272,7 +279,7 @@ class CoderRootFileDetail extends Component {
|
|||
} = this.props;
|
||||
// 文件只读状态
|
||||
const readOnly = this.props.history.location.search.indexOf('edit') === -1
|
||||
const { language, languages, description , replaceVisible , loading } = this.state;
|
||||
const { language, languages, description , replaceVisible , loading , random } = this.state;
|
||||
let flag = current_user && current_user.login && (isManager || isDeveloper);
|
||||
const Option = Select.Option;
|
||||
return (
|
||||
|
|
@ -395,6 +402,7 @@ class CoderRootFileDetail extends Component {
|
|||
filepath={`/${detail.path}`}
|
||||
content={detail.content}
|
||||
readOnly={readOnly}
|
||||
random={random}
|
||||
md={md}
|
||||
editorType="update"
|
||||
currentBranch={currentBranch}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Spin, Tooltip } from 'antd';
|
||||
import { Button, Spin, Tooltip } from 'antd';
|
||||
import { Link, Route, Switch } from 'react-router-dom';
|
||||
import { withRouter } from "react-router";
|
||||
import { Content, AlignTop } from '../Component/layout';
|
||||
|
|
@ -263,7 +263,9 @@ class Detail extends Component {
|
|||
mirror_status:2,
|
||||
firstSync: false
|
||||
})
|
||||
this.deleteProjectBack();
|
||||
this.getBanner();
|
||||
this.getDetail();
|
||||
// this.deleteProjectBack();
|
||||
} else {
|
||||
this.setState({
|
||||
firstSync: false,
|
||||
|
|
@ -309,9 +311,10 @@ class Detail extends Component {
|
|||
this.props.showNotification("镜像同步成功!");
|
||||
window.location.reload();
|
||||
} else {
|
||||
if (data.project && data.project.mirror_status === 2) {
|
||||
this.deleteProjectBack();
|
||||
}
|
||||
// 导入失败仓库用户自主
|
||||
// if (data.project && data.project.mirror_status === 2) {
|
||||
// this.deleteProjectBack();
|
||||
// }
|
||||
this.getDetail();
|
||||
this.getBanner();
|
||||
}
|
||||
|
|
@ -341,22 +344,22 @@ class Detail extends Component {
|
|||
}
|
||||
|
||||
|
||||
deleteProjectBack = () => {
|
||||
const { history } = this.props;
|
||||
const { projectsId, owner } = this.props.match.params;
|
||||
axios.delete(`/${owner}/${projectsId}.json`).then(res => {
|
||||
let hash = '/projects/mirror/new';
|
||||
if (res && res.data) {
|
||||
history.push({
|
||||
pathname: hash,
|
||||
mirror_status: 2
|
||||
});
|
||||
}
|
||||
else {
|
||||
window.location.hash = hash;
|
||||
}
|
||||
});
|
||||
}
|
||||
// deleteProjectBack = () => {
|
||||
// const { history } = this.props;
|
||||
// const { projectsId, owner } = this.props.match.params;
|
||||
// axios.delete(`/${owner}/${projectsId}.json`).then(res => {
|
||||
// let hash = '/projects/mirror/new';
|
||||
// if (res && res.data) {
|
||||
// history.push({
|
||||
// pathname: hash,
|
||||
// mirror_status: 2
|
||||
// });
|
||||
// }
|
||||
// else {
|
||||
// window.location.hash = hash;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
getDetail = () => {
|
||||
const { projectsId, owner } = this.props.match.params;
|
||||
|
|
@ -537,7 +540,26 @@ class Detail extends Component {
|
|||
</div> : ""
|
||||
}
|
||||
|
||||
|
||||
// 删除仓库
|
||||
deleteProject = () => {
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const { projectName } = this.state;
|
||||
this.props.confirm({
|
||||
content: <span style={{display:"block",textAlign:"left"}}>该操作无法撤销!且将会一并删除相关的疑修、合并请求、工作流、里程碑、动态等数据。<br/>是否确认删除 <span style={{fontWeight:"bold"}}>{owner}/{projectName}({projectsId})</span>?</span>,
|
||||
onOk: () => {
|
||||
const url = `/${owner}/${projectsId}.json`;
|
||||
axios.delete(url).then((result) => {
|
||||
window.scrollTo(0,0);
|
||||
this.props.showNotification("仓库删除成功!");
|
||||
this.props.history.push(`/${owner}`);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { projectDetail, watchers_count, praises_count,
|
||||
forked_count, firstSync, secondSync,
|
||||
|
|
@ -679,6 +701,9 @@ class Detail extends Component {
|
|||
firstSync &&
|
||||
<Content className="spincontent">
|
||||
<Spin className="spinstyle" tip={project && `正在从 ${project.mirror_url} 迁移`} size="large" />
|
||||
<Button className="red_deleteBtn mt30" onClick={this.deleteProject}>
|
||||
删除本仓库
|
||||
</Button>
|
||||
</Content>
|
||||
}
|
||||
<Spin spinning={secondSync && !firstSync} className="spinstyle" tip="正在同步镜像" size="large">
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import React, { useEffect, useState , useRef } from "react";
|
||||
import styled from "styled-components";
|
||||
import { Button ,Spin } from "antd";
|
||||
import { timeFormat, truncateCommitId } from '../common/util';
|
||||
|
|
@ -57,6 +57,24 @@ export default (props) => {
|
|||
const [isSpin, setIsSpin] = useState(true);
|
||||
const { sha , projectsId, owner } = match.params;
|
||||
|
||||
const [ dropLoading, setDropLoading] = useState(false); //加载loading
|
||||
const limit = 100;
|
||||
const fRef = useRef();
|
||||
|
||||
useEffect(()=>{
|
||||
window.addEventListener("scroll",scrollListener);
|
||||
return ()=>{window.removeEventListener("scroll",scrollListener);}
|
||||
},[])
|
||||
|
||||
const scrollListener=()=>{
|
||||
let scrollHeight = document.documentElement.scrollHeight;
|
||||
let clientHeight = document.documentElement.clientHeight;
|
||||
let scrollTop = document.documentElement.scrollTop;
|
||||
if(Math.ceil(scrollTop+clientHeight) >= scrollHeight-5){
|
||||
InitDiffData();
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
if(projectDetail){
|
||||
const { author, name} = projectDetail;
|
||||
|
|
@ -66,17 +84,18 @@ export default (props) => {
|
|||
|
||||
useEffect(() => {
|
||||
if (projectsId && owner && sha) {
|
||||
InitDiffData();
|
||||
|
||||
const url = `/${owner}/${projectsId}/commits/${sha}.json`;
|
||||
axios
|
||||
.get(url)
|
||||
.then(result => {
|
||||
if (result) {
|
||||
setData(result.data);
|
||||
// setData(result.data);
|
||||
setCommit(result.data.commit);
|
||||
setParents(result.data.parents);
|
||||
setCommitter(result.data.committer || (result.data.commit && result.data.commit.committer));
|
||||
setIsSpin(false);
|
||||
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
|
|
@ -84,6 +103,28 @@ export default (props) => {
|
|||
});
|
||||
}
|
||||
}, [projectsId , owner, sha]);
|
||||
|
||||
async function InitDiffData (){
|
||||
let f = fRef.current ? fRef.current.files : [];
|
||||
let p = fRef.current ? fRef.current.page : 1;
|
||||
let hm = fRef.current ? fRef.current.hasMore : true;
|
||||
if (!hm || dropLoading || !isSpin) {
|
||||
return;
|
||||
}
|
||||
setDropLoading(true);
|
||||
const url = `/v1/${owner}/${projectsId}/commits/${sha}/files.json`;
|
||||
await axios.get(url,{
|
||||
params:{page:p,limit}
|
||||
}).then(res=>{
|
||||
if(res && res.status === 200){
|
||||
let arr = p === 1 ? res.data.files : [...f,...res.data.files];
|
||||
setData(res.data);
|
||||
fRef.current = {files:arr,page:p+1,hasMore:arr.length === limit};
|
||||
setDropLoading(false);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="main" style={{padding:"0px",border:"none"}}>
|
||||
<Spin spinning={isSpin}>
|
||||
|
|
@ -132,10 +173,13 @@ export default (props) => {
|
|||
<Files
|
||||
history={history}
|
||||
data={data}
|
||||
filesData={fRef.current && fRef.current.files}
|
||||
owner={owner}
|
||||
projectsId={projectsId}
|
||||
parentsSha={parents && parents.length > 0 && parents[0].sha}
|
||||
mergeId={`commits/${sha}`}
|
||||
/>
|
||||
{ dropLoading && <p style={{textAlign:"center",color:"#999",padding:"10px"}}>文件加载中...</p>}
|
||||
</Spin>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -119,7 +119,8 @@
|
|||
}
|
||||
// coderDepot
|
||||
.Panels{
|
||||
max-width: 1200px;
|
||||
// max-width: 1200px;
|
||||
padding:0px 20px;
|
||||
margin: 0 auto;
|
||||
.panelmenu{
|
||||
padding-top:20px;
|
||||
|
|
@ -501,8 +502,9 @@
|
|||
}
|
||||
}
|
||||
.coderSubPage{
|
||||
width: 1200px;
|
||||
margin:0px auto;
|
||||
// width: 1200px;
|
||||
// margin:0px auto;
|
||||
padding:0px 20px;
|
||||
}
|
||||
.griditemAnchor{
|
||||
margin-left: 0px!important;
|
||||
|
|
@ -551,4 +553,27 @@
|
|||
|
||||
.replaceStyle{
|
||||
height: 140px!important;
|
||||
}
|
||||
}
|
||||
|
||||
.importFailTip{
|
||||
height: 500px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
font-weight: 400;
|
||||
font-size: 15px;
|
||||
color: #4C5B76;
|
||||
padding-top: 50px;
|
||||
.failInfo{
|
||||
max-width: 480px;
|
||||
li{
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
img{
|
||||
margin-bottom: 35px;
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
|
|
@ -6,8 +6,9 @@
|
|||
background-color: #050d34;
|
||||
}
|
||||
.ProjectListIndex{
|
||||
width: 1200px;
|
||||
margin:20px auto;
|
||||
// width: 1200px;
|
||||
// margin:20px auto;
|
||||
padding:20px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-wrap:wrap;
|
||||
|
|
@ -211,6 +212,7 @@
|
|||
}
|
||||
.spincontent{
|
||||
height:400px;
|
||||
flex-direction: column;
|
||||
}
|
||||
.spinstyle .ant-spin-text{
|
||||
margin-top:30px;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
Array.isArray(menuName)&& menuName.map((item,key)=>{
|
||||
return(
|
||||
<React.Fragment key={item.menu_name}>
|
||||
{
|
||||
{/* {
|
||||
item.menu_name === "home" &&
|
||||
<li className={pathname==="about" ? "active" : ""}>
|
||||
<Link to={{ pathname: `/${owner}/${projectsId}/about`, state }}>
|
||||
|
|
@ -60,7 +60,7 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
<span>主页</span>
|
||||
</Link>
|
||||
</li>
|
||||
}
|
||||
} */}
|
||||
{
|
||||
item.menu_name === "code" &&
|
||||
<li className={(pathname==="" || urlFlag) ? "active" : ""}>
|
||||
|
|
@ -70,7 +70,7 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
</Link>
|
||||
</li>
|
||||
}
|
||||
{
|
||||
{/* {
|
||||
item.menu_name === "issues" &&
|
||||
<li className={pathname==="issues" ? "active" : ""}>
|
||||
<Link to={{ pathname: `/${owner}/${projectsId}/issues`, state }}>
|
||||
|
|
@ -81,7 +81,7 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
{projectDetail && projectDetail.issues_count ? <span className="num">{numFormat(projectDetail.issues_count)}</span> : ""}
|
||||
</Link>
|
||||
</li>
|
||||
}
|
||||
} */}
|
||||
{
|
||||
item.menu_name === "pulls" && projectDetail && parseInt(projectDetail.type) !== 2 && platform ?
|
||||
<li className={pathname==="pulls" ? "active" : ""}>
|
||||
|
|
@ -93,17 +93,16 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
</li>:""
|
||||
}
|
||||
{/* 引擎仅对当前仓库管理员可见 */}
|
||||
{
|
||||
{/* {
|
||||
item.menu_name === "devops" ?
|
||||
<li className={pathname==="devops" ? "active" : ""}>
|
||||
{/* <Link to={{ pathname: `/${owner}/${projectsId}/devops${open_devops ? `/dispose`:""}`, state }}> */}
|
||||
<Link className='newTab' to={{ pathname: `/${owner}/${projectsId}/devops`, state:{...state,open_devops} }}>
|
||||
<i className="iconfont icon-gongzuoliuicon font-13 mr5 color-grey-3"></i>引擎(Engine)<div className='newBtnImg'></div>
|
||||
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
|
||||
</Link>
|
||||
</li>
|
||||
:""
|
||||
}
|
||||
} */}
|
||||
{/* {
|
||||
item.menu_name === "resources" &&
|
||||
<li className={pathname==="source" ? "active" : ""}>
|
||||
|
|
@ -114,7 +113,7 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
</Link>
|
||||
</li>
|
||||
} */}
|
||||
{
|
||||
{/* {
|
||||
item.menu_name === "versions" &&
|
||||
<li className={pathname==="milestones" ? "active" : ""}>
|
||||
<Link to={{ pathname: `/${owner}/${projectsId}/milestones`, state }}>
|
||||
|
|
@ -123,8 +122,8 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
{projectDetail && projectDetail.versions_count ? <span className="num">{numFormat(projectDetail.versions_count)}</span> :""}
|
||||
</Link>
|
||||
</li>
|
||||
}
|
||||
{
|
||||
} */}
|
||||
{/* {
|
||||
item.menu_name === "wiki" &&
|
||||
<li className={pathname === "wiki" ? "active" : ""}>
|
||||
<Link to={{ pathname: `/${owner}/${projectsId}/wiki`, state }}>
|
||||
|
|
@ -132,8 +131,8 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
<span>维基(Wiki)</span>
|
||||
</Link>
|
||||
</li>
|
||||
}
|
||||
{
|
||||
} */}
|
||||
{/* {
|
||||
item.menu_name === "services" &&
|
||||
<li className={pathname === "server" ? "active" : ""}>
|
||||
<Link className='newTab' to={{ pathname: `/${owner}/${projectsId}/service`, state }}>
|
||||
|
|
@ -141,7 +140,7 @@ function DetailBanner({ history,list , owner , projectsId ,showNotification , ur
|
|||
<span>服务</span><div className='newBtnImg'></div>
|
||||
</Link>
|
||||
</li>
|
||||
}
|
||||
} */}
|
||||
{
|
||||
item.menu_name === "activity" &&
|
||||
<li className={pathname==="activity" ? "active" : ""}>
|
||||
|
|
|
|||
|
|
@ -275,8 +275,8 @@ class CreateMerge extends Component {
|
|||
let _url = `/${mergeOwner}/${projectId}/compare/`;
|
||||
// type为pull时,pullBranch取value,否则取原有值
|
||||
// type为pull时,mergeBranch取原有值,否则取value
|
||||
let _pullBranch = type === 'pull' ? value : pullBranch;
|
||||
let _mergeBranch = type === 'pull' ? mergeBranch : value;
|
||||
let _pullBranch = type === 'pull' ? value : returnbar(pullBranch);
|
||||
let _mergeBranch = type === 'pull' ? returnbar(mergeBranch) : value;
|
||||
if (pullOwner === mergeOwner) {
|
||||
// 如果仓库相同, compare/目标分支...源分支
|
||||
_url += `${turnbar(_mergeBranch)}...${turnbar(_pullBranch)}`;
|
||||
|
|
@ -513,6 +513,7 @@ class CreateMerge extends Component {
|
|||
changeCommitFunc={this.changeCommitFunc}
|
||||
comparesData={comparesData}
|
||||
pullOwnerLogin={pullOwnerLogin}
|
||||
branchParams = {getBranchParams(this.props.location.pathname)}
|
||||
></MergeFooter>
|
||||
)}
|
||||
</Spin>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
import React ,{useEffect,useState } from 'react';
|
||||
import { truncateCommitId } from '../common/util';
|
||||
import { AlignCenter , FlexAJ } from '../Component/layout';
|
||||
import { Tooltip,Progress } from 'antd';
|
||||
import { Tooltip , Progress } from 'antd';
|
||||
import './merge.css';
|
||||
import './Index.scss';
|
||||
import FileDrop from './components/fileDrop';
|
||||
|
||||
function Files({ data,history,owner,projectsId , parentsSha }){
|
||||
const [ files , setFiles ] = useState(data && data.files);
|
||||
const [ copyfileTipTitle, setCopyfileTipTitle] = useState("复制文件路径");
|
||||
function Files({ data , filesData , history,owner,projectsId , parentsSha , mergeId }){
|
||||
const [ files , setFiles ] = useState(filesData);
|
||||
const [ isOpen, setIsOpen] = useState(false);
|
||||
|
||||
useEffect(()=>{
|
||||
if(data){
|
||||
setFiles(data.files);
|
||||
if(filesData){
|
||||
setFiles(filesData);
|
||||
}
|
||||
},[data]);
|
||||
},[filesData]);
|
||||
|
||||
useEffect(()=>{
|
||||
document.addEventListener('click',()=>{setIsOpen(false)})
|
||||
|
|
@ -29,33 +28,22 @@ function Files({ data,history,owner,projectsId , parentsSha }){
|
|||
}
|
||||
}
|
||||
|
||||
function copyFileName(fileName){
|
||||
var copyCont = document.createElement('input');
|
||||
copyCont.defaultValue = fileName;
|
||||
document.body.appendChild(copyCont);
|
||||
copyCont.select(); // 选择对象
|
||||
document.execCommand("Copy"); // 执行浏览器复制命令
|
||||
copyCont.className = 'copyCont';
|
||||
copyCont.style.display='none';
|
||||
setCopyfileTipTitle("复制成功");
|
||||
}
|
||||
|
||||
const folderOpen = (
|
||||
<div className="folders">
|
||||
<div className="folderList">
|
||||
{files && files.map((item, key) => {
|
||||
return (
|
||||
<a href={`#value${key}`}>
|
||||
<FlexAJ className="filesInfo" key={key} onClick={() => {item.flag && showDown(item.flag, key, item.isBin);setIsOpen(false);}}>
|
||||
<FlexAJ className="filesInfo" key={key} onClick={() => {item.flag && showDown(item.flag, key, item.is_bin);setIsOpen(false);}}>
|
||||
<AlignCenter>
|
||||
<i className="iconfont icon-wenjianicon mr4"></i>
|
||||
<span className="cursor-pointer" data-clipboard-text={item.name}>{item.name}</span>
|
||||
<span className="cursor-pointer" data-clipboard-text={item.filename}>{item.filename}</span>
|
||||
</AlignCenter>
|
||||
<div className="see-file">
|
||||
<Tooltip placement="top" title={`${item.addition+item.deletion}处更改${item.addition + item.deletion > 0 ? ":":""}${item.addition>0?item.addition+"处添加":""}${item.addition>0 && item.deletion>0 ?"和":""}${item.deletion>0?item.deletion+"处删除":""}`}>
|
||||
<Progress showInfo = {false} strokeColor = "#2DB44D" size="small" percent={item.addition/(item.addition+item.deletion)*100} />
|
||||
{item.addition >0 && <span className="color-green ml10">+{item.addition}</span>}
|
||||
{item.deletion >0 && <span className="color-red ml10">-{item.deletion}</span>}
|
||||
<Tooltip placement="top" title={`${item.additions+item.deletions}处更改${item.additions + item.deletions > 0 ? ":":""}${item.additions>0?item.additions+"处添加":""}${item.additions>0 && item.deletions>0 ?"和":""}${item.deletions>0?item.deletions+"处删除":""}`}>
|
||||
<Progress showInfo = {false} strokeColor = "#2DB44D" size="small" percent={item.additions/(item.additions+item.deletions)*100} />
|
||||
{item.additions >0 && <span className="color-green ml10">+{item.additions}</span>}
|
||||
{item.deletions >0 && <span className="color-red ml10">-{item.deletions}</span>}
|
||||
</Tooltip>
|
||||
</div>
|
||||
</FlexAJ>
|
||||
|
|
@ -66,22 +54,17 @@ function Files({ data,history,owner,projectsId , parentsSha }){
|
|||
</div>
|
||||
)
|
||||
|
||||
function subStrContent(content){
|
||||
return content ? content.slice(1) :"";
|
||||
}
|
||||
|
||||
return(
|
||||
<div onClick={(e)=>{e.nativeEvent.stopImmediatePropagation()}}>
|
||||
<AlignCenter className="color-grey-9" style={{position:'relative'}}>
|
||||
<div onClick={()=>{setIsOpen(!isOpen)}}>
|
||||
<i className={`iconfont mr5 ${isOpen? "font-18 icon-sanjiaoxing-down":"font-16 icon-triangle"}`}></i>
|
||||
<span className="color-grey-6 update-file-count">
|
||||
共有<span className="color-grey-3"> {data && data.files_count} 个文件 </span>被更改
|
||||
{ data && data.total_addition ? <span>,包括 <span className="color-green">{data && data.total_addition} 次插入</span></span>:"" }
|
||||
{ data && data.total_addition && data.total_deletion ? " 和 ":""}
|
||||
{ data && data.total_deletion ? <span className="color-red"> {data && data.total_deletion} 次删除</span>:""}
|
||||
</span>
|
||||
</div>
|
||||
<AlignCenter className="color-grey-9" style={{position:'relative'}} onClick={()=>{setIsOpen(!isOpen)}}>
|
||||
<div style={{width:20}}><i className={`iconfont mr5 ${isOpen? "font-18 icon-sanjiaoxing-down":"font-16 icon-triangle"}`}></i></div>
|
||||
<span className="color-grey-6 update-file-count">
|
||||
共有<span className="color-grey-3"> {data && data.file_nums} 个文件 </span>被更改
|
||||
{ data && data.total_addition ? <span>,包括 <span className="color-green">{data && data.total_addition} 次插入</span></span>:"" }
|
||||
{ data && data.total_addition && data.total_deletion ? " 和 ":""}
|
||||
{ data && data.total_deletion ? <span className="color-red"> {data && data.total_deletion} 次删除</span>:""}
|
||||
</span>
|
||||
{isOpen && folderOpen}
|
||||
</AlignCenter>
|
||||
{
|
||||
|
|
@ -92,57 +75,7 @@ function Files({ data,history,owner,projectsId , parentsSha }){
|
|||
return(
|
||||
<div className="files" key={key}>
|
||||
<a id= {`value${key}`} className="anchorPoint"></a>
|
||||
<FlexAJ className="filesInfo">
|
||||
<AlignCenter>
|
||||
{!item.isBin ? <i className={!item.flag?"iconfont icon-sanjiaoxing-down color-grey-9":"iconfont icon-triangle font-15 color-grey-9"} onClick={()=>showDown(item.flag,key,item.isBin)}></i>:""}
|
||||
<span className="cursor-pointer" data-clipboard-text={item.name} onClick={()=>showDown(item.flag,key,item.isBin)}>
|
||||
{ item.isRenamed && item.old_name}
|
||||
{ item.isRenamed && <i className="iconfont icon-youjiang font-12 color-grey-8 ml5 mr5"></i> }
|
||||
{item.name}
|
||||
</span>
|
||||
<Tooltip
|
||||
title={copyfileTipTitle}
|
||||
onVisibleChange={()=>setCopyfileTipTitle("复制文件路径")}
|
||||
>
|
||||
<i className="iconfont icon-fuzhiicon ml6" onClick={()=>copyFileName(item.name)}></i>
|
||||
</Tooltip>
|
||||
</AlignCenter>
|
||||
<div className="see-file">
|
||||
<Tooltip placement="top" title={`${item.addition + item.deletion}处更改${item.addition + item.deletion > 0 ? ":":""} ${item.addition > 0 ? item.addition + "处添加" : ""}${item.addition > 0 && item.deletion > 0 ? "和" : ""}${item.deletion > 0 ? item.deletion + "处删除" : ""}`}>
|
||||
<Progress showInfo = {false} strokeColor = "#2DB44D" size="small" percent={item.addition/(item.addition+item.deletion)*100} />
|
||||
<span className="ml10">{item.addition+item.deletion}处</span>
|
||||
</Tooltip>
|
||||
{
|
||||
!item.isSubmodule &&
|
||||
<span className="see-file-btn" onClick={()=>{history.push(`/${owner}/${projectsId}${item.isDeleted ? `/commits/${truncateCommitId(parentsSha)}`:`/tree/${truncateCommitId(item.sha)}/${item.name}`}`)}}>查看文件</span>
|
||||
}
|
||||
</div>
|
||||
</FlexAJ>
|
||||
{
|
||||
item.sections && item.sections.length >= 1 && !item.flag &&
|
||||
<div className="filesContent">
|
||||
{
|
||||
item.sections.map((i,k)=>{
|
||||
return(
|
||||
i.lines && i.lines.length>0 && i.lines.map((item,key)=>{
|
||||
return(
|
||||
<div key={k+key} className={(item.type === 2) ? "linesContent add" : item.type === 3 ? "linesContent reduce": item.type===4?"linesContent translate":"linesContent"}>
|
||||
<span className="lines">
|
||||
<span>{item.leftIdx && item.leftIdx !=="0" ? item.leftIdx :"" }</span>
|
||||
<span>{item.rightIdx && item.rightIdx !=="0" ? item.rightIdx :"" }</span>
|
||||
</span>
|
||||
<p style={{display:"flex"}}>
|
||||
<span className="linetype">{item.type===2 ? "+" : item.type===3 ? "-" :""}</span>
|
||||
{ (item.type===3 || item.type===2) ? subStrContent(item.content) : item.content}
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<FileDrop item={item} prekey={key} projectsId={projectsId} owner={owner} history={history} parentsSha={parentsSha} mergeId={mergeId}/>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -110,11 +110,19 @@
|
|||
border-top: 1px solid #F3F4F6;
|
||||
}
|
||||
.mergeBox{
|
||||
margin:0px auto;
|
||||
width: 1200px;
|
||||
// margin:0px auto;
|
||||
// width: 1200px;
|
||||
padding:0px 20px;
|
||||
}
|
||||
.linetype{
|
||||
width:30px;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
}
|
||||
.diffDesc{
|
||||
padding:30px 0px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
|
@ -22,14 +22,21 @@ class MergeFooter extends Component {
|
|||
activeKey: '1',
|
||||
commitCount: 0,
|
||||
filesCount: 0,
|
||||
unitData:undefined,
|
||||
// 总评论数量,包含回复
|
||||
commentsTotalCount: 0,
|
||||
page:1,
|
||||
hasMore:true,
|
||||
dropLoading:false,
|
||||
limit:100
|
||||
};
|
||||
}
|
||||
componentDidMount() {
|
||||
this.Init();
|
||||
// 为父组件绑定当前,以方便调用方法
|
||||
this.props.bindFootRef && this.props.bindFootRef(this);
|
||||
window.addEventListener("scroll",this.scrollListener);
|
||||
return ()=>{window.removeEventListener("scroll",this.scrollListener);}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
|
|
@ -41,6 +48,18 @@ class MergeFooter extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
scrollListener=()=>{
|
||||
let scrollHeight = document.documentElement.scrollHeight;
|
||||
let clientHeight = document.documentElement.clientHeight;
|
||||
let scrollTop = document.documentElement.scrollTop;
|
||||
if(Math.ceil(scrollTop+clientHeight) >= scrollHeight-5){
|
||||
const { match } = this.props;
|
||||
const { projectsId, owner, mergeId } = match.params;
|
||||
this.getFile(owner, projectsId, mergeId);
|
||||
}
|
||||
}
|
||||
|
||||
Init = (isTabChange) => {
|
||||
const { data, location, match } = this.props;
|
||||
const { pathname } = location;
|
||||
|
|
@ -60,7 +79,7 @@ class MergeFooter extends Component {
|
|||
this.setState({
|
||||
activeKey: activeKey,
|
||||
commitCount: data && data.commits_count,
|
||||
filesCount: data && data.files_count,
|
||||
filesCount:data && data.files_count
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -81,7 +100,7 @@ class MergeFooter extends Component {
|
|||
if (result) {
|
||||
this.setState({
|
||||
commitsData: result.data.commits,
|
||||
commitCount: result.data.commits_count,
|
||||
commitCount: result.data.commits_count
|
||||
});
|
||||
}
|
||||
this.setState({ isSpin: false });
|
||||
|
|
@ -91,29 +110,38 @@ class MergeFooter extends Component {
|
|||
});
|
||||
};
|
||||
|
||||
getFile = (owner, projectsId, mergeId) => {
|
||||
this.setState({ isSpin: true });
|
||||
const url = `/${owner}/${projectsId}/pulls/${mergeId}/files.json`;
|
||||
axios
|
||||
.get(url)
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
filesData: result.data,
|
||||
filesCount: result.data.files_count,
|
||||
});
|
||||
}
|
||||
this.setState({ isSpin: false });
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setState({ isSpin: false });
|
||||
});
|
||||
getFile = async(owner, projectsId, mergeId) => {
|
||||
const { page,limit , hasMore , dropLoading , filesData } = this.state;
|
||||
if(!hasMore || dropLoading){
|
||||
return;
|
||||
}
|
||||
this.setState({ isSpin: page === 1 , dropLoading:page > 1 });
|
||||
const url = `/v1/${owner}/${projectsId}/pulls/${mergeId}/files.json`;
|
||||
await axios.get(url,{
|
||||
params:{page,limit}
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
let datas = result.data;
|
||||
let files = page === 1 ? datas.files : filesData.concat(datas.files);
|
||||
this.setState({
|
||||
unitData:datas,
|
||||
filesData: files,
|
||||
hasMore:datas.files && datas.files.length === limit,
|
||||
page:page+1
|
||||
});
|
||||
}
|
||||
this.setState({ dropLoading:false,isSpin: false });
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setState({ isSpin: false });
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { projectsId, owner, mergeId } = this.props.match.params;
|
||||
|
||||
const { order_id, data = {} } = this.props;
|
||||
const { order_id, data = {} , pullOwnerLogin } = this.props;
|
||||
|
||||
const {
|
||||
isSpin,
|
||||
activeKey,
|
||||
|
|
@ -121,6 +149,8 @@ class MergeFooter extends Component {
|
|||
commitCount,
|
||||
filesData,
|
||||
commitsData = [],
|
||||
unitData,
|
||||
dropLoading
|
||||
} = this.state;
|
||||
|
||||
// 评论数量优先取Comment组件中列表接口返回的,其次取合并请求详情接口中的,都没有取默认值0
|
||||
|
|
@ -128,7 +158,6 @@ class MergeFooter extends Component {
|
|||
this.state.commentsTotalCount || data.comments_total_count || 0,
|
||||
10
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="main mergeRequest" style={{ paddingTop: '0px' }}>
|
||||
<Spin spinning={isSpin}>
|
||||
|
|
@ -193,12 +222,17 @@ class MergeFooter extends Component {
|
|||
}
|
||||
key="3"
|
||||
>
|
||||
<Files
|
||||
{...this.props}
|
||||
data={filesData}
|
||||
projectsId={projectsId}
|
||||
owner={owner}
|
||||
/>
|
||||
<div>
|
||||
<Files
|
||||
{...this.props}
|
||||
data={unitData}
|
||||
filesData={filesData}
|
||||
projectsId={projectsId}
|
||||
owner={owner}
|
||||
mergeId={`pulls/${mergeId}`}
|
||||
/>
|
||||
{ dropLoading && <p style={{textAlign:"center",color:"#999",padding:"10px"}}>文件加载中...</p>}
|
||||
</div>
|
||||
</TabPane>
|
||||
)}
|
||||
</Tabs>
|
||||
|
|
|
|||
|
|
@ -404,12 +404,20 @@ class MessageCount extends Component {
|
|||
{
|
||||
<div className="mt15">
|
||||
<Tag className="pr-branch-tag">
|
||||
<Link
|
||||
to={`/${data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author}/${data.pull_request.is_original?data.project_identifier:projectsId}/tree/${turnbar(data.pull_request && data.pull_request.head)}`}
|
||||
className="ver-middle task-hide" style={{maxWidth:"300px"}} title={`${data.pull_request.fork_project_user}: ${data.pull_request && data.pull_request.head}`}
|
||||
>
|
||||
{data.pull_request && data.pull_request.fork_project_user}: {data.pull_request && data.pull_request.head}
|
||||
</Link>
|
||||
{
|
||||
(data.pull_request.fork_project_user || data.issue.author_name!=="已注销") ?
|
||||
<Link
|
||||
to={`/${data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author}/${data.pull_request.is_original?data.project_identifier:projectsId}/tree/${turnbar(data.pull_request && data.pull_request.head)}`}
|
||||
className="ver-middle task-hide" style={{maxWidth:"300px"}} title={`${data.pull_request.fork_project_user}: ${data.pull_request && data.pull_request.head}`}
|
||||
>
|
||||
{data.pull_request && (data.pull_request.is_original ? data.pull_request.fork_project_user:data.issue.author_name)}: {data.pull_request && data.pull_request.head}
|
||||
</Link>
|
||||
:
|
||||
<span className="ver-middle task-hide" style={{maxWidth:"300px"}} title={`${data.pull_request.fork_project_user}: ${data.pull_request && data.pull_request.head}`}>
|
||||
{data.pull_request && (data.pull_request.is_original ? data.pull_request.fork_project_user:data.issue.author_name)}: {data.pull_request && data.pull_request.head}
|
||||
</span>
|
||||
|
||||
}
|
||||
</Tag>
|
||||
<span className="mr8 ver-middle">
|
||||
<i
|
||||
|
|
@ -638,7 +646,7 @@ class MessageCount extends Component {
|
|||
{...this.props}
|
||||
{...this.state}
|
||||
bindFootRef={this.bindFootRef}
|
||||
pullOwnerLogin={data.pull_request && data.pull_request.fork_project_user}
|
||||
pullOwnerLogin={data.pull_request && (data.pull_request.is_original ? data.pull_request.fork_project_user:data.issue.project_author)}
|
||||
></MergeLinkFooter>
|
||||
</div>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -281,7 +281,6 @@ class NewMerge extends Component {
|
|||
id,
|
||||
comparesData
|
||||
} = this.state;
|
||||
|
||||
const renderBrances = (list, type) => {
|
||||
if (list && list.length > 0) {
|
||||
return list.map((item, key) => {
|
||||
|
|
@ -313,7 +312,9 @@ class NewMerge extends Component {
|
|||
return <div dangerouslySetInnerHTML={{ __html: html }}></div>;
|
||||
};
|
||||
let { project } = this.props;
|
||||
|
||||
// 源仓库所有者login
|
||||
const pullOwnerLogin = projects_names && projects_names.filter(item=>{return item.id === id})[0].project_user_login;
|
||||
console.log("-------------",pullOwnerLogin,projects_names);
|
||||
return (
|
||||
<div>
|
||||
<div className="main">
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import axios from "axios";
|
|||
import "../Order/order.scss";
|
||||
import "./merge.css";
|
||||
import MergeForm from "./merge_form";
|
||||
import MergeFooter from "./merge_footer";
|
||||
const Option = Select.Option;
|
||||
class UpdateMerge extends Component {
|
||||
constructor(props) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,117 @@
|
|||
import React ,{useEffect,useState } from 'react';
|
||||
import { truncateCommitId } from '../../common/util';
|
||||
import { AlignCenter , FlexAJ } from '../../Component/layout';
|
||||
import { Tooltip , Progress , Spin } from 'antd';
|
||||
import "../Index.scss";
|
||||
import axios from 'axios';
|
||||
|
||||
|
||||
function FileDrop({prekey,item,projectsId,owner , history , mergeId,parentsSha}){
|
||||
const [ copyfileTipTitle, setCopyfileTipTitle] = useState("复制文件路径");
|
||||
const [ sections, setSections ] = useState(undefined);
|
||||
const [ show, setShow ] = useState(true);
|
||||
const [ isSpin, setIsSpin ] = useState(false);
|
||||
|
||||
useEffect(()=>{
|
||||
if(prekey < 3 && item && item.filename){
|
||||
showDown(item.filename);
|
||||
}
|
||||
},[prekey,item])
|
||||
|
||||
function copyFileName(fileName){
|
||||
var copyCont = document.createElement('input');
|
||||
copyCont.defaultValue = fileName;
|
||||
document.body.appendChild(copyCont);
|
||||
copyCont.select(); // 选择对象
|
||||
document.execCommand("Copy"); // 执行浏览器复制命令
|
||||
copyCont.className = 'copyCont';
|
||||
copyCont.style.display='none';
|
||||
setCopyfileTipTitle("复制成功");
|
||||
}
|
||||
function subStrContent(content){
|
||||
return content ? " " + content.slice(1) :"";
|
||||
}
|
||||
|
||||
function showDown(filename){
|
||||
if(!sections){
|
||||
setIsSpin(true);
|
||||
const url = `/v1/${owner}/${projectsId}/${mergeId}/files.json`;
|
||||
axios.get(url,{
|
||||
params:{filepath:filename}
|
||||
}).then(res=>{
|
||||
if(res){
|
||||
let files = res.data && res.data.files && res.data.files.length>0 && res.data.files[0];
|
||||
setSections(files.sections);
|
||||
setShow(true);
|
||||
setIsSpin(false);
|
||||
}
|
||||
})
|
||||
}else{
|
||||
setShow(!show);
|
||||
}
|
||||
}
|
||||
return(
|
||||
<div key={prekey}>
|
||||
<Spin spinning={isSpin}>
|
||||
<FlexAJ className="filesInfo">
|
||||
<AlignCenter onClick={()=>setShow(!show)} style={{cursor:!item.is_bin && item.changes !== 0?"pointer":"default"}}>
|
||||
{(!item.is_bin && item.changes !== 0) ? <div style={{width:20}}><i className={show ?"iconfont icon-sanjiaoxing-down color-grey-9":"iconfont icon-triangle font-15 color-grey-9"}></i></div>:""}
|
||||
<span className="cursor-pointer" data-clipboard-text={item.name}>
|
||||
{ item.is_renamed && item.old_name}
|
||||
{ item.is_renamed && <i className="iconfont icon-youjiang font-12 color-grey-8 ml5 mr5"></i> }
|
||||
{item.filename}
|
||||
</span>
|
||||
<Tooltip
|
||||
title={copyfileTipTitle}
|
||||
onVisibleChange={()=>setCopyfileTipTitle("复制文件路径")}
|
||||
>
|
||||
<i className="iconfont icon-fuzhiicon ml6" onClick={(e)=>{e.stopPropagation();copyFileName(item.filename);}}></i>
|
||||
</Tooltip>
|
||||
</AlignCenter>
|
||||
<div className="see-file">
|
||||
<Tooltip placement="top" title={`${item.additions + item.deletions}处更改${item.additions + item.deletions > 0 ? ":":""} ${item.additions > 0 ? item.additions + "处添加" : ""}${item.additions > 0 && item.deletions > 0 ? "和" : ""}${item.deletions > 0 ? item.deletions + "处删除" : ""}`}>
|
||||
<Progress showInfo = {false} strokeColor = "#2DB44D" size="small" percent={item.additions/(item.additions+item.deletions)*100} />
|
||||
<span className="ml10">{item.additions+item.deletions}处</span>
|
||||
</Tooltip>
|
||||
{
|
||||
!item.is_submodule &&
|
||||
<span className="see-file-btn" onClick={()=>{history.push(`/${owner}/${projectsId}${item.is_deleted ? `/commits/${truncateCommitId(parentsSha)}`:`/tree/${truncateCommitId(item.sha)}/${item.filename}`}`)}}>查看文件</span>
|
||||
}
|
||||
</div>
|
||||
</FlexAJ>
|
||||
{
|
||||
(!item.is_bin && item.changes !== 0) && show &&
|
||||
<div className="filesContent">
|
||||
{
|
||||
(sections && sections.length > 0) ? sections.map((i,k)=>{
|
||||
return(
|
||||
i.lines && i.lines.length>0 && i.lines.map((item,keys)=>{
|
||||
return(
|
||||
<div key={k+keys} className={(item.type === 2) ? "linesContent add" : item.type === 3 ? "linesContent reduce": item.type===4?"linesContent translate":"linesContent"}>
|
||||
<span className="lines">
|
||||
<span>{item.left_index && item.left_index !=="0" ? item.left_index :"" }</span>
|
||||
<span>{item.right_index && item.right_index !=="0" ? item.right_index :"" }</span>
|
||||
</span>
|
||||
<div style={{display:"flex"}}>
|
||||
<span className="linetype">{item.type===2 ? "+" : item.type===3 ? "-" :""}</span>
|
||||
<div>
|
||||
<span style={{whiteSpace:"pre-wrap"}}>{(item.type===3 || item.type===2) ? subStrContent(item.content) : item.content}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
)
|
||||
})
|
||||
:
|
||||
<div className='diffDesc'>
|
||||
<a onClick={()=>showDown(item.filename)} className='color-blue'>加载差异</a>差异被折叠
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</Spin>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default FileDrop;
|
||||
|
|
@ -197,6 +197,12 @@ form .ant-cascader-picker, form .ant-select {
|
|||
.linesContent .lines > span:first-child{
|
||||
margin-right: 0px;
|
||||
}
|
||||
.linesContent .lines,.linesContent .linetype,.no-select,.filesInfo{
|
||||
-webkit-user-select: none; /* Safari */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* IE/Edge */
|
||||
user-select: none; /* 标准语法 */
|
||||
}
|
||||
.linesContent .lines > span{
|
||||
width: 50%;
|
||||
text-align: right;
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ class merge extends Component {
|
|||
</Dropdown>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
{/* <li>
|
||||
<Dropdown
|
||||
className="topWrapperSelect"
|
||||
overlay={this.renderMenu(
|
||||
|
|
@ -390,7 +390,7 @@ class merge extends Component {
|
|||
<Icon type="caret-down" className="ml5" />
|
||||
</span>
|
||||
</Dropdown>
|
||||
</li>
|
||||
</li> */}
|
||||
|
||||
<li>
|
||||
<Dropdown
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Tabs } from 'antd';
|
||||
import { Tabs , Spin } from 'antd';
|
||||
import Commits from './Commits';
|
||||
import Files from './Files';
|
||||
import { returnbar , turnbar } from 'educoder';
|
||||
import { Base64 } from 'js-base64';
|
||||
|
||||
import '../Order/order.scss';
|
||||
import './merge.css';
|
||||
import axios from 'axios';
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
|
|
@ -13,9 +16,30 @@ class MergeFooter extends Component {
|
|||
super(props);
|
||||
this.state = {
|
||||
activeKey: '1',
|
||||
diff:undefined,
|
||||
filesData: undefined,
|
||||
page:1,
|
||||
hasMore:true,
|
||||
dropLoading:false,
|
||||
limit:100
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
this.getFilesInfo();
|
||||
window.addEventListener("scroll",this.scrollListener);
|
||||
return ()=>{window.removeEventListener("scroll",this.scrollListener);}
|
||||
}
|
||||
|
||||
scrollListener=()=>{
|
||||
let scrollHeight = document.documentElement.scrollHeight;
|
||||
let clientHeight = document.documentElement.clientHeight;
|
||||
let scrollTop = document.documentElement.scrollTop;
|
||||
if(Math.ceil(scrollTop+clientHeight) >= scrollHeight-5){
|
||||
this.getFilesInfo();
|
||||
}
|
||||
}
|
||||
|
||||
changeTab = (index) => {
|
||||
this.setState({
|
||||
activeKey: index,
|
||||
|
|
@ -27,11 +51,58 @@ class MergeFooter extends Component {
|
|||
changeCommitFunc&& changeCommitFunc(page);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
// 解决切换tab后浏览器回退不刷新的问题、点击tab后url变化但tab未切换的问题
|
||||
const newPathname = this.props.location.pathname;
|
||||
const prevPathname = prevProps.location.pathname;
|
||||
if (newPathname !== prevPathname) {
|
||||
this.getFilesInfo();
|
||||
}
|
||||
}
|
||||
|
||||
getFilesInfo=()=>{
|
||||
const { hasMore , dropLoading , filesData , page , limit } = this.state;
|
||||
if(!hasMore || dropLoading){
|
||||
return;
|
||||
}
|
||||
this.setState({dropLoading:page>1})
|
||||
const { branchParams = {} } = this.props;
|
||||
const { mergeOwner, projectId } = branchParams;
|
||||
let url = `/v1/${mergeOwner}/${projectId}/${this.getUrl()}/files.json`;
|
||||
axios.get(url,{
|
||||
params:{page,limit}
|
||||
}).then(res=>{
|
||||
if(res){
|
||||
let datas = res.data;
|
||||
let files = page === 1 ? datas.files : filesData.concat(datas.files);
|
||||
this.setState({
|
||||
diff:res.data ,
|
||||
filesData: files,
|
||||
hasMore:datas.files && datas.files.length === limit,
|
||||
dropLoading:false,page:page+1
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getUrl = ()=>{
|
||||
const { branchParams = {} } = this.props;
|
||||
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId , pullIdentity } = branchParams;
|
||||
let url = `compare`;
|
||||
if (mergeOwner === pullOwner) {
|
||||
url += `/${Base64.encode(returnbar(pullBranch))}...${Base64.encode(returnbar(mergeBranch))}`;
|
||||
} else {
|
||||
url += `/${Base64.encode(returnbar(mergeBranch))}...${pullOwner}/${pullIdentity || projectId}:${Base64.encode(returnbar(pullBranch))}`;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const { projectsId, owner } = this.props.match.params;
|
||||
const { comparesData = {} ,limit } = this.props;
|
||||
const { commits, diff, commits_count } = comparesData;
|
||||
const { activeKey } = this.state;
|
||||
const { comparesData = {} ,limit ,branchParams } = this.props;
|
||||
const { commits,commits_count } = comparesData;
|
||||
const { activeKey , diff , filesData , dropLoading } = this.state;
|
||||
|
||||
return (commits && commits.length === 0) || !diff ? (
|
||||
''
|
||||
|
|
@ -71,19 +142,24 @@ class MergeFooter extends Component {
|
|||
tab={
|
||||
<span>
|
||||
<span className="font-16">文件</span>
|
||||
{diff.files_count > 0 && (
|
||||
<span className="tabNum">{diff.files_count}</span>
|
||||
{diff.file_nums > 0 && (
|
||||
<span className="tabNum">{diff.file_nums}</span>
|
||||
)}
|
||||
</span>
|
||||
}
|
||||
key="3"
|
||||
>
|
||||
<Files
|
||||
{...this.props}
|
||||
data={diff}
|
||||
projectsId={projectsId}
|
||||
owner={owner}
|
||||
/>
|
||||
<div>
|
||||
<Files
|
||||
{...this.props}
|
||||
data={diff}
|
||||
filesData={filesData}
|
||||
projectsId={projectsId}
|
||||
owner={owner}
|
||||
mergeId={this.getUrl()}
|
||||
/>
|
||||
{ dropLoading && <p style={{textAlign:"center",color:"#999",padding:"10px"}}>文件加载中...</p>}
|
||||
</div>
|
||||
</TabPane>
|
||||
)}
|
||||
</Tabs>
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ class MergeForm extends Component {
|
|||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
{/* <Form.Item>
|
||||
{getFieldDecorator("fixed_version_id", {
|
||||
initialValue: fixed_version_id,
|
||||
})(
|
||||
|
|
@ -378,7 +378,7 @@ class MergeForm extends Component {
|
|||
{this.renderSelect(issue_versions)}
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form.Item> */}
|
||||
<Form.Item>
|
||||
{getFieldDecorator("issue_tag_ids", {
|
||||
initialValue: issue_tag_ids,
|
||||
|
|
|
|||
|
|
@ -57,7 +57,8 @@ class Index extends Component {
|
|||
tokenConTri: false,
|
||||
|
||||
gitHubUrl:false,
|
||||
checkToken:undefined
|
||||
checkToken:undefined,
|
||||
ownerDisabled:false
|
||||
}
|
||||
}
|
||||
componentDidMount = () => {
|
||||
|
|
@ -94,15 +95,21 @@ class Index extends Component {
|
|||
})
|
||||
if(OIdentifier){
|
||||
owner = owner.filter(item=>item.login === OIdentifier);
|
||||
this.setState({
|
||||
ownerDisabled:owner[0].id ? true :false
|
||||
})
|
||||
}else if(user_id){
|
||||
owner = owner.filter(item=>item.id === user_id);
|
||||
this.setState({
|
||||
ownerDisabled:false
|
||||
})
|
||||
}
|
||||
this.props.form.setFieldsValue({
|
||||
user_id:owner && owner[0].id
|
||||
})
|
||||
owner && this.setState({
|
||||
owners_id:owner[0].id,
|
||||
owners_name:owner[0].name
|
||||
owners_name:owner[0].name,
|
||||
})
|
||||
this.setOptionsList(owner, 'owners');
|
||||
}
|
||||
|
|
@ -225,10 +232,10 @@ class Index extends Component {
|
|||
license_id:licenseFlag ? license_id : undefined,
|
||||
ignore_id:ignoreFlag ? ignore_id : undefined,
|
||||
// user_id:owners_id,
|
||||
blockchain: tokenConTri,
|
||||
blockchain_token_all: 10000,
|
||||
blockchain_init_token: parseInt(blockchain_init),
|
||||
auth_token:((projectsType && projectsType === "mirror") && gitHubUrl)? values.auth_token : undefined
|
||||
// blockchain: tokenConTri,
|
||||
// blockchain_token_all: 10000,
|
||||
// blockchain_init_token: parseInt(blockchain_init),
|
||||
// auth_token:((projectsType && projectsType === "mirror") && gitHubUrl)? values.auth_token : undefined
|
||||
}).then((result) => {
|
||||
if (result && result.data.id) {
|
||||
projectsType && projectsType !== "mirror" && this.props.showNotification(`项目创建成功!`);
|
||||
|
|
@ -400,7 +407,7 @@ class Index extends Component {
|
|||
const { getFieldDecorator } = this.props.form;
|
||||
// 项目类型:deposit-托管项目,mirror-镜像项目
|
||||
const { projectsType } = this.props.match.params;
|
||||
const {current_user:{open_blockchain}} = this.props;
|
||||
const {current_user:{open_blockchain,login}} = this.props;
|
||||
|
||||
const {
|
||||
CategoryList,
|
||||
|
|
@ -426,12 +433,13 @@ class Index extends Component {
|
|||
categoreFlag,
|
||||
tokenConTri,
|
||||
gitHubUrl,
|
||||
checkToken
|
||||
checkToken,
|
||||
ownerDisabled
|
||||
} = this.state;
|
||||
return (
|
||||
<div className="main back-white" style={{padding:"0px",border:"none"}}>
|
||||
<div className="newPanel">
|
||||
<div className="newPanel_title">{projectsType && projectsType === "mirror" ? "导入" : "新建"}项目</div>
|
||||
<div className="newPanel_title">{projectsType && projectsType === "mirror" ? "导入" : "新建"}代码库</div>
|
||||
<Spin spinning={isSpin}>
|
||||
<Form>
|
||||
<div className="newPanel_content">
|
||||
|
|
@ -448,7 +456,7 @@ class Index extends Component {
|
|||
required: true, message: '请填写镜像版本库地址'
|
||||
}],
|
||||
})(
|
||||
<Input placeholder="请输入需要导入到本项目的仓库地址" onBlur={this.ChangeAddr} />
|
||||
<Input placeholder="请输入需要导入到本代码库的仓库地址" onBlur={this.ChangeAddr} />
|
||||
)}
|
||||
</Form.Item>
|
||||
<p className="formTip" style={{color:"#D1d1c9"}}>示例:https://github.com/Stability-AI/StableStudio.git</p>
|
||||
|
|
@ -460,7 +468,7 @@ class Index extends Component {
|
|||
<p className="mt10 mb10 color-grey-3 pointer" onClick={this.changeMirrorCheck}>
|
||||
需要授权验证<i className={mirrorCheck ? "iconfont icon-xiajiantou font-13 ml10 color-grey-8":"iconfont icon-youjiantou font-13 ml10 color-grey-8"}></i>
|
||||
<span className="ml20 font-12" style={{color:"#D1d1c9"}}>
|
||||
如果导入项目为私有仓库,{gitHubUrl ? `则需输入目标平台用户token进行授权,`:"则必须填写相应平台正确的用户名和密码"}
|
||||
如果导入代码库为私有仓库,{gitHubUrl ? `则需输入目标平台用户token进行授权,`:"则必须填写相应平台正确的用户名和密码"}
|
||||
{gitHubUrl && <a href="https://forum.gitlink.org.cn/forums/8516/detail" className="color-blue" target="_blank">如何获取token?</a>}
|
||||
</span>
|
||||
</p>
|
||||
|
|
@ -526,6 +534,7 @@ class Index extends Component {
|
|||
})(
|
||||
<Select
|
||||
showSearch
|
||||
disabled={ownerDisabled}
|
||||
style={{width:"260px",height:"33px"}}
|
||||
placeholder="请选择拥有者"
|
||||
className="plateAutoComplete"
|
||||
|
|
@ -546,13 +555,13 @@ class Index extends Component {
|
|||
</Form.Item>
|
||||
<span className="ml10 mr10 mt10 font-18">/</span>
|
||||
<Form.Item
|
||||
label="项目名称"
|
||||
label="代码库名称"
|
||||
className="flex1 explainPos"
|
||||
colon={false}
|
||||
>
|
||||
{getFieldDecorator('name', {
|
||||
rules: [{
|
||||
required: true, message: '请填写项目名称'
|
||||
required: true, message: '请填写代码库名称'
|
||||
}],
|
||||
})(
|
||||
<Input placeholder="例如:团队协作方法与研究" maxLength={50}/>// onBlur={this.changeName}
|
||||
|
|
@ -560,28 +569,28 @@ class Index extends Component {
|
|||
</Form.Item>
|
||||
</AlignCenter>
|
||||
<Form.Item
|
||||
label={<span>项目标识 <span className="color-grey-9">(项目url标识部分)</span></span>}
|
||||
label={<span>代码库标识 <span className="color-grey-9">(代码库url标识部分)</span></span>}
|
||||
colon={false}
|
||||
>
|
||||
{getFieldDecorator('repository_name', {
|
||||
rules: [{
|
||||
required: true, message: '请填写项目标识'
|
||||
required: true, message: '请填写代码库标识'
|
||||
}],
|
||||
})(
|
||||
<Input placeholder="项目标识请使用与项目相关的英文关键字" maxLength={100} />
|
||||
<Input placeholder="代码库标识请使用与代码库相关的英文关键字" maxLength={100} />
|
||||
)}
|
||||
</Form.Item>
|
||||
<div className="pr">
|
||||
<span className="toprightNum">{descNum}/200</span>
|
||||
<Form.Item
|
||||
label="项目简介"
|
||||
label="代码库简介"
|
||||
colon={false}
|
||||
style={{marginBottom:"0px"}}
|
||||
>
|
||||
{getFieldDecorator('description', {
|
||||
rules: [],
|
||||
})(
|
||||
<Input.TextArea maxLength={200} placeholder="项目的介绍" autoSize={{ minRows: 2, maxRows: 6 }} onChange={this.changeDesc}/>
|
||||
<Input.TextArea maxLength={200} placeholder="代码库的介绍" autoSize={{ minRows: 2, maxRows: 6 }} onChange={this.changeDesc}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
|
|
@ -649,7 +658,7 @@ class Index extends Component {
|
|||
className="privatePart"
|
||||
>
|
||||
{getFieldDecorator('private')(
|
||||
<Checkbox value="limit">将项目设为私有<span className="font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
|
||||
<Checkbox value="limit">将代码库设为私有<span className="font-13 color-grey-9">(只有代码库所有人或拥有权限的代码库成员才能看到)</span></Checkbox>
|
||||
)}
|
||||
</Form.Item >
|
||||
{
|
||||
|
|
@ -667,7 +676,7 @@ class Index extends Component {
|
|||
className="privatePart"
|
||||
>
|
||||
{getFieldDecorator('categoreFlag')(
|
||||
<Checkbox checked={categoreFlag} onChange={(e)=>this.showCateFunc(e)}>项目类别</Checkbox>
|
||||
<Checkbox checked={categoreFlag} onChange={(e)=>this.showCateFunc(e)}>代码库类别</Checkbox>
|
||||
)}
|
||||
</Form.Item>
|
||||
{categoreFlag &&
|
||||
|
|
@ -676,13 +685,13 @@ class Index extends Component {
|
|||
>
|
||||
{getFieldDecorator('project_category', {
|
||||
rules: [{
|
||||
required: categoreFlag, message: '请选择项目类别',
|
||||
required: categoreFlag, message: '请选择代码库类别',
|
||||
}, {
|
||||
validator: (rule, value, callback) => this.checkId(rule, value, callback, CategoryList, '项目类别')
|
||||
validator: (rule, value, callback) => this.checkId(rule, value, callback, CategoryList, '代码库类别')
|
||||
}],
|
||||
})(
|
||||
<AutoComplete
|
||||
placeholder="请选择项目类别"
|
||||
placeholder="请选择代码库类别"
|
||||
onChange={(value, e) => this.ChangePlatform(value, e, 'project_category', CategoryList)}
|
||||
className="plateAutoComplete"
|
||||
onBlur={(value) => this.blurCategory(value, CategoryList, "project_category")}
|
||||
|
|
@ -696,20 +705,20 @@ class Index extends Component {
|
|||
className="privatePart"
|
||||
>
|
||||
{getFieldDecorator('languageFlag')(
|
||||
<Checkbox checked={languageFlag} onChange={(e)=>this.showLanguageFunc(e)}>项目语言</Checkbox>
|
||||
<Checkbox checked={languageFlag} onChange={(e)=>this.showLanguageFunc(e)}>代码库语言</Checkbox>
|
||||
)}
|
||||
</Form.Item>
|
||||
{languageFlag &&
|
||||
<Form.Item>
|
||||
{getFieldDecorator('project_language', {
|
||||
rules: [{
|
||||
required: languageFlag, message: '请选择项目语言'
|
||||
required: languageFlag, message: '请选择代码库语言'
|
||||
}, {
|
||||
validator: (rule, value, callback) => this.checkId(rule, value, callback, LanguageList, '项目语言')
|
||||
validator: (rule, value, callback) => this.checkId(rule, value, callback, LanguageList, '代码库语言')
|
||||
}],
|
||||
})(
|
||||
<AutoComplete
|
||||
placeholder="请选择项目语言"
|
||||
placeholder="请选择代码库语言"
|
||||
onChange={(value, e) => this.ChangePlatform(value, e, 'project_language', LanguageList)}
|
||||
className="plateAutoComplete"
|
||||
onBlur={(value) => this.blurCategory(value, LanguageList, "project_language")}
|
||||
|
|
@ -720,13 +729,13 @@ class Index extends Component {
|
|||
</Form.Item>
|
||||
}
|
||||
|
||||
{/* 确权 仅在新建项目时 */}
|
||||
{/* 确权 仅在新建代码库时 */}
|
||||
{open_blockchain && projectsType === "deposit" && <div className='mt10 mb10'>
|
||||
<p className='font-16'>确权</p>
|
||||
<div className='mt5 mb5 color-grey3'><Checkbox checked={tokenConTri} onChange={(e)=>{this.setState({tokenConTri:e.target.checked})}}>加入贡献值激励确权机制</Checkbox></div>
|
||||
{tokenConTri && <Form.Item
|
||||
className="flex1"
|
||||
extra="Token指本项目的虚拟货币,决定用户在本仓库贡献度的比例,可以通过issue悬赏或在个人主页贡献确权页进行转移。创建项目时,每个项目的Token总量为10000,您可以分配您可获取的Token数量(未分配的Token将保留至项目Token余额)"
|
||||
extra="Token指本代码库的虚拟货币,决定用户在本仓库贡献度的比例,可以通过issue悬赏或在个人主页贡献确权页进行转移。创建代码库时,每个代码库的Token总量为10000,您可以分配您可获取的Token数量(未分配的Token将保留至代码库Token余额)"
|
||||
>
|
||||
{getFieldDecorator('blockchain_init', {
|
||||
rules: [{
|
||||
|
|
@ -742,7 +751,7 @@ class Index extends Component {
|
|||
}
|
||||
}}],
|
||||
})(
|
||||
<Input placeholder='请填写您(项目创建者)获取的初始Token值'/>
|
||||
<Input placeholder='请填写您(代码库创建者)获取的初始Token值'/>
|
||||
)}
|
||||
</Form.Item>}
|
||||
</div>}
|
||||
|
|
@ -751,8 +760,8 @@ class Index extends Component {
|
|||
注:<span className="ant-form-item-required"></span> 为必填项,否则为选填
|
||||
</div>
|
||||
<Form.Item className="formTip mt20">
|
||||
<Button type="primary" onClick={this.subMitFrom} className="mr20">{projectsType && projectsType === "mirror" ? "导入" : "创建"}项目</Button>
|
||||
<a onClick={()=>window.history.back(-1)} className="btn_32">取消</a>
|
||||
<Button type="primary" onClick={this.subMitFrom} className="mr20">{projectsType && projectsType === "mirror" ? "导入" : "创建"}代码库</Button>
|
||||
<Link to={`/${login}`} className="btn_32">取消</Link>
|
||||
</Form.Item>
|
||||
</div>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
.newPanel{
|
||||
border:1px solid #eaeaea;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.newPanel_title{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import 'codemirror/mode/javascript/javascript.js';
|
|||
import 'codemirror/mode/clike/clike';
|
||||
import 'codemirror/mode/css/css';
|
||||
import UserSubmitComponent from "./UserSubmitComponent";
|
||||
import CloudIDE from "./cloudIDE";
|
||||
// import CloudIDE from "./cloudIDE";
|
||||
import { Base64 } from "js-base64";
|
||||
|
||||
import "./index.css";
|
||||
|
|
@ -21,7 +21,14 @@ class m_editor extends Component {
|
|||
};
|
||||
}
|
||||
componentDidUpdate = (prevProps) => {
|
||||
if (prevProps && this.props && this.props.content !== prevProps.content) {
|
||||
let firstCondition = prevProps && this.props && this.props.content !== prevProps.content;
|
||||
let secondCondition = prevProps && this.props && this.props.random !== prevProps.random;
|
||||
if (firstCondition) {
|
||||
this.setState({
|
||||
editorValue: this.props.content
|
||||
})
|
||||
}
|
||||
if(secondCondition){
|
||||
this.setState({
|
||||
editorValue: this.props.content
|
||||
})
|
||||
|
|
@ -57,20 +64,17 @@ class m_editor extends Component {
|
|||
enabled: false,
|
||||
},
|
||||
};
|
||||
|
||||
let download_url = detail && detail.download_url;
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="editorBorderBox">
|
||||
{!readOnly ?
|
||||
<CodeMirror
|
||||
placeholder="请输入内容"
|
||||
value={editorValue}
|
||||
options={editor_options}
|
||||
onChange={this.changeEditor}
|
||||
/> :
|
||||
<CloudIDE download_url={download_url} value={editorValue} params={params} filepath={filepath&&filepath.startsWith('/')?filepath.slice(1):filepath}/>
|
||||
}
|
||||
<CodeMirror
|
||||
placeholder="请输入内容"
|
||||
value={editorValue}
|
||||
options={editor_options}
|
||||
onChange={this.changeEditor}
|
||||
readOnly={readOnly}
|
||||
/>
|
||||
</div>
|
||||
{!readOnly && (
|
||||
<div className="editorBorderSubmitBox" style={{ padding: "20px" }}>
|
||||
|
|
|
|||
|
|
@ -514,7 +514,7 @@ class order_form extends Component {
|
|||
)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="里程碑">
|
||||
{/* <Form.Item label="里程碑">
|
||||
{getFieldDecorator("fixed_version_id", {rules: []})(
|
||||
<Select
|
||||
showSearch
|
||||
|
|
@ -536,7 +536,7 @@ class order_form extends Component {
|
|||
)}
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form.Item> */}
|
||||
<Form.Item label="标记">
|
||||
{getFieldDecorator("issue_tag_ids", {rules: []})(
|
||||
<Select
|
||||
|
|
|
|||
|
|
@ -143,17 +143,17 @@ function Index(props){
|
|||
<li className={active === 1 ?"active":""}><Link to={`/settings/profile`}><i className="iconfont icon-gerenziliao mr5 font-14"></i><span className="text-shodow-bold">基本资料</span></Link></li>
|
||||
<li className={active === 2 ?"active":""}><Link to={`/settings/phone`}><i className="iconfont icon-xuanzhonganquanshezhi_icon mr5 font-14"></i><span className="text-shodow-bold">账号管理</span></Link></li>
|
||||
</ul>
|
||||
{notice_url && <ul className="securityUl ul-border-buttom">
|
||||
{/* {notice_url && <ul className="securityUl ul-border-buttom">
|
||||
<li>消息通知</li>
|
||||
<li className={active === 3 ?"active":""}><Link to={"/settings/notice"}><i className="iconfont icon-wodetongzhi font-14"></i><span className="text-shodow-bold">我的通知</span></Link></li>
|
||||
<li className={active === 4 ?"active":""}><Link to={'/settings/notice/config'}><i className="iconfont icon-tongzhiguanli font-14"></i><span className="text-shodow-bold">通知管理</span></Link></li>
|
||||
</ul>}
|
||||
</ul>} */}
|
||||
<ul className="securityUl ul-border-buttom">
|
||||
<li>安全设置</li>
|
||||
<li className={active === 5 ?"active":""}><Link to={`/settings/SSH`}><i className="iconfont icon-xuanzhongssh_icon mr5 font-14"></i><span className="text-shodow-bold">SSH密钥</span></Link></li>
|
||||
<li className={active === 6 ?"active":""}><Link to={`/settings/CLA`}><i className="iconfont icon-a-zu2044 mr5 font-13"></i><span className="text-shodow-bold">我的CLA</span></Link></li>
|
||||
{/* <li className={active === 6 ?"active":""}><Link to={`/settings/CLA`}><i className="iconfont icon-a-zu2044 mr5 font-13"></i><span className="text-shodow-bold">我的CLA</span></Link></li> */}
|
||||
</ul>
|
||||
<ul className="securityUl ul-border-buttom">
|
||||
{/* <ul className="securityUl ul-border-buttom">
|
||||
<li>Bot开发</li>
|
||||
<li className={active === 7 ?"active":""}><Link to={`/settings/mybot`}><i className="iconfont icon-kaifabot mr5 font-18"></i><span className="text-shodow-bold">我的Bot</span></Link></li>
|
||||
<li className={active === 8 ?"active":""}><Link to={`/settings/installbot`}><i className="iconfont icon-BOTpeizhi mr5 font-17"></i><span className="text-shodow-bold">Bot安装</span></Link></li>
|
||||
|
|
@ -161,7 +161,7 @@ function Index(props){
|
|||
<ul className="securityUl">
|
||||
<li>个人建站</li>
|
||||
<li className={active === 9 ?"active":""}><Link to={`/settings/mysite`}><i className="iconfont icon-liebiaoicon mr5 font-15"></i><span className="text-shodow-bold">我的站点</span></Link></li>
|
||||
</ul>
|
||||
</ul> */}
|
||||
</div>
|
||||
<LongWidth>
|
||||
<Gap>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
.whiteBack{
|
||||
background-color: #fff;
|
||||
.boies{
|
||||
width: 1200px;
|
||||
// width: 1200px;
|
||||
margin:0px auto;
|
||||
padding:30px 0px 10px;
|
||||
padding:30px 20px 10px;
|
||||
.shortW{
|
||||
width: 198px;
|
||||
border: 1px solid rgba(79, 108, 188, 0.21);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
padding:0px;
|
||||
margin-right:34px!important;
|
||||
height: 34px;
|
||||
width: 64px;
|
||||
min-width: 64px;
|
||||
text-align: center;
|
||||
line-height: 0px;
|
||||
position: relative;
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ function CollaboratorMember({projectsId,owner,project_id,author,showNotification
|
|||
</a>
|
||||
</Dropdown>
|
||||
<Search
|
||||
placeholder="搜索项目成员..."
|
||||
placeholder="搜索代码库成员..."
|
||||
enterButton="搜索"
|
||||
onSearch={setSearch}
|
||||
style={{width:300}}
|
||||
|
|
|
|||
|
|
@ -145,17 +145,18 @@ class Setting extends Component {
|
|||
this.setState({
|
||||
loading:true
|
||||
})
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const navUrl = `/${owner}/${projectsId}/project_units.json`;
|
||||
this.update(values);
|
||||
// const { projectsId , owner } = this.props.match.params;
|
||||
// const navUrl = `/${owner}/${projectsId}/project_units.json`;
|
||||
|
||||
let unit = values.project_units.filter(item => (item !== "home" && item!== "activity" && item!== "code"));
|
||||
axios.post(navUrl, {
|
||||
unit_types:unit
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
this.update(values);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
// let unit = values.project_units.filter(item => (item !== "home" && item!== "activity" && item!== "code"));
|
||||
// axios.post(navUrl, {
|
||||
// unit_types:unit
|
||||
// }).then((result) => {
|
||||
// if (result) {
|
||||
// this.update(values);
|
||||
// }
|
||||
// }).catch(error=>{})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -240,7 +241,7 @@ class Setting extends Component {
|
|||
// 取消仓库转移
|
||||
CancelDivertProject=()=>{
|
||||
this.props.confirm({
|
||||
content: "是否确认取消将此项目转移给他人?",
|
||||
content: "是否确认取消将此代码库转移给他人?",
|
||||
onOk: () => {
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const url = `/${owner}/${projectsId}/applied_transfer_projects/cancel.json`;
|
||||
|
|
@ -290,18 +291,18 @@ class Setting extends Component {
|
|||
<WhiteBack>
|
||||
<Title>基本设置</Title>
|
||||
<Form className="baseForm" style={{marginLeft: '30px'}}>
|
||||
<Form.Item label="项目名称">
|
||||
<Form.Item label="代码库名称">
|
||||
{getFieldDecorator("project_name", {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入项目名称",
|
||||
message: "请输入代码库名称",
|
||||
},
|
||||
],
|
||||
})(<Input placeholder="请输入项目名称" />)}
|
||||
})(<Input placeholder="请输入代码库名称" />)}
|
||||
{
|
||||
projectDetail && projectDetail.type && projectDetail.type !== 0 ?
|
||||
<span className="color-grey-9">该项目导入于 <a className="color-grey-6" target="_blank" href={projectDetail.mirror_url}>{projectDetail.mirror_url}</a></span>
|
||||
<span className="color-grey-9">该代码库导入于 <a className="color-grey-6" target="_blank" href={projectDetail.mirror_url}>{projectDetail.mirror_url}</a></span>
|
||||
: ""
|
||||
}
|
||||
</Form.Item>
|
||||
|
|
@ -325,45 +326,45 @@ class Setting extends Component {
|
|||
</Form.Item>
|
||||
</div>
|
||||
<Form.Item
|
||||
label={<span>项目标识 <span className="color-grey-9">(项目url标识部分,更改项目标识将导致原仓库地址失效)</span></span>}
|
||||
label={<span>代码库标识 <span className="color-grey-9">(代码库url标识部分,更改代码库标识将导致原仓库地址失效)</span></span>}
|
||||
>
|
||||
{getFieldDecorator("project_identifier", {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入项目标识",
|
||||
message: "请输入代码库标识",
|
||||
},
|
||||
],
|
||||
})(
|
||||
<Input placeholder="项目标识请使用与项目相关的英文关键字" maxLength="100" />
|
||||
<Input placeholder="代码库标识请使用与代码库相关的英文关键字" maxLength="100" />
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="项目简介">
|
||||
<Form.Item label="代码库简介">
|
||||
{getFieldDecorator("project_description", {
|
||||
rules: [],
|
||||
})(
|
||||
<TextArea
|
||||
placeholder="请输入项目简介"
|
||||
placeholder="请输入代码库简介"
|
||||
style={{ height: "80px" }} maxLength={200}
|
||||
/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="项目类别">
|
||||
<Form.Item label="代码库类别">
|
||||
{getFieldDecorator("project_category_id", {
|
||||
rules: [],
|
||||
})(
|
||||
<Select>
|
||||
<Option key={0} value={""}>未选择项目类别</Option>
|
||||
<Option key={0} value={""}>未选择代码库类别</Option>
|
||||
{CategoryList}
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="项目语言">
|
||||
<Form.Item label="代码库语言">
|
||||
{getFieldDecorator("project_language_id", {
|
||||
rules: [],
|
||||
})(
|
||||
<Select>
|
||||
<Option key={0} value={""}>未选择项目语言</Option>
|
||||
<Option key={0} value={""}>未选择代码库语言</Option>
|
||||
{LanguageList}
|
||||
</Select>
|
||||
)}
|
||||
|
|
@ -388,7 +389,7 @@ class Setting extends Component {
|
|||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Form.Item label="项目导航">
|
||||
{/* <Form.Item label="代码库导航">
|
||||
{getFieldDecorator("project_units", {
|
||||
rules: [],
|
||||
})(
|
||||
|
|
@ -406,7 +407,7 @@ class Setting extends Component {
|
|||
}
|
||||
</Checkbox.Group>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form.Item> */}
|
||||
<p className="clearfix">
|
||||
<a className="submitBtn" onClick={this.resetSetting}>
|
||||
更新仓库设置
|
||||
|
|
@ -447,7 +448,7 @@ class Setting extends Component {
|
|||
<p className="font-bd font-16">删除本仓库</p>
|
||||
<p className="mt10">
|
||||
删除仓库是永久性的,
|
||||
无法撤消,且删除后,与仓库关联的项目/任务/合并请求/版本发布等,均会被删除
|
||||
无法撤消,且删除后,与仓库关联的代码库/任务/合并请求/版本发布等,均会被删除
|
||||
</p>
|
||||
</div>
|
||||
<Button onClick={this.deleteProject} className="red_deleteBtn">
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export default (props)=>{
|
|||
return(
|
||||
<Box>
|
||||
<Short>
|
||||
<Setnav header={<Title>团队设置</Title>} nav={array}></Setnav>
|
||||
<Setnav header={<Title>团队设置</Title>} nav={array} history={props.history}></Setnav>
|
||||
</Short>
|
||||
<Long>
|
||||
<Gap>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import Loadable from "react-loadable";
|
||||
|
|
@ -9,6 +9,8 @@ import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC"
|
|||
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
|
||||
import '../css/index.scss';
|
||||
import './Index.scss';
|
||||
import { checkOpenedEnterprise } from '../Information/api';
|
||||
import axios from 'axios';
|
||||
|
||||
const GroupNew = Loadable({
|
||||
loader: () => import("./Group/GroupNew"),
|
||||
|
|
@ -41,6 +43,33 @@ const ProjectDetail = Loadable({
|
|||
});
|
||||
export default withRouter(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(
|
||||
((props)=>{
|
||||
const OIdentifier = props.match.params.OIdentifier;
|
||||
const [ organizeDetail , setOrganizeDetail ] = useState(undefined);
|
||||
const [ enterpriseOpenInfo, setEnterpriseOpenInfo] = useState(false);
|
||||
useEffect(()=>{
|
||||
if(OIdentifier){
|
||||
getDetail(OIdentifier);
|
||||
}
|
||||
},[OIdentifier]);
|
||||
|
||||
function getDetail(identifier) {
|
||||
const url = `/organizations/${identifier}.json`;
|
||||
axios.get(url).then(result=>{
|
||||
if(result && result.data){
|
||||
setOrganizeDetail(result.data);
|
||||
const {id} = result.data;
|
||||
checkOrgOpenEnterprise(id)
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
function checkOrgOpenEnterprise(orgId){
|
||||
checkOpenedEnterprise(orgId).then(res=>{
|
||||
if(res && res.data.code === 200){
|
||||
setEnterpriseOpenInfo(res.data.data)
|
||||
}
|
||||
})
|
||||
}
|
||||
return (
|
||||
<div className="newMain">
|
||||
<Switch>
|
||||
|
|
@ -83,7 +112,7 @@ export default withRouter(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(
|
|||
<Route
|
||||
path="/:OIdentifier/members"
|
||||
render={(p) => {
|
||||
return <TeamDetailIndex {...props} {...p}/>
|
||||
return <TeamDetailIndex {...props} {...p} enterpriseOpened = {enterpriseOpenInfo && enterpriseOpenInfo.isOpen}/>
|
||||
}}
|
||||
></Route>
|
||||
|
||||
|
|
@ -91,10 +120,18 @@ export default withRouter(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(
|
|||
<Route
|
||||
path="/:OIdentifier/setting"
|
||||
render={(p) => (
|
||||
<TeamDetailIndex {...props} {...p}/>
|
||||
<TeamDetailIndex {...props} {...p} enterpriseOpened = {enterpriseOpenInfo && enterpriseOpenInfo.isOpen}/>
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 开通企业工作台 */}
|
||||
<Route
|
||||
path="/:OIdentifier/enterprise"
|
||||
render={(p) => {
|
||||
return <TeamDetailIndex {...props} {...p}/>
|
||||
}}
|
||||
></Route>
|
||||
|
||||
{/* 组织下的项目详情 */}
|
||||
<Route
|
||||
path="/:owner/:projectsId"
|
||||
|
|
@ -107,7 +144,7 @@ export default withRouter(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(
|
|||
<Route
|
||||
path="/:OIdentifier"
|
||||
render={(p) => (
|
||||
<DetailIndex {...props} {...p}/>
|
||||
<DetailIndex {...props} {...p} organizeDetail={organizeDetail} enterpriseOpenInfo={enterpriseOpenInfo}/>
|
||||
)}
|
||||
></Route>
|
||||
</Switch>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@
|
|||
font-weight:700;
|
||||
color:#333333;
|
||||
font-size:22px;
|
||||
flex: 1;
|
||||
width: 0;
|
||||
margin-right: 15px;
|
||||
}
|
||||
.orz-desc{
|
||||
color:#4c5b76;
|
||||
|
|
@ -93,6 +96,7 @@
|
|||
width: 1200px;
|
||||
margin:0px auto;
|
||||
padding-top: 40px;
|
||||
min-height: 72vh;
|
||||
.list-l{
|
||||
background-color: #fff;
|
||||
// background-image: url('./images/left-bc.png');
|
||||
|
|
@ -130,7 +134,7 @@
|
|||
}
|
||||
}
|
||||
.sepment{
|
||||
margin:30px auto 20px;
|
||||
margin:0 auto 20px;
|
||||
.ant-radio-group{
|
||||
.ant-radio-button-wrapper{
|
||||
height: 44px;
|
||||
|
|
@ -220,6 +224,7 @@
|
|||
}
|
||||
.box{
|
||||
background:rgba(255,255,255,1);
|
||||
// min-height: 500px;
|
||||
.head{
|
||||
padding:25px 0px 15px;
|
||||
display: flex;
|
||||
|
|
@ -551,6 +556,7 @@
|
|||
}
|
||||
}
|
||||
.overviewcontent{
|
||||
min-height: 514px;
|
||||
.concentrateUl li{
|
||||
border-color:#cddbeb!important;
|
||||
border-radius:4px;
|
||||
|
|
|
|||
|
|
@ -7,12 +7,13 @@ import Item from './ListItem';
|
|||
import Right from './RightBox';
|
||||
import NoData from '../Nodata';
|
||||
import CheckProfile from '../Component/ProfileModal/Profile';
|
||||
import { Menu , Pagination , Dropdown , Spin , Tooltip , Radio } from 'antd';
|
||||
import { Menu , Pagination , Dropdown , Spin , Tooltip , Radio, Button } from 'antd';
|
||||
import ConcentrateProject from '../users/GeneralView/ConcentrateProject';
|
||||
import { getImageUrl } from 'educoder';
|
||||
import RenderHtml from "../../components/render-html";
|
||||
import EmptyImg from '../Images/nodata.png';
|
||||
import axios from 'axios';
|
||||
import { checkOpenedEnterprise } from '../Information/api';
|
||||
|
||||
const limit = 15;
|
||||
function List(props){
|
||||
|
|
@ -22,27 +23,11 @@ function List(props){
|
|||
const [ search , setSearch ] = useState(undefined);
|
||||
const [ page , setPage ] = useState(1);
|
||||
const [ sortBy , setSortBy ] = useState("updated_on");
|
||||
const [ organizeDetail , setOrganizeDetail ] = useState(undefined);
|
||||
const [ mode , setMode ] = useState("overview");
|
||||
|
||||
const OIdentifier = props.match.params.OIdentifier;
|
||||
const { current_user } = props;
|
||||
console.log(props);
|
||||
const { current_user, organizeDetail, enterpriseOpenInfo } = props;
|
||||
|
||||
useEffect(()=>{
|
||||
if(OIdentifier){
|
||||
getDetail(OIdentifier);
|
||||
}
|
||||
},[OIdentifier]);
|
||||
|
||||
function getDetail(id) {
|
||||
const url = `/organizations/${id}.json`;
|
||||
axios.get(url).then(result=>{
|
||||
if(result && result.data){
|
||||
setOrganizeDetail(result.data);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
if(organizeDetail){
|
||||
|
|
@ -109,17 +94,31 @@ function List(props){
|
|||
<div className="content-orz">
|
||||
<div className="top-orz">
|
||||
<div className="box">
|
||||
<img src={getImageUrl(organizeDetail && organizeDetail.avatar_url)} alt=""/>
|
||||
<img src={getImageUrl(organizeDetail && organizeDetail.avatar_url)} alt="" />
|
||||
<div className="info-orz">
|
||||
<p className="orz-main">
|
||||
<span className="orz-name">{organizeDetail && organizeDetail.nickname}</span>
|
||||
{organizeDetail && organizeDetail.is_admin ?
|
||||
<Link to={`/${OIdentifier}/setting`} className="color-blue ml10 font-14 df"><i className="iconfont icon-shezhi2"></i>设置</Link>
|
||||
:""}
|
||||
<span className="orz-name task-hide">{organizeDetail && organizeDetail.nickname}</span>
|
||||
{organizeDetail && (
|
||||
<div>
|
||||
{
|
||||
!enterpriseOpenInfo.isOpen ? organizeDetail.is_admin && (
|
||||
<Link to={`/${OIdentifier}/enterprise`}>
|
||||
<Button type='primary'>开通工作台</Button>
|
||||
</Link>
|
||||
) :
|
||||
enterpriseOpenInfo.url ? (
|
||||
<Button type='primary' onClick={() => { window.open(enterpriseOpenInfo.url) }}>前往工作台</Button>
|
||||
) : (
|
||||
<Button type='primary'>正在开通工作台</Button>
|
||||
)
|
||||
}
|
||||
{organizeDetail.is_admin && <Link to={`/${OIdentifier}/setting`} className="color-blue ml20 font-14"><Button type='primary' ghost>设置</Button></Link>}
|
||||
</div>
|
||||
)}
|
||||
</p>
|
||||
<div className="orz-desc task-hide-2">
|
||||
<Tooltip title={organizeDetail && organizeDetail.description} placement={"bottomLeft"}>
|
||||
<span style={{display:"block"}}>{organizeDetail && organizeDetail.description}</span>
|
||||
<span style={{ display: "block" }}>{organizeDetail && organizeDetail.description}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -129,7 +128,7 @@ function List(props){
|
|||
<div className="list-l">
|
||||
{
|
||||
organizeDetail.news_title &&
|
||||
<div className="teamnewstatus">
|
||||
<div className="teamnewstatus mb30">
|
||||
<p className="teamname"><i className="iconfont icon-dongtaiicon1" /><span>新闻动态</span></p>
|
||||
<p className="teamtitle">
|
||||
{organizeDetail.news_title}
|
||||
|
|
@ -228,6 +227,7 @@ function List(props){
|
|||
showCompeleteDialog={props.showCompeleteDialog}
|
||||
completeProfile={props.completeProfile}
|
||||
history={props.history}
|
||||
enterpriseOpened = {enterpriseOpenInfo.isOpen}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ const Img = styled.img`{
|
|||
height:45px;
|
||||
margin-right:12px;
|
||||
}`
|
||||
function RightBox({ OIdentifier , history , admin , showCompeleteDialog ,completeProfile }) {
|
||||
function RightBox({ OIdentifier , history , admin , showCompeleteDialog ,completeProfile, enterpriseOpened }) {
|
||||
const [ languageData, setLanguageData ] = useState(undefined);
|
||||
const [ memberData, setMemberData ] = useState(undefined);
|
||||
const [ groupData, setGroupData ] = useState(undefined);
|
||||
|
|
@ -148,7 +148,7 @@ function RightBox({ OIdentifier , history , admin , showCompeleteDialog ,complet
|
|||
</Box>
|
||||
:""
|
||||
}
|
||||
<Box
|
||||
{!enterpriseOpened && <Box
|
||||
name="组织团队"
|
||||
count={groupData && groupData.total_count}
|
||||
icon={<i className="iconfont icon-zuzhituandui font-17 mr8"></i>}
|
||||
|
|
@ -187,7 +187,7 @@ function RightBox({ OIdentifier , history , admin , showCompeleteDialog ,complet
|
|||
})}
|
||||
</React.Fragment>:<Nodata _html="暂无团队" small/>
|
||||
}
|
||||
</Box>
|
||||
</Box>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import styled from 'styled-components';
|
|||
import UploadImage from '../Component/UploadImage';
|
||||
import axios from 'axios';
|
||||
import Modals from '../Component/Modals';
|
||||
import { Encrypt } from '../../../common/Env';
|
||||
|
||||
import { getImageUrl } from 'educoder';
|
||||
const TextArea = Input.TextArea;
|
||||
|
|
@ -91,7 +92,7 @@ export default Form.create()(
|
|||
function onOk(password){
|
||||
const url = `/organizations/${organizeDetail.id}.json`;
|
||||
axios.delete(url,{
|
||||
params:{ password }
|
||||
params:{ password:Encrypt(password) }
|
||||
}).then(result=>{
|
||||
if(result && result.data){
|
||||
// 删除后跳转到个人中心的组织页面
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ const CLANew = Loadable({
|
|||
export default (( props )=>{
|
||||
const pathname = props.location.pathname;
|
||||
const OIdentifier = props.match.params.OIdentifier;
|
||||
const {organizeDetail} = props;
|
||||
const {organizeDetail, enterpriseOpened, mygetHelmetapi} = props;
|
||||
useEffect(()=>{
|
||||
if(organizeDetail){
|
||||
const {nickname} = organizeDetail;
|
||||
|
|
@ -68,8 +68,8 @@ export default (( props )=>{
|
|||
const array = {list:[
|
||||
{name:'基本设置',icon:"icon-base",href:`/${OIdentifier}/setting`},
|
||||
{name:'组织首页管理',icon:"icon-huabanfuben",href:`/${OIdentifier}/setting/index`},
|
||||
{name:'组织成员管理',icon:"icon-zuzhichengyuan",href:`/${OIdentifier}/setting/member`},
|
||||
{name:'组织团队管理',icon:"icon-zuzhixiangmu",href:`/${OIdentifier}/setting/group`},
|
||||
{name:'组织成员管理',icon:"icon-zuzhichengyuan",href: enterpriseOpened ? `${ mygetHelmetapi && mygetHelmetapi.common.zone }/${OIdentifier}/members` : `/${OIdentifier}/setting/member` , hide: enterpriseOpened},
|
||||
{name:'组织团队管理',icon:"icon-zuzhixiangmu",href:`/${OIdentifier}/setting/group`, hide: enterpriseOpened},
|
||||
// {name:'管理web钩子',icon:"icon-zhongqingdianxinicon10",href:`/${OIdentifier}/setting/hooks`}
|
||||
{name:'CLA管理',img:claIcon,href:`/${OIdentifier}/setting/agreement`,hide:organizeDetail && !organizeDetail.enabling_cla}
|
||||
],
|
||||
|
|
@ -78,7 +78,7 @@ export default (( props )=>{
|
|||
return(
|
||||
<Box>
|
||||
<Short>
|
||||
<Setnav header={<Title>组织设置</Title>} nav={array}></Setnav>
|
||||
<Setnav header={<Title>组织设置</Title>} nav={array} history={props.history}></Setnav>
|
||||
</Short>
|
||||
<Long>
|
||||
<Gap >
|
||||
|
|
|
|||
|
|
@ -0,0 +1,181 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { WhiteBack , FlexAJ } from '../../Component/layout';
|
||||
import { Table , Pagination , Popconfirm, Button, message, Tooltip, Select, Spin } from 'antd';
|
||||
import Title from '../../Component/Title';
|
||||
import Search from '../../Component/Search';
|
||||
import styled from 'styled-components';
|
||||
import { getImageUrl } from 'educoder';
|
||||
import axios from 'axios';
|
||||
import { Link } from 'react-router-dom';
|
||||
import './teamSetting.scss';
|
||||
import { createEnterpriseByGitlinkOrgId, getRoleList, getUserList, checkOpenedEnterprise } from '../../Information/api';
|
||||
|
||||
const Img = styled.img`{
|
||||
width:30px;
|
||||
height:30px;
|
||||
border-radius:50%;
|
||||
}`
|
||||
const limit = 15;
|
||||
export default (({organizeDetail,history,match, current_user})=>{
|
||||
const OIdentifier = match.params.OIdentifier;
|
||||
const {login} = current_user
|
||||
const [ page , setPage ] = useState(1);
|
||||
const [ total , setTotal ] = useState(0);
|
||||
const [ data , setData ] = useState(undefined);
|
||||
const [ roleList, setRoleList] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
// 定时器
|
||||
let intervalId = null;
|
||||
|
||||
useEffect(()=>{
|
||||
getRoleList().then(res=>{
|
||||
const {code, rows} = res && res.data
|
||||
if(code === 200){
|
||||
setRoleList(rows);
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
||||
useEffect(()=>{
|
||||
if(organizeDetail){
|
||||
const {nickname} = organizeDetail;
|
||||
document.title = `开通组织工作台-${nickname}`;
|
||||
pollData()
|
||||
}
|
||||
}, [organizeDetail])
|
||||
|
||||
useEffect(()=>{
|
||||
if(organizeDetail && organizeDetail.id){
|
||||
getData(organizeDetail.id);
|
||||
}
|
||||
},[organizeDetail,page])
|
||||
|
||||
// 轮询函数
|
||||
const pollData = () => {
|
||||
checkOpenedEnterprise(organizeDetail.id).then(res=>{
|
||||
if(res && res.data.code === 200){
|
||||
const {data} = res.data;
|
||||
if(data.isOpen && !data.url){
|
||||
setLoading(true)
|
||||
}else if(data.isOpen){
|
||||
clearInterval(intervalId);
|
||||
window.location = data.url
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
function getData(id){
|
||||
getUserList(id).then(res=>{
|
||||
const {code, rows, total} = res && res.data
|
||||
if(code === 200){
|
||||
setData(rows);
|
||||
setTotal(total);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 切换分页
|
||||
function ChangePage(page){
|
||||
setPage(page);
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '头像',
|
||||
dataIndex: 'imageUrl',
|
||||
render:(value)=>{
|
||||
return(
|
||||
<Img src={value}></Img>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '用户名',
|
||||
dataIndex: 'nickname',
|
||||
},
|
||||
{
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
},
|
||||
{
|
||||
title: '所属团队',
|
||||
dataIndex: ['role', 'roleKey'],
|
||||
width:"20%",
|
||||
render:(value,record)=>{
|
||||
return <Select value={value} onChange={(value)=>{
|
||||
const users = [...data];
|
||||
users.map(item=>item.username === record.username && (item.role.roleKey = value))
|
||||
setData(users);
|
||||
}}>
|
||||
{roleList && roleList.map(item=>{return <Select.Option key={item.roleKey}>{item.roleName}</Select.Option>})}
|
||||
</Select>
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'username',
|
||||
key: "action",
|
||||
render:(value)=>{
|
||||
return (
|
||||
<Button type='danger' size='small' disabled={value === login} onClick={()=>{
|
||||
const users = data.filter(item=>{return item.username !== value});
|
||||
setData(users);
|
||||
}}><i className='iconfont icon-fuzhi-shanchu font-14'></i></Button>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
function createEnterprise(){
|
||||
const users = data.map(item=>{return {userId: item.userId, roleKey: item.role.roleKey}})
|
||||
createEnterpriseByGitlinkOrgId(organizeDetail.id, users).then(res=>{
|
||||
if(res && res.data.code === 200){
|
||||
message.success('开通成功');
|
||||
intervalId = setInterval(pollData, 1000);
|
||||
}else{
|
||||
message.error(res && res.data.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
return(
|
||||
<Spin spinning={loading}>
|
||||
<WhiteBack style={{border:"1px solid #eee"}} className='exterpriseBox'>
|
||||
<div className='padding30'>
|
||||
首次创建组织工作台时,系统将根据组织团队用户在组织工作台中根据不同团队初始化成不同角色。请您知悉以下角色权限,再次确认组织成员的角色分配。<br/>
|
||||
<span className='font-bd'>组织管理员:</span>原owner团队成员,对组织内所有代码库均具有管理员权限,在组织工作台中拥有最高管理权限<br/>
|
||||
<span className='font-bd'>项目管理员:</span>原管理员团队成员,对组织内所有代码库均具有管理员权限,在组织工作台中拥有项目管理权限<br/>
|
||||
<span className='font-bd'>普通成员:</span>原开发者及报告者团队成员,对组织内所有代码库均具有开发者权限,在组织工作台中拥有项目基础使用权限及查看权限
|
||||
</div>
|
||||
<FlexAJ className="padding20-30">
|
||||
<div style={{width:"580px"}}>
|
||||
{/* <Search placeholder="输入用户名或邮箱、团队名搜索" onSearch={(value)=>{setSearch(value)}}/> */}
|
||||
</div>
|
||||
{/* <Sort menu={menu}>
|
||||
<a className="color-blue">角色筛选<i className="iconfont icon-sanjiaoxing-down ml3 font-14"></i></a>
|
||||
</Sort> */}
|
||||
</FlexAJ>
|
||||
<div className="pl30 pr30 pb30" style={{minHeight:"400px"}}>
|
||||
<Table
|
||||
size="small"
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
pagination={false}
|
||||
className="teamMemberTable"
|
||||
></Table>
|
||||
{
|
||||
total > limit ?
|
||||
<div className="edu-txt-center mt30 mb20">
|
||||
<Pagination simple current={page} total={total} pageSize={limit} onChange={ChangePage}></Pagination>
|
||||
</div>
|
||||
:""
|
||||
}
|
||||
</div>
|
||||
<div className='edu-txt-right pl30 pr30 pb30'>
|
||||
<Button type='primary' ghost className='mr20' onClick={()=>{history.push(`/${OIdentifier}`)}}>暂不开通</Button>
|
||||
<Button type='primary' onClick={createEnterprise}>确认并开通工作台</Button>
|
||||
</div>
|
||||
</WhiteBack>
|
||||
</Spin>
|
||||
)
|
||||
})
|
||||
|
|
@ -129,4 +129,14 @@
|
|||
margin-right: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.exterpriseBox{
|
||||
.padding30{
|
||||
color: #4C5876;
|
||||
line-height: 30px;
|
||||
border-bottom: 1px dashed #eee;
|
||||
}
|
||||
.font-bd{
|
||||
color: #0D0F12;
|
||||
}
|
||||
}
|
||||
|
|
@ -26,9 +26,15 @@ const Setting = Loadable({
|
|||
loader: () => import("../Setting/TeamSettingIndex"),
|
||||
loading: Loading,
|
||||
});
|
||||
const Enterprise = Loadable({
|
||||
loader: () => import("../Setting/enterprise"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
function Detail(props){
|
||||
const OIdentifier = props.match.params.OIdentifier;
|
||||
const pathname = props.location.pathname;
|
||||
const {enterpriseOpened} = props;
|
||||
|
||||
const [ detail , setDetail ] = useState(undefined);
|
||||
const [ flag , setFlag ] = useState(true);
|
||||
|
|
@ -78,7 +84,7 @@ function Detail(props){
|
|||
setDetail(d);
|
||||
}
|
||||
return(
|
||||
<div className="teamDetail">
|
||||
<div className="teamDetail mb50">
|
||||
{
|
||||
detail &&
|
||||
<Cards
|
||||
|
|
@ -86,18 +92,11 @@ function Detail(props){
|
|||
title={detail.nickname}
|
||||
desc={!buttonflag && detail.description}
|
||||
img={detail.avatar_url}
|
||||
rightBtn={
|
||||
<React.Fragment>
|
||||
{flag && !buttonflag && detail.is_admin ?
|
||||
<Link to={`/${OIdentifier}/setting`} className="color-blue ml10 font-14">设置<i className="iconfont icon-shezhi2 ml3 fr"></i></Link>
|
||||
:""}
|
||||
{buttonflag &&
|
||||
<span className="subNavs">
|
||||
<Link to={`/${OIdentifier}/members`} className={pathname ===`/${OIdentifier}/members` ? "active":""}><span>组织成员</span>{detail.num_users && <lable>{detail.num_users}</lable>}</Link>
|
||||
<Link to={`/${OIdentifier}/teams`} className={pathname ===`/${OIdentifier}/teams` ? "active":""}><span>组织团队</span>{detail.num_teams &&<lable>{detail.num_teams}</lable>}</Link>
|
||||
</span>
|
||||
}
|
||||
</React.Fragment>
|
||||
rightBtn={buttonflag && !enterpriseOpened &&
|
||||
<span className="subNavs">
|
||||
<Link to={`/${OIdentifier}/members`} className={pathname ===`/${OIdentifier}/members` ? "active":""}><span>组织成员</span>{detail.num_users && <lable>{detail.num_users}</lable>}</Link>
|
||||
<Link to={`/${OIdentifier}/teams`} className={pathname ===`/${OIdentifier}/teams` ? "active":""}><span>组织团队</span>{detail.num_teams &&<lable>{detail.num_teams}</lable>}</Link>
|
||||
</span>
|
||||
}
|
||||
bottomInfos={
|
||||
!buttonflag && <div>
|
||||
|
|
@ -137,19 +136,20 @@ function Detail(props){
|
|||
}}
|
||||
></Route>
|
||||
|
||||
<Route
|
||||
path="/:OIdentifier/setting"
|
||||
render={(p) => {
|
||||
return <Setting {...props} {...p} organizeDetail={detail} updateFunc={updateDetail}/>
|
||||
}}
|
||||
></Route>
|
||||
|
||||
<Route
|
||||
path="/:OIdentifier"
|
||||
path="/:OIdentifier/setting"
|
||||
render={(p) => {
|
||||
return <DetailIndex {...props} {...p} organizeDetail={detail}/>
|
||||
return <Setting {...props} {...p} organizeDetail={detail} updateFunc={updateDetail} enterpriseOpened={enterpriseOpened}/>
|
||||
}}
|
||||
></Route>
|
||||
|
||||
<Route
|
||||
path="/:OIdentifier/enterprise"
|
||||
render={(p) => {
|
||||
return <Enterprise {...props} {...p} organizeDetail={detail}/>
|
||||
}}
|
||||
></Route>
|
||||
|
||||
</Switch>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { Pagination , Spin } from 'antd';
|
|||
import AddMemberBox from './Component/AddMemberBox';
|
||||
|
||||
const limit = 16;
|
||||
function TeamMember({organizeDetail,current_user,history,match}){
|
||||
function TeamMember({organizeDetail,current_user,history,match,enterpriseOpened}){
|
||||
const OIdentifier = match.params.OIdentifier;
|
||||
const [ page , setPage ] = useState(1);
|
||||
const [ total , setTotal ] = useState(0);
|
||||
|
|
@ -46,7 +46,7 @@ function TeamMember({organizeDetail,current_user,history,match}){
|
|||
<WhiteBack style={{marginBottom:"30px",border:'1px solid #eee'}}>
|
||||
<Banner>组织成员
|
||||
{
|
||||
organizeDetail && organizeDetail.is_admin &&
|
||||
!enterpriseOpened && organizeDetail && organizeDetail.is_admin &&
|
||||
<AddMemberBox
|
||||
className="addMemberBtn"
|
||||
orzId={organizeDetail && organizeDetail.id}
|
||||
|
|
|
|||
|
|
@ -84,27 +84,25 @@ class CommonUsers extends Component {
|
|||
const { users, count , isSpin, type_title } = this.state;
|
||||
|
||||
return (
|
||||
<div className="pbt15">
|
||||
<div className="main background-f minH-670" style={{padding:"0px"}}>
|
||||
<div className="user-list-items">
|
||||
<div className="font-18 padding10-20 border-b-line">{type_title}</div>
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="w-100 inline-block">
|
||||
{count === 0 ? (
|
||||
<NoneData _html="暂时还没有相关数据!" />
|
||||
) : (
|
||||
<UserList
|
||||
users={users}
|
||||
userClass={'w-25'}
|
||||
successFunc={this.getUsersList}
|
||||
notReset={true}
|
||||
{...this.props}
|
||||
></UserList>
|
||||
)}
|
||||
</div>
|
||||
</Spin>
|
||||
{this.Paginations()}
|
||||
</div>
|
||||
<div className="main background-f minH-670" style={{padding:"0px"}}>
|
||||
<div className="user-list-items">
|
||||
<div className="font-18 padding10-20 border-b-line">{type_title}</div>
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="w-100 inline-block">
|
||||
{count === 0 ? (
|
||||
<NoneData _html="暂时还没有相关数据!" />
|
||||
) : (
|
||||
<UserList
|
||||
users={users}
|
||||
userClass={'w-25'}
|
||||
successFunc={this.getUsersList}
|
||||
notReset={true}
|
||||
{...this.props}
|
||||
></UserList>
|
||||
)}
|
||||
</div>
|
||||
</Spin>
|
||||
{this.Paginations()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -133,18 +133,16 @@ class ForkUsers extends Component {
|
|||
const { users, isSpin } = this.state;
|
||||
|
||||
return (
|
||||
<div className="pbt15">
|
||||
<div className="main background-f minH-670" style={{padding:"0px"}}>
|
||||
<div className="user-list-items">
|
||||
<div className="font-18 padding10-20 border-b-line">Fork列表</div>
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="w-100 inline-block" style={{minHeight:"400px"}}>
|
||||
{users && users.length === 0 ? <NoneData _html="暂时还没有相关数据!" /> :"" }
|
||||
{this.renderList(users)}
|
||||
</div>
|
||||
</Spin>
|
||||
{this.Paginations()}
|
||||
</div>
|
||||
<div className="main background-f minH-670" style={{padding:"0px"}}>
|
||||
<div className="user-list-items">
|
||||
<div className="font-18 padding10-20 border-b-line">Fork列表</div>
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="w-100 inline-block" style={{minHeight:"400px"}}>
|
||||
{users && users.length === 0 ? <NoneData _html="暂时还没有相关数据!" /> :"" }
|
||||
{this.renderList(users)}
|
||||
</div>
|
||||
</Spin>
|
||||
{this.Paginations()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
let wikiName = ''
|
||||
let key = '';
|
||||
if (!pathname.endsWith('/wiki/add')) {
|
||||
wikiName = decodeURI(pathname.split('/')[4]);
|
||||
wikiName = pathname.split('/')[4];
|
||||
key = pathname.split('/')[5];
|
||||
}else{
|
||||
key = search.split('=').pop();
|
||||
|
|
@ -94,7 +94,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget, initialValue, rightComponent) => (
|
||||
<Form.Item label={label} className="mb0">
|
||||
<Form.Item label={label} className="mb0" wrapperCol={{span: 18}}>
|
||||
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
|
||||
{rightComponent}
|
||||
</Form.Item>
|
||||
|
|
@ -116,12 +116,6 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
};
|
||||
validateFields((err, values) => {
|
||||
if (!err) {
|
||||
let regEn = /[\\/:*?"<>|[\]-]/g;
|
||||
if (regEn.test(values.title)) {
|
||||
message.error('文件名不能有特殊字符: \\ / : * ? \" < > | [ \] -');
|
||||
setOperateFlag(false);
|
||||
return;
|
||||
}
|
||||
const {md_content, title} = values;
|
||||
if (wikiName) {
|
||||
updateWiki({
|
||||
|
|
@ -130,7 +124,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
projectId: project.id,
|
||||
pageName: wikiName,
|
||||
title,
|
||||
commit_message: '',
|
||||
message: '',
|
||||
content_base64: Base64.encode(md_content)
|
||||
}).then(res => dealRes(res, title));
|
||||
} else {
|
||||
|
|
@ -216,7 +210,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
projectId: project.id,
|
||||
pageName: '_Sidebar',
|
||||
title: '_Sidebar',
|
||||
commit_message: '',
|
||||
message: '',
|
||||
content_base64: Base64.encode(content)
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
@ -326,7 +320,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
"title",
|
||||
[
|
||||
{ required: true, message: "请输入标题" },
|
||||
// { pattern: /[^`\[\]\/:*?''<>|%-+_]/g, message: '不允许部分特殊字符' }
|
||||
{ pattern: /^(?!-).*$/, message: '不能以-开头' }
|
||||
],
|
||||
<Input
|
||||
placeholder={"请输入标题"}
|
||||
|
|
@ -336,7 +330,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
|
|||
/>
|
||||
)}
|
||||
|
||||
<Form.Item className="mb0 wiki-md">
|
||||
<Form.Item className="mb0 wiki-md" wrapperCol={{span: 18}}>
|
||||
<MDEditor
|
||||
placeholder={"请输入wiki内容"}
|
||||
height={500}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ export default (props) => {
|
|||
project && checkItem.name && getWiki({
|
||||
owner: owner,
|
||||
repo: projectsId,
|
||||
pageName: checkItem.name,
|
||||
pageName: checkItem.sub_url,
|
||||
projectId: project.id
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
@ -189,11 +189,6 @@ export default (props) => {
|
|||
setAddMenuError("不能仅输入空格");
|
||||
return;
|
||||
}
|
||||
const regEn = /[\\/:*?"<>|[\]-]/g;
|
||||
if (regEn.test(menuName)) {
|
||||
setAddMenuError("不能有特殊字符: \\ / : * ? \" < > | [ \] -");
|
||||
return;
|
||||
}
|
||||
// 校验一级目录中是否有相同名称
|
||||
const oneMenuList = fileList.filter(item=>!item.title.trim().startsWith('[[')).map(i=>i.title.trim())
|
||||
if(oneMenuList.includes(`- ${menuName}`)){
|
||||
|
|
@ -214,7 +209,7 @@ export default (props) => {
|
|||
projectId: project.id,
|
||||
pageName: '_Sidebar',
|
||||
title: '_Sidebar',
|
||||
commit_message: '',
|
||||
message: '',
|
||||
content_base64: Base64.encode(treeToMd(sidebarList))
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
@ -231,8 +226,8 @@ export default (props) => {
|
|||
});
|
||||
}
|
||||
|
||||
function goEdit() {
|
||||
history.push(`/${owner}/${projectsId}/wiki/${encodeURI(checkItem.name)}/${checkItem.key}/edit`);
|
||||
function goEdit(params) {
|
||||
history.push(`/${owner}/${projectsId}/wiki/${encodeURI(checkItem.sub_url)}/${checkItem.key}/edit${params}`);
|
||||
}
|
||||
|
||||
function preview() {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@ body {
|
|||
background: rgba(255,255,255,1);
|
||||
}
|
||||
.wiki-main {
|
||||
width: 1200px;
|
||||
min-height: 400px;
|
||||
margin: 20px auto 60px;
|
||||
margin: 20px;
|
||||
|
||||
.ant-btn-primary {
|
||||
background-color: $wikiColor;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ export default (props) => {
|
|||
projectsId && checkItem.name && getWiki({
|
||||
owner: owner,
|
||||
repo: projectsId,
|
||||
pageName: checkItem.name,
|
||||
pageName: checkItem.sub_url,
|
||||
projectId: projectId,
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
flex-flow: column nowrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 1200px;
|
||||
min-height: 400px;
|
||||
// width: 1200px;
|
||||
min-height: 70vh;
|
||||
padding: 20px;
|
||||
margin: 20px auto;
|
||||
margin: 20px;
|
||||
background: rgba(250, 252, 255, 1);
|
||||
font-family: "PingFangSC-Medium";
|
||||
border-radius: 4px;
|
||||
|
|
|
|||
|
|
@ -116,13 +116,16 @@ export function markdownToTree(markdownText){
|
|||
lines.map((item, index) =>{
|
||||
const title = item.trim();
|
||||
const isFile = title.startsWith('[[') && title.endsWith(']]');
|
||||
const titleStr = isFile ? title.substring(2, title.length - 2) : title.substring(2, title.length)
|
||||
const node = {
|
||||
// 带空格+[[]]或者- 标识
|
||||
title: item,
|
||||
children: [],
|
||||
key: undefined,
|
||||
// 纯内容
|
||||
titleStr: isFile ? title.substring(2, title.length - 2) : title.substring(2, title.length),
|
||||
titleStr,
|
||||
// 编码后的title,获取wiki内容用title_sub
|
||||
title_sub: encodeURIComponent(titleStr),
|
||||
// 是否是wiki文件
|
||||
isFile: isFile
|
||||
}
|
||||
|
|
@ -178,6 +181,22 @@ export function findNodeByKey(list, key){
|
|||
return undefined;
|
||||
}
|
||||
|
||||
// 找到children中有相同key的数组
|
||||
export function findBrotherNodesByKey(list, key){
|
||||
for (let index = 0; index < list.length; index++) {
|
||||
const element = list[index];
|
||||
if (element.key == key) {
|
||||
return list;
|
||||
}else if (element.children && element.children.length) {
|
||||
let result = findBrotherNodesByKey(element.children, key);
|
||||
if (result.length) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
// 找到children中有相同key的数组
|
||||
export function findNodeByChildrenKey(list, key){
|
||||
for (let index = 0; index < list.length; index++) {
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ export default function Sidebar(props) {
|
|||
const {node, children, key} = item;
|
||||
if(isFile){
|
||||
// 删除页面
|
||||
deleteWiki({owner: owner, repo: projectsId, projectId: project.id, pageName: title}).then(res => {
|
||||
deleteWiki({owner: owner, repo: projectsId, projectId: project.id, pageName: item.title_sub}).then(res => {
|
||||
if(res && res.message === "204"){
|
||||
// 递归过滤相同key值的节点,执行删除操作
|
||||
const menuListByDel = findSameKeyByDel(menuList, key);
|
||||
|
|
@ -267,7 +267,7 @@ export default function Sidebar(props) {
|
|||
projectId: project.id,
|
||||
pageName: '_Sidebar',
|
||||
title: '_Sidebar',
|
||||
commit_message: '',
|
||||
message: '',
|
||||
content_base64: Base64.encode(content)
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
@ -303,20 +303,18 @@ export default function Sidebar(props) {
|
|||
e.stopPropagation();
|
||||
setVisible(item);
|
||||
setIsEditName(type);
|
||||
let title = item.title.trim();
|
||||
const isFile = title.startsWith('[[') && title.endsWith(']]');
|
||||
title = isFile ? title.substring(2,title.length-2) : title.substring(2, title.length);
|
||||
const {titleStr, title_sub} = item;
|
||||
type === 2 && getWiki({
|
||||
owner: owner,
|
||||
repo: projectsId,
|
||||
pageName: title,
|
||||
pageName: title_sub,
|
||||
projectId: project.id
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
setWikiContent(res.data.md_content);
|
||||
}
|
||||
})
|
||||
setMenuName(title);
|
||||
setMenuName(titleStr);
|
||||
}
|
||||
|
||||
// 新增子目录 或者 重命名目录
|
||||
|
|
@ -329,9 +327,8 @@ export default function Sidebar(props) {
|
|||
setAddMenuError("不能仅输入空格");
|
||||
return;
|
||||
}
|
||||
const regEn = /[\\/:*?"<>|[\]-]/g;
|
||||
if (regEn.test(menuName)) {
|
||||
setAddMenuError('不能有特殊字符: \\ / : * ? \" < > | [ \] -');
|
||||
if (isEditName === 2 && /^-/.test(menuName)) {
|
||||
setAddMenuError('不能以-开头');
|
||||
return;
|
||||
}
|
||||
if(!isEditName){
|
||||
|
|
@ -356,14 +353,16 @@ export default function Sidebar(props) {
|
|||
}else{
|
||||
// isEditName 1 编辑目录名称 2编辑页面名称
|
||||
const titleToJudge = isEditName === 2 ? `[[${menuName}]]` : `- ${menuName}`;
|
||||
const {children, node, title, key} = visible;
|
||||
const list = findNodeByChildrenKey(menuList, key) || [];
|
||||
if(title.trim() === titleToJudge){
|
||||
const {key, titleStr, title_sub} = visible;
|
||||
// 判断是否有修改名称
|
||||
if(titleStr === menuName){
|
||||
setAddMenuError("请修改名称");
|
||||
return
|
||||
}
|
||||
if(list.map(item=>item.title.trim()).includes(titleToJudge)){
|
||||
message.error("不能与同级目录名称相同");
|
||||
// 找兄弟节点
|
||||
const list = findBrotherNodesByKey(menuList, key) || [];
|
||||
if(list.map(item=>item.titleStr).includes(menuName)){
|
||||
setAddMenuError("不能与同级目录名称相同");
|
||||
return
|
||||
}
|
||||
// wiki名称不可重复
|
||||
|
|
@ -380,17 +379,16 @@ export default function Sidebar(props) {
|
|||
})
|
||||
if(isEditName === 2){
|
||||
// 编辑页面名称-> 修改wiki
|
||||
const oldTitle = title.substring(title.indexOf('[[')+2, title.indexOf(']]'))
|
||||
updateWiki({
|
||||
owner,
|
||||
repo: projectsId,
|
||||
projectId: project.id,
|
||||
// 原名称
|
||||
pageName: oldTitle,
|
||||
pageName: title_sub,
|
||||
// 现名称
|
||||
title: menuName,
|
||||
content_base64: wikiContent,
|
||||
commit_message: '',
|
||||
message: '',
|
||||
}).then(res=>{
|
||||
if(res && res.message === '200'){
|
||||
// 修改wiki名称接口请求成功,更新sidebar
|
||||
|
|
@ -424,6 +422,20 @@ export default function Sidebar(props) {
|
|||
}
|
||||
}
|
||||
|
||||
function findBrotherNodesByKey(list, key){
|
||||
for (let index = 0; index < list.length; index++) {
|
||||
const element = list[index];
|
||||
if (element.key == key) {
|
||||
return list;
|
||||
}else if (element.children && element.children.length) {
|
||||
let result = findBrotherNodesByKey(element.children, key);
|
||||
if (result.length) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function onDrop(info){
|
||||
// dragNode: 拖拽的节点 node: 放入的节点
|
||||
|
|
|
|||
|
|
@ -58,10 +58,8 @@ export default function UploadWiki(props) {
|
|||
message.error('只能上传md、txt文件');
|
||||
return false;
|
||||
}
|
||||
|
||||
let regEn = /[\\/:*?"<>|[\]-]/g;
|
||||
if (regEn.test(file.name)) {
|
||||
message.error('文件名不能有特殊字符: \\ / : * ? \" < > | [ \] -');
|
||||
if (/^-/.test(file.name)) {
|
||||
message.error('文件名不能以-开头');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +83,7 @@ export default function UploadWiki(props) {
|
|||
projectId: project.id,
|
||||
pageName: '_Sidebar',
|
||||
title: '_Sidebar',
|
||||
commit_message: '',
|
||||
message: '',
|
||||
content_base64: Base64.encode(treeToMd(sidebarList))
|
||||
}).then(res => {
|
||||
if (res && res.message === "200") {
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@ ul,ol,dl{
|
|||
text-align: right;
|
||||
}
|
||||
.main{
|
||||
width: 1200px;
|
||||
// width: 1200px;
|
||||
padding:20px;
|
||||
margin:20px auto;
|
||||
margin:0px auto;
|
||||
background: #fff;
|
||||
border-radius: 2px;
|
||||
border:1px solid #eee;
|
||||
|
|
@ -65,8 +65,9 @@ ul,ol,dl{
|
|||
border-radius: 2px;
|
||||
}
|
||||
.normal{
|
||||
width: 1200px;
|
||||
margin:0px auto;
|
||||
// width: 1200px;
|
||||
// margin:0px auto;
|
||||
padding:0px 20px;
|
||||
}
|
||||
/* 背景色 */
|
||||
.back-white{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import { withRouter } from "react-router";
|
||||
import { SnackbarHOC } from "educoder";
|
||||
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
|
||||
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
|
||||
|
||||
|
||||
const Iframe = (props) => {
|
||||
|
||||
const history = props.history
|
||||
const location = history.location
|
||||
|
||||
// if (!location.state.url) {
|
||||
// history.push("/404");
|
||||
// }
|
||||
|
||||
function iframeLoad() {
|
||||
let myIframe = document.getElementById("iframe");
|
||||
// if (myIframe.contentWindow.location && myIframe.contentWindow.location.href) {
|
||||
// window.location.href = 'http://118.145.132.196:3000/product/llm/llm-chat'
|
||||
// //myIframe.contentWindow.location.href
|
||||
// }
|
||||
}
|
||||
|
||||
return <iframe
|
||||
id="iframe"
|
||||
width="100%"
|
||||
className="test-iframe"
|
||||
src={ 'https://testllm.trustie.net' }
|
||||
onLoad={iframeLoad}
|
||||
></iframe>
|
||||
}
|
||||
|
||||
export default withRouter(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Iframe))));
|
||||
|
|
@ -387,7 +387,7 @@ class Infos extends Component {
|
|||
}
|
||||
<Menu.Item key="0"><Link to={`/${user && user.login}`} onClick={()=>this.chooseTab("0")}><i className="iconfont icon-gailan"></i>活动概览</Link></Menu.Item>
|
||||
<Menu.Item key="1"><Link to={`/${user && user.login}/statistics`}><i className="iconfont icon-shujutongji"></i>数据统计</Link></Menu.Item>
|
||||
<Menu.Item key="2"><Link to={`/${user && user.login}/projects`}><i className="iconfont icon-xiangmu"></i>参与项目</Link></Menu.Item>
|
||||
<Menu.Item key="2"><Link to={`/${user && user.login}/projects`}><i className="iconfont icon-xiangmu"></i>参与代码库</Link></Menu.Item>
|
||||
{
|
||||
current_user && user && user.login === current_user.login ?
|
||||
<Menu.Item key="3">
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ class InfosUser extends Component {
|
|||
<Spin spinning={isSpin}>
|
||||
<div className="list-r-operation" style={{padding:"20px"}}>
|
||||
<Search
|
||||
placeholder="输入项目名称关键字进行搜索"
|
||||
placeholder="输入代码库名称关键字进行搜索"
|
||||
enterButton="搜索"
|
||||
size="large"
|
||||
onSearch={()=>{this.get_projects()}}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import React , { forwardRef, useEffect } from 'react';
|
||||
import { Form , Checkbox , Input, Radio , Button , Cascader } from 'antd';
|
||||
import { Form , Checkbox , Input, Radio , Button , Cascader , Row } from 'antd';
|
||||
import { AlignCenter } from '../../Component/layout';
|
||||
import './Index.scss';
|
||||
import { locData } from '../../Utils/locData';
|
||||
import Axios from 'axios';
|
||||
import {Link} from "react-router-dom";
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const { TextArea } = Input;
|
||||
export default Form.create()(
|
||||
|
|
@ -60,22 +60,24 @@ export default Form.create()(
|
|||
)}
|
||||
</Form.Item>
|
||||
<Link className='gotoUpdateEmail mr30' to='/settings/phone'><i className='iconfont icon-bianji1 font-15 mr5'></i>更改手机号</Link>
|
||||
<Form.Item label="邮箱">
|
||||
{getFieldDecorator("email",{
|
||||
rules:[{required:true,message:"请输入邮箱账号"}]
|
||||
})(
|
||||
<Input placeholder="请点击右侧更改邮箱按钮绑定邮箱" disabled style={{width:"400px"}}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Link className='gotoUpdateEmail mr30' to='/settings/emails'><i className='iconfont icon-bianji1 font-15 mr5'></i>更改邮箱</Link>
|
||||
<Form.Item label="">
|
||||
{getFieldDecorator("show_email",{
|
||||
rules:[],
|
||||
valuePropName:"checked"
|
||||
})(
|
||||
<Checkbox>在个人主页展示</Checkbox>
|
||||
)}
|
||||
</Form.Item>
|
||||
<div>
|
||||
<Form.Item label="邮箱">
|
||||
{getFieldDecorator("email",{
|
||||
rules:[{required:true,message:"请输入邮箱账号"}]
|
||||
})(
|
||||
<Input placeholder="请点击右侧更改邮箱按钮绑定邮箱" disabled style={{width:"400px"}}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Link className='gotoUpdateEmail mr30' to='/settings/emails'><i className='iconfont icon-bianji1 font-15 mr5'></i>更改邮箱</Link>
|
||||
<Form.Item label="" >
|
||||
{getFieldDecorator("show_email",{
|
||||
rules:[],
|
||||
valuePropName:"checked"
|
||||
})(
|
||||
<Checkbox>在个人主页展示</Checkbox>
|
||||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Form.Item label="昵称">
|
||||
{getFieldDecorator("nickname",{
|
||||
rules:[]
|
||||
|
|
@ -110,6 +112,7 @@ export default Form.create()(
|
|||
<Checkbox>在个人主页展示</Checkbox>
|
||||
)}
|
||||
</Form.Item>
|
||||
<div>
|
||||
<Form.Item label="地区">
|
||||
{getFieldDecorator("location",{
|
||||
rules:[]
|
||||
|
|
@ -125,6 +128,7 @@ export default Form.create()(
|
|||
<Checkbox>在个人主页展示</Checkbox>
|
||||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Form.Item label="签名">
|
||||
{getFieldDecorator("description",{
|
||||
rules:[]
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ function Index(props){
|
|||
const { pathname } = props && props.location;
|
||||
|
||||
const [ key , setKey ] = useState("0");
|
||||
const [ type, setType] = useState('0');
|
||||
const [ type, setType] = useState('1');
|
||||
|
||||
useEffect(()=>{
|
||||
if(pathname){
|
||||
|
|
@ -55,8 +55,8 @@ function Index(props){
|
|||
<Menu.Item key="3" className="font-16" onClick={()=>{props.history.push('/settings/phone')}}>手机号管理</Menu.Item>
|
||||
<Menu.Item key="0" className="font-16" onClick={()=>{props.history.push('/settings/emails')}}>邮箱管理</Menu.Item>
|
||||
<Menu.Item key="1" className="font-16" onClick={()=>{props.history.push('/settings/password')}}>密码管理</Menu.Item>
|
||||
<Menu.Item key="4" className="font-16" onClick={()=>{props.history.push('/settings/verification')}}>实名认证</Menu.Item>
|
||||
<Menu.Item key="2" className="font-16" onClick={()=>{props.history.push('/settings/cancel')}}>账号注销</Menu.Item>
|
||||
{/* <Menu.Item key="4" className="font-16" onClick={()=>{props.history.push('/settings/verification')}}>实名认证</Menu.Item> */}
|
||||
{/* <Menu.Item key="2" className="font-16" onClick={()=>{props.history.push('/settings/cancel')}}>账号注销</Menu.Item> */}
|
||||
</Menu>}
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import img1 from '../../Images/personalInfo3.png';
|
|||
import { setmiyah } from '../../../common/Component';
|
||||
import { useEffect } from 'react';
|
||||
import Phone from './Phone';
|
||||
import { Encrypt } from '../../../common/Env';
|
||||
|
||||
export default Form.create()(
|
||||
forwardRef((props)=>{
|
||||
|
|
@ -104,7 +105,7 @@ export default Form.create()(
|
|||
const map = type === '0' ? passMap : updatePsdMap;
|
||||
if(value){
|
||||
current_user && Axios.post(`/v1/${current_user.login}/check_password.json`,{
|
||||
password: value
|
||||
password: Encrypt(value)
|
||||
}).then(res=>{
|
||||
if(res && !res.data.status){
|
||||
if(type === '0'){
|
||||
|
|
@ -195,7 +196,8 @@ export default Form.create()(
|
|||
function confirmUpdateEmail(e){
|
||||
validateFields((error,values)=>{
|
||||
if(!error){
|
||||
setVisible(true);
|
||||
// setVisible(true);
|
||||
updateEmailOrPsd();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -203,9 +205,9 @@ export default Form.create()(
|
|||
function updateEmailOrPsd(){
|
||||
if(type === '0'){
|
||||
const {code, email, password1} = getFieldsValue();
|
||||
if(code && email && password1){
|
||||
if( email && password1){
|
||||
current_user && Axios.patch(`/v1/${current_user.login}/update_email.json`,{
|
||||
code, email, password: password1
|
||||
code:"123123", email, password:Encrypt(password1)
|
||||
}).then(res=>{
|
||||
if(res && !res.data.status){
|
||||
setPassMap({password: undefined, email: undefined, code: undefined});
|
||||
|
|
@ -221,10 +223,13 @@ export default Form.create()(
|
|||
}
|
||||
}else{
|
||||
const values = getFieldsValue();
|
||||
const { old_password , password , new_password_repeat } = values;
|
||||
const url = `/accounts/change_password.json`;
|
||||
Axios.post(url,{
|
||||
login:current_user && current_user.login,
|
||||
...values
|
||||
old_password:Encrypt(old_password),
|
||||
password:Encrypt(password),
|
||||
new_password_repeat:Encrypt(new_password_repeat),
|
||||
}).then(result=>{
|
||||
if(result && result.data){
|
||||
resetFields();
|
||||
|
|
@ -242,10 +247,11 @@ export default Form.create()(
|
|||
<Fragment>
|
||||
{type === '0' ?
|
||||
<div>
|
||||
<div className='tipsBox mb15'><img src={img1} alt="" width={16} className='mr10'/>更改邮箱后,您在<span className='spanTil'>GitLink</span> 的登录账号、接收通知的邮件地址将同步变更。请谨慎更改!</div>
|
||||
{/* <div className='tipsBox mb15'><img src={img1} alt="" width={16} className='mr10'/>更改邮箱后,您在<span className='spanTil'>GitLink</span> 的登录账号、接收通知的邮件地址将同步变更。请谨慎更改!</div> */}
|
||||
<div className='tipsBox mb20 emailBox'>现邮箱地址<span className='ml10 email spanTil'>{current_user && current_user.email}</span></div>
|
||||
<div className='updateEmail mb20'>更改邮箱</div>
|
||||
<Form layout={'inline'} className="formBase passMan personalUpdateInfoForm">
|
||||
<div>
|
||||
<Form.Item label="登录密码" className={`${passMap.password ? 'hasSuccess' : ''}`}>
|
||||
{getFieldDecorator("password1",{
|
||||
rules:[
|
||||
|
|
@ -257,6 +263,7 @@ export default Form.create()(
|
|||
<Input.Password placeholder="请输入登录密码" autoComplete={"new-password"} style={{width:"400px"}}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Form.Item label="新邮箱地址" className={`${passMap.email ? 'hasSuccess' : ''}`}>
|
||||
{getFieldDecorator("email",{
|
||||
rules:[
|
||||
|
|
@ -269,7 +276,7 @@ export default Form.create()(
|
|||
<Input placeholder="请输入新邮箱地址" style={{width:"400px"}} autoComplete={"off"}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<div>
|
||||
{/* <div>
|
||||
<Form.Item label="邮箱验证码" className={`${passMap.code ? 'hasSuccess' : ''}`}>
|
||||
{getFieldDecorator("code",{
|
||||
rules:[
|
||||
|
|
@ -282,10 +289,10 @@ export default Form.create()(
|
|||
)}
|
||||
</Form.Item>
|
||||
{countDown ? <Button className='getCaptchaBut ml50' disabled>重发 ({countDown})</Button> : <Button className='getCaptchaBut ml50' onClick={getCaptcha} disabled={!emailValue}>获取验证码</Button>}
|
||||
</div>
|
||||
</div> */}
|
||||
<AlignCenter style={{marginTop:"20px"}}>
|
||||
<span className="ant-form-item-label mr10"></span>
|
||||
<Button className={`${passMap.password && passMap.email && passMap.code ? 'but25' : ''}`} type={"primary"} onClick={confirmUpdateEmail} disabled={!(passMap.password && passMap.email && passMap.code)}>确认更改</Button>
|
||||
<Button className={`${passMap.password && passMap.email ? 'but25' : ''}`} type={"primary"} onClick={confirmUpdateEmail} disabled={!(passMap.password && passMap.email )}>确认更改</Button>
|
||||
</AlignCenter>
|
||||
</Form>
|
||||
</div> :
|
||||
|
|
@ -302,6 +309,7 @@ export default Form.create()(
|
|||
<Input.Password placeholder="请输入旧密码" autoComplete={"new-password"} style={{width:"400px"}}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<div>
|
||||
<Form.Item label="新密码" className={`${updatePsdMap.password ? 'hasSuccess' : ''}`}>
|
||||
{getFieldDecorator("password",{
|
||||
rules:[
|
||||
|
|
@ -314,6 +322,7 @@ export default Form.create()(
|
|||
<Input.Password placeholder="请输入新密码" style={{width:"400px"}} onChange={(e)=>{setNewPass(e.target.value)}}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Form.Item label="确认新密码" className={`${updatePsdMap.password1 ? 'hasSuccess' : ''}`}>
|
||||
{getFieldDecorator("new_password_repeat",{
|
||||
rules:[
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import Modals from '../../Component/PublicModal/Index';
|
|||
import { AlignCenter } from '../../Component/layout';
|
||||
import img1 from '../../Images/personalInfo3.png';
|
||||
import { setmiyah } from '../../../common/Component';
|
||||
import { Encrypt } from '../../../common/Env';
|
||||
import Axios from 'axios';
|
||||
|
||||
|
||||
|
|
@ -21,7 +22,7 @@ export default Form.create()(
|
|||
const map = passMap;
|
||||
if(value){
|
||||
current_user && value.length > 7 && Axios.post(`/v1/${current_user.login}/check_password.json`,{
|
||||
password: value
|
||||
password: Encrypt(value)
|
||||
}).then(res=>{
|
||||
if(res && !res.data.status){
|
||||
map.logpassword = value;
|
||||
|
|
@ -138,16 +139,17 @@ export default Form.create()(
|
|||
function confirmUpdatePhone(){
|
||||
validateFields((error,values)=>{
|
||||
if(!error){
|
||||
setVisible(true);
|
||||
// setVisible(true);
|
||||
updateEmailOrPsd();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function updateEmailOrPsd(){
|
||||
const {mescode, phone, logpassword} = getFieldsValue();
|
||||
if(mescode && phone && logpassword){
|
||||
if(phone && logpassword){
|
||||
current_user && Axios.patch(`/v1/${current_user.login}/update_phone.json`,{
|
||||
code:mescode, phone, password:logpassword
|
||||
code:"123123", phone, password: Encrypt(logpassword)
|
||||
}).then(res=>{
|
||||
if(res && !res.data.status){
|
||||
setPassMap({logpassword: undefined, phone: undefined, code: undefined});
|
||||
|
|
@ -182,21 +184,23 @@ export default Form.create()(
|
|||
<p>更改手机号后,您在GitLink的登录账号将同步变更。请再次确认。</p>
|
||||
</div>
|
||||
</Modals>
|
||||
<div className='tipsBox mb15'><img src={img1} alt="" width={16} className='mr10'/>更改手机号后,您在<span className='spanTil'>GitLink</span> 的登录账号将同步变更。请谨慎更改!</div>
|
||||
{/* <div className='tipsBox mb15'><img src={img1} alt="" width={16} className='mr10'/>更改手机号后,您在<span className='spanTil'>GitLink</span> 的登录账号将同步变更。请谨慎更改!</div> */}
|
||||
{current_user && current_user.phone && <div className='tipsBox mb20 emailBox'>现手机号码<span className='ml10 email spanTil'>{current_user.phone}</span></div> }
|
||||
<div className='updateEmail mb20'>更改手机号</div>
|
||||
<Form layout={'inline'} className="formBase passMan personalUpdateInfoForm">
|
||||
<Form.Item label="登录密码" className={`${passMap.logpassword ? 'hasSuccess' : ''}`}>
|
||||
{getFieldDecorator("logpassword",{
|
||||
rules:[
|
||||
{required:true,message:"请输入登录密码"},
|
||||
{validator:(rule, value, callback)=>checkPsd(rule, value, callback)}
|
||||
],
|
||||
validateTrigger:"onChange",
|
||||
})(
|
||||
<Input.Password placeholder="请输入登录密码" autoComplete={"new-password"} style={{width:"400px"}}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<div>
|
||||
<Form.Item label="登录密码" className={`${passMap.logpassword ? 'hasSuccess' : ''}`}>
|
||||
{getFieldDecorator("logpassword",{
|
||||
rules:[
|
||||
{required:true,message:"请输入登录密码"},
|
||||
{validator:(rule, value, callback)=>checkPsd(rule, value, callback)}
|
||||
],
|
||||
validateTrigger:"onChange",
|
||||
})(
|
||||
<Input.Password placeholder="请输入登录密码" autoComplete={"new-password"} style={{width:"400px"}}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Form.Item label="新手机号码" className={`${passMap.phone ? 'hasSuccess' : ''}`}>
|
||||
{getFieldDecorator("phone",{
|
||||
rules:[
|
||||
|
|
@ -208,7 +212,7 @@ export default Form.create()(
|
|||
<Input placeholder="请输入新手机号码" style={{width:"400px"}} autoComplete={"off"}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<div>
|
||||
{/* <div>
|
||||
<Form.Item label="短信验证码" className={`${passMap.mescode ? 'hasSuccess' : ''}`}>
|
||||
{getFieldDecorator("mescode",{
|
||||
rules:[
|
||||
|
|
@ -221,10 +225,10 @@ export default Form.create()(
|
|||
)}
|
||||
</Form.Item>
|
||||
{countDown ? <Button className='getCaptchaBut ml50' disabled>重发 ({countDown})</Button> : <Button className='getCaptchaBut ml50' onClick={getCaptcha} disabled={!phoneValue}>获取验证码</Button>}
|
||||
</div>
|
||||
</div> */}
|
||||
<AlignCenter style={{marginTop:"20px"}}>
|
||||
<span className="ant-form-item-label mr10"></span>
|
||||
<Button onClick={confirmUpdatePhone} className={`${passMap.logpassword && passMap.phone && passMap.mescode ? 'but25' : ''}`} type={"primary"} disabled={!(passMap.logpassword && passMap.phone && passMap.mescode)}>确认更改</Button>
|
||||
<Button onClick={confirmUpdatePhone} className={`${passMap.logpassword && passMap.phone ? 'but25' : ''}`} type={"primary"} disabled={!(passMap.logpassword && passMap.phone)}>确认更改</Button>
|
||||
</AlignCenter>
|
||||
</Form>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
import React , { forwardRef, useState } from 'react';
|
||||
import { Modal , Form , Button , Input } from 'antd';
|
||||
import Axios from 'axios';
|
||||
import { Encrypt } from '../../../../common/Env';
|
||||
const { TextArea } = Input;
|
||||
|
||||
export default Form.create()(forwardRef((props)=>{
|
||||
const { getFieldDecorator , validateFields } = props && props.form;
|
||||
const { onCancel, visible , current_user} = props;
|
||||
const [ loading , setLoading ] =useState(false);
|
||||
|
||||
|
||||
function onDelete(){
|
||||
validateFields((error,values)=>{
|
||||
if(!error && current_user){
|
||||
const { password } = values;
|
||||
setLoading(true);
|
||||
const url = `/v1/${current_user.login}.json`;
|
||||
Axios.delete(url,{
|
||||
data:{...values,password:Encrypt(password)}
|
||||
}).then(result=>{
|
||||
if(result.data && result.data.status === 0){
|
||||
window.location.href = `/`;
|
||||
onCancel();
|
||||
}
|
||||
setLoading(false);
|
||||
}).catch(error=>{setLoading(false);})
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
return(
|
||||
<Modal
|
||||
title="注销账号"
|
||||
width={560}
|
||||
visible={visible}
|
||||
footer={null}
|
||||
onCancel={onCancel}
|
||||
destroyOnClose={true}
|
||||
>
|
||||
<div>
|
||||
<p className='AlignCenter font-bd font-17'><i className='iconfont icon-shanchu_important font-25 color-red mr5'/>是否仍要注销?</p>
|
||||
<p className='mt15'>注销后你将丢失该帐号产生的所有数据,一旦注销相关数据将不可恢复,请输入登录密码再次确认</p>
|
||||
<Form className='mt25'>
|
||||
<Form.Item label="密码校验">
|
||||
{getFieldDecorator("password",{
|
||||
rules:[
|
||||
{required:true,message:"请输入登录密码"},
|
||||
// {validator:(rule, value, callback)=>checkNewPass(rule, value, callback, NewPassRepeat)}
|
||||
],
|
||||
validateFirst: true,
|
||||
validateTrigger:"onBlur",
|
||||
})(
|
||||
<Input.Password placeholder="请输入登录密码"/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="注销原因">
|
||||
{getFieldDecorator("memo",{
|
||||
rules:[{required:true,message:"请输入注销原因"}],
|
||||
})(
|
||||
<TextArea rows={3} maxLength={500} placeholder="我们非常遗憾看到您想要注销账号。在您做出最终决定之前,请告诉我们您注销的原因,这将帮助我们改进社区服务。您的反馈对我们至关重要。"
|
||||
/>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<div style={{textAlign:"center"}}>
|
||||
<Button onClick={onDelete} style={{minWidth:"95px"}} loading={loading}>仍要注销</Button>
|
||||
<Button type={"primary"} style={{width:"95px"}} className='ml25' onClick={onCancel}>再想想</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
)})
|
||||
)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
|
|
@ -186,4 +186,71 @@ i.color-orange05:hover {
|
|||
|
||||
.color-light-green {
|
||||
color: #29bd8b !important;
|
||||
}
|
||||
|
||||
.AlignTop {
|
||||
display:flex;
|
||||
align-items: flex-start
|
||||
}
|
||||
.WhiteBack {
|
||||
background-color:#fff;
|
||||
border-radius:5px
|
||||
}
|
||||
.Box {
|
||||
display:flex;
|
||||
align-items:flex-start
|
||||
}
|
||||
.LongWidth {
|
||||
flex:1;
|
||||
width:0;
|
||||
border-radius:5px;
|
||||
margin-bottom:30px
|
||||
}
|
||||
.ShortWidth {
|
||||
width:300px;
|
||||
border-radius:5px;
|
||||
margin-bottom:30px
|
||||
}
|
||||
.Gap {
|
||||
padding-left:20px;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
.AlignCenter {
|
||||
display:flex;
|
||||
align-items: center
|
||||
}
|
||||
.FlexAJ {
|
||||
display:flex;
|
||||
align-items: center;
|
||||
justify-content: space-between
|
||||
}
|
||||
.mt25 {
|
||||
margin-top:25px
|
||||
}
|
||||
.User {
|
||||
display:flex;
|
||||
font-weight: bold;
|
||||
align-items: center
|
||||
}
|
||||
.User img {
|
||||
width:30px;
|
||||
height:30px;
|
||||
border-radius:50%
|
||||
}
|
||||
.User span {
|
||||
margin-left:8px
|
||||
}
|
||||
.latex-error {
|
||||
border: 1px solid #ff818266;
|
||||
border-radius: 6px;
|
||||
background-color: #ffebe9;
|
||||
padding: 10px 8px;
|
||||
font-size: 12px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.test-iframe {
|
||||
margin-top: -48px;
|
||||
vertical-align:bottom;
|
||||
height: 100vh;
|
||||
}
|
||||
|
|
@ -16,10 +16,7 @@ class Shixunauthority extends Component {
|
|||
{(!current_user || !current_user.login) && (
|
||||
<p style={{display:"inline"}}>您可尝试<a href={`/login`} className="color-blue">登录</a>或</p>
|
||||
)}
|
||||
<a href="/" className="color-blue">返回首页</a>,也可以通过
|
||||
<a target="_blank"
|
||||
href="https://qm.qq.com/cgi-bin/qm/qr?k=YVGUhY7uK8ovpyd7tG_lHe2qGZ63LOij&jump_from=webapi"
|
||||
className="color-blue">QQ</a>向我们反馈
|
||||
<a href="/" className="color-blue">返回首页</a>
|
||||
</p>
|
||||
</div>
|
||||
{/*<div style="clear:both;"></div>*/}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,6 @@ class http500 extends Component {
|
|||
<p style={{display:"inline"}}>您可尝试<a href={`/login`} className="color-blue">登录</a>或</p>
|
||||
)}
|
||||
<a href="/" className="color-blue">返回首页</a>
|
||||
,也可通过
|
||||
<a target="_blank"
|
||||
href="https://qm.qq.com/cgi-bin/qm/qr?k=YVGUhY7uK8ovpyd7tG_lHe2qGZ63LOij&jump_from=webapi"
|
||||
className="color-blue">QQ</a>向我们反馈
|
||||
</p>
|
||||
</div>
|
||||
{/*<div style="clear:both;"></div>*/}
|
||||
|
|
|
|||
|
|
@ -11,11 +11,7 @@ class Shixunnopage extends Component {
|
|||
<p className="font-16 mt56 newImages">
|
||||
<p>服务器异常,请稍后重试</p>
|
||||
您可尝试<a href="javascript:location.reload();" className="color-blue">刷新页面</a>或<a href="/"
|
||||
className="color-blue">返回首页</a>
|
||||
,也可以通过
|
||||
<a target="_blank"
|
||||
href="https://qm.qq.com/cgi-bin/qm/qr?k=YVGUhY7uK8ovpyd7tG_lHe2qGZ63LOij&jump_from=webapi"
|
||||
className="color-blue">QQ</a>向我们反馈
|
||||
className="color-blue">返回首页</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import cookie from 'react-cookies';
|
|||
import './LoginDialog.css';
|
||||
import { broadcastChannelPostMessage } from 'educoder'
|
||||
import Notcompletedysl from "../user/Notcompletedysl";
|
||||
import { Encrypt } from '../../common/Env';
|
||||
|
||||
const $ = window.$;
|
||||
var wait = 60;
|
||||
|
|
@ -331,7 +332,7 @@ class LoginDialog extends Component {
|
|||
this.setState({
|
||||
isphone: flag,
|
||||
//查询第三方登录信息
|
||||
settings: JSON.parse(localStorage.getItem("chromesetting")),
|
||||
settings: localStorage.getItem("chromesetting") !=="undefined" && JSON.parse(localStorage.getItem("chromesetting")),
|
||||
})
|
||||
|
||||
if (this.props.isRender != undefined) {
|
||||
|
|
@ -371,7 +372,7 @@ class LoginDialog extends Component {
|
|||
let url = '/accounts/login.json'
|
||||
axios.post(url, {
|
||||
login: newloginValue,
|
||||
password: newpassValue,
|
||||
password: Encrypt(newpassValue),
|
||||
autologin: isGoingValue
|
||||
}
|
||||
).then((response) => {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import axios from 'axios';
|
|||
import OtherLogin from "./component/otherLogin";
|
||||
import cookie from 'react-cookies';
|
||||
import './LoginRegisterPage.scss';
|
||||
import { Encrypt } from "../../common/Env";
|
||||
|
||||
function Login(props){
|
||||
const [message,setMessage] = useState();
|
||||
|
|
@ -18,6 +19,7 @@ function Login(props){
|
|||
const {getFieldDecorator } = form;
|
||||
const {search} = location;
|
||||
|
||||
|
||||
useEffect(()=>{
|
||||
//控制密码输入框在DOM不可见value
|
||||
clear();
|
||||
|
|
@ -40,7 +42,7 @@ function Login(props){
|
|||
if (!err) {
|
||||
axios.post(`/accounts/login.json`, {
|
||||
login: values.username,
|
||||
password: values.password,
|
||||
password: Encrypt(values.password),
|
||||
autologin: values.remember?1:0,
|
||||
}).then((response) => {
|
||||
if (!response.data.login) {
|
||||
|
|
@ -78,7 +80,7 @@ function Login(props){
|
|||
<div>
|
||||
<div className="right_cont login_content">
|
||||
<div className="login_register_head mb30">
|
||||
<span>欢迎登录 GitLink</span>
|
||||
<span>欢迎登录 {mygetHelmetapi && mygetHelmetapi.name}</span>
|
||||
<span className="link_span">没有账号?<Link to={`/register`}>去注册</Link></span>
|
||||
</div>
|
||||
<p className = {message?"message active mb10":"message"}>{message}</p>
|
||||
|
|
@ -116,7 +118,7 @@ function Login(props){
|
|||
initialValue: cookie.load('autologin'),
|
||||
})(<Checkbox>下次自动登录</Checkbox>)}
|
||||
</Form.Item>
|
||||
<Link to="/resetPassword" className="goResetPsdBut">忘记密码?</Link>
|
||||
{/* <Link to="/resetPassword" className="goResetPsdBut">忘记密码?</Link> */}
|
||||
</div>
|
||||
<Button type="primary" htmlType="submit" onClick={handleSubmit} className="login_register_cofBut">登录</Button>
|
||||
</Form>
|
||||
|
|
@ -137,7 +139,7 @@ function Login(props){
|
|||
// })
|
||||
// }
|
||||
// </p>
|
||||
<OtherLogin />
|
||||
// <OtherLogin />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,159 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { Form, Input, Button, Checkbox , Tooltip } from "antd";
|
||||
import { Link } from "react-router-dom";
|
||||
import axios from 'axios';
|
||||
// import educoderLogo from '../login/educoder.png';
|
||||
// import qqlogo from '../login/qq@2x.png';
|
||||
// import WeChatlogo from '../login/WeChat@2x.png';
|
||||
// import giteelogo from '../login/gitee.png';
|
||||
// import githublogo from '../login/github.png';
|
||||
import cookie from 'react-cookies';
|
||||
import './LoginRegisterPageNew.scss';
|
||||
import { Encrypt } from "../../common/Env";
|
||||
import { getOrzCompanyList } from "../../forge/Information/api";
|
||||
|
||||
function Login(props){
|
||||
const [message,setMessage] = useState();
|
||||
// const [setting, setSetting] = useState(undefined);
|
||||
const {form, location, mygetHelmetapi} = props;
|
||||
const {getFieldDecorator } = form;
|
||||
const {search} = location;
|
||||
|
||||
|
||||
useEffect(()=>{
|
||||
//控制密码输入框在DOM不可见value
|
||||
clear();
|
||||
//获取第三方登录平台信息
|
||||
// setSetting(JSON.parse(localStorage.getItem("chromesetting")));
|
||||
},[])
|
||||
|
||||
// 配置网页标题
|
||||
useEffect(()=>{
|
||||
if(mygetHelmetapi){
|
||||
const {name} = mygetHelmetapi;
|
||||
document.title = name;
|
||||
}
|
||||
}, [mygetHelmetapi])
|
||||
|
||||
// 登录表单提交
|
||||
function handleSubmit(){
|
||||
setMessage(undefined);
|
||||
form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
axios.post(`/accounts/login.json`, {
|
||||
login: values.username,
|
||||
password: Encrypt(values.password),
|
||||
autologin: values.remember?1:0,
|
||||
}).then((response) => {
|
||||
if (!response.data.login) {
|
||||
response.data.status === -2 ? setMessage(response.data.message) : setMessage("错误的账号或密码");
|
||||
} else {
|
||||
//判断用户是否选择【下次自动登录】
|
||||
cookie.save('autologin',values.remember);
|
||||
cookie.save('supplyphone',true);
|
||||
cookie.save("login",response.data.login);
|
||||
//意见反馈
|
||||
const searchParams = new URLSearchParams(search.substring(1));
|
||||
const goPage = searchParams.get("go_page");
|
||||
// 获取工作台,如果有已开通的工作台,则跳转到第一个工作台
|
||||
if(goPage){
|
||||
window.location.href = goPage
|
||||
}else{
|
||||
getOrzCompanyList().then(res=>{
|
||||
if(res && res.data && res.data.rows && res.data.rows[0]){
|
||||
window.location.href = `${ mygetHelmetapi && mygetHelmetapi.common.zone }/${res.data.rows[0].enterpriseIdentifier}`
|
||||
}else{
|
||||
window.location.href = `/${response.data.login}`
|
||||
}
|
||||
}).catch(()=>{
|
||||
window.location.href = `/${response.data.login}`
|
||||
})
|
||||
}
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log('error',error);
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//清除密码框的value属性->DOM看不见密码值
|
||||
function clear(){
|
||||
const password = document.getElementById("login_password");
|
||||
if(password && password.type==="password"){
|
||||
setTimeout(()=>{
|
||||
password.removeAttribute('value');
|
||||
},0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return(
|
||||
<div className="right_cont login_content">
|
||||
<div className="login_register_head mb60">
|
||||
<p>欢迎登录 <span className="head_blue">{mygetHelmetapi && mygetHelmetapi.name}</span></p>
|
||||
</div>
|
||||
<p className = {message?"message active mb10":"message"}>{message}</p>
|
||||
<Form className="login-form">
|
||||
<Form.Item>
|
||||
{getFieldDecorator('username',{
|
||||
rules:[
|
||||
{
|
||||
required:true,
|
||||
message:"请输入手机号/邮箱/用户名"
|
||||
}
|
||||
],
|
||||
validateTrigger:"onBlur",
|
||||
})(<Input className="account" placeholder="请输入手机号/邮箱/用户名" prefix={<div className="input_icon"></div>} />)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
{getFieldDecorator('password', {
|
||||
rules: [
|
||||
{
|
||||
required:true,
|
||||
message:"请输入登录密码"
|
||||
}
|
||||
],
|
||||
validateTrigger:"onBlur",
|
||||
})(
|
||||
<Input.Password className="psd" placeholder="请输入登录密码" onBlur={clear} onChange={clear} prefix={<div className="input_icon"></div>} />,
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<div className="login_register_head login mb60">
|
||||
<Form.Item>
|
||||
{getFieldDecorator('remember', {
|
||||
valuePropName: 'checked',
|
||||
initialValue: cookie.load('autologin'),
|
||||
})(<Checkbox>下次自动登录</Checkbox>)}
|
||||
</Form.Item>
|
||||
{/* <Link to="/resetPassword" className="goResetPsdBut">忘记密码?</Link> */}
|
||||
</div>
|
||||
<Button type="primary" htmlType="submit" onClick={handleSubmit} className="login_register_cofBut">登录</Button>
|
||||
</Form>
|
||||
<div className="link_span">没有账号?<Link to={`/register`}>去注册</Link></div>
|
||||
|
||||
{
|
||||
// setting && setting.third_party_new && setting.third_party_new.length > 0 ?
|
||||
// <p className="quick_logon">
|
||||
// <p className="quick_logon_p"></p>
|
||||
// <span className={"startlogin"}> 快速登录 </span>
|
||||
// {setting.third_party_new.map((item,key)=>{
|
||||
// return(
|
||||
// <a href={`${item.url}`} className="ml15 mr15">
|
||||
// <Tooltip title={`使用${item.name === "qq" ? "QQ":item.name === "wechat" ? "微信" : item.name}账号登录`}>
|
||||
// <img src={item.name === "educoder" ? educoderLogo : item.name === "qq" ? qqlogo : item.name === "wechat" ? WeChatlogo : item.name === "gitee" ? giteelogo : item.name === "github" ? githublogo : ""} width="46px" alt={`${item.name}登录`}/>
|
||||
// </Tooltip>
|
||||
// </a>
|
||||
// )
|
||||
// })
|
||||
// }
|
||||
// </p>
|
||||
// <OtherLogin />
|
||||
}
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
export default Form.create({ name: 'login' })(Login);
|
||||
|
|
@ -14,7 +14,7 @@ function LoginRegisterPage(props){
|
|||
return(
|
||||
<div className="loginRegister">
|
||||
<div className="login_register_left">
|
||||
<img src={logo} className="logo" alt="" onClick={()=>{window.location.href='/'}} />
|
||||
{/* <img src={logo} className="logo" alt="" onClick={()=>{window.location.href='/'}} /> */}
|
||||
<img src={ball} className="ball" alt="" />
|
||||
<img src={banner} className="banner" alt="" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,19 +15,19 @@
|
|||
margin-top: 45vh;
|
||||
height: auto;
|
||||
}
|
||||
.ball{ top: 51vh; }
|
||||
.ball{ top: 36vh; }
|
||||
.right_cont{width: 540px; }
|
||||
.ResetPassword_content{top: 12vh; }
|
||||
}
|
||||
/*当页面宽度大于1280px*/
|
||||
@media screen and (min-width:1280px) {
|
||||
.banner{ margin-top: 35vh; }
|
||||
.ball{ top: 43vh; }
|
||||
.ball{ top: 28vh; }
|
||||
}
|
||||
/*当页面宽度大于1680px*/
|
||||
@media screen and (min-width:1680px) {
|
||||
.banner{ height: 460px; }
|
||||
.ball{ top: 42vh; }
|
||||
.ball{ top: 27vh; }
|
||||
.right_cont{width: 580px; }
|
||||
.ResetPassword_content{top: 16vh; }
|
||||
}
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
position: absolute;
|
||||
z-index: 2;
|
||||
left: 45vw;
|
||||
padding: 2.5em 5em;
|
||||
padding: 2.5em 4em;
|
||||
border-radius: 7px;
|
||||
font-size: 15px;
|
||||
top: 50%;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
import React from "react";
|
||||
import Login from "./LoginNew";
|
||||
import Register from "./RegisterNew";
|
||||
import ResetPassword from "./ResetPasswordNew";
|
||||
import '../loginRegister/LoginRegisterPageNew.scss';
|
||||
|
||||
function LoginRegisterPage(props){
|
||||
const {mygetHelmetapi} = props;
|
||||
return(
|
||||
<div className="loginRegister">
|
||||
<div className="login_register_right">
|
||||
{props.location.pathname === "/login" ?
|
||||
<Login {...props}/>
|
||||
:
|
||||
props.location.pathname === "/register" ?
|
||||
<Register mygetHelmetapi={mygetHelmetapi}/>
|
||||
:
|
||||
<ResetPassword mygetHelmetapi={mygetHelmetapi}/>
|
||||
}
|
||||
</div>
|
||||
<div className="clear"></div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default LoginRegisterPage;
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
@import url(./font/font.css);
|
||||
|
||||
.loginRegister{
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
background-image: url(./img/bg1.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: alibaba;
|
||||
}
|
||||
.clear{
|
||||
clear: both;
|
||||
}
|
||||
.login_register_right {
|
||||
width: 1200px;
|
||||
height: 705px;
|
||||
background:#ffffff;
|
||||
box-shadow:0px 0px 20px rgba(37, 106, 206, 0.14);
|
||||
background-image: url(./img/bglogin.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 50% 100%;
|
||||
.Register_content {
|
||||
padding: 70px 75px 70px 75px;
|
||||
.registerNav {
|
||||
margin-bottom: 28px;
|
||||
a {
|
||||
color: #445a7a;
|
||||
display: inline-block;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
}
|
||||
.activeRegisterNav {
|
||||
font-family: alibaba-medium;
|
||||
color: #0d5ef8;
|
||||
border-bottom: 2px solid #0d5ef8;
|
||||
}
|
||||
}
|
||||
.ant-form-item {
|
||||
margin-bottom: 34px;
|
||||
}
|
||||
}
|
||||
.login_content {
|
||||
padding: 105px 75px 113px 75px;
|
||||
.ant-form-item {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
}
|
||||
.right_cont {
|
||||
height: 100%;
|
||||
width: 50%;
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
.login_register_head {
|
||||
font-family: alibaba-medium;
|
||||
color: #283444;
|
||||
font-size: 28px;
|
||||
line-height: 28px;
|
||||
.head_blue {
|
||||
font-size: 26px;
|
||||
color: #0d5ef8;
|
||||
}
|
||||
}
|
||||
.account {
|
||||
.input_icon::before {
|
||||
background-image: url(./img/icon1.png);
|
||||
}
|
||||
&:hover {
|
||||
.input_icon::before {
|
||||
background-image: url(./img/icon2.png);
|
||||
}
|
||||
}
|
||||
}
|
||||
.psd, .psdComfirm, .register_psd {
|
||||
.input_icon::before {
|
||||
background-image: url(./img/icon3.png);
|
||||
}
|
||||
&:hover {
|
||||
.input_icon::before {
|
||||
background-image: url(./img/icon4.png);
|
||||
}
|
||||
}
|
||||
}
|
||||
.email {
|
||||
.input_icon::before {
|
||||
background-image: url(./img/icon7.png);
|
||||
}
|
||||
&:hover {
|
||||
.input_icon::before {
|
||||
background-image: url(./img/icon8.png);
|
||||
}
|
||||
}
|
||||
}
|
||||
.phone {
|
||||
.input_icon::before {
|
||||
background-image: url(./img/icon5.png);
|
||||
}
|
||||
&:hover {
|
||||
.input_icon::before {
|
||||
background-image: url(./img/icon6.png);
|
||||
}
|
||||
}
|
||||
}
|
||||
.input_icon {
|
||||
margin-left: 50px;
|
||||
width: 0px;
|
||||
height: 30px;
|
||||
border: 1px solid;
|
||||
border-color: rgba(20, 49, 179, 0.12);
|
||||
&::before {
|
||||
transform: translate( 50%, -50%);
|
||||
position: absolute;
|
||||
content: "";
|
||||
left: 0;
|
||||
top: 50%;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
background-image: url(./img/icon1.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
.ant-input{
|
||||
width: 450px;
|
||||
height: 48px;
|
||||
border: 1px solid;
|
||||
border-color: #9eaacb;
|
||||
border-radius: 4px;
|
||||
background: #FFFFFF !important;
|
||||
color: #283444;
|
||||
padding-left: 80px;
|
||||
&:hover{
|
||||
background: rgba(0, 88, 255, 0.03);
|
||||
border-color: #0d5ef8;
|
||||
}
|
||||
}
|
||||
.login_register_cofBut {
|
||||
width: 450px;
|
||||
height: 56px;
|
||||
background: #0d5ef8;
|
||||
border-radius: 10px;
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
}
|
||||
.link_span {
|
||||
font-size:14px;
|
||||
line-height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
a {
|
||||
color: #0d5ef8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue